feature/IO-3255-simplified-parts-management - Checkpoint

This commit is contained in:
Dave
2025-09-02 15:01:56 -04:00
parent 814447373a
commit bec32c1d70
5 changed files with 254 additions and 71 deletions

View File

@@ -12,13 +12,15 @@ import InstanceRenderManager from "../../utils/instanceRenderMgr";
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component"; import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component"; import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx"; import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { selectIsPartsEntry } from "../../redux/application/application.selectors.js";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
technician: selectTechnician technician: selectTechnician,
isPartsEntry: selectIsPartsEntry
}); });
const mapDispatchToProps = () => ({}); const mapDispatchToProps = () => ({});
export function JobLinesPartPriceChange({ job, line, refetch, technician }) { export function JobLinesPartPriceChange({ job, line, refetch, technician, isPartsEntry }) {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [updatePartPrice] = useMutation(UPDATE_LINE_PPC); const [updatePartPrice] = useMutation(UPDATE_LINE_PPC);
const notification = useNotification(); const notification = useNotification();
@@ -64,6 +66,7 @@ export function JobLinesPartPriceChange({ job, line, refetch, technician }) {
const popcontent = const popcontent =
!technician && !technician &&
!isPartsEntry &&
InstanceRenderManager({ InstanceRenderManager({
imex: null, imex: null,
rome: ( rome: (

View File

@@ -481,48 +481,50 @@ export function JobLinesComponent({
{Enhanced_Payroll.treatment === "on" && ( {Enhanced_Payroll.treatment === "on" && (
<JobLineBulkAssignComponent selectedLines={selectedLines} setSelectedLines={setSelectedLines} job={job} /> <JobLineBulkAssignComponent selectedLines={selectedLines} setSelectedLines={setSelectedLines} job={job} />
)} )}
<Button {!isPartsEntry && (
disabled={(job && !job.converted) || (selectedLines.length > 0 ? false : true) || jobRO || technician} <Button
onClick={() => { disabled={(job && !job.converted) || (selectedLines.length > 0 ? false : true) || jobRO || technician}
setBillEnterContext({ onClick={() => {
actions: { refetch: refetch }, setBillEnterContext({
context: { actions: { refetch: refetch },
disableInvNumber: true, context: {
job: { id: job.id }, disableInvNumber: true,
bill: { job: { id: job.id },
vendorid: bodyshop.inhousevendorid, bill: {
invoice_number: "ih", vendorid: bodyshop.inhousevendorid,
isinhouse: true, invoice_number: "ih",
date: dayjs(), isinhouse: true,
total: 0, date: dayjs(),
billlines: selectedLines.map((p) => { total: 0,
return { billlines: selectedLines.map((p) => {
joblineid: p.id, return {
actual_price: p.act_price, joblineid: p.id,
actual_cost: 0, //p.act_price, actual_price: p.act_price,
line_desc: p.line_desc, actual_cost: 0, //p.act_price,
line_remarks: p.line_remarks, line_desc: p.line_desc,
part_type: p.part_type, line_remarks: p.line_remarks,
quantity: p.quantity || 1, part_type: p.part_type,
applicable_taxes: { quantity: p.quantity || 1,
local: false, applicable_taxes: {
state: false, local: false,
federal: false state: false,
} federal: false
}; }
}) };
})
}
} }
} });
});
//Clear out the selected lines. IO-785 //Clear out the selected lines. IO-785
setSelectedLines([]); setSelectedLines([]);
}} }}
> >
<HomeOutlined /> <HomeOutlined />
{t("parts.actions.orderinhouse")} {t("parts.actions.orderinhouse")}
{selectedLines.length > 0 && ` (${selectedLines.length})`} {selectedLines.length > 0 && ` (${selectedLines.length})`}
</Button> </Button>
)}
<Button <Button
id="job-lines-order-parts-button" id="job-lines-order-parts-button"
disabled={(job && !job.converted) || (selectedLines.length > 0 ? false : true) || jobRO || technician} disabled={(job && !job.converted) || (selectedLines.length > 0 ? false : true) || jobRO || technician}
@@ -578,7 +580,8 @@ export function JobLinesComponent({
{t("joblines.actions.new")} {t("joblines.actions.new")}
</Button> </Button>
)} )}
{InstanceRenderManager({ rome: <JobSendPartPriceChangeComponent job={job} disabled={technician} /> })} {!isPartsEntry &&
InstanceRenderManager({ rome: <JobSendPartPriceChangeComponent job={job} disabled={technician} /> })}
<JobCreateIOU job={job} selectedJobLines={selectedLines} /> <JobCreateIOU job={job} selectedJobLines={selectedLines} />
<Input.Search <Input.Search
placeholder={t("general.labels.search")} placeholder={t("general.labels.search")}

View File

@@ -139,17 +139,18 @@ export function JobsDetailHeader({ job, bodyshop, disabled, insertAuditTrail, is
<DataLabel label={t("jobs.fields.comment")} valueStyle={{ overflow: "hidden", textOverflow: "ellipsis" }}> <DataLabel label={t("jobs.fields.comment")} valueStyle={{ overflow: "hidden", textOverflow: "ellipsis" }}>
<ProductionListColumnComment record={job} /> <ProductionListColumnComment record={job} />
</DataLabel> </DataLabel>
<DataLabel label={t("jobs.fields.ins_co_nm_short")}>{job.ins_co_nm}</DataLabel> {!isPartsEntry && <DataLabel label={t("jobs.fields.ins_co_nm_short")}>{job.ins_co_nm}</DataLabel>}
<DataLabel label={t("jobs.fields.clm_no")}>{job.clm_no}</DataLabel> <DataLabel label={t("jobs.fields.clm_no")}>{job.clm_no}</DataLabel>
<DataLabel label={t("jobs.fields.ponumber")} hideIfNull> <DataLabel label={t("jobs.fields.ponumber")} hideIfNull>
{job.po_number} {job.po_number}
</DataLabel> </DataLabel>
<DataLabel label={t("jobs.fields.repairtotal")}> {!isPartsEntry && (
<CurrencyFormatter>{job.clm_total}</CurrencyFormatter> <DataLabel label={t("jobs.fields.repairtotal")}>
<span style={{ margin: "0rem .5rem" }}>/</span> <CurrencyFormatter>{job.clm_total}</CurrencyFormatter>
<CurrencyFormatter>{job.owner_owing}</CurrencyFormatter> <span style={{ margin: "0rem .5rem" }}>/</span>
</DataLabel> <CurrencyFormatter>{job.owner_owing}</CurrencyFormatter>
</DataLabel>
)}
{!isPartsEntry && ( {!isPartsEntry && (
<> <>
<DataLabel label={t("jobs.fields.alt_transport")}> <DataLabel label={t("jobs.fields.alt_transport")}>

View File

@@ -9,7 +9,6 @@ import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { pageLimit } from "../../utils/config"; import { pageLimit } from "../../utils/config";
import { alphaSort, statusSort } from "../../utils/sorters"; import { alphaSort, statusSort } from "../../utils/sorters";
import useLocalStorage from "../../utils/useLocalStorage"; import useLocalStorage from "../../utils/useLocalStorage";
@@ -144,26 +143,6 @@ export function SimplifiedPartsJobsListComponent({
sortOrder: sortcolumn === "clm_no" && sortorder, sortOrder: sortcolumn === "clm_no" && sortorder,
render: (text, record) => `${record.clm_no || ""}${record.po_number ? ` (PO: ${record.po_number})` : ""}` render: (text, record) => `${record.clm_no || ""}${record.po_number ? ` (PO: ${record.po_number})` : ""}`
}, },
{
title: t("jobs.fields.ins_co_nm"),
dataIndex: "ins_co_nm",
key: "ins_co_nm",
ellipsis: true
},
{
title: t("jobs.fields.clm_total"),
dataIndex: "clm_total",
key: "clm_total",
sorter: search?.search ? (a, b) => a.clm_total - b.clm_total : true,
sortOrder: sortcolumn === "clm_total" && sortorder,
render: (text, record) => {
return record.clm_total ? (
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
) : (
t("general.labels.unknown")
);
}
},
{ {
title: t("jobs.fields.partsstatus"), title: t("jobs.fields.partsstatus"),
dataIndex: "partsstatus", dataIndex: "partsstatus",

View File

@@ -0,0 +1,197 @@
{
"OP0": {
"desc": "REMOVE / REPLACE PARTIAL",
"opcode": "OP11",
"partcode": "PAA"
},
"OP1": {
"desc": "REFINISH / REPAIR",
"opcode": "OP1",
"partcode": "PAE"
},
"OP2": {
"desc": "REMOVE / INSTALL",
"opcode": "OP2",
"partcode": "PAE"
},
"OP3": {
"desc": "ADDITIONAL LABOR",
"opcode": "OP9",
"partcode": "PAE"
},
"OP4": {
"desc": "ALIGNMENT",
"opcode": "OP4",
"partcode": "PAS"
},
"OP5": {
"desc": "OVERHAUL",
"opcode": "OP5",
"partcode": "PAE"
},
"OP6": {
"desc": "REFINISH",
"opcode": "OP6",
"partcode": "PAE"
},
"OP7": {
"desc": "INSPECT",
"opcode": "OP7",
"partcode": "PAE"
},
"OP8": {
"desc": "CHECK / ADJUST",
"opcode": "OP8",
"partcode": "PAE"
},
"OP9": {
"desc": "REPAIR",
"opcode": "OP9",
"partcode": "PAE"
},
"OP10": {
"desc": "REPAIR , PARTIAL",
"opcode": "OP9",
"partcode": "PAE"
},
"OP11": {
"desc": "REMOVE / REPLACE",
"opcode": "OP11",
"partcode": "PAN"
},
"OP12": {
"desc": "REMOVE / REPLACE PARTIAL",
"opcode": "OP11",
"partcode": "PAN"
},
"OP13": {
"desc": "ADDITIONAL COSTS",
"opcode": "OP13",
"partcode": "PAE"
},
"OP14": {
"desc": "ADDITIONAL OPERATIONS",
"opcode": "OP14",
"partcode": "PAE"
},
"OP15": {
"desc": "BLEND",
"opcode": "OP15",
"partcode": "PAE"
},
"OP16": {
"desc": "SUBLET",
"opcode": "OP16",
"partcode": "PAS"
},
"OP17": {
"desc": "POLICY LIMIT ADJUSTMENT",
"opcode": "OP9",
"partcode": "PAE"
},
"OP18": {
"desc": "APPEAR ALLOWANCE",
"opcode": "OP7",
"partcode": "PAE"
},
"OP20": {
"desc": "REMOVE AND REINSTALL",
"opcode": "OP20",
"partcode": "PAE"
},
"OP24": {
"desc": "CHIPGUARD",
"opcode": "OP6",
"partcode": "PAE"
},
"OP25": {
"desc": "TWO TONE",
"opcode": "OP6",
"partcode": "PAE"
},
"OP26": {
"desc": "PAINTLESS DENT REPAIR",
"opcode": "OP16",
"partcode": "PAE"
},
"OP100": {
"desc": "REPLACE PRE-PRICED",
"opcode": "OP11",
"partcode": "PAA"
},
"OP101": {
"desc": "REMOVE/REPLACE RECYCLED PART",
"opcode": "OP11",
"partcode": "PAL"
},
"OP103": {
"desc": "REMOVE / REPLACE PARTIAL",
"opcode": "OP11",
"partcode": "PAA"
},
"OP104": {
"desc": "REMOVE / REPLACE PARTIAL LABOUR",
"opcode": "OP11",
"partcode": "PAA"
},
"OP105": {
"desc": "!!ADJUST MANUALLY!!",
"opcode": "OP99",
"partcode": "PAE"
},
"OP106": {
"desc": "REPAIR , PARTIAL",
"opcode": "OP9",
"partcode": "PAE"
},
"OP107": {
"desc": "CHIPGUARD",
"opcode": "OP6",
"partcode": "PAE"
},
"OP108": {
"desc": "MULTI TONE",
"opcode": "OP6",
"partcode": "PAE"
},
"OP109": {
"desc": "REPLACE PRE-PRICED",
"opcode": "OP11",
"partcode": "PAA"
},
"OP110": {
"desc": "REFINISH / REPAIR",
"opcode": "OP1",
"partcode": "PAE"
},
"OP111": {
"desc": "REMOVE / REPLACE",
"opcode": "OP11",
"partcode": "PAN"
},
"OP112": {
"desc": "REMOVE / REPLACE",
"opcode": "OP11",
"partcode": "PAA"
},
"OP113": {
"desc": "REPLACE PRE-PRICED",
"opcode": "OP11",
"partcode": "PAA"
},
"OP114": {
"desc": "REPLACE PRE-PRICED",
"opcode": "OP11",
"partcode": "PAA"
},
"OP120": {
"desc": "REPAIR , PARTIAL",
"opcode": "OP9",
"partcode": "PAE"
},
"OP260": {
"desc": "SUBLET",
"opcode": "OP16",
"partcode": "PAE"
}
}