import { FileAddFilled } from "@ant-design/icons"; import { useMutation } from "@apollo/client/react"; import { Button, Tooltip } from "antd"; import { t } from "i18next"; import dayjs from "./../../utils/day"; import { useState } from "react"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { INSERT_INVENTORY_AND_CREDIT } from "../../graphql/inventory.queries"; import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors"; import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility"; import queryString from "query-string"; import { useLocation } from "react-router-dom"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, currentUser: selectCurrentUser }); const mapDispatchToProps = () => ({}); export default connect(mapStateToProps, mapDispatchToProps)(BilllineAddInventory); export function BilllineAddInventory({ currentUser, bodyshop, billline, disabled, jobid }) { const [loading, setLoading] = useState(false); const qs = queryString.parse(useLocation().search); const billid = qs?.billid != null ? String(qs.billid) : null; const [insertInventoryLine] = useMutation(INSERT_INVENTORY_AND_CREDIT); const notification = useNotification(); const inventoryCount = billline?.inventories?.length ?? 0; const quantity = billline?.quantity ?? 0; const addToInventory = async () => { if (loading) return; // Defensive: row identity can transiently desync during remove/add reindexing. if (!billline) { notification.error({ title: t("inventory.errors.inserting", { error: "Bill line is missing (please try again)." }) }); return; } setLoading(true); try { const taxes = billline?.applicable_taxes ?? {}; const cm = { vendorid: bodyshop.inhousevendorid, invoice_number: "ih", jobid: jobid, isinhouse: true, is_credit_memo: true, date: dayjs().format("YYYY-MM-DD"), federal_tax_rate: bodyshop.bill_tax_rates.federal_tax_rate, state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate, local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate, total: 0, billlines: [ { actual_price: billline.actual_price, actual_cost: billline.actual_cost, quantity: billline.quantity, line_desc: billline.line_desc, cost_center: billline.cost_center, deductedfromlbr: billline.deductedfromlbr, applicable_taxes: { local: taxes.local, state: taxes.state, federal: taxes.federal } } ] }; cm.total = CalculateBillTotal(cm).enteredTotal.getAmount() / 100; const insertResult = await insertInventoryLine({ variables: { joblineId: billline.joblineid === "noline" ? billline.id : billline.joblineid, joblineStatus: bodyshop.md_order_statuses.default_returned, inv: { shopid: bodyshop.id, billlineid: billline.id, actual_price: billline.actual_price, actual_cost: billline.actual_cost, quantity: billline.quantity, line_desc: billline.line_desc }, cm: { ...cm, billlines: { data: cm.billlines } }, pol: { returnfrombill: billid, vendorid: bodyshop.inhousevendorid, deliver_by: dayjs().format("YYYY-MM-DD"), parts_order_lines: { data: [ { line_desc: billline.line_desc, act_price: billline.actual_price, cost: billline.actual_cost, quantity: billline.quantity, job_line_id: billline.joblineid === "noline" ? null : billline.joblineid, part_type: billline.jobline && billline.jobline.part_type, cm_received: true } ] }, order_date: "2022-06-01", orderedby: currentUser.email, jobid: jobid, user_email: currentUser.email, return: true, status: "Ordered" } }, refetchQueries: ["QUERY_BILL_BY_PK"] }); if (!insertResult?.errors?.length) { notification.success({ title: t("inventory.successes.inserted") }); } else { notification.error({ title: t("inventory.errors.inserting", { error: JSON.stringify(insertResult.errors) }) }); } } catch (err) { notification.error({ title: t("inventory.errors.inserting", { error: err?.message || String(err) }) }); } finally { setLoading(false); } }; return ( ); }