Compare commits
104 Commits
release/20
...
feature/no
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5a2be9392 | ||
|
|
df1e15be60 | ||
|
|
274b572915 | ||
|
|
fa4aa5ca8f | ||
|
|
2b537b65dd | ||
|
|
75b2cb18ca | ||
|
|
5167668958 | ||
|
|
1eacf43669 | ||
|
|
77ed64969e | ||
|
|
44ff032acc | ||
|
|
542637edb2 | ||
|
|
f7971ed60c | ||
|
|
ca71b0479a | ||
|
|
515de38fe6 | ||
|
|
113c62b36f | ||
|
|
c0ea5a9818 | ||
|
|
6b13dffe68 | ||
|
|
51d49be16e | ||
|
|
04c3abd65f | ||
|
|
29dab7312b | ||
|
|
01eb68fda1 | ||
|
|
a4c4329253 | ||
|
|
b738fc9007 | ||
|
|
5484358b32 | ||
|
|
b48d7512a2 | ||
|
|
ae3226efb8 | ||
|
|
da9ddfc419 | ||
|
|
901902c1d1 | ||
|
|
79bfb12063 | ||
|
|
c1bf112aac | ||
|
|
ecfb3e91cd | ||
|
|
e25606070b | ||
|
|
28f0d9a4b2 | ||
|
|
c125cd8ca2 | ||
|
|
123f94a0f5 | ||
|
|
d601617819 | ||
|
|
80bd2dc6d8 | ||
|
|
45bd2d3281 | ||
|
|
b4304c743e | ||
|
|
faf9fbb9d8 | ||
|
|
6d1581a4e1 | ||
|
|
28f6c72de1 | ||
|
|
54577ac680 | ||
|
|
c912681793 | ||
|
|
09f909142b | ||
|
|
89b515fff4 | ||
|
|
fb380a5b31 | ||
|
|
3896a0b03d | ||
|
|
832674662d | ||
|
|
f2b2011900 | ||
|
|
15c305317a | ||
|
|
d6924c2292 | ||
|
|
7ccd356f0a | ||
|
|
592b47b5d4 | ||
|
|
d9beee7f2f | ||
|
|
75743f44e7 | ||
|
|
3d68a7099b | ||
|
|
71f161ec27 | ||
|
|
9b1f24926f | ||
|
|
bcc153caa5 | ||
|
|
f59911d5ab | ||
|
|
417958e1e8 | ||
|
|
ccf2f0ad47 | ||
|
|
bb993ab1fb | ||
|
|
9c39c8d59b | ||
|
|
3439f09d9a | ||
|
|
279e93f0c3 | ||
|
|
92f14d6fa5 | ||
|
|
148c645f18 | ||
|
|
9a65b6a1ce | ||
|
|
839c82abb9 | ||
|
|
471756d7ad | ||
|
|
2e2a4920ca | ||
|
|
f775e09391 | ||
|
|
c0b0bcd55e | ||
|
|
1bc5493f3f | ||
|
|
2579558090 | ||
|
|
bc9a3a21a8 | ||
|
|
f11eb6406d | ||
|
|
3d6bad9e7d | ||
|
|
12a5f17351 | ||
|
|
a2032553d9 | ||
|
|
d22979dadc | ||
|
|
c1068ec92b | ||
|
|
a318f3e74b | ||
|
|
e5a5cb4e85 | ||
|
|
f8151e387e | ||
|
|
b98bfe566a | ||
|
|
c0220f0ca2 | ||
|
|
3e121a1a25 | ||
|
|
a2a8868223 | ||
|
|
80d16b4651 | ||
|
|
ce3fbab1dc | ||
|
|
4c1a333514 | ||
|
|
0660b79c01 | ||
|
|
63ec578b6a | ||
|
|
dcf388ff7c | ||
|
|
0cd1b41ed9 | ||
|
|
79124daa9a | ||
|
|
76ec55d709 | ||
|
|
51c5d163a5 | ||
|
|
a6f2cfba0f | ||
|
|
da51aeb135 | ||
|
|
1ba904d082 |
@@ -1,21 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"es6": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"globals": {
|
|
||||||
"Atomics": "readonly",
|
|
||||||
"SharedArrayBuffer": "readonly"
|
|
||||||
},
|
|
||||||
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2018,
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"no-console": "off"
|
|
||||||
},
|
|
||||||
"settings": {},
|
|
||||||
"plugins": ["cypress"]
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<babeledit_project version="1.2" be_version="2.7.1">
|
<babeledit_project be_version="2.7.1" version="1.2">
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
BabelEdit project file
|
BabelEdit project file
|
||||||
@@ -2354,6 +2354,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>is_credit_memo_short</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>
|
<concept_node>
|
||||||
<name>local_tax_rate</name>
|
<name>local_tax_rate</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -3633,6 +3654,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>bill_allow_post_to_closed</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>
|
<concept_node>
|
||||||
<name>bill_federal_tax_rate</name>
|
<name>bill_federal_tax_rate</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -4367,6 +4409,27 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>last_name_first</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>
|
<concept_node>
|
||||||
<name>lastnumberworkingdays</name>
|
<name>lastnumberworkingdays</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -4388,6 +4451,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>logo_img_footer_margin</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>logo_img_header_margin</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>
|
<concept_node>
|
||||||
<name>logo_img_path</name>
|
<name>logo_img_path</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -4556,6 +4661,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>md_from_emails</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>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>md_hour_split</name>
|
<name>md_hour_split</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -4648,6 +4774,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>private</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>
|
<concept_node>
|
||||||
<name>state</name>
|
<name>state</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -4755,6 +4902,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>md_parts_order_comment</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>
|
<concept_node>
|
||||||
<name>md_payment_types</name>
|
<name>md_payment_types</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -7238,6 +7406,32 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>ss_configuration</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>dailyhrslimit</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>
|
<folder_node>
|
||||||
<name>ssbuckets</name>
|
<name>ssbuckets</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -8733,6 +8927,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>qbo_departmentid</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>qbo_usa</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>
|
<concept_node>
|
||||||
<name>rbac</name>
|
<name>rbac</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -13163,6 +13399,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>from</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>
|
<concept_node>
|
||||||
<name>subject</name>
|
<name>subject</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -20119,6 +20376,27 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>auto_add_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>
|
<concept_node>
|
||||||
<name>ca_bc_pvrt</name>
|
<name>ca_bc_pvrt</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -20581,6 +20859,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>date_rentalresp</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>
|
<concept_node>
|
||||||
<name>date_scheduled</name>
|
<name>date_scheduled</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -20602,6 +20901,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>date_towin</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>
|
<concept_node>
|
||||||
<name>ded_amt</name>
|
<name>ded_amt</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -22979,6 +23299,27 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>rate_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>
|
<concept_node>
|
||||||
<name>rate_la1</name>
|
<name>rate_la1</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -26437,6 +26778,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>parts_received</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>
|
<concept_node>
|
||||||
<name>parts_tax_rates</name>
|
<name>parts_tax_rates</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -27371,6 +27733,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>threshhold</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>
|
<concept_node>
|
||||||
<name>total_cost</name>
|
<name>total_cost</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -29708,6 +30091,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>cancelallappointments</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>
|
<concept_node>
|
||||||
<name>closejob</name>
|
<name>closejob</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -31016,6 +31420,37 @@
|
|||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>owner</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>labels</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>noownerinfo</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>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>owners</name>
|
<name>owners</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -32384,6 +32819,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>notyetordered</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>
|
<concept_node>
|
||||||
<name>oec</name>
|
<name>oec</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -34752,6 +35208,48 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>lag_time_ro</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>mechanical_authorization</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>
|
<concept_node>
|
||||||
<name>mpi_animal_checklist</name>
|
<name>mpi_animal_checklist</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -36293,6 +36791,58 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>bodyshop</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>labels</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>qbo_departmentid</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>qbo_usa</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>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>cardsettings</name>
|
<name>cardsettings</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -36650,6 +37200,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>stickyheader</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>
|
<concept_node>
|
||||||
<name>sublets</name>
|
<name>sublets</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -38427,6 +38998,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>production_by_repair_status_one</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>
|
<concept_node>
|
||||||
<name>production_by_ro</name>
|
<name>production_by_ro</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -42723,6 +43315,63 @@
|
|||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>users</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>errors</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>signinerror</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>auth/user-not-found</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>auth/wrong-password</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>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>vehicles</name>
|
<name>vehicles</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -43353,6 +44002,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>novehinfo</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>
|
<concept_node>
|
||||||
<name>relatedjobs</name>
|
<name>relatedjobs</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -3,83 +3,89 @@
|
|||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:4000",
|
"proxy": "http://localhost:4000",
|
||||||
|
"browser": {
|
||||||
|
"fs": false,
|
||||||
|
"path": false,
|
||||||
|
"os": false
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.5.6",
|
"@apollo/client": "^3.5.10",
|
||||||
"@asseinfo/react-kanban": "^2.2.0",
|
"@asseinfo/react-kanban": "^2.2.0",
|
||||||
"@craco/craco": "^6.4.3",
|
"@craco/craco": "^6.4.3",
|
||||||
"@fingerprintjs/fingerprintjs": "^3.3.1",
|
"@fingerprintjs/fingerprintjs": "^3.3.3",
|
||||||
"@sentry/react": "^6.16.1",
|
"@jsreport/browser-client": "^3.1.0",
|
||||||
"@sentry/tracing": "^6.16.1",
|
"@sentry/react": "^6.19.6",
|
||||||
"@splitsoftware/splitio-react": "^1.3.0",
|
"@sentry/tracing": "^6.19.6",
|
||||||
"@stripe/react-stripe-js": "^1.7.0",
|
"@splitsoftware/splitio-react": "^1.4.0",
|
||||||
"@stripe/stripe-js": "^1.22.0",
|
"@stripe/react-stripe-js": "^1.7.1",
|
||||||
"@tanem/react-nprogress": "^3.0.82",
|
"@stripe/stripe-js": "^1.27.0",
|
||||||
"antd": "^4.17.4",
|
"@tanem/react-nprogress": "^5.0.0",
|
||||||
|
"antd": "^4.19.5",
|
||||||
"apollo-link-logger": "^2.0.0",
|
"apollo-link-logger": "^2.0.0",
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.26.1",
|
||||||
"craco-less": "^1.20.0",
|
"craco-less": "^2.0.0",
|
||||||
"dinero.js": "^1.9.1",
|
"dinero.js": "^1.9.1",
|
||||||
"dotenv": "^10.0.0",
|
"dotenv": "^16.0.0",
|
||||||
"enquire-js": "^0.2.1",
|
"enquire-js": "^0.2.1",
|
||||||
"env-cmd": "^10.1.0",
|
"env-cmd": "^10.1.0",
|
||||||
"exifr": "^7.1.3",
|
"exifr": "^7.1.3",
|
||||||
"firebase": "^9.6.1",
|
"firebase": "^9.6.10",
|
||||||
"graphql": "^16.2.0",
|
"graphql": "^16.3.0",
|
||||||
"i18next": "^21.6.3",
|
"i18next": "^21.6.16",
|
||||||
"i18next-browser-languagedetector": "^6.1.2",
|
"i18next-browser-languagedetector": "^6.1.4",
|
||||||
"jsoneditor": "^9.5.8",
|
"jsoneditor": "^9.7.4",
|
||||||
"jsreport-browser-client-dist": "^1.3.0",
|
"libphonenumber-js": "^1.9.51",
|
||||||
"libphonenumber-js": "^1.9.44",
|
"logrocket": "^2.2.1",
|
||||||
"logrocket": "^2.1.2",
|
"markerjs2": "^2.21.0",
|
||||||
"markerjs2": "^2.17.2",
|
|
||||||
"moment-business-days": "^1.2.0",
|
"moment-business-days": "^1.2.0",
|
||||||
"moment-timezone": "^0.5.34",
|
"moment-timezone": "^0.5.34",
|
||||||
"phone": "^3.1.10",
|
"phone": "^3.1.15",
|
||||||
"preval.macro": "^5.0.0",
|
"preval.macro": "^5.0.0",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.8.1",
|
||||||
"query-string": "^7.0.1",
|
"query-string": "^7.1.1",
|
||||||
"rc-queue-anim": "^2.0.0",
|
"rc-queue-anim": "^2.0.0",
|
||||||
"rc-scroll-anim": "^2.7.6",
|
"rc-scroll-anim": "^2.7.6",
|
||||||
"react": "^17.0.2",
|
"react": "^18.0.0",
|
||||||
"react-big-calendar": "^0.38.2",
|
"react-big-calendar": "^0.40.0",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^18.0.0",
|
||||||
"react-drag-listview": "^0.1.8",
|
"react-drag-listview": "^0.1.9",
|
||||||
"react-grid-gallery": "^0.5.5",
|
"react-grid-gallery": "^0.5.5",
|
||||||
"react-grid-layout": "^1.3.0",
|
"react-grid-layout": "^1.3.4",
|
||||||
"react-i18next": "^11.15.1",
|
"react-i18next": "^11.16.6",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"react-number-format": "^4.9.0",
|
"react-number-format": "^4.9.1",
|
||||||
"react-redux": "^7.2.6",
|
"react-redux": "^7.2.8",
|
||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.4",
|
||||||
"react-router-dom": "^5.3.0",
|
"react-router-dom": "^5.3.0",
|
||||||
"react-scripts": "^4.0.3",
|
"react-scripts": "^4.0.3",
|
||||||
|
"react-sticky": "^6.0.3",
|
||||||
"react-sublime-video": "^0.2.5",
|
"react-sublime-video": "^0.2.5",
|
||||||
"react-virtualized": "^9.22.3",
|
"react-virtualized": "^9.22.3",
|
||||||
"recharts": "^2.1.8",
|
"recharts": "^2.1.9",
|
||||||
"redux": "^4.1.2",
|
"redux": "^4.1.2",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"redux-saga": "^1.1.3",
|
"redux-saga": "^1.1.3",
|
||||||
"redux-state-sync": "^3.1.2",
|
"redux-state-sync": "^3.1.2",
|
||||||
"reselect": "^4.1.5",
|
"reselect": "^4.1.5",
|
||||||
"sass": "^1.45.0",
|
"sass": "^1.50.0",
|
||||||
"socket.io-client": "^4.4.0",
|
"socket.io-client": "^4.4.1",
|
||||||
"styled-components": "^5.3.3",
|
"styled-components": "^5.3.5",
|
||||||
"subscriptions-transport-ws": "^0.11.0",
|
"subscriptions-transport-ws": "^0.11.0",
|
||||||
"web-vitals": "^2.1.2",
|
"web-vitals": "^2.1.4",
|
||||||
"workbox-background-sync": "^6.4.2",
|
"workbox-background-sync": "^6.5.3",
|
||||||
"workbox-broadcast-update": "^6.4.2",
|
"workbox-broadcast-update": "^6.5.3",
|
||||||
"workbox-cacheable-response": "^6.4.2",
|
"workbox-cacheable-response": "^6.5.3",
|
||||||
"workbox-core": "^6.4.2",
|
"workbox-core": "^6.5.3",
|
||||||
"workbox-expiration": "^6.4.2",
|
"workbox-expiration": "^6.5.3",
|
||||||
"workbox-google-analytics": "^6.4.2",
|
"workbox-google-analytics": "^6.5.3",
|
||||||
"workbox-navigation-preload": "^6.4.2",
|
"workbox-navigation-preload": "^6.5.3",
|
||||||
"workbox-precaching": "^6.4.2",
|
"workbox-precaching": "^6.5.3",
|
||||||
"workbox-range-requests": "^6.4.2",
|
"workbox-range-requests": "^6.5.3",
|
||||||
"workbox-routing": "^6.4.2",
|
"workbox-routing": "^6.5.3",
|
||||||
"workbox-strategies": "^6.4.2",
|
"workbox-strategies": "^6.5.3",
|
||||||
"workbox-streams": "^6.4.2",
|
"workbox-streams": "^6.5.3",
|
||||||
"yauzl": "^2.10.0"
|
"yauzl": "^2.10.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -116,11 +122,11 @@
|
|||||||
"react-error-overlay": "6.0.9"
|
"react-error-overlay": "6.0.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sentry/webpack-plugin": "^1.18.3",
|
"@sentry/webpack-plugin": "^1.18.8",
|
||||||
"@testing-library/cypress": "^8.0.2",
|
"@testing-library/cypress": "^8.0.2",
|
||||||
"cypress": "^9.1.1",
|
"cypress": "^9.5.4",
|
||||||
"eslint-plugin-cypress": "^2.12.1",
|
"eslint-plugin-cypress": "^2.12.1",
|
||||||
"react-error-overlay": "6.0.9",
|
"react-error-overlay": "6.0.11",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
"source-map-explorer": "^2.5.2"
|
"source-map-explorer": "^2.5.2"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -76,14 +77,12 @@ export function AccountingPayablesTableComponent({
|
|||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.job.owner ? (
|
return record.job.owner ? (
|
||||||
<Link to={"/manage/owners/" + record.job.owner.id}>
|
<Link to={"/manage/owners/" + record.job.owner.id}>
|
||||||
{`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record.job} />
|
||||||
record.job.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>{`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${
|
<span>
|
||||||
record.job.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record.job} />
|
||||||
}`}</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -162,10 +161,19 @@ export function AccountingPayablesTableComponent({
|
|||||||
const dataSource = state.search
|
const dataSource = state.search
|
||||||
? payments.filter(
|
? payments.filter(
|
||||||
(v) =>
|
(v) =>
|
||||||
(v.vendor.name || "")
|
(v.paymentnum || "")
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(state.search.toLowerCase()) ||
|
.includes(state.search.toLowerCase()) ||
|
||||||
(v.invoice_number || "")
|
((v.job && v.job.ro_number) || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(state.search.toLowerCase()) ||
|
||||||
|
((v.job && v.job.ownr_fn) || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(state.search.toLowerCase()) ||
|
||||||
|
((v.job && v.job.ownr_ln) || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(state.search.toLowerCase()) ||
|
||||||
|
((v.job && v.job.ownr_co_nm) || "")
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(state.search.toLowerCase())
|
.includes(state.search.toLowerCase())
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||||
import JobExportButton from "../jobs-close-export-button/jobs-close-export-button.component";
|
import JobExportButton from "../jobs-close-export-button/jobs-close-export-button.component";
|
||||||
import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-button.component";
|
import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-button.component";
|
||||||
|
|
||||||
@@ -12,6 +12,9 @@ import { connect } from "react-redux";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||||
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
@@ -62,6 +65,18 @@ export function AccountingReceivablesTableComponent({
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.date_invoiced"),
|
||||||
|
dataIndex: "date_invoiced",
|
||||||
|
key: "date_invoiced",
|
||||||
|
sorter: (a, b) => dateSort(a.date_invoiced, b.date_invoiced),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "date_invoiced" &&
|
||||||
|
state.sortedInfo.order,
|
||||||
|
render: (text, record) => (
|
||||||
|
<DateFormatter>{record.date_invoiced}</DateFormatter>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.owner"),
|
title: t("jobs.fields.owner"),
|
||||||
dataIndex: "owner",
|
dataIndex: "owner",
|
||||||
@@ -72,14 +87,12 @@ export function AccountingReceivablesTableComponent({
|
|||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.owner ? (
|
return record.owner ? (
|
||||||
<Link to={"/manage/owners/" + record.owner.id}>
|
<Link to={"/manage/owners/" + record.owner.id}>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<span>
|
||||||
record.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
}`}</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useLocation, useHistory } from "react-router-dom";
|
import { useLocation, useHistory } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
|
DELETE_BILL_LINE,
|
||||||
INSERT_NEW_BILL_LINES,
|
INSERT_NEW_BILL_LINES,
|
||||||
UPDATE_BILL_LINE,
|
UPDATE_BILL_LINE,
|
||||||
} from "../../graphql/bill-lines.queries";
|
} from "../../graphql/bill-lines.queries";
|
||||||
@@ -58,6 +59,7 @@ export function BillDetailEditcontainer({
|
|||||||
const [update_bill] = useMutation(UPDATE_BILL);
|
const [update_bill] = useMutation(UPDATE_BILL);
|
||||||
const [insertBillLine] = useMutation(INSERT_NEW_BILL_LINES);
|
const [insertBillLine] = useMutation(INSERT_NEW_BILL_LINES);
|
||||||
const [updateBillLine] = useMutation(UPDATE_BILL_LINE);
|
const [updateBillLine] = useMutation(UPDATE_BILL_LINE);
|
||||||
|
const [deleteBillLine] = useMutation(DELETE_BILL_LINE);
|
||||||
|
|
||||||
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
|
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
|
||||||
.filter((screen) => !!screen[1])
|
.filter((screen) => !!screen[1])
|
||||||
@@ -107,6 +109,20 @@ export function BillDetailEditcontainer({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//Find bill lines that were deleted.
|
||||||
|
const deletedJobLines = [];
|
||||||
|
|
||||||
|
data.bills_by_pk.billlines.forEach((a) => {
|
||||||
|
const matchingRecord = billlines.find((b) => b.id === a.id);
|
||||||
|
if (!matchingRecord) {
|
||||||
|
deletedJobLines.push(a);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
deletedJobLines.forEach((d) => {
|
||||||
|
updates.push(deleteBillLine({ variables: { id: d.id } }));
|
||||||
|
});
|
||||||
|
|
||||||
billlines.forEach((billline) => {
|
billlines.forEach((billline) => {
|
||||||
const { deductedfromlbr, jobline, ...il } = billline;
|
const { deductedfromlbr, jobline, ...il } = billline;
|
||||||
delete il.__typename;
|
delete il.__typename;
|
||||||
@@ -142,6 +158,7 @@ export function BillDetailEditcontainer({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(updates);
|
await Promise.all(updates);
|
||||||
|
|
||||||
insertAuditTrail({
|
insertAuditTrail({
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export function BillFormComponent({
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bills.fields.vendor")}
|
label={t("bills.fields.vendor")}
|
||||||
name="vendorid"
|
name="vendorid"
|
||||||
style={{ display: billEdit ? "none" : null }}
|
// style={{ display: billEdit ? "none" : null }}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -229,6 +229,7 @@ export function BillFormComponent({
|
|||||||
({ getFieldValue }) => ({
|
({ getFieldValue }) => ({
|
||||||
validator(rule, value) {
|
validator(rule, value) {
|
||||||
if (
|
if (
|
||||||
|
!bodyshop.bill_allow_post_to_closed &&
|
||||||
(job.status === bodyshop.md_ro_statuses.default_invoiced ||
|
(job.status === bodyshop.md_ro_statuses.default_invoiced ||
|
||||||
job.status === bodyshop.md_ro_statuses.default_exported ||
|
job.status === bodyshop.md_ro_statuses.default_exported ||
|
||||||
job.status === bodyshop.md_ro_statuses.default_void) &&
|
job.status === bodyshop.md_ro_statuses.default_void) &&
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { selectSelectedConversation } from "../../redux/messaging/messaging.sele
|
|||||||
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||||
import "./chat-conversation-list.styles.scss";
|
import "./chat-conversation-list.styles.scss";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
selectedConversation: selectSelectedConversation,
|
selectedConversation: selectSelectedConversation,
|
||||||
@@ -40,9 +41,9 @@ export function ChatConversationListComponent({
|
|||||||
{item.job_conversations.length > 0 ? (
|
{item.job_conversations.length > 0 ? (
|
||||||
<div className="chat-name">
|
<div className="chat-name">
|
||||||
{item.job_conversations.map((j, idx) => (
|
{item.job_conversations.map((j, idx) => (
|
||||||
<div key={idx}>{`${j.job.ownr_fn || ""} ${
|
<div key={idx}>
|
||||||
j.job.ownr_ln || ""
|
<OwnerNameDisplay ownerObject={j.job} />
|
||||||
} ${j.job.ownr_co_nm || ""} `}</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import React from "react";
|
|||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
import { REMOVE_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
import { REMOVE_CONVERSATION_TAG } from "../../graphql/job-conversations.queries";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function ChatConversationTitleTags({ jobConversations }) {
|
export default function ChatConversationTitleTags({ jobConversations }) {
|
||||||
const [removeJobConversation] = useMutation(REMOVE_CONVERSATION_TAG);
|
const [removeJobConversation] = useMutation(REMOVE_CONVERSATION_TAG);
|
||||||
@@ -45,9 +46,8 @@ export default function ChatConversationTitleTags({ jobConversations }) {
|
|||||||
onClose={() => handleRemoveTag(item.job.id)}
|
onClose={() => handleRemoveTag(item.job.id)}
|
||||||
>
|
>
|
||||||
<Link to={`/manage/jobs/${item.job.id}`}>
|
<Link to={`/manage/jobs/${item.job.id}`}>
|
||||||
{`${item.job.ro_number || "?"} | ${item.job.ownr_fn || ""} ${
|
{`${item.job.ro_number || "?"} | `}
|
||||||
item.job.ownr_ln || ""
|
<OwnerNameDisplay ownerObject={item.job} />
|
||||||
} ${item.job.ownr_co_nm || ""}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
</Tag>
|
</Tag>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { CloseCircleOutlined, LoadingOutlined } from "@ant-design/icons";
|
import { CloseCircleOutlined, LoadingOutlined } from "@ant-design/icons";
|
||||||
import { Select, Empty, Space } from "antd";
|
import { Empty, Select, Space } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function ChatTagRoComponent({
|
export default function ChatTagRoComponent({
|
||||||
roOptions,
|
roOptions,
|
||||||
@@ -27,9 +28,7 @@ export default function ChatTagRoComponent({
|
|||||||
>
|
>
|
||||||
{roOptions.map((item, idx) => (
|
{roOptions.map((item, idx) => (
|
||||||
<Select.Option key={item.id || idx}>
|
<Select.Option key={item.id || idx}>
|
||||||
{` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${
|
{` ${item.ro_number || ""} | ${OwnerNameDisplayFunction(item)}`}
|
||||||
item.ownr_ln || ""
|
|
||||||
} ${item.ownr_co_nm || ""}`}
|
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import React from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import DataLabel from "../data-label/data-label.component";
|
import DataLabel from "../data-label/data-label.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
export default function ContractJobBlock({ job }) {
|
export default function ContractJobBlock({ job }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
@@ -23,9 +23,7 @@ export default function ContractJobBlock({ job }) {
|
|||||||
} ${(job && job.v_model_desc) || ""}`}
|
} ${(job && job.v_model_desc) || ""}`}
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
<DataLabel label={t("jobs.fields.owner")}>
|
<DataLabel label={t("jobs.fields.owner")}>
|
||||||
{`${(job && job.ownr_fn) || ""} ${(job && job.ownr_ln) || ""} ${
|
<OwnerNameDisplay ownerObject={job} />
|
||||||
(job && job.ownr_co_nm) || ""
|
|
||||||
}`}
|
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import React, { useMemo, useState } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function ContractsJobsComponent({
|
export default function ContractsJobsComponent({
|
||||||
loading,
|
loading,
|
||||||
@@ -43,17 +44,7 @@ export default function ContractsJobsComponent({
|
|||||||
width: "25%",
|
width: "25%",
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
|
||||||
render: (text, record) => {
|
render: (text, record) => <OwnerNameDisplay ownerObject={record} />,
|
||||||
return record.owner ? (
|
|
||||||
<span>
|
|
||||||
{record.ownr_fn} {record.ownr_ln} {record.ownr_co_nm || ""}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
<span>{`${record.ownr_fn} ${record.ownr_ln} ${
|
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.status"),
|
title: t("jobs.fields.status"),
|
||||||
|
|||||||
@@ -12,17 +12,22 @@ import { setModalContext } from "../../redux/modals/modals.actions";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
setContractFinderContext: (context) =>
|
setContractFinderContext: (context) =>
|
||||||
dispatch(setModalContext({ context: context, modal: "contractFinder" })),
|
dispatch(setModalContext({ context: context, modal: "contractFinder" })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(ContractsList);
|
export default connect(mapStateToProps, mapDispatchToProps)(ContractsList);
|
||||||
|
|
||||||
export function ContractsList({
|
export function ContractsList({
|
||||||
|
bodyshop,
|
||||||
loading,
|
loading,
|
||||||
contracts,
|
contracts,
|
||||||
refetch,
|
refetch,
|
||||||
@@ -72,7 +77,9 @@ export function ContractsList({
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "driver_ln" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "driver_ln" && state.sortedInfo.order,
|
||||||
render: (text, record) =>
|
render: (text, record) =>
|
||||||
`${record.driver_fn || ""} ${record.driver_ln || ""}`,
|
bodyshop.last_name_first
|
||||||
|
? `${record.driver_ln || ""}, ${record.driver_fn || ""}`
|
||||||
|
: `${record.driver_fn || ""} ${record.driver_ln || ""}`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("contracts.labels.vehicle"),
|
title: t("contracts.labels.vehicle"),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { DateFormatter } from "../../utils/DateFormatter";
|
|||||||
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
|
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
|
||||||
import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component";
|
import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component";
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||||
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
//import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormFieldsChanged form={form} />
|
{/* <FormFieldsChanged form={form} /> */}
|
||||||
<LayoutFormRow header={t("courtesycars.labels.vehicle")}>
|
<LayoutFormRow header={t("courtesycars.labels.vehicle")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("courtesycars.fields.make")}
|
label={t("courtesycars.fields.make")}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Table, Button, Input, Card, Space } from "antd";
|
import { SyncOutlined } from "@ant-design/icons";
|
||||||
|
import { Button, Card, Input, Space, Table } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
import { SyncOutlined } from "@ant-design/icons";
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
sortedInfo: {},
|
sortedInfo: {},
|
||||||
@@ -97,9 +99,9 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
|||||||
render: (text, record) =>
|
render: (text, record) =>
|
||||||
record.cccontracts.length === 1 ? (
|
record.cccontracts.length === 1 ? (
|
||||||
<Link to={`/manage/jobs/${record.cccontracts[0].job.id}`}>
|
<Link to={`/manage/jobs/${record.cccontracts[0].job.id}`}>
|
||||||
{`${record.cccontracts[0].job.ro_number} - ${
|
{`${
|
||||||
record.cccontracts[0].job.ownr_fn || ""
|
record.cccontracts[0].job.ro_number
|
||||||
} ${record.cccontracts[0].job.ownr_ln || ""} ${record.cccontracts[0].job.ownr_co_nm || ""}`}
|
} - ${OwnerNameDisplayFunction(record.cccontracts[0].job)}`}
|
||||||
</Link>
|
</Link>
|
||||||
) : null,
|
) : null,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||||
import { DateFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function CsiResponseListPaginated({
|
export default function CsiResponseListPaginated({
|
||||||
refetch,
|
refetch,
|
||||||
@@ -48,14 +49,12 @@ export default function CsiResponseListPaginated({
|
|||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.job.owner ? (
|
return record.job.owner ? (
|
||||||
<Link to={"/manage/owners/" + record.job.owner.id}>
|
<Link to={"/manage/owners/" + record.job.owner.id}>
|
||||||
{`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record.job} />
|
||||||
record.job.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>{`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${
|
<span>
|
||||||
record.job.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record.job} />
|
||||||
}`}</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,9 +16,14 @@ import EmailDocumentsComponent from "../email-documents/email-documents.componen
|
|||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import {
|
||||||
|
selectBodyshop,
|
||||||
|
selectCurrentUser,
|
||||||
|
} from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
currentUser: selectCurrentUser,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
@@ -28,7 +33,12 @@ export default connect(
|
|||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(EmailOverlayComponent);
|
)(EmailOverlayComponent);
|
||||||
|
|
||||||
export function EmailOverlayComponent({ form, selectedMediaState, bodyshop }) {
|
export function EmailOverlayComponent({
|
||||||
|
form,
|
||||||
|
selectedMediaState,
|
||||||
|
bodyshop,
|
||||||
|
currentUser,
|
||||||
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const handleClick = ({ item, key, keyPath }) => {
|
const handleClick = ({ item, key, keyPath }) => {
|
||||||
const email = item.props.value;
|
const email = item.props.value;
|
||||||
@@ -51,6 +61,27 @@ export function EmailOverlayComponent({ form, selectedMediaState, bodyshop }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Form.Item
|
||||||
|
label={t("emails.fields.from")}
|
||||||
|
name="from"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Select>
|
||||||
|
<Select.Option key={currentUser.email}>
|
||||||
|
{currentUser.email}
|
||||||
|
</Select.Option>
|
||||||
|
<Select.Option key={bodyshop.email}>{bodyshop.email}</Select.Option>
|
||||||
|
{bodyshop.md_from_emails &&
|
||||||
|
bodyshop.md_from_emails.map((e) => (
|
||||||
|
<Select.Option key={e}>{e}</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={
|
label={
|
||||||
<Space>
|
<Space>
|
||||||
|
|||||||
@@ -56,13 +56,9 @@ export function EmailOverlayContainer({
|
|||||||
: bodyshop.shopname,
|
: bodyshop.shopname,
|
||||||
address: EmailSettings.fromAddress,
|
address: EmailSettings.fromAddress,
|
||||||
},
|
},
|
||||||
ReplyTo: {
|
|
||||||
Email: currentUser.validemail ? currentUser.email : bodyshop.email,
|
|
||||||
Name: currentUser.displayName,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (allValues) => {
|
||||||
logImEXEvent("email_send_from_modal");
|
logImEXEvent("email_send_from_modal");
|
||||||
|
|
||||||
//const attachments = [];
|
//const attachments = [];
|
||||||
@@ -77,10 +73,15 @@ export function EmailOverlayContainer({
|
|||||||
// attachments.push(t);
|
// attachments.push(t);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
const { from, ...values } = allValues;
|
||||||
setSending(true);
|
setSending(true);
|
||||||
try {
|
try {
|
||||||
await axios.post("/sendemail", {
|
await axios.post("/sendemail", {
|
||||||
...defaultEmailFrom,
|
...defaultEmailFrom,
|
||||||
|
ReplyTo: {
|
||||||
|
Email: from,
|
||||||
|
Name: currentUser.displayName,
|
||||||
|
},
|
||||||
...values,
|
...values,
|
||||||
html: rawHtml,
|
html: rawHtml,
|
||||||
attachments: [
|
attachments: [
|
||||||
@@ -138,6 +139,7 @@ export function EmailOverlayContainer({
|
|||||||
}
|
}
|
||||||
|
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
|
from: currentUser.validemail ? currentUser.email : bodyshop.email,
|
||||||
...emailConfig.messageOptions,
|
...emailConfig.messageOptions,
|
||||||
cc:
|
cc:
|
||||||
emailConfig.messageOptions.cc &&
|
emailConfig.messageOptions.cc &&
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
import { useLazyQuery } from "@apollo/client";
|
import { useLazyQuery } from "@apollo/client";
|
||||||
|
import { LoadingOutlined } from "@ant-design/icons";
|
||||||
import { AutoComplete, Divider, Space } from "antd";
|
import { AutoComplete, Divider, Space } from "antd";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link, useHistory } from "react-router-dom";
|
||||||
import { GLOBAL_SEARCH_QUERY } from "../../graphql/search.queries";
|
import { GLOBAL_SEARCH_QUERY } from "../../graphql/search.queries";
|
||||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import OwnerNameDisplay, {
|
||||||
|
OwnerNameDisplayFunction,
|
||||||
|
} from "../owner-name-display/owner-name-display.component";
|
||||||
export default function GlobalSearch() {
|
export default function GlobalSearch() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const history = useHistory();
|
||||||
const [callSearch, { error, data }] = useLazyQuery(GLOBAL_SEARCH_QUERY);
|
const [callSearch, { loading, error, data }] =
|
||||||
|
useLazyQuery(GLOBAL_SEARCH_QUERY);
|
||||||
|
|
||||||
const executeSearch = (v) => {
|
const executeSearch = (v) => {
|
||||||
if (v && v.variables.search && v.variables.search !== "") callSearch(v);
|
if (v && v.variables.search && v.variables.search !== "") callSearch(v);
|
||||||
@@ -39,9 +43,9 @@ export default function GlobalSearch() {
|
|||||||
<Space size="small" split={<Divider type="vertical" />}>
|
<Space size="small" split={<Divider type="vertical" />}>
|
||||||
<strong>{job.ro_number || t("general.labels.na")}</strong>
|
<strong>{job.ro_number || t("general.labels.na")}</strong>
|
||||||
<span>{`${job.status || ""}`}</span>
|
<span>{`${job.status || ""}`}</span>
|
||||||
<span>{`${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
<span>
|
||||||
job.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={job} />
|
||||||
}`}</span>
|
</span>
|
||||||
<span>{`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${
|
<span>{`${job.v_model_yr || ""} ${job.v_make_desc || ""} ${
|
||||||
job.v_model_desc || ""
|
job.v_model_desc || ""
|
||||||
}`}</span>
|
}`}</span>
|
||||||
@@ -57,15 +61,13 @@ export default function GlobalSearch() {
|
|||||||
options: data.search_owners.map((owner) => {
|
options: data.search_owners.map((owner) => {
|
||||||
return {
|
return {
|
||||||
key: owner.id,
|
key: owner.id,
|
||||||
value: `${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${
|
value: OwnerNameDisplayFunction(owner),
|
||||||
owner.ownr_co_nm || ""
|
|
||||||
}`,
|
|
||||||
label: (
|
label: (
|
||||||
<Link to={`/manage/owners/${owner.id}`}>
|
<Link to={`/manage/owners/${owner.id}`}>
|
||||||
<Space size="small" split={<Divider type="vertical" />} wrap>
|
<Space size="small" split={<Divider type="vertical" />} wrap>
|
||||||
<span>{`${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${
|
<span>
|
||||||
owner.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={owner} />
|
||||||
}`}</span>
|
</span>
|
||||||
<PhoneNumberFormatter>
|
<PhoneNumberFormatter>
|
||||||
{owner.ownr_ph1}
|
{owner.ownr_ph1}
|
||||||
</PhoneNumberFormatter>
|
</PhoneNumberFormatter>
|
||||||
@@ -171,8 +173,13 @@ export default function GlobalSearch() {
|
|||||||
<AutoComplete
|
<AutoComplete
|
||||||
options={options}
|
options={options}
|
||||||
onSearch={handleSearch}
|
onSearch={handleSearch}
|
||||||
|
suffixIcon={loading && <LoadingOutlined spin />}
|
||||||
|
defaultActiveFirstOption
|
||||||
placeholder={t("general.labels.globalsearch")}
|
placeholder={t("general.labels.globalsearch")}
|
||||||
allowClear
|
allowClear
|
||||||
|
onSelect={(val, opt) => {
|
||||||
|
history.push(opt.label.props.to);
|
||||||
|
}}
|
||||||
></AutoComplete>
|
></AutoComplete>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.
|
|||||||
import ScheduleAtChange from "./job-at-change.component";
|
import ScheduleAtChange from "./job-at-change.component";
|
||||||
import ScheduleEventColor from "./schedule-event.color.component";
|
import ScheduleEventColor from "./schedule-event.color.component";
|
||||||
import ScheduleEventNote from "./schedule-event.note.component";
|
import ScheduleEventNote from "./schedule-event.note.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -73,9 +74,9 @@ export function ScheduleEventComponent({
|
|||||||
</Space>
|
</Space>
|
||||||
) : (
|
) : (
|
||||||
<Space>
|
<Space>
|
||||||
<strong>{`${(event.job && event.job.ownr_fn) || ""} ${
|
<strong>
|
||||||
(event.job && event.job.ownr_ln) || ""
|
<OwnerNameDisplay ownerObject={event.job} />
|
||||||
}`}</strong>
|
</strong>
|
||||||
<span style={{ margin: 4 }}>
|
<span style={{ margin: 4 }}>
|
||||||
{`${(event.job && event.job.v_model_yr) || ""} ${
|
{`${(event.job && event.job.v_model_yr) || ""} ${
|
||||||
(event.job && event.job.v_make_desc) || ""
|
(event.job && event.job.v_make_desc) || ""
|
||||||
@@ -256,9 +257,9 @@ export function ScheduleEventComponent({
|
|||||||
<Space>
|
<Space>
|
||||||
{event.note && <AlertFilled className="production-alert" />}
|
{event.note && <AlertFilled className="production-alert" />}
|
||||||
<strong>{`${event.job.ro_number || t("general.labels.na")}`}</strong>
|
<strong>{`${event.job.ro_number || t("general.labels.na")}`}</strong>
|
||||||
<span>{`${(event.job && event.job.ownr_fn) || ""} ${
|
<span>
|
||||||
(event.job && event.job.ownr_ln) || ""
|
<OwnerNameDisplay ownerObject={event.job} />
|
||||||
} ${(event.job && event.job.ownr_co_nm) || ""}`}</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
<Space>
|
<Space>
|
||||||
<span>
|
<span>
|
||||||
|
|||||||
@@ -64,9 +64,9 @@ export default function JobBillsTotalComponent({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const totalPartsSublet = Dinero(totals.parts.parts.total).add(
|
const totalPartsSublet = Dinero(totals.parts.parts.total)
|
||||||
Dinero(totals.parts.sublets.total)
|
.add(Dinero(totals.parts.sublets.total))
|
||||||
);
|
.add(Dinero(totals.additional.towing));
|
||||||
|
|
||||||
const discrepancy = totalPartsSublet.subtract(billTotals);
|
const discrepancy = totalPartsSublet.subtract(billTotals);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
import { useQuery } from "@apollo/client";
|
||||||
|
import { Row, Col, Timeline, Typography, Space, Divider, Skeleton } from "antd";
|
||||||
|
import React from "react";
|
||||||
|
import { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
export default function JobLinesExpander({ jobline, jobid }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { loading, error, data } = useQuery(GET_JOB_LINE_ORDERS, {
|
||||||
|
fetchPolicy: "network-only",
|
||||||
|
nextFetchPolicy: "network-only",
|
||||||
|
variables: {
|
||||||
|
joblineid: jobline.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (loading) return <Skeleton />;
|
||||||
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Col md={24} lg={12}>
|
||||||
|
<Typography.Title level={4}>
|
||||||
|
{t("parts_orders.labels.parts_orders")}
|
||||||
|
</Typography.Title>
|
||||||
|
<Timeline>
|
||||||
|
{data.parts_order_lines.length > 0 ? (
|
||||||
|
data.parts_order_lines.map((line) => (
|
||||||
|
<Timeline.Item key={line.id}>
|
||||||
|
<Space split={<Divider type="vertical" />} wrap>
|
||||||
|
<Link
|
||||||
|
to={`/manage/jobs/${jobid}?partsorderid=${line.parts_order.id}`}
|
||||||
|
>
|
||||||
|
{line.parts_order.order_number}
|
||||||
|
</Link>
|
||||||
|
<DateFormatter>{line.parts_order.order_date}</DateFormatter>
|
||||||
|
{line.parts_order.vendor.name}
|
||||||
|
</Space>
|
||||||
|
</Timeline.Item>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Timeline.Item>
|
||||||
|
{t("parts_orders.labels.notyetordered")}
|
||||||
|
</Timeline.Item>
|
||||||
|
)}
|
||||||
|
</Timeline>
|
||||||
|
</Col>
|
||||||
|
<Col md={24} lg={12}></Col>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ import {
|
|||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
WarningFilled,
|
WarningFilled,
|
||||||
EditFilled,
|
EditFilled,
|
||||||
|
PlusCircleTwoTone,
|
||||||
|
MinusCircleTwoTone,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { useMutation } from "@apollo/client";
|
import { useMutation } from "@apollo/client";
|
||||||
import {
|
import {
|
||||||
@@ -38,9 +40,11 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re
|
|||||||
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
|
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import JobCreateIOU from "../job-create-iou/job-create-iou.component";
|
import JobCreateIOU from "../job-create-iou/job-create-iou.component";
|
||||||
|
import JobLinesExpander from "./job-lines-expander.component";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
bodyshop: selectBodyshop,
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
});
|
});
|
||||||
@@ -53,6 +57,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function JobLinesComponent({
|
export function JobLinesComponent({
|
||||||
|
bodyshop,
|
||||||
jobRO,
|
jobRO,
|
||||||
technician,
|
technician,
|
||||||
setPartsOrderContext,
|
setPartsOrderContext,
|
||||||
@@ -72,6 +77,9 @@ export function JobLinesComponent({
|
|||||||
filteredInfo: {},
|
filteredInfo: {},
|
||||||
});
|
});
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const jobIsPrivate = bodyshop.md_ins_cos.find(
|
||||||
|
(c) => c.name === job.ins_co_nm
|
||||||
|
)?.private;
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@@ -283,7 +291,7 @@ export function JobLinesComponent({
|
|||||||
key: "actions",
|
key: "actions",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<div>
|
<div>
|
||||||
{record.manual_line && (
|
{(record.manual_line || jobIsPrivate) && (
|
||||||
<Space>
|
<Space>
|
||||||
<Button
|
<Button
|
||||||
disabled={jobRO}
|
disabled={jobRO}
|
||||||
@@ -449,6 +457,19 @@ export function JobLinesComponent({
|
|||||||
scroll={{
|
scroll={{
|
||||||
x: true,
|
x: true,
|
||||||
}}
|
}}
|
||||||
|
expandable={{
|
||||||
|
expandedRowRender: (record) => (
|
||||||
|
<JobLinesExpander jobline={record} jobid={job.id} />
|
||||||
|
),
|
||||||
|
rowExpandable: (record) => true,
|
||||||
|
//expandRowByClick: true,
|
||||||
|
expandIcon: ({ expanded, onExpand, record }) =>
|
||||||
|
expanded ? (
|
||||||
|
<MinusCircleTwoTone onClick={(e) => onExpand(record, e)} />
|
||||||
|
) : (
|
||||||
|
<PlusCircleTwoTone onClick={(e) => onExpand(record, e)} />
|
||||||
|
),
|
||||||
|
}}
|
||||||
onRow={(record, rowIndex) => {
|
onRow={(record, rowIndex) => {
|
||||||
return {
|
return {
|
||||||
onDoubleClick: (event) => {
|
onDoubleClick: (event) => {
|
||||||
@@ -462,7 +483,7 @@ export function JobLinesComponent({
|
|||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
rowSelection={{
|
rowSelection={{
|
||||||
selectedRowKeys: selectedLines.map((item) => item.id),
|
selectedRowKeys: selectedLines.map((item) => item && item.id),
|
||||||
onSelectAll: (selected, selectedRows, changeRows) => {
|
onSelectAll: (selected, selectedRows, changeRows) => {
|
||||||
setSelectedLines(selectedRows);
|
setSelectedLines(selectedRows);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -55,15 +55,17 @@ export function JobEmployeeAssignments({
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{bodyshop.employees.map((emp) => (
|
{bodyshop.employees
|
||||||
<Select.Option
|
.filter((emp) => emp.active)
|
||||||
value={emp.id}
|
.map((emp) => (
|
||||||
key={emp.id}
|
<Select.Option
|
||||||
name={`${emp.first_name} ${emp.last_name}`}
|
value={emp.id}
|
||||||
>
|
key={emp.id}
|
||||||
{`${emp.first_name} ${emp.last_name}`}
|
name={`${emp.first_name} ${emp.last_name}`}
|
||||||
</Select.Option>
|
>
|
||||||
))}
|
{`${emp.first_name} ${emp.last_name}`}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default function JobLinesBillRefernece({ jobline }) {
|
|||||||
{subletRequired && <WarningFilled />}
|
{subletRequired && <WarningFilled />}
|
||||||
{`${(billLine.actual_price * billLine.quantity).toFixed(2)} (${
|
{`${(billLine.actual_price * billLine.quantity).toFixed(2)} (${
|
||||||
billLine.bill.vendor.name
|
billLine.bill.vendor.name
|
||||||
})`}
|
} #${billLine.bill.invoice_number})`}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,6 +216,7 @@ export function JobLinesUpsertModalComponent({
|
|||||||
rules={[
|
rules={[
|
||||||
({ getFieldValue }) => ({
|
({ getFieldValue }) => ({
|
||||||
validator(rule, value) {
|
validator(rule, value) {
|
||||||
|
console.log(value);
|
||||||
if (!value || getFieldValue("part_type") !== "PAE") {
|
if (!value || getFieldValue("part_type") !== "PAE") {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
@@ -226,7 +227,10 @@ export function JobLinesUpsertModalComponent({
|
|||||||
}),
|
}),
|
||||||
({ getFieldValue }) => ({
|
({ getFieldValue }) => ({
|
||||||
validator(rule, value) {
|
validator(rule, value) {
|
||||||
if (!!getFieldValue("part_type") === !!value) {
|
console.log(value, !!value);
|
||||||
|
if (
|
||||||
|
!!getFieldValue("part_type") === (!!value || value === 0)
|
||||||
|
) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default function JobReconciliationBillsTable({
|
|||||||
dataIndex: "line_desc",
|
dataIndex: "line_desc",
|
||||||
key: "line_desc",
|
key: "line_desc",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
minWidth: "65rem",
|
width: "10rem",
|
||||||
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
||||||
@@ -72,11 +72,11 @@ export default function JobReconciliationBillsTable({
|
|||||||
state.sortedInfo.columnKey === "quantity" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "quantity" && state.sortedInfo.order,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("bills.fields.is_credit_memo"),
|
title: t("bills.fields.is_credit_memo_short"),
|
||||||
dataIndex: "is_credit_memo",
|
dataIndex: "is_credit_memo",
|
||||||
key: "is_credit_memo",
|
key: "is_credit_memo",
|
||||||
sorter: (a, b) => a.bill.is_credit_memo - b.bill.is_credit_memo,
|
sorter: (a, b) => a.bill.is_credit_memo - b.bill.is_credit_memo,
|
||||||
width: "8rem",
|
width: "3rem",
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "is_credit_memo" &&
|
state.sortedInfo.columnKey === "is_credit_memo" &&
|
||||||
state.sortedInfo.order,
|
state.sortedInfo.order,
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ export default function JobReconciliationModalComponent({ job, bills }) {
|
|||||||
.flat() || [];
|
.flat() || [];
|
||||||
|
|
||||||
const jobLineData = job.joblines.filter(
|
const jobLineData = job.joblines.filter(
|
||||||
(j) => j.part_type !== null && j.part_type !== "PAE"
|
(j) =>
|
||||||
|
(j.part_type !== null && j.part_type !== "PAE") ||
|
||||||
|
(j.line_desc &&
|
||||||
|
j.line_desc.toLowerCase().includes("towing") &&
|
||||||
|
j.lbr_op === "OP13")
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
SEARCH_JOBS_FOR_AUTOCOMPLETE,
|
SEARCH_JOBS_FOR_AUTOCOMPLETE,
|
||||||
} from "../../graphql/jobs.queries";
|
} from "../../graphql/jobs.queries";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
const JobSearchSelect = (
|
const JobSearchSelect = (
|
||||||
@@ -86,11 +87,9 @@ const JobSearchSelect = (
|
|||||||
<span>
|
<span>
|
||||||
{`${clm_no && o.clm_no ? `${o.clm_no} | ` : ""}${
|
{`${clm_no && o.clm_no ? `${o.clm_no} | ` : ""}${
|
||||||
o.ro_number || t("general.labels.na")
|
o.ro_number || t("general.labels.na")
|
||||||
} | ${o.ownr_ln || ""} ${o.ownr_fn || ""} ${
|
} | ${OwnerNameDisplayFunction(o)} | ${
|
||||||
o.ownr_co_nm ? ` ${o.ownr_co_num}` : ""
|
o.v_model_yr || ""
|
||||||
}| ${o.v_model_yr || ""} ${o.v_make_desc || ""} ${
|
} ${o.v_make_desc || ""} ${o.v_model_desc || ""}`}
|
||||||
o.v_model_desc || ""
|
|
||||||
}`}
|
|
||||||
</span>
|
</span>
|
||||||
<Tag>
|
<Tag>
|
||||||
<strong>{o.status}</strong>
|
<strong>{o.status}</strong>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Table } from "antd";
|
import { Space, Table } from "antd";
|
||||||
import Dinero from "dinero.js";
|
import Dinero from "dinero.js";
|
||||||
import React, { useMemo, useState } from "react";
|
import React, { useMemo, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -119,7 +119,18 @@ export default function JobTotalsTableLabor({ job }) {
|
|||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
</Table.Summary.Row>
|
</Table.Summary.Row>
|
||||||
<Table.Summary.Row>
|
<Table.Summary.Row>
|
||||||
<Table.Summary.Cell>{t("jobs.labels.mapa")}</Table.Summary.Cell>
|
<Table.Summary.Cell>
|
||||||
|
<Space>
|
||||||
|
{t("jobs.labels.mapa")}
|
||||||
|
{job.materials &&
|
||||||
|
job.materials.mapa &&
|
||||||
|
job.materials.mapa.cal_maxdlr &&
|
||||||
|
job.materials.mapa.cal_maxdlr > 0 &&
|
||||||
|
t("jobs.labels.threshhold", {
|
||||||
|
amount: job.materials.mapa.cal_maxdlr,
|
||||||
|
})}
|
||||||
|
</Space>
|
||||||
|
</Table.Summary.Cell>
|
||||||
<Table.Summary.Cell align="right">
|
<Table.Summary.Cell align="right">
|
||||||
<CurrencyFormatter>
|
<CurrencyFormatter>
|
||||||
{job.job_totals.rates.mapa.rate}
|
{job.job_totals.rates.mapa.rate}
|
||||||
@@ -133,7 +144,18 @@ export default function JobTotalsTableLabor({ job }) {
|
|||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
</Table.Summary.Row>
|
</Table.Summary.Row>
|
||||||
<Table.Summary.Row>
|
<Table.Summary.Row>
|
||||||
<Table.Summary.Cell>{t("jobs.labels.mash")}</Table.Summary.Cell>
|
<Table.Summary.Cell>
|
||||||
|
<Space wrap>
|
||||||
|
{t("jobs.labels.mash")}
|
||||||
|
{job.materials &&
|
||||||
|
job.materials.mash &&
|
||||||
|
job.materials.mash.cal_maxdlr &&
|
||||||
|
job.materials.mash.cal_maxdlr > 0 &&
|
||||||
|
t("jobs.labels.threshhold", {
|
||||||
|
amount: job.materials.mash.cal_maxdlr,
|
||||||
|
})}
|
||||||
|
</Space>
|
||||||
|
</Table.Summary.Cell>
|
||||||
<Table.Summary.Cell align="right">
|
<Table.Summary.Cell align="right">
|
||||||
<CurrencyFormatter>
|
<CurrencyFormatter>
|
||||||
{job.job_totals.rates.mash.rate}
|
{job.job_totals.rates.mash.rate}
|
||||||
|
|||||||
@@ -58,6 +58,15 @@ export default function JobsAdminDatesChange({ job }) {
|
|||||||
>
|
>
|
||||||
<FormDatePicker format="MM/DD/YYYY" />
|
<FormDatePicker format="MM/DD/YYYY" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item label={t("jobs.fields.date_towin")} name="date_towin">
|
||||||
|
<DateTimePicker />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.date_rentalresp")}
|
||||||
|
name="date_rentalresp"
|
||||||
|
>
|
||||||
|
<DateTimePicker />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.date_open")} name="date_open">
|
<Form.Item label={t("jobs.fields.date_open")} name="date_open">
|
||||||
<DateTimePicker />
|
<DateTimePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Wahtever is left in the existing lines, are lines that should be removed.
|
//Wahtever is left in the existing lines, are lines that should be removed.
|
||||||
|
|
||||||
const insertQueries = linesToInsert.reduce((acc, value, idx) => {
|
const insertQueries = linesToInsert.reduce((acc, value, idx) => {
|
||||||
return acc + generateInsertQuery(value, idx, jobId);
|
return acc + generateInsertQuery(value, idx, jobId);
|
||||||
}, "");
|
}, "");
|
||||||
@@ -49,6 +48,13 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
|
|||||||
const removeQueries = existingLines.reduce((acc, value, idx) => {
|
const removeQueries = existingLines.reduce((acc, value, idx) => {
|
||||||
return acc + generateRemoveQuery(value, idx);
|
return acc + generateRemoveQuery(value, idx);
|
||||||
}, "");
|
}, "");
|
||||||
|
console.log(insertQueries, updateQueries, removeQueries);
|
||||||
|
|
||||||
|
if ((insertQueries + updateQueries + removeQueries).trim() === "") {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
resolve(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
resolve(gql`
|
resolve(gql`
|
||||||
|
|||||||
@@ -220,12 +220,13 @@ export function JobsAvailableContainer({
|
|||||||
);
|
);
|
||||||
|
|
||||||
delete supp.joblines;
|
delete supp.joblines;
|
||||||
await client.mutate({
|
if (suppDelta !== null) {
|
||||||
mutation: gql`
|
await client.mutate({
|
||||||
${suppDelta}
|
mutation: gql`
|
||||||
`,
|
${suppDelta}
|
||||||
});
|
`,
|
||||||
|
});
|
||||||
|
}
|
||||||
const updateResult = await updateJob({
|
const updateResult = await updateJob({
|
||||||
variables: {
|
variables: {
|
||||||
jobId: selectedJob,
|
jobId: selectedJob,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { insertAuditTrail } from "../../redux/application/application.actions";
|
|||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import axios from "axios";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -53,6 +53,12 @@ export function JobsConvertButton({
|
|||||||
variables: { jobId: job.id, ...values },
|
variables: { jobId: job.id, ...values },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (values.ca_gst_registrant) {
|
||||||
|
await axios.post("/job/totalsssu", {
|
||||||
|
id: job.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!res.errors) {
|
if (!res.errors) {
|
||||||
refetch();
|
refetch();
|
||||||
notification["success"]({
|
notification["success"]({
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
|||||||
<Form.Item label={t("jobs.fields.date_open")} name="date_open">
|
<Form.Item label={t("jobs.fields.date_open")} name="date_open">
|
||||||
<DateTimePicker disabled={jobRO} />
|
<DateTimePicker disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item label={t("jobs.fields.date_towin")} name="date_towin">
|
||||||
|
<DateTimePicker disabled={jobRO} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label={t("jobs.fields.date_rentalresp")} name="date_rentalresp">
|
||||||
|
<DateTimePicker disabled={jobRO} />
|
||||||
|
</Form.Item>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
|
|
||||||
<FormRow header={t("jobs.forms.scheddates")}>
|
<FormRow header={t("jobs.forms.scheddates")}>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
Col,
|
Col,
|
||||||
Divider,
|
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
@@ -23,8 +22,8 @@ import FormItemPhone, {
|
|||||||
} from "../form-items-formatted/phone-form-item.component";
|
} from "../form-items-formatted/phone-form-item.component";
|
||||||
import Car from "../job-damage-visual/job-damage-visual.component";
|
import Car from "../job-damage-visual/job-damage-visual.component";
|
||||||
import JobsDetailChangeEstimator from "../jobs-detail-change-estimator/jobs-detail-change-estimator.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";
|
import JobsDetailChangeFileHandler from "../jobs-detail-change-filehandler/jobs-detail-change-filehandler.component";
|
||||||
|
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -220,15 +219,8 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
|||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Divider
|
|
||||||
orientation="left"
|
|
||||||
type="horizontal"
|
|
||||||
style={{ marginTop: ".8rem", float: "right" }}
|
|
||||||
>
|
|
||||||
{t("jobs.forms.appraiserinfo")}
|
|
||||||
</Divider>
|
|
||||||
|
|
||||||
<FormRow noDivider>
|
<FormRow header={t("jobs.forms.appraiserinfo")}>
|
||||||
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
|
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
|
||||||
<Input disabled={jobRO} />
|
<Input disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { connect } from "react-redux";
|
|||||||
import { Link, useHistory } from "react-router-dom";
|
import { Link, useHistory } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { CANCEL_APPOINTMENTS_BY_JOB_ID } from "../../graphql/appointments.queries";
|
||||||
import { DELETE_JOB, UPDATE_JOB, VOID_JOB } from "../../graphql/jobs.queries";
|
import { DELETE_JOB, UPDATE_JOB, VOID_JOB } from "../../graphql/jobs.queries";
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
@@ -56,6 +57,7 @@ export function JobsDetailHeaderActions({
|
|||||||
const [deleteJob] = useMutation(DELETE_JOB);
|
const [deleteJob] = useMutation(DELETE_JOB);
|
||||||
const [updateJob] = useMutation(UPDATE_JOB);
|
const [updateJob] = useMutation(UPDATE_JOB);
|
||||||
const [voidJob] = useMutation(VOID_JOB);
|
const [voidJob] = useMutation(VOID_JOB);
|
||||||
|
const [cancelAllAppointments] = useMutation(CANCEL_APPOINTMENTS_BY_JOB_ID);
|
||||||
const jobInProduction = useMemo(() => {
|
const jobInProduction = useMemo(() => {
|
||||||
return bodyshop.md_ro_statuses.production_statuses.includes(job.status);
|
return bodyshop.md_ro_statuses.production_statuses.includes(job.status);
|
||||||
}, [job, bodyshop.md_ro_statuses.production_statuses]);
|
}, [job, bodyshop.md_ro_statuses.production_statuses]);
|
||||||
@@ -121,6 +123,39 @@ export function JobsDetailHeaderActions({
|
|||||||
>
|
>
|
||||||
{t("jobs.actions.schedule")}
|
{t("jobs.actions.schedule")}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
disabled={job.status !== bodyshop.md_ro_statuses.default_scheduled}
|
||||||
|
>
|
||||||
|
<Popconfirm
|
||||||
|
title={t("general.labels.areyousure")}
|
||||||
|
okText="Yes"
|
||||||
|
cancelText="No"
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
disabled={job.status !== bodyshop.md_ro_statuses.default_scheduled}
|
||||||
|
onConfirm={async () => {
|
||||||
|
const jobUpdate = await cancelAllAppointments({
|
||||||
|
variables: {
|
||||||
|
jobid: job.id,
|
||||||
|
job: {
|
||||||
|
date_scheduled: null,
|
||||||
|
scheduled_in: null,
|
||||||
|
scheduled_completion: null,
|
||||||
|
status: bodyshop.md_ro_statuses.default_imported,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (!jobUpdate.errors) {
|
||||||
|
notification["success"]({
|
||||||
|
message: t("appointments.successes.canceled"),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
getPopupContainer={(trigger) => trigger.parentNode}
|
||||||
|
>
|
||||||
|
{t("menus.jobsactions.cancelallappointments")}
|
||||||
|
</Popconfirm>
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
disabled={
|
disabled={
|
||||||
!!job.intakechecklist ||
|
!!job.intakechecklist ||
|
||||||
@@ -401,6 +436,9 @@ export function JobsDetailHeaderActions({
|
|||||||
job: {
|
job: {
|
||||||
status: bodyshop.md_ro_statuses.default_void,
|
status: bodyshop.md_ro_statuses.default_void,
|
||||||
voided: true,
|
voided: true,
|
||||||
|
scheduled_in: null,
|
||||||
|
scheduled_completion: null,
|
||||||
|
inproduction: false,
|
||||||
},
|
},
|
||||||
note: [
|
note: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import "./jobs-detail-header.styles.scss";
|
|||||||
import JobsRelatedRos from "../jobs-related-ros/jobs-related-ros.component";
|
import JobsRelatedRos from "../jobs-related-ros/jobs-related-ros.component";
|
||||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||||
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
@@ -60,6 +61,12 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
);
|
);
|
||||||
}, [job.status, bodyshop.md_ro_statuses.post_production_statuses]);
|
}, [job.status, bodyshop.md_ro_statuses.post_production_statuses]);
|
||||||
|
|
||||||
|
const vehicleTitle = `${job.v_model_yr || ""} ${job.v_color || ""}
|
||||||
|
${job.v_make_desc || ""}
|
||||||
|
${job.v_model_desc || ""}`.trim();
|
||||||
|
|
||||||
|
const ownerTitle = OwnerNameDisplayFunction(job).trim();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]} style={{ alignItems: "stretch" }}>
|
<Row gutter={[16, 16]} style={{ alignItems: "stretch" }}>
|
||||||
<Col {...colSpan}>
|
<Col {...colSpan}>
|
||||||
@@ -152,9 +159,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
style={{ height: "100%" }}
|
style={{ height: "100%" }}
|
||||||
title={
|
title={
|
||||||
<Link to={disabled ? "#" : `/manage/owners/${job.owner.id}`}>
|
<Link to={disabled ? "#" : `/manage/owners/${job.owner.id}`}>
|
||||||
{`${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
{ownerTitle.length > 0
|
||||||
job.ownr_co_nm || ""
|
? ownerTitle
|
||||||
}`}
|
: t("owner.labels.noownerinfo")}
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
@@ -188,9 +195,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
: job.vehicle && `/manage/vehicles/${job.vehicle.id}`
|
: job.vehicle && `/manage/vehicles/${job.vehicle.id}`
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{`${job.v_model_yr || ""} ${job.v_color || ""}
|
{vehicleTitle.length > 0
|
||||||
${job.v_make_desc || ""}
|
? vehicleTitle
|
||||||
${job.v_model_desc || ""}`}
|
: t("vehicles.labels.novehinfo")}
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span></span>
|
<span></span>
|
||||||
|
|||||||
@@ -88,6 +88,33 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<CABCpvrtCalculator form={form} disabled={jobRO} />
|
<CABCpvrtCalculator form={form} disabled={jobRO} />
|
||||||
</Space>
|
</Space>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.auto_add_ats")}
|
||||||
|
name="auto_add_ats"
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
|
<Switch disabled={jobRO} />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item
|
||||||
|
nostyle
|
||||||
|
shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}
|
||||||
|
>
|
||||||
|
{() => {
|
||||||
|
if (form.getFieldValue("auto_add_ats"))
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.rate_ats")}
|
||||||
|
name="rate_ats"
|
||||||
|
initialValue={bodyshop.shoprates.rate_atp}
|
||||||
|
>
|
||||||
|
<CurrencyInput disabled={jobRO} />
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}}
|
||||||
|
</Form.Item>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
<FormRow>
|
<FormRow>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -100,7 +127,13 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
|||||||
label={t("jobs.fields.state_tax_rate")}
|
label={t("jobs.fields.state_tax_rate")}
|
||||||
name="state_tax_rate"
|
name="state_tax_rate"
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={1} precision={2} disabled={jobRO} autoComplete="new-password"/>
|
<InputNumber
|
||||||
|
min={0}
|
||||||
|
max={1}
|
||||||
|
precision={2}
|
||||||
|
disabled={jobRO}
|
||||||
|
autoComplete="new-password"
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.local_tax_rate")}
|
label={t("jobs.fields.local_tax_rate")}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import React from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function JobsFindModalComponent({
|
export default function JobsFindModalComponent({
|
||||||
selectedJob,
|
selectedJob,
|
||||||
@@ -43,15 +44,12 @@ export default function JobsFindModalComponent({
|
|||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.owner ? (
|
return record.owner ? (
|
||||||
<Link to={"/manage/owners/" + record.owner.id}>
|
<Link to={"/manage/owners/" + record.owner.id}>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
// t("jobs.errors.noowner")
|
<span>
|
||||||
<span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
</span>
|
||||||
}`}</span>
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import StartChatButton from "../chat-open-button/chat-open-button.component";
|
import StartChatButton from "../chat-open-button/chat-open-button.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -52,14 +52,12 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.ownerid ? (
|
return record.ownerid ? (
|
||||||
<Link to={"/manage/owners/" + record.ownerid}>
|
<Link to={"/manage/owners/" + record.ownerid}>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<span>
|
||||||
record.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
}`}</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
|||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -141,14 +142,12 @@ export function JobsList({ bodyshop }) {
|
|||||||
to={"/manage/owners/" + record.owner.id}
|
to={"/manage/owners/" + record.owner.id}
|
||||||
onClick={(e) => e.stopPropagation()}
|
onClick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<span>
|
||||||
record.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
}`}</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ export function JobNotesComponent({
|
|||||||
<EditFilled />
|
<EditFilled />
|
||||||
</Button>
|
</Button>
|
||||||
<PrintWrapperComponent
|
<PrintWrapperComponent
|
||||||
emailOnly
|
|
||||||
templateObject={{
|
templateObject={{
|
||||||
name: Templates.individual_job_note.key,
|
name: Templates.individual_job_note.key,
|
||||||
|
|
||||||
@@ -124,7 +123,7 @@ export function JobNotesComponent({
|
|||||||
messageObject={{
|
messageObject={{
|
||||||
subject: Templates.individual_job_note.subject,
|
subject: Templates.individual_job_note.subject,
|
||||||
}}
|
}}
|
||||||
id={record.id}
|
id={jobId}
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { QUERY_SEARCH_OWNER_BY_IDX } from "../../graphql/owners.queries";
|
|||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
import OwnerFindModalComponent from "./owner-find-modal.component";
|
import OwnerFindModalComponent from "./owner-find-modal.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function OwnerFindModalContainer({
|
export default function OwnerFindModalContainer({
|
||||||
loading,
|
loading,
|
||||||
@@ -30,9 +31,7 @@ export default function OwnerFindModalContainer({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (modalProps.visible && owner) {
|
if (modalProps.visible && owner) {
|
||||||
const s = `${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${
|
const s = OwnerNameDisplayFunction(owner);
|
||||||
owner.ownr_co_nm || ""
|
|
||||||
}`;
|
|
||||||
|
|
||||||
setSearchText(s.trim());
|
setSearchText(s.trim());
|
||||||
callSearchowners({ variables: { search: s.trim() } });
|
callSearchowners({ variables: { search: s.trim() } });
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { store } from "../../redux/store";
|
||||||
|
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)(OwnerNameDisplay);
|
||||||
|
|
||||||
|
export function OwnerNameDisplay({ bodyshop, ownerObject }) {
|
||||||
|
const emptyTest =
|
||||||
|
ownerObject.ownr_fn + ownerObject.ownr_ln + ownerObject.ownr_co_nm;
|
||||||
|
|
||||||
|
if (!emptyTest || emptyTest === "null" || emptyTest.trim() === "")
|
||||||
|
return "N/A";
|
||||||
|
|
||||||
|
if (bodyshop.last_name_first)
|
||||||
|
return `${ownerObject.ownr_ln || ""}, ${ownerObject.ownr_fn || ""} ${
|
||||||
|
ownerObject.ownr_co_nm || ""
|
||||||
|
}`.trim();
|
||||||
|
|
||||||
|
return `${ownerObject.ownr_fn || ""} ${ownerObject.ownr_ln || ""} ${
|
||||||
|
ownerObject.ownr_co_nm || ""
|
||||||
|
}`.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function OwnerNameDisplayFunction(ownerObject) {
|
||||||
|
const emptyTest =
|
||||||
|
ownerObject.ownr_fn + ownerObject.ownr_ln + ownerObject.ownr_co_nm;
|
||||||
|
|
||||||
|
if (!emptyTest || emptyTest === "null" || emptyTest.trim() === "")
|
||||||
|
return "N/A";
|
||||||
|
|
||||||
|
const rdxStore = store.getState();
|
||||||
|
|
||||||
|
if (rdxStore.user.bodyshop.last_name_first)
|
||||||
|
return `${ownerObject.ownr_ln || ""}, ${ownerObject.ownr_fn || ""} ${
|
||||||
|
ownerObject.ownr_co_nm || ""
|
||||||
|
}`.trim();
|
||||||
|
|
||||||
|
return `${ownerObject.ownr_fn || ""} ${ownerObject.ownr_ln || ""} ${
|
||||||
|
ownerObject.ownr_co_nm || ""
|
||||||
|
}`.trim();
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
SEARCH_OWNERS_FOR_AUTOCOMPLETE,
|
SEARCH_OWNERS_FOR_AUTOCOMPLETE,
|
||||||
} from "../../graphql/owners.queries";
|
} from "../../graphql/owners.queries";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
@@ -16,10 +17,8 @@ const OwnerSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => {
|
|||||||
SEARCH_OWNERS_FOR_AUTOCOMPLETE
|
SEARCH_OWNERS_FOR_AUTOCOMPLETE
|
||||||
);
|
);
|
||||||
|
|
||||||
const [
|
const [callIdSearch, { loading: idLoading, error: idError, data: idData }] =
|
||||||
callIdSearch,
|
useLazyQuery(SEARCH_OWNERS_BY_ID_FOR_AUTOCOMPLETE);
|
||||||
{ loading: idLoading, error: idError, data: idData },
|
|
||||||
] = useLazyQuery(SEARCH_OWNERS_BY_ID_FOR_AUTOCOMPLETE);
|
|
||||||
|
|
||||||
const executeSearch = (v) => {
|
const executeSearch = (v) => {
|
||||||
callSearch(v);
|
callSearch(v);
|
||||||
@@ -78,9 +77,7 @@ const OwnerSearchSelect = ({ value, onChange, onBlur, disabled }, ref) => {
|
|||||||
{theOptions
|
{theOptions
|
||||||
? theOptions.map((o) => (
|
? theOptions.map((o) => (
|
||||||
<Option key={o.id} value={o.id}>
|
<Option key={o.id} value={o.id}>
|
||||||
{`${o.ownr_ln || ""} ${o.ownr_fn || ""} ${
|
{`${OwnerNameDisplayFunction(o)} | ${o.ownr_addr1 || ""} `}
|
||||||
o.ownr_co_nm ? ` ${o.ownr_co_num}` : ""
|
|
||||||
}| ${o.ownr_addr1 || ""} `}
|
|
||||||
</Option>
|
</Option>
|
||||||
))
|
))
|
||||||
: null}
|
: null}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@ import React from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||||
|
import OwnerNameDisplay, {
|
||||||
|
OwnerNameDisplayFunction,
|
||||||
|
} from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function OwnerTagPopoverComponent({ job }) {
|
export default function OwnerTagPopoverComponent({ job }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const content = (
|
const content = (
|
||||||
@@ -10,9 +14,9 @@ export default function OwnerTagPopoverComponent({ job }) {
|
|||||||
<Row>
|
<Row>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Descriptions title={t("owners.labels.fromclaim")} column={1}>
|
<Descriptions title={t("owners.labels.fromclaim")} column={1}>
|
||||||
<Descriptions.Item key="1" label={t("jobs.fields.owner")}>{`${
|
<Descriptions.Item key="1" label={t("jobs.fields.owner")}>
|
||||||
job.ownr_fn || ""
|
<OwnerNameDisplay ownerObject={job} />
|
||||||
} ${job.ownr_ln || ""} ${job.ownr_co_nm || ""}`}</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item key="2" label={t("jobs.fields.ownr_ph1")}>
|
<Descriptions.Item key="2" label={t("jobs.fields.ownr_ph1")}>
|
||||||
<PhoneFormatter>{job.ownr_ph1 || ""}</PhoneFormatter>
|
<PhoneFormatter>{job.ownr_ph1 || ""}</PhoneFormatter>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
@@ -31,11 +35,9 @@ export default function OwnerTagPopoverComponent({ job }) {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={12}>
|
<Col span={12}>
|
||||||
<Descriptions title={t("owners.labels.fromowner")} column={1}>
|
<Descriptions title={t("owners.labels.fromowner")} column={1}>
|
||||||
<Descriptions.Item key="1" label={t("jobs.fields.owner")}>{`${
|
<Descriptions.Item key="1" label={t("jobs.fields.owner")}>
|
||||||
job.owner.ownr_fn || ""
|
<OwnerNameDisplay ownerObject={job.owner} />
|
||||||
} ${job.owner.ownr_ln || ""} ${
|
</Descriptions.Item>
|
||||||
job.owner.ownr_co_nm || ""
|
|
||||||
}`}</Descriptions.Item>
|
|
||||||
<Descriptions.Item key="2" label={t("jobs.fields.ownr_ph1")}>
|
<Descriptions.Item key="2" label={t("jobs.fields.ownr_ph1")}>
|
||||||
<PhoneFormatter>{job.owner.ownr_ph1 || ""}</PhoneFormatter>
|
<PhoneFormatter>{job.owner.ownr_ph1 || ""}</PhoneFormatter>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
@@ -68,9 +70,7 @@ export default function OwnerTagPopoverComponent({ job }) {
|
|||||||
<Popover placement="bottom" content={content}>
|
<Popover placement="bottom" content={content}>
|
||||||
<Tag color="cyan">
|
<Tag color="cyan">
|
||||||
<Link to={`/manage/owners/${job.owner.id}`}>
|
<Link to={`/manage/owners/${job.owner.id}`}>
|
||||||
{job.owner
|
{job.owner ? OwnerNameDisplayFunction(job) : t("jobs.errors.noowner")}
|
||||||
? `${job.ownr_co_nm || ""}${job.ownr_fn || ""} ${job.ownr_ln || ""}`
|
|
||||||
: t("jobs.errors.noowner")}
|
|
||||||
</Link>
|
</Link>
|
||||||
</Tag>
|
</Tag>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import React, { useState } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function OwnersListComponent({
|
export default function OwnersListComponent({
|
||||||
loading,
|
loading,
|
||||||
@@ -33,9 +34,7 @@ export default function OwnersListComponent({
|
|||||||
key: "name",
|
key: "name",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Link to={"/manage/owners/" + record.id}>
|
<Link to={"/manage/owners/" + record.id}>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import { notification } from "antd";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setPartnerVersion } from "../../redux/application/application.actions";
|
import { setPartnerVersion } from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import {store} from '../../redux/store'
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -21,45 +18,48 @@ export default connect(
|
|||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(PartnerPingComponent);
|
)(PartnerPingComponent);
|
||||||
|
|
||||||
export function PartnerPingComponent({ bodyshop, setPartnerVersion }) {
|
export function PartnerPingComponent({ bodyshop, }) {
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Create an scoped async function in the hook
|
// Create an scoped async function in the hook
|
||||||
async function checkPartnerStatus() {
|
|
||||||
if (!bodyshop) return;
|
|
||||||
try {
|
|
||||||
//if (process.env.NODE_ENV === "development") return;
|
|
||||||
const PartnerResponse = await axios.post("http://localhost:1337/ping/");
|
|
||||||
const { appver, qbpath } = PartnerResponse.data;
|
|
||||||
setPartnerVersion(appver);
|
|
||||||
console.log({ appver, qbpath });
|
|
||||||
if (
|
|
||||||
!qbpath &&
|
|
||||||
!(
|
|
||||||
bodyshop &&
|
|
||||||
(bodyshop.cdk_dealerid ||
|
|
||||||
bodyshop.pbs_serialnumber ||
|
|
||||||
bodyshop.accountingconfig.qbo)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
notification["error"]({
|
|
||||||
title: "",
|
|
||||||
message: t("general.messages.noacctfilepath"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
notification["error"]({
|
|
||||||
title: "",
|
|
||||||
message: t("general.messages.partnernotrunning"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Execute the created function directly
|
// Execute the created function directly
|
||||||
checkPartnerStatus();
|
checkPartnerStatus(bodyshop);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [bodyshop]);
|
}, [bodyshop]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function checkPartnerStatus(bodyshop) {
|
||||||
|
if (!bodyshop) return;
|
||||||
|
try {
|
||||||
|
//if (process.env.NODE_ENV === "development") return;
|
||||||
|
const PartnerResponse = await axios.post("http://localhost:1337/ping/");
|
||||||
|
// const {
|
||||||
|
// appver, //qbpath
|
||||||
|
// } = PartnerResponse.data;
|
||||||
|
console.log(PartnerResponse.data)
|
||||||
|
store.dispatch(setPartnerVersion(PartnerResponse.data));
|
||||||
|
// if (
|
||||||
|
// checkAcctPath &&
|
||||||
|
// !qbpath &&
|
||||||
|
// !(
|
||||||
|
// bodyshop &&
|
||||||
|
// (bodyshop.cdk_dealerid ||
|
||||||
|
// bodyshop.pbs_serialnumber ||
|
||||||
|
// bodyshop.accountingconfig.qbo)
|
||||||
|
// )
|
||||||
|
// ) {
|
||||||
|
// notification["error"]({
|
||||||
|
// title: "",
|
||||||
|
// message: i18n.t("general.messages.noacctfilepath"),
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
} catch (error) {
|
||||||
|
console.log("ImEX Online Partner is not running.", error);
|
||||||
|
// notification["error"]({
|
||||||
|
// title: "",
|
||||||
|
// message: i18n.t("general.messages.partnernotrunning"),
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -425,8 +425,6 @@ export function PartsOrderListTableComponent({
|
|||||||
placement="right"
|
placement="right"
|
||||||
onClose={() => handleOnRowClick(null)}
|
onClose={() => handleOnRowClick(null)}
|
||||||
visible={selectedpartsorder}
|
visible={selectedpartsorder}
|
||||||
//getContainer={false}
|
|
||||||
style={{ position: "absolute" }}
|
|
||||||
closable
|
closable
|
||||||
width={drawerPercentage}
|
width={drawerPercentage}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DeleteFilled, WarningFilled } from "@ant-design/icons";
|
import { DeleteFilled, WarningFilled, DownOutlined } from "@ant-design/icons";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import {
|
import {
|
||||||
Divider,
|
Divider,
|
||||||
@@ -9,6 +9,8 @@ import {
|
|||||||
Space,
|
Space,
|
||||||
Tag,
|
Tag,
|
||||||
Select,
|
Select,
|
||||||
|
Menu,
|
||||||
|
Dropdown,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -39,6 +41,7 @@ export function PartsOrderModalComponent({
|
|||||||
isReturn,
|
isReturn,
|
||||||
preferredMake,
|
preferredMake,
|
||||||
job,
|
job,
|
||||||
|
form,
|
||||||
}) {
|
}) {
|
||||||
const [sendType, setSendType] = sendTypeState;
|
const [sendType, setSendType] = sendTypeState;
|
||||||
const { OEConnection } = useTreatments(
|
const { OEConnection } = useTreatments(
|
||||||
@@ -52,6 +55,21 @@ export function PartsOrderModalComponent({
|
|||||||
bodyshop.imexshopid
|
bodyshop.imexshopid
|
||||||
);
|
);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const handleClick = ({ item, key, keyPath }) => {
|
||||||
|
form.setFieldsValue({ comments: item.props.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
const menu = (
|
||||||
|
<div>
|
||||||
|
<Menu onClick={handleClick}>
|
||||||
|
{bodyshop.md_parts_order_comment.map((comment, idx) => (
|
||||||
|
<Menu.Item value={comment.comment} key={idx}>
|
||||||
|
{comment.label}
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -73,6 +91,7 @@ export function PartsOrderModalComponent({
|
|||||||
options={vendorList}
|
options={vendorList}
|
||||||
disabled={isReturn}
|
disabled={isReturn}
|
||||||
preferredMake={preferredMake}
|
preferredMake={preferredMake}
|
||||||
|
showPhone
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -242,7 +261,23 @@ export function PartsOrderModalComponent({
|
|||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.List>
|
</Form.List>
|
||||||
<Form.Item name="comments" label={t("parts_orders.fields.comments")}>
|
<Form.Item
|
||||||
|
name="comments"
|
||||||
|
label={
|
||||||
|
<Space>
|
||||||
|
{t("parts_orders.fields.comments")}
|
||||||
|
<Dropdown overlay={menu}>
|
||||||
|
<a
|
||||||
|
className="ant-dropdown-link"
|
||||||
|
href=" #"
|
||||||
|
onClick={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
<DownOutlined />
|
||||||
|
</a>
|
||||||
|
</Dropdown>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Input.TextArea rows={3} />
|
<Input.TextArea rows={3} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
|
|||||||
@@ -196,6 +196,11 @@ export function PartsOrderModalContainer({
|
|||||||
(item) => item.id === values.vendorid
|
(item) => item.id === values.vendorid
|
||||||
)[0];
|
)[0];
|
||||||
|
|
||||||
|
let vendorEmails =
|
||||||
|
matchingVendor &&
|
||||||
|
matchingVendor.email &&
|
||||||
|
matchingVendor.email.split(RegExp("[;,]"));
|
||||||
|
|
||||||
GenerateDocument(
|
GenerateDocument(
|
||||||
{
|
{
|
||||||
name: isReturn
|
name: isReturn
|
||||||
@@ -206,7 +211,7 @@ export function PartsOrderModalContainer({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
to: matchingVendor ? [matchingVendor.email] : null,
|
to: matchingVendor ? vendorEmails : null,
|
||||||
replyTo: bodyshop.email,
|
replyTo: bodyshop.email,
|
||||||
subject: isReturn
|
subject: isReturn
|
||||||
? Templates.parts_return_slip.subject
|
? Templates.parts_return_slip.subject
|
||||||
@@ -341,6 +346,7 @@ export function PartsOrderModalContainer({
|
|||||||
<LoadingSpinner />
|
<LoadingSpinner />
|
||||||
) : (
|
) : (
|
||||||
<PartsOrderModalComponent
|
<PartsOrderModalComponent
|
||||||
|
form={form}
|
||||||
vendorList={(data && data.vendors) || []}
|
vendorList={(data && data.vendors) || []}
|
||||||
sendTypeState={sendTypeState}
|
sendTypeState={sendTypeState}
|
||||||
isReturn={isReturn}
|
isReturn={isReturn}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { alphaSort } from "../../utils/sorters";
|
|||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container";
|
import CaBcEtfTableModalContainer from "../ca-bc-etf-table-modal/ca-bc-etf-table-modal.container";
|
||||||
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test");
|
const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test");
|
||||||
|
|
||||||
@@ -78,14 +79,12 @@ export function PaymentsListPaginated({
|
|||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.job.owner ? (
|
return record.job.owner ? (
|
||||||
<Link to={"/manage/owners/" + record.job.owner.id}>
|
<Link to={"/manage/owners/" + record.job.owner.id}>
|
||||||
{`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.job.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>{`${record.job.ownr_fn || ""} ${record.job.ownr_ln || ""} ${
|
<span>
|
||||||
record.job.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
}`}</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import ProductionListColumnProductionNote from "../production-list-columns/produ
|
|||||||
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
|
||||||
import "./production-board-card.styles.scss";
|
import "./production-board-card.styles.scss";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
export default function ProductionBoardCard(
|
export default function ProductionBoardCard(
|
||||||
technician,
|
technician,
|
||||||
@@ -22,7 +23,7 @@ export default function ProductionBoardCard(
|
|||||||
) {
|
) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
let employee_body, employee_prep, employee_refinish; //employee_csr;
|
let employee_body, employee_prep, employee_refinish, employee_csr;
|
||||||
if (card.employee_body) {
|
if (card.employee_body) {
|
||||||
employee_body = bodyshop.employees.find((e) => e.id === card.employee_body);
|
employee_body = bodyshop.employees.find((e) => e.id === card.employee_body);
|
||||||
}
|
}
|
||||||
@@ -34,6 +35,9 @@ export default function ProductionBoardCard(
|
|||||||
(e) => e.id === card.employee_refinish
|
(e) => e.id === card.employee_refinish
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (card.employee_csr) {
|
||||||
|
employee_csr = bodyshop.employees.find((e) => e.id === card.employee_csr);
|
||||||
|
}
|
||||||
// if (card.employee_csr) {
|
// if (card.employee_csr) {
|
||||||
// employee_csr = bodyshop.employees.find((e) => e.id === card.employee_csr);
|
// employee_csr = bodyshop.employees.find((e) => e.id === card.employee_csr);
|
||||||
// }
|
// }
|
||||||
@@ -58,20 +62,22 @@ export default function ProductionBoardCard(
|
|||||||
<PauseCircleOutlined style={{ color: "orangered" }} />
|
<PauseCircleOutlined style={{ color: "orangered" }} />
|
||||||
)}
|
)}
|
||||||
<span style={{ fontWeight: "bolder" }}>
|
<span style={{ fontWeight: "bolder" }}>
|
||||||
{card.ro_number || t("general.labels.na")}
|
<Link
|
||||||
|
to={
|
||||||
|
technician
|
||||||
|
? `/tech/joblookup?selected=${card.id}`
|
||||||
|
: `/manage/jobs/${card.id}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{card.ro_number || t("general.labels.na")}
|
||||||
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
extra={
|
extra={
|
||||||
technician ? (
|
<Link to={{ search: `?selected=${card.id}` }}>
|
||||||
<Link to={`/tech/joblookup?selected=${card.id}`}>
|
<EyeFilled />
|
||||||
<EyeFilled />
|
</Link>
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
<Link to={`/manage/jobs/${card.id}`}>
|
|
||||||
<EyeFilled />
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Row>
|
<Row>
|
||||||
@@ -82,9 +88,9 @@ export default function ProductionBoardCard(
|
|||||||
card.ownr_co_nm || ""
|
card.ownr_co_nm || ""
|
||||||
}`}</div>
|
}`}</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="ellipses">{`${card.ownr_ln || ""}, ${
|
<div className="ellipses">
|
||||||
card.ownr_fn || ""
|
<OwnerNameDisplay ownerObject={card} />
|
||||||
} ${card.ownr_co_nm || ""}`}</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
@@ -131,11 +137,11 @@ export default function ProductionBoardCard(
|
|||||||
)} ${employee_refinish.last_name.charAt(0)}`
|
)} ${employee_refinish.last_name.charAt(0)}`
|
||||||
: ""
|
: ""
|
||||||
} ${card.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
} ${card.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
|
||||||
{/* <Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`C: ${
|
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`C: ${
|
||||||
employee_csr
|
employee_csr
|
||||||
? `${employee_csr.first_name} ${employee_csr.last_name}`
|
? `${employee_csr.first_name} ${employee_csr.last_name}`
|
||||||
: ""
|
: ""
|
||||||
}`}</Col> */}
|
}`}</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -131,6 +131,13 @@ export default function ProductionBoardKanbanCardSettings({
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
valuePropName="checked"
|
||||||
|
label={t("production.labels.stickyheader")}
|
||||||
|
name="stickyheader"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
|
import { SyncOutlined } from "@ant-design/icons";
|
||||||
import { useApolloClient } from "@apollo/client";
|
import { useApolloClient } from "@apollo/client";
|
||||||
import Board, { moveCard } from "@asseinfo/react-kanban";
|
import Board, { moveCard } from "@asseinfo/react-kanban";
|
||||||
//import "@asseinfo/react-kanban/dist/styles.css";
|
import { Button, Grid, notification, PageHeader, Space, Statistic } from "antd";
|
||||||
import "./production-board-kanban.styles.scss";
|
|
||||||
import { SyncOutlined } from "@ant-design/icons";
|
|
||||||
import { Grid, notification, Button, PageHeader, Space, Statistic } from "antd";
|
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
import { Sticky, StickyContainer } from "react-sticky";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import ProductionBoardCard from "../production-board-kanban-card/production-board-kanban-card.component";
|
|
||||||
import { createBoardData } from "./production-board-kanban.utils.js";
|
|
||||||
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
|
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
||||||
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
|
|
||||||
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";
|
import styled from "styled-components";
|
||||||
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
|
||||||
|
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
|
||||||
|
import ProductionBoardCard from "../production-board-kanban-card/production-board-kanban-card.component";
|
||||||
|
import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component";
|
||||||
|
import ProductionBoardKanbanCardSettings from "./production-board-kanban.card-settings.component";
|
||||||
|
//import "@asseinfo/react-kanban/dist/styles.css";
|
||||||
|
import "./production-board-kanban.styles.scss";
|
||||||
|
import { createBoardData } from "./production-board-kanban.utils.js";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
@@ -183,9 +184,52 @@ export function ProductionBoardKanbanComponent({
|
|||||||
: standardSizes[selectedBreakpoint[0]]
|
: standardSizes[selectedBreakpoint[0]]
|
||||||
: "250";
|
: "250";
|
||||||
|
|
||||||
|
const stickyHeader = {
|
||||||
|
renderColumnHeader: ({ title }) => (
|
||||||
|
<Sticky>
|
||||||
|
{({
|
||||||
|
style,
|
||||||
|
|
||||||
|
// the following are also available but unused in this example
|
||||||
|
isSticky,
|
||||||
|
wasSticky,
|
||||||
|
distanceFromTop,
|
||||||
|
distanceFromBottom,
|
||||||
|
calculatedHeight,
|
||||||
|
}) => (
|
||||||
|
<div
|
||||||
|
className="react-kanban-column-header"
|
||||||
|
style={{ ...style, zIndex: "99", backgroundColor: "#ddd" }}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Sticky>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const cardSettings =
|
||||||
|
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,
|
||||||
|
stickyheader: false,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container width={width}>
|
<Container width={width}>
|
||||||
<IndefiniteLoading loading={isMoving} />
|
<IndefiniteLoading loading={isMoving} />
|
||||||
|
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={
|
title={
|
||||||
<Space>
|
<Space>
|
||||||
@@ -215,34 +259,19 @@ export function ProductionBoardKanbanComponent({
|
|||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<ProductionListDetailComponent jobs={data} />
|
||||||
<Board
|
<StickyContainer>
|
||||||
children={boardLanes}
|
<Board
|
||||||
disableCardDrag={isMoving}
|
style={{ height: "100%" }}
|
||||||
renderCard={(card) =>
|
children={boardLanes}
|
||||||
ProductionBoardCard(
|
disableCardDrag={isMoving}
|
||||||
technician,
|
{...(cardSettings.stickyheader && stickyHeader)}
|
||||||
card,
|
renderCard={(card) =>
|
||||||
bodyshop,
|
ProductionBoardCard(technician, card, bodyshop, cardSettings)
|
||||||
associationSettings &&
|
}
|
||||||
associationSettings.kanban_settings &&
|
onCardDragEnd={handleDragEnd}
|
||||||
Object.keys(associationSettings.kanban_settings).length > 0
|
/>
|
||||||
? associationSettings.kanban_settings
|
</StickyContainer>
|
||||||
: {
|
|
||||||
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}
|
|
||||||
/>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export const createBoardData = (AllStatuses, Jobs, filter) => {
|
|||||||
include ||
|
include ||
|
||||||
j.employee_body === employeeId ||
|
j.employee_body === employeeId ||
|
||||||
j.employee_prep === employeeId ||
|
j.employee_prep === employeeId ||
|
||||||
|
j.employee_csr === employeeId ||
|
||||||
j.employee_refinish === employeeId;
|
j.employee_refinish === employeeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,9 +77,8 @@ export const createBoardData = (AllStatuses, Jobs, filter) => {
|
|||||||
|
|
||||||
Object.keys(DataGroupedByStatus).map((statusGroupKey) => {
|
Object.keys(DataGroupedByStatus).map((statusGroupKey) => {
|
||||||
try {
|
try {
|
||||||
boardLanes.columns.find(
|
boardLanes.columns.find((l) => l.id === statusGroupKey).cards =
|
||||||
(l) => l.id === statusGroupKey
|
sortByParentId(DataGroupedByStatus[statusGroupKey]);
|
||||||
).cards = sortByParentId(DataGroupedByStatus[statusGroupKey]);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("Error while creating board card", error);
|
console.log("Error while creating board card", error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import ProductionListColumnStatus from "./production-list-columns.status.compone
|
|||||||
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
||||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||||
import ProductionListColumnComment from "./production-list-columns.comment.component";
|
import ProductionListColumnComment from "./production-list-columns.comment.component";
|
||||||
|
import ProductionListColumnPartsReceived from "./production-list-columns.partsreceived.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
||||||
return [
|
return [
|
||||||
@@ -67,11 +69,7 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
dataIndex: "ownr",
|
dataIndex: "ownr",
|
||||||
key: "ownr",
|
key: "ownr",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => (
|
render: (text, record) => <OwnerNameDisplay ownerObject={record} />,
|
||||||
<span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}</span>
|
|
||||||
),
|
|
||||||
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "ownr" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "ownr" && state.sortedInfo.order,
|
||||||
@@ -81,6 +79,13 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
dataIndex: "vehicle",
|
dataIndex: "vehicle",
|
||||||
key: "vehicle",
|
key: "vehicle",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
sorter: (a, b) =>
|
||||||
|
alphaSort(
|
||||||
|
a.v_make_desc + a.v_model_desc,
|
||||||
|
b.v_make_desc + b.v_model_desc
|
||||||
|
),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "ownr" && state.sortedInfo.order,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<span>{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
|
<span>{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
|
||||||
record.v_model_desc || ""
|
record.v_model_desc || ""
|
||||||
@@ -96,7 +101,7 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "actual_in" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "actual_in" && state.sortedInfo.order,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListDate record={record} field="actual_in" time/>
|
<ProductionListDate record={record} field="actual_in" time />
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -477,6 +482,14 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18n.t("jobs.labels.parts_received"),
|
||||||
|
dataIndex: "parts_received",
|
||||||
|
key: "parts_received",
|
||||||
|
render: (text, record) => (
|
||||||
|
<ProductionListColumnPartsReceived record={record} />
|
||||||
|
),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
export default r;
|
export default r;
|
||||||
|
|||||||
@@ -116,15 +116,17 @@ export function ProductionListEmpAssignment({
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{bodyshop.employees.map((emp) => (
|
{bodyshop.employees
|
||||||
<Select.Option
|
.filter((emp) => emp.active)
|
||||||
value={emp.id}
|
.map((emp) => (
|
||||||
key={emp.id}
|
<Select.Option
|
||||||
name={`${emp.first_name} ${emp.last_name}`}
|
value={emp.id}
|
||||||
>
|
key={emp.id}
|
||||||
{`${emp.first_name} ${emp.last_name}`}
|
name={`${emp.first_name} ${emp.last_name}`}
|
||||||
</Select.Option>
|
>
|
||||||
))}
|
{`${emp.first_name} ${emp.last_name}`}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
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
|
||||||
|
)(ProductionListColumnPartsReceived);
|
||||||
|
|
||||||
|
export function ProductionListColumnPartsReceived({ bodyshop, record }) {
|
||||||
|
const amount = useMemo(() => {
|
||||||
|
const amount = record.joblines_status.reduce(
|
||||||
|
(acc, val) => {
|
||||||
|
acc.total += val.count;
|
||||||
|
acc.received =
|
||||||
|
val.status === bodyshop.md_order_statuses.default_received
|
||||||
|
? acc.received + val.count
|
||||||
|
: acc.received;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ total: 0, received: 0 }
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...amount,
|
||||||
|
percent:
|
||||||
|
amount.total !== 0
|
||||||
|
? ((amount.received / amount.total) * 100).toFixed(0) + "%"
|
||||||
|
: "N/A",
|
||||||
|
};
|
||||||
|
}, [record, bodyshop.md_order_statuses]);
|
||||||
|
|
||||||
|
return `${amount.percent} (${amount.received}/${amount.total})`;
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
|||||||
import ProductionRemoveButton from "../production-remove-button/production-remove-button.component";
|
import ProductionRemoveButton from "../production-remove-button/production-remove-button.component";
|
||||||
import JobAtChange from "../job-at-change/job-at-change.component";
|
import JobAtChange from "../job-at-change/job-at-change.component";
|
||||||
import { PrinterFilled } from "@ant-design/icons";
|
import { PrinterFilled } from "@ant-design/icons";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
@@ -107,9 +107,7 @@ export function ProductionListDetail({ jobs, setPrintCenterContext }) {
|
|||||||
{theJob.ins_co_nm || ""}
|
{theJob.ins_co_nm || ""}
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
<Descriptions.Item label={t("jobs.fields.owner")}>
|
<Descriptions.Item label={t("jobs.fields.owner")}>
|
||||||
{`${theJob.ownr_fn || ""} ${theJob.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={theJob} />
|
||||||
theJob.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
<StartChatButton
|
<StartChatButton
|
||||||
phone={data.jobs_by_pk.ownr_ph1}
|
phone={data.jobs_by_pk.ownr_ph1}
|
||||||
jobid={data.jobs_by_pk.id}
|
jobid={data.jobs_by_pk.id}
|
||||||
|
|||||||
@@ -8,8 +8,11 @@ import { connect } from "react-redux";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
const ProdTemplates = TemplateList("production");
|
const ProdTemplates = TemplateList("production");
|
||||||
const { production_by_technician_one, production_by_category_one } =
|
const {
|
||||||
TemplateList("special");
|
production_by_technician_one,
|
||||||
|
production_by_category_one,
|
||||||
|
production_by_repair_status_one,
|
||||||
|
} = TemplateList("special");
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -95,6 +98,29 @@ export function ProductionListPrint({ bodyshop }) {
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
))}
|
))}
|
||||||
</Menu.SubMenu>
|
</Menu.SubMenu>
|
||||||
|
<Menu.SubMenu
|
||||||
|
title={t("reportcenter.templates.production_by_repair_status_one")}
|
||||||
|
>
|
||||||
|
{bodyshop.md_ro_statuses.production_statuses.map((e) => (
|
||||||
|
<Menu.Item
|
||||||
|
key={e}
|
||||||
|
onClick={async () => {
|
||||||
|
setLoading(true);
|
||||||
|
await GenerateDocument(
|
||||||
|
{
|
||||||
|
name: production_by_repair_status_one.key,
|
||||||
|
variables: { status: e },
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
"p"
|
||||||
|
);
|
||||||
|
setLoading(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{e}
|
||||||
|
</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu.SubMenu>
|
||||||
</Menu>
|
</Menu>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -88,12 +88,6 @@ export function ProductionListTable({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleTableChange = (pagination, filters, sorter) => {
|
const handleTableChange = (pagination, filters, sorter) => {
|
||||||
console.log(
|
|
||||||
"🚀 ~ file: production-list-table.component.jsx ~ line 91 ~ pagination, filters, sorter",
|
|
||||||
pagination,
|
|
||||||
filters,
|
|
||||||
sorter
|
|
||||||
);
|
|
||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
filteredInfo: filters,
|
filteredInfo: filters,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { DateTimeFormatter } from "../../utils/DateFormatter";
|
|||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||||
import "./schedule-production-list.styles.scss";
|
import "./schedule-production-list.styles.scss";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
export default function ScheduleProductionList() {
|
export default function ScheduleProductionList() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [callQuery, { loading, error, data }] = useLazyQuery(
|
const [callQuery, { loading, error, data }] = useLazyQuery(
|
||||||
@@ -36,9 +36,7 @@ export default function ScheduleProductionList() {
|
|||||||
<td>
|
<td>
|
||||||
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
||||||
</td>
|
</td>
|
||||||
<td>{`${j.ownr_fn || ""} ${j.ownr_ln || ""} ${
|
<td><OwnerNameDisplay ownerObject={j} /></td>
|
||||||
j.ownr_co_nm || ""
|
|
||||||
}`}</td>
|
|
||||||
<td>{`${j.v_model_yr || ""} ${j.v_make_desc || ""} ${
|
<td>{`${j.v_model_yr || ""} ${j.v_make_desc || ""} ${
|
||||||
j.v_model_desc || ""
|
j.v_model_desc || ""
|
||||||
}`}</td>
|
}`}</td>
|
||||||
|
|||||||
@@ -142,6 +142,18 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.logo_img_header_margin")}
|
||||||
|
name={["logo_img_path", "headerMargin"]}
|
||||||
|
>
|
||||||
|
<InputNumber min={0} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.logo_img_footer_margin")}
|
||||||
|
name={["logo_img_path", "footerMargin"]}
|
||||||
|
>
|
||||||
|
<InputNumber min={0} />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("bodyshop.labels.accountingsetup")}>
|
<LayoutFormRow header={t("bodyshop.labels.accountingsetup")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -151,6 +163,27 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item shouldUpdate noStyle>
|
||||||
|
{() => (
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.labels.qbo_usa")}
|
||||||
|
shouldUpdate
|
||||||
|
valuePropName="checked"
|
||||||
|
name={["accountingconfig", "qbo_usa"]}
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
disabled={!form.getFieldValue(["accountingconfig", "qbo"])}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.labels.qbo_departmentid")}
|
||||||
|
name={["accountingconfig", "qbo_departmentid"]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.labels.accountingtiers")}
|
label={t("bodyshop.labels.accountingtiers")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -487,7 +520,6 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<CurrencyInput />
|
<CurrencyInput />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={["attach_pdf_to_email"]}
|
name={["attach_pdf_to_email"]}
|
||||||
label={t("bodyshop.fields.attach_pdf_to_email")}
|
label={t("bodyshop.fields.attach_pdf_to_email")}
|
||||||
@@ -495,6 +527,18 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={["md_from_emails"]}
|
||||||
|
label={t("bodyshop.fields.md_from_emails")}
|
||||||
|
// rules={[
|
||||||
|
// {
|
||||||
|
// //message: t("general.validation.required"),
|
||||||
|
// type: "array",
|
||||||
|
// },
|
||||||
|
// ]}
|
||||||
|
>
|
||||||
|
<Select mode="tags" />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={["md_email_cc", "parts_order"]}
|
name={["md_email_cc", "parts_order"]}
|
||||||
label={t("bodyshop.fields.md_email_cc", { template: "parts_order" })}
|
label={t("bodyshop.fields.md_email_cc", { template: "parts_order" })}
|
||||||
@@ -514,6 +558,13 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={["bill_allow_post_to_closed"]}
|
||||||
|
label={t("bodyshop.fields.bill_allow_post_to_closed")}
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={["md_ded_notes"]}
|
name={["md_ded_notes"]}
|
||||||
label={t("bodyshop.fields.md_ded_notes")}
|
label={t("bodyshop.fields.md_ded_notes")}
|
||||||
@@ -526,6 +577,13 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Select mode="tags" />
|
<Select mode="tags" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={["last_name_first"]}
|
||||||
|
label={t("bodyshop.fields.last_name_first")}
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}>
|
<LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}>
|
||||||
<Form.List name={["md_messaging_presets"]}>
|
<Form.List name={["md_messaging_presets"]}>
|
||||||
@@ -760,14 +818,23 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Space>
|
<Form.Item
|
||||||
<Form.Item
|
label={t("bodyshop.fields.md_ins_co.zip")}
|
||||||
label={t("bodyshop.fields.md_ins_co.zip")}
|
key={`${index}zip`}
|
||||||
key={`${index}zip`}
|
name={[field.name, "zip"]}
|
||||||
name={[field.name, "zip"]}
|
>
|
||||||
>
|
<Input />
|
||||||
<Input />
|
</Form.Item>
|
||||||
</Form.Item>
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.md_ins_co.private")}
|
||||||
|
key={`${index}private`}
|
||||||
|
name={[field.name, "private"]}
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Space wrap>
|
||||||
<DeleteFilled
|
<DeleteFilled
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
remove(field.name);
|
remove(field.name);
|
||||||
@@ -1260,6 +1327,72 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
}}
|
}}
|
||||||
</Form.List>
|
</Form.List>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
<LayoutFormRow grow header={t("bodyshop.fields.md_parts_order_comment")}>
|
||||||
|
<Form.List name={["md_parts_order_comment"]}>
|
||||||
|
{(fields, { add, remove, move }) => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{fields.map((field, index) => (
|
||||||
|
<Form.Item key={field.key}>
|
||||||
|
<LayoutFormRow noDivider>
|
||||||
|
<Form.Item
|
||||||
|
label={t("general.labels.label")}
|
||||||
|
key={`${index}label`}
|
||||||
|
name={[field.name, "label"]}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("parts_orders.fields.comments")}
|
||||||
|
key={`${index}comment`}
|
||||||
|
name={[field.name, "comment"]}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Space wrap>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ export default function ShopInfoSchedulingComponent({ form }) {
|
|||||||
>
|
>
|
||||||
<Select mode="tags" />
|
<Select mode="tags" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={["ss_configuration", "dailyhrslimit"]}
|
||||||
|
label={t("bodyshop.fields.ss_configuration.dailyhrslimit")}
|
||||||
|
>
|
||||||
|
<InputNumber min={0} />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<Divider orientation="left">{t("bodyshop.labels.workingdays")}</Divider>
|
<Divider orientation="left">{t("bodyshop.labels.workingdays")}</Divider>
|
||||||
<Space wrap size="large">
|
<Space wrap size="large">
|
||||||
|
|||||||
@@ -81,7 +81,10 @@ export function SignInComponent({
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{signInError ? (
|
{signInError ? (
|
||||||
<AlertComponent type="error" message={signInError.message} />
|
<AlertComponent
|
||||||
|
type="error"
|
||||||
|
message={t(`users.errors.signinerror.${signInError.code}`)}
|
||||||
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<Button
|
<Button
|
||||||
className="login-btn"
|
className="login-btn"
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import AlertComponent from "../alert/alert.component";
|
|||||||
import DataLabel from "../data-label/data-label.component";
|
import DataLabel from "../data-label/data-label.component";
|
||||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
import TechClockOffButton from "../tech-job-clock-out-button/tech-job-clock-out-button.component";
|
import TechClockOffButton from "../tech-job-clock-out-button/tech-job-clock-out-button.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
@@ -60,11 +61,9 @@ export function TechClockedInList({ technician }) {
|
|||||||
<Card
|
<Card
|
||||||
title={
|
title={
|
||||||
<Link to={`/tech/joblookup?selected=${ticket.job.id}`}>
|
<Link to={`/tech/joblookup?selected=${ticket.job.id}`}>
|
||||||
{`${ticket.job.ro_number || t("general.labels.na")} ${
|
{`${
|
||||||
ticket.job.ownr_fn || ""
|
ticket.job.ro_number || t("general.labels.na")
|
||||||
} ${ticket.job.ownr_ln || ""} ${
|
} ${OwnerNameDisplayFunction(ticket.job)}`}
|
||||||
ticket.job.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
actions={[
|
actions={[
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
|||||||
import { onlyUnique } from "../../utils/arrayHelper";
|
import { onlyUnique } from "../../utils/arrayHelper";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -108,9 +109,9 @@ export function TechLookupJobsList({ bodyshop }) {
|
|||||||
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<span>
|
||||||
record.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
}`}</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -237,7 +237,7 @@ export function TimeTicketModalComponent({
|
|||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
t("timetickets.validation.clockoffwithoutclockon")
|
t("timetickets.validation.clockoffwithoutclockon")
|
||||||
);
|
);
|
||||||
if (!value.isSameOrAfter(clockon))
|
if (value && !value.isSameOrAfter(clockon))
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
t("timetickets.validation.clockoffmustbeafterclockon")
|
t("timetickets.validation.clockoffmustbeafterclockon")
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
|
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
|
||||||
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -34,9 +35,7 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
|
|||||||
key: "owner",
|
key: "owner",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Link to={`/manage/owners/${record.owner.id}`}>
|
<Link to={`/manage/owners/${record.owner.id}`}>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { HeartOutlined } from "@ant-design/icons";
|
import { HeartOutlined } from "@ant-design/icons";
|
||||||
import { Select, Tag } from "antd";
|
import { Select, Space, Tag } from "antd";
|
||||||
import React, { forwardRef, useEffect, useState } from "react";
|
import React, { forwardRef, useEffect, useState } from "react";
|
||||||
|
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
//To be used as a form element only.
|
//To be used as a form element only.
|
||||||
|
|
||||||
const VendorSearchSelect = (
|
const VendorSearchSelect = (
|
||||||
{ value, onChange, options, onSelect, disabled, preferredMake },
|
{ value, onChange, options, onSelect, disabled, preferredMake, showPhone },
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const [option, setOption] = useState(value);
|
const [option, setOption] = useState(value);
|
||||||
@@ -35,6 +36,7 @@ const VendorSearchSelect = (
|
|||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
|
dropdownMatchSelectWidth={false}
|
||||||
onChange={setOption}
|
onChange={setOption}
|
||||||
optionFilterProp="name"
|
optionFilterProp="name"
|
||||||
onSelect={onSelect}
|
onSelect={onSelect}
|
||||||
@@ -50,10 +52,15 @@ const VendorSearchSelect = (
|
|||||||
>
|
>
|
||||||
<div className="imex-flex-row">
|
<div className="imex-flex-row">
|
||||||
<div style={{ flex: 1 }}>{o.name}</div>
|
<div style={{ flex: 1 }}>{o.name}</div>
|
||||||
<HeartOutlined />
|
<Space style={{ marginLeft: "1rem" }}>
|
||||||
{o.discount && o.discount !== 0 ? (
|
<HeartOutlined style={{ color: "red" }} />
|
||||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
{o.phone && showPhone && (
|
||||||
) : null}
|
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||||
|
)}
|
||||||
|
{o.discount && o.discount !== 0 ? (
|
||||||
|
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||||
|
) : null}
|
||||||
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
</Option>
|
</Option>
|
||||||
))
|
))
|
||||||
@@ -64,9 +71,14 @@ const VendorSearchSelect = (
|
|||||||
<div className="imex-flex-row" style={{ width: "100%" }}>
|
<div className="imex-flex-row" style={{ width: "100%" }}>
|
||||||
<div style={{ flex: 1 }}>{o.name}</div>
|
<div style={{ flex: 1 }}>{o.name}</div>
|
||||||
|
|
||||||
{o.discount && o.discount !== 0 ? (
|
<Space style={{ marginLeft: "1rem" }}>
|
||||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
{o.phone && showPhone && (
|
||||||
) : null}
|
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||||
|
)}
|
||||||
|
{o.discount && o.discount !== 0 ? (
|
||||||
|
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||||
|
) : null}
|
||||||
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
</Option>
|
</Option>
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ export default function VendorsFormComponent({
|
|||||||
formLoading,
|
formLoading,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
responsibilityCenters,
|
responsibilityCenters,
|
||||||
|
selectedvendor,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
@@ -52,7 +53,12 @@ export default function VendorsFormComponent({
|
|||||||
>
|
>
|
||||||
{t("general.actions.save")}
|
{t("general.actions.save")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="danger" onClick={handleDelete} loading={formLoading}>
|
<Button
|
||||||
|
type="danger"
|
||||||
|
disabled={selectedvendor === "new"}
|
||||||
|
onClick={handleDelete}
|
||||||
|
loading={formLoading}
|
||||||
|
>
|
||||||
{t("general.actions.delete")}
|
{t("general.actions.delete")}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
@@ -109,12 +115,14 @@ export default function VendorsFormComponent({
|
|||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("vendors.fields.email")}
|
label={t("vendors.fields.email")}
|
||||||
rules={[
|
rules={
|
||||||
{
|
[
|
||||||
type: "email",
|
// {
|
||||||
message: t("general.validation.invalidemail"),
|
// type: "email",
|
||||||
},
|
// message: t("general.validation.invalidemail"),
|
||||||
]}
|
// },
|
||||||
|
]
|
||||||
|
}
|
||||||
name="email"
|
name="email"
|
||||||
>
|
>
|
||||||
<FormItemEmail email={getFieldValue("email")} />
|
<FormItemEmail email={getFieldValue("email")} />
|
||||||
|
|||||||
@@ -39,30 +39,30 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
const [insertvendor] = useMutation(INSERT_NEW_VENDOR);
|
const [insertvendor] = useMutation(INSERT_NEW_VENDOR);
|
||||||
const [deleteVendor] = useMutation(DELETE_VENDOR);
|
const [deleteVendor] = useMutation(DELETE_VENDOR);
|
||||||
|
|
||||||
const handleDelete = () => {
|
const handleDelete = async () => {
|
||||||
setFormLoading(true);
|
setFormLoading(true);
|
||||||
deleteVendor({
|
const result = await deleteVendor({
|
||||||
variables: { id: selectedvendor },
|
variables: { id: selectedvendor },
|
||||||
refetchQueries: ["QUERY_ALL_VENDORS"],
|
refetchQueries: ["QUERY_ALL_VENDORS"],
|
||||||
})
|
});
|
||||||
.then((r) => {
|
console.log(result);
|
||||||
notification["success"]({
|
if (result.errors) {
|
||||||
message: t("vendors.successes.deleted"),
|
notification["error"]({
|
||||||
});
|
message: t("vendors.errors.deleting"),
|
||||||
delete search.selectedvendor;
|
|
||||||
history.push({ search: queryString.stringify(search) });
|
|
||||||
if (refetch)
|
|
||||||
refetch().then((r) => {
|
|
||||||
form.resetFields();
|
|
||||||
});
|
|
||||||
setFormLoading(false);
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
notification["error"]({
|
|
||||||
message: t("vendors.errors.deleting"),
|
|
||||||
});
|
|
||||||
setFormLoading(false);
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
notification["success"]({
|
||||||
|
message: t("vendors.successes.deleted"),
|
||||||
|
});
|
||||||
|
delete search.selectedvendor;
|
||||||
|
history.push({ search: queryString.stringify(search) });
|
||||||
|
if (refetch)
|
||||||
|
refetch().then((r) => {
|
||||||
|
form.resetFields();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setFormLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (values) => {
|
||||||
@@ -139,6 +139,7 @@ function VendorsFormContainer({ refetch, bodyshop }) {
|
|||||||
formLoading={formLoading}
|
formLoading={formLoading}
|
||||||
handleDelete={handleDelete}
|
handleDelete={handleDelete}
|
||||||
responsibilityCenters={bodyshop.md_responsibility_centers || null}
|
responsibilityCenters={bodyshop.md_responsibility_centers || null}
|
||||||
|
selectedvendor={selectedvendor}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
t("vendors.labels.noneselected")
|
t("vendors.labels.noneselected")
|
||||||
|
|||||||
@@ -245,6 +245,27 @@ export const CANCEL_APPOINTMENT_BY_ID = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const CANCEL_APPOINTMENTS_BY_JOB_ID = gql`
|
||||||
|
mutation CANCEL_APPOINTMENTS_BY_JOB_ID($jobid: uuid!, $job: jobs_set_input) {
|
||||||
|
update_appointments(
|
||||||
|
where: { _and: { jobid: { _eq: $jobid }, arrived: { _eq: false } } }
|
||||||
|
_set: { canceled: true }
|
||||||
|
) {
|
||||||
|
returning {
|
||||||
|
id
|
||||||
|
canceled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
update_jobs_by_pk(pk_columns: { id: $jobid }, _set: $job) {
|
||||||
|
date_scheduled
|
||||||
|
id
|
||||||
|
scheduled_in
|
||||||
|
scheduled_completion
|
||||||
|
status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const QUERY_APPOINTMENTS_BY_JOBID = gql`
|
export const QUERY_APPOINTMENTS_BY_JOBID = gql`
|
||||||
query QUERY_APPOINTMENTS_BY_JOBID($jobid: uuid!) {
|
query QUERY_APPOINTMENTS_BY_JOBID($jobid: uuid!) {
|
||||||
appointments(where: { jobid: { _eq: $jobid } }, order_by: { start: desc }) {
|
appointments(where: { jobid: { _eq: $jobid } }, order_by: { start: desc }) {
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ export const UPDATE_BILL_LINE = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
export const DELETE_BILL_LINE = gql`
|
||||||
|
mutation DELETE_BILL_LINE($id: uuid!) {
|
||||||
|
delete_billlines_by_pk(id: $id) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const INSERT_NEW_BILL_LINES = gql`
|
export const INSERT_NEW_BILL_LINES = gql`
|
||||||
mutation INSERT_NEW_BILL_LINES($billLines: [billlines_insert_input!]!) {
|
mutation INSERT_NEW_BILL_LINES($billLines: [billlines_insert_input!]!) {
|
||||||
|
|||||||
@@ -101,6 +101,11 @@ export const QUERY_BODYSHOP = gql`
|
|||||||
md_filehandlers
|
md_filehandlers
|
||||||
md_email_cc
|
md_email_cc
|
||||||
timezone
|
timezone
|
||||||
|
ss_configuration
|
||||||
|
md_from_emails
|
||||||
|
last_name_first
|
||||||
|
md_parts_order_comment
|
||||||
|
bill_allow_post_to_closed
|
||||||
employees {
|
employees {
|
||||||
user_email
|
user_email
|
||||||
id
|
id
|
||||||
@@ -199,6 +204,11 @@ export const UPDATE_SHOP = gql`
|
|||||||
md_filehandlers
|
md_filehandlers
|
||||||
md_email_cc
|
md_email_cc
|
||||||
timezone
|
timezone
|
||||||
|
ss_configuration
|
||||||
|
md_from_emails
|
||||||
|
last_name_first
|
||||||
|
md_parts_order_comment
|
||||||
|
bill_allow_post_to_closed
|
||||||
employees {
|
employees {
|
||||||
id
|
id
|
||||||
first_name
|
first_name
|
||||||
@@ -266,7 +276,6 @@ export const QUERY_DELIVER_CHECKLIST = gql`
|
|||||||
ro_number
|
ro_number
|
||||||
actual_completion
|
actual_completion
|
||||||
actual_delivery
|
actual_delivery
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ export const GET_LINE_TICKET_BY_PK = gql`
|
|||||||
employeeid
|
employeeid
|
||||||
memo
|
memo
|
||||||
flat_rate
|
flat_rate
|
||||||
|
clockon
|
||||||
|
clockoff
|
||||||
employee {
|
employee {
|
||||||
id
|
id
|
||||||
first_name
|
first_name
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ export const QUERY_EXACT_JOB_IN_PRODUCTION = gql`
|
|||||||
employee_refinish
|
employee_refinish
|
||||||
employee_prep
|
employee_prep
|
||||||
employee_csr
|
employee_csr
|
||||||
|
joblines_status {
|
||||||
|
part_type
|
||||||
|
status
|
||||||
|
count
|
||||||
|
}
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: {
|
where: {
|
||||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
@@ -219,6 +224,11 @@ export const QUERY_EXACT_JOBS_IN_PRODUCTION = gql`
|
|||||||
employee_refinish
|
employee_refinish
|
||||||
employee_prep
|
employee_prep
|
||||||
employee_csr
|
employee_csr
|
||||||
|
joblines_status {
|
||||||
|
part_type
|
||||||
|
status
|
||||||
|
count
|
||||||
|
}
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: {
|
where: {
|
||||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
@@ -294,6 +304,11 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
|
|||||||
employee_prep
|
employee_prep
|
||||||
employee_csr
|
employee_csr
|
||||||
suspended
|
suspended
|
||||||
|
joblines_status {
|
||||||
|
part_type
|
||||||
|
status
|
||||||
|
count
|
||||||
|
}
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: {
|
where: {
|
||||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
@@ -595,6 +610,9 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
ca_gst_registrant
|
ca_gst_registrant
|
||||||
ownerid
|
ownerid
|
||||||
ded_note
|
ded_note
|
||||||
|
materials
|
||||||
|
auto_add_ats
|
||||||
|
rate_ats
|
||||||
owner {
|
owner {
|
||||||
id
|
id
|
||||||
ownr_fn
|
ownr_fn
|
||||||
@@ -649,6 +667,8 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
date_invoiced
|
date_invoiced
|
||||||
date_last_contacted
|
date_last_contacted
|
||||||
date_next_contact
|
date_next_contact
|
||||||
|
date_towin
|
||||||
|
date_rentalresp
|
||||||
date_exported
|
date_exported
|
||||||
status
|
status
|
||||||
owner_owing
|
owner_owing
|
||||||
@@ -696,20 +716,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
joblineid
|
joblineid
|
||||||
bill {
|
bill {
|
||||||
id
|
id
|
||||||
vendor {
|
invoice_number
|
||||||
id
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parts_order_lines {
|
|
||||||
id
|
|
||||||
parts_order {
|
|
||||||
id
|
|
||||||
order_number
|
|
||||||
comments
|
|
||||||
order_date
|
|
||||||
user_email
|
|
||||||
vendor {
|
vendor {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -1096,6 +1103,15 @@ export const VOID_JOB = gql`
|
|||||||
insert_notes(objects: $note) {
|
insert_notes(objects: $note) {
|
||||||
affected_rows
|
affected_rows
|
||||||
}
|
}
|
||||||
|
update_appointments(
|
||||||
|
where: { jobid: { _eq: $jobId } }
|
||||||
|
_set: { canceled: true }
|
||||||
|
) {
|
||||||
|
returning {
|
||||||
|
id
|
||||||
|
canceled
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -2086,3 +2102,23 @@ export const DELETE_RELATED_RO = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
export const GET_JOB_LINE_ORDERS = gql`
|
||||||
|
query GET_JOB_LINE_ORDERS($joblineid: uuid!) {
|
||||||
|
parts_order_lines(where: { job_line_id: { _eq: $joblineid } }) {
|
||||||
|
id
|
||||||
|
act_price
|
||||||
|
parts_order {
|
||||||
|
id
|
||||||
|
order_date
|
||||||
|
order_number
|
||||||
|
orderedby
|
||||||
|
return
|
||||||
|
comments
|
||||||
|
vendor {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export const QUERY_ALL_VENDORS_FOR_ORDER = gql`
|
|||||||
discount
|
discount
|
||||||
email
|
email
|
||||||
active
|
active
|
||||||
|
phone
|
||||||
}
|
}
|
||||||
jobs(where: { id: { _eq: $jobId } }) {
|
jobs(where: { id: { _eq: $jobId } }) {
|
||||||
v_make_desc
|
v_make_desc
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import * as Sentry from "@sentry/react";
|
|||||||
import "antd/dist/antd.less";
|
import "antd/dist/antd.less";
|
||||||
import Dinero from "dinero.js";
|
import Dinero from "dinero.js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactDOM from "react-dom";
|
import { createRoot } from "react-dom/client";
|
||||||
import { Provider } from "react-redux";
|
import { Provider } from "react-redux";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import { PersistGate } from "redux-persist/integration/react";
|
import { PersistGate } from "redux-persist/integration/react";
|
||||||
@@ -39,7 +39,9 @@ if (process.env.NODE_ENV !== "development") {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render(
|
const container = document.getElementById("root");
|
||||||
|
const root = createRoot(container); // createRoot(container!) if you use TypeScript
|
||||||
|
root.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<PersistGate
|
<PersistGate
|
||||||
@@ -49,48 +51,7 @@ ReactDOM.render(
|
|||||||
<AppContainer />
|
<AppContainer />
|
||||||
</PersistGate>
|
</PersistGate>
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</Provider>,
|
</Provider>
|
||||||
document.getElementById("root")
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// const onServiceWorkerUpdate = (registration) => {
|
|
||||||
// console.log("onServiceWorkerUpdate", registration);
|
|
||||||
|
|
||||||
// const btn = (
|
|
||||||
// <Space flex>
|
|
||||||
// <Button
|
|
||||||
// onClick={async () => {
|
|
||||||
// window.open("https://imex-online.noticeable.news/", "_blank");
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {i18n.t("general.actions.viewreleasenotes")}
|
|
||||||
// </Button>
|
|
||||||
// <Button
|
|
||||||
// type="primary"
|
|
||||||
// onClick={async () => {
|
|
||||||
// if (registration && registration.waiting) {
|
|
||||||
// await registration.unregister();
|
|
||||||
// // Makes Workbox call skipWaiting()
|
|
||||||
// registration.waiting.postMessage({ type: "SKIP_WAITING" });
|
|
||||||
// // Once the service worker is unregistered, we can reload the page to let
|
|
||||||
// // the browser download a fresh copy of our app (invalidating the cache)
|
|
||||||
// window.location.reload();
|
|
||||||
// }
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {i18n.t("general.actions.refresh")}
|
|
||||||
// </Button>
|
|
||||||
// </Space>
|
|
||||||
// );
|
|
||||||
// notification.open({
|
|
||||||
// icon: <AlertOutlined />,
|
|
||||||
// message: i18n.t("general.messages.newversiontitle"),
|
|
||||||
// description: i18n.t("general.messages.newversionmessage"),
|
|
||||||
// duration: 0,
|
|
||||||
// btn,
|
|
||||||
// key: "updateavailable",
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// serviceWorkerRegistration.register({ onUpdate: onServiceWorkerUpdate });
|
|
||||||
reportWebVitals();
|
reportWebVitals();
|
||||||
|
|||||||
@@ -5,16 +5,19 @@ import { connect } from "react-redux";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import AccountingPayablesTable from "../../components/accounting-payables-table/accounting-payables-table.component";
|
import AccountingPayablesTable from "../../components/accounting-payables-table/accounting-payables-table.component";
|
||||||
import AlertComponent from "../../components/alert/alert.component";
|
import AlertComponent from "../../components/alert/alert.component";
|
||||||
|
import { checkPartnerStatus } from "../../components/partner-ping/partner-ping.component";
|
||||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||||
import { QUERY_BILLS_FOR_EXPORT } from "../../graphql/accounting.queries";
|
import { QUERY_BILLS_FOR_EXPORT } from "../../graphql/accounting.queries";
|
||||||
import {
|
import {
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
|
import { selectPartnerVersion } from "../../redux/application/application.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
partnerVersion: selectPartnerVersion,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@@ -26,6 +29,7 @@ export function AccountingPayablesContainer({
|
|||||||
bodyshop,
|
bodyshop,
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
|
partnerVersion,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -38,7 +42,8 @@ export function AccountingPayablesContainer({
|
|||||||
label: t("titles.bc.accounting-payables"),
|
label: t("titles.bc.accounting-payables"),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}, [t, setBreadcrumbs, setSelectedHeader]);
|
checkPartnerStatus(bodyshop, true);
|
||||||
|
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
|
||||||
|
|
||||||
const { loading, error, data } = useQuery(QUERY_BILLS_FOR_EXPORT, {
|
const { loading, error, data } = useQuery(QUERY_BILLS_FOR_EXPORT, {
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
@@ -47,9 +52,24 @@ export function AccountingPayablesContainer({
|
|||||||
|
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
|
||||||
|
const noPath =
|
||||||
|
!partnerVersion?.qbpath &&
|
||||||
|
!(
|
||||||
|
bodyshop &&
|
||||||
|
(bodyshop.cdk_dealerid ||
|
||||||
|
bodyshop.pbs_serialnumber ||
|
||||||
|
bodyshop.accountingconfig.qbo)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<RbacWrapper action="accounting:payables">
|
<RbacWrapper action="accounting:payables">
|
||||||
|
{noPath && (
|
||||||
|
<AlertComponent
|
||||||
|
type="error"
|
||||||
|
message={t("general.messages.noacctfilepath")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<AccountingPayablesTable
|
<AccountingPayablesTable
|
||||||
loadaing={loading}
|
loadaing={loading}
|
||||||
bills={data ? data.bills : []}
|
bills={data ? data.bills : []}
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ import {
|
|||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||||
|
import { checkPartnerStatus } from "../../components/partner-ping/partner-ping.component";
|
||||||
|
import { selectPartnerVersion } from "../../redux/application/application.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
partnerVersion: selectPartnerVersion,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@@ -25,6 +28,7 @@ export function AccountingPaymentsContainer({
|
|||||||
bodyshop,
|
bodyshop,
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
|
partnerVersion,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -37,7 +41,8 @@ export function AccountingPaymentsContainer({
|
|||||||
label: t("titles.bc.accounting-payments"),
|
label: t("titles.bc.accounting-payments"),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}, [t, setBreadcrumbs, setSelectedHeader]);
|
checkPartnerStatus(bodyshop, true);
|
||||||
|
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
|
||||||
|
|
||||||
const { loading, error, data } = useQuery(QUERY_PAYMENTS_FOR_EXPORT, {
|
const { loading, error, data } = useQuery(QUERY_PAYMENTS_FOR_EXPORT, {
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
@@ -45,10 +50,23 @@ export function AccountingPaymentsContainer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
const noPath =
|
||||||
|
!partnerVersion?.qbpath &&
|
||||||
|
!(
|
||||||
|
bodyshop &&
|
||||||
|
(bodyshop.cdk_dealerid ||
|
||||||
|
bodyshop.pbs_serialnumber ||
|
||||||
|
bodyshop.accountingconfig.qbo)
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<RbacWrapper action="accounting:payments">
|
<RbacWrapper action="accounting:payments">
|
||||||
|
{noPath && (
|
||||||
|
<AlertComponent
|
||||||
|
type="error"
|
||||||
|
message={t("general.messages.noacctfilepath")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<AccountingPaymentsTable
|
<AccountingPaymentsTable
|
||||||
loadaing={loading}
|
loadaing={loading}
|
||||||
payments={data ? data.payments : []}
|
payments={data ? data.payments : []}
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ import {
|
|||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||||
|
import { checkPartnerStatus } from "../../components/partner-ping/partner-ping.component";
|
||||||
|
import { selectPartnerVersion } from "../../redux/application/application.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
partnerVersion: selectPartnerVersion,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@@ -25,6 +28,7 @@ export function AccountingReceivablesContainer({
|
|||||||
bodyshop,
|
bodyshop,
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
|
partnerVersion,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -37,7 +41,8 @@ export function AccountingReceivablesContainer({
|
|||||||
label: t("titles.bc.accounting-receivables"),
|
label: t("titles.bc.accounting-receivables"),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
}, [t, setBreadcrumbs, setSelectedHeader]);
|
checkPartnerStatus(bodyshop, true);
|
||||||
|
}, [t, setBreadcrumbs, setSelectedHeader, bodyshop]);
|
||||||
|
|
||||||
const { loading, error, data } = useQuery(QUERY_JOBS_FOR_EXPORT, {
|
const { loading, error, data } = useQuery(QUERY_JOBS_FOR_EXPORT, {
|
||||||
variables: {
|
variables: {
|
||||||
@@ -48,9 +53,25 @@ export function AccountingReceivablesContainer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
|
||||||
|
const noPath =
|
||||||
|
!partnerVersion?.qbpath &&
|
||||||
|
!(
|
||||||
|
bodyshop &&
|
||||||
|
(bodyshop.cdk_dealerid ||
|
||||||
|
bodyshop.pbs_serialnumber ||
|
||||||
|
bodyshop.accountingconfig.qbo)
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<RbacWrapper action="accounting:receivables">
|
<RbacWrapper action="accounting:receivables">
|
||||||
|
{noPath && (
|
||||||
|
<AlertComponent
|
||||||
|
type="error"
|
||||||
|
message={t("general.messages.noacctfilepath")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<AccountingReceivablesTable
|
<AccountingReceivablesTable
|
||||||
loadaing={loading}
|
loadaing={loading}
|
||||||
jobs={data ? data.jobs : []}
|
jobs={data ? data.jobs : []}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { SyncOutlined } from "@ant-design/icons";
|
import { SyncOutlined, EditFilled } from "@ant-design/icons";
|
||||||
import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd";
|
import { Button, Card, Checkbox, Input, Space, Table, Typography } from "antd";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
@@ -141,7 +141,9 @@ export function BillsListPage({
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
<Link to={`/manage/bills?billid=${record.id}`}>
|
<Link to={`/manage/bills?billid=${record.id}`}>
|
||||||
<Button>{t("bills.actions.edit")}</Button>
|
<Button>
|
||||||
|
<EditFilled />
|
||||||
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
{
|
{
|
||||||
// <Button
|
// <Button
|
||||||
|
|||||||
@@ -70,7 +70,12 @@ export function CourtesyCarCreateContainer({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RbacWrapper action="courtesycar:create">
|
<RbacWrapper action="courtesycar:create">
|
||||||
<Form form={form} autoComplete="new-password" onFinish={handleFinish}>
|
<Form
|
||||||
|
form={form}
|
||||||
|
autoComplete="new-password"
|
||||||
|
onFinish={handleFinish}
|
||||||
|
layout="vertical"
|
||||||
|
>
|
||||||
<CourtesyCarFormComponent form={form} saveLoading={loading} />
|
<CourtesyCarFormComponent form={form} saveLoading={loading} />
|
||||||
</Form>
|
</Form>
|
||||||
</RbacWrapper>
|
</RbacWrapper>
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import { OwnerNameDisplayFunction } from "../../components/owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -143,9 +144,7 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
|||||||
<Link to={`/manage/jobs/${data && data.jobs_by_pk.id}`}>{`${
|
<Link to={`/manage/jobs/${data && data.jobs_by_pk.id}`}>{`${
|
||||||
data && data.jobs_by_pk && data.jobs_by_pk.ro_number
|
data && data.jobs_by_pk && data.jobs_by_pk.ro_number
|
||||||
}`}</Link>
|
}`}</Link>
|
||||||
{` | ${data.jobs_by_pk.ownr_fn || ""} ${
|
{` | ${OwnerNameDisplayFunction(data.jobs_by_pk)} | ${
|
||||||
data.jobs_by_pk.ownr_ln || ""
|
|
||||||
} ${data.jobs_by_pk.ownr_co_nm || ""} | ${
|
|
||||||
data.jobs_by_pk.v_model_yr || ""
|
data.jobs_by_pk.v_model_yr || ""
|
||||||
} ${data.jobs_by_pk.v_make_desc || ""} ${
|
} ${data.jobs_by_pk.v_make_desc || ""} ${
|
||||||
data.jobs_by_pk.v_model_desc || ""
|
data.jobs_by_pk.v_model_desc || ""
|
||||||
|
|||||||
@@ -3,12 +3,19 @@ import React, { useEffect } from "react";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import AlertComponent from "../../components/alert/alert.component";
|
||||||
import JobsAvailableTableContainer from "../../components/jobs-available-table/jobs-available-table.container";
|
import JobsAvailableTableContainer from "../../components/jobs-available-table/jobs-available-table.container";
|
||||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||||
import {
|
import {
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
|
import { selectPartnerVersion } from "../../redux/application/application.selectors";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
partnerVersion: selectPartnerVersion,
|
||||||
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||||
@@ -16,6 +23,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function JobsAvailablePageContainer({
|
export function JobsAvailablePageContainer({
|
||||||
|
partnerVersion,
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
}) {
|
}) {
|
||||||
@@ -40,9 +48,18 @@ export function JobsAvailablePageContainer({
|
|||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
{!partnerVersion && (
|
||||||
|
<AlertComponent
|
||||||
|
type="warning"
|
||||||
|
message={t("general.messages.partnernotrunning")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<JobsAvailableTableContainer />
|
<JobsAvailableTableContainer />
|
||||||
</div>
|
</div>
|
||||||
</RbacWrapper>
|
</RbacWrapper>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default connect(null, mapDispatchToProps)(JobsAvailablePageContainer);
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(JobsAvailablePageContainer);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import AlertComponent from "../../components/alert/alert.component";
|
import AlertComponent from "../../components/alert/alert.component";
|
||||||
import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
|
import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
|
||||||
import NotFound from "../../components/not-found/not-found.component";
|
import NotFound from "../../components/not-found/not-found.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../../components/owner-name-display/owner-name-display.component";
|
||||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||||
import { GET_JOB_BY_PK, UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { GET_JOB_BY_PK, UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
import {
|
import {
|
||||||
@@ -78,11 +79,10 @@ function JobsDetailPageContainer({
|
|||||||
CreateRecentItem(
|
CreateRecentItem(
|
||||||
jobId,
|
jobId,
|
||||||
"job",
|
"job",
|
||||||
`${data.jobs_by_pk.ro_number || t("general.labels.na")} | ${
|
|
||||||
data.jobs_by_pk.ownr_fn || ""
|
`${
|
||||||
} ${data.jobs_by_pk.ownr_ln || ""} ${
|
data.jobs_by_pk.ro_number || t("general.labels.na")
|
||||||
data.jobs_by_pk.ownr_co_nm || ""
|
} | ${OwnerNameDisplayFunction(data.jobs_by_pk)}`,
|
||||||
}`,
|
|
||||||
`/manage/jobs/${jobId}`
|
`/manage/jobs/${jobId}`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
import { CreateRecentItem } from "../../utils/create-recent-item";
|
import { CreateRecentItem } from "../../utils/create-recent-item";
|
||||||
import OwnersDetailComponent from "./owners-detail.page.component";
|
import OwnersDetailComponent from "./owners-detail.page.component";
|
||||||
import NotFound from "../../components/not-found/not-found.component";
|
import NotFound from "../../components/not-found/not-found.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../../components/owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||||
@@ -38,11 +39,7 @@ export function OwnersDetailContainer({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = t("titles.owners-detail", {
|
document.title = t("titles.owners-detail", {
|
||||||
name: data
|
name: data ? OwnerNameDisplayFunction(data.owners_by_pk) : "",
|
||||||
? `${(data.owners_by_pk && data.owners_by_pk.ownr_fn) || ""} ${
|
|
||||||
(data.owners_by_pk && data.owners_by_pk.ownr_ln) || ""
|
|
||||||
} ${(data.owners_by_pk && data.owners_by_pk.ownr_co_nm) || ""}`
|
|
||||||
: "",
|
|
||||||
});
|
});
|
||||||
setSelectedHeader("owners");
|
setSelectedHeader("owners");
|
||||||
setBreadcrumbs([
|
setBreadcrumbs([
|
||||||
@@ -50,11 +47,7 @@ export function OwnersDetailContainer({
|
|||||||
{
|
{
|
||||||
link: `/manage/owners/${ownerId}`,
|
link: `/manage/owners/${ownerId}`,
|
||||||
label: t("titles.bc.owner-detail", {
|
label: t("titles.bc.owner-detail", {
|
||||||
name: data
|
name: data ? OwnerNameDisplayFunction(data.owners_by_pk) : "",
|
||||||
? `${(data.owners_by_pk && data.owners_by_pk.ownr_fn) || ""} ${
|
|
||||||
(data.owners_by_pk && data.owners_by_pk.ownr_ln) || ""
|
|
||||||
} ${(data.owners_by_pk && data.owners_by_pk.ownr_co_nm) || ""}`
|
|
||||||
: "",
|
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
@@ -64,9 +57,7 @@ export function OwnersDetailContainer({
|
|||||||
CreateRecentItem(
|
CreateRecentItem(
|
||||||
ownerId,
|
ownerId,
|
||||||
"owner",
|
"owner",
|
||||||
`${data.owners_by_pk.ownr_fn || ""} ${
|
OwnerNameDisplayFunction(data.owners_by_pk),
|
||||||
data.owners_by_pk.ownr_ln || ""
|
|
||||||
} ${data.owners_by_pk.ownr_co_nm || ""}`,
|
|
||||||
`/manage/owners/${ownerId}`
|
`/manage/owners/${ownerId}`
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { alphaSort } from "../../utils/sorters";
|
|||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
|
import OwnerNameDisplay from "../../components/owner-name-display/owner-name-display.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -120,14 +121,12 @@ export function PartsQueuePageComponent({ bodyshop }) {
|
|||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.ownerid ? (
|
return record.ownerid ? (
|
||||||
<Link to={"/manage/owners/" + record.ownerid}>
|
<Link to={"/manage/owners/" + record.ownerid}>
|
||||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
record.ownr_co_nm || ""
|
|
||||||
}`}
|
|
||||||
</Link>
|
</Link>
|
||||||
) : (
|
) : (
|
||||||
<span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
<span>
|
||||||
record.ownr_co_nm || ""
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
}`}</span>
|
</span>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
confirmPasswordReset,
|
confirmPasswordReset,
|
||||||
signInWithEmailAndPassword,
|
signInWithEmailAndPassword,
|
||||||
signOut,
|
signOut,
|
||||||
|
sendPasswordResetEmail,
|
||||||
} from "firebase/auth";
|
} from "firebase/auth";
|
||||||
import { doc } from "firebase/firestore";
|
import { doc } from "firebase/firestore";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
@@ -223,16 +224,16 @@ export function* signInSuccessSaga({ payload }) {
|
|||||||
export function* onSendPasswordResetStart() {
|
export function* onSendPasswordResetStart() {
|
||||||
yield takeLatest(
|
yield takeLatest(
|
||||||
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START,
|
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START,
|
||||||
sendPasswordResetEmail
|
sendPasswordResetEmailSaga
|
||||||
);
|
);
|
||||||
yield takeLatest(
|
yield takeLatest(
|
||||||
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START_AGAIN,
|
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START_AGAIN,
|
||||||
sendPasswordResetEmail
|
sendPasswordResetEmailSaga
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export function* sendPasswordResetEmail({ payload }) {
|
export function* sendPasswordResetEmailSaga({ payload }) {
|
||||||
try {
|
try {
|
||||||
yield sendPasswordResetEmail(payload, {
|
yield sendPasswordResetEmail(auth, payload, {
|
||||||
url: "https://imex.online/passwordreset",
|
url: "https://imex.online/passwordreset",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -269,7 +270,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
|
|||||||
const userEmail = yield select((state) => state.user.currentUser.email);
|
const userEmail = yield select((state) => state.user.currentUser.email);
|
||||||
try {
|
try {
|
||||||
console.log("Setting shop timezone.");
|
console.log("Setting shop timezone.");
|
||||||
// moment.tz.setDefault(payload.timezone);
|
// moment.tz.setDefault(payload.timezone);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
"federal_tax_rate": "Federal Tax Rate",
|
"federal_tax_rate": "Federal Tax Rate",
|
||||||
"invoice_number": "Invoice Number",
|
"invoice_number": "Invoice Number",
|
||||||
"is_credit_memo": "Credit Memo?",
|
"is_credit_memo": "Credit Memo?",
|
||||||
|
"is_credit_memo_short": "CM",
|
||||||
"local_tax_rate": "Local Tax Rate",
|
"local_tax_rate": "Local Tax Rate",
|
||||||
"ro_number": "RO Number",
|
"ro_number": "RO Number",
|
||||||
"state_tax_rate": "Provincial/State Tax Rate",
|
"state_tax_rate": "Provincial/State Tax Rate",
|
||||||
@@ -232,6 +233,7 @@
|
|||||||
},
|
},
|
||||||
"appt_length": "Default Appointment Length",
|
"appt_length": "Default Appointment Length",
|
||||||
"attach_pdf_to_email": "Attach PDF copy to sent emails?",
|
"attach_pdf_to_email": "Attach PDF copy to sent emails?",
|
||||||
|
"bill_allow_post_to_closed": "Allow Bills to be posted to Closed Jobs",
|
||||||
"bill_federal_tax_rate": "Bills - Federal Tax Rate %",
|
"bill_federal_tax_rate": "Bills - Federal Tax Rate %",
|
||||||
"bill_local_tax_rate": "Bill - Provincial/State Tax Rate %",
|
"bill_local_tax_rate": "Bill - Provincial/State Tax Rate %",
|
||||||
"bill_state_tax_rate": "Bill - Provincial/State Tax Rate %",
|
"bill_state_tax_rate": "Bill - Provincial/State Tax Rate %",
|
||||||
@@ -274,7 +276,10 @@
|
|||||||
"mapa": "Job Costing - Paint Materials Hourly Cost Rate",
|
"mapa": "Job Costing - Paint Materials Hourly Cost Rate",
|
||||||
"mash": "Job Costing - Shop Materials Hourly Cost Rate"
|
"mash": "Job Costing - Shop Materials Hourly Cost Rate"
|
||||||
},
|
},
|
||||||
|
"last_name_first": "Display Owner Info as <Last>, <First>",
|
||||||
"lastnumberworkingdays": "Scoreboard - Last Number of Working Days",
|
"lastnumberworkingdays": "Scoreboard - Last Number of Working Days",
|
||||||
|
"logo_img_footer_margin": "Footer Margin (px)",
|
||||||
|
"logo_img_header_margin": "Header Margin (px)",
|
||||||
"logo_img_path": "Shop Logo",
|
"logo_img_path": "Shop Logo",
|
||||||
"logo_img_path_height": "Logo Image Height",
|
"logo_img_path_height": "Logo Image Height",
|
||||||
"logo_img_path_width": "Logo Image Width",
|
"logo_img_path_width": "Logo Image Width",
|
||||||
@@ -283,6 +288,7 @@
|
|||||||
"md_classes": "Classes",
|
"md_classes": "Classes",
|
||||||
"md_ded_notes": "Deductible Notes",
|
"md_ded_notes": "Deductible Notes",
|
||||||
"md_email_cc": "Auto Email CC: $t(printcenter.subjects.jobs.{{template}})",
|
"md_email_cc": "Auto Email CC: $t(printcenter.subjects.jobs.{{template}})",
|
||||||
|
"md_from_emails": "Additional From Emails",
|
||||||
"md_hour_split": {
|
"md_hour_split": {
|
||||||
"paint": "Paint Hour Split",
|
"paint": "Paint Hour Split",
|
||||||
"prep": "Prep Hour Split"
|
"prep": "Prep Hour Split"
|
||||||
@@ -290,12 +296,14 @@
|
|||||||
"md_ins_co": {
|
"md_ins_co": {
|
||||||
"city": "City",
|
"city": "City",
|
||||||
"name": "Insurance Company Name",
|
"name": "Insurance Company Name",
|
||||||
|
"private": "Private",
|
||||||
"state": "Province/State",
|
"state": "Province/State",
|
||||||
"street1": "Street 1",
|
"street1": "Street 1",
|
||||||
"street2": "Street 2",
|
"street2": "Street 2",
|
||||||
"zip": "Zip/Postal Code"
|
"zip": "Zip/Postal Code"
|
||||||
},
|
},
|
||||||
"md_jobline_presets": "Jobline Presets",
|
"md_jobline_presets": "Jobline Presets",
|
||||||
|
"md_parts_order_comment": "Parts Orders Comments",
|
||||||
"md_payment_types": "Payment Types",
|
"md_payment_types": "Payment Types",
|
||||||
"md_referral_sources": "Referral Sources",
|
"md_referral_sources": "Referral Sources",
|
||||||
"messaginglabel": "Messaging Preset Label",
|
"messaginglabel": "Messaging Preset Label",
|
||||||
@@ -453,6 +461,9 @@
|
|||||||
"label": "Label",
|
"label": "Label",
|
||||||
"templates": "Templates"
|
"templates": "Templates"
|
||||||
},
|
},
|
||||||
|
"ss_configuration": {
|
||||||
|
"dailyhrslimit": "Daily Incoming Hours Limit"
|
||||||
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
"gte": "Greater Than/Equal to (hrs)",
|
"gte": "Greater Than/Equal to (hrs)",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
@@ -533,6 +544,8 @@
|
|||||||
"partslocations": "Parts Locations",
|
"partslocations": "Parts Locations",
|
||||||
"printlater": "Print Later",
|
"printlater": "Print Later",
|
||||||
"qbo": "Use QuickBooks Online?",
|
"qbo": "Use QuickBooks Online?",
|
||||||
|
"qbo_departmentid": "QBO Department ID",
|
||||||
|
"qbo_usa": "QBO USA Compatibility",
|
||||||
"rbac": "Role Based Access Control",
|
"rbac": "Role Based Access Control",
|
||||||
"responsibilitycenters": {
|
"responsibilitycenters": {
|
||||||
"costs": "Cost Centers",
|
"costs": "Cost Centers",
|
||||||
@@ -825,6 +838,7 @@
|
|||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": "CC",
|
"cc": "CC",
|
||||||
|
"from": "From",
|
||||||
"subject": "Subject",
|
"subject": "Subject",
|
||||||
"to": "To"
|
"to": "To"
|
||||||
},
|
},
|
||||||
@@ -1072,7 +1086,7 @@
|
|||||||
"mod_lbr_ty": "Labor Type",
|
"mod_lbr_ty": "Labor Type",
|
||||||
"notes": "Notes",
|
"notes": "Notes",
|
||||||
"oem_partno": "OEM Part #",
|
"oem_partno": "OEM Part #",
|
||||||
"op_code_desc": "Operation Code Description",
|
"op_code_desc": "Op Code Description",
|
||||||
"part_qty": "Qty.",
|
"part_qty": "Qty.",
|
||||||
"part_type": "Part Type",
|
"part_type": "Part Type",
|
||||||
"part_types": {
|
"part_types": {
|
||||||
@@ -1232,6 +1246,7 @@
|
|||||||
"08": "Left Rear Side",
|
"08": "Left Rear Side",
|
||||||
"09": "Left Side"
|
"09": "Left Side"
|
||||||
},
|
},
|
||||||
|
"auto_add_ats": "Automatically Add/Update ATS",
|
||||||
"ca_bc_pvrt": "PVRT",
|
"ca_bc_pvrt": "PVRT",
|
||||||
"ca_customer_gst": "Customer Portion of GST",
|
"ca_customer_gst": "Customer Portion of GST",
|
||||||
"ca_gst_registrant": "GST Registrant",
|
"ca_gst_registrant": "GST Registrant",
|
||||||
@@ -1254,7 +1269,9 @@
|
|||||||
"date_last_contacted": "Last Contacted Date",
|
"date_last_contacted": "Last Contacted Date",
|
||||||
"date_next_contact": "Next Contact Date",
|
"date_next_contact": "Next Contact Date",
|
||||||
"date_open": "Open",
|
"date_open": "Open",
|
||||||
|
"date_rentalresp": "Shop Rental Responsibility Start",
|
||||||
"date_scheduled": "Scheduled",
|
"date_scheduled": "Scheduled",
|
||||||
|
"date_towin": "Towed In",
|
||||||
"ded_amt": "Deductible",
|
"ded_amt": "Deductible",
|
||||||
"ded_note": "Deductible Note",
|
"ded_note": "Deductible Note",
|
||||||
"ded_status": "Deductible Status",
|
"ded_status": "Deductible Status",
|
||||||
@@ -1377,6 +1394,7 @@
|
|||||||
"production_vars": {
|
"production_vars": {
|
||||||
"note": "Production Note"
|
"note": "Production Note"
|
||||||
},
|
},
|
||||||
|
"rate_ats": "ATS Rate",
|
||||||
"rate_la1": "LA1",
|
"rate_la1": "LA1",
|
||||||
"rate_la2": "LA2",
|
"rate_la2": "LA2",
|
||||||
"rate_la3": "LA3",
|
"rate_la3": "LA3",
|
||||||
@@ -1554,6 +1572,7 @@
|
|||||||
"override_header": "Override estimate header on import?",
|
"override_header": "Override estimate header on import?",
|
||||||
"ownerassociation": "Owner Association",
|
"ownerassociation": "Owner Association",
|
||||||
"parts": "Parts",
|
"parts": "Parts",
|
||||||
|
"parts_received": "Parts Rec.",
|
||||||
"parts_tax_rates": "Parts Tax rates",
|
"parts_tax_rates": "Parts Tax rates",
|
||||||
"partsfilter": "Parts Only",
|
"partsfilter": "Parts Only",
|
||||||
"partssubletstotal": "Parts & Sublets Total",
|
"partssubletstotal": "Parts & Sublets Total",
|
||||||
@@ -1602,6 +1621,7 @@
|
|||||||
"supplementnote": "The job had a supplement imported.",
|
"supplementnote": "The job had a supplement imported.",
|
||||||
"suspended": "SUSPENDED",
|
"suspended": "SUSPENDED",
|
||||||
"suspense": "Suspense",
|
"suspense": "Suspense",
|
||||||
|
"threshhold": "Max Threshold: ${{amount}}",
|
||||||
"total_cost": "Total Cost",
|
"total_cost": "Total Cost",
|
||||||
"total_cust_payable": "Total Customer Amount Payable",
|
"total_cust_payable": "Total Customer Amount Payable",
|
||||||
"total_repairs": "Total Repairs",
|
"total_repairs": "Total Repairs",
|
||||||
@@ -1745,6 +1765,7 @@
|
|||||||
},
|
},
|
||||||
"jobsactions": {
|
"jobsactions": {
|
||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
|
"cancelallappointments": "Cancel all appointments",
|
||||||
"closejob": "Close Job",
|
"closejob": "Close Job",
|
||||||
"deletejob": "Delete Job",
|
"deletejob": "Delete Job",
|
||||||
"duplicate": "Duplicate this Job",
|
"duplicate": "Duplicate this Job",
|
||||||
@@ -1832,6 +1853,11 @@
|
|||||||
"updated": "Note updated successfully."
|
"updated": "Note updated successfully."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"owner": {
|
||||||
|
"labels": {
|
||||||
|
"noownerinfo": "No owner information."
|
||||||
|
}
|
||||||
|
},
|
||||||
"owners": {
|
"owners": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"update": "Update Selected Records"
|
"update": "Update Selected Records"
|
||||||
@@ -1920,6 +1946,7 @@
|
|||||||
"email": "Send by Email",
|
"email": "Send by Email",
|
||||||
"inthisorder": "Parts in this Order",
|
"inthisorder": "Parts in this Order",
|
||||||
"newpartsorder": "New Parts Order",
|
"newpartsorder": "New Parts Order",
|
||||||
|
"notyetordered": "This part has not yet been ordered.",
|
||||||
"oec": "Order via OEC",
|
"oec": "Order via OEC",
|
||||||
"orderhistory": "Order History",
|
"orderhistory": "Order History",
|
||||||
"parts_orders": "Parts Orders",
|
"parts_orders": "Parts Orders",
|
||||||
@@ -2068,6 +2095,8 @@
|
|||||||
"labels": "Labels",
|
"labels": "Labels",
|
||||||
"position": "Starting Position"
|
"position": "Starting Position"
|
||||||
},
|
},
|
||||||
|
"lag_time_ro": "Lag Time",
|
||||||
|
"mechanical_authorization": "Mechanical Authorization",
|
||||||
"mpi_animal_checklist": "MPI - Animal Checklist",
|
"mpi_animal_checklist": "MPI - Animal Checklist",
|
||||||
"mpi_eglass_auth": "MPI - eGlass Auth",
|
"mpi_eglass_auth": "MPI - eGlass Auth",
|
||||||
"mpi_final_acct_sheet": "MPI - Final Accounting Sheet",
|
"mpi_final_acct_sheet": "MPI - Final Accounting Sheet",
|
||||||
@@ -2159,6 +2188,12 @@
|
|||||||
"ats": "Alternative Transportation",
|
"ats": "Alternative Transportation",
|
||||||
"bodyhours": "B",
|
"bodyhours": "B",
|
||||||
"bodypriority": "B/P",
|
"bodypriority": "B/P",
|
||||||
|
"bodyshop": {
|
||||||
|
"labels": {
|
||||||
|
"qbo_departmentid": "QBO Department ID",
|
||||||
|
"qbo_usa": "QBO USA"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cardsettings": "Card Settings",
|
"cardsettings": "Card Settings",
|
||||||
"clm_no": "Claim Number",
|
"clm_no": "Claim Number",
|
||||||
"comment": "Comment",
|
"comment": "Comment",
|
||||||
@@ -2176,6 +2211,7 @@
|
|||||||
"refinishhours": "R",
|
"refinishhours": "R",
|
||||||
"scheduled_completion": "Scheduled Completion",
|
"scheduled_completion": "Scheduled Completion",
|
||||||
"selectview": "Select a View",
|
"selectview": "Select a View",
|
||||||
|
"stickyheader": "Sticky Header (BETA)",
|
||||||
"sublets": "Sublets",
|
"sublets": "Sublets",
|
||||||
"totalhours": "Total Hrs ",
|
"totalhours": "Total Hrs ",
|
||||||
"touchtime": "T/T",
|
"touchtime": "T/T",
|
||||||
@@ -2280,6 +2316,7 @@
|
|||||||
"production_by_csr": "Production by CSR",
|
"production_by_csr": "Production by CSR",
|
||||||
"production_by_last_name": "Production by Last Name",
|
"production_by_last_name": "Production by Last Name",
|
||||||
"production_by_repair_status": "Production by Status",
|
"production_by_repair_status": "Production by Status",
|
||||||
|
"production_by_repair_status_one": "Production filtered by Status",
|
||||||
"production_by_ro": "Production by RO",
|
"production_by_ro": "Production by RO",
|
||||||
"production_by_target_date": "Production by Target Date",
|
"production_by_target_date": "Production by Target Date",
|
||||||
"production_by_technician": "Production by Technician",
|
"production_by_technician": "Production by Technician",
|
||||||
@@ -2541,6 +2578,14 @@
|
|||||||
"passwordchanged": "Password changed successfully. "
|
"passwordchanged": "Password changed successfully. "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"users": {
|
||||||
|
"errors": {
|
||||||
|
"signinerror": {
|
||||||
|
"auth/user-not-found": "A user with this email does not exist.",
|
||||||
|
"auth/wrong-password": "The email and password combination you provided is incorrect."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"noaccess": "The vehicle does not exist or you do not have access to it.",
|
"noaccess": "The vehicle does not exist or you do not have access to it.",
|
||||||
@@ -2578,6 +2623,7 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"fromvehicle": "Historical Vehicle Record",
|
"fromvehicle": "Historical Vehicle Record",
|
||||||
|
"novehinfo": "No Vehicle Information",
|
||||||
"relatedjobs": "Related Jobs",
|
"relatedjobs": "Related Jobs",
|
||||||
"updatevehicle": "Update Vehicle Information"
|
"updatevehicle": "Update Vehicle Information"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
"federal_tax_rate": "",
|
"federal_tax_rate": "",
|
||||||
"invoice_number": "",
|
"invoice_number": "",
|
||||||
"is_credit_memo": "",
|
"is_credit_memo": "",
|
||||||
|
"is_credit_memo_short": "",
|
||||||
"local_tax_rate": "",
|
"local_tax_rate": "",
|
||||||
"ro_number": "",
|
"ro_number": "",
|
||||||
"state_tax_rate": "",
|
"state_tax_rate": "",
|
||||||
@@ -232,6 +233,7 @@
|
|||||||
},
|
},
|
||||||
"appt_length": "",
|
"appt_length": "",
|
||||||
"attach_pdf_to_email": "",
|
"attach_pdf_to_email": "",
|
||||||
|
"bill_allow_post_to_closed": "",
|
||||||
"bill_federal_tax_rate": "",
|
"bill_federal_tax_rate": "",
|
||||||
"bill_local_tax_rate": "",
|
"bill_local_tax_rate": "",
|
||||||
"bill_state_tax_rate": "",
|
"bill_state_tax_rate": "",
|
||||||
@@ -274,7 +276,10 @@
|
|||||||
"mapa": "",
|
"mapa": "",
|
||||||
"mash": ""
|
"mash": ""
|
||||||
},
|
},
|
||||||
|
"last_name_first": "",
|
||||||
"lastnumberworkingdays": "",
|
"lastnumberworkingdays": "",
|
||||||
|
"logo_img_footer_margin": "",
|
||||||
|
"logo_img_header_margin": "",
|
||||||
"logo_img_path": "",
|
"logo_img_path": "",
|
||||||
"logo_img_path_height": "",
|
"logo_img_path_height": "",
|
||||||
"logo_img_path_width": "",
|
"logo_img_path_width": "",
|
||||||
@@ -283,6 +288,7 @@
|
|||||||
"md_classes": "",
|
"md_classes": "",
|
||||||
"md_ded_notes": "",
|
"md_ded_notes": "",
|
||||||
"md_email_cc": "",
|
"md_email_cc": "",
|
||||||
|
"md_from_emails": "",
|
||||||
"md_hour_split": {
|
"md_hour_split": {
|
||||||
"paint": "",
|
"paint": "",
|
||||||
"prep": ""
|
"prep": ""
|
||||||
@@ -290,12 +296,14 @@
|
|||||||
"md_ins_co": {
|
"md_ins_co": {
|
||||||
"city": "",
|
"city": "",
|
||||||
"name": "",
|
"name": "",
|
||||||
|
"private": "",
|
||||||
"state": "",
|
"state": "",
|
||||||
"street1": "",
|
"street1": "",
|
||||||
"street2": "",
|
"street2": "",
|
||||||
"zip": ""
|
"zip": ""
|
||||||
},
|
},
|
||||||
"md_jobline_presets": "",
|
"md_jobline_presets": "",
|
||||||
|
"md_parts_order_comment": "",
|
||||||
"md_payment_types": "",
|
"md_payment_types": "",
|
||||||
"md_referral_sources": "",
|
"md_referral_sources": "",
|
||||||
"messaginglabel": "",
|
"messaginglabel": "",
|
||||||
@@ -453,6 +461,9 @@
|
|||||||
"label": "",
|
"label": "",
|
||||||
"templates": ""
|
"templates": ""
|
||||||
},
|
},
|
||||||
|
"ss_configuration": {
|
||||||
|
"dailyhrslimit": ""
|
||||||
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
"gte": "",
|
"gte": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
@@ -533,6 +544,8 @@
|
|||||||
"partslocations": "",
|
"partslocations": "",
|
||||||
"printlater": "",
|
"printlater": "",
|
||||||
"qbo": "",
|
"qbo": "",
|
||||||
|
"qbo_departmentid": "",
|
||||||
|
"qbo_usa": "",
|
||||||
"rbac": "",
|
"rbac": "",
|
||||||
"responsibilitycenters": {
|
"responsibilitycenters": {
|
||||||
"costs": "",
|
"costs": "",
|
||||||
@@ -825,6 +838,7 @@
|
|||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": "",
|
"cc": "",
|
||||||
|
"from": "",
|
||||||
"subject": "",
|
"subject": "",
|
||||||
"to": ""
|
"to": ""
|
||||||
},
|
},
|
||||||
@@ -1232,6 +1246,7 @@
|
|||||||
"08": "",
|
"08": "",
|
||||||
"09": ""
|
"09": ""
|
||||||
},
|
},
|
||||||
|
"auto_add_ats": "",
|
||||||
"ca_bc_pvrt": "",
|
"ca_bc_pvrt": "",
|
||||||
"ca_customer_gst": "",
|
"ca_customer_gst": "",
|
||||||
"ca_gst_registrant": "",
|
"ca_gst_registrant": "",
|
||||||
@@ -1254,7 +1269,9 @@
|
|||||||
"date_last_contacted": "",
|
"date_last_contacted": "",
|
||||||
"date_next_contact": "",
|
"date_next_contact": "",
|
||||||
"date_open": "Abierto",
|
"date_open": "Abierto",
|
||||||
|
"date_rentalresp": "",
|
||||||
"date_scheduled": "Programado",
|
"date_scheduled": "Programado",
|
||||||
|
"date_towin": "",
|
||||||
"ded_amt": "Deducible",
|
"ded_amt": "Deducible",
|
||||||
"ded_note": "",
|
"ded_note": "",
|
||||||
"ded_status": "Estado deducible",
|
"ded_status": "Estado deducible",
|
||||||
@@ -1377,6 +1394,7 @@
|
|||||||
"production_vars": {
|
"production_vars": {
|
||||||
"note": ""
|
"note": ""
|
||||||
},
|
},
|
||||||
|
"rate_ats": "",
|
||||||
"rate_la1": "Tarifa LA1",
|
"rate_la1": "Tarifa LA1",
|
||||||
"rate_la2": "Tarifa LA2",
|
"rate_la2": "Tarifa LA2",
|
||||||
"rate_la3": "Tarifa LA3",
|
"rate_la3": "Tarifa LA3",
|
||||||
@@ -1554,6 +1572,7 @@
|
|||||||
"override_header": "¿Anular encabezado estimado al importar?",
|
"override_header": "¿Anular encabezado estimado al importar?",
|
||||||
"ownerassociation": "",
|
"ownerassociation": "",
|
||||||
"parts": "Partes",
|
"parts": "Partes",
|
||||||
|
"parts_received": "",
|
||||||
"parts_tax_rates": "",
|
"parts_tax_rates": "",
|
||||||
"partsfilter": "",
|
"partsfilter": "",
|
||||||
"partssubletstotal": "",
|
"partssubletstotal": "",
|
||||||
@@ -1602,6 +1621,7 @@
|
|||||||
"supplementnote": "",
|
"supplementnote": "",
|
||||||
"suspended": "",
|
"suspended": "",
|
||||||
"suspense": "",
|
"suspense": "",
|
||||||
|
"threshhold": "",
|
||||||
"total_cost": "",
|
"total_cost": "",
|
||||||
"total_cust_payable": "",
|
"total_cust_payable": "",
|
||||||
"total_repairs": "",
|
"total_repairs": "",
|
||||||
@@ -1745,6 +1765,7 @@
|
|||||||
},
|
},
|
||||||
"jobsactions": {
|
"jobsactions": {
|
||||||
"admin": "",
|
"admin": "",
|
||||||
|
"cancelallappointments": "",
|
||||||
"closejob": "",
|
"closejob": "",
|
||||||
"deletejob": "",
|
"deletejob": "",
|
||||||
"duplicate": "",
|
"duplicate": "",
|
||||||
@@ -1832,6 +1853,11 @@
|
|||||||
"updated": "Nota actualizada con éxito."
|
"updated": "Nota actualizada con éxito."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"owner": {
|
||||||
|
"labels": {
|
||||||
|
"noownerinfo": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"owners": {
|
"owners": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"update": ""
|
"update": ""
|
||||||
@@ -1920,6 +1946,7 @@
|
|||||||
"email": "Enviar por correo electrónico",
|
"email": "Enviar por correo electrónico",
|
||||||
"inthisorder": "Partes en este pedido",
|
"inthisorder": "Partes en este pedido",
|
||||||
"newpartsorder": "",
|
"newpartsorder": "",
|
||||||
|
"notyetordered": "",
|
||||||
"oec": "",
|
"oec": "",
|
||||||
"orderhistory": "Historial de pedidos",
|
"orderhistory": "Historial de pedidos",
|
||||||
"parts_orders": "",
|
"parts_orders": "",
|
||||||
@@ -2068,6 +2095,8 @@
|
|||||||
"labels": "",
|
"labels": "",
|
||||||
"position": ""
|
"position": ""
|
||||||
},
|
},
|
||||||
|
"lag_time_ro": "",
|
||||||
|
"mechanical_authorization": "",
|
||||||
"mpi_animal_checklist": "",
|
"mpi_animal_checklist": "",
|
||||||
"mpi_eglass_auth": "",
|
"mpi_eglass_auth": "",
|
||||||
"mpi_final_acct_sheet": "",
|
"mpi_final_acct_sheet": "",
|
||||||
@@ -2159,6 +2188,12 @@
|
|||||||
"ats": "",
|
"ats": "",
|
||||||
"bodyhours": "",
|
"bodyhours": "",
|
||||||
"bodypriority": "",
|
"bodypriority": "",
|
||||||
|
"bodyshop": {
|
||||||
|
"labels": {
|
||||||
|
"qbo_departmentid": "",
|
||||||
|
"qbo_usa": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
"comment": "",
|
"comment": "",
|
||||||
@@ -2176,6 +2211,7 @@
|
|||||||
"refinishhours": "",
|
"refinishhours": "",
|
||||||
"scheduled_completion": "",
|
"scheduled_completion": "",
|
||||||
"selectview": "",
|
"selectview": "",
|
||||||
|
"stickyheader": "",
|
||||||
"sublets": "",
|
"sublets": "",
|
||||||
"totalhours": "",
|
"totalhours": "",
|
||||||
"touchtime": "",
|
"touchtime": "",
|
||||||
@@ -2280,6 +2316,7 @@
|
|||||||
"production_by_csr": "",
|
"production_by_csr": "",
|
||||||
"production_by_last_name": "",
|
"production_by_last_name": "",
|
||||||
"production_by_repair_status": "",
|
"production_by_repair_status": "",
|
||||||
|
"production_by_repair_status_one": "",
|
||||||
"production_by_ro": "",
|
"production_by_ro": "",
|
||||||
"production_by_target_date": "",
|
"production_by_target_date": "",
|
||||||
"production_by_technician": "",
|
"production_by_technician": "",
|
||||||
@@ -2541,6 +2578,14 @@
|
|||||||
"passwordchanged": ""
|
"passwordchanged": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"users": {
|
||||||
|
"errors": {
|
||||||
|
"signinerror": {
|
||||||
|
"auth/user-not-found": "",
|
||||||
|
"auth/wrong-password": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"noaccess": "El vehículo no existe o usted no tiene acceso a él.",
|
"noaccess": "El vehículo no existe o usted no tiene acceso a él.",
|
||||||
@@ -2578,6 +2623,7 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"fromvehicle": "",
|
"fromvehicle": "",
|
||||||
|
"novehinfo": "",
|
||||||
"relatedjobs": "",
|
"relatedjobs": "",
|
||||||
"updatevehicle": ""
|
"updatevehicle": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
"federal_tax_rate": "",
|
"federal_tax_rate": "",
|
||||||
"invoice_number": "",
|
"invoice_number": "",
|
||||||
"is_credit_memo": "",
|
"is_credit_memo": "",
|
||||||
|
"is_credit_memo_short": "",
|
||||||
"local_tax_rate": "",
|
"local_tax_rate": "",
|
||||||
"ro_number": "",
|
"ro_number": "",
|
||||||
"state_tax_rate": "",
|
"state_tax_rate": "",
|
||||||
@@ -232,6 +233,7 @@
|
|||||||
},
|
},
|
||||||
"appt_length": "",
|
"appt_length": "",
|
||||||
"attach_pdf_to_email": "",
|
"attach_pdf_to_email": "",
|
||||||
|
"bill_allow_post_to_closed": "",
|
||||||
"bill_federal_tax_rate": "",
|
"bill_federal_tax_rate": "",
|
||||||
"bill_local_tax_rate": "",
|
"bill_local_tax_rate": "",
|
||||||
"bill_state_tax_rate": "",
|
"bill_state_tax_rate": "",
|
||||||
@@ -274,7 +276,10 @@
|
|||||||
"mapa": "",
|
"mapa": "",
|
||||||
"mash": ""
|
"mash": ""
|
||||||
},
|
},
|
||||||
|
"last_name_first": "",
|
||||||
"lastnumberworkingdays": "",
|
"lastnumberworkingdays": "",
|
||||||
|
"logo_img_footer_margin": "",
|
||||||
|
"logo_img_header_margin": "",
|
||||||
"logo_img_path": "",
|
"logo_img_path": "",
|
||||||
"logo_img_path_height": "",
|
"logo_img_path_height": "",
|
||||||
"logo_img_path_width": "",
|
"logo_img_path_width": "",
|
||||||
@@ -283,6 +288,7 @@
|
|||||||
"md_classes": "",
|
"md_classes": "",
|
||||||
"md_ded_notes": "",
|
"md_ded_notes": "",
|
||||||
"md_email_cc": "",
|
"md_email_cc": "",
|
||||||
|
"md_from_emails": "",
|
||||||
"md_hour_split": {
|
"md_hour_split": {
|
||||||
"paint": "",
|
"paint": "",
|
||||||
"prep": ""
|
"prep": ""
|
||||||
@@ -290,12 +296,14 @@
|
|||||||
"md_ins_co": {
|
"md_ins_co": {
|
||||||
"city": "",
|
"city": "",
|
||||||
"name": "",
|
"name": "",
|
||||||
|
"private": "",
|
||||||
"state": "",
|
"state": "",
|
||||||
"street1": "",
|
"street1": "",
|
||||||
"street2": "",
|
"street2": "",
|
||||||
"zip": ""
|
"zip": ""
|
||||||
},
|
},
|
||||||
"md_jobline_presets": "",
|
"md_jobline_presets": "",
|
||||||
|
"md_parts_order_comment": "",
|
||||||
"md_payment_types": "",
|
"md_payment_types": "",
|
||||||
"md_referral_sources": "",
|
"md_referral_sources": "",
|
||||||
"messaginglabel": "",
|
"messaginglabel": "",
|
||||||
@@ -453,6 +461,9 @@
|
|||||||
"label": "",
|
"label": "",
|
||||||
"templates": ""
|
"templates": ""
|
||||||
},
|
},
|
||||||
|
"ss_configuration": {
|
||||||
|
"dailyhrslimit": ""
|
||||||
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
"gte": "",
|
"gte": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
@@ -533,6 +544,8 @@
|
|||||||
"partslocations": "",
|
"partslocations": "",
|
||||||
"printlater": "",
|
"printlater": "",
|
||||||
"qbo": "",
|
"qbo": "",
|
||||||
|
"qbo_departmentid": "",
|
||||||
|
"qbo_usa": "",
|
||||||
"rbac": "",
|
"rbac": "",
|
||||||
"responsibilitycenters": {
|
"responsibilitycenters": {
|
||||||
"costs": "",
|
"costs": "",
|
||||||
@@ -825,6 +838,7 @@
|
|||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": "",
|
"cc": "",
|
||||||
|
"from": "",
|
||||||
"subject": "",
|
"subject": "",
|
||||||
"to": ""
|
"to": ""
|
||||||
},
|
},
|
||||||
@@ -1232,6 +1246,7 @@
|
|||||||
"08": "",
|
"08": "",
|
||||||
"09": ""
|
"09": ""
|
||||||
},
|
},
|
||||||
|
"auto_add_ats": "",
|
||||||
"ca_bc_pvrt": "",
|
"ca_bc_pvrt": "",
|
||||||
"ca_customer_gst": "",
|
"ca_customer_gst": "",
|
||||||
"ca_gst_registrant": "",
|
"ca_gst_registrant": "",
|
||||||
@@ -1254,7 +1269,9 @@
|
|||||||
"date_last_contacted": "",
|
"date_last_contacted": "",
|
||||||
"date_next_contact": "",
|
"date_next_contact": "",
|
||||||
"date_open": "Ouvrir",
|
"date_open": "Ouvrir",
|
||||||
|
"date_rentalresp": "",
|
||||||
"date_scheduled": "Prévu",
|
"date_scheduled": "Prévu",
|
||||||
|
"date_towin": "",
|
||||||
"ded_amt": "Déductible",
|
"ded_amt": "Déductible",
|
||||||
"ded_note": "",
|
"ded_note": "",
|
||||||
"ded_status": "Statut de franchise",
|
"ded_status": "Statut de franchise",
|
||||||
@@ -1377,6 +1394,7 @@
|
|||||||
"production_vars": {
|
"production_vars": {
|
||||||
"note": ""
|
"note": ""
|
||||||
},
|
},
|
||||||
|
"rate_ats": "",
|
||||||
"rate_la1": "Taux LA1",
|
"rate_la1": "Taux LA1",
|
||||||
"rate_la2": "Taux LA2",
|
"rate_la2": "Taux LA2",
|
||||||
"rate_la3": "Taux LA3",
|
"rate_la3": "Taux LA3",
|
||||||
@@ -1554,6 +1572,7 @@
|
|||||||
"override_header": "Remplacer l'en-tête d'estimation à l'importation?",
|
"override_header": "Remplacer l'en-tête d'estimation à l'importation?",
|
||||||
"ownerassociation": "",
|
"ownerassociation": "",
|
||||||
"parts": "les pièces",
|
"parts": "les pièces",
|
||||||
|
"parts_received": "",
|
||||||
"parts_tax_rates": "",
|
"parts_tax_rates": "",
|
||||||
"partsfilter": "",
|
"partsfilter": "",
|
||||||
"partssubletstotal": "",
|
"partssubletstotal": "",
|
||||||
@@ -1602,6 +1621,7 @@
|
|||||||
"supplementnote": "",
|
"supplementnote": "",
|
||||||
"suspended": "",
|
"suspended": "",
|
||||||
"suspense": "",
|
"suspense": "",
|
||||||
|
"threshhold": "",
|
||||||
"total_cost": "",
|
"total_cost": "",
|
||||||
"total_cust_payable": "",
|
"total_cust_payable": "",
|
||||||
"total_repairs": "",
|
"total_repairs": "",
|
||||||
@@ -1745,6 +1765,7 @@
|
|||||||
},
|
},
|
||||||
"jobsactions": {
|
"jobsactions": {
|
||||||
"admin": "",
|
"admin": "",
|
||||||
|
"cancelallappointments": "",
|
||||||
"closejob": "",
|
"closejob": "",
|
||||||
"deletejob": "",
|
"deletejob": "",
|
||||||
"duplicate": "",
|
"duplicate": "",
|
||||||
@@ -1832,6 +1853,11 @@
|
|||||||
"updated": "Remarque mise à jour avec succès."
|
"updated": "Remarque mise à jour avec succès."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"owner": {
|
||||||
|
"labels": {
|
||||||
|
"noownerinfo": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"owners": {
|
"owners": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"update": ""
|
"update": ""
|
||||||
@@ -1920,6 +1946,7 @@
|
|||||||
"email": "Envoyé par email",
|
"email": "Envoyé par email",
|
||||||
"inthisorder": "Pièces dans cette commande",
|
"inthisorder": "Pièces dans cette commande",
|
||||||
"newpartsorder": "",
|
"newpartsorder": "",
|
||||||
|
"notyetordered": "",
|
||||||
"oec": "",
|
"oec": "",
|
||||||
"orderhistory": "Historique des commandes",
|
"orderhistory": "Historique des commandes",
|
||||||
"parts_orders": "",
|
"parts_orders": "",
|
||||||
@@ -2068,6 +2095,8 @@
|
|||||||
"labels": "",
|
"labels": "",
|
||||||
"position": ""
|
"position": ""
|
||||||
},
|
},
|
||||||
|
"lag_time_ro": "",
|
||||||
|
"mechanical_authorization": "",
|
||||||
"mpi_animal_checklist": "",
|
"mpi_animal_checklist": "",
|
||||||
"mpi_eglass_auth": "",
|
"mpi_eglass_auth": "",
|
||||||
"mpi_final_acct_sheet": "",
|
"mpi_final_acct_sheet": "",
|
||||||
@@ -2159,6 +2188,12 @@
|
|||||||
"ats": "",
|
"ats": "",
|
||||||
"bodyhours": "",
|
"bodyhours": "",
|
||||||
"bodypriority": "",
|
"bodypriority": "",
|
||||||
|
"bodyshop": {
|
||||||
|
"labels": {
|
||||||
|
"qbo_departmentid": "",
|
||||||
|
"qbo_usa": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
"comment": "",
|
"comment": "",
|
||||||
@@ -2176,6 +2211,7 @@
|
|||||||
"refinishhours": "",
|
"refinishhours": "",
|
||||||
"scheduled_completion": "",
|
"scheduled_completion": "",
|
||||||
"selectview": "",
|
"selectview": "",
|
||||||
|
"stickyheader": "",
|
||||||
"sublets": "",
|
"sublets": "",
|
||||||
"totalhours": "",
|
"totalhours": "",
|
||||||
"touchtime": "",
|
"touchtime": "",
|
||||||
@@ -2280,6 +2316,7 @@
|
|||||||
"production_by_csr": "",
|
"production_by_csr": "",
|
||||||
"production_by_last_name": "",
|
"production_by_last_name": "",
|
||||||
"production_by_repair_status": "",
|
"production_by_repair_status": "",
|
||||||
|
"production_by_repair_status_one": "",
|
||||||
"production_by_ro": "",
|
"production_by_ro": "",
|
||||||
"production_by_target_date": "",
|
"production_by_target_date": "",
|
||||||
"production_by_technician": "",
|
"production_by_technician": "",
|
||||||
@@ -2541,6 +2578,14 @@
|
|||||||
"passwordchanged": ""
|
"passwordchanged": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"users": {
|
||||||
|
"errors": {
|
||||||
|
"signinerror": {
|
||||||
|
"auth/user-not-found": "",
|
||||||
|
"auth/wrong-password": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
"errors": {
|
"errors": {
|
||||||
"noaccess": "Le véhicule n'existe pas ou vous n'y avez pas accès.",
|
"noaccess": "Le véhicule n'existe pas ou vous n'y avez pas accès.",
|
||||||
@@ -2578,6 +2623,7 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"fromvehicle": "",
|
"fromvehicle": "",
|
||||||
|
"novehinfo": "",
|
||||||
"relatedjobs": "",
|
"relatedjobs": "",
|
||||||
"updatevehicle": ""
|
"updatevehicle": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { gql } from "@apollo/client";
|
import { gql } from "@apollo/client";
|
||||||
import { notification } from "antd";
|
import { notification } from "antd";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import jsreport from "jsreport-browser-client-dist";
|
import jsreport from "@jsreport/browser-client";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { auth } from "../firebase/firebase.utils";
|
import { auth } from "../firebase/firebase.utils";
|
||||||
@@ -24,13 +24,34 @@ export default async function RenderTemplate(
|
|||||||
let { contextData, useShopSpecificTemplate } = await fetchContextData(
|
let { contextData, useShopSpecificTemplate } = await fetchContextData(
|
||||||
templateObject
|
templateObject
|
||||||
);
|
);
|
||||||
|
const { ignoreCustomMargins } = Templates[templateObject.name];
|
||||||
|
|
||||||
let reportRequest = {
|
let reportRequest = {
|
||||||
template: {
|
template: {
|
||||||
name: useShopSpecificTemplate
|
name: useShopSpecificTemplate
|
||||||
? `/${bodyshop.imexshopid}/${templateObject.name}`
|
? `/${bodyshop.imexshopid}/${templateObject.name}`
|
||||||
: `/${templateObject.name}`,
|
: `/${templateObject.name}`,
|
||||||
...(renderAsHtml ? {} : { recipe: "chrome-pdf" }),
|
...(renderAsHtml
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
recipe: "chrome-pdf",
|
||||||
|
...(!ignoreCustomMargins && {
|
||||||
|
chrome: {
|
||||||
|
marginTop:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.headerMargin &&
|
||||||
|
bodyshop.logo_img_path.headerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.headerMargin
|
||||||
|
: "36px",
|
||||||
|
marginBottom:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.footerMargin &&
|
||||||
|
bodyshop.logo_img_path.footerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.footerMargin
|
||||||
|
: "36px",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
...(renderAsExcel ? { recipe: "html-to-xlsx" } : {}),
|
...(renderAsExcel ? { recipe: "html-to-xlsx" } : {}),
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
@@ -39,7 +60,7 @@ export default async function RenderTemplate(
|
|||||||
...templateObject.context,
|
...templateObject.context,
|
||||||
headerpath: `/${bodyshop.imexshopid}/header.html`,
|
headerpath: `/${bodyshop.imexshopid}/header.html`,
|
||||||
bodyshop: bodyshop,
|
bodyshop: bodyshop,
|
||||||
offset: moment().utcOffset(),
|
offset: bodyshop.timezone, //moment().utcOffset(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -121,7 +142,25 @@ export async function RenderTemplates(
|
|||||||
name: rootTemplate.useShopSpecificTemplate
|
name: rootTemplate.useShopSpecificTemplate
|
||||||
? `/${bodyshop.imexshopid}/${rootTemplate.templateObject.name}`
|
? `/${bodyshop.imexshopid}/${rootTemplate.templateObject.name}`
|
||||||
: `/${rootTemplate.templateObject.name}`,
|
: `/${rootTemplate.templateObject.name}`,
|
||||||
...(renderAsHtml ? {} : { recipe: "chrome-pdf" }),
|
...(renderAsHtml
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
recipe: "chrome-pdf",
|
||||||
|
chrome: {
|
||||||
|
marginTop:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.headerMargin &&
|
||||||
|
bodyshop.logo_img_path.headerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.headerMargin
|
||||||
|
: "36px",
|
||||||
|
marginBottom:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.footerMargin &&
|
||||||
|
bodyshop.logo_img_path.footerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.footerMargin
|
||||||
|
: "36px",
|
||||||
|
},
|
||||||
|
}),
|
||||||
pdfOperations: templateAndData.map((template) => {
|
pdfOperations: templateAndData.map((template) => {
|
||||||
return {
|
return {
|
||||||
template: {
|
template: {
|
||||||
|
|||||||
@@ -37,6 +37,14 @@ export const TemplateList = (type, context) => {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
group: "authorization",
|
group: "authorization",
|
||||||
},
|
},
|
||||||
|
mechanical_authorization: {
|
||||||
|
title: i18n.t("printcenter.jobs.mechanical_authorization"),
|
||||||
|
description: "Diagnostic Authorization",
|
||||||
|
subject: i18n.t("printcenter.jobs.mechanical_authorization"),
|
||||||
|
key: "mechanical_authorization",
|
||||||
|
disabled: false,
|
||||||
|
group: "authorization",
|
||||||
|
},
|
||||||
appointment_reminder: {
|
appointment_reminder: {
|
||||||
title: i18n.t("printcenter.jobs.appointment_reminder"),
|
title: i18n.t("printcenter.jobs.appointment_reminder"),
|
||||||
description: "All Jobs Notes",
|
description: "All Jobs Notes",
|
||||||
@@ -363,6 +371,7 @@ export const TemplateList = (type, context) => {
|
|||||||
subject: i18n.t("printcenter.jobs.parts_label_single"),
|
subject: i18n.t("printcenter.jobs.parts_label_single"),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
group: "ro",
|
group: "ro",
|
||||||
|
ignoreCustomMargins: true,
|
||||||
},
|
},
|
||||||
envelope_return_address: {
|
envelope_return_address: {
|
||||||
title: i18n.t("printcenter.jobs.envelope_return_address"),
|
title: i18n.t("printcenter.jobs.envelope_return_address"),
|
||||||
@@ -371,6 +380,7 @@ export const TemplateList = (type, context) => {
|
|||||||
key: "envelope_return_address",
|
key: "envelope_return_address",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
group: "ro",
|
group: "ro",
|
||||||
|
ignoreCustomMargins: true,
|
||||||
},
|
},
|
||||||
sgi_certificate_of_repairs: {
|
sgi_certificate_of_repairs: {
|
||||||
title: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
title: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
||||||
@@ -454,6 +464,14 @@ export const TemplateList = (type, context) => {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
group: "post",
|
group: "post",
|
||||||
},
|
},
|
||||||
|
lag_time_ro: {
|
||||||
|
title: i18n.t("printcenter.jobs.lag_time_ro"),
|
||||||
|
description: "CASL Authorization",
|
||||||
|
subject: i18n.t("printcenter.jobs.lag_time_ro"),
|
||||||
|
key: "lag_time_ro",
|
||||||
|
disabled: false,
|
||||||
|
group: "ro",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
...(!type || type === "job_special"
|
...(!type || type === "job_special"
|
||||||
@@ -1664,6 +1682,18 @@ export const TemplateList = (type, context) => {
|
|||||||
//idtype: "vendor",
|
//idtype: "vendor",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
|
production_by_repair_status_one: {
|
||||||
|
title: i18n.t(
|
||||||
|
"reportcenter.templates.production_by_repair_status_one"
|
||||||
|
),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t(
|
||||||
|
"reportcenter.templates.production_by_repair_status_one"
|
||||||
|
),
|
||||||
|
key: "production_by_repair_status_one",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
|
|||||||
5204
client/yarn.lock
5204
client/yarn.lock
File diff suppressed because it is too large
Load Diff
1
hasura/metadata/network.yaml
Normal file
1
hasura/metadata/network.yaml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user