Compare commits

...

82 Commits

Author SHA1 Message Date
Allan Carr
d8d8a4701e IO-2839 DMS Allocation Labels
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-07-10 14:54:04 -07:00
Dave Richer
84bb25985b Merged in release/2024-06-28 (pull request #1510)
Release - 2024/06/28

Approved-by: Allan Carr
2024-06-28 23:02:23 +00:00
Allan Carr
e38a58550f Merged in feature/IO-2832-Purchases-by-RO-Date (pull request #1508)
IO-2832 Purchases by RO - Invoice Date bound

Approved-by: Dave Richer
2024-06-28 15:33:02 +00:00
Allan Carr
25ef4c6228 IO-2832 Purchases by RO - Invoice Date bound
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-27 18:57:43 -07:00
Allan Carr
277fbeebc8 Merged in release/2024-06-28 (pull request #1506)
Release/2024 06 28

Approved-by: Dave Richer
2024-06-26 18:09:45 +00:00
Allan Carr
399df78957 Merged in feature/IO-2793-QBO-State-Tax-Null (pull request #1504)
IO-2793 Insure Part Tax Type Exists
2024-06-26 16:31:40 +00:00
Allan Carr
294325343b IO-2793 Insure Part Tax Type Exists
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-26 09:32:04 -07:00
Allan Carr
ed17eec948 Merged in feature/IO-2829-Multiple-Towing-Lines (pull request #1500)
IO-2829 Multiple Towing Lines

Approved-by: Dave Richer
2024-06-26 00:51:52 +00:00
Allan Carr
f87c95079c Merged in feature/IO-2830-Bill-Line-Select-Search-Component (pull request #1501)
IO-2830 Bill Line Select Search Component

Approved-by: Dave Richer
2024-06-26 00:50:58 +00:00
Allan Carr
327149ffc9 IO-2830 Bill Line Select Search Component
remove unused variable

Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-25 13:32:01 -07:00
Allan Carr
f81b21b933 IO-2829 Multiple Towing Lines
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-25 13:26:56 -07:00
Allan Carr
a559b56983 Merged in feature/IO-2520-Kaizen-Data-Pump (pull request #1499)
IO-2520 Kaizen Data Pump

Approved-by: Dave Richer
2024-06-25 19:22:55 +00:00
Allan Carr
6a9030b653 IO-2520 Kaizen Data Pump
Add in Repair Line Details, Time Ticket Details, Void Date

Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-25 11:57:38 -07:00
Dave Richer
fc7da187f4 Merged in release/2024-06-21 (pull request #1498)
Release/2024 06 21
2024-06-21 22:47:20 +00:00
Allan Carr
f593f83ec1 Merged in feature/IO-2820-Adjust-to-Bottom-Line-State-Tax (pull request #1496)
IO-2820 Adjustment to Bottom Line
2024-06-21 22:32:03 +00:00
Allan Carr
5752f123ac IO-2820 Adjustment to Bottom Line
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-21 15:32:55 -07:00
Allan Carr
6396d68584 Merged in feature/IO-2828-Deliver-Checklist-Delete (pull request #1494)
IO-2828 Add InstanceManager and correct delete button for delivery checklist
2024-06-21 18:14:38 +00:00
Allan Carr
bfd29f25dd IO-2828 Add InstanceManager and correct delete button for delivery checklist
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-21 11:12:10 -07:00
Allan Carr
e75e35e4ee Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1493)
Feature/IO-2793 State Tax Null QBO
2024-06-20 21:39:24 +00:00
Allan Carr
d7ddbf7e8d IO-2793 Change Additional Costs tax item
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-20 14:15:10 -07:00
Allan Carr
1b0198af63 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1491)
IO-2793 Change Additional Costs tax item
2024-06-20 21:14:35 +00:00
Allan Carr
ace16ba873 IO-2793 Adjustment for parts
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-20 13:46:54 -07:00
Allan Carr
f57a4bd948 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1489)
IO-2793 Adjustment for parts
2024-06-20 20:45:44 +00:00
Allan Carr
fef4393f9c Merged in feature/IO-2795-Delivery-Checklist-Option (pull request #1487)
IO-2795 Delivery Date required on Delivery Checklist

Approved-by: Dave Richer
2024-06-20 18:43:20 +00:00
Allan Carr
47adb6d40a IO-2795 Delivery Date required on Delivery Checklist
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-20 11:26:05 -07:00
Allan Carr
4940b10910 IO-2793 Adjustmnet for OP14
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-20 08:30:58 -07:00
Allan Carr
9c8e241ef7 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1486)
IO-2793 Adjustmnet for OP14
2024-06-20 15:30:14 +00:00
Allan Carr
c3d6b98c89 Merged in feature/IO-2820-Adjust-to-Bottom-Line-State-Tax (pull request #1483)
IO-2820 State Tax & Adjustment to Bottom Line

Approved-by: Dave Richer
2024-06-18 20:39:40 +00:00
Allan Carr
4b49654083 Merged in feature/IO-2814-Job-Costing-Correction (pull request #1484)
IO-2814 Job Costing Correction for OP14 Duplication

Approved-by: Dave Richer
2024-06-18 20:39:16 +00:00
Allan Carr
78223078f4 Merged in feature/IO-2816-Unsaved-Changes-Manual-Creation-of-Job (pull request #1485)
IO-2816 Unsaved Changes on Manual Job Creation

Approved-by: Dave Richer
2024-06-18 20:39:03 +00:00
Allan Carr
ca4b78d44c IO-2816 Unsaved Changes on Manual Job Creation
Correct Hardcoded button labels

Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-18 13:16:58 -07:00
Allan Carr
d7bfc789e2 IO-2814 Job Costing Correction for OP14 Duplication
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-18 08:44:35 -07:00
Allan Carr
b54d0ed62a Merge branch 'master-AIO' into feature/IO-2814-Job-Costing-Correction
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-18 08:43:51 -07:00
Allan Carr
8386443cb0 IO-2820 State Tax & Adjustment to Bottom Line
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-17 10:13:36 -07:00
Dave Richer
7959dc67ce Merged in release/AIO/2024-06-07 (pull request #1482)
Release/AIO/2024 06 07
2024-06-11 00:38:31 +00:00
Allan Carr
0d2cdec75c IO-2793 Correction for Sublet Part Tax
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-10 14:42:21 -07:00
Allan Carr
a4116b6c28 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1480)
IO-2793 Correction for Sublet Part Tax
2024-06-10 21:41:17 +00:00
Allan Carr
269ef25ece IO-2793 Better tax handling
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-10 14:14:15 -07:00
Allan Carr
575fbd5357 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1478)
IO-2793 Better tax handling
2024-06-10 21:13:20 +00:00
Allan Carr
2ad887fb82 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1476)
IO-2793 Correct passed Variable
2024-06-10 18:25:27 +00:00
Allan Carr
40a1a86f72 IO-2793 Correct passed Variable
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-10 11:25:06 -07:00
Allan Carr
95d43d936c Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1474)
IO-2793 Correct variables
2024-06-10 18:03:12 +00:00
Allan Carr
9f56568680 IO-2793 Correct variables
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-10 10:58:01 -07:00
Allan Carr
3428940c72 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1472)
IO-2793 Change to function for better clarity
2024-06-10 17:49:06 +00:00
Allan Carr
ea604a5e64 IO-2793 Change to function for better clarity
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-10 09:59:45 -07:00
Allan Carr
5b76473cbc IO-2793 Correct Parts Side for Taxes
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-07 15:59:51 -07:00
Allan Carr
db5359e086 Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1470)
Feature/IO-2793 State Tax Null QBO
2024-06-07 22:58:58 +00:00
Allan Carr
35046f11c2 IO-2793 Add Comment to see output for testing
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-07 14:31:33 -07:00
Allan Carr
f4c4005a2a IO-2814 Remove Comment as api.test.romeonline.io doesn't update w/ CICD
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-07 12:16:59 -07:00
Allan Carr
69d8d27ad3 Merged in feature/IO-2814-Job-Costing-Correction (pull request #1467)
IO-2814 Remove Comment as api.test.romeonline.io doesn't update w/ CICD
2024-06-07 19:16:01 +00:00
Allan Carr
755acd24f0 IO-2814 Correct Parts Price and add Console Log
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-07 11:40:39 -07:00
Allan Carr
079d6cfee6 Merged in feature/IO-2814-Job-Costing-Correction (pull request #1465)
IO-2814 Correct Parts Price and add Console Log
2024-06-07 18:39:43 +00:00
Allan Carr
3e3b3c269a Merged in feature/IO-2814-Job-Costing-Correction (pull request #1462)
IO-2814 Job Cost Correction
2024-06-07 03:18:49 +00:00
Allan Carr
39f1af7d4b Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1463)
IO-2793 State Tax Null QBO
2024-06-07 03:18:40 +00:00
Allan Carr
1ea4d616d7 IO-2793 State Tax Null QBO
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-06 15:00:58 -07:00
Allan Carr
fdf0ecf6f6 IO-2814 Job Cost Correction
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-06 14:51:44 -07:00
Allan Carr
e5f7285253 Merge branch 'feature/IO-2793-State-Tax-Null-QBO' into release/AIO/2024-06-07
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>

# Conflicts:
#	server/accounting/qb-receivables-lines.js
2024-06-03 17:28:18 -07:00
Allan Carr
e46c304f7c IO-2793 State Tax to QBO refactor
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-03 17:23:33 -07:00
Dave Richer
1aa570db90 Merged in hotfix/revert-tax-import-code (pull request #1459)
revert previous change due to problems with tax import.
2024-06-03 22:04:31 +00:00
Dave Richer
1c2be3c890 Merged in hotfix/revert-tax-import-code (pull request #1458)
revert previous change due to problems with tax import.
2024-06-03 22:04:05 +00:00
Dave Richer
05e4eacf34 revert previous change due to problems with tax import.
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-06-03 18:03:22 -04:00
Allan Carr
e1417b03f9 Merged in feature/IO-2801-os-loader-bills-data (pull request #1456)
IO-2801 os-loader bills data

Approved-by: Dave Richer
2024-06-03 18:59:08 +00:00
Allan Carr
7b99de8046 IO-2801 os-loader bills data
add in job object to bills in opensearch for ro_number to be searchable again

Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-03 11:50:44 -07:00
Dave Richer
6dc03d7f67 Merged in release/AIO/2024-05-31 (pull request #1452)
Release/AIO/2024 05 31
2024-06-01 17:19:20 +00:00
Allan Carr
2a5e6a51aa Merged in feature/IO-2793-State-Tax-Null-QBO (pull request #1451)
IO-2793 State Tax Rate Null send to QBO

Approved-by: Dave Richer
2024-06-01 17:16:55 +00:00
Allan Carr
885477fa68 IO-2793 State Tax Rate Null send to QBO
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-05-31 12:31:49 -07:00
Dave Richer
c7db792793 Merged in feature/IO-2796-Header-IDS (pull request #1450)
- Add Additional IDS to headers
2024-05-31 17:23:55 +00:00
Dave Richer
31be51ef79 Merged release/AIO/2024-05-31 into feature/IO-2796-Header-IDS 2024-05-31 17:23:45 +00:00
Dave Richer
e4066c1570 - Add Additional IDS to headers
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-05-31 13:20:54 -04:00
Patrick Fic
ec480f2cb1 Resolve Bill Posting errors on Beta. 2024-05-29 14:08:49 -07:00
Patrick Fic
f5b30c9376 Resolve API Route. 2024-05-28 12:23:42 -07:00
Patrick Fic
412508fbcf Merge branch 'hotfix/AIO/2024-05-28' into master-AIO 2024-05-28 12:19:28 -07:00
Patrick Fic
dbfd9bce54 Resolve region for US intellipay. 2024-05-28 12:19:18 -07:00
Dave Richer
52e0558c79 Merged in release/AIO/2024-05-24 (pull request #1449)
Release/AIO/2024 05 24
2024-05-24 20:45:23 +00:00
Allan Carr
562d0b8641 Merged in feature/IO-2785-IO-Rescue-Header (pull request #1444)
IO-2785 AIO IO Header Rescue Link

Approved-by: Dave Richer
2024-05-23 19:47:27 +00:00
Patrick Fic
d48d6cdd91 Merge branch 'hotfix/AIO/2024-05-23' into release/AIO/2024-05-24 2024-05-23 11:40:35 -07:00
Patrick Fic
9363790541 Merge branch 'hotfix/AIO/2024-05-23' into master-AIO 2024-05-23 10:58:13 -07:00
Patrick Fic
2bceba948d Resolve postback logging. 2024-05-23 10:57:39 -07:00
Patrick Fic
cdf6050ec2 Merge branch 'release/AIO/2024-05-17' into release/AIO/2024-05-24 2024-05-22 08:43:41 -07:00
Patrick Fic
f451155689 Add Firebase Service Worker to public. 2024-05-15 10:27:42 -07:00
Dave Richer
9f06e19346 Fix eslint regression
Signed-off-by: Dave Richer <dave@imexsystems.ca>
2024-05-14 12:38:56 -04:00
Dave Richer
f4be3e9668 Fix issue with global search 2024-05-14 12:20:49 -04:00
27 changed files with 2103 additions and 1797 deletions

View File

@@ -0,0 +1,56 @@
// Scripts for firebase and firebase messaging
importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js");
// Initialize the Firebase app in the service worker by passing the generated config
let firebaseConfig;
switch (this.location.hostname) {
case "localhost":
firebaseConfig = {
apiKey: "AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc",
authDomain: "imex-dev.firebaseapp.com",
databaseURL: "https://imex-dev.firebaseio.com",
projectId: "imex-dev",
storageBucket: "imex-dev.appspot.com",
messagingSenderId: "759548147434",
appId: "1:759548147434:web:e8239868a48ceb36700993",
measurementId: "G-K5XRBVVB4S",
};
break;
case "test.imex.online":
firebaseConfig = {
apiKey: "AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c",
authDomain: "imex-test.firebaseapp.com",
projectId: "imex-test",
storageBucket: "imex-test.appspot.com",
messagingSenderId: "991923618608",
appId: "1:991923618608:web:633437569cdad78299bef5",
// measurementId: "${config.measurementId}",
};
break;
case "imex.online":
default:
firebaseConfig = {
apiKey: "AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU",
authDomain: "imex-prod.firebaseapp.com",
databaseURL: "https://imex-prod.firebaseio.com",
projectId: "imex-prod",
storageBucket: "imex-prod.appspot.com",
messagingSenderId: "253497221485",
appId: "1:253497221485:web:3c81c483b94db84b227a64",
measurementId: "G-NTWBKG2L0M",
};
}
firebase.initializeApp(firebaseConfig);
// Retrieve firebase messaging
const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (payload) {
// Customize notification here
const channel = new BroadcastChannel("imex-sw-messages");
channel.postMessage(payload);
//self.registration.showNotification(notificationTitle, notificationOptions);
});

View File

@@ -150,7 +150,7 @@ export function App({ bodyshop, checkUserSession, currentUser, online, setOnline
<ProductFruits <ProductFruits
workspaceCode={InstanceRenderMgr({ workspaceCode={InstanceRenderMgr({
imex: null, imex: null,
rome: null, rome: "9BkbEseqNqxw8jUH",
promanager: "aoJoEifvezYI0Z0P" promanager: "aoJoEifvezYI0Z0P"
})} })}
debug debug

View File

@@ -4,7 +4,6 @@ import { useTranslation } from "react-i18next";
import InstanceRenderMgr from "../../utils/instanceRenderMgr"; import InstanceRenderMgr from "../../utils/instanceRenderMgr";
//To be used as a form element only. //To be used as a form element only.
const { Option } = Select;
const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps }, ref) => { const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps }, ref) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -25,31 +24,27 @@ const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps },
); );
}} }}
notFoundContent={"Removed."} notFoundContent={"Removed."}
{...restProps} options={[
> { value: "noline", label: t("billlines.labels.other"), name: t("billlines.labels.other") },
<Select.Option key={null} value={"noline"} cost={0} line_desc={""}> ...options.map((item) => ({
{t("billlines.labels.other")} disabled: allowRemoved ? false : item.removed,
</Select.Option> key: item.id,
{options value: item.id,
? options.map((item) => ( cost: item.act_price ? item.act_price : 0,
<Option part_type: item.part_type,
disabled={allowRemoved ? false : item.removed} line_desc: item.line_desc,
key={item.id} part_qty: item.part_qty,
value={item.id} oem_partno: item.oem_partno,
cost={item.act_price ? item.act_price : 0} alt_partno: item.alt_partno,
part_type={item.part_type} act_price: item.act_price,
line_desc={item.line_desc} style: {
part_qty={item.part_qty} ...(item.removed ? { textDecoration: "line-through" } : {})
oem_partno={item.oem_partno} },
alt_partno={item.alt_partno} name: `${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
act_price={item.act_price} item.oem_partno ? ` - ${item.oem_partno}` : ""
style={{ }${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim(),
...(item.removed ? { textDecoration: "line-through" } : {}) label: (
}} <>
name={`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
item.oem_partno ? ` - ${item.oem_partno}` : ""
}${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim()}
>
<span> <span>
{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${ {`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
item.oem_partno ? ` - ${item.oem_partno}` : "" item.oem_partno ? ` - ${item.oem_partno}` : ""
@@ -60,14 +55,15 @@ const BillLineSearchSelect = ({ options, disabled, allowRemoved, ...restProps },
<span style={{ float: "right", paddingleft: "1rem" }}>{`${item.mod_lb_hrs} units`}</span> <span style={{ float: "right", paddingleft: "1rem" }}>{`${item.mod_lb_hrs} units`}</span>
) )
})} })}
<span style={{ float: "right", paddingleft: "1rem" }}> <span style={{ float: "right", paddingleft: "1rem" }}>
{item.act_price ? `$${item.act_price && item.act_price.toFixed(2)}` : ``} {item.act_price ? `$${item.act_price && item.act_price.toFixed(2)}` : ``}
</span> </span>
</Option> </>
)) )
: null} }))
</Select> ]}
{...restProps}
></Select>
); );
}; };
export default forwardRef(BillLineSearchSelect); export default forwardRef(BillLineSearchSelect);

View File

@@ -3,14 +3,13 @@ import axios from "axios";
import _ from "lodash"; import _ from "lodash";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link } from "react-router-dom";
import PhoneNumberFormatter from "../../utils/PhoneFormatter"; import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component"; import OwnerNameDisplay, { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component"; import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component";
export default function GlobalSearchOs() { export default function GlobalSearchOs() {
const { t } = useTranslation(); const { t } = useTranslation();
const history = useNavigate();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [data, setData] = useState(false); const [data, setData] = useState(false);
@@ -178,15 +177,7 @@ export default function GlobalSearchOs() {
}; };
return ( return (
<AutoComplete <AutoComplete options={data} onSearch={handleSearch} defaultActiveFirstOption onClear={() => setData([])}>
options={data}
onSearch={handleSearch}
defaultActiveFirstOption
onSelect={(val, opt) => {
history(opt.label.props.to);
}}
onClear={() => setData([])}
>
<Input.Search <Input.Search
size="large" size="large"
placeholder={t("general.labels.globalsearch")} placeholder={t("general.labels.globalsearch")}

View File

@@ -3,7 +3,7 @@ import { AutoComplete, Divider, Input, Space } from "antd";
import _ from "lodash"; import _ from "lodash";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link } from "react-router-dom";
import { GLOBAL_SEARCH_QUERY } from "../../graphql/search.queries"; import { GLOBAL_SEARCH_QUERY } from "../../graphql/search.queries";
import PhoneNumberFormatter from "../../utils/PhoneFormatter"; import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import AlertComponent from "../alert/alert.component"; import AlertComponent from "../alert/alert.component";
@@ -12,7 +12,6 @@ import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.compon
export default function GlobalSearch() { export default function GlobalSearch() {
const { t } = useTranslation(); const { t } = useTranslation();
const history = useNavigate();
const [callSearch, { loading, error, data }] = useLazyQuery(GLOBAL_SEARCH_QUERY); const [callSearch, { loading, error, data }] = useLazyQuery(GLOBAL_SEARCH_QUERY);
const executeSearch = (v) => { const executeSearch = (v) => {
@@ -157,14 +156,7 @@ export default function GlobalSearch() {
if (error) return <AlertComponent message={error.message} type="error" />; if (error) return <AlertComponent message={error.message} type="error" />;
return ( return (
<AutoComplete <AutoComplete options={options} onSearch={handleSearch} defaultActiveFirstOption>
options={options}
onSearch={handleSearch}
defaultActiveFirstOption
onSelect={(val, opt) => {
history(opt.label.props.to);
}}
>
<Input.Search <Input.Search
size="large" size="large"
placeholder={t("general.labels.globalsearch")} placeholder={t("general.labels.globalsearch")}

View File

@@ -141,11 +141,13 @@ function Header({
accountingChildren.push( accountingChildren.push(
{ {
key: "bills", key: "bills",
id: "header-accounting-bills",
icon: <Icon component={FaFileInvoiceDollar} />, icon: <Icon component={FaFileInvoiceDollar} />,
label: <Link to="/manage/bills">{t("menus.header.bills")}</Link> label: <Link to="/manage/bills">{t("menus.header.bills")}</Link>
}, },
{ {
key: "enterbills", key: "enterbills",
id: "header-accounting-enterbills",
icon: <Icon component={GiPayMoney} />, icon: <Icon component={GiPayMoney} />,
label: t("menus.header.enterbills"), label: t("menus.header.enterbills"),
onClick: () => { onClick: () => {
@@ -165,6 +167,7 @@ function Header({
}, },
{ {
key: "inventory", key: "inventory",
id: "header-accounting-inventory",
icon: <Icon component={FaFileInvoiceDollar} />, icon: <Icon component={FaFileInvoiceDollar} />,
label: <Link to="/manage/inventory">{t("menus.header.inventory")}</Link> label: <Link to="/manage/inventory">{t("menus.header.inventory")}</Link>
} }
@@ -183,11 +186,13 @@ function Header({
}, },
{ {
key: "allpayments", key: "allpayments",
id: "header-accounting-allpayments",
icon: <BankFilled />, icon: <BankFilled />,
label: <Link to="/manage/payments">{t("menus.header.allpayments")}</Link> label: <Link to="/manage/payments">{t("menus.header.allpayments")}</Link>
}, },
{ {
key: "enterpayments", key: "enterpayments",
id: "header-accounting-enterpayments",
icon: <Icon component={FaCreditCard} />, icon: <Icon component={FaCreditCard} />,
label: t("menus.header.enterpayment"), label: t("menus.header.enterpayment"),
onClick: () => { onClick: () => {
@@ -203,6 +208,7 @@ function Header({
if (ImEXPay.treatment === "on") { if (ImEXPay.treatment === "on") {
accountingChildren.push({ accountingChildren.push({
key: "entercardpayments", key: "entercardpayments",
id: "header-accounting-entercardpayments",
icon: <Icon component={FaCreditCard} />, icon: <Icon component={FaCreditCard} />,
label: t("menus.header.entercardpayment"), label: t("menus.header.entercardpayment"),
onClick: () => { onClick: () => {
@@ -227,6 +233,7 @@ function Header({
}, },
{ {
key: "timetickets", key: "timetickets",
id: "header-accounting-timetickets",
icon: <FieldTimeOutlined />, icon: <FieldTimeOutlined />,
label: <Link to="/manage/timetickets">{t("menus.header.timetickets")}</Link> label: <Link to="/manage/timetickets">{t("menus.header.timetickets")}</Link>
} }
@@ -235,6 +242,7 @@ function Header({
if (bodyshop?.md_tasks_presets?.use_approvals) { if (bodyshop?.md_tasks_presets?.use_approvals) {
accountingChildren.push({ accountingChildren.push({
key: "ttapprovals", key: "ttapprovals",
id: "header-accounting-ttapprovals",
icon: <FieldTimeOutlined />, icon: <FieldTimeOutlined />,
label: <Link to="/manage/ttapprovals">{t("menus.header.ttapprovals")}</Link> label: <Link to="/manage/ttapprovals">{t("menus.header.ttapprovals")}</Link>
}); });
@@ -244,6 +252,7 @@ function Header({
key: "entertimetickets", key: "entertimetickets",
icon: <Icon component={GiPlayerTime} />, icon: <Icon component={GiPlayerTime} />,
label: t("menus.header.entertimeticket"), label: t("menus.header.entertimeticket"),
id: "header-accounting-entertimetickets",
onClick: () => { onClick: () => {
setTimeTicketContext({ setTimeTicketContext({
actions: {}, actions: {},
@@ -264,6 +273,7 @@ function Header({
const accountingExportChildren = [ const accountingExportChildren = [
{ {
key: "receivables", key: "receivables",
id: "header-accounting-receivables",
label: <Link to="/manage/accounting/receivables">{t("menus.header.accounting-receivables")}</Link> label: <Link to="/manage/accounting/receivables">{t("menus.header.accounting-receivables")}</Link>
} }
]; ];
@@ -271,6 +281,7 @@ function Header({
if (!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber)) || DmsAp.treatment === "on") { if (!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber)) || DmsAp.treatment === "on") {
accountingExportChildren.push({ accountingExportChildren.push({
key: "payables", key: "payables",
id: "header-accounting-payables",
label: <Link to="/manage/accounting/payables">{t("menus.header.accounting-payables")}</Link> label: <Link to="/manage/accounting/payables">{t("menus.header.accounting-payables")}</Link>
}); });
} }
@@ -278,6 +289,7 @@ function Header({
if (!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber))) { if (!((bodyshop && bodyshop.cdk_dealerid) || (bodyshop && bodyshop.pbs_serialnumber))) {
accountingExportChildren.push({ accountingExportChildren.push({
key: "payments", key: "payments",
id: "header-accounting-payments",
label: <Link to="/manage/accounting/payments">{t("menus.header.accounting-payments")}</Link> label: <Link to="/manage/accounting/payments">{t("menus.header.accounting-payments")}</Link>
}); });
} }
@@ -288,6 +300,7 @@ function Header({
}, },
{ {
key: "exportlogs", key: "exportlogs",
id: "header-accounting-exportlogs",
label: <Link to="/manage/accounting/exportlogs">{t("menus.header.export-logs")}</Link> label: <Link to="/manage/accounting/exportlogs">{t("menus.header.export-logs")}</Link>
} }
); );
@@ -301,6 +314,7 @@ function Header({
) { ) {
accountingChildren.push({ accountingChildren.push({
key: "accountingexport", key: "accountingexport",
id: "header-accounting-export",
icon: <ExportOutlined />, icon: <ExportOutlined />,
label: t("menus.header.export"), label: t("menus.header.export"),
children: accountingExportChildren children: accountingExportChildren

View File

@@ -1,6 +1,5 @@
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { Button, Card, Form, Input, notification, Switch } from "antd"; import { Button, Card, Form, Input, notification, Switch } from "antd";
import dayjs from "../../../../utils/day";
import queryString from "query-string"; import queryString from "query-string";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -14,6 +13,7 @@ import { UPDATE_OWNER } from "../../../../graphql/owners.queries";
import { insertAuditTrail } from "../../../../redux/application/application.actions"; import { insertAuditTrail } from "../../../../redux/application/application.actions";
import { selectBodyshop, selectCurrentUser } from "../../../../redux/user/user.selectors"; import { selectBodyshop, selectCurrentUser } from "../../../../redux/user/user.selectors";
import AuditTrailMapping from "../../../../utils/AuditTrailMappings"; import AuditTrailMapping from "../../../../utils/AuditTrailMappings";
import dayjs from "../../../../utils/day";
import ConfigFormComponents from "../../../config-form-components/config-form-components.component"; import ConfigFormComponents from "../../../config-form-components/config-form-components.component";
import DateTimePicker from "../../../form-date-time-picker/form-date-time-picker.component"; import DateTimePicker from "../../../form-date-time-picker/form-date-time-picker.component";
@@ -275,7 +275,19 @@ export function JobChecklistForm({ insertAuditTrail, formItems, bodyshop, curren
> >
<DateTimePicker disabled={readOnly} /> <DateTimePicker disabled={readOnly} />
</Form.Item> </Form.Item>
<Form.Item name="actual_delivery" label={t("jobs.fields.actual_delivery")} disabled={readOnly}> <Form.Item
name="actual_delivery"
label={t("jobs.fields.actual_delivery")}
rules={[
{
required: bodyshop.deliverchecklist.actual_delivery
? bodyshop.deliverchecklist.actual_delivery
: false
//message: t("general.validation.required"),
}
]}
disabled={readOnly}
>
<DateTimePicker disabled={readOnly} /> <DateTimePicker disabled={readOnly} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item

View File

@@ -3,6 +3,7 @@ import { Button, Space, notification } from "antd";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { DELETE_DELIVERY_CHECKLIST, DELETE_INTAKE_CHECKLIST } from "../../graphql/jobs.queries"; import { DELETE_DELIVERY_CHECKLIST, DELETE_INTAKE_CHECKLIST } from "../../graphql/jobs.queries";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
export default function JobAdminDeleteIntake({ job }) { export default function JobAdminDeleteIntake({ job }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -47,16 +48,22 @@ export default function JobAdminDeleteIntake({ job }) {
setLoading(false); setLoading(false);
}; };
return ( const InstanceRender = InstanceRenderManager({
imex: true,
rome: "USE_IMEX",
promanager: false
});
return InstanceRender ? (
<> <>
<Space wrap> <Space wrap>
<Button loading={loading} onClick={handleDelete} disabled={!job.intakechecklist}> <Button loading={loading} onClick={handleDelete} disabled={!job.intakechecklist}>
{t("jobs.labels.deleteintake")} {t("jobs.labels.deleteintake")}
</Button> </Button>
<Button loading={loading} onClick={handleDeleteDelivery} disabled={!job.deliverychecklist}> <Button loading={loading} onClick={handleDeleteDelivery} disabled={!job.deliverchecklist}>
{t("jobs.labels.deletedelivery")} {t("jobs.labels.deletedelivery")}
</Button> </Button>
</Space> </Space>
</> </>
); ) : null;
} }

View File

@@ -1,7 +1,7 @@
import { DownCircleFilled } from "@ant-design/icons"; import { DownCircleFilled } from "@ant-design/icons";
import { useApolloClient, useMutation } from "@apollo/client"; import { useApolloClient, useMutation } from "@apollo/client";
import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Button, Card, Dropdown, Form, Input, Modal, Popconfirm, Popover, Select, Space, notification } from "antd"; import { Button, Card, Dropdown, Form, Input, Modal, notification, Popconfirm, Popover, Select, Space } from "antd";
import axios from "axios"; import axios from "axios";
import parsePhoneNumber from "libphonenumber-js"; import parsePhoneNumber from "libphonenumber-js";
import React, { useMemo, useState } from "react"; import React, { useMemo, useState } from "react";
@@ -641,6 +641,7 @@ export function JobsDetailHeaderActions({
const menuItems = [ const menuItems = [
{ {
key: "schedule", key: "schedule",
id: "job-actions-schedule",
disabled: !jobInPreProduction || !job.converted || jobRO, disabled: !jobInPreProduction || !job.converted || jobRO,
label: t("jobs.actions.schedule"), label: t("jobs.actions.schedule"),
onClick: () => { onClick: () => {
@@ -657,6 +658,7 @@ export function JobsDetailHeaderActions({
}, },
{ {
key: "cancelallappointments", key: "cancelallappointments",
id: "job-actions-cancelallappointments",
onClick: () => { onClick: () => {
if (job.status !== bodyshop.md_ro_statuses.default_scheduled) { if (job.status !== bodyshop.md_ro_statuses.default_scheduled) {
return; return;
@@ -670,6 +672,7 @@ export function JobsDetailHeaderActions({
imex: [ imex: [
{ {
key: "intake", key: "intake",
id: "job-actions-intake",
disabled: !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO, disabled: !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO,
label: label:
!!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO ? ( !!job.intakechecklist || !jobInPreProduction || !job.converted || jobRO ? (
@@ -680,6 +683,7 @@ export function JobsDetailHeaderActions({
}, },
{ {
key: "deliver", key: "deliver",
id: "job-actions-deliver",
disabled: !jobInProduction || jobRO, disabled: !jobInProduction || jobRO,
label: !jobInProduction ? ( label: !jobInProduction ? (
t("jobs.actions.deliver") t("jobs.actions.deliver")
@@ -689,6 +693,7 @@ export function JobsDetailHeaderActions({
}, },
{ {
key: "checklist", key: "checklist",
id: "job-actions-checklist",
disabled: !job.converted, disabled: !job.converted,
label: <Link to={`/manage/jobs/${job.id}/checklist`}>{t("jobs.actions.viewchecklist")}</Link> label: <Link to={`/manage/jobs/${job.id}/checklist`}>{t("jobs.actions.viewchecklist")}</Link>
} }
@@ -697,6 +702,7 @@ export function JobsDetailHeaderActions({
promanager: [ promanager: [
{ {
key: "toggleproduction", key: "toggleproduction",
id: "job-actions-toggleproduction",
disabled: !job.converted || jobRO, disabled: !job.converted || jobRO,
label: <JobsDetailHeaderActionsToggleProduction job={job} refetch={refetch} /> label: <JobsDetailHeaderActionsToggleProduction job={job} refetch={refetch} />
} }
@@ -710,6 +716,7 @@ export function JobsDetailHeaderActions({
? [ ? [
{ {
key: "entertimetickets", key: "entertimetickets",
id: "job-actions-entertimetickets",
disabled: !job.converted || (!bodyshop.tt_allow_post_to_invoiced && job.date_invoiced), disabled: !job.converted || (!bodyshop.tt_allow_post_to_invoiced && job.date_invoiced),
label: t("timetickets.actions.enter"), label: t("timetickets.actions.enter"),
onClick: () => { onClick: () => {
@@ -733,6 +740,7 @@ export function JobsDetailHeaderActions({
if (bodyshop.md_tasks_presets.enable_tasks) { if (bodyshop.md_tasks_presets.enable_tasks) {
menuItems.push({ menuItems.push({
key: "claimtimetickettasks", key: "claimtimetickettasks",
id: "job-actions-claimtimetickettasks",
disabled: !job.converted || (!bodyshop.tt_allow_post_to_invoiced && job.date_invoiced), disabled: !job.converted || (!bodyshop.tt_allow_post_to_invoiced && job.date_invoiced),
onClick: () => { onClick: () => {
setTimeTicketTaskContext({ setTimeTicketTaskContext({
@@ -746,6 +754,7 @@ export function JobsDetailHeaderActions({
menuItems.push({ menuItems.push({
key: "enterpayments", key: "enterpayments",
id: "job-actions-enterpayments",
disabled: !job.converted, disabled: !job.converted,
label: t("menus.header.enterpayment"), label: t("menus.header.enterpayment"),
onClick: () => { onClick: () => {
@@ -761,6 +770,7 @@ export function JobsDetailHeaderActions({
if (ImEXPay.treatment === "on") { if (ImEXPay.treatment === "on") {
menuItems.push({ menuItems.push({
key: "entercardpayments", key: "entercardpayments",
id: "job-actions-entercardpayments",
disabled: !job.converted, disabled: !job.converted,
label: t("menus.header.entercardpayment"), label: t("menus.header.entercardpayment"),
onClick: () => { onClick: () => {
@@ -777,6 +787,7 @@ export function JobsDetailHeaderActions({
if (HasFeatureAccess({ featureName: "courtesycars", bodyshop })) { if (HasFeatureAccess({ featureName: "courtesycars", bodyshop })) {
menuItems.push({ menuItems.push({
key: "cccontract", key: "cccontract",
id: "job-actions-cccontract",
disabled: jobRO || !job.converted, disabled: jobRO || !job.converted,
label: ( label: (
<Link state={{ jobId: job.id }} to="/manage/courtesycars/contracts/new"> <Link state={{ jobId: job.id }} to="/manage/courtesycars/contracts/new">
@@ -788,6 +799,7 @@ export function JobsDetailHeaderActions({
menuItems.push({ menuItems.push({
key: "createtask", key: "createtask",
id: "job-actions-createtask",
label: t("menus.header.create_task"), label: t("menus.header.create_task"),
onClick: () => onClick: () =>
setTaskUpsertContext({ setTaskUpsertContext({
@@ -800,12 +812,14 @@ export function JobsDetailHeaderActions({
job.inproduction job.inproduction
? { ? {
key: "removefromproduction", key: "removefromproduction",
id: "job-actions-removefromproduction",
disabled: !job.converted, disabled: !job.converted,
label: t("jobs.actions.removefromproduction"), label: t("jobs.actions.removefromproduction"),
onClick: () => AddToProduction(client, job.id, refetch, true) onClick: () => AddToProduction(client, job.id, refetch, true)
} }
: { : {
key: "addtoproduction", key: "addtoproduction",
id: "job-actions-addtoproduction",
disabled: !job.converted, disabled: !job.converted,
label: t("jobs.actions.addtoproduction"), label: t("jobs.actions.addtoproduction"),
onClick: () => AddToProduction(client, job.id, refetch) onClick: () => AddToProduction(client, job.id, refetch)
@@ -815,12 +829,14 @@ export function JobsDetailHeaderActions({
menuItems.push( menuItems.push(
{ {
key: "togglesuspend", key: "togglesuspend",
id: "job-actions-togglesuspend",
onClick: handleSuspend, onClick: handleSuspend,
label: job.suspended ? t("production.actions.unsuspend") : t("production.actions.suspend") label: job.suspended ? t("production.actions.unsuspend") : t("production.actions.suspend")
}, },
{ {
key: "toggleAlert", key: "toggleAlert",
onClick: handleAlertToggle, onClick: handleAlertToggle,
id: "job-actions-togglealert",
label: label:
job.production_vars && job.production_vars.alert job.production_vars && job.production_vars.alert
? t("production.labels.alertoff") ? t("production.labels.alertoff")
@@ -832,6 +848,7 @@ export function JobsDetailHeaderActions({
children: [ children: [
{ {
key: "duplicate", key: "duplicate",
id: "job-actions-duplicate",
label: ( label: (
<Popconfirm <Popconfirm
title={t("jobs.labels.duplicateconfirm")} title={t("jobs.labels.duplicateconfirm")}
@@ -847,6 +864,7 @@ export function JobsDetailHeaderActions({
}, },
{ {
key: "duplicatenolines", key: "duplicatenolines",
id: "job-actions-duplicatenolines",
label: ( label: (
<Popconfirm <Popconfirm
title={t("jobs.labels.duplicateconfirm")} title={t("jobs.labels.duplicateconfirm")}
@@ -870,6 +888,7 @@ export function JobsDetailHeaderActions({
? [ ? [
{ {
key: "postbills", key: "postbills",
id: "job-actions-postbills",
disabled: !job.converted, disabled: !job.converted,
label: t("jobs.actions.postbills"), label: t("jobs.actions.postbills"),
onClick: () => { onClick: () => {
@@ -888,6 +907,7 @@ export function JobsDetailHeaderActions({
{ {
key: "addtopartsqueue", key: "addtopartsqueue",
id: "job-actions-addtopartsqueue",
disabled: !job.converted || !jobInProduction || jobRO, disabled: !job.converted || !jobInProduction || jobRO,
label: t("jobs.actions.addtopartsqueue"), label: t("jobs.actions.addtopartsqueue"),
onClick: async () => { onClick: async () => {
@@ -913,6 +933,7 @@ export function JobsDetailHeaderActions({
}, },
{ {
key: "closejob", key: "closejob",
id: "job-actions-closejob",
disabled: !jobInPostProduction, disabled: !jobInPostProduction,
label: !jobInPostProduction ? ( label: !jobInPostProduction ? (
t("menus.jobsactions.closejob") t("menus.jobsactions.closejob")
@@ -928,6 +949,7 @@ export function JobsDetailHeaderActions({
}, },
{ {
key: "admin", key: "admin",
id: "job-actions-admin",
label: ( label: (
<Link <Link
to={{ to={{
@@ -949,6 +971,7 @@ export function JobsDetailHeaderActions({
) { ) {
menuItems.push({ menuItems.push({
key: "exportcustdata", key: "exportcustdata",
id: "job-actions-exportcustdata",
disabled: !job.converted, disabled: !job.converted,
label: t("jobs.actions.exportcustdata"), label: t("jobs.actions.exportcustdata"),
onClick: handleExportCustData onClick: handleExportCustData
@@ -959,18 +982,21 @@ export function JobsDetailHeaderActions({
const children = [ const children = [
{ {
key: "email", key: "email",
id: "job-actions-email",
disabled: !!!job.ownr_ea, disabled: !!!job.ownr_ea,
label: t("general.labels.email"), label: t("general.labels.email"),
onClick: handleCreateCsi onClick: handleCreateCsi
}, },
{ {
key: "text", key: "text",
id: "job-actions-text",
disabled: !!!job.ownr_ph1, disabled: !!!job.ownr_ph1,
label: t("general.labels.text"), label: t("general.labels.text"),
onClick: handleCreateCsi onClick: handleCreateCsi
}, },
{ {
key: "generate", key: "generate",
id: "job-actions-generate",
disabled: job.csiinvites && job.csiinvites.length > 0, disabled: job.csiinvites && job.csiinvites.length > 0,
label: t("jobs.actions.generatecsi"), label: t("jobs.actions.generatecsi"),
onClick: handleCreateCsi onClick: handleCreateCsi
@@ -1004,6 +1030,7 @@ export function JobsDetailHeaderActions({
} }
menuItems.push({ menuItems.push({
key: "sendcsi", key: "sendcsi",
id: "job-actions-sendcsi",
label: t("jobs.actions.sendcsi"), label: t("jobs.actions.sendcsi"),
disabled: !job.converted, disabled: !job.converted,
children children
@@ -1012,6 +1039,7 @@ export function JobsDetailHeaderActions({
menuItems.push({ menuItems.push({
key: "jobcosting", key: "jobcosting",
id: "job-actions-jobcosting",
disabled: !job.converted, disabled: !job.converted,
label: t("jobs.labels.jobcosting"), label: t("jobs.labels.jobcosting"),
onClick: () => { onClick: () => {
@@ -1029,6 +1057,7 @@ export function JobsDetailHeaderActions({
if (job && !job.converted) { if (job && !job.converted) {
menuItems.push({ menuItems.push({
key: "deletejob", key: "deletejob",
id: "job-actions-deletejob",
label: ( label: (
<Popconfirm <Popconfirm
title={t("jobs.labels.deleteconfirm")} title={t("jobs.labels.deleteconfirm")}
@@ -1045,6 +1074,7 @@ export function JobsDetailHeaderActions({
menuItems.push({ menuItems.push({
key: "manualevent", key: "manualevent",
id: "job-actions-manualevent",
onClick: (e) => { onClick: (e) => {
setVisibility(true); setVisibility(true);
}, },
@@ -1054,6 +1084,7 @@ export function JobsDetailHeaderActions({
if (!jobRO && job.converted) { if (!jobRO && job.converted) {
menuItems.push({ menuItems.push({
key: "voidjob", key: "voidjob",
id: "job-actions-voidjob",
label: ( label: (
<RbacWrapper action="jobs:void" noauth> <RbacWrapper action="jobs:void" noauth>
<Popconfirm <Popconfirm

View File

@@ -101,7 +101,7 @@ export function PartsOrderListTableComponent({
} else { } else {
const fetchData = async () => { const fetchData = async () => {
const result = await billQuery({ const result = await billQuery({
variables: { billid: returnfrombill }, variables: { billid: returnfrombill }
}); });
setBillData(result.data); setBillData(result.data);
}; };
@@ -203,7 +203,7 @@ export function PartsOrderListTableComponent({
is_credit_memo: record.return, is_credit_memo: record.return,
billlines: record.parts_order_lines.map((pol) => { billlines: record.parts_order_lines.map((pol) => {
return { return {
joblineid: pol.job_line_id, joblineid: pol.job_line_id || "noline",
line_desc: pol.line_desc, line_desc: pol.line_desc,
quantity: pol.quantity, quantity: pol.quantity,

View File

@@ -319,6 +319,18 @@ export default function ShopInfoIntakeChecklistComponent({ form }) {
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item
name={["deliverchecklist", "actual_delivery"]}
label={t("bodyshop.fields.deliver.require_actual_delivery_date")}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<Switch />
</Form.Item>
</SelectorDiv> </SelectorDiv>
</div> </div>
); );

View File

@@ -1,5 +1,5 @@
import { Button, Result, Space, Steps } from "antd";
import { PageHeader } from "@ant-design/pro-layout"; import { PageHeader } from "@ant-design/pro-layout";
import { Button, Result, Space, Steps } from "antd";
import React, { useContext, useState } from "react"; import React, { useContext, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -9,7 +9,6 @@ import JobsCreateJobsInfo from "../../components/jobs-create-jobs-info/jobs-crea
import JobsCreateOwnerInfoContainer from "../../components/jobs-create-owner-info/jobs-create-owner-info.container"; import JobsCreateOwnerInfoContainer from "../../components/jobs-create-owner-info/jobs-create-owner-info.container";
import JobsCreateVehicleInfoContainer from "../../components/jobs-create-vehicle-info/jobs-create-vehicle-info.container"; import JobsCreateVehicleInfoContainer from "../../components/jobs-create-vehicle-info/jobs-create-vehicle-info.container";
import JobCreateContext from "../../pages/jobs-create/jobs-create.context"; import JobCreateContext from "../../pages/jobs-create/jobs-create.context";
import FormsFieldChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
export default function JobsCreateComponent({ form }) { export default function JobsCreateComponent({ form }) {
const [pageIndex, setPageIndex] = useState(0); const [pageIndex, setPageIndex] = useState(0);
@@ -41,10 +40,11 @@ export default function JobsCreateComponent({ form }) {
const next = () => { const next = () => {
setPageIndex(pageIndex + 1); setPageIndex(pageIndex + 1);
console.log("NExt"); console.log("Next");
}; };
const prev = () => { const prev = () => {
setPageIndex(pageIndex - 1); setPageIndex(pageIndex - 1);
console.log("Previous");
}; };
const { Step } = Steps; const { Step } = Steps;
@@ -53,26 +53,26 @@ export default function JobsCreateComponent({ form }) {
<PageHeader <PageHeader
extra={ extra={
<Space wrap> <Space wrap>
{pageIndex > 0 && <Button onClick={() => prev()}>Previous</Button>} {pageIndex > 0 && <Button onClick={() => prev()}>{t("general.actions.previous")}</Button>}
{pageIndex < steps.length - 1 && ( {pageIndex < steps.length - 1 && (
<Button <Button
type="primary" type="primary"
onClick={() => { onClick={() => {
next(); next();
// form form
// .validateFields() .validateFields()
// .then((r) => { .then((r) => {
// if (steps[pageIndex].validation) { if (steps[pageIndex].validation) {
// setErrorMessage(null); setErrorMessage(null);
// next(); next();
// } else { } else {
// setErrorMessage(steps[pageIndex].error); setErrorMessage(steps[pageIndex].error);
// } }
// }) })
// .catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
}} }}
> >
Next {t("general.actions.next")}
</Button> </Button>
)} )}
{pageIndex === steps.length - 1 && ( {pageIndex === steps.length - 1 && (
@@ -104,17 +104,17 @@ export default function JobsCreateComponent({ form }) {
}} }}
onClick={() => { onClick={() => {
setPageIndex(idx); setPageIndex(idx);
// form form
// .validateFields() .validateFields()
// .then((r) => { .then((r) => {
// if (steps[pageIndex].validation) { if (steps[pageIndex].validation) {
// setErrorMessage(null); setErrorMessage(null);
// setPageIndex(idx); setPageIndex(idx);
// } else { } else {
// setErrorMessage(steps[pageIndex].error); setErrorMessage(steps[pageIndex].error);
// } }
// }) })
// .catch((error) => console.log("error", error)); .catch((error) => console.log("error", error));
}} }}
/> />
))} ))}
@@ -144,7 +144,7 @@ export default function JobsCreateComponent({ form }) {
) : ( ) : (
<div> <div>
<ProgressButtons top /> <ProgressButtons top />
<FormsFieldChanged form={form} />
{errorMessage ? ( {errorMessage ? (
<div> <div>
<AlertComponent message={errorMessage} type="error" /> <AlertComponent message={errorMessage} type="error" />

View File

@@ -291,6 +291,7 @@ export function JobsDetailPage({
{ {
key: "general", key: "general",
icon: <Icon component={FaShieldAlt} />, icon: <Icon component={FaShieldAlt} />,
id: "job-details-general",
label: t("menus.jobsdetail.general"), label: t("menus.jobsdetail.general"),
forceRender: true, forceRender: true,
children: <JobsDetailGeneral job={job} form={form} /> children: <JobsDetailGeneral job={job} form={form} />
@@ -298,6 +299,7 @@ export function JobsDetailPage({
{ {
key: "repairdata", key: "repairdata",
icon: <BarsOutlined />, icon: <BarsOutlined />,
id: "job-details-repairdata",
label: t("menus.jobsdetail.repairdata"), label: t("menus.jobsdetail.repairdata"),
forceRender: true, forceRender: true,
children: <JobsLinesContainer job={job} joblines={job.joblines} refetch={refetch} form={form} /> children: <JobsLinesContainer job={job} joblines={job.joblines} refetch={refetch} form={form} />
@@ -305,18 +307,21 @@ export function JobsDetailPage({
{ {
key: "rates", key: "rates",
icon: <DollarCircleOutlined />, icon: <DollarCircleOutlined />,
id: "job-details-rates",
label: t("menus.jobsdetail.rates"), label: t("menus.jobsdetail.rates"),
forceRender: true, forceRender: true,
children: <JobsDetailRates job={job} form={form} /> children: <JobsDetailRates job={job} form={form} />
}, },
{ {
key: "totals", key: "totals",
id: "job-details-totals",
icon: <DollarCircleOutlined />, icon: <DollarCircleOutlined />,
label: t("menus.jobsdetail.totals"), label: t("menus.jobsdetail.totals"),
children: <JobsDetailTotals job={job} refetch={refetch} /> children: <JobsDetailTotals job={job} refetch={refetch} />
}, },
{ {
key: "partssublet", key: "partssublet",
id: "job-details-partssublet",
icon: <ToolFilled />, icon: <ToolFilled />,
label: HasFeatureAccess({ featureName: "bills", bodyshop }) label: HasFeatureAccess({ featureName: "bills", bodyshop })
? t("menus.jobsdetail.partssublet") ? t("menus.jobsdetail.partssublet")
@@ -331,6 +336,7 @@ export function JobsDetailPage({
? [ ? [
{ {
key: "labor", key: "labor",
id: "job-details-labor",
icon: <Icon component={FaHardHat} />, icon: <Icon component={FaHardHat} />,
label: t("menus.jobsdetail.labor"), label: t("menus.jobsdetail.labor"),
children: <JobsDetailLaborContainer job={job} jobId={job.id} /> children: <JobsDetailLaborContainer job={job} jobId={job.id} />
@@ -340,11 +346,13 @@ export function JobsDetailPage({
{ {
key: "lifecycle", key: "lifecycle",
icon: <BarsOutlined />, icon: <BarsOutlined />,
id: "job-details-lifecycle",
label: t("menus.jobsdetail.lifecycle"), label: t("menus.jobsdetail.lifecycle"),
children: <JobLifecycleComponent job={job} statuses={bodyshop.md_ro_statuses} /> children: <JobLifecycleComponent job={job} statuses={bodyshop.md_ro_statuses} />
}, },
{ {
key: "dates", key: "dates",
id: "job-details-dates",
icon: <CalendarFilled />, icon: <CalendarFilled />,
label: t("menus.jobsdetail.dates"), label: t("menus.jobsdetail.dates"),
forceRender: true, forceRender: true,
@@ -358,6 +366,7 @@ export function JobsDetailPage({
? [ ? [
{ {
key: "documents", key: "documents",
id: "job-details-documents",
icon: <FileImageFilled />, icon: <FileImageFilled />,
label: t("jobs.labels.documents"), label: t("jobs.labels.documents"),
children: bodyshop.uselocalmediaserver ? ( children: bodyshop.uselocalmediaserver ? (
@@ -370,6 +379,7 @@ export function JobsDetailPage({
: []), : []),
{ {
key: "notes", key: "notes",
id: "job-details-notes",
icon: <Icon component={FaRegStickyNote} />, icon: <Icon component={FaRegStickyNote} />,
label: t("jobs.labels.notes"), label: t("jobs.labels.notes"),
children: <JobNotesContainer jobId={job.id} /> children: <JobNotesContainer jobId={job.id} />
@@ -377,12 +387,14 @@ export function JobsDetailPage({
{ {
key: "audit", key: "audit",
icon: <HistoryOutlined />, icon: <HistoryOutlined />,
id: "job-details-audit",
label: t("jobs.labels.audit"), label: t("jobs.labels.audit"),
children: <JobAuditTrail jobId={job.id} /> children: <JobAuditTrail jobId={job.id} />
}, },
{ {
key: "tasks", key: "tasks",
icon: <FaTasks />, icon: <FaTasks />,
id: "job-details-tasks",
label: ( label: (
<Space direction="horizontal"> <Space direction="horizontal">
{t("jobs.labels.tasks")} {t("jobs.labels.tasks")}

View File

@@ -295,7 +295,8 @@
"dailypainttarget": "Scoreboard - Daily Paint Target", "dailypainttarget": "Scoreboard - Daily Paint Target",
"default_adjustment_rate": "Default Labor Deduction Adjustment Rate", "default_adjustment_rate": "Default Labor Deduction Adjustment Rate",
"deliver": { "deliver": {
"templates": "Delivery Templates" "templates": "Delivery Templates",
"require_actual_delivery_date": "Require Actual Delivery"
}, },
"dms": { "dms": {
"apcontrol": "AP Control Number", "apcontrol": "AP Control Number",
@@ -646,7 +647,10 @@
"payers": "Payers" "payers": "Payers"
}, },
"cdk_dealerid": "CDK Dealer ID", "cdk_dealerid": "CDK Dealer ID",
"costsmapping": "Costs Mapping",
"dms_allocations": "DMS Allocations",
"pbs_serialnumber": "PBS Serial Number", "pbs_serialnumber": "PBS Serial Number",
"profitsmapping": "Profits Mapping",
"title": "DMS" "title": "DMS"
}, },
"emaillater": "Email Later", "emaillater": "Email Later",
@@ -1139,6 +1143,8 @@
"download": "Download", "download": "Download",
"edit": "Edit", "edit": "Edit",
"login": "Login", "login": "Login",
"next": "Next",
"previous": "Previous",
"print": "Print", "print": "Print",
"refresh": "Refresh", "refresh": "Refresh",
"remove": "Remove", "remove": "Remove",
@@ -2933,6 +2939,8 @@
"purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)", "purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)",
"purchases_by_date_range_detail": "Purchases by Date - Detail", "purchases_by_date_range_detail": "Purchases by Date - Detail",
"purchases_by_date_range_summary": "Purchases by Date - Summary", "purchases_by_date_range_summary": "Purchases by Date - Summary",
"purchases_by_ro_detail_date": "Purchases by RO - Detail",
"purchases_by_ro_summary_date": "Purchases by RO - Summary",
"purchases_by_vendor_detailed_date_range": "Purchases By Vendor - Detailed", "purchases_by_vendor_detailed_date_range": "Purchases By Vendor - Detailed",
"purchases_by_vendor_summary_date_range": "Purchases by Vendor - Summary", "purchases_by_vendor_summary_date_range": "Purchases by Vendor - Summary",
"purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed", "purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed",

View File

@@ -295,7 +295,8 @@
"dailypainttarget": "", "dailypainttarget": "",
"default_adjustment_rate": "", "default_adjustment_rate": "",
"deliver": { "deliver": {
"templates": "" "templates": "",
"require_actual_delivery_date": ""
}, },
"dms": { "dms": {
"apcontrol": "", "apcontrol": "",
@@ -646,7 +647,10 @@
"payers": "" "payers": ""
}, },
"cdk_dealerid": "", "cdk_dealerid": "",
"costsmapping": "",
"dms_allocations": "",
"pbs_serialnumber": "", "pbs_serialnumber": "",
"profitsmapping": "",
"title": "" "title": ""
}, },
"emaillater": "", "emaillater": "",
@@ -1139,6 +1143,8 @@
"download": "", "download": "",
"edit": "Editar", "edit": "Editar",
"login": "", "login": "",
"next": "",
"previous": "",
"print": "", "print": "",
"refresh": "", "refresh": "",
"remove": "", "remove": "",
@@ -2933,6 +2939,8 @@
"purchases_by_cost_center_summary": "", "purchases_by_cost_center_summary": "",
"purchases_by_date_range_detail": "", "purchases_by_date_range_detail": "",
"purchases_by_date_range_summary": "", "purchases_by_date_range_summary": "",
"purchases_by_ro_detail_date": "",
"purchases_by_ro_summary_date": "",
"purchases_by_vendor_detailed_date_range": "", "purchases_by_vendor_detailed_date_range": "",
"purchases_by_vendor_summary_date_range": "", "purchases_by_vendor_summary_date_range": "",
"purchases_grouped_by_vendor_detailed": "", "purchases_grouped_by_vendor_detailed": "",

View File

@@ -295,7 +295,8 @@
"dailypainttarget": "", "dailypainttarget": "",
"default_adjustment_rate": "", "default_adjustment_rate": "",
"deliver": { "deliver": {
"templates": "" "templates": "",
"require_actual_delivery_date": ""
}, },
"dms": { "dms": {
"apcontrol": "", "apcontrol": "",
@@ -646,7 +647,10 @@
"payers": "" "payers": ""
}, },
"cdk_dealerid": "", "cdk_dealerid": "",
"costsmapping": "",
"dms_allocations": "",
"pbs_serialnumber": "", "pbs_serialnumber": "",
"profitsmapping": "",
"title": "" "title": ""
}, },
"emaillater": "", "emaillater": "",
@@ -1139,6 +1143,8 @@
"download": "", "download": "",
"edit": "modifier", "edit": "modifier",
"login": "", "login": "",
"next": "",
"previous": "",
"print": "", "print": "",
"refresh": "", "refresh": "",
"remove": "", "remove": "",
@@ -2933,6 +2939,8 @@
"purchases_by_cost_center_summary": "", "purchases_by_cost_center_summary": "",
"purchases_by_date_range_detail": "", "purchases_by_date_range_detail": "",
"purchases_by_date_range_summary": "", "purchases_by_date_range_summary": "",
"purchases_by_ro_detail_date": "",
"purchases_by_ro_summary_date": "",
"purchases_by_vendor_detailed_date_range": "", "purchases_by_vendor_detailed_date_range": "",
"purchases_by_vendor_summary_date_range": "", "purchases_by_vendor_summary_date_range": "",
"purchases_grouped_by_vendor_detailed": "", "purchases_grouped_by_vendor_detailed": "",

View File

@@ -1081,6 +1081,32 @@ export const TemplateList = (type, context) => {
}, },
group: "purchases" group: "purchases"
}, },
purchases_by_ro_detail_date: {
title: i18n.t("reportcenter.templates.purchases_by_ro_detail_date"),
description: "",
subject: i18n.t("reportcenter.templates.purchases_by_ro_detail_date"),
key: "purchases_by_ro_detail_date",
//idtype: "vendor",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_invoiced")
},
group: "purchases"
},
purchases_by_ro_summary_date: {
title: i18n.t("reportcenter.templates.purchases_by_ro_summary_date"),
description: "",
subject: i18n.t("reportcenter.templates.purchases_by_ro_summary_date"),
key: "purchases_by_ro_summary_date",
//idtype: "vendor",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_invoiced")
},
group: "purchases"
},
job_costing_ro_date_summary: { job_costing_ro_date_summary: {
title: i18n.t("reportcenter.templates.job_costing_ro_date_summary"), title: i18n.t("reportcenter.templates.job_costing_ro_date_summary"),
description: "", description: "",

View File

@@ -1,4 +1,5 @@
export default async function FcmHandler({ client, payload }) { export default async function FcmHandler({ client, payload }) {
console.log("FCM", payload);
switch (payload.type) { switch (payload.type) {
case "messaging-inbound": case "messaging-inbound":
client.cache.modify({ client.cache.modify({

View File

@@ -174,10 +174,7 @@ async function OpenSearchUpdateHandler(req, res) {
const bulkOperation = []; const bulkOperation = [];
slicedArray.forEach((bill) => { slicedArray.forEach((bill) => {
bulkOperation.push({ index: { _index: "bills", _id: bill.id } }); bulkOperation.push({ index: { _index: "bills", _id: bill.id } });
bulkOperation.push({ bulkOperation.push({ ...bill, bodyshopid: bill.job.bodyshopid });
...omit(bill, ["job"]),
bodyshopid: bill.job.bodyshopid
});
}); });
promiseQueue.push(bulkOperation); promiseQueue.push(bulkOperation);
} }

View File

@@ -71,16 +71,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
{ {
local: false, local: false,
federal: InstanceManager({ imex: true, rome: false }), federal: InstanceManager({ imex: true, rome: false }),
state: state: checkStateTax(jobline, jobs_by_pk)
jobs_by_pk.state_tax_rate === 0
? false
: jobline.db_ref === "900511" ||
jobline.db_ref === "900510" ||
(jobline.mod_lb_hrs === 0 && //Extending IO-1375 as a part of IO-2023
jobline.act_price > 0 &&
jobline.lbr_op === "OP14")
? true
: jobline.tax_part
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );
@@ -156,7 +147,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
{ {
local: false, local: false,
federal: InstanceManager({ imex: true, rome: false }), federal: InstanceManager({ imex: true, rome: false }),
state: jobs_by_pk.state_tax_rate === 0 ? false : true state: jobs_by_pk.tax_lbr_rt === 0 ? false : true
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );
@@ -224,7 +215,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
{ {
local: false, local: false,
federal: InstanceManager({ imex: true, rome: false }), federal: InstanceManager({ imex: true, rome: false }),
state: jobs_by_pk.state_tax_rate === 0 ? false : true state: jobs_by_pk.tax_paint_mat_rt === 0 ? false : true
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );
@@ -293,7 +284,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
{ {
local: false, local: false,
federal: InstanceManager({ imex: true, rome: false }), federal: InstanceManager({ imex: true, rome: false }),
state: jobs_by_pk.state_tax_rate === 0 ? false : true state: jobs_by_pk.tax_shop_mat_rt === 0 ? false : true
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );
@@ -379,7 +370,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
{ {
local: false, local: false,
federal: InstanceManager({ imex: true, rome: false }), federal: InstanceManager({ imex: true, rome: false }),
state: jobs_by_pk.state_tax_rate === 0 ? false : true state: jobs_by_pk.tax_tow_rt === 0 ? false : true
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );
@@ -439,7 +430,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
{ {
local: false, local: false,
federal: InstanceManager({ imex: true, rome: false }), federal: InstanceManager({ imex: true, rome: false }),
state: jobs_by_pk.state_tax_rate === 0 ? false : true state: jobs_by_pk.tax_str_rt === 0 ? false : true
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );
@@ -499,7 +490,7 @@ exports.default = function ({ bodyshop, jobs_by_pk, qbo = false, items, taxCodes
{ {
local: false, local: false,
federal: InstanceManager({ imex: true, rome: false }), federal: InstanceManager({ imex: true, rome: false }),
state: jobs_by_pk.state_tax_rate === 0 ? false : true state: jobs_by_pk.tax_lbr_rt === 0 ? false : true
}, },
bodyshop.md_responsibility_centers.sales_tax_codes bodyshop.md_responsibility_centers.sales_tax_codes
); );
@@ -879,6 +870,64 @@ exports.createMultiQbPayerLines = function ({ bodyshop, jobs_by_pk, qbo = false,
return InvoiceLineAdd; return InvoiceLineAdd;
}; };
function checkStateTax(jobline, jobs_by_pk) {
const isPaintOrShopMat = jobline.db_ref === "936008" || jobline.db_ref === "936007";
if (isPaintOrShopMat) {
if (jobline.db_ref === "936008") {
if (jobs_by_pk.tax_paint_mat_rt === 0) {
return false;
} else {
return true;
}
}
if (jobline.db_ref === "936007") {
if (jobs_by_pk.tax_shop_mat_rt === 0) {
return false;
} else {
return true;
}
}
}
const isAdditionalCost =
(jobline.lbr_op === "OP13" ||
(jobline.lbr_op === "OP14" && jobline.act_price > 0 && jobline.mod_lb_hrs === 0) ||
(jobline.db_ref && jobline.db_ref.startsWith("9360")) ||
(jobline.db_ref && jobline.db_ref.startsWith("90051"))) &&
!isPaintOrShopMat;
if (!jobline.part_type && isAdditionalCost) {
if (jobs_by_pk.tax_lbr_rt === 0) {
return false;
} else {
return true;
}
}
if (jobline.tax_part === false) {
return false;
} else {
if (jobline.part_type) {
if (
!jobs_by_pk.parts_tax_rates[`${jobline.part_type.toUpperCase()}`] ||
jobs_by_pk.parts_tax_rates[`${jobline.part_type.toUpperCase()}`].prt_tax_in === false ||
jobs_by_pk.parts_tax_rates[`${jobline.part_type.toUpperCase()}`].prt_tax_rt === 0
) {
return false;
} else {
return true;
}
} else {
if (jobs_by_pk.tax_lbr_rt === 0) {
return false;
} else {
return true;
}
}
}
}
function CheckQBOUSATaxID({ jobline, job, type }) { function CheckQBOUSATaxID({ jobline, job, type }) {
//Replacing this to be all non-taxable items with the refactor of parts tax rates. //Replacing this to be all non-taxable items with the refactor of parts tax rates.
return "NON"; return "NON";

View File

@@ -211,6 +211,8 @@ const CreateRepairOrderTag = (job, errorCallback) => {
} }
const repairCosts = CreateCosts(job); const repairCosts = CreateCosts(job);
const jobline = CreateJobLines(job.joblines);
const timeticket = CreateTimeTickets(job.timetickets);
try { try {
const ret = { const ret = {
@@ -276,8 +278,11 @@ const CreateRepairOrderTag = (job, errorCallback) => {
DateInvoiced: DateInvoiced:
(job.date_invoiced && moment(job.date_invoiced).tz(job.bodyshop.timezone).format(DateFormat)) || "", (job.date_invoiced && moment(job.date_invoiced).tz(job.bodyshop.timezone).format(DateFormat)) || "",
DateExported: DateExported:
(job.date_exported && moment(job.date_exported).tz(job.bodyshop.timezone).format(DateFormat)) || "" (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: { jobline },
TimeTicketDetails: { timeticket },
Sales: { Sales: {
Labour: { Labour: {
Aluminum: Dinero(job.job_totals.rates.laa.total).toFormat(DineroFormat), Aluminum: Dinero(job.job_totals.rates.laa.total).toFormat(DineroFormat),
@@ -625,3 +630,38 @@ const CreateCosts = (job) => {
}, 0) }, 0)
}; };
}; };
const CreateJobLines = (joblines) => {
const repairLines = [];
joblines.forEach((jobline) => {
repairLines.push({
line_description: jobline.line_desc,
oem_part_no: jobline.oem_partno,
alt_part_no: jobline.alt_partno,
op_code_desc: jobline.op_code_desc,
part_type: jobline.part_type,
part_qty: jobline.part_qty,
part_price: jobline.act_price,
labor_type: jobline.mod_lbr_ty,
labor_hours: jobline.mod_lb_hrs
});
});
return repairLines;
};
const CreateTimeTickets = (timetickets) => {
const timeTickets = [];
timetickets.forEach((ticket) => {
timeTickets.push({
date: ticket.date,
employee: ticket.employee.employee_number
.trim()
.concat(" - ", ticket.employee.first_name.trim(), " ", ticket.employee.last_name.trim())
.trim(),
productive_hrs: ticket.productivehrs,
actual_hrs: ticket.actualhrs,
cost_center: ticket.cost_center
});
});
return timeTickets;
};

View File

@@ -206,8 +206,13 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
adjustment_bottom_line adjustment_bottom_line
state_tax_rate state_tax_rate
qb_multiple_payers qb_multiple_payers
parts_tax_rates
tax_paint_mat_rt tax_paint_mat_rt
tax_lbr_rt tax_lbr_rt
tax_shop_mat_rt
tax_sub_rt
tax_tow_rt
tax_str_rt
owner { owner {
accountingid accountingid
} }
@@ -1108,7 +1113,7 @@ exports.KAIZEN_QUERY = `query KAIZEN_EXPORT($start: timestamptz, $bodyshopid: uu
use_paint_scale_data use_paint_scale_data
timezone timezone
} }
jobs(where: {_and: [{updated_at: {_gt: $start}}, {updated_at: {_lte: $end}}, {shopid: {_eq: $bodyshopid}}]}) { jobs(where: {_and: [{updated_at: {_gt: $start}}, {updated_at: {_lte: $end}}, {converted: {_eq: true}}, {shopid: {_eq: $bodyshopid}}]}) {
actual_completion actual_completion
actual_delivery actual_delivery
actual_in actual_in
@@ -1133,6 +1138,7 @@ exports.KAIZEN_QUERY = `query KAIZEN_EXPORT($start: timestamptz, $bodyshopid: uu
date_invoiced date_invoiced
date_open date_open
date_repairstarted date_repairstarted
date_void
employee_body_rel { employee_body_rel {
first_name first_name
last_name last_name
@@ -1163,6 +1169,7 @@ exports.KAIZEN_QUERY = `query KAIZEN_EXPORT($start: timestamptz, $bodyshopid: uu
ins_co_nm ins_co_nm
joblines(where: {removed: {_eq: false}}) { joblines(where: {removed: {_eq: false}}) {
act_price act_price
alt_partno
billlines(order_by: {bill: {date: desc_nulls_last}} limit: 1) { billlines(order_by: {bill: {date: desc_nulls_last}} limit: 1) {
actual_cost actual_cost
actual_price actual_price
@@ -1183,6 +1190,8 @@ exports.KAIZEN_QUERY = `query KAIZEN_EXPORT($start: timestamptz, $bodyshopid: uu
line_no line_no
mod_lb_hrs mod_lb_hrs
mod_lbr_ty mod_lbr_ty
oem_partno
op_code_desc
parts_order_lines(order_by: {parts_order: {order_date: desc_nulls_last}} limit: 1){ parts_order_lines(order_by: {parts_order: {order_date: desc_nulls_last}} limit: 1){
parts_order{ parts_order{
id id
@@ -1195,7 +1204,6 @@ exports.KAIZEN_QUERY = `query KAIZEN_EXPORT($start: timestamptz, $bodyshopid: uu
profitcenter_labor profitcenter_labor
prt_dsmk_m prt_dsmk_m
prt_dsmk_p prt_dsmk_p
oem_partno
status status
} }
job_totals job_totals
@@ -1246,12 +1254,18 @@ exports.KAIZEN_QUERY = `query KAIZEN_EXPORT($start: timestamptz, $bodyshopid: uu
scheduled_in scheduled_in
status status
timetickets { timetickets {
id
rate
cost_center
actualhrs actualhrs
productivehrs cost_center
date
employee {
employee_number
first_name
last_name
}
flat_rate flat_rate
id
productivehrs
rate
} }
tlos_ind tlos_ind
v_color v_color
@@ -1534,6 +1548,7 @@ exports.QUERY_JOB_COSTING_DETAILS = ` query QUERY_JOB_COSTING_DETAILS($id: uuid!
op_code_desc op_code_desc
profitcenter_part profitcenter_part
profitcenter_labor profitcenter_labor
act_price_before_ppc
} }
bills { bills {
id id
@@ -2475,7 +2490,6 @@ query QUERY_TASK_BY_ID($id: uuid!) {
`; `;
exports.GET_JOBS_BY_PKS = `query GET_JOBS_BY_PKS($ids: [uuid!]!) { exports.GET_JOBS_BY_PKS = `query GET_JOBS_BY_PKS($ids: [uuid!]!) {
jobs(where: {id: {_in: $ids}}) { jobs(where: {id: {_in: $ids}}) {
id id

View File

@@ -6,6 +6,7 @@ const qs = require("query-string");
const axios = require("axios"); const axios = require("axios");
const moment = require("moment"); const moment = require("moment");
const logger = require("../utils/logger"); const logger = require("../utils/logger");
const InstanceManager = require("../utils/instanceMgr").default;
require("dotenv").config({ require("dotenv").config({
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`) path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
@@ -16,7 +17,10 @@ const domain = process.env.NODE_ENV ? "secure" : "test";
const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager"); const { SecretsManagerClient, GetSecretValueCommand } = require("@aws-sdk/client-secrets-manager");
const client = new SecretsManagerClient({ const client = new SecretsManagerClient({
region: "ca-central-1" //TODO-AIO: instance manager required when merged to master-AIO region: InstanceManager({
imex: "ca-central-1",
rome: "us-east-2"
})
}); });
const gqlClient = require("../graphql-client/graphql-client").client; const gqlClient = require("../graphql-client/graphql-client").client;
@@ -145,19 +149,19 @@ exports.generate_payment_url = async (req, res) => {
}; };
exports.postback = async (req, res) => { exports.postback = async (req, res) => {
logger.log("intellipay-postback", "DEBUG", req.user?.email, null, req.body);
const { body: values } = req;
const comment = Buffer.from(values?.comment, "base64").toString();
if ((!values.invoice || values.invoice === "") && !comment) {
//invoice is specified through the pay link. Comment by IO.
logger.log("intellipay-postback-ignored", "DEBUG", req.user?.email, null, req.body);
res.sendStatus(200);
return;
}
try { try {
logger.log("intellipay-postback", "DEBUG", req.user?.email, null, req.body);
const { body: values } = req;
const comment = Buffer.from(values?.comment, "base64").toString();
if ((!values.invoice || values.invoice === "") && !comment) {
//invoice is specified through the pay link. Comment by IO.
logger.log("intellipay-postback-ignored", "DEBUG", req.user?.email, null, req.body);
res.sendStatus(200);
return;
}
if (values.invoice) { if (values.invoice) {
//This is a link email that's been sent out. //This is a link email that's been sent out.
const job = await gqlClient.request(queries.GET_JOB_BY_PK, { const job = await gqlClient.request(queries.GET_JOB_BY_PK, {

View File

@@ -269,7 +269,7 @@ function GenerateCostingData(job) {
job && job &&
job.joblines.reduce( job.joblines.reduce(
(acc, val) => { (acc, val) => {
//Parts Lines //Shop or Paint Material Flags
if (val.db_ref === "936008") { if (val.db_ref === "936008") {
//If either of these DB REFs change, they also need to change in job-totals/job-costing calculations. //If either of these DB REFs change, they also need to change in job-totals/job-costing calculations.
hasMapaLine = true; hasMapaLine = true;
@@ -277,6 +277,8 @@ function GenerateCostingData(job) {
if (val.db_ref === "936007") { if (val.db_ref === "936007") {
hasMashLine = true; hasMashLine = true;
} }
//Labor Profit Center
if (val.mod_lbr_ty) { if (val.mod_lbr_ty) {
const laborProfitCenter = val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "Unknown"; const laborProfitCenter = val.profitcenter_labor || defaultProfits[val.mod_lbr_ty] || "Unknown";
@@ -307,6 +309,7 @@ function GenerateCostingData(job) {
} }
} }
// Part Profit Center
if (val.part_type && val.part_type !== "PAE" && val.part_type !== "PAS" && val.part_type !== "PASL") { if (val.part_type && val.part_type !== "PAE" && val.part_type !== "PAS" && val.part_type !== "PASL") {
const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown";
@@ -315,7 +318,9 @@ function GenerateCostingData(job) {
if (!partsProfitCenter) if (!partsProfitCenter)
console.log("Unknown cost/profit center mapping for parts.", val.line_desc, val.part_type); console.log("Unknown cost/profit center mapping for parts.", val.line_desc, val.part_type);
const partsAmount = Dinero({ const partsAmount = Dinero({
amount: Math.round((val.act_price || 0) * 100) amount: val.act_price_before_ppc
? Math.round(val.act_price_before_ppc * 100)
: Math.round(val.act_price * 100)
}) })
.multiply(val.part_qty || 1) .multiply(val.part_qty || 1)
.add( .add(
@@ -324,7 +329,9 @@ function GenerateCostingData(job) {
? val.prt_dsmk_m ? val.prt_dsmk_m
? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) }) ? Dinero({ amount: Math.round(val.prt_dsmk_m * 100) })
: Dinero({ : Dinero({
amount: Math.round(val.act_price * 100) amount: val.act_price_before_ppc
? Math.round(val.act_price_before_ppc * 100)
: Math.round(val.act_price * 100)
}) })
.multiply(val.part_qty || 0) .multiply(val.part_qty || 0)
.percentage(Math.abs(val.prt_dsmk_p || 0)) .percentage(Math.abs(val.prt_dsmk_p || 0))
@@ -334,6 +341,8 @@ function GenerateCostingData(job) {
if (!acc.parts[partsProfitCenter]) acc.parts[partsProfitCenter] = Dinero(); if (!acc.parts[partsProfitCenter]) acc.parts[partsProfitCenter] = Dinero();
acc.parts[partsProfitCenter] = acc.parts[partsProfitCenter].add(partsAmount); acc.parts[partsProfitCenter] = acc.parts[partsProfitCenter].add(partsAmount);
} }
//Sublet Profit Center
if (val.part_type && val.part_type !== "PAE" && (val.part_type === "PAS" || val.part_type === "PASL")) { if (val.part_type && val.part_type !== "PAE" && (val.part_type === "PAS" || val.part_type === "PASL")) {
const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown"; const partsProfitCenter = val.profitcenter_part || defaultProfits[val.part_type] || "Unknown";
@@ -362,8 +371,11 @@ function GenerateCostingData(job) {
acc.sublet[partsProfitCenter] = acc.sublet[partsProfitCenter].add(partsAmount); acc.sublet[partsProfitCenter] = acc.sublet[partsProfitCenter].add(partsAmount);
} }
//To deal with additional costs. //Additional Profit Center
if (!val.part_type && !val.mod_lbr_ty) { if (
(!val.part_type && !val.mod_lbr_ty) ||
(!val.part_type && val.mod_lbr_ty && val.act_price > 0 && val.lbr_op !== "OP14")
) {
//Does it already have a defined profit center? //Does it already have a defined profit center?
//If so, use it, otherwise try to use the same from the auto-allocate logic in IO app jobs-close-auto-allocate. //If so, use it, otherwise try to use the same from the auto-allocate logic in IO app jobs-close-auto-allocate.
const partsProfitCenter = val.profitcenter_part || getAdditionalCostCenter(val, defaultProfits) || "Unknown"; const partsProfitCenter = val.profitcenter_part || getAdditionalCostCenter(val, defaultProfits) || "Unknown";

View File

@@ -643,7 +643,7 @@ function CalculateAdditional(job) {
additionalCosts: null, additionalCosts: null,
additionalCostItems: [], additionalCostItems: [],
adjustments: null, adjustments: null,
towing: null, towing: Dinero(),
shipping: Dinero(), shipping: Dinero(),
storage: null, storage: null,
pvrt: null, pvrt: null,
@@ -668,7 +668,7 @@ function CalculateAdditional(job) {
} }
if (val.line_desc.toLowerCase().includes("towing")) { if (val.line_desc.toLowerCase().includes("towing")) {
ret.towing = lineValue; ret.towing = ret.towing.add(lineValue);
return acc; return acc;
} else { } else {
ret.additionalCostItems.push({ key: val.line_desc, total: lineValue }); ret.additionalCostItems.push({ key: val.line_desc, total: lineValue });
@@ -909,6 +909,25 @@ function CalculateTaxesTotals(job, otherTotals) {
} }
}); });
if (job.adjustment_bottom_line) {
const subtotal_before_adjustment = subtotal.add(Dinero({ amount: Math.round(job.adjustment_bottom_line * -100) }));
const percent_of_adjustment =
Math.round(
subtotal_before_adjustment.toUnit() /
(job.adjustment_bottom_line > 0 ? job.adjustment_bottom_line : job.adjustment_bottom_line * -1)
) / 100;
Object.keys(taxableAmountsByTier).forEach((taxTierKey) => {
taxable_adjustment = taxableAmountsByTier[taxTierKey].multiply(percent_of_adjustment);
console.log("🚀 ~ taxableAmountsByTier ~ taxable_adjustment:", taxable_adjustment);
if (job.adjustment_bottom_line > 0) {
taxableAmountsByTier[taxTierKey] = taxableAmountsByTier[taxTierKey].add(taxable_adjustment);
} else {
taxableAmountsByTier[taxTierKey] = taxableAmountsByTier[taxTierKey].subtract(taxable_adjustment);
}
});
}
const remainingTaxableAmounts = taxableAmountsByTier; const remainingTaxableAmounts = taxableAmountsByTier;
console.log("*** Taxable Amounts by Tier***"); console.log("*** Taxable Amounts by Tier***");
console.table(JSON.parse(JSON.stringify(taxableAmountsByTier))); console.table(JSON.parse(JSON.stringify(taxableAmountsByTier)));

View File

@@ -489,7 +489,7 @@ function CalculateAdditional(job) {
additionalCosts: null, additionalCosts: null,
additionalCostItems: [], additionalCostItems: [],
adjustments: null, adjustments: null,
towing: null, towing: Dinero(),
shipping: Dinero(), shipping: Dinero(),
storage: null, storage: null,
pvrt: null, pvrt: null,
@@ -512,7 +512,7 @@ function CalculateAdditional(job) {
} }
if (val.line_desc.toLowerCase().includes("towing")) { if (val.line_desc.toLowerCase().includes("towing")) {
ret.towing = lineValue; ret.towing = ret.towing.add(lineValue);
return acc; return acc;
} else { } else {
ret.additionalCostItems.push({ key: val.line_desc, total: lineValue }); ret.additionalCostItems.push({ key: val.line_desc, total: lineValue });