import {useMutation, useQuery} from "@apollo/client"; import {Button, Form, Popconfirm, Space} from "antd"; import dayjs from "../../utils/day"; import queryString from "query-string"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { useLocation } from "react-router-dom"; import { createStructuredSelector } from "reselect"; import { DELETE_BILL_LINE, INSERT_NEW_BILL_LINES, UPDATE_BILL_LINE } from "../../graphql/bill-lines.queries"; import { QUERY_BILL_BY_PK, UPDATE_BILL } from "../../graphql/bills.queries"; import { insertAuditTrail } from "../../redux/application/application.actions"; import { setModalContext } from "../../redux/modals/modals.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings"; import AlertComponent from "../alert/alert.component"; import BillFormContainer from "../bill-form/bill-form.container"; import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component"; import BillPrintButton from "../bill-print-button/bill-print-button.component"; import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-button.component"; import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-gallery.container"; import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container"; import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component"; import BillDetailEditReturn from "./bill-detail-edit-return.component"; import {PageHeader} from "@ant-design/pro-layout"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, }); const mapDispatchToProps = (dispatch) => ({ setPartsOrderContext: (context) => dispatch(setModalContext({context: context, modal: "partsOrder"})), insertAuditTrail: ({jobid, operation}) => dispatch(insertAuditTrail({jobid, operation})), }); export default connect( mapStateToProps, mapDispatchToProps )(BillDetailEditcontainer); export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail, bodyshop,}) { const search = queryString.parse(useLocation().search); const {t} = useTranslation(); const [form] = Form.useForm(); const [visible, setVisible] = useState(false); const [updateLoading, setUpdateLoading] = useState(false); const [update_bill] = useMutation(UPDATE_BILL); const [insertBillLine] = useMutation(INSERT_NEW_BILL_LINES); const [updateBillLine] = useMutation(UPDATE_BILL_LINE); const [deleteBillLine] = useMutation(DELETE_BILL_LINE); const {loading, error, data, refetch} = useQuery(QUERY_BILL_BY_PK, { variables: {billid: search.billid}, skip: !!!search.billid, fetchPolicy: "network-only", nextFetchPolicy: "network-only", }); // ... rest of the code remains the same const handleSave = () => { //It's got a previously deducted bill line! if ( data.bills_by_pk.billlines.filter((b) => b.deductedfromlbr).length > 0 || form.getFieldValue("billlines").filter((b) => b.deductedfromlbr).length > 0 ) setVisible(true); else { form.submit(); } }; const handleFinish = async (values) => { setUpdateLoading(true); //let adjustmentsToInsert = {}; const {billlines, upload, ...bill} = values; const updates = []; updates.push( update_bill({ variables: {billId: search.billid, bill: bill}, }) ); billlines.forEach((l) => { delete l.selected; }); //Find bill lines that were deleted. const deletedJobLines = []; data.bills_by_pk.billlines.forEach((a) => { const matchingRecord = billlines.find((b) => b.id === a.id); if (!matchingRecord) { deletedJobLines.push(a); } }); deletedJobLines.forEach((d) => { updates.push(deleteBillLine({variables: {id: d.id}})); }); billlines.forEach((billline) => { const {deductedfromlbr, inventories, jobline, ...il} = billline; delete il.__typename; if (il.id) { updates.push( updateBillLine({ variables: { billLineId: il.id, billLine: { ...il, deductedfromlbr: deductedfromlbr, joblineid: il.joblineid === "noline" ? null : il.joblineid, }, }, }) ); } else { //It's a new line, have to insert it. updates.push( insertBillLine({ variables: { billLines: [ { ...il, deductedfromlbr: deductedfromlbr, billid: search.billid, joblineid: il.joblineid === "noline" ? null : il.joblineid, }, ], }, }) ); } }); await Promise.all(updates); insertAuditTrail({ jobid: bill.jobid, billid: search.billid, operation: AuditTrailMapping.billupdated(bill.invoice_number), }); await refetch(); form.setFieldsValue(transformData(data)); form.resetFields(); setVisible(false); setUpdateLoading(false); }; if (error) return ; if (!search.billid) return <>; //
{t("bills.labels.noneselected")}
; const exported = data && data.bills_by_pk && data.bills_by_pk.exported; return ( <> {loading && } {data && ( <> form.submit()} onCancel={() => setVisible(false)} okButtonProps={{ loading: updateLoading }} title={t("bills.labels.editadjwarning")} > } />
{bodyshop.uselocalmediaserver ? ( ) : ( )} )} ); } const transformData = (data) => { return data ? { ...data.bills_by_pk, billlines: data.bills_by_pk.billlines.map((i) => { return { ...i, joblineid: !!i.joblineid ? i.joblineid : "noline", applicable_taxes: { federal: (i.applicable_taxes && i.applicable_taxes.federal) || false, state: (i.applicable_taxes && i.applicable_taxes.state) || false, local: (i.applicable_taxes && i.applicable_taxes.local) || false, }, }; }), date: data.bills_by_pk ? dayjs(data.bills_by_pk.date) : null, } : {}; };