Compare commits

...

49 Commits

Author SHA1 Message Date
Allan Carr
98bff6d8f6 IO-2824 Dev Server Instance Switch
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2024-06-20 10:56:07 -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
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
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
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
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
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
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
19 changed files with 260 additions and 96 deletions

View File

@@ -1,7 +1,8 @@
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
VITE_APP_GA_CODE=231099835 VITE_APP_GA_CODE=231099835
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"} # VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
VITE_APP_FIREBASE_CONFIG={"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"}
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
VITE_APP_CLOUDINARY_API_KEY=957865933348715 VITE_APP_CLOUDINARY_API_KEY=957865933348715

View File

@@ -1,7 +1,8 @@
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
VITE_APP_GA_CODE=231099835 VITE_APP_GA_CODE=231099835
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"} # VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
VITE_APP_FIREBASE_CONFIG={"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"}
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
VITE_APP_CLOUDINARY_API_KEY=957865933348715 VITE_APP_CLOUDINARY_API_KEY=957865933348715

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

@@ -25,31 +25,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 +56,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,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

@@ -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

@@ -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

@@ -12,6 +12,9 @@
"admin": "cd admin && npm start", "admin": "cd admin && npm start",
"client": "cd client && npm start", "client": "cd client && npm start",
"server": "nodemon server.js", "server": "nodemon server.js",
"server:imex": "nodemon server.js imex",
"server:rome": "nodemon server.js rome",
"server:promanager": "nodemon server.js promanager",
"build": "cd client && npm run build", "build": "cd client && npm run build",
"dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\"", "dev": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\"",
"deva": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\" \"npm run admin\"", "deva": "concurrently --kill-others-on-fail \"npm run server\" \"npm run client\" \"npm run admin\"",

View File

@@ -8,9 +8,11 @@ const cookieParser = require("cookie-parser");
const http = require("http"); const http = require("http");
const { Server } = require("socket.io"); const { Server } = require("socket.io");
const instanceName = process.argv[2];
// Load environment variables // Load environment variables
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"}${instanceName ? `.${instanceName}` : ''}`)
}); });
// Import custom utilities and handlers // Import custom utilities and handlers

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,66 @@ 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.db_ref && jobline.db_ref.startsWith("9360"))) && !isPaintOrShopMat;
if (!jobline.part_type && isAdditionalCost) {
if (jobs_by_pk.tax_lbr_rt === 0) {
return false;
} else {
return true;
}
}
if (
jobline.db_ref === "900511" ||
jobline.db_ref === "900510" ||
(jobline.mod_lb_hrs === 0 && jobline.act_price > 0 && jobline.lbr_op === "OP14")
)
return true; //Extending IO-1375 as a part of IO-2023
if (jobline.tax_part === false) {
return false;
} else {
if (jobline.part_type) {
if (
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

@@ -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
} }
@@ -1534,6 +1539,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

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,7 @@ 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 +327,7 @@ 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 +337,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 +367,8 @@ 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)) {
//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";