Compare commits

...

9 Commits

Author SHA1 Message Date
Allan Carr
8cd2e65305 IO-3560 Part # on Return Item Modal
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2026-02-23 19:09:35 -08:00
Allan Carr
e3f49ebca4 Merged in hotfix/2026-02-23 (pull request #3031)
IO-3576 Fortellis Refetch Make Model
2026-02-23 23:31:50 +00:00
Allan Carr
d2d9be433c Merged in feature/IO-3576-Fortellis-Refetch-Make-Model (pull request #3030)
IO-3576 Fortellis Refetch Make Model
2026-02-23 23:28:23 +00:00
Allan Carr
f0c0b5dc45 IO-3576 Fortellis Refetch Make Model
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2026-02-23 15:28:07 -08:00
Allan Carr
a6a621e73f Merged in hotfix/2026-02-19 (pull request #3026)
IO-3570 Strip - from Owner Name in regex
2026-02-19 21:21:52 +00:00
Allan Carr
ba3e831503 Merged in hotfix/2026-02-19 (pull request #3023)
IO-3570 Fortellis Owner Phone Search
2026-02-19 20:37:09 +00:00
Allan Carr
ade8461851 Merged in hotfix/2026-02-19 (pull request #3020)
Hotfix/2026 02 19
2026-02-19 20:07:21 +00:00
Allan Carr
78b9b8d260 Merged in hotfix/2026-02-19 (pull request #3016)
Hotfix/2026 02 19
2026-02-19 18:52:41 +00:00
Allan Carr
6317606ce1 Merged in hotfix/2026-02-19 (pull request #3014)
IO-3570 Filter Vehicle Results from VIN Query to records that only have a vehicleVehID
2026-02-19 18:02:40 +00:00
7 changed files with 84 additions and 41 deletions

View File

@@ -28,6 +28,20 @@ export function BillDetailEditReturn({ setPartsOrderContext, data, disabled }) {
const { t } = useTranslation();
const [form] = Form.useForm();
const [open, setOpen] = useState(false);
const initialValues =
data && data.bills_by_pk
? {
...data.bills_by_pk,
billlines: (data.bills_by_pk.billlines || []).map((bl) => {
const oem = bl.oem_partno || (bl.jobline && bl.jobline.oem_partno) || "";
const alt = bl.alt_partno || (bl.jobline && bl.jobline.alt_partno) || "";
return {
...bl,
oem_partno: `${oem || ""} ${alt ? `(${alt})` : ""}`.trim()
};
})
}
: undefined;
const handleFinish = ({ billlines }) => {
const selectedLines = billlines.filter((l) => l.selected).map((l) => l.id);
@@ -74,8 +88,9 @@ export function BillDetailEditReturn({ setPartsOrderContext, data, disabled }) {
destroyOnHidden
title={t("bills.actions.return")}
onOk={() => form.submit()}
width={700}
>
<Form initialValues={data?.bills_by_pk} onFinish={handleFinish} form={form}>
<Form initialValues={initialValues} onFinish={handleFinish} form={form}>
<Form.List name={["billlines"]}>
{(fields) => {
return (
@@ -95,9 +110,10 @@ export function BillDetailEditReturn({ setPartsOrderContext, data, disabled }) {
/>
</td>
<td>{t("billlines.fields.line_desc")}</td>
<td>{t("billlines.fields.quantity")}</td>
<td>{t("billlines.fields.actual_price")}</td>
<td>{t("billlines.fields.actual_cost")}</td>
<td>{t("billlines.fields.oem_partno")}</td>
<td style={{ textAlign: "right" }}>{t("billlines.fields.quantity")}</td>
<td style={{ textAlign: "right" }}>{t("billlines.fields.actual_price")}</td>
<td style={{ textAlign: "right" }}>{t("billlines.fields.actual_cost")}</td>
</tr>
</thead>
<tbody>
@@ -127,6 +143,15 @@ export function BillDetailEditReturn({ setPartsOrderContext, data, disabled }) {
</Form.Item>
</td>
<td>
<Form.Item
// label={t("joblines.fields.oem_partno")}
key={`${index}jobline.oem_partno`}
name={[field.name, "oem_partno"]}
>
<ReadOnlyFormItemComponent />
</Form.Item>
</td>
<td style={{ textAlign: "right" }}>
<Form.Item
// label={t("joblines.fields.quantity")}
key={`${index}quantity`}
@@ -135,7 +160,7 @@ export function BillDetailEditReturn({ setPartsOrderContext, data, disabled }) {
<ReadOnlyFormItemComponent />
</Form.Item>
</td>
<td>
<td style={{ textAlign: "right" }}>
<Form.Item
// label={t("joblines.fields.actual_price")}
key={`${index}actual_price`}
@@ -144,7 +169,7 @@ export function BillDetailEditReturn({ setPartsOrderContext, data, disabled }) {
<ReadOnlyFormItemComponent type="currency" />
</Form.Item>
</td>
<td>
<td style={{ textAlign: "right" }}>
<Form.Item
// label={t("joblines.fields.actual_cost")}
key={`${index}actual_cost`}

View File

@@ -185,6 +185,7 @@ export const QUERY_BILL_BY_PK = gql`
id
}
jobline {
alt_partno
oem_partno
part_type
}

View File

@@ -167,6 +167,7 @@
"line_desc": "Line Description",
"local_tax_applicable": "Loc. Tax?",
"location": "Location",
"oem_partno": "Part #",
"quantity": "Quantity",
"state_tax_applicable": "St. Tax?"
},

View File

@@ -167,6 +167,7 @@
"line_desc": "",
"local_tax_applicable": "",
"location": "",
"oem_partno": "",
"quantity": "",
"state_tax_applicable": ""
},

View File

@@ -167,6 +167,7 @@
"line_desc": "",
"local_tax_applicable": "",
"location": "",
"oem_partno": "",
"quantity": "",
"state_tax_applicable": ""
},

View File

@@ -264,29 +264,30 @@ const CreateRepairOrderTag = (job, errorCallback) => {
}${job.est_ct_fn ? job.est_ct_fn : ""}`
},
Dates: {
DateEstimated: (job.date_estimated && moment(job.date_estimated).format(DateFormat)) || "",
DateOpened: (job.date_opened && moment(job.date_opened).format(DateFormat)) || "",
DateScheduled:
(job.scheduled_in && moment(job.scheduled_in).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateArrived: (job.actual_in && moment(job.actual_in).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateEstimated: job.date_estimated ? moment(job.date_estimated).format(DateFormat) : "",
DateOpened: job.date_open ? moment(job.date_open).tz(job.bodyshop.timezone).format(DateFormat) : "",
DateScheduled: job.scheduled_in ? moment(job.scheduled_in).tz(job.bodyshop.timezone).format(DateFormat) : "",
DateArrived: job.actual_in ? moment(job.actual_in).tz(job.bodyshop.timezone).format(DateFormat) : "",
DateStart: job.date_repairstarted
? (job.date_repairstarted && moment(job.date_repairstarted).tz(job.bodyshop.timezone).format(DateFormat)) ||
""
: (job.actual_in && moment(job.actual_in).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateScheduledCompletion:
(job.scheduled_completion && moment(job.scheduled_completion).tz(job.bodyshop.timezone).format(DateFormat)) ||
"",
DateCompleted:
(job.actual_completion && moment(job.actual_completion).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateScheduledDelivery:
(job.scheduled_delivery && moment(job.scheduled_delivery).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateDelivered:
(job.actual_delivery && moment(job.actual_delivery).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateInvoiced:
(job.date_invoiced && moment(job.date_invoiced).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateExported:
(job.date_exported && moment(job.date_exported).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateVoid: (job.date_void && moment(job.date_void).tz(job.bodyshop.timezone).format(DateFormat)) || ""
? moment(job.date_repairstarted).tz(job.bodyshop.timezone).format(DateFormat)
: job.actual_in
? moment(job.actual_in).tz(job.bodyshop.timezone).format(DateFormat)
: "",
DateScheduledCompletion: job.scheduled_completion
? moment(job.scheduled_completion).tz(job.bodyshop.timezone).format(DateFormat)
: "",
DateCompleted: job.actual_completion
? moment(job.actual_completion).tz(job.bodyshop.timezone).format(DateFormat)
: "",
DateScheduledDelivery: job.scheduled_delivery
? moment(job.scheduled_delivery).tz(job.bodyshop.timezone).format(DateFormat)
: "",
DateDelivered: job.actual_delivery
? moment(job.actual_delivery).tz(job.bodyshop.timezone).format(DateFormat)
: "",
DateInvoiced: job.date_invoiced ? moment(job.date_invoiced).tz(job.bodyshop.timezone).format(DateFormat) : "",
DateExported: job.date_exported ? moment(job.date_exported).tz(job.bodyshop.timezone).format(DateFormat) : "",
DateVoid: job.date_void ? moment(job.date_void).tz(job.bodyshop.timezone).format(DateFormat) : ""
},
JobLineDetails: (function () {
const joblineSource = Array.isArray(job.joblines) ? job.joblines : job.joblines ? [job.joblines] : [];

View File

@@ -235,18 +235,6 @@ async function MakeFortellisCall({
// jobid: socket?.recordid
// });
if (result.data.checkStatusAfterSeconds) {
return DelayedCallback({
delayMeta: result.data,
access_token,
SubscriptionID: SubscriptionMeta.subscriptionId,
ReqId,
departmentIds: DepartmentId
});
}
logger.log(
"fortellis-log-event-json",
"DEBUG",
@@ -261,6 +249,18 @@ async function MakeFortellisCall({
},
);
if (result.data.checkStatusAfterSeconds) {
return DelayedCallback({
delayMeta: result.data,
access_token,
SubscriptionID: SubscriptionMeta.subscriptionId,
ReqId,
departmentIds: DepartmentId,
jobid,
socket
});
}
return result.data;
} catch (error) {
const errorDetails = {
@@ -310,7 +310,7 @@ async function MakeFortellisCall({
//Some Fortellis calls return a batch result that isn't ready immediately.
//This function will check the status of the call and wait until it is ready.
//It will try 5 times before giving up.
async function DelayedCallback({ delayMeta, access_token, SubscriptionID, ReqId, departmentIds }) {
async function DelayedCallback({ delayMeta, access_token, SubscriptionID, ReqId, departmentIds, jobid, socket }) {
for (let index = 0; index < 5; index++) {
await sleep(delayMeta.checkStatusAfterSeconds * 1000);
//Check to see if the call is ready.
@@ -334,6 +334,19 @@ async function DelayedCallback({ delayMeta, access_token, SubscriptionID, ReqId,
//"Department-Id": departmentIds[0].id
}
});
logger.log(
"fortellis-log-event-json-DelayedCallback",
"DEBUG",
socket?.user?.email,
jobid,
{
requestcurl: batchResult.config.curlCommand,
reqid: batchResult.config.headers["Request-Id"] || null,
subscriptionId: batchResult.config.headers["Subscription-Id"] || null,
resultdata: batchResult.data,
resultStatus: batchResult.status
},
);
// await writeFortellisLogToFile({
// timestamp: new Date().toISOString(),
// reqId: ReqId,