Compare commits
47 Commits
release/20
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ef18cf0718 | ||
|
|
e98f9763fd | ||
|
|
46abf01366 | ||
|
|
45ab7543d5 | ||
|
|
fed16efd10 | ||
|
|
49bf461c36 | ||
|
|
696781c857 | ||
|
|
5540872f62 | ||
|
|
69690f0184 | ||
|
|
f11a4c93ac | ||
|
|
9eed33b5f2 | ||
|
|
55b7715e1c | ||
|
|
c129b5ba8c | ||
|
|
efc2844d99 | ||
|
|
ab38f85d38 | ||
|
|
81eccba393 | ||
|
|
b3b49fd4ca | ||
|
|
b7a08db4e7 | ||
|
|
2d63c3d576 | ||
|
|
5f4a2392af | ||
|
|
f6fe8be7c4 | ||
|
|
89af6d23e8 | ||
|
|
7e1431d65e | ||
|
|
d50e845ba0 | ||
|
|
6796c35e5b | ||
|
|
4a68a10005 | ||
|
|
17088b3025 | ||
|
|
4e3c659b6d | ||
|
|
6afcf82cc4 | ||
|
|
f4ddb40bde | ||
|
|
6017e2172e | ||
|
|
bef9e64bf8 | ||
|
|
e8d95bdb68 | ||
|
|
10fb7d9d96 | ||
|
|
2ec196e664 | ||
|
|
1f38b98bfd | ||
|
|
a7c76386bc | ||
|
|
042b67c531 | ||
|
|
2e72ed3698 | ||
|
|
bc01f46388 | ||
|
|
84c7fdba5a | ||
|
|
8f58f09c8c | ||
|
|
d8296e1d01 | ||
|
|
fa1fffd8b9 | ||
|
|
ff53355b4a | ||
|
|
9e3a2e920d | ||
|
|
e7157119ae |
@@ -8103,6 +8103,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>filehandlers</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>insurancecos</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -8664,6 +8685,27 @@
|
||||
<folder_node>
|
||||
<name>validation</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>centermustexist</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>larsplit</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -17491,6 +17533,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>changefilehandler</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>changelaborrate</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -19737,6 +19800,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>date_next_contact</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>date_open</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -29272,6 +29356,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>noattachedjobs</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
@@ -29424,6 +29529,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>recentonly</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>selectmedia</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -30627,6 +30753,27 @@
|
||||
<folder_node>
|
||||
<name>errors</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>associatedbills</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>backordering</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -32874,6 +33021,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>ab_proof_of_loss</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>appointment_confirmation</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -33231,6 +33399,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>individual_job_note</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>invoice_customer_payable</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34050,6 +34239,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>worksheet_sorted_by_operation_type</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
@@ -34662,6 +34872,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>settings</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
@@ -34730,6 +34961,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>ats</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>bodyhours</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34772,6 +35024,69 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>cardsettings</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>clm_no</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>compact</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>detailpriority</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34793,6 +35108,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>employeeassignments</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>employeesearch</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34814,6 +35150,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>ins_co_nm</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>jobdetail</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34835,6 +35192,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>laborhrs</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>note</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34856,6 +35234,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>ownr_nm</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>paintpriority</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34877,6 +35276,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>production_note</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>refinishhours</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34898,6 +35318,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>scheduled_completion</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>selectview</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -36465,6 +36906,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>open_orders_status</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>parts_backorder</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
|
||||
@@ -2,74 +2,74 @@
|
||||
"name": "bodyshop",
|
||||
"version": "0.1.1",
|
||||
"private": true,
|
||||
"proxy": "http://localhost:5000",
|
||||
"proxy": "http://localhost:4000",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.4.16",
|
||||
"@apollo/client": "^3.4.17",
|
||||
"@asseinfo/react-kanban": "^2.2.0",
|
||||
"@craco/craco": "^6.4.0",
|
||||
"@fingerprintjs/fingerprintjs": "^3.3.0",
|
||||
"@lourenci/react-kanban": "^2.1.0",
|
||||
"@openreplay/tracker": "^3.4.4",
|
||||
"@openreplay/tracker": "^3.4.7",
|
||||
"@openreplay/tracker-assist": "^3.4.4",
|
||||
"@openreplay/tracker-graphql": "^3.0.0",
|
||||
"@openreplay/tracker-redux": "^3.0.0",
|
||||
"@sentry/react": "^6.13.3",
|
||||
"@sentry/tracing": "^6.13.3",
|
||||
"@sentry/react": "^6.14.3",
|
||||
"@sentry/tracing": "^6.14.3",
|
||||
"@splitsoftware/splitio-react": "^1.3.0",
|
||||
"@stripe/react-stripe-js": "^1.6.0",
|
||||
"@stripe/stripe-js": "^1.20.2",
|
||||
"@tanem/react-nprogress": "^3.0.81",
|
||||
"@stripe/stripe-js": "^1.21.1",
|
||||
"@tanem/react-nprogress": "^3.0.82",
|
||||
"antd": "^4.16.13",
|
||||
"apollo-link-logger": "^2.0.0",
|
||||
"axios": "^0.23.0",
|
||||
"axios": "^0.24.0",
|
||||
"craco-less": "^1.20.0",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^10.0.0",
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^9.1.3",
|
||||
"graphql": "^15.6.1",
|
||||
"i18next": "^21.3.3",
|
||||
"firebase": "^9.4.1",
|
||||
"graphql": "^16.0.1",
|
||||
"i18next": "^21.4.2",
|
||||
"i18next-browser-languagedetector": "^6.1.2",
|
||||
"jsoneditor": "^9.5.6",
|
||||
"jsoneditor": "^9.5.7",
|
||||
"jsreport-browser-client-dist": "^1.3.0",
|
||||
"libphonenumber-js": "^1.9.38",
|
||||
"libphonenumber-js": "^1.9.42",
|
||||
"logrocket": "^2.1.1",
|
||||
"markerjs2": "^2.15.0",
|
||||
"markerjs2": "^2.17.0",
|
||||
"moment-business-days": "^1.2.0",
|
||||
"phone": "^3.1.8",
|
||||
"phone": "^3.1.9",
|
||||
"preval.macro": "^5.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"query-string": "^7.0.1",
|
||||
"rc-queue-anim": "^2.0.0",
|
||||
"rc-scroll-anim": "^2.7.6",
|
||||
"react": "^17.0.1",
|
||||
"react-big-calendar": "^0.38.0",
|
||||
"react-big-calendar": "^0.38.1",
|
||||
"react-color": "^2.19.3",
|
||||
"react-cookie": "^4.1.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-drag-listview": "^0.1.8",
|
||||
"react-grid-gallery": "^0.5.5",
|
||||
"react-grid-layout": "^1.3.0",
|
||||
"react-i18next": "^11.12.0",
|
||||
"react-i18next": "^11.14.2",
|
||||
"react-icons": "^4.3.1",
|
||||
"react-number-format": "^4.7.3",
|
||||
"react-redux": "^7.2.5",
|
||||
"react-number-format": "^4.8.0",
|
||||
"react-redux": "^7.2.6",
|
||||
"react-resizable": "^3.0.4",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-scripts": "^4.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"recharts": "^2.1.5",
|
||||
"redux": "^4.1.1",
|
||||
"recharts": "^2.1.6",
|
||||
"redux": "^4.1.2",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.1.3",
|
||||
"redux-state-sync": "^3.1.2",
|
||||
"reselect": "^4.0.0",
|
||||
"sass": "^1.43.3",
|
||||
"reselect": "^4.1.2",
|
||||
"sass": "^1.43.4",
|
||||
"socket.io-client": "^4.3.2",
|
||||
"styled-components": "^5.3.3",
|
||||
"subscriptions-transport-ws": "^0.9.18",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"web-vitals": "^2.1.2",
|
||||
"workbox-background-sync": "^6.3.0",
|
||||
"workbox-broadcast-update": "^6.3.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ShrinkOutlined } from "@ant-design/icons";
|
||||
import { Col, Row, Typography } from "antd";
|
||||
import { ShrinkOutlined, InfoCircleOutlined } from "@ant-design/icons";
|
||||
import { Col, Row, Tooltip, Typography } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -31,6 +31,9 @@ export function ChatPopupComponent({
|
||||
{t("messaging.labels.messaging")}
|
||||
</Typography.Title>
|
||||
<ChatNewConversation />
|
||||
<Tooltip title={t("messaging.labels.recentonly")}>
|
||||
<InfoCircleOutlined />
|
||||
</Tooltip>
|
||||
</div>
|
||||
<ShrinkOutlined
|
||||
onClick={() => toggleChatVisible()}
|
||||
|
||||
@@ -42,7 +42,6 @@ export default function ContractFormComponent({
|
||||
<ContractStatusSelector />
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
<Form.Item
|
||||
label={t("contracts.fields.start")}
|
||||
name="start"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Table, Col , Checkbox} from "antd";
|
||||
import { Button, Table, Col, Checkbox } from "antd";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -23,15 +23,26 @@ export function DmsCustomerSelector({ bodyshop }) {
|
||||
const [customerList, setcustomerList] = useState([]);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [selectedCustomer, setSelectedCustomer] = useState(null);
|
||||
const [dmsType, setDmsType] = useState("cdk");
|
||||
|
||||
socket.on("cdk-select-customer", (customerList, callback) => {
|
||||
setVisible(true);
|
||||
setDmsType("cdk");
|
||||
setcustomerList(customerList);
|
||||
});
|
||||
socket.on("pbs-select-customer", (customerList, callback) => {
|
||||
setVisible(true);
|
||||
setDmsType("pbs");
|
||||
setcustomerList(customerList);
|
||||
console.log(
|
||||
"🚀 ~ file: dms-customer-selector.component.jsx ~ line 37 ~ socket.on ~ customerList",
|
||||
customerList
|
||||
);
|
||||
});
|
||||
|
||||
const onUseSelected = () => {
|
||||
setVisible(false);
|
||||
socket.emit("cdk-selected-customer", selectedCustomer);
|
||||
socket.emit(`${dmsType}-selected-customer`, selectedCustomer);
|
||||
setSelectedCustomer(null);
|
||||
};
|
||||
|
||||
@@ -50,7 +61,7 @@ export function DmsCustomerSelector({ bodyshop }) {
|
||||
setSelectedCustomer(null);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
const cdkColumns = [
|
||||
{
|
||||
title: t("jobs.fields.dms.id"),
|
||||
dataIndex: ["id", "value"],
|
||||
@@ -60,13 +71,14 @@ export function DmsCustomerSelector({ bodyshop }) {
|
||||
title: t("jobs.fields.dms.vinowner"),
|
||||
dataIndex: "vinOwner",
|
||||
key: "vinOwner",
|
||||
render: (text, record) => <Checkbox disabled checked={record.vinOwner}/>
|
||||
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.dms.name1"),
|
||||
dataIndex: ["name1", "fullName"],
|
||||
key: "name1",
|
||||
sorter: (a, b) => alphaSort(a.name1?.fullName, b.name1?.fullName),
|
||||
sorter: (a, b) =>
|
||||
alphaSort(a.name1 && a.name1.fullName, b.name1 && b.name1.fullName),
|
||||
},
|
||||
|
||||
{
|
||||
@@ -74,11 +86,43 @@ export function DmsCustomerSelector({ bodyshop }) {
|
||||
//dataIndex: ["name2", "fullName"],
|
||||
key: "address",
|
||||
render: (record, value) =>
|
||||
`${record?.address?.addressLine[0]}, ${record.address?.city} ${record.address?.stateOrProvince} ${record.address?.postalCode}`,
|
||||
`${record.address && record.address.addressLine[0]}, ${
|
||||
record.address && record.address.city
|
||||
} ${record.address && record.address.stateOrProvince} ${
|
||||
record.address && record.address.postalCode
|
||||
}`,
|
||||
},
|
||||
];
|
||||
|
||||
if (!visible) return <></>;
|
||||
const pbsColumns = [
|
||||
{
|
||||
title: t("jobs.fields.dms.id"),
|
||||
dataIndex: "ContactId",
|
||||
key: "ContactId",
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.dms.vinowner"),
|
||||
dataIndex: "vinOwner",
|
||||
key: "vinOwner",
|
||||
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.dms.name1"),
|
||||
key: "name1",
|
||||
sorter: (a, b) => alphaSort(a.LastName, b.LastName),
|
||||
render: (text, record) =>
|
||||
`${record.FirstName || ""} ${record.LastName || ""}`,
|
||||
},
|
||||
|
||||
{
|
||||
title: t("jobs.fields.dms.address"),
|
||||
key: "address",
|
||||
render: (record, value) =>
|
||||
`${record.Address}, ${record.City} ${record.State} ${record.ZipCode}`,
|
||||
},
|
||||
];
|
||||
|
||||
if (!visible) return null;
|
||||
return (
|
||||
<Col span={24}>
|
||||
<Table
|
||||
@@ -104,13 +148,17 @@ export function DmsCustomerSelector({ bodyshop }) {
|
||||
</div>
|
||||
)}
|
||||
pagination={{ position: "top" }}
|
||||
columns={columns}
|
||||
rowKey={(record) => record.id.value}
|
||||
columns={dmsType === "cdk" ? cdkColumns : pbsColumns}
|
||||
rowKey={(record) =>
|
||||
dmsType === "cdk" ? record.id.value : record.ContactId
|
||||
}
|
||||
dataSource={customerList}
|
||||
//onChange={handleTableChange}
|
||||
rowSelection={{
|
||||
onSelect: (props) => {
|
||||
setSelectedCustomer(props.id.value);
|
||||
onSelect: (record) => {
|
||||
setSelectedCustomer(
|
||||
dmsType === "cdk" ? record.id.value : record.ContactId
|
||||
);
|
||||
},
|
||||
type: "radio",
|
||||
selectedRowKeys: [selectedCustomer],
|
||||
|
||||
@@ -119,33 +119,35 @@ export function DmsPostForm({ bodyshop, socket, job }) {
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
|
||||
<LayoutFormRow style={{ justifyContent: "center" }} grow>
|
||||
<Form.Item
|
||||
name="dms_make"
|
||||
label={t("jobs.fields.dms.dms_make")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input disabled />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="dms_model"
|
||||
label={t("jobs.fields.dms.dms_model")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input disabled />
|
||||
</Form.Item>
|
||||
{bodyshop.cdk_dealerid && (
|
||||
<LayoutFormRow style={{ justifyContent: "center" }} grow>
|
||||
<Form.Item
|
||||
name="dms_make"
|
||||
label={t("jobs.fields.dms.dms_make")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input disabled />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="dms_model"
|
||||
label={t("jobs.fields.dms.dms_model")}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input disabled />
|
||||
</Form.Item>
|
||||
|
||||
<DmsCdkMakes form={form} socket={socket} job={job} />
|
||||
<DmsCdkMakesRefetch />
|
||||
</LayoutFormRow>
|
||||
<DmsCdkMakes form={form} socket={socket} job={job} />
|
||||
<DmsCdkMakesRefetch />
|
||||
</LayoutFormRow>
|
||||
)}
|
||||
<Form.Item
|
||||
name="story"
|
||||
label={t("jobs.fields.dms.story")}
|
||||
@@ -157,6 +159,7 @@ export function DmsPostForm({ bodyshop, socket, job }) {
|
||||
>
|
||||
<Input.TextArea maxLength={240} />
|
||||
</Form.Item>
|
||||
|
||||
<Divider />
|
||||
<Form.List name={["payers"]}>
|
||||
{(fields, { add, remove }) => {
|
||||
|
||||
@@ -1,15 +1,71 @@
|
||||
import { UploadOutlined } from "@ant-design/icons";
|
||||
import { Divider, Form, Input, Select, Tabs, Upload } from "antd";
|
||||
import { UploadOutlined, UserAddOutlined } from "@ant-design/icons";
|
||||
import {
|
||||
Divider,
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
Tabs,
|
||||
Upload,
|
||||
Space,
|
||||
Menu,
|
||||
Dropdown,
|
||||
} from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import EmailDocumentsComponent from "../email-documents/email-documents.component";
|
||||
import _ from "lodash";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(EmailOverlayComponent);
|
||||
|
||||
export default function EmailOverlayComponent({ form, selectedMediaState }) {
|
||||
export function EmailOverlayComponent({ form, selectedMediaState, bodyshop }) {
|
||||
const { t } = useTranslation();
|
||||
const handleClick = ({ item, key, keyPath }) => {
|
||||
const email = item.props.value;
|
||||
form.setFieldsValue({ to: _.uniq([...form.getFieldValue("to"), email]) });
|
||||
};
|
||||
|
||||
const menu = (
|
||||
<div>
|
||||
<Menu onClick={handleClick}>
|
||||
{bodyshop.employees
|
||||
.filter((e) => e.user_email)
|
||||
.map((e, idx) => (
|
||||
<Menu.Item value={e.user_email} key={idx}>
|
||||
{`${e.first_name} ${e.last_name}`}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form.Item
|
||||
label={t("emails.fields.to")}
|
||||
label={
|
||||
<Space>
|
||||
{t("emails.fields.to")}
|
||||
<Dropdown overlay={menu}>
|
||||
<a
|
||||
className="ant-dropdown-link"
|
||||
href=" #"
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>
|
||||
<UserAddOutlined />
|
||||
</a>
|
||||
</Dropdown>
|
||||
</Space>
|
||||
}
|
||||
name="to"
|
||||
rules={[
|
||||
{
|
||||
|
||||
@@ -7,10 +7,12 @@ import { selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import moment from "moment";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
|
||||
});
|
||||
@@ -24,9 +26,20 @@ export function EmailTestComponent({ currentUser, setEmailOptions }) {
|
||||
{
|
||||
name: values.key,
|
||||
variables: {
|
||||
...(values.start
|
||||
? {
|
||||
start: moment(values.start).startOf("day").format("YYYY-MM-DD"),
|
||||
}
|
||||
: {}),
|
||||
...(values.end
|
||||
? { end: moment(values.end).endOf("day").format("YYYY-MM-DD") }
|
||||
: {}),
|
||||
...(values.start
|
||||
? { starttz: moment(values.start).startOf("day") }
|
||||
: {}),
|
||||
...(values.end ? { endtz: moment(values.end).endOf("day") } : {}),
|
||||
|
||||
...(values.id ? { id: values.id } : {}),
|
||||
...(values.start ? { start: values.start } : {}),
|
||||
...(values.end ? { end: values.end } : {}),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -46,12 +46,16 @@ import {
|
||||
} from "../../redux/application/application.selectors";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import { signOutStart } from "../../redux/user/user.actions";
|
||||
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
recentItems: selectRecentItems,
|
||||
selectedHeader: selectSelectedHeader,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
@@ -69,6 +73,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
function Header({
|
||||
handleMenuClick,
|
||||
currentUser,
|
||||
bodyshop,
|
||||
selectedHeader,
|
||||
signOutStart,
|
||||
setBillEnterContext,
|
||||
@@ -237,16 +242,26 @@ function Header({
|
||||
{t("menus.header.accounting-receivables")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="payables">
|
||||
<Link to="/manage/accounting/payables">
|
||||
{t("menus.header.accounting-payables")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="payments">
|
||||
<Link to="/manage/accounting/payments">
|
||||
{t("menus.header.accounting-payments")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
{!(
|
||||
(bodyshop && bodyshop.cdk_dealerid) ||
|
||||
(bodyshop && bodyshop.pbs_serialnumber)
|
||||
) && (
|
||||
<Menu.Item key="payables">
|
||||
<Link to="/manage/accounting/payables">
|
||||
{t("menus.header.accounting-payables")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
)}
|
||||
{!(
|
||||
(bodyshop && bodyshop.cdk_dealerid) ||
|
||||
(bodyshop && bodyshop.pbs_serialnumber)
|
||||
) && (
|
||||
<Menu.Item key="payments">
|
||||
<Link to="/manage/accounting/payments">
|
||||
{t("menus.header.accounting-payments")}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
)}
|
||||
<Menu.Item key="export-logs">
|
||||
<Link to="/manage/accounting/exportlogs">
|
||||
{t("menus.header.export-logs")}
|
||||
|
||||
@@ -73,7 +73,7 @@ export const reconcileByPrice = (
|
||||
|
||||
jobLines.forEach((jl) => {
|
||||
const matchingBillLineIds = billLines
|
||||
.filter((bl) => bl.actual_price === jl.act_price && !jl.removed)
|
||||
.filter((bl) => bl.actual_price === jl.act_price && bl.quantity === jl.part_qty && !jl.removed)
|
||||
.map((bl) => bl.id);
|
||||
|
||||
if (matchingBillLineIds.length > 1) {
|
||||
|
||||
@@ -61,7 +61,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
||||
);
|
||||
};
|
||||
|
||||
const overlay = bodyshop.cdk_dealerid && (
|
||||
const overlay = (bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||
<Menu onClick={handleMenuClick}>
|
||||
{bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => (
|
||||
<Menu.Item key={mapping.name}>{mapping.name}</Menu.Item>
|
||||
@@ -69,7 +69,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
||||
</Menu>
|
||||
);
|
||||
|
||||
return bodyshop.cdk_dealerid ? (
|
||||
return bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? (
|
||||
<Dropdown overlay={overlay}>
|
||||
<Button disabled={disabled}>{t("jobs.actions.dmsautoallocate")}</Button>
|
||||
</Dropdown>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { DownOutlined } from "@ant-design/icons";
|
||||
import { Dropdown, Menu } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
@@ -11,8 +10,6 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleClick = ({ item, key, keyPath }) => {
|
||||
const est = item.props.value;
|
||||
form.setFieldsValue(est);
|
||||
@@ -37,7 +34,7 @@ export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) {
|
||||
href=" #"
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>
|
||||
{t("jobs.actions.changestimator")} <DownOutlined />
|
||||
<DownOutlined />
|
||||
</a>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { DownOutlined } from "@ant-design/icons";
|
||||
import { Dropdown, Menu } from "antd";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
export function JobsDetailChangeFilehandler({ disabled, form, bodyshop }) {
|
||||
const handleClick = ({ item, key, keyPath }) => {
|
||||
const est = item.props.value;
|
||||
form.setFieldsValue(est);
|
||||
};
|
||||
|
||||
const menu = (
|
||||
<div>
|
||||
<Menu onClick={handleClick}>
|
||||
{bodyshop.md_filehandlers.map((est, idx) => (
|
||||
<Menu.Item value={est} key={idx}>
|
||||
{`${est.ins_ct_fn} ${est.ins_ct_ln}`}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dropdown overlay={menu} disabled={disabled}>
|
||||
<a
|
||||
className="ant-dropdown-link"
|
||||
href=" #"
|
||||
onClick={(e) => e.preventDefault()}
|
||||
>
|
||||
<DownOutlined />
|
||||
</a>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(JobsDetailChangeFilehandler);
|
||||
@@ -75,6 +75,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
||||
>
|
||||
<DateTimePicker />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.date_next_contact")}
|
||||
name="date_next_contact"
|
||||
>
|
||||
<DateTimePicker />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.scheduled_completion")}
|
||||
name="scheduled_completion"
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
InputNumber,
|
||||
Row,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
} from "antd";
|
||||
import React from "react";
|
||||
@@ -23,7 +24,7 @@ import FormItemPhone, {
|
||||
import Car from "../job-damage-visual/job-damage-visual.component";
|
||||
import JobsDetailChangeEstimator from "../jobs-detail-change-estimator/jobs-detail-change-estimator.component";
|
||||
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||
|
||||
import JobsDetailChangeFileHandler from "../jobs-detail-change-filehandler/jobs-detail-change-filehandler.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -85,7 +86,15 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
||||
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city">
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.ins_ct_ln")} name="ins_ct_ln">
|
||||
<Form.Item
|
||||
label={
|
||||
<Space>
|
||||
{t("jobs.fields.ins_ct_ln")}
|
||||
<JobsDetailChangeFileHandler form={form} disabled={jobRO} />
|
||||
</Space>
|
||||
}
|
||||
name="ins_ct_ln"
|
||||
>
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn">
|
||||
@@ -135,7 +144,7 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
||||
label={t("jobs.fields.referral_source_extra")}
|
||||
name="referral_source_extra"
|
||||
>
|
||||
<Input disabled={jobRO}/>
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.alt_transport")} name="alt_transport">
|
||||
<Select disabled={jobRO} allowClear>
|
||||
@@ -219,12 +228,19 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
||||
{t("jobs.forms.appraiserinfo")}
|
||||
</Divider>
|
||||
|
||||
<JobsDetailChangeEstimator form={form} disabled={jobRO} />
|
||||
<FormRow noDivider>
|
||||
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.est_ct_fn")} name="est_ct_fn">
|
||||
<Form.Item
|
||||
label={
|
||||
<Space>
|
||||
{t("jobs.fields.est_ct_fn")}
|
||||
<JobsDetailChangeEstimator form={form} disabled={jobRO} />
|
||||
</Space>
|
||||
}
|
||||
name="est_ct_fn"
|
||||
>
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln">
|
||||
|
||||
@@ -3,17 +3,17 @@ import { notification } from "antd";
|
||||
import React, { useState } from "react";
|
||||
//import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import AlertComponent from "../../components/alert/alert.component";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import {
|
||||
DELETE_NOTE,
|
||||
QUERY_NOTES_BY_JOB_PK,
|
||||
} from "../../graphql/notes.queries";
|
||||
import JobNotesComponent from "./jobs.notes.component";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import JobNotesComponent from "./jobs.notes.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -63,6 +63,7 @@ export function JobNotesContainer({ jobId, insertAuditTrail }) {
|
||||
refetch={refetch}
|
||||
deleteLoading={deleteLoading}
|
||||
handleNoteDelete={handleNoteDelete}
|
||||
ro_number={data ? data.jobs_by_pk.ro_number : null}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,9 @@ import { createStructuredSelector } from "reselect";
|
||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import NoteUpsertModal from "../note-upsert-modal/note-upsert-modal.container";
|
||||
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
@@ -33,8 +35,12 @@ export function JobNotesComponent({
|
||||
jobId,
|
||||
setNoteUpsertContext,
|
||||
deleteLoading,
|
||||
ro_number,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const Templates = TemplateList("job_special", {
|
||||
ro_number,
|
||||
});
|
||||
|
||||
const columns = [
|
||||
{
|
||||
@@ -107,6 +113,18 @@ export function JobNotesComponent({
|
||||
>
|
||||
<EditFilled />
|
||||
</Button>
|
||||
<PrintWrapperComponent
|
||||
emailOnly
|
||||
templateObject={{
|
||||
name: Templates.individual_job_note.key,
|
||||
|
||||
variables: { id: record.id },
|
||||
}}
|
||||
messageObject={{
|
||||
subject: Templates.individual_job_note.subject,
|
||||
}}
|
||||
id={record.id}
|
||||
/>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -119,7 +119,7 @@ export function PartsOrderListTableComponent({
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title={t("parts_orders.labels.confirmdelete")}
|
||||
disabled={jobRO || !record.return}
|
||||
disabled={jobRO}
|
||||
onConfirm={async () => {
|
||||
//Delete the parts return.!
|
||||
|
||||
@@ -139,7 +139,7 @@ export function PartsOrderListTableComponent({
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Button disabled={jobRO || !record.return}>
|
||||
<Button disabled={jobRO}>
|
||||
<DeleteFilled />
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
|
||||
@@ -8,6 +8,7 @@ export default function PrintWrapperComponent({
|
||||
messageObject = {},
|
||||
children,
|
||||
id,
|
||||
emailOnly = false,
|
||||
}) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const handlePrint = async (type) => {
|
||||
@@ -19,7 +20,7 @@ export default function PrintWrapperComponent({
|
||||
return (
|
||||
<Space>
|
||||
{children || null}
|
||||
<PrinterFilled onClick={() => handlePrint("p")} />
|
||||
{!emailOnly && <PrinterFilled onClick={() => handlePrint("p")} />}
|
||||
<MailFilled onClick={() => handlePrint("e")} />
|
||||
{loading && <Spin />}
|
||||
</Space>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Input, PageHeader, Space, Spin } from "antd";
|
||||
import { Input, Space, Spin } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -26,8 +26,7 @@ export function ProductionBoardFilters({
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<PageHeader
|
||||
extra={
|
||||
|
||||
<Space wrap>
|
||||
{loading && <Spin />}
|
||||
<Input.Search
|
||||
@@ -46,7 +45,6 @@ export function ProductionBoardFilters({
|
||||
allowClear
|
||||
/>
|
||||
</Space>
|
||||
}
|
||||
></PageHeader>
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,106 +1,171 @@
|
||||
import { CalendarOutlined, EyeFilled } from "@ant-design/icons";
|
||||
import { Card, Col, Row, Space } from "antd";
|
||||
import React from "react";
|
||||
import { Card, Row, Col, Dropdown } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Link } from "react-router-dom";
|
||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import ProductionAlert from "../production-list-columns/production-list-columns.alert.component";
|
||||
import { EyeFilled } from "@ant-design/icons";
|
||||
import { Link } from "react-router-dom";
|
||||
import "./production-board-card.styles.scss";
|
||||
import ProductionRemoveButton from "../production-remove-button/production-remove-button.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
||||
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
|
||||
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
||||
import "./production-board-card.styles.scss";
|
||||
|
||||
export default function ProductionBoardCard(technician, card) {
|
||||
export default function ProductionBoardCard(
|
||||
technician,
|
||||
card,
|
||||
bodyshop,
|
||||
cardSettings
|
||||
) {
|
||||
const { t } = useTranslation();
|
||||
const menu = (
|
||||
<div>
|
||||
<Card title={t("general.labels.actions")}>
|
||||
<ProductionRemoveButton jobId={card.id} />
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
|
||||
let employee_body, employee_prep, employee_refinish; //employee_csr;
|
||||
if (card.employee_body) {
|
||||
employee_body = bodyshop.employees.find((e) => e.id === card.employee_body);
|
||||
}
|
||||
if (card.employee_prep) {
|
||||
employee_prep = bodyshop.employees.find((e) => e.id === card.employee_prep);
|
||||
}
|
||||
if (card.employee_refinish) {
|
||||
employee_refinish = bodyshop.employees.find(
|
||||
(e) => e.id === card.employee_refinish
|
||||
);
|
||||
}
|
||||
// if (card.employee_csr) {
|
||||
// employee_csr = bodyshop.employees.find((e) => e.id === card.employee_csr);
|
||||
// }
|
||||
|
||||
return (
|
||||
<Dropdown overlay={menu} trigger={["contextMenu"]}>
|
||||
<Card
|
||||
className="react-kanban-card imex-kanban-card tight-antd-rows"
|
||||
//style={{ margin: ".2rem 0rem" }}
|
||||
title={`${card.ro_number || t("general.labels.na")} - ${
|
||||
card.v_model_yr
|
||||
} ${card.v_make_desc || ""} ${card.v_model_desc || ""}`}
|
||||
>
|
||||
<Row>
|
||||
<Card
|
||||
className="react-kanban-card imex-kanban-card"
|
||||
size="small"
|
||||
title={
|
||||
<Space>
|
||||
<ProductionAlert record={card} key="alert" />
|
||||
<span style={{ fontWeight: "bolder" }}>
|
||||
{card.ro_number || t("general.labels.na")}
|
||||
</span>
|
||||
</Space>
|
||||
}
|
||||
extra={
|
||||
technician ? (
|
||||
<Link to={`/tech/joblookup?selected=${card.id}`}>
|
||||
<EyeFilled />
|
||||
</Link>
|
||||
) : (
|
||||
<Link to={`/manage/jobs/${card.id}`}>
|
||||
<EyeFilled />
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
>
|
||||
<Row>
|
||||
{cardSettings && cardSettings.ownr_nm && (
|
||||
<Col span={24}>
|
||||
<div className="ellipses">{`${card.ownr_fn || ""} ${
|
||||
card.ownr_ln || ""
|
||||
} ${card.ownr_co_nm || ""}`}</div>
|
||||
{cardSettings && cardSettings.compact ? (
|
||||
<div className="ellipses">{`${card.ownr_ln || ""} ${
|
||||
card.ownr_co_nm || ""
|
||||
}`}</div>
|
||||
) : (
|
||||
<div className="ellipses">{`${card.ownr_ln || ""}, ${
|
||||
card.ownr_fn || ""
|
||||
} ${card.ownr_co_nm || ""}`}</div>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={12}>
|
||||
<div className="ellipses">{card.clm_no || ""}</div>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
)}
|
||||
<Col span={24}>
|
||||
<div className="ellipses">{`${card.v_model_yr || ""} ${
|
||||
card.v_make_desc || ""
|
||||
} ${card.v_model_desc || ""}`}</div>
|
||||
</Col>
|
||||
{cardSettings && cardSettings.ins_co_nm && card.ins_co_nm && (
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
|
||||
<div className="ellipses">{card.ins_co_nm || ""}</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
)}
|
||||
{cardSettings && cardSettings.clm_no && card.clm_no && (
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
|
||||
<div className="ellipses">{card.clm_no || ""}</div>
|
||||
</Col>
|
||||
)}
|
||||
|
||||
{cardSettings && cardSettings.employeeassignments && (
|
||||
<Col span={24}>
|
||||
<div className="imex-flex-row imex-flex-row__flex-space-around">
|
||||
<div className="mex-flex-row__margin">
|
||||
<div>{`B: ${card.labhrs.aggregate.sum.mod_lb_hrs || "?"}`}</div>
|
||||
<div>{`R: ${card.larhrs.aggregate.sum.mod_lb_hrs || "?"}`}</div>
|
||||
</div>
|
||||
<div className="mex-flex-row__margin">
|
||||
<div>{`B: ${
|
||||
card.employee_body_rel
|
||||
? `${card.employee_body_rel.first_name} ${card.employee_body_rel.last_name}`
|
||||
: ""
|
||||
}`}</div>
|
||||
<div>{`P: ${
|
||||
card.employee_prep_rel
|
||||
? `${card.employee_prep_rel.first_name} ${card.employee_prep_rel.last_name}`
|
||||
: ""
|
||||
}`}</div>
|
||||
<div>{`R: ${
|
||||
card.employee_refinish_rel
|
||||
? `${card.employee_refinish_rel.first_name} ${card.employee_refinish_rel.last_name}`
|
||||
: ""
|
||||
}`}</div>
|
||||
<div>{`CSR: ${
|
||||
card.employee_csr_rel
|
||||
? `${card.employee_csr_rel.first_name} ${card.employee_csr_rel.last_name}`
|
||||
: ""
|
||||
}`}</div>
|
||||
</div>
|
||||
</div>
|
||||
<Row>
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`B: ${
|
||||
employee_body
|
||||
? `${employee_body.first_name.substr(
|
||||
0,
|
||||
3
|
||||
)} ${employee_body.last_name.charAt(0)}`
|
||||
: ""
|
||||
} ${card.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`P: ${
|
||||
employee_prep
|
||||
? `${employee_prep.first_name.substr(
|
||||
0,
|
||||
3
|
||||
)} ${employee_prep.last_name.charAt(0)}`
|
||||
: ""
|
||||
}`}</Col>
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`R: ${
|
||||
employee_refinish
|
||||
? `${employee_refinish.first_name.substr(
|
||||
0,
|
||||
3
|
||||
)} ${employee_refinish.last_name.charAt(0)}`
|
||||
: ""
|
||||
} ${card.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
||||
{/* <Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`C: ${
|
||||
employee_csr
|
||||
? `${employee_csr.first_name} ${employee_csr.last_name}`
|
||||
: ""
|
||||
}`}</Col> */}
|
||||
</Row>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={18}>
|
||||
<DateTimeFormatter>{card.scheduled_completion}</DateTimeFormatter>
|
||||
)}
|
||||
{/* {cardSettings && cardSettings.laborhrs && (
|
||||
<Col span={24}>
|
||||
<Row>
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`B: ${
|
||||
card.labhrs.aggregate.sum.mod_lb_hrs || "?"
|
||||
} hrs`}</Col>
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`R: ${
|
||||
card.larhrs.aggregate.sum.mod_lb_hrs || "?"
|
||||
} hrs`}</Col>
|
||||
</Row>
|
||||
</Col>
|
||||
<Col span={6}>
|
||||
)} */}
|
||||
{cardSettings &&
|
||||
cardSettings.scheduled_completion &&
|
||||
card.scheduled_completion && (
|
||||
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
|
||||
<Space>
|
||||
<CalendarOutlined />
|
||||
<DateTimeFormatter format="MM/DD">
|
||||
{card.scheduled_completion}
|
||||
</DateTimeFormatter>
|
||||
</Space>
|
||||
</Col>
|
||||
)}
|
||||
{cardSettings && cardSettings.ats && card.alt_transport && (
|
||||
<Col span={12}>
|
||||
<div>{card.alt_transport || ""}</div>
|
||||
</Col>
|
||||
</Row>
|
||||
<div>
|
||||
<ProductionListColumnProductionNote record={card} />
|
||||
</div>
|
||||
<div className="imex-flex-row imex-flex-row__flex-space-around">
|
||||
<ProductionAlert record={card} key="alert" />
|
||||
<ProductionSubletsManageComponent subletJobLines={card.subletLines} />
|
||||
{technician ? (
|
||||
<Link to={`/tech/joblookup?selected=${card.id}`}>
|
||||
<EyeFilled />
|
||||
</Link>
|
||||
) : (
|
||||
<Link to={`/manage/jobs/${card.id}`}>
|
||||
<EyeFilled />
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
</Dropdown>
|
||||
)}
|
||||
{cardSettings && cardSettings.sublets && (
|
||||
<Col span={12}>
|
||||
<ProductionSubletsManageComponent
|
||||
subletJobLines={card.subletLines}
|
||||
/>
|
||||
</Col>
|
||||
)}
|
||||
{cardSettings && cardSettings.production_note && (
|
||||
<Col span={24}>
|
||||
{cardSettings && cardSettings.production_note && (
|
||||
<ProductionListColumnProductionNote record={card} />
|
||||
)}
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Form,
|
||||
notification,
|
||||
Popover,
|
||||
Row,
|
||||
Switch,
|
||||
} from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { UPDATE_KANBAN_SETTINGS } from "../../graphql/user.queries";
|
||||
|
||||
export default function ProductionBoardKanbanCardSettings({
|
||||
associationSettings,
|
||||
}) {
|
||||
const [form] = Form.useForm();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [updateKbSettings] = useMutation(UPDATE_KANBAN_SETTINGS);
|
||||
|
||||
useEffect(() => {
|
||||
form.setFieldsValue(
|
||||
associationSettings && associationSettings.kanban_settings
|
||||
);
|
||||
}, [form, associationSettings, visible]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
setLoading(true);
|
||||
const result = await updateKbSettings({
|
||||
variables: {
|
||||
id: associationSettings && associationSettings.id,
|
||||
ks: values,
|
||||
},
|
||||
});
|
||||
if (result.errors) {
|
||||
notification.open({
|
||||
type: "error",
|
||||
message: t("production.errors.settings", {
|
||||
error: JSON.stringify(result.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
setVisible(false);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const overlay = (
|
||||
<div>
|
||||
<Card>
|
||||
<Form form={form} onFinish={handleFinish} layout="vertical">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
label={t("production.labels.compact")}
|
||||
name="compact"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.ownr_nm")}
|
||||
name="ownr_nm"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.clm_no")}
|
||||
name="clm_no"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.ins_co_nm")}
|
||||
name="ins_co_nm"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
{/* <Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.laborhrs")}
|
||||
name="laborhrs"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item> */}
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.employeeassignments")}
|
||||
name="employeeassignments"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={12}>
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.scheduled_completion")}
|
||||
name="scheduled_completion"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.ats")}
|
||||
name="ats"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.production_note")}
|
||||
name="production_note"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
{/* <Form.Item
|
||||
valuePropName='checked' label={t("production.labels.alert")} name="alert">
|
||||
<Switch/>
|
||||
</Form.Item> */}
|
||||
<Form.Item
|
||||
valuePropName="checked"
|
||||
label={t("production.labels.sublets")}
|
||||
name="sublets"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</Form>
|
||||
<Button
|
||||
onClick={() => {
|
||||
form.submit();
|
||||
}}
|
||||
>
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<Popover content={overlay} visible={visible}>
|
||||
<Button loading={loading} onClick={() => setVisible(true)}>
|
||||
{t("production.labels.cardsettings")}
|
||||
</Button>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import Board, { moveCard } from "@lourenci/react-kanban";
|
||||
import "@lourenci/react-kanban/dist/styles.css";
|
||||
import { notification } from "antd";
|
||||
import Board, { moveCard } from "@asseinfo/react-kanban";
|
||||
//import "@asseinfo/react-kanban/dist/styles.css";
|
||||
import "./production-board-kanban.styles.scss";
|
||||
import { Grid, notification, PageHeader, Space, Statistic } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -16,6 +17,8 @@ import ProductionBoardFilters from "../production-board-filters/production-board
|
||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import ProductionBoardKanbanCardSettings from "./production-board-kanban.card-settings.component";
|
||||
import styled from "styled-components";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -32,6 +35,7 @@ export function ProductionBoardKanbanComponent({
|
||||
bodyshop,
|
||||
technician,
|
||||
insertAuditTrail,
|
||||
associationSettings,
|
||||
}) {
|
||||
const [boardLanes, setBoardLanes] = useState({
|
||||
columns: [{ id: "Loading...", title: "Loading...", cards: [] }],
|
||||
@@ -116,6 +120,7 @@ export function ProductionBoardKanbanComponent({
|
||||
newChildCard ? newChildCard.id : null,
|
||||
newChildCardNewParent
|
||||
),
|
||||
// TODO: optimisticResponse
|
||||
});
|
||||
insertAuditTrail({
|
||||
jobid: card.id,
|
||||
@@ -131,21 +136,112 @@ export function ProductionBoardKanbanComponent({
|
||||
}
|
||||
};
|
||||
|
||||
const totalHrs = data
|
||||
.reduce(
|
||||
(acc, val) =>
|
||||
acc +
|
||||
(val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) +
|
||||
(val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
|
||||
0
|
||||
)
|
||||
.toFixed(1);
|
||||
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
|
||||
.filter((screen) => !!screen[1])
|
||||
.slice(-1)[0];
|
||||
|
||||
const standardSizes = {
|
||||
xs: "250",
|
||||
sm: "250",
|
||||
md: "250",
|
||||
lg: "250",
|
||||
xl: "250",
|
||||
xxl: "250",
|
||||
};
|
||||
const compactSizes = {
|
||||
xs: "150",
|
||||
sm: "150",
|
||||
md: "150",
|
||||
lg: "150",
|
||||
xl: "155",
|
||||
xxl: "155",
|
||||
};
|
||||
|
||||
const width = selectedBreakpoint
|
||||
? associationSettings &&
|
||||
associationSettings.kanban_settings &&
|
||||
associationSettings.kanban_settings.compact
|
||||
? compactSizes[selectedBreakpoint[0]]
|
||||
: standardSizes[selectedBreakpoint[0]]
|
||||
: "250";
|
||||
|
||||
const Container = styled.div`
|
||||
.react-kanban-card-skeleton,
|
||||
.react-kanban-card,
|
||||
.react-kanban-card-adder-form {
|
||||
box-sizing: border-box;
|
||||
max-width: ${width}px;
|
||||
min-width: ${width}px;
|
||||
}
|
||||
`;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Container>
|
||||
<IndefiniteLoading loading={isMoving} />
|
||||
<ProductionBoardFilters
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
loading={isMoving}
|
||||
<PageHeader
|
||||
title={
|
||||
<Space>
|
||||
<Statistic
|
||||
title={t("dashboard.titles.productionhours")}
|
||||
value={totalHrs}
|
||||
/>
|
||||
<Statistic
|
||||
title={t("appointments.labels.inproduction")}
|
||||
value={data && data.length}
|
||||
/>
|
||||
</Space>
|
||||
}
|
||||
extra={
|
||||
<Space wrap>
|
||||
<ProductionBoardFilters
|
||||
filter={filter}
|
||||
setFilter={setFilter}
|
||||
loading={isMoving}
|
||||
/>
|
||||
<ProductionBoardKanbanCardSettings
|
||||
associationSettings={associationSettings}
|
||||
/>
|
||||
</Space>
|
||||
}
|
||||
/>
|
||||
|
||||
<Board
|
||||
children={boardLanes}
|
||||
disableCardDrag={isMoving}
|
||||
renderCard={(card) => ProductionBoardCard(technician, card)}
|
||||
renderCard={(card) =>
|
||||
ProductionBoardCard(
|
||||
technician,
|
||||
card,
|
||||
bodyshop,
|
||||
associationSettings &&
|
||||
associationSettings.kanban_settings &&
|
||||
Object.keys(associationSettings.kanban_settings).length > 0
|
||||
? associationSettings.kanban_settings
|
||||
: {
|
||||
ats: true,
|
||||
clm_no: true,
|
||||
compact: false,
|
||||
ownr_nm: true,
|
||||
sublets: true,
|
||||
ins_co_nm: true,
|
||||
production_note: true,
|
||||
employeeassignments: true,
|
||||
scheduled_completion: true,
|
||||
}
|
||||
)
|
||||
}
|
||||
onCardDragEnd={handleDragEnd}
|
||||
/>
|
||||
</div>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
export default connect(
|
||||
|
||||
@@ -1,25 +1,40 @@
|
||||
import { useSubscription } from "@apollo/client";
|
||||
import { useQuery, useSubscription } from "@apollo/client";
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { SUBSCRIPTION_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import ProductionBoardKanbanComponent from "./production-board-kanban.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
currentUser: selectCurrentUser,
|
||||
});
|
||||
|
||||
export function ProductionBoardKanbanContainer({ bodyshop }) {
|
||||
export function ProductionBoardKanbanContainer({ bodyshop, currentUser }) {
|
||||
const { loading, data } = useSubscription(
|
||||
SUBSCRIPTION_JOBS_IN_PRODUCTION,
|
||||
{}
|
||||
);
|
||||
|
||||
const { loading: associationSettingsLoading, data: associationSettings } =
|
||||
useQuery(QUERY_KANBAN_SETTINGS, {
|
||||
variables: { email: currentUser.email },
|
||||
});
|
||||
|
||||
return (
|
||||
<ProductionBoardKanbanComponent
|
||||
loading={loading}
|
||||
loading={loading || associationSettingsLoading}
|
||||
data={data ? data.jobs : []}
|
||||
associationSettings={
|
||||
associationSettings && associationSettings.associations[0]
|
||||
? associationSettings.associations[0]
|
||||
: null
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
.react-kanban-board {
|
||||
padding: 5px;
|
||||
}
|
||||
.react-kanban-card {
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
padding: 4px;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
// .react-kanban-card-skeleton,
|
||||
// .react-kanban-card,
|
||||
// .react-kanban-card-adder-form {
|
||||
// box-sizing: border-box;
|
||||
// max-width: 145px;
|
||||
// min-width: 145px;
|
||||
// }
|
||||
|
||||
.react-kanban-card--dragging {
|
||||
box-shadow: 2px 2px grey;
|
||||
}
|
||||
.react-kanban-card__description {
|
||||
padding-top: 10px;
|
||||
}
|
||||
.react-kanban-card__title {
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 5px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.react-kanban-column {
|
||||
padding: 10px;
|
||||
border-radius: 2px;
|
||||
background-color: #eee;
|
||||
margin: 5px;
|
||||
}
|
||||
.react-kanban-column input:focus {
|
||||
outline: none;
|
||||
}
|
||||
.react-kanban-card-adder-form {
|
||||
border-radius: 3px;
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
.react-kanban-card-adder-form input {
|
||||
border: 0px;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
}
|
||||
.react-kanban-card-adder-button {
|
||||
width: 100%;
|
||||
margin-top: 5px;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
border: 1px solid #ccc;
|
||||
transition: 0.3s;
|
||||
border-radius: 3px;
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.react-kanban-card-adder-button:hover {
|
||||
background-color: #ccc;
|
||||
}
|
||||
.react-kanban-card-adder-form__title {
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 5px;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 0px;
|
||||
}
|
||||
.react-kanban-card-adder-form__title:focus {
|
||||
outline: none;
|
||||
}
|
||||
.react-kanban-card-adder-form__description {
|
||||
width: 100%;
|
||||
margin-top: 10px;
|
||||
}
|
||||
.react-kanban-card-adder-form__description:focus {
|
||||
outline: none;
|
||||
}
|
||||
.react-kanban-card-adder-form__button {
|
||||
background-color: #eee;
|
||||
border: none;
|
||||
padding: 5px;
|
||||
width: 45%;
|
||||
margin-top: 5px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.react-kanban-card-adder-form__button:hover {
|
||||
transition: 0.3s;
|
||||
cursor: pointer;
|
||||
background-color: #ccc;
|
||||
}
|
||||
.react-kanban-column-header {
|
||||
padding-bottom: 10px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.react-kanban-column-header input:focus {
|
||||
outline: none;
|
||||
}
|
||||
.react-kanban-column-header__button {
|
||||
color: #333333;
|
||||
background-color: #ffffff;
|
||||
border-color: #cccccc;
|
||||
}
|
||||
.react-kanban-column-header__button:hover,
|
||||
.react-kanban-column-header__button:focus,
|
||||
.react-kanban-column-header__button:active {
|
||||
background-color: #e6e6e6;
|
||||
}
|
||||
.react-kanban-column-adder-button {
|
||||
border: 2px dashed #eee;
|
||||
height: 132px;
|
||||
margin: 5px;
|
||||
}
|
||||
.react-kanban-column-adder-button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import i18n from "i18next";
|
||||
import moment from "moment";
|
||||
import React from "react";
|
||||
import { Link } from "react-router-dom";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
@@ -11,11 +12,11 @@ import ProductionListColumnBodyPriority from "./production-list-columns.bodyprio
|
||||
import ProductionListDate from "./production-list-columns.date.component";
|
||||
import ProductionListColumnDetailPriority from "./production-list-columns.detailpriority.component";
|
||||
import ProductionListEmployeeAssignment from "./production-list-columns.empassignment.component";
|
||||
import ProductionListLastContacted from "./production-list-columns.lastcontacted.component";
|
||||
import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component";
|
||||
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
|
||||
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||
import ProductionListLastContacted from "./production-list-columns.lastcontacted.component";
|
||||
|
||||
const r = ({ technician, state, activeStatuses }) => {
|
||||
return [
|
||||
@@ -109,6 +110,29 @@ const r = ({ technician, state, activeStatuses }) => {
|
||||
state.sortedInfo.order,
|
||||
render: (text, record) => <ProductionListLastContacted record={record} />,
|
||||
},
|
||||
{
|
||||
title: i18n.t("jobs.fields.date_next_contact"),
|
||||
dataIndex: "date_next_contact",
|
||||
key: "date_next_contact",
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => dateSort(a.date_next_contact, b.date_next_contact),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "date_next_contact" &&
|
||||
state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<span
|
||||
style={{
|
||||
color:
|
||||
record.date_next_contact &&
|
||||
moment(record.date_next_contact).isBefore(moment())
|
||||
? "red"
|
||||
: "",
|
||||
}}
|
||||
>
|
||||
<ProductionListDate record={record} field="date_next_contact" time />
|
||||
</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: i18n.t("jobs.fields.scheduled_delivery"),
|
||||
dataIndex: "scheduled_delivery",
|
||||
@@ -332,7 +356,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
||||
render: (text, record) => (
|
||||
<ProductionListEmployeeAssignment
|
||||
record={record}
|
||||
type="employee_body_rel"
|
||||
type="employee_body"
|
||||
/>
|
||||
),
|
||||
},
|
||||
@@ -343,7 +367,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
||||
render: (text, record) => (
|
||||
<ProductionListEmployeeAssignment
|
||||
record={record}
|
||||
type="employee_prep_rel"
|
||||
type="employee_prep"
|
||||
/>
|
||||
),
|
||||
},
|
||||
@@ -352,10 +376,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
||||
dataIndex: "employee_csr",
|
||||
key: "employee_csr",
|
||||
render: (text, record) => (
|
||||
<ProductionListEmployeeAssignment
|
||||
record={record}
|
||||
type="employee_csr_rel"
|
||||
/>
|
||||
<ProductionListEmployeeAssignment record={record} type="employee_csr" />
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -365,7 +386,7 @@ const r = ({ technician, state, activeStatuses }) => {
|
||||
render: (text, record) => (
|
||||
<ProductionListEmployeeAssignment
|
||||
record={record}
|
||||
type="employee_refinish_rel"
|
||||
type="employee_refinish"
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -49,7 +49,7 @@ export function ProductionListEmpAssignment({
|
||||
const result = await updateJob({
|
||||
variables: { jobId: record.id, job: { [empAssignment]: employeeid } },
|
||||
|
||||
awaitRefetchQueries: true,
|
||||
// awaitRefetchQueries: true,
|
||||
});
|
||||
|
||||
insertAuditTrail({
|
||||
@@ -145,13 +145,18 @@ export function ProductionListEmpAssignment({
|
||||
</Row>
|
||||
);
|
||||
|
||||
let theEmployee;
|
||||
|
||||
if (record[type])
|
||||
theEmployee = bodyshop.employees.find((e) => e.id === record[type]);
|
||||
|
||||
return (
|
||||
<Popover destroyTooltipOnHide content={popContent} visible={visibility}>
|
||||
<Spin spinning={loading}>
|
||||
{record[type] ? (
|
||||
<div>
|
||||
<span>{`${record[type].first_name || ""} ${
|
||||
record[type].last_name || ""
|
||||
<span>{`${theEmployee.first_name || ""} ${
|
||||
theEmployee.last_name || ""
|
||||
}`}</span>
|
||||
<DeleteFilled
|
||||
style={iconStyle}
|
||||
@@ -174,13 +179,13 @@ export function ProductionListEmpAssignment({
|
||||
|
||||
const determineFieldName = (operation) => {
|
||||
switch (operation) {
|
||||
case "employee_body_rel":
|
||||
case "employee_body":
|
||||
return "employee_body";
|
||||
case "employee_prep_rel":
|
||||
case "employee_prep":
|
||||
return "employee_prep";
|
||||
case "employee_refinish_rel":
|
||||
case "employee_refinish":
|
||||
return "employee_refinish";
|
||||
case "employee_csr_rel":
|
||||
case "employee_csr":
|
||||
return "employee_csr";
|
||||
default:
|
||||
return null;
|
||||
|
||||
@@ -29,7 +29,11 @@ export function ProductionLastContacted({ currentUser, record }) {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const handleFinish = async ({ date_last_contacted, note }) => {
|
||||
const handleFinish = async ({
|
||||
date_last_contacted,
|
||||
date_next_contact,
|
||||
note,
|
||||
}) => {
|
||||
logImEXEvent("production_last_contacted");
|
||||
|
||||
//e.stopPropagation();
|
||||
@@ -38,6 +42,7 @@ export function ProductionLastContacted({ currentUser, record }) {
|
||||
jobId: record.id,
|
||||
job: {
|
||||
date_last_contacted,
|
||||
...(date_next_contact ? { date_next_contact } : {}),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -98,7 +103,16 @@ export function ProductionLastContacted({ currentUser, record }) {
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Form form={form} onFinish={handleFinish} layout="vertical">
|
||||
<Form.Item name="date_last_contacted">
|
||||
<Form.Item
|
||||
name="date_last_contacted"
|
||||
label={t("jobs.fields.date_last_contacted")}
|
||||
>
|
||||
<FormDateTimePickerComponent />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="date_next_contact"
|
||||
label={t("jobs.fields.date_next_contact")}
|
||||
>
|
||||
<FormDateTimePickerComponent />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("notes.labels.notetoadd")} name="note">
|
||||
|
||||
@@ -182,10 +182,16 @@ export function ProductionListTable({
|
||||
<div>
|
||||
<PageHeader
|
||||
title={
|
||||
<Statistic
|
||||
title={t("dashboard.titles.productionhours")}
|
||||
value={totalHrs}
|
||||
/>
|
||||
<Space>
|
||||
<Statistic
|
||||
title={t("dashboard.titles.productionhours")}
|
||||
value={totalHrs}
|
||||
/>
|
||||
<Statistic
|
||||
title={t("appointments.labels.inproduction")}
|
||||
value={dataSource && dataSource.length}
|
||||
/>
|
||||
</Space>
|
||||
}
|
||||
extra={
|
||||
<Space wrap>
|
||||
|
||||
@@ -56,7 +56,10 @@ export default function ProductionSubletsManageComponent({ subletJobLines }) {
|
||||
<Button
|
||||
key="complete"
|
||||
loading={loading}
|
||||
onClick={() => handleSubletMark(s, "complete")}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleSubletMark(s, "complete");
|
||||
}}
|
||||
type={s.sublet_completed ? "primary" : "ghost"}
|
||||
>
|
||||
<CheckCircleFilled
|
||||
@@ -66,7 +69,10 @@ export default function ProductionSubletsManageComponent({ subletJobLines }) {
|
||||
<Button
|
||||
key="sublet"
|
||||
loading={loading}
|
||||
onClick={() => handleSubletMark(s, "ignore")}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
handleSubletMark(s, "ignore");
|
||||
}}
|
||||
type={s.sublet_ignored ? "primary" : "ghost"}
|
||||
>
|
||||
<EyeInvisibleFilled
|
||||
|
||||
@@ -848,6 +848,88 @@ export default function ShopInfoGeneral({ form }) {
|
||||
}}
|
||||
</Form.List>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow grow header={t("bodyshop.labels.filehandlers")}>
|
||||
<Form.List name={["md_filehandlers"]}>
|
||||
{(fields, { add, remove, move }) => {
|
||||
return (
|
||||
<div>
|
||||
{fields.map((field, index) => (
|
||||
<Form.Item key={field.key}>
|
||||
<LayoutFormRow noDivider>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.ins_ct_fn")}
|
||||
key={`${index}ins_ct_fn`}
|
||||
name={[field.name, "ins_ct_fn"]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.ins_ct_ln")}
|
||||
key={`${index}ins_ct_ln`}
|
||||
name={[field.name, "ins_ct_ln"]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.ins_ph1")}
|
||||
key={`${index}ins_ph1`}
|
||||
name={[field.name, "ins_ph1"]}
|
||||
rules={[
|
||||
({ getFieldValue }) =>
|
||||
PhoneItemFormatterValidation(getFieldValue, [
|
||||
field.name,
|
||||
"ins_ph",
|
||||
]),
|
||||
]}
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.ins_ea")}
|
||||
key={`${index}ins_ea`}
|
||||
name={[field.name, "ins_ea"]}
|
||||
rules={[
|
||||
{
|
||||
type: "email",
|
||||
message: "This is not a valid email address.",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<FormItemEmail
|
||||
email={form.getFieldValue([field.name, "ins_ea"])}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Space>
|
||||
<DeleteFilled
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
<FormListMoveArrows
|
||||
move={move}
|
||||
index={index}
|
||||
total={fields.length}
|
||||
/>
|
||||
</Space>
|
||||
</LayoutFormRow>
|
||||
</Form.Item>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => {
|
||||
add();
|
||||
}}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{t("general.actions.add")}
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow grow header={t("bodyshop.fields.md_ccc_rates")}>
|
||||
<Form.List name={["md_ccc_rates"]}>
|
||||
{(fields, { add, remove, move }) => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -98,7 +98,9 @@ export const QUERY_BODYSHOP = gql`
|
||||
md_ded_notes
|
||||
pbs_configuration
|
||||
pbs_serialnumber
|
||||
md_filehandlers
|
||||
employees {
|
||||
user_email
|
||||
id
|
||||
active
|
||||
first_name
|
||||
@@ -192,6 +194,7 @@ export const UPDATE_SHOP = gql`
|
||||
md_ded_notes
|
||||
pbs_configuration
|
||||
pbs_serialnumber
|
||||
md_filehandlers
|
||||
employees {
|
||||
id
|
||||
first_name
|
||||
@@ -199,6 +202,7 @@ export const UPDATE_SHOP = gql`
|
||||
last_name
|
||||
employee_number
|
||||
rates
|
||||
user_email
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { gql } from "@apollo/client";
|
||||
|
||||
export const QUERY_EMPLOYEES = gql`
|
||||
query QUERY_EMPLOYEES {
|
||||
employees {
|
||||
employees(order_by: { employee_number: asc }) {
|
||||
last_name
|
||||
id
|
||||
first_name
|
||||
|
||||
@@ -125,6 +125,7 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
||||
scheduled_completion
|
||||
scheduled_delivery
|
||||
date_last_contacted
|
||||
date_next_contact
|
||||
ins_co_nm
|
||||
clm_total
|
||||
ownr_ph1
|
||||
@@ -134,39 +135,10 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
||||
production_vars
|
||||
kanbanparent
|
||||
alt_transport
|
||||
joblines_status {
|
||||
part_type
|
||||
count
|
||||
status
|
||||
}
|
||||
employee_body
|
||||
employee_body_rel {
|
||||
id
|
||||
first_name
|
||||
last_name
|
||||
}
|
||||
employee_refinish
|
||||
employee_refinish_rel {
|
||||
id
|
||||
first_name
|
||||
last_name
|
||||
}
|
||||
employee_prep
|
||||
employee_prep_rel {
|
||||
id
|
||||
first_name
|
||||
last_name
|
||||
}
|
||||
employee_csr_rel {
|
||||
id
|
||||
first_name
|
||||
last_name
|
||||
}
|
||||
partcount: joblines_aggregate(where: { removed: { _eq: false } }) {
|
||||
nodes {
|
||||
status
|
||||
}
|
||||
}
|
||||
employee_csr
|
||||
labhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||
@@ -519,6 +491,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
date_scheduled
|
||||
date_invoiced
|
||||
date_last_contacted
|
||||
date_next_contact
|
||||
date_exported
|
||||
status
|
||||
owner_owing
|
||||
@@ -762,6 +735,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
|
||||
scheduled_delivery
|
||||
date_invoiced
|
||||
date_last_contacted
|
||||
date_next_contact
|
||||
date_open
|
||||
date_exported
|
||||
|
||||
@@ -848,6 +822,7 @@ export const QUERY_TECH_JOB_DETAILS = gql`
|
||||
scheduled_delivery
|
||||
date_invoiced
|
||||
date_last_contacted
|
||||
date_next_contact
|
||||
date_open
|
||||
date_exported
|
||||
voided
|
||||
|
||||
@@ -14,6 +14,7 @@ export const QUERY_NOTES_BY_JOB_PK = gql`
|
||||
query QUERY_NOTES_BY_JOB_PK($id: uuid!) {
|
||||
jobs_by_pk(id: $id) {
|
||||
id
|
||||
ro_number
|
||||
notes {
|
||||
created_at
|
||||
created_by
|
||||
|
||||
@@ -69,3 +69,25 @@ export const UPDATE_FCM_TOKEN = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const QUERY_KANBAN_SETTINGS = gql`
|
||||
query QUERY_KANBAN_SETTINGS($email: String!) {
|
||||
associations(
|
||||
where: { _and: { useremail: { _eq: $email }, active: { _eq: true } } }
|
||||
) {
|
||||
id
|
||||
kanban_settings
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const UPDATE_KANBAN_SETTINGS = gql`
|
||||
mutation UPDATE_KANBAN_SETTINGS($id: uuid!, $ks: jsonb) {
|
||||
update_associations_by_pk(
|
||||
pk_columns: { id: $id }
|
||||
_set: { kanban_settings: $ks }
|
||||
) {
|
||||
id
|
||||
kanban_settings
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Button, Col, PageHeader, Row } from "antd";
|
||||
import { Button, Col, PageHeader, Row, Space, Form, Switch } from "antd";
|
||||
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ContractCarsContainer from "../../components/contract-cars/contract-cars.container";
|
||||
@@ -13,14 +14,25 @@ export default function ContractCreatePageComponent({
|
||||
const { t } = useTranslation();
|
||||
|
||||
const CreateButton = (
|
||||
<Button
|
||||
disabled={!selectedJobState[0] || !selectedCarState[0]}
|
||||
type="primary"
|
||||
onClick={() => form.submit()}
|
||||
loading={loading}
|
||||
>
|
||||
{t("general.actions.create")}
|
||||
</Button>
|
||||
<Space size="large">
|
||||
{selectedJobState[0] && selectedCarState[0] && (
|
||||
<Form.Item
|
||||
label={t("jobs.actions.addtoproduction")}
|
||||
name="addtoproduction"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Button
|
||||
disabled={!selectedJobState[0] || !selectedCarState[0]}
|
||||
type="primary"
|
||||
onClick={() => form.submit()}
|
||||
loading={loading}
|
||||
>
|
||||
{t("general.actions.create")}
|
||||
</Button>
|
||||
</Space>
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useHistory, useLocation } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
import { INSERT_NEW_CONTRACT } from "../../graphql/cccontracts.queries";
|
||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||
import {
|
||||
setBreadcrumbs,
|
||||
setSelectedHeader,
|
||||
@@ -37,8 +38,9 @@ export function ContractCreatePageContainer({
|
||||
(location.state && location.state.jobId) || null
|
||||
);
|
||||
const [insertContract] = useMutation(INSERT_NEW_CONTRACT);
|
||||
const [intakeJob] = useMutation(UPDATE_JOB);
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
const handleFinish = async ({ addtoproduction, ...values }) => {
|
||||
if (!!selectedCarState[0] && !!selectedJobState[0]) {
|
||||
setLoading(true);
|
||||
const result = await insertContract({
|
||||
@@ -54,12 +56,35 @@ export function ContractCreatePageContainer({
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!result.errors) {
|
||||
//Update the courtesy car to have the damage.
|
||||
notification["success"]({
|
||||
message: t("contracts.successes.saved"),
|
||||
});
|
||||
|
||||
//Intake the job if required
|
||||
if (addtoproduction) {
|
||||
const result2 = await intakeJob({
|
||||
variables: {
|
||||
jobId: selectedJobState[0],
|
||||
job: {
|
||||
actual_in: new Date(),
|
||||
inproduction: true,
|
||||
status: bodyshop.md_ro_statuses.default_arrived,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (result2.errors) {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.saving", {
|
||||
error: JSON.stringify(!result2.errors),
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
form.resetFields();
|
||||
form.resetFields();
|
||||
history.push(
|
||||
|
||||
@@ -120,7 +120,11 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
if (loading) return <LoadingSpinner />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
|
||||
if (!jobId || !bodyshop.cdk_dealerid || !(data && data.jobs_by_pk))
|
||||
if (
|
||||
!jobId ||
|
||||
!(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) ||
|
||||
!(data && data.jobs_by_pk)
|
||||
)
|
||||
return <Result status="404" />;
|
||||
|
||||
return (
|
||||
|
||||
@@ -208,7 +208,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
||||
>
|
||||
<DateTimePicker disabled={jobRO} />
|
||||
</Form.Item>
|
||||
{bodyshop.cdk_dealerid && (
|
||||
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||
<Form.Item
|
||||
label={t("jobs.fields.kmin")}
|
||||
name="kmin"
|
||||
@@ -221,7 +221,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
||||
<InputNumber precision={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
)}
|
||||
{bodyshop.cdk_dealerid && (
|
||||
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||
<Form.Item
|
||||
label={t("jobs.fields.kmout")}
|
||||
name="kmout"
|
||||
|
||||
@@ -503,6 +503,7 @@
|
||||
"emaillater": "Email Later",
|
||||
"employees": "Employees",
|
||||
"estimators": "Estimators",
|
||||
"filehandlers": "File Handlers",
|
||||
"insurancecos": "Insurance Companies",
|
||||
"intakechecklist": "Intake Checklist",
|
||||
"jobstatuses": "Job Statuses",
|
||||
@@ -535,6 +536,7 @@
|
||||
"save": "Shop configuration saved successfully. "
|
||||
},
|
||||
"validation": {
|
||||
"centermustexist": "The chosen responsibility center does not exist.",
|
||||
"larsplit": "Refinish hour split must add up to 1.",
|
||||
"useremailmustexist": "This email is not a valid user."
|
||||
}
|
||||
@@ -1091,6 +1093,7 @@
|
||||
"addtoscoreboard": "Add to Scoreboard",
|
||||
"allocate": "Allocate",
|
||||
"autoallocate": "Auto Allocate",
|
||||
"changefilehandler": "Change File Handler",
|
||||
"changelaborrate": "Change Labor Rate",
|
||||
"changestatus": "Change Status",
|
||||
"changestimator": "Change Estimator",
|
||||
@@ -1205,6 +1208,7 @@
|
||||
"date_exported": "Exported",
|
||||
"date_invoiced": "Invoiced",
|
||||
"date_last_contacted": "Last Contacted Date",
|
||||
"date_next_contact": "Next Contact Date",
|
||||
"date_open": "Open",
|
||||
"date_scheduled": "Scheduled",
|
||||
"ded_amt": "Deductible",
|
||||
@@ -1725,7 +1729,8 @@
|
||||
"new": "New Conversation"
|
||||
},
|
||||
"errors": {
|
||||
"invalidphone": "The phone number is invalid. Unable to open conversation. "
|
||||
"invalidphone": "The phone number is invalid. Unable to open conversation. ",
|
||||
"noattachedjobs": "No jobs have been associated to this conversation. "
|
||||
},
|
||||
"labels": {
|
||||
"archive": "Archive",
|
||||
@@ -1735,6 +1740,7 @@
|
||||
"nojobs": "Not associated to any job.",
|
||||
"phonenumber": "Phone #",
|
||||
"presets": "Presets",
|
||||
"recentonly": "Only your most recent 50 conversations will be shown here. If you are looking for an older conversation, find the related contact and click their phone number to view the conversation.",
|
||||
"selectmedia": "Select Media",
|
||||
"sentby": "Sent by {{by}} at {{time}}",
|
||||
"typeamessage": "Send a message...",
|
||||
@@ -1824,6 +1830,7 @@
|
||||
"receivebill": "Receive Bill"
|
||||
},
|
||||
"errors": {
|
||||
"associatedbills": "This parts order cannot",
|
||||
"backordering": "Error backordering part {{message}}.",
|
||||
"creating": "Error encountered when creating parts order. "
|
||||
},
|
||||
@@ -1849,7 +1856,7 @@
|
||||
},
|
||||
"labels": {
|
||||
"allpartsto": "All Parts Location",
|
||||
"confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. ",
|
||||
"confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ",
|
||||
"email": "Send by Email",
|
||||
"inthisorder": "Parts in this Order",
|
||||
"newpartsorder": "New Parts Order",
|
||||
@@ -1968,6 +1975,7 @@
|
||||
"zip": "Postal Code/Zip"
|
||||
},
|
||||
"3rdpartypayer": "Invoice to Third Party Payer",
|
||||
"ab_proof_of_loss": "AB - Proof of Loss",
|
||||
"appointment_confirmation": "Appointment Confirmation",
|
||||
"appointment_reminder": "Appointment Reminder",
|
||||
"casl_authorization": "CASL Authorization",
|
||||
@@ -1985,6 +1993,7 @@
|
||||
"fippa_authorization": "FIPPA Authorization",
|
||||
"glass_express_checklist": "Glass Express Checklist",
|
||||
"guarantee": "Repair Guarantee",
|
||||
"individual_job_note": "Job Note RO # {{ro_number}}",
|
||||
"invoice_customer_payable": "Invoice (Customer Payable)",
|
||||
"invoice_total_payable": "Invoice (Total Payable)",
|
||||
"iou_form": "IOU Form",
|
||||
@@ -2023,7 +2032,8 @@
|
||||
"worksheet_by_line_number": "Worksheet by Line Number",
|
||||
"worksheet_sorted_by_operation": "Worksheet by Operation",
|
||||
"worksheet_sorted_by_operation_no_hours": "Worksheet by Operation (No Hours)",
|
||||
"worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type"
|
||||
"worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type",
|
||||
"worksheet_sorted_by_operation_type": "Worksheet by Operation Type"
|
||||
},
|
||||
"labels": {
|
||||
"groups": {
|
||||
@@ -2068,20 +2078,31 @@
|
||||
},
|
||||
"errors": {
|
||||
"boardupdate": "Error encountered updating job. {{message}}",
|
||||
"removing": "Error removing from production board. {{error}}"
|
||||
"removing": "Error removing from production board. {{error}}",
|
||||
"settings": "Error saving board settings: {{error}}"
|
||||
},
|
||||
"labels": {
|
||||
"alert": "Alert",
|
||||
"alertoff": "Remove alert from job",
|
||||
"alerton": "Add alert to job",
|
||||
"ats": "Alternative Transportation",
|
||||
"bodyhours": "B",
|
||||
"bodypriority": "B/P",
|
||||
"cardsettings": "Card Settings",
|
||||
"clm_no": "Claim Number",
|
||||
"compact": "Compact Cards",
|
||||
"detailpriority": "D/P",
|
||||
"employeeassignments": "Employee Assignments",
|
||||
"employeesearch": "Employee Search",
|
||||
"ins_co_nm": "Insurance Company Name",
|
||||
"jobdetail": "Job Details",
|
||||
"laborhrs": "Labor Hours",
|
||||
"note": "Production Note",
|
||||
"ownr_nm": "Owner Name",
|
||||
"paintpriority": "P/P",
|
||||
"production_note": "Production Note",
|
||||
"refinishhours": "R",
|
||||
"scheduled_completion": "Scheduled Completion",
|
||||
"selectview": "Select a View",
|
||||
"sublets": "Sublets",
|
||||
"totalhours": "Total Hrs ",
|
||||
@@ -2176,6 +2197,7 @@
|
||||
"open_orders_csr": "Open Orders by CSR",
|
||||
"open_orders_estimator": "Open Orders by Estimator",
|
||||
"open_orders_ins_co": "Open Orders by Insurance Company",
|
||||
"open_orders_status": "Open Orders by Status",
|
||||
"parts_backorder": "Backordered Parts",
|
||||
"parts_not_recieved": "Parts Not Received",
|
||||
"payments_by_date": "Payments by Date",
|
||||
|
||||
@@ -503,6 +503,7 @@
|
||||
"emaillater": "",
|
||||
"employees": "",
|
||||
"estimators": "",
|
||||
"filehandlers": "",
|
||||
"insurancecos": "",
|
||||
"intakechecklist": "",
|
||||
"jobstatuses": "",
|
||||
@@ -535,6 +536,7 @@
|
||||
"save": ""
|
||||
},
|
||||
"validation": {
|
||||
"centermustexist": "",
|
||||
"larsplit": "",
|
||||
"useremailmustexist": ""
|
||||
}
|
||||
@@ -1091,6 +1093,7 @@
|
||||
"addtoscoreboard": "",
|
||||
"allocate": "",
|
||||
"autoallocate": "",
|
||||
"changefilehandler": "",
|
||||
"changelaborrate": "",
|
||||
"changestatus": "Cambiar Estado",
|
||||
"changestimator": "",
|
||||
@@ -1205,6 +1208,7 @@
|
||||
"date_exported": "Exportado",
|
||||
"date_invoiced": "Facturado",
|
||||
"date_last_contacted": "",
|
||||
"date_next_contact": "",
|
||||
"date_open": "Abierto",
|
||||
"date_scheduled": "Programado",
|
||||
"ded_amt": "Deducible",
|
||||
@@ -1725,7 +1729,8 @@
|
||||
"new": ""
|
||||
},
|
||||
"errors": {
|
||||
"invalidphone": ""
|
||||
"invalidphone": "",
|
||||
"noattachedjobs": ""
|
||||
},
|
||||
"labels": {
|
||||
"archive": "",
|
||||
@@ -1735,6 +1740,7 @@
|
||||
"nojobs": "",
|
||||
"phonenumber": "",
|
||||
"presets": "",
|
||||
"recentonly": "",
|
||||
"selectmedia": "",
|
||||
"sentby": "",
|
||||
"typeamessage": "Enviar un mensaje...",
|
||||
@@ -1824,6 +1830,7 @@
|
||||
"receivebill": ""
|
||||
},
|
||||
"errors": {
|
||||
"associatedbills": "",
|
||||
"backordering": "",
|
||||
"creating": "Se encontró un error al crear el pedido de piezas."
|
||||
},
|
||||
@@ -1968,6 +1975,7 @@
|
||||
"zip": ""
|
||||
},
|
||||
"3rdpartypayer": "",
|
||||
"ab_proof_of_loss": "",
|
||||
"appointment_confirmation": "",
|
||||
"appointment_reminder": "",
|
||||
"casl_authorization": "",
|
||||
@@ -1985,6 +1993,7 @@
|
||||
"fippa_authorization": "",
|
||||
"glass_express_checklist": "",
|
||||
"guarantee": "",
|
||||
"individual_job_note": "",
|
||||
"invoice_customer_payable": "",
|
||||
"invoice_total_payable": "",
|
||||
"iou_form": "",
|
||||
@@ -2023,7 +2032,8 @@
|
||||
"worksheet_by_line_number": "",
|
||||
"worksheet_sorted_by_operation": "",
|
||||
"worksheet_sorted_by_operation_no_hours": "",
|
||||
"worksheet_sorted_by_operation_part_type": ""
|
||||
"worksheet_sorted_by_operation_part_type": "",
|
||||
"worksheet_sorted_by_operation_type": ""
|
||||
},
|
||||
"labels": {
|
||||
"groups": {
|
||||
@@ -2068,20 +2078,31 @@
|
||||
},
|
||||
"errors": {
|
||||
"boardupdate": "",
|
||||
"removing": ""
|
||||
"removing": "",
|
||||
"settings": ""
|
||||
},
|
||||
"labels": {
|
||||
"alert": "",
|
||||
"alertoff": "",
|
||||
"alerton": "",
|
||||
"ats": "",
|
||||
"bodyhours": "",
|
||||
"bodypriority": "",
|
||||
"cardsettings": "",
|
||||
"clm_no": "",
|
||||
"compact": "",
|
||||
"detailpriority": "",
|
||||
"employeeassignments": "",
|
||||
"employeesearch": "",
|
||||
"ins_co_nm": "",
|
||||
"jobdetail": "",
|
||||
"laborhrs": "",
|
||||
"note": "",
|
||||
"ownr_nm": "",
|
||||
"paintpriority": "",
|
||||
"production_note": "",
|
||||
"refinishhours": "",
|
||||
"scheduled_completion": "",
|
||||
"selectview": "",
|
||||
"sublets": "",
|
||||
"totalhours": "",
|
||||
@@ -2176,6 +2197,7 @@
|
||||
"open_orders_csr": "",
|
||||
"open_orders_estimator": "",
|
||||
"open_orders_ins_co": "",
|
||||
"open_orders_status": "",
|
||||
"parts_backorder": "",
|
||||
"parts_not_recieved": "",
|
||||
"payments_by_date": "",
|
||||
|
||||
@@ -503,6 +503,7 @@
|
||||
"emaillater": "",
|
||||
"employees": "",
|
||||
"estimators": "",
|
||||
"filehandlers": "",
|
||||
"insurancecos": "",
|
||||
"intakechecklist": "",
|
||||
"jobstatuses": "",
|
||||
@@ -535,6 +536,7 @@
|
||||
"save": ""
|
||||
},
|
||||
"validation": {
|
||||
"centermustexist": "",
|
||||
"larsplit": "",
|
||||
"useremailmustexist": ""
|
||||
}
|
||||
@@ -1091,6 +1093,7 @@
|
||||
"addtoscoreboard": "",
|
||||
"allocate": "",
|
||||
"autoallocate": "",
|
||||
"changefilehandler": "",
|
||||
"changelaborrate": "",
|
||||
"changestatus": "Changer le statut",
|
||||
"changestimator": "",
|
||||
@@ -1205,6 +1208,7 @@
|
||||
"date_exported": "Exportés",
|
||||
"date_invoiced": "Facturé",
|
||||
"date_last_contacted": "",
|
||||
"date_next_contact": "",
|
||||
"date_open": "Ouvrir",
|
||||
"date_scheduled": "Prévu",
|
||||
"ded_amt": "Déductible",
|
||||
@@ -1725,7 +1729,8 @@
|
||||
"new": ""
|
||||
},
|
||||
"errors": {
|
||||
"invalidphone": ""
|
||||
"invalidphone": "",
|
||||
"noattachedjobs": ""
|
||||
},
|
||||
"labels": {
|
||||
"archive": "",
|
||||
@@ -1735,6 +1740,7 @@
|
||||
"nojobs": "",
|
||||
"phonenumber": "",
|
||||
"presets": "",
|
||||
"recentonly": "",
|
||||
"selectmedia": "",
|
||||
"sentby": "",
|
||||
"typeamessage": "Envoyer un message...",
|
||||
@@ -1824,6 +1830,7 @@
|
||||
"receivebill": ""
|
||||
},
|
||||
"errors": {
|
||||
"associatedbills": "",
|
||||
"backordering": "",
|
||||
"creating": "Erreur rencontrée lors de la création de la commande de pièces."
|
||||
},
|
||||
@@ -1968,6 +1975,7 @@
|
||||
"zip": ""
|
||||
},
|
||||
"3rdpartypayer": "",
|
||||
"ab_proof_of_loss": "",
|
||||
"appointment_confirmation": "",
|
||||
"appointment_reminder": "",
|
||||
"casl_authorization": "",
|
||||
@@ -1985,6 +1993,7 @@
|
||||
"fippa_authorization": "",
|
||||
"glass_express_checklist": "",
|
||||
"guarantee": "",
|
||||
"individual_job_note": "",
|
||||
"invoice_customer_payable": "",
|
||||
"invoice_total_payable": "",
|
||||
"iou_form": "",
|
||||
@@ -2023,7 +2032,8 @@
|
||||
"worksheet_by_line_number": "",
|
||||
"worksheet_sorted_by_operation": "",
|
||||
"worksheet_sorted_by_operation_no_hours": "",
|
||||
"worksheet_sorted_by_operation_part_type": ""
|
||||
"worksheet_sorted_by_operation_part_type": "",
|
||||
"worksheet_sorted_by_operation_type": ""
|
||||
},
|
||||
"labels": {
|
||||
"groups": {
|
||||
@@ -2068,20 +2078,31 @@
|
||||
},
|
||||
"errors": {
|
||||
"boardupdate": "",
|
||||
"removing": ""
|
||||
"removing": "",
|
||||
"settings": ""
|
||||
},
|
||||
"labels": {
|
||||
"alert": "",
|
||||
"alertoff": "",
|
||||
"alerton": "",
|
||||
"ats": "",
|
||||
"bodyhours": "",
|
||||
"bodypriority": "",
|
||||
"cardsettings": "",
|
||||
"clm_no": "",
|
||||
"compact": "",
|
||||
"detailpriority": "",
|
||||
"employeeassignments": "",
|
||||
"employeesearch": "",
|
||||
"ins_co_nm": "",
|
||||
"jobdetail": "",
|
||||
"laborhrs": "",
|
||||
"note": "",
|
||||
"ownr_nm": "",
|
||||
"paintpriority": "",
|
||||
"production_note": "",
|
||||
"refinishhours": "",
|
||||
"scheduled_completion": "",
|
||||
"selectview": "",
|
||||
"sublets": "",
|
||||
"totalhours": "",
|
||||
@@ -2176,6 +2197,7 @@
|
||||
"open_orders_csr": "",
|
||||
"open_orders_estimator": "",
|
||||
"open_orders_ins_co": "",
|
||||
"open_orders_status": "",
|
||||
"parts_backorder": "",
|
||||
"parts_not_recieved": "",
|
||||
"payments_by_date": "",
|
||||
|
||||
@@ -12,7 +12,9 @@ export function DateFormatter(props) {
|
||||
|
||||
export function DateTimeFormatter(props) {
|
||||
return props.children
|
||||
? moment(props.children).format("MM/DD/YYYY hh:mm a")
|
||||
? moment(props.children).format(
|
||||
props.format ? props.format : "MM/DD/YYYY hh:mm a"
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
@@ -182,6 +182,18 @@ export const TemplateList = (type, context) => {
|
||||
disabled: false,
|
||||
group: "worksheet",
|
||||
},
|
||||
worksheet_sorted_by_operation_type: {
|
||||
title: i18n.t(
|
||||
"printcenter.jobs.worksheet_sorted_by_operation_type"
|
||||
),
|
||||
description: "All Jobs Notes",
|
||||
subject: i18n.t(
|
||||
"printcenter.jobs.worksheet_sorted_by_operation_type"
|
||||
),
|
||||
key: "worksheet_sorted_by_operation_type",
|
||||
disabled: false,
|
||||
group: "worksheet",
|
||||
},
|
||||
worksheet_sorted_by_operation: {
|
||||
title: i18n.t("printcenter.jobs.worksheet_sorted_by_operation"),
|
||||
description: "All Jobs Notes",
|
||||
@@ -407,6 +419,17 @@ export const TemplateList = (type, context) => {
|
||||
CA_MB: true,
|
||||
},
|
||||
},
|
||||
ab_proof_of_loss: {
|
||||
title: i18n.t("printcenter.jobs.ab_proof_of_loss"),
|
||||
description: "Thank You Letter by RO",
|
||||
key: "ab_proof_of_loss",
|
||||
subject: i18n.t("printcenter.jobs.ab_proof_of_loss"),
|
||||
disabled: false,
|
||||
group: "pre",
|
||||
regions: {
|
||||
CA_AB: true,
|
||||
},
|
||||
},
|
||||
// parts_label_multi: {
|
||||
// title: i18n.t("printcenter.jobs.parts_label_multi"),
|
||||
// description: "Thank You Letter by RO",
|
||||
@@ -440,6 +463,15 @@ export const TemplateList = (type, context) => {
|
||||
subject: i18n.t("printcenter.jobs.csi_invitation_action"),
|
||||
disabled: false,
|
||||
},
|
||||
individual_job_note: {
|
||||
title: i18n.t("printcenter.jobs.individual_job_note"),
|
||||
description: "CSI invite",
|
||||
key: "individual_job_note",
|
||||
subject: i18n.t("printcenter.jobs.individual_job_note", {
|
||||
ro_number: (context && context.ro_number) || "",
|
||||
}),
|
||||
disabled: false,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(!type || type === "appointment"
|
||||
@@ -1181,6 +1213,19 @@ export const TemplateList = (type, context) => {
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
open_orders_status: {
|
||||
title: i18n.t("reportcenter.templates.open_orders_status"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.open_orders_status"),
|
||||
key: "open_orders_status",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
open_orders_csr: {
|
||||
title: i18n.t("reportcenter.templates.open_orders_csr"),
|
||||
description: "",
|
||||
|
||||
2144
client/yarn.lock
2144
client/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -203,6 +203,7 @@
|
||||
- authlevel
|
||||
- default_prod_list_view
|
||||
- id
|
||||
- kanban_settings
|
||||
- qbo_realmId
|
||||
- shopid
|
||||
- useremail
|
||||
@@ -217,6 +218,7 @@
|
||||
- active
|
||||
- authlevel
|
||||
- default_prod_list_view
|
||||
- kanban_settings
|
||||
- qbo_realmId
|
||||
filter:
|
||||
bodyshop:
|
||||
@@ -828,6 +830,7 @@
|
||||
- md_classes
|
||||
- md_ded_notes
|
||||
- md_estimators
|
||||
- md_filehandlers
|
||||
- md_hour_split
|
||||
- md_ins_cos
|
||||
- md_jobline_presets
|
||||
@@ -906,6 +909,7 @@
|
||||
- md_classes
|
||||
- md_ded_notes
|
||||
- md_estimators
|
||||
- md_filehandlers
|
||||
- md_hour_split
|
||||
- md_ins_cos
|
||||
- md_jobline_presets
|
||||
@@ -2590,6 +2594,7 @@
|
||||
- date_exported
|
||||
- date_invoiced
|
||||
- date_last_contacted
|
||||
- date_next_contact
|
||||
- date_open
|
||||
- date_scheduled
|
||||
- ded_amt
|
||||
@@ -2841,6 +2846,7 @@
|
||||
- date_exported
|
||||
- date_invoiced
|
||||
- date_last_contacted
|
||||
- date_next_contact
|
||||
- date_open
|
||||
- date_scheduled
|
||||
- ded_amt
|
||||
@@ -3102,6 +3108,7 @@
|
||||
- date_exported
|
||||
- date_invoiced
|
||||
- date_last_contacted
|
||||
- date_next_contact
|
||||
- date_open
|
||||
- date_scheduled
|
||||
- ded_amt
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."bodyshops" add column "md_filehandlers" jsonb
|
||||
-- null default jsonb_build_array();
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."bodyshops" add column "md_filehandlers" jsonb
|
||||
null default jsonb_build_array();
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||
-- null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||
null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" alter column "date_next_contact" drop not null;
|
||||
alter table "public"."jobs" add column "date_next_contact" timestamptz;
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."jobs" drop column "date_next_contact" cascade;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||
-- null;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."jobs" add column "date_next_contact" timestamptz
|
||||
null;
|
||||
@@ -0,0 +1,4 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."associations" add column "kanban_settings" jsonb
|
||||
-- null default jsonb_build_object();
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."associations" add column "kanban_settings" jsonb
|
||||
null default jsonb_build_object();
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."associations" alter column "kanban_settings" set default jsonb_build_object();
|
||||
@@ -0,0 +1 @@
|
||||
alter table "public"."associations" alter column "kanban_settings" set default '{"ats": true, "clm_no": true, "compact": false, "ownr_nm": true, "sublets": true, "ins_co_nm": true, "production_note": true, "employeeassignments": true, "scheduled_completion": true}';
|
||||
20
package.json
20
package.json
@@ -17,7 +17,8 @@
|
||||
"start": "node server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"aws-sdk": "^2.1013.0",
|
||||
"aws-sdk": "^2.1028.0",
|
||||
"axios": "^0.24.0",
|
||||
"bluebird": "^3.7.2",
|
||||
"body-parser": "^1.18.3",
|
||||
"cloudinary": "^1.27.1",
|
||||
@@ -28,25 +29,24 @@
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "10.0.0",
|
||||
"express": "^4.16.4",
|
||||
"firebase-admin": "^9.12.0",
|
||||
"graphql": "^15.6.1",
|
||||
"firebase-admin": "^10.0.0",
|
||||
"graphql": "^16.0.1",
|
||||
"graphql-request": "^3.6.1",
|
||||
"graylog2": "^0.2.1",
|
||||
"inline-css": "^3.0.0",
|
||||
"intuit-oauth": "^4.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"moment": "^2.29.1",
|
||||
"node-fetch": "^2.6.1",
|
||||
"node-mailjet": "^3.3.4",
|
||||
"node-quickbooks": "^2.0.39",
|
||||
"nodemailer": "^6.7.0",
|
||||
"phone": "^3.1.8",
|
||||
"nodemailer": "^6.7.1",
|
||||
"phone": "^3.1.9",
|
||||
"query-string": "^7.0.1",
|
||||
"soap": "^0.42.0",
|
||||
"socket.io": "^4.3.1",
|
||||
"soap": "^0.43.0",
|
||||
"socket.io": "^4.3.2",
|
||||
"ssh2-sftp-client": "^7.1.0",
|
||||
"stripe": "^8.184.0",
|
||||
"twilio": "^3.70.0",
|
||||
"stripe": "^8.188.0",
|
||||
"twilio": "^3.71.1",
|
||||
"uuid": "^8.3.2",
|
||||
"xmlbuilder2": "^3.0.2"
|
||||
},
|
||||
|
||||
@@ -5,7 +5,6 @@ const path = require("path");
|
||||
const compression = require("compression");
|
||||
const twilio = require("twilio");
|
||||
const logger = require("./server/utils/logger");
|
||||
global.fetch = require("node-fetch");
|
||||
var fb = require("./server/firebase/firebase-handler");
|
||||
var cookieParser = require("cookie-parser");
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ require("dotenv").config({
|
||||
`.env.${process.env.NODE_ENV || "development"}`
|
||||
),
|
||||
});
|
||||
const CdkBase = require("../web-sockets/web-socket");
|
||||
|
||||
const IMEX_PBS_USER = process.env.IMEX_PBS_USER,
|
||||
IMEX_PBS_PASSWORD = process.env.IMEX_PBS_PASSWORD;
|
||||
@@ -19,3 +18,13 @@ exports.PBS_CREDENTIALS = PBS_CREDENTIALS;
|
||||
// process.env.NODE_ENV === "production"
|
||||
// ? "https://3pa.dmotorworks.com"
|
||||
// : "https://uat-3pa.dmotorworks.com";
|
||||
|
||||
const pbsDomain = `https://partnerhub.pbsdealers.com/json/reply`;
|
||||
exports.PBS_ENDPOINTS = {
|
||||
AccountGet: `${pbsDomain}/AccountGet`,
|
||||
ContactGet: `${pbsDomain}/ContactGet`,
|
||||
VehicleGet: `${pbsDomain}/VehicleGet`,
|
||||
AccountingPostingChange: `${pbsDomain}/AccountingPostingChange`,
|
||||
ContactChange: `${pbsDomain}/ContactChange`,
|
||||
VehicleChange: `${pbsDomain}/VehicleChange`,
|
||||
};
|
||||
|
||||
@@ -6,25 +6,48 @@ require("dotenv").config({
|
||||
),
|
||||
});
|
||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||
const soap = require("soap");
|
||||
const axios = require("axios").default;
|
||||
const queries = require("../../graphql-client/queries");
|
||||
const CdkBase = require("../../web-sockets/web-socket");
|
||||
const { PBS_ENDPOINTS, PBS_CREDENTIALS } = require("./pbs-constants");
|
||||
|
||||
//const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl");
|
||||
//const CalcualteAllocations = require("./cdk-calculate-allocations").default;
|
||||
|
||||
const CalculateAllocations =
|
||||
require("../../cdk/cdk-calculate-allocations").default;
|
||||
const CdkBase = require("../../web-sockets/web-socket");
|
||||
const moment = require("moment");
|
||||
|
||||
exports.default = async function (socket, jobid) {
|
||||
exports.default = async function (socket, { txEnvelope, jobid }) {
|
||||
socket.logEvents = [];
|
||||
socket.recordid = jobid;
|
||||
|
||||
socket.txEnvelope = txEnvelope;
|
||||
try {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`Received Job export request for id ${jobid}`
|
||||
);
|
||||
|
||||
const JobData = await QueryJobData(socket, jobid);
|
||||
socket.JobData = JobData;
|
||||
|
||||
//Query for the Vehicle record to get the associated customer.
|
||||
// socket.DmsVeh = await QueryVehicleFromDms(socket);
|
||||
//Todo: Need to validate the lines and methods below.
|
||||
if (socket.DmsVeh && socket.DmsVeh.CustomerRef) {
|
||||
//Get the associated customer from the Vehicle Record.
|
||||
socket.DMSVehCustomer = await QueryCustomerBycodeFromDms(
|
||||
socket,
|
||||
socket.DmsVeh.CustomerRef
|
||||
);
|
||||
}
|
||||
socket.DMSCustList = await QueryCustomersFromDms(socket);
|
||||
|
||||
socket.emit("pbs-select-customer", [
|
||||
...(socket.DMSVehCustomer
|
||||
? [{ ...socket.DMSVehCustomer, vinOwner: true }]
|
||||
: []),
|
||||
...socket.DMSCustList,
|
||||
]);
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
@@ -33,3 +56,570 @@ exports.default = async function (socket, jobid) {
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
exports.PbsSelectedCustomer = async function PbsSelectedCustomer(
|
||||
socket,
|
||||
selectedCustomerId
|
||||
) {
|
||||
try {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`User selected customer ${selectedCustomerId || "NEW"}`
|
||||
);
|
||||
|
||||
//Upsert the contact information as per Wafaa's Email.
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`Upserting contact information to DMS for ${socket.JobData.ownr_fn} ${socket.JobData.ownr_ln} ${socket.JobData.ownr_co_nm}`
|
||||
);
|
||||
const ownerRef = await UpsertContactData(socket, selectedCustomerId);
|
||||
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`Upserting vehicle information to DMS for ${socket.JobData.v_vin}`
|
||||
);
|
||||
await UpsertVehicleData(socket, ownerRef.ReferenceId);
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Inserting account data.`);
|
||||
await InsertAccountPostingData(socket);
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Marking job as exported.`);
|
||||
// await MarkJobExported(socket, socket.JobData.id);
|
||||
|
||||
socket.emit("export-success", socket.JobData.id);
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error encountered in CdkSelectedCustomer. ${error}`
|
||||
);
|
||||
await InsertFailedExportLog(socket, error);
|
||||
}
|
||||
};
|
||||
|
||||
async function CheckForErrors(socket, response) {
|
||||
if (response.WasSuccessful === undefined || response.WasSuccessful === true) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`Succesful response from DMS. ${response.Message || ""}`
|
||||
);
|
||||
} else {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error received from DMS: ${response.Message}`
|
||||
);
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"TRACE",
|
||||
`Error received from DMS: ${JSON.stringify(response)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async function QueryJobData(socket, jobid) {
|
||||
CdkBase.createLogEvent(socket, "DEBUG", `Querying job data for id ${jobid}`);
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.QUERY_JOBS_FOR_PBS_EXPORT, { id: jobid });
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"TRACE",
|
||||
`Job data query result ${JSON.stringify(result, null, 2)}`
|
||||
);
|
||||
return result.jobs_by_pk;
|
||||
}
|
||||
|
||||
async function QueryVehicleFromDms(socket) {
|
||||
try {
|
||||
const { data: VehicleGetResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.VehicleGet,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
// VehicleId: "00000000000000000000000000000000",
|
||||
// Year: "String",
|
||||
// Make: "String",
|
||||
// Model: "String",
|
||||
// Trim: "String",
|
||||
// ModelNumber: "String",
|
||||
// StockNumber: "String",
|
||||
VIN: socket.JobData.v_vin,
|
||||
// LicenseNumber: "String",
|
||||
// Lot: "String",
|
||||
// Status: "String",
|
||||
// StatusList: ["String"],
|
||||
// OwnerRef: "00000000000000000000000000000000",
|
||||
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||
// LastSaleSince: "0001-01-01T00:00:00.0000000Z",
|
||||
// VehicleIDList: ["00000000000000000000000000000000"],
|
||||
// IncludeInactive: false,
|
||||
// IncludeBuildVehicles: false,
|
||||
// ShortVIN: "String",
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS }
|
||||
);
|
||||
CheckForErrors(socket, VehicleGetResponse);
|
||||
return VehicleGetResponse;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error in QueryVehicleFromDms - ${error}`
|
||||
);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
async function QueryCustomersFromDms(socket) {
|
||||
try {
|
||||
const { data: CustomerGetResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.ContactGet,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
//ContactId: "00000000000000000000000000000000",
|
||||
ContactCode: socket.JobData.owner.accountingid,
|
||||
FirstName: socket.JobData.ownr_co_nm
|
||||
? socket.JobData.ownr_co_nm
|
||||
: socket.JobData.ownr_fn,
|
||||
LastName: socket.JobData.ownr_ln,
|
||||
PhoneNumber: socket.JobData.ownr_ph1,
|
||||
// EmailAddress: "String",
|
||||
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||
// ContactIdList: ["00000000000000000000000000000000"],
|
||||
// IncludeInactive: false,
|
||||
// PayableAccount: "String",
|
||||
// ReceivableAccount: "String",
|
||||
// DriverLicense: "String",
|
||||
// ZipCode: "String",
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS }
|
||||
);
|
||||
CheckForErrors(socket, CustomerGetResponse);
|
||||
return CustomerGetResponse && CustomerGetResponse.Contacts;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error in QueryCustomersFromDms - ${error}`
|
||||
);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
async function QueryCustomerBycodeFromDms(socket, CustomerRef) {
|
||||
try {
|
||||
const { data: CustomerGetResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.ContactGet,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
ContactId: CustomerRef,
|
||||
//ContactCode: socket.JobData.owner.accountingid,
|
||||
//FirstName: socket.JobData.ownr_co_nm
|
||||
// ? socket.JobData.ownr_co_nm
|
||||
// : socket.JobData.ownr_fn,
|
||||
//LastName: socket.JobData.ownr_ln,
|
||||
//PhoneNumber: socket.JobData.ownr_ph1,
|
||||
// EmailAddress: "String",
|
||||
// ModifiedSince: "0001-01-01T00:00:00.0000000Z",
|
||||
// ModifiedUntil: "0001-01-01T00:00:00.0000000Z",
|
||||
// ContactIdList: ["00000000000000000000000000000000"],
|
||||
// IncludeInactive: false,
|
||||
// PayableAccount: "String",
|
||||
// ReceivableAccount: "String",
|
||||
// DriverLicense: "String",
|
||||
// ZipCode: "String",
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS }
|
||||
);
|
||||
CheckForErrors(socket, CustomerGetResponse);
|
||||
return CustomerGetResponse && CustomerGetResponse.Contacts;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error in QueryCustomersFromDms - ${error}`
|
||||
);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function UpsertContactData(socket, selectedCustomerId) {
|
||||
try {
|
||||
const { data: ContactChangeResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.ContactChange,
|
||||
{
|
||||
ContactInfo: {
|
||||
// Id: socket.JobData.owner.id,
|
||||
...(selectedCustomerId ? { ContactId: selectedCustomerId } : {}),
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
Code: socket.JobData.owner.accountingid,
|
||||
...(socket.JobData.ownr_co_nm
|
||||
? {
|
||||
//LastName: socket.JobData.ownr_ln,
|
||||
FirstName: socket.JobData.ownr_co_nm,
|
||||
IsBusiness: true,
|
||||
}
|
||||
: {
|
||||
LastName: socket.JobData.ownr_ln,
|
||||
FirstName: socket.JobData.ownr_fn,
|
||||
IsBusiness: false,
|
||||
}),
|
||||
|
||||
//Salutation: "String",
|
||||
//MiddleName: "String",
|
||||
//ContactName: "String",
|
||||
IsInactive: false,
|
||||
|
||||
//ApartmentNumber: "String",
|
||||
Address: socket.JobData.ownr_addr1,
|
||||
City: socket.JobData.ownr_city,
|
||||
//County: socket.JobData.ownr_addr1,
|
||||
State: socket.JobData.ownr_st,
|
||||
ZipCode: socket.JobData.ownr_zip,
|
||||
//BusinessPhone: "String",
|
||||
//BusinessPhoneExt: "String",
|
||||
HomePhone: socket.JobData.ownr_ph2,
|
||||
CellPhone: socket.JobData.ownr_ph1,
|
||||
//BusinessPhoneRawReverse: "String",
|
||||
//HomePhoneRawReverse: "String",
|
||||
//CellPhoneRawReverse: "String",
|
||||
//FaxNumber: "String",
|
||||
EmailAddress: socket.JobData.ownr_ea,
|
||||
//Notes: "String",
|
||||
//CriticalMemo: "String",
|
||||
//BirthDate: "0001-01-01T00:00:00.0000000Z",
|
||||
// Gender: "String",
|
||||
// DriverLicense: "String",
|
||||
//PreferredContactMethods: ["String"],
|
||||
// LastUpdate: "0001-01-01T00:00:00.0000000Z",
|
||||
// CustomFields: [{ Key: "String", Value: "String", Type: "String" }],
|
||||
// FleetType: "String",
|
||||
// CommunicationPreferences: {
|
||||
// Email: "String",
|
||||
// Phone: "String",
|
||||
// TextMessage: "String",
|
||||
// Letter: "String",
|
||||
// Preferred: "String",
|
||||
// },
|
||||
// SalesRepRef: "00000000000000000000000000000000",
|
||||
// Language: "String",
|
||||
// PayableAccount: "String",
|
||||
// ReceivableAccount: "String",
|
||||
// IsStatic: false,
|
||||
// PrimaryImageRef: "00000000000000000000000000000000",
|
||||
// PayableAccounts: [{ SerialNumber: "String", Account: "String" }],
|
||||
// ReceivableAccounts: [{ SerialNumber: "String", Account: "String" }],
|
||||
// ManufacturerLoyaltyNumber: "String",
|
||||
},
|
||||
IsAsynchronous: false,
|
||||
// UserRequest: "String",
|
||||
// UserRef: "00000000000000000000000000000000",
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS }
|
||||
);
|
||||
CheckForErrors(socket, ContactChangeResponse);
|
||||
return ContactChangeResponse;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error in UpsertContactData - ${error}`
|
||||
);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function UpsertVehicleData(socket, ownerRef) {
|
||||
try {
|
||||
const { data: VehicleChangeResponse } = await axios.post(
|
||||
PBS_ENDPOINTS.VehicleChange,
|
||||
{
|
||||
VehicleInfo: {
|
||||
//Id: "string/00000000-0000-0000-0000-000000000000",
|
||||
//VehicleId: "00000000000000000000000000000000",
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
//StockNumber: "String",
|
||||
VIN: socket.JobData.v_vin,
|
||||
LicenseNumber: socket.JobData.plate_no,
|
||||
//FleetNumber: "String",
|
||||
//Status: "String",
|
||||
OwnerRef: ownerRef, // "00000000000000000000000000000000",
|
||||
//ModelNumber: "String",
|
||||
Make: socket.JobData.v_make_desc,
|
||||
Model: socket.JobData.v_model_desc,
|
||||
//Trim: "String",
|
||||
//VehicleType: "String",
|
||||
Year: socket.JobData.v_model_yr,
|
||||
Odometer: socket.JobData.kmin,
|
||||
ExteriorColor: {
|
||||
Code: socket.JobData.v_color,
|
||||
//Description: "String",
|
||||
},
|
||||
// InteriorColor: { Code: "String", Description: "String" },
|
||||
//Engine: "String",
|
||||
// Cylinders: "String",
|
||||
// Transmission: "String",
|
||||
// DriveWheel: "String",
|
||||
// Fuel: "String",
|
||||
// Weight: 0,
|
||||
// InServiceDate: "0001-01-01T00:00:00.0000000Z",
|
||||
// LastServiceDate: "0001-01-01T00:00:00.0000000Z",
|
||||
// LastServiceMileage: 0,
|
||||
// Lot: "String",
|
||||
// LotDescription: "String",
|
||||
// Category: "String",
|
||||
// Options: [
|
||||
// {
|
||||
// Group: "String",
|
||||
// Code: "String",
|
||||
// Description: "String",
|
||||
// AdditionalInfo: "String",
|
||||
// Price: 0,
|
||||
// Cost: 0,
|
||||
// Residual: 0,
|
||||
// },
|
||||
// ],
|
||||
// Refurbishments: [
|
||||
// {
|
||||
// ReferenceNumber: "String",
|
||||
// Description: "String",
|
||||
// Price: 0,
|
||||
// Cost: 0,
|
||||
// Date: "0001-01-01T00:00:00.0000000Z",
|
||||
// ApplicationModel: "String",
|
||||
// },
|
||||
// ],
|
||||
// Order: {
|
||||
// InvoiceNumber: "String",
|
||||
// Price: 0,
|
||||
// Status: "String",
|
||||
// Eta: "String",
|
||||
// EstimatedCost: 0,
|
||||
// OrderDate: "String",
|
||||
// StatusDate: "String",
|
||||
// IgnitionKeyCode: "String",
|
||||
// DoorKeyCode: "String",
|
||||
// Description: "String",
|
||||
// LocationStatus: "String",
|
||||
// LocationStatusDate: "0001-01-01T00:00:00.0000000Z",
|
||||
// },
|
||||
// MSR: 0,
|
||||
// BaseMSR: 0,
|
||||
// Retail: 0,
|
||||
// DateReceived: "0001-01-01T00:00:00.0000000Z",
|
||||
// InternetPrice: 0,
|
||||
// Lotpack: 0,
|
||||
// Holdback: 0,
|
||||
// InternetNotes: "String",
|
||||
// Notes: "String",
|
||||
// CriticalMemo: "String",
|
||||
// IsCertified: false,
|
||||
// LastSaleDate: "0001-01-01T00:00:00.0000000Z",
|
||||
// LastUpdate: "0001-01-01T00:00:00.0000000Z",
|
||||
// AppraisedValue: 0,
|
||||
// Warranties: [
|
||||
// {
|
||||
// Type: "String",
|
||||
// CompanyName: "String",
|
||||
// CoveragePlan: "String",
|
||||
// Description: "String",
|
||||
// Price: 0,
|
||||
// Cost: 0,
|
||||
// Term: "String",
|
||||
// Deductible: 0,
|
||||
// PolicyNumber: "String",
|
||||
// StartDate: "String",
|
||||
// StartMileage: 0,
|
||||
// ExpirationDate: "String",
|
||||
// ExpirationMileage: 0,
|
||||
// },
|
||||
// ],
|
||||
// Freight: 0,
|
||||
// Air: 0,
|
||||
// Inventory: 0,
|
||||
// IsInactive: false,
|
||||
// CustomFields: [{ Key: "String", Value: "String", Type: "String" }],
|
||||
// FloorPlanCode: "String",
|
||||
// FloorPlanAmount: 0,
|
||||
// Insurance: {
|
||||
// Company: "String",
|
||||
// Policy: "String",
|
||||
// ExpiryDate: "0001-01-01T00:00:00.0000000Z",
|
||||
// AgentName: "String",
|
||||
// AgentPhoneNumber: "String",
|
||||
// },
|
||||
// Body: "String",
|
||||
// ShortVIN: "String",
|
||||
// AdditionalDrivers: ["00000000000000000000000000000000"],
|
||||
// OrderDetails: { Distributor: "String" },
|
||||
// PrimaryImageRef: "00000000000000000000000000000000",
|
||||
// Hold: {
|
||||
// VehicleRef: "00000000000000000000000000000000",
|
||||
// HoldFrom: "0001-01-01T00:00:00.0000000Z",
|
||||
// HoldUntil: "0001-01-01T00:00:00.0000000Z",
|
||||
// UserRef: "00000000000000000000000000000000",
|
||||
// ContactRef: "00000000000000000000000000000000",
|
||||
// Comments: "String",
|
||||
// },
|
||||
// SeatingCapacity: "String",
|
||||
// DeliveryDate: "0001-01-01T00:00:00.0000000Z",
|
||||
// WarrantyExpiry: "0001-01-01T00:00:00.0000000Z",
|
||||
// IsConditionallySold: false,
|
||||
// SalesDivision: 0,
|
||||
// StyleRef: "String",
|
||||
},
|
||||
IsAsynchronous: false,
|
||||
// UserRequest: "String",
|
||||
// UserRef: "00000000000000000000000000000000",
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS }
|
||||
);
|
||||
CheckForErrors(socket, VehicleChangeResponse);
|
||||
return VehicleChangeResponse;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error in UpsertVehicleData - ${error}`
|
||||
);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
async function InsertAccountPostingData(socket) {
|
||||
try {
|
||||
const allocations = await CalculateAllocations(socket, socket.JobData.id);
|
||||
|
||||
const wips = [];
|
||||
allocations.forEach((alloc) => {
|
||||
//Add the sale item from each allocation.
|
||||
if (alloc.sale.getAmount() > 0 && !alloc.tax) {
|
||||
const item = {
|
||||
Account: alloc.profitCenter.dms_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
Amount: alloc.sale.multiply(-1).toFormat("0.0"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||
};
|
||||
wips.push(item);
|
||||
}
|
||||
|
||||
//Add the cost Item.
|
||||
if (alloc.cost.getAmount() > 0 && !alloc.tax) {
|
||||
const item = {
|
||||
Account: alloc.costCenter.dms_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
Amount: alloc.cost.toFormat("0.0"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||
};
|
||||
wips.push(item);
|
||||
|
||||
const itemWip = {
|
||||
Account: alloc.costCenter.dms_wip_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
Amount: alloc.cost.multiply(-1).toFormat("0.0"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||
};
|
||||
wips.push(itemWip);
|
||||
//Add to the WIP account.
|
||||
}
|
||||
|
||||
if (alloc.tax) {
|
||||
if (alloc.sale.getAmount() > 0) {
|
||||
const item2 = {
|
||||
Account: alloc.profitCenter.dms_acctnumber,
|
||||
ControlNumber: socket.JobData.ro_number,
|
||||
Amount: alloc.sale.multiply(-1).toFormat("0.0"),
|
||||
//Comment: "String",
|
||||
//AdditionalInfo: "String",
|
||||
InvoiceNumber: socket.JobData.ro_number,
|
||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
||||
};
|
||||
wips.push(item2);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const { data: AccountPostingChange } = await axios.post(
|
||||
PBS_ENDPOINTS.AccountingPostingChange,
|
||||
{
|
||||
SerialNumber: socket.JobData.bodyshop.pbs_serialnumber,
|
||||
Posting: {
|
||||
Reference: socket.JobData.ro_number,
|
||||
JournalCode: socket.txEnvelope.journal,
|
||||
TransactionDate: moment(socket.JobData.date_invoiced).toISOString(), //"0001-01-01T00:00:00.0000000Z",
|
||||
Description: socket.txEnvelope.story,
|
||||
//AdditionalInfo: "String",
|
||||
Source: "ImEX Online",
|
||||
Lines: wips,
|
||||
},
|
||||
},
|
||||
{ auth: PBS_CREDENTIALS }
|
||||
);
|
||||
|
||||
CheckForErrors(socket, AccountPostingChange);
|
||||
return AccountPostingChange;
|
||||
} catch (error) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
`Error in InsertAccountPostingData - ${error}`
|
||||
);
|
||||
throw new Error(error);
|
||||
}
|
||||
}
|
||||
|
||||
async function MarkJobExported(socket, jobid) {
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`Marking job as exported for id ${jobid}`
|
||||
);
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.MARK_JOB_EXPORTED, {
|
||||
jobId: jobid,
|
||||
job: {
|
||||
status:
|
||||
socket.JobData.bodyshop.md_ro_statuses.default_exported ||
|
||||
"Exported*",
|
||||
date_exported: new Date(),
|
||||
},
|
||||
log: {
|
||||
bodyshopid: socket.JobData.bodyshop.id,
|
||||
jobid: jobid,
|
||||
successful: true,
|
||||
useremail: socket.user.email,
|
||||
},
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function InsertFailedExportLog(socket, error) {
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {});
|
||||
const result = await client
|
||||
.setHeaders({ Authorization: `Bearer ${socket.handshake.auth.token}` })
|
||||
.request(queries.INSERT_EXPORT_LOG, {
|
||||
log: {
|
||||
bodyshopid: socket.JobData.bodyshop.id,
|
||||
jobid: socket.JobData.id,
|
||||
successful: false,
|
||||
message: [error],
|
||||
useremail: socket.user.email,
|
||||
},
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -76,7 +76,12 @@ exports.default = function ({
|
||||
{
|
||||
local: false,
|
||||
federal: true,
|
||||
state: (jobline.db_ref === "900511" || jobline.db_ref === "900510") ? true: jobline.tax_part,
|
||||
state:
|
||||
jobs_by_pk.state_tax_rate === 0
|
||||
? false
|
||||
: jobline.db_ref === "900511" || jobline.db_ref === "900510"
|
||||
? true
|
||||
: jobline.tax_part,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
);
|
||||
@@ -142,7 +147,7 @@ exports.default = function ({
|
||||
{
|
||||
local: false,
|
||||
federal: true,
|
||||
state: true,
|
||||
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
);
|
||||
@@ -204,7 +209,7 @@ exports.default = function ({
|
||||
{
|
||||
local: false,
|
||||
federal: true,
|
||||
state: true,
|
||||
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
);
|
||||
@@ -267,7 +272,7 @@ exports.default = function ({
|
||||
{
|
||||
local: false,
|
||||
federal: true,
|
||||
state: true,
|
||||
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
);
|
||||
@@ -346,7 +351,7 @@ exports.default = function ({
|
||||
{
|
||||
local: false,
|
||||
federal: true,
|
||||
state: true,
|
||||
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
);
|
||||
@@ -394,7 +399,7 @@ exports.default = function ({
|
||||
{
|
||||
local: false,
|
||||
federal: true,
|
||||
state: true,
|
||||
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
);
|
||||
@@ -445,7 +450,7 @@ exports.default = function ({
|
||||
{
|
||||
local: false,
|
||||
federal: true,
|
||||
state: true,
|
||||
state: jobs_by_pk.state_tax_rate === 0 ? false : true,
|
||||
},
|
||||
bodyshop.md_responsibility_centers.sales_tax_codes
|
||||
);
|
||||
|
||||
@@ -152,7 +152,7 @@ const generatePayment = (payment, isThreeTier, twoTierPref) => {
|
||||
QBXML: {
|
||||
QBXMLMsgsRq: {
|
||||
"@onError": "continueOnError",
|
||||
wMemoAddRq: {
|
||||
CreditMemoAddRq: {
|
||||
CreditMemoAdd: {
|
||||
CustomerRef: {
|
||||
FullName: (payment.job.bodyshop.accountingconfig.tiers === 3
|
||||
|
||||
@@ -37,7 +37,6 @@ exports.default = async function ReloadCdkMakes(req, res) {
|
||||
const BearerToken = req.headers.authorization;
|
||||
//Query all CDK Models
|
||||
const newList = await GetCdkMakes(req, cdk_dealerid);
|
||||
console.log("🚀 ~ file: cdk-get-makes.js ~ line 40 ~ newList", newList);
|
||||
|
||||
//Clear out the existing records
|
||||
const client = new GraphQLClient(process.env.GRAPHQL_ENDPOINT, {
|
||||
@@ -69,10 +68,6 @@ exports.default = async function ReloadCdkMakes(req, res) {
|
||||
};
|
||||
}),
|
||||
});
|
||||
console.log(
|
||||
"🚀 ~ file: cdk-get-makes.js ~ line 66 ~ insertResult",
|
||||
insertResult
|
||||
);
|
||||
|
||||
logger.log(
|
||||
"cdk-replace-makes-models-success",
|
||||
@@ -121,9 +116,28 @@ async function GetCdkMakes(req, cdk_dealerid) {
|
||||
);
|
||||
|
||||
CheckCdkResponseForError(null, soapResponseVehicleSearch);
|
||||
const [
|
||||
result, //rawResponse, soapheader, rawRequest
|
||||
] = soapResponseVehicleSearch;
|
||||
const [result, rawResponse, , rawRequest] = soapResponseVehicleSearch;
|
||||
logger.log(
|
||||
"cdk-replace-makes-models-request",
|
||||
"ERROR",
|
||||
req.user.email,
|
||||
null,
|
||||
{
|
||||
cdk_dealerid,
|
||||
xml: rawRequest,
|
||||
}
|
||||
);
|
||||
|
||||
logger.log(
|
||||
"cdk-replace-makes-models-response",
|
||||
"ERROR",
|
||||
req.user.email,
|
||||
null,
|
||||
{
|
||||
cdk_dealerid,
|
||||
xml: rawResponse,
|
||||
}
|
||||
);
|
||||
|
||||
return result.return;
|
||||
} catch (error) {
|
||||
|
||||
@@ -180,7 +180,7 @@ async function CdkSelectedCustomer(socket, selectedCustomerId) {
|
||||
`{5} Updating Service Vehicle History.`
|
||||
);
|
||||
socket.DMSVehHistory = await InsertServiceVehicleHistory(socket);
|
||||
socket.emit("export-success", socket.JobData.id);
|
||||
// socket.emit("export-success", socket.JobData.id);
|
||||
} else {
|
||||
//Get the error code
|
||||
CdkBase.createLogEvent(
|
||||
@@ -607,23 +607,33 @@ async function InsertDmsCustomer(socket, newCustomerNumber) {
|
||||
},
|
||||
email: {
|
||||
desc: socket.JobData.ownr_ea ? "Other" : "CustomerDeclined",
|
||||
value: socket.JobData.ownr_ea ? "Other" : null,
|
||||
value: socket.JobData.ownr_ea ? socket.JobData.ownr_ea : null,
|
||||
},
|
||||
},
|
||||
demographics: null,
|
||||
name1: {
|
||||
companyname:
|
||||
companyName:
|
||||
socket.JobData.ownr_co_nm &&
|
||||
socket.JobData.ownr_co_nm.replace(replaceSpecialRegex, ""),
|
||||
socket.JobData.ownr_co_nm
|
||||
.replace(replaceSpecialRegex, "")
|
||||
.toUpperCase(),
|
||||
|
||||
firstName:
|
||||
socket.JobData.ownr_fn &&
|
||||
socket.JobData.ownr_fn.replace(replaceSpecialRegex, ""),
|
||||
socket.JobData.ownr_fn
|
||||
.replace(replaceSpecialRegex, "")
|
||||
.toUpperCase(),
|
||||
fullname: null,
|
||||
lastName:
|
||||
socket.JobData.ownr_ln &&
|
||||
socket.JobData.ownr_ln.replace(replaceSpecialRegex, ""),
|
||||
socket.JobData.ownr_ln
|
||||
.replace(replaceSpecialRegex, "")
|
||||
.toUpperCase(),
|
||||
middleName: null,
|
||||
nameType: "Person",
|
||||
nameType:
|
||||
socket.JobData.ownr_co_nm && socket.JobData.ownr_co_nm
|
||||
? "Business"
|
||||
: "Person",
|
||||
suffix: null,
|
||||
title: null,
|
||||
},
|
||||
@@ -700,6 +710,7 @@ async function InsertDmsVehicle(socket) {
|
||||
manufacturer: {},
|
||||
vehicle: {
|
||||
deliveryDate: moment().format("YYYYMMDD"),
|
||||
licensePlateNo: socket.JobData.plate_no,
|
||||
make: socket.txEnvelope.dms_make,
|
||||
modelAbrev: socket.txEnvelope.dms_model,
|
||||
modelYear: socket.JobData.v_model_yr,
|
||||
@@ -758,6 +769,31 @@ async function UpdateDmsVehicle(socket) {
|
||||
CdkWsdl.VehicleInsertUpdate
|
||||
);
|
||||
|
||||
let ids = [];
|
||||
|
||||
const existingOwnerinVeh = socket.DMSVeh.owners.filter(
|
||||
(o) => o.id.value === socket.DMSCust.id.value
|
||||
);
|
||||
|
||||
if (existingOwnerinVeh) {
|
||||
ids = socket.DMSVeh.owners.filter(
|
||||
(o) => o.id.value === socket.DMSCust.id.value
|
||||
);
|
||||
} else {
|
||||
ids = [
|
||||
{
|
||||
assigningPartyId: "CURRENT",
|
||||
value: socket.DMSCust.id.value,
|
||||
},
|
||||
...socket.DMSVeh.owners.map((o) => {
|
||||
return {
|
||||
assigningPartyId: "PREVIOUS",
|
||||
value: o.id.value,
|
||||
};
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
const soapResponseVehicleInsertUpdate =
|
||||
await soapClientVehicleInsertUpdate.updateAsync({
|
||||
arg0: CDK_CREDENTIALS,
|
||||
@@ -776,12 +812,7 @@ async function UpdateDmsVehicle(socket) {
|
||||
socket.DMSVeh.vehicle.deliveryDate
|
||||
).toISOString(),
|
||||
},
|
||||
owners: {
|
||||
id: {
|
||||
assigningPartyId: "CURRENT",
|
||||
value: socket.DMSCust.id.value,
|
||||
},
|
||||
},
|
||||
owners: { ids: ids },
|
||||
},
|
||||
arg3: "VEHICLES",
|
||||
});
|
||||
@@ -835,9 +866,9 @@ async function InsertServiceVehicleHistory(socket) {
|
||||
roNumber: socket.JobData.ro_number.match(/\d+/g),
|
||||
mileage: socket.txEnvelope.kmout,
|
||||
openDate: moment(socket.JobData.actual_in).format("YYYY-MM-DD"),
|
||||
openTime: moment(socket.JobData.actual_in).format("HH:MM:SS"),
|
||||
openTime: moment(socket.JobData.actual_in).format("HH:MM:ss"),
|
||||
closeDate: moment(socket.JobData.invoice_date).format("YYYY-MM-DD"),
|
||||
closeTime: moment(socket.JobData.invoice_date).format("HH:MM:SS"),
|
||||
closeTime: moment(socket.JobData.invoice_date).format("HH:MM:ss"),
|
||||
comments: socket.txEnvelope.story,
|
||||
cashierID: socket.JobData.bodyshop.cdk_configuration.cashierid,
|
||||
},
|
||||
|
||||
@@ -70,11 +70,15 @@ exports.default = async (req, res) => {
|
||||
}
|
||||
|
||||
var ret = builder
|
||||
.create(autoHouseObject, {
|
||||
version: "1.0",
|
||||
encoding: "UTF-8",
|
||||
})
|
||||
.end({ pretty: true, allowEmptyTags: true });
|
||||
.create(
|
||||
{
|
||||
version: "1.0",
|
||||
encoding: "UTF-8",
|
||||
keepNullNodes: true,
|
||||
},
|
||||
autoHouseObject
|
||||
)
|
||||
.end({ allowEmptyTags: true });
|
||||
|
||||
allxmlsToUpload.push({
|
||||
xml: ret,
|
||||
@@ -107,6 +111,11 @@ exports.default = async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
res.sendStatus(200);
|
||||
return;
|
||||
}
|
||||
|
||||
let sftp = new Client();
|
||||
sftp.on("error", (errors) =>
|
||||
logger.log("autohouse-sftp-error", "ERROR", "api", null, {
|
||||
@@ -239,7 +248,8 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
||||
ReferralDate: null,
|
||||
EstimateAppointmentDate: null,
|
||||
SecondFollowUpDate: null,
|
||||
AssignedDate: null,
|
||||
AssignedDate:
|
||||
job.asgn_date && moment(job.asgn_date).format(AhDateFormat),
|
||||
EstComplete: null,
|
||||
CustomerAuthorizationDate: null,
|
||||
InsuranceAuthorizationDate: null,
|
||||
@@ -248,7 +258,7 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
||||
job.scheduled_in && moment(job.scheduled_in).format(AhDateFormat),
|
||||
CarinShop: job.actual_in && moment(job.actual_in).format(AhDateFormat),
|
||||
InsInspDate: null,
|
||||
StartDate: null,
|
||||
StartDate: job.actual_in && moment(job.actual_in).format(AhDateFormat),
|
||||
PartsOrder: null,
|
||||
TeardownHold: null,
|
||||
SupplementSubmittedDate: null,
|
||||
@@ -287,7 +297,10 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
||||
StructuralRate: job.rate_las,
|
||||
PMRate: job.rate_mapa,
|
||||
BMRate: job.rate_mash,
|
||||
TaxRate: null,
|
||||
TaxRate:
|
||||
job.parts_tax_rates &&
|
||||
job.parts_tax_rates.PAN &&
|
||||
job.parts_tax_rates.PAN.prt_tax_rt,
|
||||
StorageRateperDay: null,
|
||||
DaysStored: null,
|
||||
},
|
||||
@@ -389,39 +402,45 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
||||
job.job_totals.parts.parts.list.PAA.total
|
||||
).toFormat(AHDineroFormat),
|
||||
PartsAMCost: repairCosts.PartsAMCost.toFormat(AHDineroFormat),
|
||||
PartsReconditioned: null,
|
||||
PartsReconditioned:
|
||||
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
|
||||
PartsReconditionedCost:
|
||||
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
|
||||
PartsRecycled: Dinero(
|
||||
job.job_totals.parts.parts.list.PAR &&
|
||||
job.job_totals.parts.parts.list.PAR.total
|
||||
).toFormat(AHDineroFormat),
|
||||
PartsRecycledCost: null,
|
||||
PartsRecycledCost:
|
||||
repairCosts.PartsRecycledCost.toFormat(AHDineroFormat),
|
||||
PartsOther: Dinero(
|
||||
job.job_totals.parts.parts.list.PAO &&
|
||||
job.job_totals.parts.parts.list.PAO.total
|
||||
).toFormat(AHDineroFormat),
|
||||
PartsOtherCost: null,
|
||||
PartsOtherCost: repairCosts.PartsOtherCost.toFormat(AHDineroFormat),
|
||||
SubletTotal: Dinero(job.job_totals.parts.sublets.total).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
SubletTotalCost: 0,
|
||||
SubletTotalCost: repairCosts.SubletTotalCost.toFormat(AHDineroFormat),
|
||||
BodyLaborTotal: Dinero(job.job_totals.rates.lab.total).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
BodyLaborTotalCost: 0,
|
||||
BodyLaborTotalCost:
|
||||
repairCosts.BodyLaborTotalCost.toFormat(AHDineroFormat),
|
||||
RefinishLaborTotal: Dinero(job.job_totals.rates.lar.total).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
RefinishLaborTotalCost: 0,
|
||||
RefinishLaborTotalCost:
|
||||
repairCosts.RefinishLaborTotalCost.toFormat(AHDineroFormat),
|
||||
MechanicalLaborTotal: Dinero(job.job_totals.rates.lam.total).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
MechanicalLaborTotalCost: 0,
|
||||
MechanicalLaborTotalCost:
|
||||
repairCosts.MechanicalLaborTotalCost.toFormat(AHDineroFormat),
|
||||
StructuralLaborTotal: Dinero(job.job_totals.rates.las.total).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
StructuralLaborTotalCost: null,
|
||||
StructuralLaborTotalCost:
|
||||
repairCosts.StructuralLaborTotalCost.toFormat(AHDineroFormat),
|
||||
MiscellaneousChargeTotal: null,
|
||||
MiscellaneousChargeTotalCost: null,
|
||||
PMTotal: Dinero(job.job_totals.rates.mapa.total).toFormat(
|
||||
@@ -437,11 +456,11 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
||||
TowingTotal: Dinero(job.job_totals.additional.towing).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
TowingTotalCost: null,
|
||||
TowingTotalCost: repairCosts.TowingTotalCost.toFormat(AHDineroFormat),
|
||||
StorageTotal: Dinero(job.job_totals.additional.storage).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
StorageTotalCost: null,
|
||||
StorageTotalCost: repairCosts.StorageTotalCost.toFormat(AHDineroFormat),
|
||||
DetailTotal: null,
|
||||
DetailTotalCost: null,
|
||||
SalesTaxTotal: Dinero(job.job_totals.totals.local_tax)
|
||||
@@ -472,7 +491,7 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
||||
Hub50Comment: null,
|
||||
DateofChange: null,
|
||||
BodyTechName: null,
|
||||
TotalLossYN: null,
|
||||
TotalLossYN: job.tlos_ind ? "Y" : "N",
|
||||
InsScreenCommentsLine1: null,
|
||||
InsScreenCommentsLine2: null,
|
||||
AssignmentCaller: null,
|
||||
@@ -483,7 +502,9 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
||||
PaintTechName: null,
|
||||
ImportType: null,
|
||||
ImportFile: null,
|
||||
GSTTax: null,
|
||||
GSTTax: Dinero(job.job_totals.totals.federal_tax).toFormat(
|
||||
AHDineroFormat
|
||||
),
|
||||
RepairDelayStatusCode: null,
|
||||
RepairDelaycomment: null,
|
||||
AgentMktgID: null,
|
||||
|
||||
@@ -126,6 +126,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
|
||||
towing_payable
|
||||
storage_payable
|
||||
adjustment_bottom_line
|
||||
state_tax_rate
|
||||
owner {
|
||||
accountingid
|
||||
}
|
||||
@@ -157,6 +158,94 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
|
||||
|
||||
exports.QUERY_JOBS_FOR_CDK_EXPORT = `
|
||||
query QUERY_JOBS_FOR_CDK_EXPORT($id: uuid!) {
|
||||
jobs_by_pk(id: $id) {
|
||||
id
|
||||
job_totals
|
||||
date_invoiced
|
||||
ro_number
|
||||
clm_total
|
||||
clm_no
|
||||
invoice_allocation
|
||||
ownerid
|
||||
ownr_ln
|
||||
ownr_fn
|
||||
ownr_co_nm
|
||||
ownr_addr1
|
||||
ownr_addr2
|
||||
ownr_ph1
|
||||
ownr_ph2
|
||||
ownr_zip
|
||||
ownr_city
|
||||
ownr_ctry
|
||||
ownr_st
|
||||
ownr_ea
|
||||
ins_co_nm
|
||||
job_totals
|
||||
rate_la1
|
||||
rate_la2
|
||||
rate_la3
|
||||
rate_la4
|
||||
rate_laa
|
||||
rate_lab
|
||||
rate_lad
|
||||
rate_lae
|
||||
rate_laf
|
||||
rate_lag
|
||||
rate_lam
|
||||
rate_lar
|
||||
rate_las
|
||||
rate_lau
|
||||
rate_ma2s
|
||||
rate_ma2t
|
||||
rate_ma3s
|
||||
rate_mabl
|
||||
rate_macs
|
||||
rate_mahw
|
||||
rate_mapa
|
||||
rate_mash
|
||||
rate_matd
|
||||
class
|
||||
ca_bc_pvrt
|
||||
plate_no
|
||||
plate_st
|
||||
v_vin
|
||||
v_model_yr
|
||||
v_model_desc
|
||||
v_make_desc
|
||||
v_color
|
||||
ca_customer_gst
|
||||
bodyshop {
|
||||
id
|
||||
md_ro_statuses
|
||||
md_responsibility_centers
|
||||
accountingconfig
|
||||
cdk_dealerid
|
||||
cdk_configuration
|
||||
}
|
||||
owner {
|
||||
accountingid
|
||||
}
|
||||
joblines(where:{removed: {_eq:false}}) {
|
||||
id
|
||||
line_desc
|
||||
part_type
|
||||
act_price
|
||||
mod_lb_hrs
|
||||
mod_lbr_ty
|
||||
part_qty
|
||||
op_code_desc
|
||||
profitcenter_labor
|
||||
profitcenter_part
|
||||
db_ref
|
||||
prt_dsmk_p
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
`;
|
||||
|
||||
exports.QUERY_JOBS_FOR_PBS_EXPORT = `
|
||||
query QUERY_JOBS_FOR_PBS_EXPORT($id: uuid!) {
|
||||
jobs_by_pk(id: $id) {
|
||||
id
|
||||
job_totals
|
||||
@@ -217,10 +306,11 @@ query QUERY_JOBS_FOR_CDK_EXPORT($id: uuid!) {
|
||||
md_ro_statuses
|
||||
md_responsibility_centers
|
||||
accountingconfig
|
||||
cdk_dealerid
|
||||
cdk_configuration
|
||||
pbs_serialnumber
|
||||
pbs_configuration
|
||||
}
|
||||
owner {
|
||||
id
|
||||
accountingid
|
||||
}
|
||||
joblines(where:{removed: {_eq:false}}) {
|
||||
@@ -465,6 +555,7 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshop
|
||||
rate_mash
|
||||
job_totals
|
||||
driveable
|
||||
parts_tax_rates
|
||||
bodyshop {
|
||||
id
|
||||
shopname
|
||||
|
||||
@@ -78,15 +78,17 @@ exports.receive = async (req, res) => {
|
||||
});
|
||||
}
|
||||
try {
|
||||
const r2 = await client.request(queries.RECEIVE_MESSAGE, {
|
||||
msg: newMessage,
|
||||
});
|
||||
if (response.bodyshops[0].conversations[0]) {
|
||||
const r3 = await client.request(queries.INSERT_MESSAGE, {
|
||||
id:
|
||||
msg: newMessage,
|
||||
conversationid:
|
||||
response.bodyshops[0].conversations[0] &&
|
||||
response.bodyshops[0].conversations[0].id,
|
||||
});
|
||||
} else {
|
||||
const r2 = await client.request(queries.RECEIVE_MESSAGE, {
|
||||
msg: newMessage,
|
||||
});
|
||||
}
|
||||
|
||||
logger.log("sms-inbound-success", "DEBUG", "api", null, {
|
||||
|
||||
@@ -17,7 +17,7 @@ const CdkCalculateAllocations =
|
||||
require("../cdk/cdk-calculate-allocations").default;
|
||||
const { isArray } = require("lodash");
|
||||
const logger = require("../utils/logger");
|
||||
const PbsExportJob = require("../accounting/pbs/pbs-job-export");
|
||||
const {default: PbsExportJob, PbsSelectedCustomer} = require("../accounting/pbs/pbs-job-export");
|
||||
|
||||
io.use(function (socket, next) {
|
||||
try {
|
||||
@@ -99,9 +99,29 @@ io.on("connection", (socket) => {
|
||||
//END CDK
|
||||
|
||||
//PBS
|
||||
socket.on("pbs-calculate-allocations", async (jobid, callback) => {
|
||||
const allocations = await CdkCalculateAllocations(socket, jobid);
|
||||
createLogEvent(socket, "DEBUG", `Allocations calculated.`);
|
||||
createLogEvent(
|
||||
socket,
|
||||
"TRACE",
|
||||
`Allocations calculated. ${JSON.stringify(allocations, null, 2)}`
|
||||
);
|
||||
|
||||
callback(allocations);
|
||||
});
|
||||
socket.on("pbs-export-job", (jobid) => {
|
||||
PbsExportJob(socket, jobid);
|
||||
});
|
||||
socket.on("pbs-selected-customer", (selectedCustomerId) => {
|
||||
createLogEvent(
|
||||
socket,
|
||||
"DEBUG",
|
||||
`User selected customer ID ${selectedCustomerId}`
|
||||
);
|
||||
socket.selectedCustomerId = selectedCustomerId;
|
||||
PbsSelectedCustomer(socket, selectedCustomerId);
|
||||
});
|
||||
//End PBS
|
||||
|
||||
socket.on("disconnect", () => {
|
||||
|
||||
118
yarn.lock
118
yarn.lock
@@ -600,10 +600,10 @@ atob@2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
|
||||
|
||||
aws-sdk@^2.1013.0:
|
||||
version "2.1013.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1013.0.tgz#85babc473b0bc90cc1160eb48baf616ddb86e346"
|
||||
integrity sha512-TXxkp/meAdofpC15goFpNuur7fvh/mcMRfHJoP1jYzTtD0wcoB4FK16GLcny0uDYgkQgZuiO9QYv3Rq5bhGCqQ==
|
||||
aws-sdk@^2.1028.0:
|
||||
version "2.1028.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1028.0.tgz#ce076076174afa9bd311406b8186ea90163e3331"
|
||||
integrity sha512-OmR0NcpU8zsDcUOZhM+eZ6CzlUFtuaEuRyjm6mxDO0KI7lJAp7/NzB6tcellRrgWxL+NO7b5TSxi+m28qu5ocQ==
|
||||
dependencies:
|
||||
buffer "4.9.2"
|
||||
events "1.1.1"
|
||||
@@ -625,12 +625,12 @@ aws4@^1.8.0:
|
||||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
|
||||
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
|
||||
|
||||
axios-ntlm@^1.1.6:
|
||||
version "1.1.7"
|
||||
resolved "https://registry.yarnpkg.com/axios-ntlm/-/axios-ntlm-1.1.7.tgz#996f87be748595519c7de93f8c93eacdb65465dc"
|
||||
integrity sha512-wWsjWHreHpzfhTPL6cD/H7SfUWDr5u8RQjdxsLg7byP2ozgnDvN9q/w5ozngwcTKAy4fmv6QOfzNxsLkzIIUMQ==
|
||||
axios-ntlm@^1.2.0:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/axios-ntlm/-/axios-ntlm-1.2.1.tgz#8facad74cdf5a53eab34fa2fe91c8d4358950ed4"
|
||||
integrity sha512-M8qLdkOjVSrYmzOs7sxc/Ynu54yT2YHVOLFiTxicwPnll0H+sP3fkEQHGgEzpBcH4UA/ovRgTioR/vjelUG35A==
|
||||
dependencies:
|
||||
axios "^0.21.1"
|
||||
axios "^0.21.3"
|
||||
|
||||
axios@^0.21.1:
|
||||
version "0.21.1"
|
||||
@@ -639,13 +639,20 @@ axios@^0.21.1:
|
||||
dependencies:
|
||||
follow-redirects "^1.10.0"
|
||||
|
||||
axios@^0.21.4:
|
||||
axios@^0.21.3, axios@^0.21.4:
|
||||
version "0.21.4"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
|
||||
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
axios@^0.24.0:
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.24.0.tgz#804e6fa1e4b9c5288501dd9dff56a7a0940d20d6"
|
||||
integrity sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.4"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
@@ -1146,7 +1153,7 @@ debug@2.6.9:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@~4.3.1, debug@~4.3.2:
|
||||
debug@4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.2, debug@~4.3.1, debug@~4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b"
|
||||
integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==
|
||||
@@ -1694,10 +1701,10 @@ finalhandler@~1.1.2:
|
||||
statuses "~1.5.0"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
firebase-admin@^9.12.0:
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-9.12.0.tgz#d7e889e97c9c31610efbcd131bb6d06a783af757"
|
||||
integrity sha512-AtA7OH5RbIFGoc0gZOQgaYC6cdjdhZv4w3XgWoupkPKO1HY+0GzixOuXDa75kFeoVyhIyo4PkLg/GAC1dC1P6w==
|
||||
firebase-admin@^10.0.0:
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-10.0.0.tgz#0638cd50d2395fddc9d8af4e1699d0a10b1b22d8"
|
||||
integrity sha512-EOAk5ZaqXhBBvx9ZyXd28kw8glMTt3xl0g3BepGRCy0RSSUPGOzfAqjGhc65guSKgFOpT5mAUycYcJbqullKUQ==
|
||||
dependencies:
|
||||
"@firebase/database-compat" "^0.1.1"
|
||||
"@firebase/database-types" "^0.7.2"
|
||||
@@ -1743,6 +1750,11 @@ follow-redirects@^1.14.0:
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
|
||||
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
|
||||
|
||||
follow-redirects@^1.14.4:
|
||||
version "1.14.5"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381"
|
||||
integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==
|
||||
|
||||
forever-agent@~0.6.1:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
|
||||
@@ -1973,10 +1985,10 @@ graphql-request@^3.6.1:
|
||||
extract-files "^9.0.0"
|
||||
form-data "^3.0.0"
|
||||
|
||||
graphql@^15.6.1:
|
||||
version "15.6.1"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.6.1.tgz#9125bdf057553525da251e19e96dab3d3855ddfc"
|
||||
integrity sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw==
|
||||
graphql@^16.0.1:
|
||||
version "16.0.1"
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.0.1.tgz#93a13cd4e0e38ca8d0832e79614c8578bfd34f10"
|
||||
integrity sha512-oPvCuu6dlLdiz8gZupJ47o1clgb72r1u8NDBcQYjcV6G/iEdmE11B1bBlkhXRvV0LisP/SXRFP7tT6AgaTjpzg==
|
||||
|
||||
graylog2@^0.2.1:
|
||||
version "0.2.1"
|
||||
@@ -2103,19 +2115,6 @@ http-signature@~1.2.0:
|
||||
jsprim "^1.2.2"
|
||||
sshpk "^1.7.0"
|
||||
|
||||
httpntlm@^1.5.2:
|
||||
version "1.7.7"
|
||||
resolved "https://registry.yarnpkg.com/httpntlm/-/httpntlm-1.7.7.tgz#51b914f18e5de2868d4bfe50aeecdb1db23218a1"
|
||||
integrity sha512-Pv2Rvrz8H0qv1Dne5mAdZ9JegG1uc6Vu5lwLflIY6s8RKHdZQbW39L4dYswSgqMDT0pkJILUTKjeyU0VPNRZjA==
|
||||
dependencies:
|
||||
httpreq ">=0.4.22"
|
||||
underscore "~1.12.1"
|
||||
|
||||
httpreq@>=0.4.22:
|
||||
version "0.5.2"
|
||||
resolved "https://registry.yarnpkg.com/httpreq/-/httpreq-0.5.2.tgz#be6777292fa1038d7771d7c01d9a5e1219de951c"
|
||||
integrity sha512-2Jm+x9WkExDOeFRrdBCBSpLPT5SokTcRHkunV3pjKmX/cx6av8zQ0WtHUMDrYb6O4hBFzNU6sxJEypvRUVYKnw==
|
||||
|
||||
https-proxy-agent@5, https-proxy-agent@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
|
||||
@@ -2822,10 +2821,10 @@ node-quickbooks@^2.0.39:
|
||||
util "0.10.3"
|
||||
uuid "^3.1.0"
|
||||
|
||||
nodemailer@^6.7.0:
|
||||
version "6.7.0"
|
||||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.0.tgz#86614722c4e0c33d1b5b02aecb90d6d629932b0d"
|
||||
integrity sha512-AtiTVUFHLiiDnMQ43zi0YgkzHOEWUkhDgPlBXrsDzJiJvB29Alo4OKxHQ0ugF3gRqRQIneCLtZU3yiUo7pItZw==
|
||||
nodemailer@^6.7.1:
|
||||
version "6.7.1"
|
||||
resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.1.tgz#09f72f8b375f7b259291757007bcd902c0174c6e"
|
||||
integrity sha512-E1C8G3rnXrGjznwGP1k+OrW5k4rl0XtqTEB19f7vtJAMYwfxZVSsAu2iY5xJkrZsbVYr6PwwAwRmFlakPoFC0A==
|
||||
|
||||
nth-check@~1.0.1:
|
||||
version "1.0.2"
|
||||
@@ -2975,10 +2974,10 @@ performance-now@^2.1.0:
|
||||
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
|
||||
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
|
||||
|
||||
phone@^3.1.8:
|
||||
version "3.1.8"
|
||||
resolved "https://registry.yarnpkg.com/phone/-/phone-3.1.8.tgz#6e348512539c9df81bf07fddb3ed3e2ec7e0c66e"
|
||||
integrity sha512-eyneQKbBwhy6PLYgkioO4CcocMUrFHh4WEfYl1A3PpiQK9tiP0ABKU4yhs7F1URKDbp+oeI8rbJU0+8uMgWfBQ==
|
||||
phone@^3.1.9:
|
||||
version "3.1.9"
|
||||
resolved "https://registry.yarnpkg.com/phone/-/phone-3.1.9.tgz#692d70061c0d7391ebcd67f30bee4364b52264e5"
|
||||
integrity sha512-u5jPSlbB4lq9W2ptznEb4eBBKnr3y8xAL4Dsn4uFzUl2gWZE6QiQgxMUMelHq3VUUzFq1QM579SkTxJ+k++igg==
|
||||
|
||||
pick-util@^1.1.3:
|
||||
version "1.1.3"
|
||||
@@ -3509,18 +3508,17 @@ snakeize@^0.1.0:
|
||||
resolved "https://registry.yarnpkg.com/snakeize/-/snakeize-0.1.0.tgz#10c088d8b58eb076b3229bb5a04e232ce126422d"
|
||||
integrity sha1-EMCI2LWOsHazIpu1oE4jLOEmQi0=
|
||||
|
||||
soap@^0.42.0:
|
||||
version "0.42.0"
|
||||
resolved "https://registry.yarnpkg.com/soap/-/soap-0.42.0.tgz#33f6ce109f9e6fdc9b61c3665c592c6d0e18e0ab"
|
||||
integrity sha512-7q4tYAkK0+KIeYRK0n/JBFP7XdZChqfGUfcDQRXt5uvKkRtj0gxTEc7WbfLnOqjyif86v5/MosE/4K+8ZYaB1Q==
|
||||
soap@^0.43.0:
|
||||
version "0.43.0"
|
||||
resolved "https://registry.yarnpkg.com/soap/-/soap-0.43.0.tgz#3172b7de12011dfc6981db99be9bc1df2a05a94a"
|
||||
integrity sha512-Dgp6TD9f3NXvKhBy95XXphiSlNIU2RSc9PP1NEgBOE1laUWP+bdF+8uT1lf1tFadFEAYurFg6/s2tNil6rlltw==
|
||||
dependencies:
|
||||
axios "^0.21.1"
|
||||
axios-ntlm "^1.1.6"
|
||||
axios-ntlm "^1.2.0"
|
||||
content-type-parser "^1.0.2"
|
||||
debug "^4.3.1"
|
||||
debug "^4.3.2"
|
||||
formidable "^1.2.2"
|
||||
get-stream "^6.0.1"
|
||||
httpntlm "^1.5.2"
|
||||
lodash "^4.17.21"
|
||||
sax ">=0.6"
|
||||
strip-bom "^3.0.0"
|
||||
@@ -3541,10 +3539,10 @@ socket.io-parser@~4.0.4:
|
||||
component-emitter "~1.3.0"
|
||||
debug "~4.3.1"
|
||||
|
||||
socket.io@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.3.1.tgz#c0aa14f3f916a8ab713e83a5bd20c16600245763"
|
||||
integrity sha512-HC5w5Olv2XZ0XJ4gOLGzzHEuOCfj3G0SmoW3jLHYYh34EVsIr3EkW9h6kgfW+K3TFEcmYy8JcPWe//KUkBp5jA==
|
||||
socket.io@^4.3.2:
|
||||
version "4.3.2"
|
||||
resolved "https://registry.yarnpkg.com/socket.io/-/socket.io-4.3.2.tgz#85ae0cf5cf18acbce648ac9f48aba66df8cea6bf"
|
||||
integrity sha512-6S5tV4jcY6dbZ/lLzD6EkvNWI3s81JO6ABP/EpvOlK1NPOcIj3AS4khi6xXw6JlZCASq82HQV4SapfmVMMl2dg==
|
||||
dependencies:
|
||||
accepts "~1.3.4"
|
||||
base64id "~2.0.0"
|
||||
@@ -3751,10 +3749,10 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
stripe@^8.184.0:
|
||||
version "8.184.0"
|
||||
resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.184.0.tgz#ea68470ca6045bb47516c4fea3b775fd6ce15a36"
|
||||
integrity sha512-ZUdvyX+sizTxXLEbUjgTShrulSWSkMIt7hIKdAkhnajYrHdzVtdmhBJl8sQbR9chMVox3Ig5ohilyeIrvcCE2g==
|
||||
stripe@^8.188.0:
|
||||
version "8.188.0"
|
||||
resolved "https://registry.yarnpkg.com/stripe/-/stripe-8.188.0.tgz#1d892c2f9000847c627db06a374529e7fbd2b83e"
|
||||
integrity sha512-AW5IOKq4y+ENfHddJPrLL/GSvGj1MnBvUe6QMI1z27x/4pMNrU7v0ZqzRSJCihWqP0tUuCmQibSYSbsV4XJ3zA==
|
||||
dependencies:
|
||||
"@types/node" ">=8.1.0"
|
||||
qs "^6.6.0"
|
||||
@@ -3918,10 +3916,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
||||
|
||||
twilio@^3.70.0:
|
||||
version "3.70.0"
|
||||
resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.70.0.tgz#9e6a96f0c46e8256d74bce918baeb7e678c4c1aa"
|
||||
integrity sha512-GhohvQfP3aHEwiCb6MWqDJ/KeSyFmFwCQtoSuHEwevE7GCxCq6spK36HlCNg3UyTTZNvfdIhN9Sf1wDWeDIbOg==
|
||||
twilio@^3.71.1:
|
||||
version "3.71.1"
|
||||
resolved "https://registry.yarnpkg.com/twilio/-/twilio-3.71.1.tgz#15bbb4b51c75d91cc07a8149378c4af330e543cc"
|
||||
integrity sha512-P/KFvm33UW15EnpHJKgdTxUa1u6MlR/u+sCVnL4ie2TDRv6t7kX+ieIGQMpH7bP/z7FXkTjEt0lz4M+XJ/XWOg==
|
||||
dependencies:
|
||||
axios "^0.21.4"
|
||||
dayjs "^1.8.29"
|
||||
@@ -3981,7 +3979,7 @@ uid-safe@2.1.5:
|
||||
dependencies:
|
||||
random-bytes "~1.0.0"
|
||||
|
||||
underscore@1.12.1, underscore@~1.12.1:
|
||||
underscore@1.12.1:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e"
|
||||
integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==
|
||||
|
||||
Reference in New Issue
Block a user