Compare commits

...

74 Commits

Author SHA1 Message Date
Patrick Fic
5db43dd065 IO-70 Add basic functions of OEC. 2021-11-29 15:04:34 -08:00
Patrick Fic
53be0bbc1a IO-70 OEC WIP. 2021-11-29 08:57:44 -08:00
Patrick Fic
bfcc03850b IO-70 Add OEC Through Partner Call. 2021-11-23 00:30:11 -08:00
Patrick Fic
65402c1420 Clean up console log statements. 2021-11-22 23:20:13 -08:00
Patrick Fic
b462b2fa03 IO-1485 Auto CC on parts order. 2021-11-22 15:39:12 -08:00
Patrick Fic
0c26b90591 IO-1533 Resolve board rerender. 2021-11-21 21:59:33 -08:00
Patrick Fic
f8f2384c54 Merged in release/2021-11-19 (pull request #272)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-19 20:08:53 +00:00
Patrick Fic
ef18cf0718 IO-233 CDK Updates. 2021-11-19 10:50:38 -08:00
Patrick Fic
9d35fc85ad Merged in release/2021-11-19 (pull request #271)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-18 18:39:14 +00:00
Patrick Fic
e98f9763fd Resolve QB Payments Refund Issue. 2021-11-18 10:38:04 -08:00
Patrick Fic
95e5385cd1 Merged in release/2021-11-19 (pull request #270)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-18 17:19:57 +00:00
Patrick Fic
46abf01366 IO-1533 Resolve defaults check issue for production board. 2021-11-18 09:19:34 -08:00
Patrick Fic
87f06425e1 Merged in release/2021-11-19 (pull request #269)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-18 06:19:53 +00:00
Patrick Fic
45ab7543d5 Resolve CI Issues. 2021-11-17 22:18:09 -08:00
Patrick Fic
120e4fc94c Merged in release/2021-11-19 (pull request #268)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-18 06:17:09 +00:00
Patrick Fic
fed16efd10 IO-1533 Added check for null settings on kanban. 2021-11-17 22:16:43 -08:00
Patrick Fic
ea6277c586 Merged in release/2021-11-19 (pull request #267)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-18 06:08:21 +00:00
Patrick Fic
49bf461c36 IO-1533 Kanban Customizations 2021-11-17 22:07:50 -08:00
Patrick Fic
696781c857 IO-1533 Kanban Customizations 2021-11-17 21:47:05 -08:00
Patrick Fic
5540872f62 IO-1531 CC Contract add to production. 2021-11-17 20:18:21 -08:00
Patrick Fic
dac53a56c3 Merged in release/2021-11-19 (pull request #266)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-18 01:30:23 +00:00
Patrick Fic
69690f0184 IO-1533 Kanban Customizations 2021-11-17 15:29:04 -08:00
Patrick Fic
f11a4c93ac IO-233 CDK Updates 2021-11-17 14:44:07 -08:00
Patrick Fic
d74870812e Merged in release/2021-11-19 (pull request #265)
release/2021-11-19

Approved-by: Patrick Fic
2021-11-16 01:17:31 +00:00
Patrick Fic
9eed33b5f2 Resolve CI issues with missing imports. 2021-11-15 17:15:51 -08:00
Patrick Fic
55b7715e1c IO-1529 Added gateway templates. 2021-11-15 17:14:12 -08:00
Patrick Fic
c129b5ba8c IO-1533 Kanban Customization 2021-11-15 13:53:54 -08:00
Patrick Fic
efc2844d99 IO-1530 Email individual note. 2021-11-15 11:06:10 -08:00
Patrick Fic
ab38f85d38 Package updates. 2021-11-15 10:36:41 -08:00
Patrick Fic
81eccba393 Merged in release/2021-11-12 (pull request #263)
release/2021-11-12

Approved-by: Patrick Fic
2021-11-12 21:46:33 +00:00
Patrick Fic
b3b49fd4ca Email test fix & Shop Config validation for resp centers. 2021-11-12 13:46:01 -08:00
Patrick Fic
b7a08db4e7 Merged in release/2021-11-12 (pull request #262)
IO-117 PBS WIP

Approved-by: Patrick Fic
2021-11-11 02:13:28 +00:00
Patrick Fic
2d63c3d576 IO-1528 Autohouse Updates. 2021-11-10 18:06:24 -08:00
Patrick Fic
5f4a2392af Costmetic updates & limit of conversations in subscription. 2021-11-10 17:09:09 -08:00
Patrick Fic
f6fe8be7c4 IO-1491 Simplify production query to use ignore employee relationships and match locally. 2021-11-10 16:54:02 -08:00
Patrick Fic
89af6d23e8 IO-1513 Added next contact date. 2021-11-10 16:22:52 -08:00
Patrick Fic
7e1431d65e IO-117 WIP PBS 2021-11-10 15:30:07 -08:00
Patrick Fic
d50e845ba0 IO-117 PBS WIP 2021-11-10 08:18:29 -08:00
Patrick Fic
6796c35e5b Merged in release/2021-11-12 (pull request #260)
release/2021-11-12

Approved-by: Patrick Fic
2021-11-10 01:06:57 +00:00
Patrick Fic
4a68a10005 IO-1486 Add dropdown for file handler. 2021-11-09 17:05:20 -08:00
Patrick Fic
17088b3025 IO-1188 Add AB proof of loss. 2021-11-09 16:33:20 -08:00
Patrick Fic
4e3c659b6d IO-1497 Ability to delete parts orders. 2021-11-09 16:31:57 -08:00
Patrick Fic
6afcf82cc4 IO-1505 Resolve PST exempt exporting to QBO. 2021-11-09 16:04:16 -08:00
Patrick Fic
f4ddb40bde IO-117 PBS WIP 2021-11-09 13:56:52 -08:00
Patrick Fic
6017e2172e IO-117 PBS WIP 2021-11-09 10:38:07 -08:00
Patrick Fic
bef9e64bf8 Resolve associations permissions to allow adjustments of RBAC. 2021-11-08 11:23:37 -08:00
Patrick Fic
e8d95bdb68 IO-1508 Add # of jobs in production. 2021-11-08 11:12:56 -08:00
Patrick Fic
10fb7d9d96 IO-1499 Reconciliation to consider quantity. 2021-11-08 10:50:21 -08:00
Patrick Fic
2ec196e664 IO-1510 Missing report templates 2021-11-08 10:29:16 -08:00
Patrick Fic
1f38b98bfd Package Updates 2021-11-08 10:27:38 -08:00
Patrick Fic
a7c76386bc Merged in release/2021-11-01 (pull request #258)
release/2021-11-01

Approved-by: Patrick Fic
2021-11-01 16:00:52 +00:00
Patrick Fic
042b67c531 IO-1438 Resolve issue with texting 2021-11-01 08:57:30 -07:00
Patrick Fic
2e72ed3698 IO-1438 Resolve Texting Issue 2021-11-01 08:40:53 -07:00
Patrick Fic
bc01f46388 Merge branch 'release/2021-10-29' into test 2021-10-29 13:48:27 -07:00
Patrick Fic
74f791541f IO-256 Resolve no invoice on CM QBO export. 2021-10-29 13:48:17 -07:00
Patrick Fic
84c7fdba5a Merge branch 'release/2021-10-29' into test 2021-10-29 11:30:53 -07:00
Patrick Fic
630fa23f6c Resolve uneeded import CI error. 2021-10-29 11:30:43 -07:00
Patrick Fic
8f58f09c8c Merge branch 'release/2021-10-29' into test 2021-10-29 11:19:36 -07:00
Patrick Fic
a0922f2944 IO-1476 Add Hrs to schedule modal. 2021-10-29 11:18:17 -07:00
Patrick Fic
b8f001625b IO-1502 PST on Adjustments for QBO 2021-10-29 10:55:35 -07:00
Patrick Fic
53394efebf IO-1503 QBO Credit Memos 2021-10-28 09:56:59 -07:00
Patrick Fic
d8296e1d01 Merge branch 'release/2021-10-29' into test 2021-10-27 11:37:04 -07:00
Patrick Fic
2c00e5ee79 IO-256 Resolve QBO Aposstroph Issues 2021-10-27 11:36:40 -07:00
Patrick Fic
34e220dcad IO-233 Update Regex for CDK. 2021-10-27 10:46:06 -07:00
Patrick Fic
fa1fffd8b9 Merge branch 'release/2021-10-29' into test 2021-10-27 08:39:20 -07:00
Patrick Fic
67eb430ff9 Add missing query field to CDK. 2021-10-27 08:39:05 -07:00
Patrick Fic
ff53355b4a Merge branch 'release/2021-10-29' into test 2021-10-27 08:30:03 -07:00
Patrick Fic
331b2c517b Update CDK Country Inclusion. 2021-10-27 08:29:43 -07:00
Patrick Fic
05d9f20a66 Mark Other RO field as Read Only 2021-10-26 15:38:05 -07:00
Patrick Fic
9e3a2e920d Merge branch 'release/2021-10-29' into test 2021-10-26 13:10:37 -07:00
Patrick Fic
1511b87959 IO-1487 MPI Totals Adjustments 2021-10-26 13:10:07 -07:00
Patrick Fic
9c3e4b7b83 IO-1489 Resolve payables memo for QBO. 2021-10-25 17:25:29 -07:00
Patrick Fic
b718f49071 IO-256 Resolve QBO Payable Vendor Insert. 2021-10-25 17:05:21 -07:00
Patrick Fic
e7157119ae Merged in release/2021-10-29 (pull request #256)
Release/2021 10 29
2021-10-25 21:58:53 +00:00
132 changed files with 9649 additions and 1632 deletions

1
.gitignore vendored
View File

@@ -112,3 +112,4 @@ firebase/.env
.elasticbeanstalk/*
!.elasticbeanstalk/*.cfg.yml
!.elasticbeanstalk/*.global.yml
logs/oAuthClient-log.log

View File

@@ -4304,6 +4304,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>md_email_cc</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>
<name>md_hour_split</name>
<children>
@@ -8103,6 +8124,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>filehandlers</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>insurancecos</name>
<definition_loaded>false</definition_loaded>
@@ -8664,6 +8706,27 @@
<folder_node>
<name>validation</name>
<children>
<concept_node>
<name>centermustexist</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>larsplit</name>
<definition_loaded>false</definition_loaded>
@@ -17491,6 +17554,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>changefilehandler</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>changelaborrate</name>
<definition_loaded>false</definition_loaded>
@@ -19737,6 +19821,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>date_next_contact</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>date_open</name>
<definition_loaded>false</definition_loaded>
@@ -29272,6 +29377,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>noattachedjobs</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
@@ -29424,6 +29550,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>recentonly</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>selectmedia</name>
<definition_loaded>false</definition_loaded>
@@ -30627,6 +30774,27 @@
<folder_node>
<name>errors</name>
<children>
<concept_node>
<name>associatedbills</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>backordering</name>
<definition_loaded>false</definition_loaded>
@@ -30669,6 +30837,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>oec</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>
@@ -31162,6 +31351,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>oec</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>orderhistory</name>
<definition_loaded>false</definition_loaded>
@@ -32874,6 +33084,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>ab_proof_of_loss</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>appointment_confirmation</name>
<definition_loaded>false</definition_loaded>
@@ -33231,6 +33462,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>individual_job_note</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>invoice_customer_payable</name>
<definition_loaded>false</definition_loaded>
@@ -34050,6 +34302,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>worksheet_sorted_by_operation_type</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
@@ -34662,6 +34935,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>settings</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
@@ -34730,6 +35024,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>ats</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>bodyhours</name>
<definition_loaded>false</definition_loaded>
@@ -34772,6 +35087,69 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>cardsettings</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>clm_no</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>compact</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>detailpriority</name>
<definition_loaded>false</definition_loaded>
@@ -34793,6 +35171,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>employeeassignments</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>employeesearch</name>
<definition_loaded>false</definition_loaded>
@@ -34814,6 +35213,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>ins_co_nm</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobdetail</name>
<definition_loaded>false</definition_loaded>
@@ -34835,6 +35255,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>laborhrs</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>note</name>
<definition_loaded>false</definition_loaded>
@@ -34856,6 +35297,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>ownr_nm</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>paintpriority</name>
<definition_loaded>false</definition_loaded>
@@ -34877,6 +35339,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>production_note</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>refinishhours</name>
<definition_loaded>false</definition_loaded>
@@ -34898,6 +35381,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>scheduled_completion</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>selectview</name>
<definition_loaded>false</definition_loaded>
@@ -36465,6 +36969,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>open_orders_status</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>parts_backorder</name>
<definition_loaded>false</definition_loaded>

View File

@@ -2,74 +2,74 @@
"name": "bodyshop",
"version": "0.1.1",
"private": true,
"proxy": "http://localhost:5000",
"proxy": "http://localhost:4000",
"dependencies": {
"@apollo/client": "^3.4.16",
"@apollo/client": "^3.4.17",
"@asseinfo/react-kanban": "^2.2.0",
"@craco/craco": "^6.4.0",
"@fingerprintjs/fingerprintjs": "^3.3.0",
"@lourenci/react-kanban": "^2.1.0",
"@openreplay/tracker": "^3.4.4",
"@openreplay/tracker": "^3.4.7",
"@openreplay/tracker-assist": "^3.4.4",
"@openreplay/tracker-graphql": "^3.0.0",
"@openreplay/tracker-redux": "^3.0.0",
"@sentry/react": "^6.13.3",
"@sentry/tracing": "^6.13.3",
"@sentry/react": "^6.14.3",
"@sentry/tracing": "^6.14.3",
"@splitsoftware/splitio-react": "^1.3.0",
"@stripe/react-stripe-js": "^1.6.0",
"@stripe/stripe-js": "^1.20.2",
"@tanem/react-nprogress": "^3.0.81",
"@stripe/stripe-js": "^1.21.1",
"@tanem/react-nprogress": "^3.0.82",
"antd": "^4.16.13",
"apollo-link-logger": "^2.0.0",
"axios": "^0.23.0",
"axios": "^0.24.0",
"craco-less": "^1.20.0",
"dinero.js": "^1.9.1",
"dotenv": "^10.0.0",
"enquire-js": "^0.2.1",
"env-cmd": "^10.1.0",
"exifr": "^7.1.3",
"firebase": "^9.1.3",
"graphql": "^15.6.1",
"i18next": "^21.3.3",
"firebase": "^9.4.1",
"graphql": "^16.0.1",
"i18next": "^21.4.2",
"i18next-browser-languagedetector": "^6.1.2",
"jsoneditor": "^9.5.6",
"jsoneditor": "^9.5.7",
"jsreport-browser-client-dist": "^1.3.0",
"libphonenumber-js": "^1.9.38",
"libphonenumber-js": "^1.9.42",
"logrocket": "^2.1.1",
"markerjs2": "^2.15.0",
"markerjs2": "^2.17.0",
"moment-business-days": "^1.2.0",
"phone": "^3.1.8",
"phone": "^3.1.9",
"preval.macro": "^5.0.0",
"prop-types": "^15.7.2",
"query-string": "^7.0.1",
"rc-queue-anim": "^2.0.0",
"rc-scroll-anim": "^2.7.6",
"react": "^17.0.1",
"react-big-calendar": "^0.38.0",
"react-big-calendar": "^0.38.1",
"react-color": "^2.19.3",
"react-cookie": "^4.1.1",
"react-dom": "^17.0.1",
"react-drag-listview": "^0.1.8",
"react-grid-gallery": "^0.5.5",
"react-grid-layout": "^1.3.0",
"react-i18next": "^11.12.0",
"react-i18next": "^11.14.2",
"react-icons": "^4.3.1",
"react-number-format": "^4.7.3",
"react-redux": "^7.2.5",
"react-number-format": "^4.8.0",
"react-redux": "^7.2.6",
"react-resizable": "^3.0.4",
"react-router-dom": "^5.3.0",
"react-scripts": "^4.0.3",
"react-sublime-video": "^0.2.5",
"react-virtualized": "^9.22.3",
"recharts": "^2.1.5",
"redux": "^4.1.1",
"recharts": "^2.1.6",
"redux": "^4.1.2",
"redux-persist": "^6.0.0",
"redux-saga": "^1.1.3",
"redux-state-sync": "^3.1.2",
"reselect": "^4.0.0",
"sass": "^1.43.3",
"reselect": "^4.1.2",
"sass": "^1.43.4",
"socket.io-client": "^4.3.2",
"styled-components": "^5.3.3",
"subscriptions-transport-ws": "^0.9.18",
"subscriptions-transport-ws": "^0.11.0",
"web-vitals": "^2.1.2",
"workbox-background-sync": "^6.3.0",
"workbox-broadcast-update": "^6.3.0",

View File

@@ -27,7 +27,6 @@ export const tracker = new Tracker({
onStart: async ({ sessionID }) => {
const user = await getCurrentUser();
if (user) tracker.setUserID(user.email);
console.log("ORS SESSION ", sessionID, user && user.email);
},
});

View File

@@ -53,7 +53,6 @@ export function App({ checkUserSession, currentUser, online, setOnline }) {
const { t } = useTranslation();
window.addEventListener("offline", function (e) {
console.log("Internet connection lost.");
setOnline(false);
});

View File

@@ -157,16 +157,6 @@ export function BillEnterModalLinesComponent({
billlines: getFieldsValue("billlines").billlines.map(
(item, idx) => {
if (idx === index) {
console.log(
"Found and setting.",
!!item.actual_cost
? item.actual_cost
: Math.round(
(parseFloat(e.target.value) * (1 - discount) +
Number.EPSILON) *
100
) / 100
);
return {
...item,
actual_cost: !!item.actual_cost

View File

@@ -14,7 +14,6 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => {
showSearch
// optionFilterProp="line_desc"
filterOption={(inputValue, option) => {
console.log(inputValue);
return (
(option.line_desc &&
option.line_desc

View File

@@ -20,7 +20,6 @@ export function ChatNewConversation({ openChatByPhone }) {
const { t } = useTranslation();
const [form] = Form.useForm();
const handleFinish = (values) => {
console.log("values :>> ", values);
openChatByPhone({ phone_num: values.phoneNumber });
form.resetFields();
};

View File

@@ -1,5 +1,5 @@
import { ShrinkOutlined } from "@ant-design/icons";
import { Col, Row, Typography } from "antd";
import { ShrinkOutlined, InfoCircleOutlined } from "@ant-design/icons";
import { Col, Row, Tooltip, Typography } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -31,6 +31,9 @@ export function ChatPopupComponent({
{t("messaging.labels.messaging")}
</Typography.Title>
<ChatNewConversation />
<Tooltip title={t("messaging.labels.recentonly")}>
<InfoCircleOutlined />
</Tooltip>
</div>
<ShrinkOutlined
onClick={() => toggleChatVisible()}

View File

@@ -42,7 +42,6 @@ export default function ContractFormComponent({
<ContractStatusSelector />
</Form.Item>
)}
<Form.Item
label={t("contracts.fields.start")}
name="start"

View File

@@ -86,10 +86,7 @@ export function DashboardGridComponent({ currentUser, bodyshop }) {
const handleRemoveComponent = (key) => {
logImEXEvent("dashboard_remove_component", { name: key });
const idxToRemove = state.items.findIndex((i) => i.i === key);
console.log(
"🚀 ~ file: dashboard-grid.component.jsx ~ line 81 ~ idxToRemove",
idxToRemove
);
const items = _.cloneDeep(state.items);
items.splice(idxToRemove, 1);

View File

@@ -1,10 +1,10 @@
import { Button } from "antd";
import axios from "axios";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { useTranslation } from "react-i18next";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
@@ -19,11 +19,11 @@ export function DmsCdkMakesRefetch({ bodyshop, form, socket }) {
const { t } = useTranslation();
const handleRefetch = async () => {
setLoading(true);
const response = await axios.post("/cdk/getvehicles", {
await axios.post("/cdk/getvehicles", {
cdk_dealerid: bodyshop.cdk_dealerid,
bodyshopid: bodyshop.id,
});
console.log(response);
setLoading(false);
};
return (

View File

@@ -1,4 +1,4 @@
import { Button, Table, Col , Checkbox} from "antd";
import { Button, Table, Col, Checkbox } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -23,15 +23,26 @@ export function DmsCustomerSelector({ bodyshop }) {
const [customerList, setcustomerList] = useState([]);
const [visible, setVisible] = useState(false);
const [selectedCustomer, setSelectedCustomer] = useState(null);
const [dmsType, setDmsType] = useState("cdk");
socket.on("cdk-select-customer", (customerList, callback) => {
setVisible(true);
setDmsType("cdk");
setcustomerList(customerList);
});
socket.on("pbs-select-customer", (customerList, callback) => {
setVisible(true);
setDmsType("pbs");
setcustomerList(customerList);
console.log(
"🚀 ~ file: dms-customer-selector.component.jsx ~ line 37 ~ socket.on ~ customerList",
customerList
);
});
const onUseSelected = () => {
setVisible(false);
socket.emit("cdk-selected-customer", selectedCustomer);
socket.emit(`${dmsType}-selected-customer`, selectedCustomer);
setSelectedCustomer(null);
};
@@ -50,7 +61,7 @@ export function DmsCustomerSelector({ bodyshop }) {
setSelectedCustomer(null);
};
const columns = [
const cdkColumns = [
{
title: t("jobs.fields.dms.id"),
dataIndex: ["id", "value"],
@@ -60,13 +71,14 @@ export function DmsCustomerSelector({ bodyshop }) {
title: t("jobs.fields.dms.vinowner"),
dataIndex: "vinOwner",
key: "vinOwner",
render: (text, record) => <Checkbox disabled checked={record.vinOwner}/>
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />,
},
{
title: t("jobs.fields.dms.name1"),
dataIndex: ["name1", "fullName"],
key: "name1",
sorter: (a, b) => alphaSort(a.name1?.fullName, b.name1?.fullName),
sorter: (a, b) =>
alphaSort(a.name1 && a.name1.fullName, b.name1 && b.name1.fullName),
},
{
@@ -74,11 +86,43 @@ export function DmsCustomerSelector({ bodyshop }) {
//dataIndex: ["name2", "fullName"],
key: "address",
render: (record, value) =>
`${record?.address?.addressLine[0]}, ${record.address?.city} ${record.address?.stateOrProvince} ${record.address?.postalCode}`,
`${record.address && record.address.addressLine[0]}, ${
record.address && record.address.city
} ${record.address && record.address.stateOrProvince} ${
record.address && record.address.postalCode
}`,
},
];
if (!visible) return <></>;
const pbsColumns = [
{
title: t("jobs.fields.dms.id"),
dataIndex: "ContactId",
key: "ContactId",
},
{
title: t("jobs.fields.dms.vinowner"),
dataIndex: "vinOwner",
key: "vinOwner",
render: (text, record) => <Checkbox disabled checked={record.vinOwner} />,
},
{
title: t("jobs.fields.dms.name1"),
key: "name1",
sorter: (a, b) => alphaSort(a.LastName, b.LastName),
render: (text, record) =>
`${record.FirstName || ""} ${record.LastName || ""}`,
},
{
title: t("jobs.fields.dms.address"),
key: "address",
render: (record, value) =>
`${record.Address}, ${record.City} ${record.State} ${record.ZipCode}`,
},
];
if (!visible) return null;
return (
<Col span={24}>
<Table
@@ -104,13 +148,17 @@ export function DmsCustomerSelector({ bodyshop }) {
</div>
)}
pagination={{ position: "top" }}
columns={columns}
rowKey={(record) => record.id.value}
columns={dmsType === "cdk" ? cdkColumns : pbsColumns}
rowKey={(record) =>
dmsType === "cdk" ? record.id.value : record.ContactId
}
dataSource={customerList}
//onChange={handleTableChange}
rowSelection={{
onSelect: (props) => {
setSelectedCustomer(props.id.value);
onSelect: (record) => {
setSelectedCustomer(
dmsType === "cdk" ? record.id.value : record.ContactId
);
},
type: "radio",
selectedRowKeys: [selectedCustomer],

View File

@@ -27,7 +27,7 @@ export function DmsLogEvents({ socket, logs, bodyshop }) {
<Timeline.Item key={idx} color={LogLevelHierarchy(log.level)}>
<Space wrap align="start" style={{}}>
<Tag color={LogLevelHierarchy(log.level)}>{log.level}</Tag>
<span>{moment(log.timestamp).format("MM/DD/YYYY HH:MM:ss")}</span>
<span>{moment(log.timestamp).format("MM/DD/YYYY HH:mm:ss")}</span>
<Divider type="vertical" />
<span>{log.message}</span>
</Space>

View File

@@ -119,33 +119,35 @@ export function DmsPostForm({ bodyshop, socket, job }) {
</Form.Item>
</LayoutFormRow>
<LayoutFormRow style={{ justifyContent: "center" }} grow>
<Form.Item
name="dms_make"
label={t("jobs.fields.dms.dms_make")}
rules={[
{
required: true,
},
]}
>
<Input disabled />
</Form.Item>
<Form.Item
name="dms_model"
label={t("jobs.fields.dms.dms_model")}
rules={[
{
required: true,
},
]}
>
<Input disabled />
</Form.Item>
{bodyshop.cdk_dealerid && (
<LayoutFormRow style={{ justifyContent: "center" }} grow>
<Form.Item
name="dms_make"
label={t("jobs.fields.dms.dms_make")}
rules={[
{
required: true,
},
]}
>
<Input disabled />
</Form.Item>
<Form.Item
name="dms_model"
label={t("jobs.fields.dms.dms_model")}
rules={[
{
required: true,
},
]}
>
<Input disabled />
</Form.Item>
<DmsCdkMakes form={form} socket={socket} job={job} />
<DmsCdkMakesRefetch />
</LayoutFormRow>
<DmsCdkMakes form={form} socket={socket} job={job} />
<DmsCdkMakesRefetch />
</LayoutFormRow>
)}
<Form.Item
name="story"
label={t("jobs.fields.dms.story")}
@@ -157,6 +159,7 @@ export function DmsPostForm({ bodyshop, socket, job }) {
>
<Input.TextArea maxLength={240} />
</Form.Item>
<Divider />
<Form.List name={["payers"]}>
{(fields, { add, remove }) => {

View File

@@ -58,11 +58,9 @@ export function DocumentEditorComponent({ currentUser, bodyshop, document }) {
if (imgRef.current !== null) {
// create a marker.js MarkerArea
markerArea.current = new markerjs2.MarkerArea(imgRef.current);
console.log(`markerArea.current`, markerArea.current);
// attach an event handler to assign annotated image back to our image element
markerArea.current.addCloseEventListener((closeEvent) => {
console.log("Close Event", closeEvent);
});
markerArea.current.addCloseEventListener((closeEvent) => {});
markerArea.current.addRenderEventListener((dataUrl) => {
imgRef.current.src = dataUrl;

View File

@@ -14,8 +14,6 @@ var cleanAxios = axios.create();
cleanAxios.interceptors.request.eject(axiosAuthInterceptorId);
export const handleUpload = (ev, context) => {
console.log("Handling Upload", ev);
logImEXEvent("document_upload", { filetype: ev.file.type });
const { onError, onSuccess, onProgress } = ev;
@@ -61,7 +59,7 @@ export const uploadToCloudinary = async (
// let eager = process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS;
//Get the signed url.
console.log("fileType", fileType);
const upload_preset = fileType.startsWith("video")
? "incoming_upload_video"
: "incoming_upload";
@@ -74,7 +72,6 @@ export const uploadToCloudinary = async (
});
if (signedURLResponse.status !== 200) {
console.log("Error Getting Signed URL", signedURLResponse.statusText);
if (!!onError) onError(signedURLResponse.statusText);
notification["error"]({
message: i18n.t("documents.errors.getpresignurl", {
@@ -113,13 +110,8 @@ export const uploadToCloudinary = async (
...options,
}
);
console.log("Upload Response", cloudinaryUploadResponse.data);
if (cloudinaryUploadResponse.status !== 200) {
console.log(
"Error uploading to cloudinary.",
cloudinaryUploadResponse.statusText
);
if (!!onError) onError(cloudinaryUploadResponse.statusText);
notification["error"]({
message: i18n.t("documents.errors.insert", {

View File

@@ -35,10 +35,6 @@ export function EmailDocumentsComponent({
},
skip: !emailConfig.jobid,
});
console.log(
"🚀 ~ file: email-documents.component.jsx ~ line 38 ~ emailConfig",
emailConfig
);
return (
<div>

View File

@@ -1,15 +1,71 @@
import { UploadOutlined } from "@ant-design/icons";
import { Divider, Form, Input, Select, Tabs, Upload } from "antd";
import { UploadOutlined, UserAddOutlined } from "@ant-design/icons";
import {
Divider,
Form,
Input,
Select,
Tabs,
Upload,
Space,
Menu,
Dropdown,
} from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import EmailDocumentsComponent from "../email-documents/email-documents.component";
import _ from "lodash";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(EmailOverlayComponent);
export default function EmailOverlayComponent({ form, selectedMediaState }) {
export function EmailOverlayComponent({ form, selectedMediaState, bodyshop }) {
const { t } = useTranslation();
const handleClick = ({ item, key, keyPath }) => {
const email = item.props.value;
form.setFieldsValue({ to: _.uniq([...form.getFieldValue("to"), email]) });
};
const menu = (
<div>
<Menu onClick={handleClick}>
{bodyshop.employees
.filter((e) => e.user_email)
.map((e, idx) => (
<Menu.Item value={e.user_email} key={idx}>
{`${e.first_name} ${e.last_name}`}
</Menu.Item>
))}
</Menu>
</div>
);
return (
<div>
<Form.Item
label={t("emails.fields.to")}
label={
<Space>
{t("emails.fields.to")}
<Dropdown overlay={menu}>
<a
className="ant-dropdown-link"
href=" #"
onClick={(e) => e.preventDefault()}
>
<UserAddOutlined />
</a>
</Dropdown>
</Space>
}
name="to"
rules={[
{

View File

@@ -111,7 +111,6 @@ export function EmailOverlayContainer({
notification["success"]({ message: t("emails.successes.sent") });
toggleEmailOverlayVisible();
} catch (error) {
console.log(JSON.stringify(error));
notification["error"]({
message: t("emails.errors.notsent", { message: error.message }),
});
@@ -149,6 +148,18 @@ export function EmailOverlayContainer({
html: response.data,
fileList: [],
});
if (
bodyshop.md_email_cc[emailConfig.template.name] &&
bodyshop.md_email_cc[emailConfig.template.name].length > 0
) {
form.setFieldsValue({
cc: [
...(form.getFieldValue("cc") || []),
...bodyshop.md_email_cc[emailConfig.template.name],
],
});
}
setLoading(false);
};

View File

@@ -7,10 +7,12 @@ import { selectCurrentUser } from "../../redux/user/user.selectors";
import { GenerateDocument } from "../../utils/RenderTemplate";
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import moment from "moment";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
});
@@ -19,14 +21,24 @@ export function EmailTestComponent({ currentUser, setEmailOptions }) {
const [form] = Form.useForm();
const handleFinish = (values) => {
console.log("values", values);
GenerateDocument(
{
name: values.key,
variables: {
...(values.start
? {
start: moment(values.start).startOf("day").format("YYYY-MM-DD"),
}
: {}),
...(values.end
? { end: moment(values.end).endOf("day").format("YYYY-MM-DD") }
: {}),
...(values.start
? { starttz: moment(values.start).startOf("day") }
: {}),
...(values.end ? { endtz: moment(values.end).endOf("day") } : {}),
...(values.id ? { id: values.id } : {}),
...(values.start ? { start: values.start } : {}),
...(values.end ? { end: values.end } : {}),
},
},
{

View File

@@ -46,12 +46,16 @@ import {
} from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions";
import { signOutStart } from "../../redux/user/user.actions";
import { selectCurrentUser } from "../../redux/user/user.selectors";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
recentItems: selectRecentItems,
selectedHeader: selectSelectedHeader,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
@@ -69,6 +73,7 @@ const mapDispatchToProps = (dispatch) => ({
function Header({
handleMenuClick,
currentUser,
bodyshop,
selectedHeader,
signOutStart,
setBillEnterContext,
@@ -237,16 +242,26 @@ function Header({
{t("menus.header.accounting-receivables")}
</Link>
</Menu.Item>
<Menu.Item key="payables">
<Link to="/manage/accounting/payables">
{t("menus.header.accounting-payables")}
</Link>
</Menu.Item>
<Menu.Item key="payments">
<Link to="/manage/accounting/payments">
{t("menus.header.accounting-payments")}
</Link>
</Menu.Item>
{!(
(bodyshop && bodyshop.cdk_dealerid) ||
(bodyshop && bodyshop.pbs_serialnumber)
) && (
<Menu.Item key="payables">
<Link to="/manage/accounting/payables">
{t("menus.header.accounting-payables")}
</Link>
</Menu.Item>
)}
{!(
(bodyshop && bodyshop.cdk_dealerid) ||
(bodyshop && bodyshop.pbs_serialnumber)
) && (
<Menu.Item key="payments">
<Link to="/manage/accounting/payments">
{t("menus.header.accounting-payments")}
</Link>
</Menu.Item>
)}
<Menu.Item key="export-logs">
<Link to="/manage/accounting/exportlogs">
{t("menus.header.export-logs")}

View File

@@ -10,15 +10,11 @@ export default function HelpRescue() {
var bodyFormData = new FormData();
bodyFormData.append("Code", code);
bodyFormData.append("hostederrorhandling", 1);
const res1 = await fetch(
"https://secure.logmeinrescue.com/Customer/Code.aspx",
{
mode: "no-cors",
method: "POST",
body: bodyFormData,
}
);
console.log("handleClick -> res1", await res1.text());
await fetch("https://secure.logmeinrescue.com/Customer/Code.aspx", {
mode: "no-cors",
method: "POST",
body: bodyFormData,
});
};
return (
@@ -40,7 +36,6 @@ export default function HelpRescue() {
method="post"
id="logmeinsupport"
onSubmit={(...props) => {
console.log(`props`, props);
alert();
}}
>

View File

@@ -44,7 +44,7 @@ export function Jobd3RdPartyModal({ bodyshop, jobId }) {
};
const handleFinish = (values) => {
const { sendtype, ...restVals } = values;
console.log(restVals);
GenerateDocument(
{
name: TemplateList("job_special").thirdpartypayer.key,

View File

@@ -56,7 +56,7 @@ export function ScheduleEventColor({ bodyshop, event }) {
<Menu.Item key={"null"}>{t("general.actions.clear")}</Menu.Item>
</Menu>
);
console.log(`event`, event);
return (
<Dropdown overlay={menu}>
<a href=" #" onClick={(e) => e.preventDefault()}>

View File

@@ -176,7 +176,7 @@ export function ScheduleEventComponent({
t("appointments.labels.reminder", {
shopname: bodyshop.shopname,
date: moment(event.start).format("MM/DD/YYYY"),
time: moment(event.start).format("HH:MM a"),
time: moment(event.start).format("HH:mm a"),
})
);
setVisible(false);

View File

@@ -55,7 +55,6 @@ export default function JobBillsTotalComponent({
);
}
if (il.deductedfromlbr) {
console.log(i, "Deducting from labor.");
lbrAdjustments = lbrAdjustments.add(
Dinero({
amount: Math.round((il.actual_price || 0) * 100),

View File

@@ -34,7 +34,7 @@ export default function JobIntakeTemplateList({ templates }) {
const renderAllTemplates = async () => {
logImEXEvent("checklist_render_all_templates");
setLoading(true);
console.log("templates :>> ", templates);
await GenerateDocuments(
templates.map((key) => {
return { name: key, variables: { id: jobId } };

View File

@@ -35,7 +35,7 @@ export function JobCostingModalContainer({
async function getData() {
if (jobId && visible) {
const { data } = await axios.post("/job/costing", { jobid: jobId });
console.log(data);
setCostingData(data);
}
}

View File

@@ -77,7 +77,6 @@ export default function JobCostingPartsTable({ data, summaryData }) {
.includes(searchText.toLowerCase())
);
console.log("data :>> ", data);
return (
<div>
<Table

View File

@@ -73,7 +73,7 @@ export const reconcileByPrice = (
jobLines.forEach((jl) => {
const matchingBillLineIds = billLines
.filter((bl) => bl.actual_price === jl.act_price && !jl.removed)
.filter((bl) => bl.actual_price === jl.act_price && bl.quantity === jl.part_qty && !jl.removed)
.map((bl) => bl.id);
if (matchingBillLineIds.length > 1) {

View File

@@ -42,9 +42,7 @@ export default function ScoreboardAddButton({
}, [visibility, job.id, callQuery]);
useEffect(() => {
console.log("UE", entryData);
if (entryData && entryData.scoreboard && entryData.scoreboard[0]) {
console.log("Setting FOrm");
form.setFieldsValue(entryData.scoreboard[0]);
}
}, [entryData, form]);

View File

@@ -22,7 +22,6 @@ export function JobsAdminClass({ bodyshop, job }) {
const [updateJob] = useMutation(UPDATE_JOB);
const handleFinish = async (values) => {
console.log(values);
setLoading(true);
const result = await updateJob({
variables: { jobId: job.id, job: values },

View File

@@ -13,7 +13,6 @@ export default function JobsAdminDatesChange({ job }) {
const [updateJob] = useMutation(UPDATE_JOB);
const handleFinish = async (values) => {
console.log(values);
setLoading(true);
const result = await updateJob({
variables: { jobId: job.id, job: values },

View File

@@ -10,7 +10,6 @@ export default function JobAdminOwnerReassociate({ job }) {
const [form] = Form.useForm();
const [updateJob] = useMutation(UPDATE_JOB);
const handleFinish = async (values) => {
console.log(values);
setLoading(true);
const result = await updateJob({
variables: { jobId: job.id, job: { ownerid: values.ownerid } },

View File

@@ -10,7 +10,6 @@ export default function JobAdminOwnerReassociate({ job }) {
const [form] = Form.useForm();
const [updateJob] = useMutation(UPDATE_JOB);
const handleFinish = async (values) => {
console.log(values);
setLoading(true);
const result = await updateJob({
variables: { jobId: job.id, job: { vehicleid: values.vehicleid } },

View File

@@ -3,8 +3,6 @@ import { gql } from "@apollo/client";
import _ from "lodash";
export const GetSupplementDelta = async (client, jobId, newLines) => {
console.log("-----Begin Supplement-----");
const {
data: { joblines: existingLinesFromDb },
} = await client.query({

View File

@@ -61,7 +61,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
);
};
const overlay = bodyshop.cdk_dealerid && (
const overlay = (bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Menu onClick={handleMenuClick}>
{bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => (
<Menu.Item key={mapping.name}>{mapping.name}</Menu.Item>
@@ -69,7 +69,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
</Menu>
);
return bodyshop.cdk_dealerid ? (
return bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? (
<Dropdown overlay={overlay}>
<Button disabled={disabled}>{t("jobs.actions.dmsautoallocate")}</Button>
</Dropdown>

View File

@@ -1,7 +1,6 @@
import { DownOutlined } from "@ant-design/icons";
import { Dropdown, Menu } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
@@ -11,8 +10,6 @@ const mapStateToProps = createStructuredSelector({
});
export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) {
const { t } = useTranslation();
const handleClick = ({ item, key, keyPath }) => {
const est = item.props.value;
form.setFieldsValue(est);
@@ -37,7 +34,7 @@ export function JobsDetailChangeEstimator({ disabled, form, bodyshop }) {
href=" #"
onClick={(e) => e.preventDefault()}
>
{t("jobs.actions.changestimator")} <DownOutlined />
<DownOutlined />
</a>
</Dropdown>
);

View File

@@ -0,0 +1,43 @@
import { DownOutlined } from "@ant-design/icons";
import { Dropdown, Menu } from "antd";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobsDetailChangeFilehandler({ disabled, form, bodyshop }) {
const handleClick = ({ item, key, keyPath }) => {
const est = item.props.value;
form.setFieldsValue(est);
};
const menu = (
<div>
<Menu onClick={handleClick}>
{bodyshop.md_filehandlers.map((est, idx) => (
<Menu.Item value={est} key={idx}>
{`${est.ins_ct_fn} ${est.ins_ct_ln}`}
</Menu.Item>
))}
</Menu>
</div>
);
return (
<Dropdown overlay={menu} disabled={disabled}>
<a
className="ant-dropdown-link"
href=" #"
onClick={(e) => e.preventDefault()}
>
<DownOutlined />
</a>
</Dropdown>
);
}
export default connect(mapStateToProps, null)(JobsDetailChangeFilehandler);

View File

@@ -75,6 +75,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
>
<DateTimePicker />
</Form.Item>
<Form.Item
label={t("jobs.fields.date_next_contact")}
name="date_next_contact"
>
<DateTimePicker />
</Form.Item>
<Form.Item
label={t("jobs.fields.scheduled_completion")}
name="scheduled_completion"

View File

@@ -6,6 +6,7 @@ import {
InputNumber,
Row,
Select,
Space,
Switch,
} from "antd";
import React from "react";
@@ -23,7 +24,7 @@ import FormItemPhone, {
import Car from "../job-damage-visual/job-damage-visual.component";
import JobsDetailChangeEstimator from "../jobs-detail-change-estimator/jobs-detail-change-estimator.component";
import FormRow from "../layout-form-row/layout-form-row.component";
import JobsDetailChangeFileHandler from "../jobs-detail-change-filehandler/jobs-detail-change-filehandler.component";
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
@@ -85,7 +86,15 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city">
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_ct_ln")} name="ins_ct_ln">
<Form.Item
label={
<Space>
{t("jobs.fields.ins_ct_ln")}
<JobsDetailChangeFileHandler form={form} disabled={jobRO} />
</Space>
}
name="ins_ct_ln"
>
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn">
@@ -135,7 +144,7 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
label={t("jobs.fields.referral_source_extra")}
name="referral_source_extra"
>
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.alt_transport")} name="alt_transport">
<Select disabled={jobRO} allowClear>
@@ -219,12 +228,19 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
{t("jobs.forms.appraiserinfo")}
</Divider>
<JobsDetailChangeEstimator form={form} disabled={jobRO} />
<FormRow noDivider>
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ct_fn")} name="est_ct_fn">
<Form.Item
label={
<Space>
{t("jobs.fields.est_ct_fn")}
<JobsDetailChangeEstimator form={form} disabled={jobRO} />
</Space>
}
name="est_ct_fn"
>
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln">

View File

@@ -19,7 +19,6 @@ export default async function DuplicateJob(
variables: { id: jobId },
});
console.log("res", res);
const { jobs_by_pk } = res.data;
const existingJob = _.cloneDeep(jobs_by_pk);
delete existingJob.__typename;

View File

@@ -40,7 +40,6 @@ export function JobsDocumentsGalleryReassign({ bodyshop, galleryImages }) {
const updateImage = async (i, jobid) => {
//Move the cloudinary image
console.log(i);
//Update it in the database.
const result = await updateDocument({

View File

@@ -3,17 +3,17 @@ import { notification } from "antd";
import React, { useState } from "react";
//import SpinComponent from "../../components/loading-spinner/loading-spinner.component";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import AlertComponent from "../../components/alert/alert.component";
import { logImEXEvent } from "../../firebase/firebase.utils";
import {
DELETE_NOTE,
QUERY_NOTES_BY_JOB_PK,
} from "../../graphql/notes.queries";
import JobNotesComponent from "./jobs.notes.component";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import JobNotesComponent from "./jobs.notes.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -63,6 +63,7 @@ export function JobNotesContainer({ jobId, insertAuditTrail }) {
refetch={refetch}
deleteLoading={deleteLoading}
handleNoteDelete={handleNoteDelete}
ro_number={data ? data.jobs_by_pk.ro_number : null}
/>
);
}

View File

@@ -13,7 +13,9 @@ import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import { TemplateList } from "../../utils/TemplateConstants";
import NoteUpsertModal from "../note-upsert-modal/note-upsert-modal.container";
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
@@ -33,8 +35,12 @@ export function JobNotesComponent({
jobId,
setNoteUpsertContext,
deleteLoading,
ro_number,
}) {
const { t } = useTranslation();
const Templates = TemplateList("job_special", {
ro_number,
});
const columns = [
{
@@ -107,6 +113,18 @@ export function JobNotesComponent({
>
<EditFilled />
</Button>
<PrintWrapperComponent
emailOnly
templateObject={{
name: Templates.individual_job_note.key,
variables: { id: record.id },
}}
messageObject={{
subject: Templates.individual_job_note.subject,
}}
id={record.id}
/>
</Space>
),
},

View File

@@ -29,7 +29,7 @@ export function PartnerPingComponent({ setPartnerVersion }) {
//if (process.env.NODE_ENV === "development") return;
const PartnerResponse = await axios.post("http://localhost:1337/ping/");
const { appver, qbpath } = PartnerResponse.data;
console.log("SETTING PARTNER VERSION.");
setPartnerVersion(appver);
console.log({ appver, qbpath });
if (!qbpath) {

View File

@@ -119,7 +119,7 @@ export function PartsOrderListTableComponent({
</Button>
<Popconfirm
title={t("parts_orders.labels.confirmdelete")}
disabled={jobRO || !record.return}
disabled={jobRO}
onConfirm={async () => {
//Delete the parts return.!
@@ -139,7 +139,7 @@ export function PartsOrderListTableComponent({
});
}}
>
<Button disabled={jobRO || !record.return}>
<Button disabled={jobRO}>
<DeleteFilled />
</Button>
</Popconfirm>

View File

@@ -164,6 +164,7 @@ export default function PartsOrderModalComponent({
<Radio value={"none"}>{t("general.labels.none")}</Radio>
<Radio value={"e"}>{t("parts_orders.labels.email")}</Radio>
<Radio value={"p"}>{t("parts_orders.labels.print")}</Radio>
<Radio value={"oec"}>{t("parts_orders.labels.oec")}</Radio>
</Radio.Group>
</div>
);

View File

@@ -1,13 +1,16 @@
import { useMutation, useQuery } from "@apollo/client";
import { useMutation, useQuery, useApolloClient } from "@apollo/client";
import { Form, Modal, notification } from "antd";
import moment from "moment";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { logImEXEvent, auth } from "../../firebase/firebase.utils";
import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries";
import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries";
import {
INSERT_NEW_PARTS_ORDERS,
QUERY_PARTS_ORDER_OEC,
} from "../../graphql/parts-orders.queries";
import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { setEmailOptions } from "../../redux/email/email.actions";
@@ -26,6 +29,7 @@ import { TemplateList } from "../../utils/TemplateConstants";
import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import PartsOrderModalComponent from "./parts-order-modal.component";
import axios from "axios";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
@@ -52,7 +56,7 @@ export function PartsOrderModalContainer({
insertAuditTrail,
}) {
const { t } = useTranslation();
const client = useApolloClient();
const { visible, context, actions } = partsOrderModal;
const {
jobId,
@@ -175,7 +179,7 @@ export function PartsOrderModalContainer({
}
if (refetch) refetch();
toggleModalVisible();
const Templates = TemplateList("partsorder", context);
if (sendType === "e") {
@@ -215,7 +219,50 @@ export function PartsOrderModalContainer({
{},
"p"
);
} else if (sendType === "oec") {
//Send to Partner OEC.
try {
const partsOrder = await client.query({
query: QUERY_PARTS_ORDER_OEC,
variables: {
id: insertResult.data.insert_parts_orders.returning[0].id,
},
});
const oecResponse = await axios.post(
"http://localhost:1337/oec/",
partsOrder.data.parts_orders_by_pk,
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
},
}
);
if (oecResponse.data && oecResponse.data.success === false) {
notification.open({
type: "error",
message: t("parts_orders.errors.oec", {
error: oecResponse.data.error,
}),
});
}
} catch (error) {
console.log("Error OEC.", error);
notification["error"]({
message: t("parts_orders.errors.oec", {
error: JSON.stringify(error.message),
}),
});
return;
}
}
toggleModalVisible();
};
const initialValues = {

View File

@@ -60,12 +60,10 @@ export function PartsStatusPie({ bodyshop, joblines_status }) {
[pieColor, t]
);
const memoizedData = useMemo(() => Calculatedata(joblines_status), [
joblines_status,
Calculatedata,
]);
console.log("PartsStatusPie -> memoizedData", memoizedData);
const memoizedData = useMemo(
() => Calculatedata(joblines_status),
[joblines_status, Calculatedata]
);
return (
<div>

View File

@@ -8,6 +8,7 @@ export default function PrintWrapperComponent({
messageObject = {},
children,
id,
emailOnly = false,
}) {
const [loading, setLoading] = useState(false);
const handlePrint = async (type) => {
@@ -19,7 +20,7 @@ export default function PrintWrapperComponent({
return (
<Space>
{children || null}
<PrinterFilled onClick={() => handlePrint("p")} />
{!emailOnly && <PrinterFilled onClick={() => handlePrint("p")} />}
<MailFilled onClick={() => handlePrint("e")} />
{loading && <Spin />}
</Space>

View File

@@ -1,4 +1,4 @@
import { Input, PageHeader, Space, Spin } from "antd";
import { Input, Space, Spin } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -26,8 +26,7 @@ export function ProductionBoardFilters({
const { t } = useTranslation();
return (
<PageHeader
extra={
<Space wrap>
{loading && <Spin />}
<Input.Search
@@ -46,7 +45,6 @@ export function ProductionBoardFilters({
allowClear
/>
</Space>
}
></PageHeader>
);
}

View File

@@ -1,106 +1,171 @@
import { CalendarOutlined, EyeFilled } from "@ant-design/icons";
import { Card, Col, Row, Space } from "antd";
import React from "react";
import { Card, Row, Col, Dropdown } from "antd";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import ProductionAlert from "../production-list-columns/production-list-columns.alert.component";
import { EyeFilled } from "@ant-design/icons";
import { Link } from "react-router-dom";
import "./production-board-card.styles.scss";
import ProductionRemoveButton from "../production-remove-button/production-remove-button.component";
import { useTranslation } from "react-i18next";
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
import "./production-board-card.styles.scss";
export default function ProductionBoardCard(technician, card) {
export default function ProductionBoardCard(
technician,
card,
bodyshop,
cardSettings
) {
const { t } = useTranslation();
const menu = (
<div>
<Card title={t("general.labels.actions")}>
<ProductionRemoveButton jobId={card.id} />
</Card>
</div>
);
let employee_body, employee_prep, employee_refinish; //employee_csr;
if (card.employee_body) {
employee_body = bodyshop.employees.find((e) => e.id === card.employee_body);
}
if (card.employee_prep) {
employee_prep = bodyshop.employees.find((e) => e.id === card.employee_prep);
}
if (card.employee_refinish) {
employee_refinish = bodyshop.employees.find(
(e) => e.id === card.employee_refinish
);
}
// if (card.employee_csr) {
// employee_csr = bodyshop.employees.find((e) => e.id === card.employee_csr);
// }
return (
<Dropdown overlay={menu} trigger={["contextMenu"]}>
<Card
className="react-kanban-card imex-kanban-card tight-antd-rows"
//style={{ margin: ".2rem 0rem" }}
title={`${card.ro_number || t("general.labels.na")} - ${
card.v_model_yr
} ${card.v_make_desc || ""} ${card.v_model_desc || ""}`}
>
<Row>
<Card
className="react-kanban-card imex-kanban-card"
size="small"
title={
<Space>
<ProductionAlert record={card} key="alert" />
<span style={{ fontWeight: "bolder" }}>
{card.ro_number || t("general.labels.na")}
</span>
</Space>
}
extra={
technician ? (
<Link to={`/tech/joblookup?selected=${card.id}`}>
<EyeFilled />
</Link>
) : (
<Link to={`/manage/jobs/${card.id}`}>
<EyeFilled />
</Link>
)
}
>
<Row>
{cardSettings && cardSettings.ownr_nm && (
<Col span={24}>
<div className="ellipses">{`${card.ownr_fn || ""} ${
card.ownr_ln || ""
} ${card.ownr_co_nm || ""}`}</div>
{cardSettings && cardSettings.compact ? (
<div className="ellipses">{`${card.ownr_ln || ""} ${
card.ownr_co_nm || ""
}`}</div>
) : (
<div className="ellipses">{`${card.ownr_ln || ""}, ${
card.ownr_fn || ""
} ${card.ownr_co_nm || ""}`}</div>
)}
</Col>
</Row>
<Row>
<Col span={12}>
<div className="ellipses">{card.clm_no || ""}</div>
</Col>
<Col span={12}>
)}
<Col span={24}>
<div className="ellipses">{`${card.v_model_yr || ""} ${
card.v_make_desc || ""
} ${card.v_model_desc || ""}`}</div>
</Col>
{cardSettings && cardSettings.ins_co_nm && card.ins_co_nm && (
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
<div className="ellipses">{card.ins_co_nm || ""}</div>
</Col>
</Row>
<Row>
)}
{cardSettings && cardSettings.clm_no && card.clm_no && (
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
<div className="ellipses">{card.clm_no || ""}</div>
</Col>
)}
{cardSettings && cardSettings.employeeassignments && (
<Col span={24}>
<div className="imex-flex-row imex-flex-row__flex-space-around">
<div className="mex-flex-row__margin">
<div>{`B: ${card.labhrs.aggregate.sum.mod_lb_hrs || "?"}`}</div>
<div>{`R: ${card.larhrs.aggregate.sum.mod_lb_hrs || "?"}`}</div>
</div>
<div className="mex-flex-row__margin">
<div>{`B: ${
card.employee_body_rel
? `${card.employee_body_rel.first_name} ${card.employee_body_rel.last_name}`
: ""
}`}</div>
<div>{`P: ${
card.employee_prep_rel
? `${card.employee_prep_rel.first_name} ${card.employee_prep_rel.last_name}`
: ""
}`}</div>
<div>{`R: ${
card.employee_refinish_rel
? `${card.employee_refinish_rel.first_name} ${card.employee_refinish_rel.last_name}`
: ""
}`}</div>
<div>{`CSR: ${
card.employee_csr_rel
? `${card.employee_csr_rel.first_name} ${card.employee_csr_rel.last_name}`
: ""
}`}</div>
</div>
</div>
<Row>
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`B: ${
employee_body
? `${employee_body.first_name.substr(
0,
3
)} ${employee_body.last_name.charAt(0)}`
: ""
} ${card.labhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`P: ${
employee_prep
? `${employee_prep.first_name.substr(
0,
3
)} ${employee_prep.last_name.charAt(0)}`
: ""
}`}</Col>
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`R: ${
employee_refinish
? `${employee_refinish.first_name.substr(
0,
3
)} ${employee_refinish.last_name.charAt(0)}`
: ""
} ${card.larhrs.aggregate.sum.mod_lb_hrs || "?"}h`}</Col>
{/* <Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`C: ${
employee_csr
? `${employee_csr.first_name} ${employee_csr.last_name}`
: ""
}`}</Col> */}
</Row>
</Col>
</Row>
<Row>
<Col span={18}>
<DateTimeFormatter>{card.scheduled_completion}</DateTimeFormatter>
)}
{/* {cardSettings && cardSettings.laborhrs && (
<Col span={24}>
<Row>
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`B: ${
card.labhrs.aggregate.sum.mod_lb_hrs || "?"
} hrs`}</Col>
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>{`R: ${
card.larhrs.aggregate.sum.mod_lb_hrs || "?"
} hrs`}</Col>
</Row>
</Col>
<Col span={6}>
)} */}
{cardSettings &&
cardSettings.scheduled_completion &&
card.scheduled_completion && (
<Col span={cardSettings && cardSettings.compact ? 24 : 12}>
<Space>
<CalendarOutlined />
<DateTimeFormatter format="MM/DD">
{card.scheduled_completion}
</DateTimeFormatter>
</Space>
</Col>
)}
{cardSettings && cardSettings.ats && card.alt_transport && (
<Col span={12}>
<div>{card.alt_transport || ""}</div>
</Col>
</Row>
<div>
<ProductionListColumnProductionNote record={card} />
</div>
<div className="imex-flex-row imex-flex-row__flex-space-around">
<ProductionAlert record={card} key="alert" />
<ProductionSubletsManageComponent subletJobLines={card.subletLines} />
{technician ? (
<Link to={`/tech/joblookup?selected=${card.id}`}>
<EyeFilled />
</Link>
) : (
<Link to={`/manage/jobs/${card.id}`}>
<EyeFilled />
</Link>
)}
</div>
</Card>
</Dropdown>
)}
{cardSettings && cardSettings.sublets && (
<Col span={12}>
<ProductionSubletsManageComponent
subletJobLines={card.subletLines}
/>
</Col>
)}
{cardSettings && cardSettings.production_note && (
<Col span={24}>
{cardSettings && cardSettings.production_note && (
<ProductionListColumnProductionNote record={card} />
)}
</Col>
)}
</Row>
</Card>
);
}

View File

@@ -0,0 +1,154 @@
import { useMutation } from "@apollo/client";
import {
Button,
Card,
Col,
Form,
notification,
Popover,
Row,
Switch,
} from "antd";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { UPDATE_KANBAN_SETTINGS } from "../../graphql/user.queries";
export default function ProductionBoardKanbanCardSettings({
associationSettings,
}) {
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false);
const [updateKbSettings] = useMutation(UPDATE_KANBAN_SETTINGS);
useEffect(() => {
form.setFieldsValue(
associationSettings && associationSettings.kanban_settings
);
}, [form, associationSettings, visible]);
const { t } = useTranslation();
const handleFinish = async (values) => {
setLoading(true);
const result = await updateKbSettings({
variables: {
id: associationSettings && associationSettings.id,
ks: values,
},
});
if (result.errors) {
notification.open({
type: "error",
message: t("production.errors.settings", {
error: JSON.stringify(result.errors),
}),
});
}
setVisible(false);
setLoading(false);
};
const overlay = (
<div>
<Card>
<Form form={form} onFinish={handleFinish} layout="vertical">
<Row gutter={[16, 16]}>
<Col span={12}>
<Form.Item
label={t("production.labels.compact")}
name="compact"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
valuePropName="checked"
label={t("production.labels.ownr_nm")}
name="ownr_nm"
>
<Switch />
</Form.Item>
<Form.Item
valuePropName="checked"
label={t("production.labels.clm_no")}
name="clm_no"
>
<Switch />
</Form.Item>
<Form.Item
valuePropName="checked"
label={t("production.labels.ins_co_nm")}
name="ins_co_nm"
>
<Switch />
</Form.Item>
{/* <Form.Item
valuePropName="checked"
label={t("production.labels.laborhrs")}
name="laborhrs"
>
<Switch />
</Form.Item> */}
<Form.Item
valuePropName="checked"
label={t("production.labels.employeeassignments")}
name="employeeassignments"
>
<Switch />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
valuePropName="checked"
label={t("production.labels.scheduled_completion")}
name="scheduled_completion"
>
<Switch />
</Form.Item>
<Form.Item
valuePropName="checked"
label={t("production.labels.ats")}
name="ats"
>
<Switch />
</Form.Item>
<Form.Item
valuePropName="checked"
label={t("production.labels.production_note")}
name="production_note"
>
<Switch />
</Form.Item>
{/* <Form.Item
valuePropName='checked' label={t("production.labels.alert")} name="alert">
<Switch/>
</Form.Item> */}
<Form.Item
valuePropName="checked"
label={t("production.labels.sublets")}
name="sublets"
>
<Switch />
</Form.Item>
</Col>
</Row>
</Form>
<Button
onClick={() => {
form.submit();
}}
>
{t("general.actions.save")}
</Button>
</Card>
</div>
);
return (
<Popover content={overlay} visible={visible}>
<Button loading={loading} onClick={() => setVisible(true)}>
{t("production.labels.cardsettings")}
</Button>
</Popover>
);
}

View File

@@ -1,7 +1,8 @@
import { useApolloClient } from "@apollo/client";
import Board, { moveCard } from "@lourenci/react-kanban";
import "@lourenci/react-kanban/dist/styles.css";
import { notification } from "antd";
import Board, { moveCard } from "@asseinfo/react-kanban";
//import "@asseinfo/react-kanban/dist/styles.css";
import "./production-board-kanban.styles.scss";
import { Grid, notification, PageHeader, Space, Statistic } from "antd";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -16,6 +17,8 @@ import ProductionBoardFilters from "../production-board-filters/production-board
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { insertAuditTrail } from "../../redux/application/application.actions";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import ProductionBoardKanbanCardSettings from "./production-board-kanban.card-settings.component";
import styled from "styled-components";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -32,6 +35,7 @@ export function ProductionBoardKanbanComponent({
bodyshop,
technician,
insertAuditTrail,
associationSettings,
}) {
const [boardLanes, setBoardLanes] = useState({
columns: [{ id: "Loading...", title: "Loading...", cards: [] }],
@@ -116,6 +120,7 @@ export function ProductionBoardKanbanComponent({
newChildCard ? newChildCard.id : null,
newChildCardNewParent
),
// TODO: optimisticResponse
});
insertAuditTrail({
jobid: card.id,
@@ -131,24 +136,115 @@ export function ProductionBoardKanbanComponent({
}
};
const totalHrs = data
.reduce(
(acc, val) =>
acc +
(val.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) +
(val.larhrs?.aggregate?.sum?.mod_lb_hrs || 0),
0
)
.toFixed(1);
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
.filter((screen) => !!screen[1])
.slice(-1)[0];
const standardSizes = {
xs: "250",
sm: "250",
md: "250",
lg: "250",
xl: "250",
xxl: "250",
};
const compactSizes = {
xs: "150",
sm: "150",
md: "150",
lg: "150",
xl: "155",
xxl: "155",
};
const width = selectedBreakpoint
? associationSettings &&
associationSettings.kanban_settings &&
associationSettings.kanban_settings.compact
? compactSizes[selectedBreakpoint[0]]
: standardSizes[selectedBreakpoint[0]]
: "250";
return (
<div>
<Container width={width}>
<IndefiniteLoading loading={isMoving} />
<ProductionBoardFilters
filter={filter}
setFilter={setFilter}
loading={isMoving}
<PageHeader
title={
<Space>
<Statistic
title={t("dashboard.titles.productionhours")}
value={totalHrs}
/>
<Statistic
title={t("appointments.labels.inproduction")}
value={data && data.length}
/>
</Space>
}
extra={
<Space wrap>
<ProductionBoardFilters
filter={filter}
setFilter={setFilter}
loading={isMoving}
/>
<ProductionBoardKanbanCardSettings
associationSettings={associationSettings}
/>
</Space>
}
/>
<Board
children={boardLanes}
disableCardDrag={isMoving}
renderCard={(card) => ProductionBoardCard(technician, card)}
renderCard={(card) =>
ProductionBoardCard(
technician,
card,
bodyshop,
associationSettings &&
associationSettings.kanban_settings &&
Object.keys(associationSettings.kanban_settings).length > 0
? associationSettings.kanban_settings
: {
ats: true,
clm_no: true,
compact: false,
ownr_nm: true,
sublets: true,
ins_co_nm: true,
production_note: true,
employeeassignments: true,
scheduled_completion: true,
}
)
}
onCardDragEnd={handleDragEnd}
/>
</div>
</Container>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ProductionBoardKanbanComponent);
const Container = styled.div`
.react-kanban-card-skeleton,
.react-kanban-card,
.react-kanban-card-adder-form {
box-sizing: border-box;
max-width: ${(props) => props.width}px;
min-width: ${(props) => props.width}px;
}
`;

View File

@@ -1,25 +1,40 @@
import { useSubscription } from "@apollo/client";
import { useQuery, useSubscription } from "@apollo/client";
import React from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { SUBSCRIPTION_JOBS_IN_PRODUCTION } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { QUERY_KANBAN_SETTINGS } from "../../graphql/user.queries";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import ProductionBoardKanbanComponent from "./production-board-kanban.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
currentUser: selectCurrentUser,
});
export function ProductionBoardKanbanContainer({ bodyshop }) {
export function ProductionBoardKanbanContainer({ bodyshop, currentUser }) {
const { loading, data } = useSubscription(
SUBSCRIPTION_JOBS_IN_PRODUCTION,
{}
);
const { loading: associationSettingsLoading, data: associationSettings } =
useQuery(QUERY_KANBAN_SETTINGS, {
variables: { email: currentUser.email },
});
return (
<ProductionBoardKanbanComponent
loading={loading}
loading={loading || associationSettingsLoading}
data={data ? data.jobs : []}
associationSettings={
associationSettings && associationSettings.associations[0]
? associationSettings.associations[0]
: null
}
/>
);
}

View File

@@ -0,0 +1,123 @@
.react-kanban-board {
padding: 5px;
}
.react-kanban-card {
border-radius: 3px;
background-color: #fff;
padding: 4px;
margin-bottom: 7px;
}
// .react-kanban-card-skeleton,
// .react-kanban-card,
// .react-kanban-card-adder-form {
// box-sizing: border-box;
// max-width: 145px;
// min-width: 145px;
// }
.react-kanban-card--dragging {
box-shadow: 2px 2px grey;
}
.react-kanban-card__description {
padding-top: 10px;
}
.react-kanban-card__title {
border-bottom: 1px solid #eee;
padding-bottom: 5px;
font-weight: bold;
display: flex;
justify-content: space-between;
}
.react-kanban-column {
padding: 10px;
border-radius: 2px;
background-color: #eee;
margin: 5px;
}
.react-kanban-column input:focus {
outline: none;
}
.react-kanban-card-adder-form {
border-radius: 3px;
background-color: #fff;
padding: 10px;
margin-bottom: 7px;
}
.react-kanban-card-adder-form input {
border: 0px;
font-family: inherit;
font-size: inherit;
}
.react-kanban-card-adder-button {
width: 100%;
margin-top: 5px;
background-color: transparent;
cursor: pointer;
border: 1px solid #ccc;
transition: 0.3s;
border-radius: 3px;
font-size: 20px;
margin-bottom: 10px;
font-weight: bold;
}
.react-kanban-card-adder-button:hover {
background-color: #ccc;
}
.react-kanban-card-adder-form__title {
font-weight: bold;
border-bottom: 1px solid #eee;
padding-bottom: 5px;
font-weight: bold;
display: flex;
justify-content: space-between;
width: 100%;
padding: 0px;
}
.react-kanban-card-adder-form__title:focus {
outline: none;
}
.react-kanban-card-adder-form__description {
width: 100%;
margin-top: 10px;
}
.react-kanban-card-adder-form__description:focus {
outline: none;
}
.react-kanban-card-adder-form__button {
background-color: #eee;
border: none;
padding: 5px;
width: 45%;
margin-top: 5px;
border-radius: 3px;
}
.react-kanban-card-adder-form__button:hover {
transition: 0.3s;
cursor: pointer;
background-color: #ccc;
}
.react-kanban-column-header {
padding-bottom: 10px;
font-weight: bold;
}
.react-kanban-column-header input:focus {
outline: none;
}
.react-kanban-column-header__button {
color: #333333;
background-color: #ffffff;
border-color: #cccccc;
}
.react-kanban-column-header__button:hover,
.react-kanban-column-header__button:focus,
.react-kanban-column-header__button:active {
background-color: #e6e6e6;
}
.react-kanban-column-adder-button {
border: 2px dashed #eee;
height: 132px;
margin: 5px;
}
.react-kanban-column-adder-button:hover {
cursor: pointer;
}

View File

@@ -1,4 +1,5 @@
import i18n from "i18next";
import moment from "moment";
import React from "react";
import { Link } from "react-router-dom";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -11,11 +12,11 @@ import ProductionListColumnBodyPriority from "./production-list-columns.bodyprio
import ProductionListDate from "./production-list-columns.date.component";
import ProductionListColumnDetailPriority from "./production-list-columns.detailpriority.component";
import ProductionListEmployeeAssignment from "./production-list-columns.empassignment.component";
import ProductionListLastContacted from "./production-list-columns.lastcontacted.component";
import ProductionListColumnPaintPriority from "./production-list-columns.paintpriority.component";
import ProductionListColumnNote from "./production-list-columns.productionnote.component";
import ProductionListColumnStatus from "./production-list-columns.status.component";
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
import ProductionListLastContacted from "./production-list-columns.lastcontacted.component";
const r = ({ technician, state, activeStatuses }) => {
return [
@@ -109,6 +110,29 @@ const r = ({ technician, state, activeStatuses }) => {
state.sortedInfo.order,
render: (text, record) => <ProductionListLastContacted record={record} />,
},
{
title: i18n.t("jobs.fields.date_next_contact"),
dataIndex: "date_next_contact",
key: "date_next_contact",
ellipsis: true,
sorter: (a, b) => dateSort(a.date_next_contact, b.date_next_contact),
sortOrder:
state.sortedInfo.columnKey === "date_next_contact" &&
state.sortedInfo.order,
render: (text, record) => (
<span
style={{
color:
record.date_next_contact &&
moment(record.date_next_contact).isBefore(moment())
? "red"
: "",
}}
>
<ProductionListDate record={record} field="date_next_contact" time />
</span>
),
},
{
title: i18n.t("jobs.fields.scheduled_delivery"),
dataIndex: "scheduled_delivery",
@@ -332,7 +356,7 @@ const r = ({ technician, state, activeStatuses }) => {
render: (text, record) => (
<ProductionListEmployeeAssignment
record={record}
type="employee_body_rel"
type="employee_body"
/>
),
},
@@ -343,7 +367,7 @@ const r = ({ technician, state, activeStatuses }) => {
render: (text, record) => (
<ProductionListEmployeeAssignment
record={record}
type="employee_prep_rel"
type="employee_prep"
/>
),
},
@@ -352,10 +376,7 @@ const r = ({ technician, state, activeStatuses }) => {
dataIndex: "employee_csr",
key: "employee_csr",
render: (text, record) => (
<ProductionListEmployeeAssignment
record={record}
type="employee_csr_rel"
/>
<ProductionListEmployeeAssignment record={record} type="employee_csr" />
),
},
{
@@ -365,7 +386,7 @@ const r = ({ technician, state, activeStatuses }) => {
render: (text, record) => (
<ProductionListEmployeeAssignment
record={record}
type="employee_refinish_rel"
type="employee_refinish"
/>
),
},

View File

@@ -49,7 +49,7 @@ export function ProductionListEmpAssignment({
const result = await updateJob({
variables: { jobId: record.id, job: { [empAssignment]: employeeid } },
awaitRefetchQueries: true,
// awaitRefetchQueries: true,
});
insertAuditTrail({
@@ -145,13 +145,18 @@ export function ProductionListEmpAssignment({
</Row>
);
let theEmployee;
if (record[type])
theEmployee = bodyshop.employees.find((e) => e.id === record[type]);
return (
<Popover destroyTooltipOnHide content={popContent} visible={visibility}>
<Spin spinning={loading}>
{record[type] ? (
<div>
<span>{`${record[type].first_name || ""} ${
record[type].last_name || ""
<span>{`${theEmployee.first_name || ""} ${
theEmployee.last_name || ""
}`}</span>
<DeleteFilled
style={iconStyle}
@@ -174,13 +179,13 @@ export function ProductionListEmpAssignment({
const determineFieldName = (operation) => {
switch (operation) {
case "employee_body_rel":
case "employee_body":
return "employee_body";
case "employee_prep_rel":
case "employee_prep":
return "employee_prep";
case "employee_refinish_rel":
case "employee_refinish":
return "employee_refinish";
case "employee_csr_rel":
case "employee_csr":
return "employee_csr";
default:
return null;

View File

@@ -29,7 +29,11 @@ export function ProductionLastContacted({ currentUser, record }) {
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
const [form] = Form.useForm();
const handleFinish = async ({ date_last_contacted, note }) => {
const handleFinish = async ({
date_last_contacted,
date_next_contact,
note,
}) => {
logImEXEvent("production_last_contacted");
//e.stopPropagation();
@@ -38,6 +42,7 @@ export function ProductionLastContacted({ currentUser, record }) {
jobId: record.id,
job: {
date_last_contacted,
...(date_next_contact ? { date_next_contact } : {}),
},
},
});
@@ -98,7 +103,16 @@ export function ProductionLastContacted({ currentUser, record }) {
onClick={(e) => e.stopPropagation()}
>
<Form form={form} onFinish={handleFinish} layout="vertical">
<Form.Item name="date_last_contacted">
<Form.Item
name="date_last_contacted"
label={t("jobs.fields.date_last_contacted")}
>
<FormDateTimePickerComponent />
</Form.Item>
<Form.Item
name="date_next_contact"
label={t("jobs.fields.date_next_contact")}
>
<FormDateTimePickerComponent />
</Form.Item>
<Form.Item label={t("notes.labels.notetoadd")} name="note">

View File

@@ -182,10 +182,16 @@ export function ProductionListTable({
<div>
<PageHeader
title={
<Statistic
title={t("dashboard.titles.productionhours")}
value={totalHrs}
/>
<Space>
<Statistic
title={t("dashboard.titles.productionhours")}
value={totalHrs}
/>
<Statistic
title={t("appointments.labels.inproduction")}
value={dataSource && dataSource.length}
/>
</Space>
}
extra={
<Space wrap>

View File

@@ -56,7 +56,10 @@ export default function ProductionSubletsManageComponent({ subletJobLines }) {
<Button
key="complete"
loading={loading}
onClick={() => handleSubletMark(s, "complete")}
onClick={(e) => {
e.stopPropagation();
handleSubletMark(s, "complete");
}}
type={s.sublet_completed ? "primary" : "ghost"}
>
<CheckCircleFilled
@@ -66,7 +69,10 @@ export default function ProductionSubletsManageComponent({ subletJobLines }) {
<Button
key="sublet"
loading={loading}
onClick={() => handleSubletMark(s, "ignore")}
onClick={(e) => {
e.stopPropagation();
handleSubletMark(s, "ignore");
}}
type={s.sublet_ignored ? "primary" : "ghost"}
>
<EyeInvisibleFilled

View File

@@ -71,7 +71,7 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
const start = values.dates[0];
const end = values.dates[1];
const { id } = values;
console.log("values", values);
await GenerateDocument(
{
name: values.key,

View File

@@ -5,9 +5,8 @@ import {
Input,
Row,
Select,
Space,
Switch,
Typography,
Space, Switch,
Typography
} from "antd";
import axios from "axios";
import moment from "moment";
@@ -75,6 +74,12 @@ export function ScheduleJobModalComponent({
return (
<Row gutter={[16, 16]}>
<Col span={12}>
<Space>
<Typography.Title level={3}>{lbrHrsData?.jobs_by_pk?.ro_number}</Typography.Title>
<Typography.Title
level={4}
>{`B/R Hrs:${lbrHrsData?.jobs_by_pk.labhrs?.aggregate.sum.mod_lb_hrs}/${lbrHrsData?.jobs_by_pk.larhrs?.aggregate.sum.mod_lb_hrs}`}</Typography.Title>
</Space>
<LayoutFormRow grow>
<Form.Item
name="start"

View File

@@ -101,7 +101,6 @@ export function ScheduleJobModalContainer({
}
if (existingAppointments.data.appointments.length > 0) {
console.log("Cancelling all previous appts.");
await Promise.all(
existingAppointments.data.appointments.map((app) => {
return cancelAppointment({

View File

@@ -3,12 +3,9 @@ import { Form } from "antd";
import ConfigFormComponents from "../config-form-components/config-form-components.component";
export default function ShopCsiConfigForm({ selectedCsi }) {
console.log("ShopCsiConfigForm -> selectedCsi", selectedCsi);
const readOnly = !!selectedCsi;
const [form] = Form.useForm();
const handleFinish = (values) => {
console.log("values :>> ", values);
};
const handleFinish = (values) => {};
return (
<div>

View File

@@ -467,6 +467,19 @@ export default function ShopInfoGeneral({ form }) {
>
<Switch />
</Form.Item>
<Form.Item
name={["md_email_cc", "parts_order"]}
label={t("bodyshop.fields.md_email_cc", { template: "parts_order" })}
rules={[
{
required: true,
//message: t("general.validation.required"),
type: "array",
},
]}
>
<Select mode="tags" />
</Form.Item>
<Form.Item
name={["tt_allow_post_to_invoiced"]}
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
@@ -848,6 +861,88 @@ export default function ShopInfoGeneral({ form }) {
}}
</Form.List>
</LayoutFormRow>
<LayoutFormRow grow header={t("bodyshop.labels.filehandlers")}>
<Form.List name={["md_filehandlers"]}>
{(fields, { add, remove, move }) => {
return (
<div>
{fields.map((field, index) => (
<Form.Item key={field.key}>
<LayoutFormRow noDivider>
<Form.Item
label={t("jobs.fields.ins_ct_fn")}
key={`${index}ins_ct_fn`}
name={[field.name, "ins_ct_fn"]}
>
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ct_ln")}
key={`${index}ins_ct_ln`}
name={[field.name, "ins_ct_ln"]}
>
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ph1")}
key={`${index}ins_ph1`}
name={[field.name, "ins_ph1"]}
rules={[
({ getFieldValue }) =>
PhoneItemFormatterValidation(getFieldValue, [
field.name,
"ins_ph",
]),
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ea")}
key={`${index}ins_ea`}
name={[field.name, "ins_ea"]}
rules={[
{
type: "email",
message: "This is not a valid email address.",
},
]}
>
<FormItemEmail
email={form.getFieldValue([field.name, "ins_ea"])}
/>
</Form.Item>
<Space>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
</Space>
</LayoutFormRow>
</Form.Item>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => {
add();
}}
style={{ width: "100%" }}
>
{t("general.actions.add")}
</Button>
</Form.Item>
</div>
);
}}
</Form.List>
</LayoutFormRow>
<LayoutFormRow grow header={t("bodyshop.fields.md_ccc_rates")}>
<Form.List name={["md_ccc_rates"]}>
{(fields, { add, remove, move }) => {

View File

@@ -344,10 +344,6 @@ export default function ShopInfoROStatusComponent({ form }) {
const ColorPicker = ({ value, onChange, style, ...restProps }) => {
const handleChange = (color) => {
console.log(
"🚀 ~ file: shop-info.rostatus.component.jsx ~ line 345 ~ color",
color
);
if (onChange) onChange(color.rgb);
};
return (

View File

@@ -116,11 +116,10 @@ export function TimeTicketModalComponent({
<EmployeeSearchSelect
options={employeeAutoCompleteOptions}
onSelect={(value) => {
console.log(value);
const emps =
employeeAutoCompleteOptions &&
employeeAutoCompleteOptions.filter((e) => e.id === value)[0];
console.log(emps);
form.setFieldsValue({ flat_rate: emps && emps.flat_rate });
}}
/>

View File

@@ -37,10 +37,9 @@ export function UserValidatePwReset({
async function checkCodeValid() {
try {
const codeValid = await checkActionCode(auth, oobCode);
console.log("codeValid :>> ", codeValid);
setCodeValid({ loading: false, ...codeValid });
} catch (error) {
console.log("error :>> ", error);
setCodeValid({ loading: false, ...error });
}
}

View File

@@ -37,7 +37,7 @@ export function VendorsPhonebookAdd({ form, bodyshop, disabled }) {
"zip",
"country",
]);
console.log(`VendorValues`, VendorValues);
const result = await insertPhonebook({
variables: {
phonebook_entry: [

View File

@@ -98,7 +98,10 @@ export const QUERY_BODYSHOP = gql`
md_ded_notes
pbs_configuration
pbs_serialnumber
md_filehandlers
md_email_cc
employees {
user_email
id
active
first_name
@@ -192,6 +195,8 @@ export const UPDATE_SHOP = gql`
md_ded_notes
pbs_configuration
pbs_serialnumber
md_filehandlers
md_email_cc
employees {
id
first_name
@@ -199,6 +204,7 @@ export const UPDATE_SHOP = gql`
last_name
employee_number
rates
user_email
}
}
}

View File

@@ -2,7 +2,7 @@ import { gql } from "@apollo/client";
export const QUERY_EMPLOYEES = gql`
query QUERY_EMPLOYEES {
employees {
employees(order_by: { employee_number: asc }) {
last_name
id
first_name

View File

@@ -125,6 +125,7 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
scheduled_completion
scheduled_delivery
date_last_contacted
date_next_contact
ins_co_nm
clm_total
ownr_ph1
@@ -134,39 +135,10 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
production_vars
kanbanparent
alt_transport
joblines_status {
part_type
count
status
}
employee_body
employee_body_rel {
id
first_name
last_name
}
employee_refinish
employee_refinish_rel {
id
first_name
last_name
}
employee_prep
employee_prep_rel {
id
first_name
last_name
}
employee_csr_rel {
id
first_name
last_name
}
partcount: joblines_aggregate(where: { removed: { _eq: false } }) {
nodes {
status
}
}
employee_csr
labhrs: joblines_aggregate(
where: {
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
@@ -208,6 +180,7 @@ export const QUERY_LBR_HRS_BY_PK = gql`
query QUERY_LBR_HRS_BY_PK($id: uuid!) {
jobs_by_pk(id: $id) {
id
ro_number
labhrs: joblines_aggregate(
where: {
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
@@ -518,6 +491,7 @@ export const GET_JOB_BY_PK = gql`
date_scheduled
date_invoiced
date_last_contacted
date_next_contact
date_exported
status
owner_owing
@@ -535,6 +509,7 @@ export const GET_JOB_BY_PK = gql`
unq_seq
line_ind
line_desc
line_ref
part_type
oem_partno
db_price
@@ -760,6 +735,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
scheduled_delivery
date_invoiced
date_last_contacted
date_next_contact
date_open
date_exported
@@ -846,6 +822,7 @@ export const QUERY_TECH_JOB_DETAILS = gql`
scheduled_delivery
date_invoiced
date_last_contacted
date_next_contact
date_open
date_exported
voided

View File

@@ -14,6 +14,7 @@ export const QUERY_NOTES_BY_JOB_PK = gql`
query QUERY_NOTES_BY_JOB_PK($id: uuid!) {
jobs_by_pk(id: $id) {
id
ro_number
notes {
created_at
created_by

View File

@@ -11,6 +11,278 @@ export const INSERT_NEW_PARTS_ORDERS = gql`
}
`;
export const QUERY_PARTS_ORDER_OEC = gql`
query QUERY_PARTS_ORDER_OEC($id: uuid!) {
parts_orders_by_pk(id: $id) {
parts_order_lines {
jobline {
tran_code
act_price
db_ref
db_price
db_hrs
glass_flag
id
lbr_amt
lbr_hrs_j
lbr_inc
lbr_op
lbr_op_j
lbr_tax
lbr_typ_j
line_desc
line_ind
line_no
line_ref
location
misc_amt
misc_sublt
misc_tax
mod_lb_hrs
mod_lbr_ty
oem_partno
op_code_desc
paint_stg
paint_tone
part_qty
part_type
price_inc
price_j
prt_dsmk_m
prt_dsmk_p
tax_part
unq_seq
alt_co_id
alt_overrd
alt_part_i
alt_partm
alt_partno
bett_amt
bett_pctg
bett_tax
bett_type
cert_part
est_seq
}
act_price
id
db_price
line_desc
quantity
}
job {
bodyshop{
shopname
bill_tax_rates
}
ro_number
clm_no
asgn_no
asgn_date
state_tax_rate
area_of_damage
asgn_no
asgn_type
ciecaid
clm_addr1
clm_city
clm_addr2
clm_ct_fn
clm_ct_ln
clm_ct_ph
clm_ct_phx
clm_ctry
clm_ea
clm_fax
clm_faxx
clm_ofc_id
clm_ofc_nm
clm_ph1
clm_ph1x
clm_ph2
clm_ph2x
clm_st
clm_title
clm_total
clm_zip
ded_amt
est_addr1
est_addr2
est_city
est_co_nm
est_ct_fn
est_ctry
est_ct_ln
est_ea
est_ph1
est_st
est_zip
g_bett_amt
id
ins_addr1
ins_city
ins_addr2
ins_co_id
ins_co_nm
ins_ct_fn
ins_ct_ln
ins_ct_ph
ins_ct_phx
ins_ctry
ins_ea
ins_fax
ins_faxx
ins_memo
ins_ph1
ins_ph1x
ins_ph2
ins_ph2x
ins_st
ins_title
ins_zip
insd_addr1
insd_addr2
insd_city
insd_co_nm
insd_ctry
insd_ea
insd_fax
insd_faxx
insd_fn
insd_ln
insd_ph1
insd_ph1x
insd_ph2
insd_ph2x
insd_st
insd_title
insd_zip
job_totals
loss_cat
loss_date
loss_desc
loss_of_use
loss_type
ownr_addr1
ownr_addr2
ownr_city
ownr_co_nm
ownr_ctry
ownr_ea
ownr_fax
ownr_faxx
ownr_ph1
ownr_fn
ownr_ln
ownr_ph1x
ownr_ph2
ownr_ph2x
ownr_st
ownr_title
ownr_zip
parts_tax_rates
pay_amt
pay_date
pay_type
pay_chknm
payee_nms
plate_no
plate_st
po_number
policy_no
tax_lbr_rt
tax_levies_rt
tax_paint_mat_rt
tax_predis
tax_prethr
tax_pstthr
tax_registration_number
tax_str_rt
tax_shop_mat_rt
tax_sub_rt
tax_thramt
tax_tow_rt
theft_ind
tlos_ind
towin
v_color
v_make_desc
v_model_desc
v_model_yr
v_vin
vehicle {
v_bstyle
v_type
v_trimcode
v_tone
v_stage
v_prod_dt
v_options
v_paint_codes
v_model_yr
v_model_desc
v_mldgcode
v_makecode
v_make_desc
v_engine
v_cond
v_color
trim_color
shopid
plate_no
plate_st
db_v_code
v_vin
}
agt_zip
agt_st
agt_ph2x
agt_ph2
agt_ph1x
agt_ph1
agt_lic_no
agt_faxx
agt_fax
agt_ea
agt_ctry
agt_ct_phx
agt_ct_ph
agt_ct_ln
agt_ct_fn
agt_co_nm
agt_co_id
agt_city
agt_addr1
agt_addr2
adj_g_disc
rate_matd
rate_mash
rate_mapa
rate_mahw
rate_macs
rate_mabl
rate_ma3s
rate_ma2t
rate_ma2s
rate_lau
rate_las
rate_lar
rate_lam
rate_lag
rate_laf
rate_lae
rate_lad
rate_lab
rate_laa
rate_la4
rate_la3
rate_la2
rate_la1
}
}
}
`;
export const DELETE_PARTS_ORDER = gql`
mutation DELETE_PARTS_ORDER($partsOrderId: uuid!) {
delete_parts_orders_by_pk(id: $partsOrderId) {

View File

@@ -69,3 +69,25 @@ export const UPDATE_FCM_TOKEN = gql`
}
}
`;
export const QUERY_KANBAN_SETTINGS = gql`
query QUERY_KANBAN_SETTINGS($email: String!) {
associations(
where: { _and: { useremail: { _eq: $email }, active: { _eq: true } } }
) {
id
kanban_settings
}
}
`;
export const UPDATE_KANBAN_SETTINGS = gql`
mutation UPDATE_KANBAN_SETTINGS($id: uuid!, $ks: jsonb) {
update_associations_by_pk(
pk_columns: { id: $id }
_set: { kanban_settings: $ks }
) {
id
kanban_settings
}
}
`;

View File

@@ -58,7 +58,7 @@ export default class Home extends React.Component {
}, 500);
}
/* 如果不是 dva 2.0 请删除 end */
console.log("Setting $crisp segments", ["lead"]);
window.$crisp.push(["set", "session:segments", [["lead"]]]);
window.$crisp.push([
"set",

View File

@@ -1,4 +1,5 @@
import { Button, Col, PageHeader, Row } from "antd";
import { Button, Col, PageHeader, Row, Space, Form, Switch } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import ContractCarsContainer from "../../components/contract-cars/contract-cars.container";
@@ -13,14 +14,25 @@ export default function ContractCreatePageComponent({
const { t } = useTranslation();
const CreateButton = (
<Button
disabled={!selectedJobState[0] || !selectedCarState[0]}
type="primary"
onClick={() => form.submit()}
loading={loading}
>
{t("general.actions.create")}
</Button>
<Space size="large">
{selectedJobState[0] && selectedCarState[0] && (
<Form.Item
label={t("jobs.actions.addtoproduction")}
name="addtoproduction"
valuePropName="checked"
>
<Switch />
</Form.Item>
)}
<Button
disabled={!selectedJobState[0] || !selectedCarState[0]}
type="primary"
onClick={() => form.submit()}
loading={loading}
>
{t("general.actions.create")}
</Button>
</Space>
);
return (

View File

@@ -7,6 +7,7 @@ import { useHistory, useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
import { INSERT_NEW_CONTRACT } from "../../graphql/cccontracts.queries";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import {
setBreadcrumbs,
setSelectedHeader,
@@ -37,8 +38,9 @@ export function ContractCreatePageContainer({
(location.state && location.state.jobId) || null
);
const [insertContract] = useMutation(INSERT_NEW_CONTRACT);
const [intakeJob] = useMutation(UPDATE_JOB);
const handleFinish = async (values) => {
const handleFinish = async ({ addtoproduction, ...values }) => {
if (!!selectedCarState[0] && !!selectedJobState[0]) {
setLoading(true);
const result = await insertContract({
@@ -54,12 +56,35 @@ export function ContractCreatePageContainer({
},
},
});
if (!result.errors) {
//Update the courtesy car to have the damage.
notification["success"]({
message: t("contracts.successes.saved"),
});
//Intake the job if required
if (addtoproduction) {
const result2 = await intakeJob({
variables: {
jobId: selectedJobState[0],
job: {
actual_in: new Date(),
inproduction: true,
status: bodyshop.md_ro_statuses.default_arrived,
},
},
});
if (result2.errors) {
notification["error"]({
message: t("jobs.errors.saving", {
error: JSON.stringify(!result2.errors),
}),
});
return;
}
}
form.resetFields();
form.resetFields();
history.push(

View File

@@ -124,11 +124,6 @@ export function ContractDetailPageContainer({
if (loading) return <LoadingSpinner />;
if (!!!data.cccontracts_by_pk) return <NotFound />;
console.log(
"data.cccontracts_by_pk",
!!!data.cccontracts_by_pk,
data.cccontracts_by_pk
);
return (
<RbacWrapper action="contracts:detail">

View File

@@ -92,7 +92,7 @@ export function CsiContainerPage({ currentUser }) {
/>
</Layout>
);
console.log(bodyshop);
return (
<Layout
style={{ height: "100vh", display: "flex", flexDirection: "column" }}

View File

@@ -120,7 +120,11 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type="error" />;
if (!jobId || !bodyshop.cdk_dealerid || !(data && data.jobs_by_pk))
if (
!jobId ||
!(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) ||
!(data && data.jobs_by_pk)
)
return <Result status="404" />;
return (

View File

@@ -208,7 +208,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
>
<DateTimePicker disabled={jobRO} />
</Form.Item>
{bodyshop.cdk_dealerid && (
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.kmin")}
name="kmin"
@@ -221,7 +221,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
<InputNumber precision={0} disabled={jobRO} />
</Form.Item>
)}
{bodyshop.cdk_dealerid && (
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
<Form.Item
label={t("jobs.fields.kmout")}
name="kmout"

View File

@@ -10,7 +10,6 @@ export default function MobilePaymentComponent() {
const [paymentRequest, setPaymentRequest] = useState(null);
useEffect(() => {
if (stripe) {
console.log("in useeff");
const pr = stripe.paymentRequest({
country: "CA",
displayItems: [{ label: "Deductible", amount: 1 }],
@@ -23,10 +22,8 @@ export default function MobilePaymentComponent() {
requestPayerEmail: true,
});
console.log("pr", pr);
// Check the availability of the Payment Request API.
pr.canMakePayment().then((result) => {
console.log("result", result);
if (result) {
setPaymentRequest(pr);
} else {
@@ -45,7 +42,7 @@ export default function MobilePaymentComponent() {
if (paymentRequest) {
paymentRequest.on("paymentmethod", async (ev) => {
//Call server side to get the client secret
//Call server side to get the client secret
// Confirm the PaymentIntent without handling potential next actions (yet).
const { error: confirmError } = await stripe.confirmCardPayment(
"clientSecret",
@@ -63,14 +60,14 @@ export default function MobilePaymentComponent() {
// it to close the browser payment method collection interface.
ev.complete("success");
// Let Stripe.js handle the rest of the payment flow.
const { error, paymentIntent } = await stripe.confirmCardPayment(
const { error, //paymentIntent
} = await stripe.confirmCardPayment(
"clientSecret"
);
if (error) {
// The payment failed -- ask your customer for a new payment method.
} else {
// The payment has succeeded.
console.log('paymentIntent', paymentIntent)
}
}
});

View File

@@ -1,7 +1,7 @@
import React from "react";
import MobilePaymentComponent from "./mobile-payment.component";
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
import React from "react";
import MobilePaymentComponent from "./mobile-payment.component";
const stripePromise = new Promise((resolve, reject) => {
resolve(

View File

@@ -120,8 +120,6 @@ export function* calculateScheduleLoad({ payload: end }) {
yield put(scheduleLoadSuccess(load));
} catch (error) {
//console.log("Error in sendEmailFailure saga.", error.message);
console.log("error", error);
yield put(scheduleLoadFailure(error));
}
}
@@ -139,14 +137,7 @@ export function* insertAuditTrailSaga({
const state = yield select();
const bodyshop = state.user.bodyshop;
const currentUser = state.user.currentUser;
console.log(
"Inserting audit trail for",
bodyshop.shopname,
currentUser.email,
jobid,
billid,
operation
);
const variables = {
auditObj: {
bodyshopid: bodyshop.id,

View File

@@ -178,13 +178,13 @@ export function* signInSuccessSaga({ payload }) {
try {
// window.$crisp.push(["set", "user:email", [payload.email]]);
console.log("$crisp set nickname", [payload.displayName || payload.email]);
window.$crisp.push([
"set",
"user:nickname",
[payload.displayName || payload.email],
]);
console.log("Setting $crisp segments", ["user"]);
window.$crisp.push(["set", "session:segments", [["user"]]]);
Sentry.setUser({
@@ -235,7 +235,6 @@ export function* validatePasswordResetStart({ payload: { password, code } }) {
yield confirmPasswordReset(auth, code, password);
yield put(validatePasswordResetSuccess());
} catch (error) {
console.log("function*validatePasswordResetStart -> error", error);
yield put(validatePasswordResetFailure(error.message));
}
}
@@ -267,7 +266,6 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
try {
window.$crisp.push(["set", "user:company", [payload.shopname]]);
if (authRecord[0] && authRecord[0].user.validemail) {
console.log("$crisp user email", authRecord[0].user.email);
window.$crisp.push(["set", "user:email", [authRecord[0].user.email]]);
}
} catch (error) {

View File

@@ -271,6 +271,7 @@
"md_ccc_rates": "Courtesy Car Contract Rate Presets",
"md_classes": "Classes",
"md_ded_notes": "Deductible Notes",
"md_email_cc": "Auto Email CC: $t(printcenter.subjects.jobs.{{template}})",
"md_hour_split": {
"paint": "Paint Hour Split",
"prep": "Prep Hour Split"
@@ -503,6 +504,7 @@
"emaillater": "Email Later",
"employees": "Employees",
"estimators": "Estimators",
"filehandlers": "File Handlers",
"insurancecos": "Insurance Companies",
"intakechecklist": "Intake Checklist",
"jobstatuses": "Job Statuses",
@@ -535,6 +537,7 @@
"save": "Shop configuration saved successfully. "
},
"validation": {
"centermustexist": "The chosen responsibility center does not exist.",
"larsplit": "Refinish hour split must add up to 1.",
"useremailmustexist": "This email is not a valid user."
}
@@ -1091,6 +1094,7 @@
"addtoscoreboard": "Add to Scoreboard",
"allocate": "Allocate",
"autoallocate": "Auto Allocate",
"changefilehandler": "Change File Handler",
"changelaborrate": "Change Labor Rate",
"changestatus": "Change Status",
"changestimator": "Change Estimator",
@@ -1205,6 +1209,7 @@
"date_exported": "Exported",
"date_invoiced": "Invoiced",
"date_last_contacted": "Last Contacted Date",
"date_next_contact": "Next Contact Date",
"date_open": "Open",
"date_scheduled": "Scheduled",
"ded_amt": "Deductible",
@@ -1725,7 +1730,8 @@
"new": "New Conversation"
},
"errors": {
"invalidphone": "The phone number is invalid. Unable to open conversation. "
"invalidphone": "The phone number is invalid. Unable to open conversation. ",
"noattachedjobs": "No jobs have been associated to this conversation. "
},
"labels": {
"archive": "Archive",
@@ -1735,6 +1741,7 @@
"nojobs": "Not associated to any job.",
"phonenumber": "Phone #",
"presets": "Presets",
"recentonly": "Only your most recent 50 conversations will be shown here. If you are looking for an older conversation, find the related contact and click their phone number to view the conversation.",
"selectmedia": "Select Media",
"sentby": "Sent by {{by}} at {{time}}",
"typeamessage": "Send a message...",
@@ -1824,8 +1831,10 @@
"receivebill": "Receive Bill"
},
"errors": {
"associatedbills": "This parts order cannot",
"backordering": "Error backordering part {{message}}.",
"creating": "Error encountered when creating parts order. "
"creating": "Error encountered when creating parts order. ",
"oec": "Error creating EMS files for OEC. {{error}}"
},
"fields": {
"act_price": "Price",
@@ -1849,10 +1858,11 @@
},
"labels": {
"allpartsto": "All Parts Location",
"confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. ",
"confirmdelete": "Are you sure you want to delete this item? It cannot be recovered. Job line statuses will not be updated and may require manual review. ",
"email": "Send by Email",
"inthisorder": "Parts in this Order",
"newpartsorder": "New Parts Order",
"oec": "Order via OEC",
"orderhistory": "Order History",
"parts_orders": "Parts Orders",
"print": "Show Printed Form",
@@ -1968,6 +1978,7 @@
"zip": "Postal Code/Zip"
},
"3rdpartypayer": "Invoice to Third Party Payer",
"ab_proof_of_loss": "AB - Proof of Loss",
"appointment_confirmation": "Appointment Confirmation",
"appointment_reminder": "Appointment Reminder",
"casl_authorization": "CASL Authorization",
@@ -1985,6 +1996,7 @@
"fippa_authorization": "FIPPA Authorization",
"glass_express_checklist": "Glass Express Checklist",
"guarantee": "Repair Guarantee",
"individual_job_note": "Job Note RO # {{ro_number}}",
"invoice_customer_payable": "Invoice (Customer Payable)",
"invoice_total_payable": "Invoice (Total Payable)",
"iou_form": "IOU Form",
@@ -2023,7 +2035,8 @@
"worksheet_by_line_number": "Worksheet by Line Number",
"worksheet_sorted_by_operation": "Worksheet by Operation",
"worksheet_sorted_by_operation_no_hours": "Worksheet by Operation (No Hours)",
"worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type"
"worksheet_sorted_by_operation_part_type": "Worksheet by Operation & Part Type",
"worksheet_sorted_by_operation_type": "Worksheet by Operation Type"
},
"labels": {
"groups": {
@@ -2068,20 +2081,31 @@
},
"errors": {
"boardupdate": "Error encountered updating job. {{message}}",
"removing": "Error removing from production board. {{error}}"
"removing": "Error removing from production board. {{error}}",
"settings": "Error saving board settings: {{error}}"
},
"labels": {
"alert": "Alert",
"alertoff": "Remove alert from job",
"alerton": "Add alert to job",
"ats": "Alternative Transportation",
"bodyhours": "B",
"bodypriority": "B/P",
"cardsettings": "Card Settings",
"clm_no": "Claim Number",
"compact": "Compact Cards",
"detailpriority": "D/P",
"employeeassignments": "Employee Assignments",
"employeesearch": "Employee Search",
"ins_co_nm": "Insurance Company Name",
"jobdetail": "Job Details",
"laborhrs": "Labor Hours",
"note": "Production Note",
"ownr_nm": "Owner Name",
"paintpriority": "P/P",
"production_note": "Production Note",
"refinishhours": "R",
"scheduled_completion": "Scheduled Completion",
"selectview": "Select a View",
"sublets": "Sublets",
"totalhours": "Total Hrs ",
@@ -2176,6 +2200,7 @@
"open_orders_csr": "Open Orders by CSR",
"open_orders_estimator": "Open Orders by Estimator",
"open_orders_ins_co": "Open Orders by Insurance Company",
"open_orders_status": "Open Orders by Status",
"parts_backorder": "Backordered Parts",
"parts_not_recieved": "Parts Not Received",
"payments_by_date": "Payments by Date",

View File

@@ -271,6 +271,7 @@
"md_ccc_rates": "",
"md_classes": "",
"md_ded_notes": "",
"md_email_cc": "",
"md_hour_split": {
"paint": "",
"prep": ""
@@ -503,6 +504,7 @@
"emaillater": "",
"employees": "",
"estimators": "",
"filehandlers": "",
"insurancecos": "",
"intakechecklist": "",
"jobstatuses": "",
@@ -535,6 +537,7 @@
"save": ""
},
"validation": {
"centermustexist": "",
"larsplit": "",
"useremailmustexist": ""
}
@@ -1091,6 +1094,7 @@
"addtoscoreboard": "",
"allocate": "",
"autoallocate": "",
"changefilehandler": "",
"changelaborrate": "",
"changestatus": "Cambiar Estado",
"changestimator": "",
@@ -1205,6 +1209,7 @@
"date_exported": "Exportado",
"date_invoiced": "Facturado",
"date_last_contacted": "",
"date_next_contact": "",
"date_open": "Abierto",
"date_scheduled": "Programado",
"ded_amt": "Deducible",
@@ -1725,7 +1730,8 @@
"new": ""
},
"errors": {
"invalidphone": ""
"invalidphone": "",
"noattachedjobs": ""
},
"labels": {
"archive": "",
@@ -1735,6 +1741,7 @@
"nojobs": "",
"phonenumber": "",
"presets": "",
"recentonly": "",
"selectmedia": "",
"sentby": "",
"typeamessage": "Enviar un mensaje...",
@@ -1824,8 +1831,10 @@
"receivebill": ""
},
"errors": {
"associatedbills": "",
"backordering": "",
"creating": "Se encontró un error al crear el pedido de piezas."
"creating": "Se encontró un error al crear el pedido de piezas.",
"oec": ""
},
"fields": {
"act_price": "",
@@ -1853,6 +1862,7 @@
"email": "Enviar por correo electrónico",
"inthisorder": "Partes en este pedido",
"newpartsorder": "",
"oec": "",
"orderhistory": "Historial de pedidos",
"parts_orders": "",
"print": "Mostrar formulario impreso",
@@ -1968,6 +1978,7 @@
"zip": ""
},
"3rdpartypayer": "",
"ab_proof_of_loss": "",
"appointment_confirmation": "",
"appointment_reminder": "",
"casl_authorization": "",
@@ -1985,6 +1996,7 @@
"fippa_authorization": "",
"glass_express_checklist": "",
"guarantee": "",
"individual_job_note": "",
"invoice_customer_payable": "",
"invoice_total_payable": "",
"iou_form": "",
@@ -2023,7 +2035,8 @@
"worksheet_by_line_number": "",
"worksheet_sorted_by_operation": "",
"worksheet_sorted_by_operation_no_hours": "",
"worksheet_sorted_by_operation_part_type": ""
"worksheet_sorted_by_operation_part_type": "",
"worksheet_sorted_by_operation_type": ""
},
"labels": {
"groups": {
@@ -2068,20 +2081,31 @@
},
"errors": {
"boardupdate": "",
"removing": ""
"removing": "",
"settings": ""
},
"labels": {
"alert": "",
"alertoff": "",
"alerton": "",
"ats": "",
"bodyhours": "",
"bodypriority": "",
"cardsettings": "",
"clm_no": "",
"compact": "",
"detailpriority": "",
"employeeassignments": "",
"employeesearch": "",
"ins_co_nm": "",
"jobdetail": "",
"laborhrs": "",
"note": "",
"ownr_nm": "",
"paintpriority": "",
"production_note": "",
"refinishhours": "",
"scheduled_completion": "",
"selectview": "",
"sublets": "",
"totalhours": "",
@@ -2176,6 +2200,7 @@
"open_orders_csr": "",
"open_orders_estimator": "",
"open_orders_ins_co": "",
"open_orders_status": "",
"parts_backorder": "",
"parts_not_recieved": "",
"payments_by_date": "",

View File

@@ -271,6 +271,7 @@
"md_ccc_rates": "",
"md_classes": "",
"md_ded_notes": "",
"md_email_cc": "",
"md_hour_split": {
"paint": "",
"prep": ""
@@ -503,6 +504,7 @@
"emaillater": "",
"employees": "",
"estimators": "",
"filehandlers": "",
"insurancecos": "",
"intakechecklist": "",
"jobstatuses": "",
@@ -535,6 +537,7 @@
"save": ""
},
"validation": {
"centermustexist": "",
"larsplit": "",
"useremailmustexist": ""
}
@@ -1091,6 +1094,7 @@
"addtoscoreboard": "",
"allocate": "",
"autoallocate": "",
"changefilehandler": "",
"changelaborrate": "",
"changestatus": "Changer le statut",
"changestimator": "",
@@ -1205,6 +1209,7 @@
"date_exported": "Exportés",
"date_invoiced": "Facturé",
"date_last_contacted": "",
"date_next_contact": "",
"date_open": "Ouvrir",
"date_scheduled": "Prévu",
"ded_amt": "Déductible",
@@ -1725,7 +1730,8 @@
"new": ""
},
"errors": {
"invalidphone": ""
"invalidphone": "",
"noattachedjobs": ""
},
"labels": {
"archive": "",
@@ -1735,6 +1741,7 @@
"nojobs": "",
"phonenumber": "",
"presets": "",
"recentonly": "",
"selectmedia": "",
"sentby": "",
"typeamessage": "Envoyer un message...",
@@ -1824,8 +1831,10 @@
"receivebill": ""
},
"errors": {
"associatedbills": "",
"backordering": "",
"creating": "Erreur rencontrée lors de la création de la commande de pièces."
"creating": "Erreur rencontrée lors de la création de la commande de pièces.",
"oec": ""
},
"fields": {
"act_price": "",
@@ -1853,6 +1862,7 @@
"email": "Envoyé par email",
"inthisorder": "Pièces dans cette commande",
"newpartsorder": "",
"oec": "",
"orderhistory": "Historique des commandes",
"parts_orders": "",
"print": "Afficher le formulaire imprimé",
@@ -1968,6 +1978,7 @@
"zip": ""
},
"3rdpartypayer": "",
"ab_proof_of_loss": "",
"appointment_confirmation": "",
"appointment_reminder": "",
"casl_authorization": "",
@@ -1985,6 +1996,7 @@
"fippa_authorization": "",
"glass_express_checklist": "",
"guarantee": "",
"individual_job_note": "",
"invoice_customer_payable": "",
"invoice_total_payable": "",
"iou_form": "",
@@ -2023,7 +2035,8 @@
"worksheet_by_line_number": "",
"worksheet_sorted_by_operation": "",
"worksheet_sorted_by_operation_no_hours": "",
"worksheet_sorted_by_operation_part_type": ""
"worksheet_sorted_by_operation_part_type": "",
"worksheet_sorted_by_operation_type": ""
},
"labels": {
"groups": {
@@ -2068,20 +2081,31 @@
},
"errors": {
"boardupdate": "",
"removing": ""
"removing": "",
"settings": ""
},
"labels": {
"alert": "",
"alertoff": "",
"alerton": "",
"ats": "",
"bodyhours": "",
"bodypriority": "",
"cardsettings": "",
"clm_no": "",
"compact": "",
"detailpriority": "",
"employeeassignments": "",
"employeesearch": "",
"ins_co_nm": "",
"jobdetail": "",
"laborhrs": "",
"note": "",
"ownr_nm": "",
"paintpriority": "",
"production_note": "",
"refinishhours": "",
"scheduled_completion": "",
"selectview": "",
"sublets": "",
"totalhours": "",
@@ -2176,6 +2200,7 @@
"open_orders_csr": "",
"open_orders_estimator": "",
"open_orders_ins_co": "",
"open_orders_status": "",
"parts_backorder": "",
"parts_not_recieved": "",
"payments_by_date": "",

View File

@@ -12,7 +12,9 @@ export function DateFormatter(props) {
export function DateTimeFormatter(props) {
return props.children
? moment(props.children).format("MM/DD/YYYY hh:mm a")
? moment(props.children).format(
props.format ? props.format : "MM/DD/YYYY hh:mm a"
)
: null;
}

View File

@@ -195,7 +195,6 @@ export const GenerateDocuments = async (templates) => {
};
const fetchContextData = async (templateObject) => {
console.log("Fetching context data", templateObject);
const bodyshop = store.getState().user.bodyshop;
jsreport.headers["Authorization"] =

View File

@@ -182,6 +182,18 @@ export const TemplateList = (type, context) => {
disabled: false,
group: "worksheet",
},
worksheet_sorted_by_operation_type: {
title: i18n.t(
"printcenter.jobs.worksheet_sorted_by_operation_type"
),
description: "All Jobs Notes",
subject: i18n.t(
"printcenter.jobs.worksheet_sorted_by_operation_type"
),
key: "worksheet_sorted_by_operation_type",
disabled: false,
group: "worksheet",
},
worksheet_sorted_by_operation: {
title: i18n.t("printcenter.jobs.worksheet_sorted_by_operation"),
description: "All Jobs Notes",
@@ -407,6 +419,17 @@ export const TemplateList = (type, context) => {
CA_MB: true,
},
},
ab_proof_of_loss: {
title: i18n.t("printcenter.jobs.ab_proof_of_loss"),
description: "Thank You Letter by RO",
key: "ab_proof_of_loss",
subject: i18n.t("printcenter.jobs.ab_proof_of_loss"),
disabled: false,
group: "pre",
regions: {
CA_AB: true,
},
},
// parts_label_multi: {
// title: i18n.t("printcenter.jobs.parts_label_multi"),
// description: "Thank You Letter by RO",
@@ -440,6 +463,15 @@ export const TemplateList = (type, context) => {
subject: i18n.t("printcenter.jobs.csi_invitation_action"),
disabled: false,
},
individual_job_note: {
title: i18n.t("printcenter.jobs.individual_job_note"),
description: "CSI invite",
key: "individual_job_note",
subject: i18n.t("printcenter.jobs.individual_job_note", {
ro_number: (context && context.ro_number) || "",
}),
disabled: false,
},
}
: {}),
...(!type || type === "appointment"
@@ -1181,6 +1213,19 @@ export const TemplateList = (type, context) => {
},
group: "jobs",
},
open_orders_status: {
title: i18n.t("reportcenter.templates.open_orders_status"),
description: "",
subject: i18n.t("reportcenter.templates.open_orders_status"),
key: "open_orders_status",
//idtype: "vendor",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_open"),
},
group: "jobs",
},
open_orders_csr: {
title: i18n.t("reportcenter.templates.open_orders_csr"),
description: "",

File diff suppressed because it is too large Load Diff

View File

@@ -203,6 +203,7 @@
- authlevel
- default_prod_list_view
- id
- kanban_settings
- qbo_realmId
- shopid
- useremail
@@ -217,6 +218,7 @@
- active
- authlevel
- default_prod_list_view
- kanban_settings
- qbo_realmId
filter:
bodyshop:
@@ -827,7 +829,9 @@
- md_ccc_rates
- md_classes
- md_ded_notes
- md_email_cc
- md_estimators
- md_filehandlers
- md_hour_split
- md_ins_cos
- md_jobline_presets
@@ -905,7 +909,9 @@
- md_ccc_rates
- md_classes
- md_ded_notes
- md_email_cc
- md_estimators
- md_filehandlers
- md_hour_split
- md_ins_cos
- md_jobline_presets
@@ -2154,6 +2160,7 @@
- sublet_completed
- sublet_ignored
- tax_part
- tran_code
- unq_seq
- updated_at
select_permissions:
@@ -2215,6 +2222,7 @@
- sublet_completed
- sublet_ignored
- tax_part
- tran_code
- unq_seq
- updated_at
filter:
@@ -2287,6 +2295,7 @@
- sublet_completed
- sublet_ignored
- tax_part
- tran_code
- unq_seq
- updated_at
filter:
@@ -2299,7 +2308,16 @@
_eq: X-Hasura-User-Id
- active:
_eq: true
check: null
check:
job:
bodyshop:
associations:
_and:
- user:
authid:
_eq: X-Hasura-User-Id
- active:
_eq: true
delete_permissions:
- role: user
permission:
@@ -2590,6 +2608,7 @@
- date_exported
- date_invoiced
- date_last_contacted
- date_next_contact
- date_open
- date_scheduled
- ded_amt
@@ -2841,6 +2860,7 @@
- date_exported
- date_invoiced
- date_last_contacted
- date_next_contact
- date_open
- date_scheduled
- ded_amt
@@ -3102,6 +3122,7 @@
- date_exported
- date_invoiced
- date_last_contacted
- date_next_contact
- date_open
- date_scheduled
- ded_amt

View File

@@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."bodyshops" add column "md_filehandlers" jsonb
-- null default jsonb_build_array();

View File

@@ -0,0 +1,2 @@
alter table "public"."bodyshops" add column "md_filehandlers" jsonb
null default jsonb_build_array();

Some files were not shown because too many files have changed in this diff Show More