Added negative validation on entering invoices for credit memos BOD-219
This commit is contained in:
@@ -8350,6 +8350,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>enteringcreditmemo</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>federal_tax</name>
|
<name>federal_tax</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
} from "antd";
|
} from "antd";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import AlertComponent from "../alert/alert.component";
|
||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
||||||
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
||||||
@@ -50,17 +51,18 @@ export default function InvoiceFormComponent({
|
|||||||
}, [form, setDiscount, vendorAutoCompleteOptions, loadLines]);
|
}, [form, setDiscount, vendorAutoCompleteOptions, loadLines]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='invoice-form-wrapper'>
|
<div className="invoice-form-wrapper">
|
||||||
<div className='invoice-form-invoice-details'>
|
<div className="invoice-form-invoice-details">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name='jobid'
|
name="jobid"
|
||||||
label={t("invoices.fields.ro_number")}
|
label={t("invoices.fields.ro_number")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<JobSearchSelect
|
<JobSearchSelect
|
||||||
options={roAutoCompleteOptions}
|
options={roAutoCompleteOptions}
|
||||||
disabled={invoiceEdit}
|
disabled={invoiceEdit}
|
||||||
@@ -73,74 +75,82 @@ export default function InvoiceFormComponent({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.vendor")}
|
label={t("invoices.fields.vendor")}
|
||||||
name='vendorid'
|
name="vendorid"
|
||||||
style={{ display: invoiceEdit ? "none" : null }}
|
style={{ display: invoiceEdit ? "none" : null }}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<VendorSearchSelect
|
<VendorSearchSelect
|
||||||
options={vendorAutoCompleteOptions}
|
options={vendorAutoCompleteOptions}
|
||||||
onSelect={handleVendorSelect}
|
onSelect={handleVendorSelect}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
<div className='invoice-form-invoice-details'>
|
<div className="invoice-form-invoice-details">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.invoice_number")}
|
label={t("invoices.fields.invoice_number")}
|
||||||
name='invoice_number'
|
name="invoice_number"
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.date")}
|
label={t("invoices.fields.date")}
|
||||||
name='date'
|
name="date"
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<DatePicker />
|
<DatePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.is_credit_memo")}
|
label={t("invoices.fields.is_credit_memo")}
|
||||||
name='is_credit_memo'
|
name="is_credit_memo"
|
||||||
valuePropName='checked'>
|
valuePropName="checked"
|
||||||
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.total")}
|
label={t("invoices.fields.total")}
|
||||||
name='total'
|
name="total"
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
<CurrencyInput />
|
>
|
||||||
|
<CurrencyInput min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.federal_tax_rate")}
|
label={t("invoices.fields.federal_tax_rate")}
|
||||||
name='federal_tax_rate'>
|
name="federal_tax_rate"
|
||||||
<CurrencyInput />
|
>
|
||||||
|
<CurrencyInput min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.state_tax_rate")}
|
label={t("invoices.fields.state_tax_rate")}
|
||||||
name='state_tax_rate'>
|
name="state_tax_rate"
|
||||||
<CurrencyInput />
|
>
|
||||||
|
<CurrencyInput min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoices.fields.local_tax_rate")}
|
label={t("invoices.fields.local_tax_rate")}
|
||||||
name='local_tax_rate'>
|
name="local_tax_rate"
|
||||||
<CurrencyInput />
|
>
|
||||||
|
<CurrencyInput min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
<InvoiceFormLines
|
<InvoiceFormLines
|
||||||
@@ -151,18 +161,19 @@ export default function InvoiceFormComponent({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name='upload'
|
name="upload"
|
||||||
label='Upload'
|
label="Upload"
|
||||||
style={{ display: invoiceEdit ? "none" : null }}
|
style={{ display: invoiceEdit ? "none" : null }}
|
||||||
valuePropName='fileList'
|
valuePropName="fileList"
|
||||||
getValueFromEvent={(e) => {
|
getValueFromEvent={(e) => {
|
||||||
console.log("Upload event:", e);
|
console.log("Upload event:", e);
|
||||||
if (Array.isArray(e)) {
|
if (Array.isArray(e)) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
return e && e.fileList;
|
return e && e.fileList;
|
||||||
}}>
|
}}
|
||||||
<Upload name='logo' beforeUpload={() => false} listType='picture'>
|
>
|
||||||
|
<Upload name="logo" beforeUpload={() => false} listType="picture">
|
||||||
<Button>Click to upload</Button>
|
<Button>Click to upload</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -185,46 +196,54 @@ export default function InvoiceFormComponent({
|
|||||||
totals = CalculateInvoiceTotal(values);
|
totals = CalculateInvoiceTotal(values);
|
||||||
if (!!totals)
|
if (!!totals)
|
||||||
return (
|
return (
|
||||||
<div className='invoice-form-totals'>
|
<div>
|
||||||
<Statistic
|
<div className="invoice-form-totals">
|
||||||
title={t("invoices.labels.subtotal")}
|
<Statistic
|
||||||
value={totals.subtotal.toFormat()}
|
title={t("invoices.labels.subtotal")}
|
||||||
precision={2}
|
value={totals.subtotal.toFormat()}
|
||||||
/>
|
precision={2}
|
||||||
<Statistic
|
/>
|
||||||
title={t("invoices.labels.federal_tax")}
|
<Statistic
|
||||||
value={totals.federalTax.toFormat()}
|
title={t("invoices.labels.federal_tax")}
|
||||||
precision={2}
|
value={totals.federalTax.toFormat()}
|
||||||
/>
|
precision={2}
|
||||||
<Statistic
|
/>
|
||||||
title={t("invoices.labels.state_tax")}
|
<Statistic
|
||||||
value={totals.stateTax.toFormat()}
|
title={t("invoices.labels.state_tax")}
|
||||||
precision={2}
|
value={totals.stateTax.toFormat()}
|
||||||
/>
|
precision={2}
|
||||||
<Statistic
|
/>
|
||||||
title={t("invoices.labels.local_tax")}
|
<Statistic
|
||||||
value={totals.localTax.toFormat()}
|
title={t("invoices.labels.local_tax")}
|
||||||
precision={2}
|
value={totals.localTax.toFormat()}
|
||||||
/>
|
precision={2}
|
||||||
<Statistic
|
/>
|
||||||
title={t("invoices.labels.entered_total")}
|
<Statistic
|
||||||
value={totals.enteredTotal.toFormat()}
|
title={t("invoices.labels.entered_total")}
|
||||||
precision={2}
|
value={totals.enteredTotal.toFormat()}
|
||||||
/>
|
precision={2}
|
||||||
<Statistic
|
/>
|
||||||
title={t("invoices.labels.invoice_total")}
|
<Statistic
|
||||||
value={totals.invoiceTotal.toFormat()}
|
title={t("invoices.labels.invoice_total")}
|
||||||
precision={2}
|
value={totals.invoiceTotal.toFormat()}
|
||||||
/>
|
precision={2}
|
||||||
<Statistic
|
/>
|
||||||
title={t("invoices.labels.discrepancy")}
|
<Statistic
|
||||||
valueStyle={{
|
title={t("invoices.labels.discrepancy")}
|
||||||
color:
|
valueStyle={{
|
||||||
totals.discrepancy.getAmount() === 0 ? "green" : "red",
|
color:
|
||||||
}}
|
totals.discrepancy.getAmount() === 0 ? "green" : "red",
|
||||||
value={totals.discrepancy.toFormat()}
|
}}
|
||||||
precision={2}
|
value={totals.discrepancy.toFormat()}
|
||||||
/>
|
precision={2}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{form.getFieldValue("is_credit_memo") ? (
|
||||||
|
<AlertComponent
|
||||||
|
type="warning"
|
||||||
|
message={t("invoices.labels.enteringcreditmemo")}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
const { setFieldsValue, getFieldsValue } = form;
|
const { setFieldsValue, getFieldsValue } = form;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form.List name='invoicelines'>
|
<Form.List name="invoicelines">
|
||||||
{(fields, { add, remove }) => {
|
{(fields, { add, remove }) => {
|
||||||
return (
|
return (
|
||||||
<div className='invoice-form-lines-wrapper'>
|
<div className="invoice-form-lines-wrapper">
|
||||||
{fields.map((field, index) => (
|
{fields.map((field, index) => (
|
||||||
<Form.Item required={false} key={field.key}>
|
<Form.Item required={false} key={field.key}>
|
||||||
<div className='invoice-form-line'>
|
<div className="invoice-form-line">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoicelines.fields.jobline")}
|
label={t("invoicelines.fields.jobline")}
|
||||||
key={`${index}joblinename`}
|
key={`${index}joblinename`}
|
||||||
@@ -31,7 +31,8 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<InvoiceLineSearchSelect
|
<InvoiceLineSearchSelect
|
||||||
options={lineData}
|
options={lineData}
|
||||||
onSelect={(value, opt) => {
|
onSelect={(value, opt) => {
|
||||||
@@ -68,7 +69,8 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -80,8 +82,9 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
<InputNumber precision={0} />
|
>
|
||||||
|
<InputNumber precision={0} min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoicelines.fields.actual")}
|
label={t("invoicelines.fields.actual")}
|
||||||
@@ -92,8 +95,10 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<CurrencyInput
|
<CurrencyInput
|
||||||
|
min={0}
|
||||||
onBlur={(e) => {
|
onBlur={(e) => {
|
||||||
setFieldsValue({
|
setFieldsValue({
|
||||||
invoicelines: getFieldsValue(
|
invoicelines: getFieldsValue(
|
||||||
@@ -122,8 +127,9 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
<CurrencyInput />
|
>
|
||||||
|
<CurrencyInput min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item shouldUpdate>
|
<Form.Item shouldUpdate>
|
||||||
{() => {
|
{() => {
|
||||||
@@ -151,7 +157,8 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
message: t("general.validation.required"),
|
message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}>
|
]}
|
||||||
|
>
|
||||||
<Select style={{ width: "150px" }}>
|
<Select style={{ width: "150px" }}>
|
||||||
{responsibilityCenters.costs.map((item) => (
|
{responsibilityCenters.costs.map((item) => (
|
||||||
<Select.Option key={item.name}>
|
<Select.Option key={item.name}>
|
||||||
@@ -164,22 +171,25 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
label={t("invoicelines.fields.federal_tax_applicable")}
|
label={t("invoicelines.fields.federal_tax_applicable")}
|
||||||
key={`${index}fedtax`}
|
key={`${index}fedtax`}
|
||||||
initialValue={true}
|
initialValue={true}
|
||||||
valuePropName='checked'
|
valuePropName="checked"
|
||||||
name={[field.name, "applicable_taxes", "federal"]}>
|
name={[field.name, "applicable_taxes", "federal"]}
|
||||||
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoicelines.fields.state_tax_applicable")}
|
label={t("invoicelines.fields.state_tax_applicable")}
|
||||||
key={`${index}statetax`}
|
key={`${index}statetax`}
|
||||||
valuePropName='checked'
|
valuePropName="checked"
|
||||||
name={[field.name, "applicable_taxes", "state"]}>
|
name={[field.name, "applicable_taxes", "state"]}
|
||||||
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("invoicelines.fields.local_tax_applicable")}
|
label={t("invoicelines.fields.local_tax_applicable")}
|
||||||
key={`${index}localtax`}
|
key={`${index}localtax`}
|
||||||
valuePropName='checked'
|
valuePropName="checked"
|
||||||
name={[field.name, "applicable_taxes", "local"]}>
|
name={[field.name, "applicable_taxes", "local"]}
|
||||||
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<DeleteFilled
|
<DeleteFilled
|
||||||
@@ -192,11 +202,12 @@ export default function InvoiceEnterModalLinesComponent({
|
|||||||
))}
|
))}
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
<Button
|
<Button
|
||||||
type='dashed'
|
type="dashed"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
add();
|
add();
|
||||||
}}
|
}}
|
||||||
style={{ width: "50%" }}>
|
style={{ width: "50%" }}
|
||||||
|
>
|
||||||
{t("invoicelines.actions.newline")}
|
{t("invoicelines.actions.newline")}
|
||||||
</Button>
|
</Button>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -550,6 +550,7 @@
|
|||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
"discrepancy": "Discrepancy",
|
"discrepancy": "Discrepancy",
|
||||||
"entered_total": "Total of Entered Lines",
|
"entered_total": "Total of Entered Lines",
|
||||||
|
"enteringcreditmemo": "You are entering a credit memo. Please ensure you are also entering positive values.",
|
||||||
"federal_tax": "Federal Tax",
|
"federal_tax": "Federal Tax",
|
||||||
"invoice_total": "Invoice Total Amount",
|
"invoice_total": "Invoice Total Amount",
|
||||||
"invoices": "Invoices",
|
"invoices": "Invoices",
|
||||||
|
|||||||
@@ -550,6 +550,7 @@
|
|||||||
"actions": "",
|
"actions": "",
|
||||||
"discrepancy": "",
|
"discrepancy": "",
|
||||||
"entered_total": "",
|
"entered_total": "",
|
||||||
|
"enteringcreditmemo": "",
|
||||||
"federal_tax": "",
|
"federal_tax": "",
|
||||||
"invoice_total": "",
|
"invoice_total": "",
|
||||||
"invoices": "",
|
"invoices": "",
|
||||||
|
|||||||
@@ -550,6 +550,7 @@
|
|||||||
"actions": "",
|
"actions": "",
|
||||||
"discrepancy": "",
|
"discrepancy": "",
|
||||||
"entered_total": "",
|
"entered_total": "",
|
||||||
|
"enteringcreditmemo": "",
|
||||||
"federal_tax": "",
|
"federal_tax": "",
|
||||||
"invoice_total": "",
|
"invoice_total": "",
|
||||||
"invoices": "",
|
"invoices": "",
|
||||||
|
|||||||
Reference in New Issue
Block a user