Fixed rounding bug on invoice total calculation BOD-120. Added documents viewing to edit invoice BOD-75 BOD-63.
This commit is contained in:
@@ -16,6 +16,8 @@ import AlertComponent from "../alert/alert.component";
|
||||
import InvoiceFormContainer from "../invoice-form/invoice-form.container";
|
||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||
import { UPDATE_INVOICE_LINE } from "../../graphql/invoice-lines.queries";
|
||||
import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-gallery.container";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
@@ -27,7 +29,7 @@ export function InvoiceDetailEditContainer({ bodyshop }) {
|
||||
const [updateInvoice] = useMutation(UPDATE_INVOICE);
|
||||
const [updateInvoiceLine] = useMutation(UPDATE_INVOICE_LINE);
|
||||
|
||||
const { loading, error, data } = useQuery(QUERY_INVOICE_BY_PK, {
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_INVOICE_BY_PK, {
|
||||
variables: { invoiceid: search.invoiceid },
|
||||
skip: !!!search.invoiceid,
|
||||
});
|
||||
@@ -100,7 +102,13 @@ export function InvoiceDetailEditContainer({ bodyshop }) {
|
||||
<Button htmlType="submit" type="primary">
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
<InvoiceFormContainer form={form} hideVendor />
|
||||
<InvoiceFormContainer form={form} invoiceEdit />
|
||||
<JobDocumentsGallery
|
||||
jobId={data ? data.invoices_by_pk.jobid : null}
|
||||
invoiceId={search.invoiceid}
|
||||
documentsList={data ? data.invoices_by_pk.documents : []}
|
||||
invoicesCallback={refetch}
|
||||
/>
|
||||
</Form>
|
||||
</LoadingSkeleton>
|
||||
);
|
||||
|
||||
@@ -23,7 +23,7 @@ export default function InvoiceFormComponent({
|
||||
lineData,
|
||||
responsibilityCenters,
|
||||
loadLines,
|
||||
hideVendor,
|
||||
invoiceEdit,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -61,6 +61,7 @@ export default function InvoiceFormComponent({
|
||||
>
|
||||
<JobSearchSelect
|
||||
options={roAutoCompleteOptions}
|
||||
disabled={invoiceEdit}
|
||||
onBlur={() => {
|
||||
if (form.getFieldValue("jobid") !== null) {
|
||||
loadLines({ variables: { id: form.getFieldValue("jobid") } });
|
||||
@@ -71,7 +72,7 @@ export default function InvoiceFormComponent({
|
||||
<Form.Item
|
||||
label={t("invoices.fields.vendor")}
|
||||
name="vendorid"
|
||||
style={{ display: hideVendor ? "none" : null }}
|
||||
style={{ display: invoiceEdit ? "none" : null }}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
@@ -162,6 +163,7 @@ export default function InvoiceFormComponent({
|
||||
<Form.Item
|
||||
name="upload"
|
||||
label="Upload"
|
||||
style={{ display: invoiceEdit ? "none" : null }}
|
||||
valuePropName="fileList"
|
||||
getValueFromEvent={(e) => {
|
||||
console.log("Upload event:", e);
|
||||
@@ -239,10 +241,6 @@ export default function InvoiceFormComponent({
|
||||
return null;
|
||||
}}
|
||||
</Form.Item>
|
||||
|
||||
<Button onClick={() => console.log(form.getFieldsValue())}>
|
||||
Get Values
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
export function InvoiceFormContainer({ bodyshop, form, hideVendor }) {
|
||||
export function InvoiceFormContainer({ bodyshop, form, invoiceEdit }) {
|
||||
const { data: RoAutoCompleteData } = useQuery(ACTIVE_JOBS_FOR_AUTOCOMPLETE, {
|
||||
variables: { statuses: bodyshop.md_ro_statuses.open_statuses || ["Open"] },
|
||||
});
|
||||
@@ -27,7 +27,7 @@ export function InvoiceFormContainer({ bodyshop, form, hideVendor }) {
|
||||
<div>
|
||||
<InvoiceFormComponent
|
||||
form={form}
|
||||
hideVendor={hideVendor}
|
||||
invoiceEdit={invoiceEdit}
|
||||
roAutoCompleteOptions={RoAutoCompleteData && RoAutoCompleteData.jobs}
|
||||
vendorAutoCompleteOptions={
|
||||
VendorAutoCompleteData && VendorAutoCompleteData.vendors
|
||||
|
||||
@@ -33,7 +33,7 @@ export const CalculateInvoiceTotal = (invoice) => {
|
||||
}
|
||||
});
|
||||
|
||||
const invoiceTotal = Dinero({ amount: (parseFloat(total) || 0) * 100 });
|
||||
const invoiceTotal = Dinero({ amount: Math.round((total || 0) * 100) });
|
||||
const enteredTotal = subtotal.add(federalTax).add(stateTax).add(localTax);
|
||||
const discrepancy = enteredTotal.subtract(invoiceTotal);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ const { Option } = Select;
|
||||
|
||||
//To be used as a form element only.
|
||||
|
||||
const JobSearchSelect = ({ value, onChange, options, onBlur }) => {
|
||||
const JobSearchSelect = ({ value, onChange, options, onBlur, disabled }) => {
|
||||
const [option, setOption] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -15,22 +15,25 @@ const JobSearchSelect = ({ value, onChange, options, onBlur }) => {
|
||||
|
||||
return (
|
||||
<Select
|
||||
disabled={disabled}
|
||||
showSearch
|
||||
autoFocus
|
||||
value={option}
|
||||
style={{
|
||||
width: 300
|
||||
width: 300,
|
||||
}}
|
||||
onChange={setOption}
|
||||
optionFilterProp="children"
|
||||
onBlur={onBlur}
|
||||
>
|
||||
{options
|
||||
? options.map(o => (
|
||||
? options.map((o) => (
|
||||
<Option key={o.id} value={o.id}>
|
||||
{`${o.ro_number ? o.ro_number : o.est_number} | ${o.ownr_ln ||
|
||||
""} ${o.ownr_fn || ""} | ${o.v_model_yr ||
|
||||
""} ${o.v_make_desc || ""} ${o.v_model_desc || ""}`}
|
||||
{`${o.ro_number ? o.ro_number : o.est_number} | ${
|
||||
o.ownr_ln || ""
|
||||
} ${o.ownr_fn || ""} | ${o.v_model_yr || ""} ${
|
||||
o.v_make_desc || ""
|
||||
} ${o.v_model_desc || ""}`}
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
|
||||
@@ -4,9 +4,15 @@ import DocumentsUploadContainer from "../documents-upload/documents-upload.conta
|
||||
import JobsDocumentsDownloadButton from "./jobs-document-gallery.download.component";
|
||||
import JobsDocumentsDeleteButton from "./jobs-documents-gallery.delete.component";
|
||||
|
||||
function JobsDocumentsComponent({ data, jobId, refetch }) {
|
||||
function JobsDocumentsComponent({
|
||||
data,
|
||||
jobId,
|
||||
refetch,
|
||||
invoiceId,
|
||||
invoicesCallback,
|
||||
}) {
|
||||
const [galleryImages, setgalleryImages] = useState([]);
|
||||
|
||||
console.log("Gallery Data", data);
|
||||
useEffect(() => {
|
||||
setgalleryImages(
|
||||
data.reduce((acc, value) => {
|
||||
@@ -28,17 +34,18 @@ function JobsDocumentsComponent({ data, jobId, refetch }) {
|
||||
}, [data, setgalleryImages]);
|
||||
|
||||
return (
|
||||
<div className='clearfix'>
|
||||
<div className="clearfix">
|
||||
<DocumentsUploadContainer
|
||||
jobId={jobId}
|
||||
callbackAfterUpload={refetch}
|
||||
invoiceId={invoiceId}
|
||||
callbackAfterUpload={invoicesCallback || refetch}
|
||||
tagsArray={["test"]}
|
||||
/>
|
||||
|
||||
<JobsDocumentsDownloadButton galleryImages={galleryImages} />
|
||||
<JobsDocumentsDeleteButton
|
||||
galleryImages={galleryImages}
|
||||
deletionCallback={refetch}
|
||||
deletionCallback={invoicesCallback || refetch}
|
||||
/>
|
||||
|
||||
<Gallery
|
||||
|
||||
@@ -5,14 +5,28 @@ import AlertComponent from "../alert/alert.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
import JobDocuments from "./jobs-documents-gallery.component";
|
||||
|
||||
export default function JobsDocumentsContainer({ jobId }) {
|
||||
export default function JobsDocumentsContainer({
|
||||
jobId,
|
||||
invoiceId,
|
||||
documentsList,
|
||||
invoicesCallback,
|
||||
}) {
|
||||
const { loading, error, data, refetch } = useQuery(GET_DOCUMENTS_BY_JOB, {
|
||||
variables: { jobId: jobId },
|
||||
fetchPolicy: "network-only"
|
||||
fetchPolicy: "network-only",
|
||||
skip: !!invoiceId,
|
||||
});
|
||||
|
||||
if (loading) return <LoadingSpinner />;
|
||||
if (error) return <AlertComponent type="error" message={error.message} />;
|
||||
|
||||
return <JobDocuments data={data.documents} jobId={jobId} refetch={refetch} />;
|
||||
return (
|
||||
<JobDocuments
|
||||
data={(data && data.documents) || documentsList || []}
|
||||
invoiceId={invoiceId}
|
||||
jobId={jobId}
|
||||
refetch={refetch}
|
||||
invoicesCallback={invoicesCallback}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import "firebase/analytics";
|
||||
import "firebase/messaging";
|
||||
|
||||
const config = JSON.parse(process.env.REACT_APP_FIREBASE_CONFIG);
|
||||
console.log("Firebase config", config);
|
||||
firebase.initializeApp(config);
|
||||
|
||||
export const auth = firebase.auth();
|
||||
|
||||
@@ -107,6 +107,12 @@ export const QUERY_INVOICE_BY_PK = gql`
|
||||
joblineid
|
||||
applicable_taxes
|
||||
}
|
||||
documents {
|
||||
id
|
||||
key
|
||||
name
|
||||
type
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -826,7 +826,7 @@
|
||||
}
|
||||
},
|
||||
"titles": {
|
||||
"app": "Bodyshop by ImEX Systems",
|
||||
"app": "ImEX Online",
|
||||
"bc": {
|
||||
"availablejobs": "Available Jobs",
|
||||
"contracts": "Contracts",
|
||||
|
||||
@@ -826,7 +826,7 @@
|
||||
}
|
||||
},
|
||||
"titles": {
|
||||
"app": "Carrocería de ImEX Systems",
|
||||
"app": "ImEX Online",
|
||||
"bc": {
|
||||
"availablejobs": "",
|
||||
"contracts": "",
|
||||
|
||||
@@ -826,7 +826,7 @@
|
||||
}
|
||||
},
|
||||
"titles": {
|
||||
"app": "Carrosserie par ImEX Systems",
|
||||
"app": "ImEX Online",
|
||||
"bc": {
|
||||
"availablejobs": "",
|
||||
"contracts": "",
|
||||
|
||||
@@ -20,7 +20,7 @@ i18n
|
||||
//lng: "en",
|
||||
detection: {},
|
||||
fallbackLng: "en-US",
|
||||
debug: true,
|
||||
debug: process.env.NODE_ENV === "production" ? false : true,
|
||||
|
||||
//keySeparator: false, // we do not use keys in form messages.welcome
|
||||
|
||||
|
||||
Reference in New Issue
Block a user