Fixed rounding bug on invoice total calculation BOD-120. Added documents viewing to edit invoice BOD-75 BOD-63.

This commit is contained in:
Patrick Fic
2020-05-07 09:25:48 -07:00
parent 9d4b36aeec
commit 723f8da825
13 changed files with 65 additions and 30 deletions

View File

@@ -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>
);

View File

@@ -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>
);
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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}

View File

@@ -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

View File

@@ -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}
/>
);
}

View File

@@ -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();

View File

@@ -107,6 +107,12 @@ export const QUERY_INVOICE_BY_PK = gql`
joblineid
applicable_taxes
}
documents {
id
key
name
type
}
}
}
`;

View File

@@ -826,7 +826,7 @@
}
},
"titles": {
"app": "Bodyshop by ImEX Systems",
"app": "ImEX Online",
"bc": {
"availablejobs": "Available Jobs",
"contracts": "Contracts",

View File

@@ -826,7 +826,7 @@
}
},
"titles": {
"app": "Carrocería de ImEX Systems",
"app": "ImEX Online",
"bc": {
"availablejobs": "",
"contracts": "",

View File

@@ -826,7 +826,7 @@
}
},
"titles": {
"app": "Carrosserie par ImEX Systems",
"app": "ImEX Online",
"bc": {
"availablejobs": "",
"contracts": "",

View File

@@ -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