Compare commits

..

95 Commits

Author SHA1 Message Date
Patrick Fic
402d13ad99 Merge branch 'test' into release/2021-10-15 2021-10-15 10:53:50 -07:00
Patrick Fic
e803f5a2d4 IO-1471 Total Hrs in produciton. 2021-10-15 10:53:24 -07:00
Patrick Fic
161d476ab3 IO-256 Export payments with no matching invoice & export cust data. 2021-10-14 15:07:31 -07:00
Patrick Fic
ce84a89cf3 Merge branch 'release/2021-10-15' into test 2021-10-14 11:22:14 -07:00
Patrick Fic
1d210a9e52 IO-1468 QB and CDK Updates for MCE Markup 2021-10-14 11:21:06 -07:00
Patrick Fic
660f463aea IO-1468 Resolve line markup for MCE. 2021-10-14 10:52:08 -07:00
Patrick Fic
ad9f01111c Merge branch 'release/2021-10-15' into test 2021-10-13 21:22:55 -07:00
Patrick Fic
1b885e4114 IO-256 Add description to receivables export. 2021-10-13 21:22:38 -07:00
Patrick Fic
b56742bcb2 IO-256 QBO Improvements. 2021-10-13 21:12:02 -07:00
Patrick Fic
40d4d69a9a Merge branch 'release/2021-10-15' into test 2021-10-13 17:03:00 -07:00
Patrick Fic
b54d5beb76 IO-256 Resolve Bill Center reference 2021-10-13 17:02:39 -07:00
Patrick Fic
5cbcd440f5 Merge branch 'feature/qbo' into test 2021-10-13 15:49:02 -07:00
Patrick Fic
1cdc34249a IO-256 Fix null handling for missing metadata. 2021-10-13 15:48:43 -07:00
Patrick Fic
8bbb218777 Merge branch 'feature/qbo' into test
# Conflicts:
#	server/accounting/qbo/qbo-payables.js
#	server/accounting/qbo/qbo-payments.js
#	server/accounting/qbo/qbo-receivables.js
2021-10-13 15:25:02 -07:00
Patrick Fic
755ac7f657 IO-256 Improved Logging 2021-10-13 15:24:14 -07:00
Patrick Fic
d7b884ff86 Revert "IO-256 Genericize email."
This reverts commit fda3620ed0.
2021-10-13 15:14:26 -07:00
Patrick Fic
fda3620ed0 IO-256 Genericize email. 2021-10-13 15:10:36 -07:00
Patrick Fic
61ad9f0d58 IO-256 Add CORS back for QBO. 2021-10-13 15:01:59 -07:00
Patrick Fic
804c8ad40a IO-256 Add cookie location 2021-10-13 14:49:47 -07:00
Patrick Fic
0ddf009f8f Reverse CORS & Fix Cookie Setting. 2021-10-13 14:35:39 -07:00
Patrick Fic
14309b5c96 QBO CORS Updates 2021-10-13 14:06:25 -07:00
Patrick Fic
57d9de469a Add CORS to Server. 2021-10-13 14:01:59 -07:00
Patrick Fic
404ade396c QB URL Updates. 2021-10-13 13:39:04 -07:00
Patrick Fic
bdad6da6d9 QB URL Fix. 2021-10-13 13:35:42 -07:00
Patrick Fic
e7ef3b94c1 QB Env update. 2021-10-13 13:34:56 -07:00
Patrick Fic
c19c92ab7e QBO port fix. 2021-10-13 13:25:15 -07:00
Patrick Fic
944229bae3 Update process env. 2021-10-13 13:22:56 -07:00
Patrick Fic
661b05d9e3 Merge branch 'feature/qbo' into test 2021-10-13 13:15:48 -07:00
Patrick Fic
4d1d471a66 Merge branch 'release/2021-10-15' into test 2021-10-13 13:15:35 -07:00
Patrick Fic
3e84fbbaf4 IO-1458 IO-1465 Sorting Fixes. 2021-10-13 11:52:11 -07:00
Patrick Fic
9ee8e9007a IO-256 Add Payables Posting. 2021-10-12 20:18:06 -07:00
Patrick Fic
4d52a5c44a IO-256 Exporting of payments 2021-10-12 19:07:43 -07:00
Patrick Fic
fff9073f9d IO-256 Add vendor credits. 2021-10-12 16:54:28 -07:00
Patrick Fic
71f0b8a005 Merge branch 'release/2021-10-15' into test 2021-10-12 16:41:01 -07:00
Patrick Fic
d2b965f79e Resolve CI Issue. 2021-10-12 16:40:27 -07:00
Patrick Fic
a02aa71a95 Merged in release/2021-10-15 (pull request #248)
release/2021-10-15

Approved-by: Patrick Fic
2021-10-12 23:33:17 +00:00
Patrick Fic
7562bf5c95 IO-1418 Allow owner re-search on import. 2021-10-12 16:17:31 -07:00
Patrick Fic
f9521483e2 IO-1448 Disable negative deductible amounts. 2021-10-12 14:39:20 -07:00
Patrick Fic
ca85858885 IO-1453 Allow null scheduled completion dates on cehcklist view. 2021-10-12 14:27:22 -07:00
Patrick Fic
c7b3a94533 IO-1441 Conversion safety check. 2021-10-12 14:18:09 -07:00
Patrick Fic
b010c9ecb0 IO-1458 Production Board Sort ORder 2021-10-12 13:50:25 -07:00
Patrick Fic
0b98d04bac IO-1458 Production Board Sort Order 2021-10-12 13:49:32 -07:00
Patrick Fic
e25e388e59 Merged in release/2021-10-15 (pull request #247)
IO-233 Replace unknown CDK function.

Approved-by: Patrick Fic
2021-10-12 19:06:35 +00:00
Patrick Fic
10654b7916 IO-233 Replace unknown CDK function. 2021-10-12 12:04:50 -07:00
Patrick Fic
3572fff2c1 Merged in release/2021-10-08 (pull request #245)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-07 23:38:03 +00:00
Patrick Fic
774e4cdf94 IO-1430 Add note on last contacted update. 2021-10-07 16:26:48 -07:00
Patrick Fic
65ade5cab8 IO-1428 add ph2 to global search. 2021-10-07 16:00:35 -07:00
Patrick Fic
bf21a073fb IO-1415 Update cache on line delete. 2021-10-07 15:48:29 -07:00
Patrick Fic
851f1c265f Merged in release/2021-10-08 (pull request #244)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-07 16:51:36 +00:00
Patrick Fic
51f3b5927b IO-1428 IO-1338 Add ownr_ph2. 2021-10-07 09:47:10 -07:00
Patrick Fic
42c779f368 IO-1415 Default tax part to true. 2021-10-07 09:19:37 -07:00
Patrick Fic
c104ee4fd9 Merged in release/2021-10-08 (pull request #243)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-06 20:37:34 +00:00
Patrick Fic
0b2efa31b5 IO-1375 IO-1383 CDK Tax Addition 2021-10-06 13:37:14 -07:00
Patrick Fic
17baa8fcb2 IO-1404 Rates in shop info minimums 2021-10-05 16:36:53 -07:00
Patrick Fic
e550baf59d Merged in release/2021-10-08 (pull request #242)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-05 23:20:08 +00:00
Patrick Fic
fd53eb92e6 Merge branch 'test' into release/2021-10-08 2021-10-05 16:19:41 -07:00
Patrick Fic
6521c0bfb8 IO-1413 Change color of kanban background 2021-10-05 14:22:45 -07:00
Patrick Fic
50489dd682 IO-1415 Add tax part & refresh line ticket on line edit 2021-10-05 14:15:21 -07:00
Patrick Fic
220afa5add IO-1405 resolve shift label issues. 2021-10-05 14:05:16 -07:00
Patrick Fic
9d549b02fe IO-1410 Remove ded from lbr lines on reconciliation. 2021-10-05 13:59:43 -07:00
Patrick Fic
ca2ded047b Merged in release/2021-10-08 (pull request #241)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-05 18:48:13 +00:00
Patrick Fic
c423e61ce8 IO-1422 Resolve send email with attachments. 2021-10-05 11:47:37 -07:00
Patrick Fic
65550c7bf4 IO-1436 App tax part fix to all regions. 2021-10-05 11:36:21 -07:00
Patrick Fic
cdb4da9e5f IO-1412 Resolve production list saving and loading. 2021-10-05 09:40:25 -07:00
Patrick Fic
b59a5303c6 IO-1430 add Last Contacted date to job. 2021-10-05 09:12:44 -07:00
Patrick Fic
9a72abbed0 IO-1426 Add time to date detail card. 2021-10-05 08:53:20 -07:00
Patrick Fic
762a5ff01b IO-1432 Add offset for speed print. 2021-10-05 08:49:38 -07:00
Patrick Fic
2f6571e703 Package updates. 2021-10-05 07:59:51 -07:00
Patrick Fic
80c90f1819 IO-1399 Parts Order Modal Updates 2021-10-04 16:13:33 -07:00
Patrick Fic
4b0c2c60a2 IO-1398 Parts Order Mark Duplication 2021-10-04 16:00:05 -07:00
Patrick Fic
ee7d7d2f6a IO-1397 Preview cards consistency updates. 2021-10-04 15:55:43 -07:00
Patrick Fic
0ad670013b IO-1395 Add missing info to job preview. 2021-10-04 15:48:28 -07:00
Patrick Fic
064a66aa66 IO-1329 Filtering on bill line posting 2021-10-04 14:37:37 -07:00
Patrick Fic
f46c19b152 Merged in release/2021-10-08 (pull request #239)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-04 20:35:21 +00:00
Patrick Fic
ea2c583b26 IO-1419 Resolve hsaura migration issues with new field. 2021-10-04 13:20:35 -07:00
Patrick Fic
7bd2a90141 Merged in release/2021-10-08 (pull request #238)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-04 19:11:34 +00:00
Patrick Fic
632549dd9d IO-1406 Parts Order label update 2021-10-04 12:08:47 -07:00
Patrick Fic
70ef274821 IO-1404 IO-1403 Remove negative value options for 2021-10-04 12:08:29 -07:00
Patrick Fic
7d9759fda4 IO-1419 Added comments to parts orders. 2021-10-04 11:59:33 -07:00
Patrick Fic
0fd06d5e4e IO-1421 Add day of week to smart scheduling buttons. 2021-10-04 11:48:55 -07:00
Patrick Fic
4995e44e06 IO-1424 Add other referral source 2021-10-04 11:43:33 -07:00
Patrick Fic
96f292f61c JSR CHange 2021-10-04 07:57:14 -07:00
Patrick Fic
c62f5e3911 Merged in release/2021-10-08 (pull request #235)
Resolve CI.

Approved-by: Patrick Fic
2021-10-01 22:56:48 +00:00
Patrick Fic
9f1d184081 Resolve CI. 2021-10-01 15:56:24 -07:00
Patrick Fic
29e596eedb Merged in release/2021-10-08 (pull request #234)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-01 22:41:36 +00:00
Patrick Fic
6e28afda67 IO-1417 Resolve custom templates printing. 2021-10-01 15:41:17 -07:00
Patrick Fic
eca7e9fba1 Merged in release/2021-10-08 (pull request #233)
IO-1392 Add IOU Form to Print Center

Approved-by: Patrick Fic
2021-10-01 16:25:04 +00:00
Patrick Fic
aa2ac2b296 IO-1392 Add IOU Form to Print Center 2021-10-01 09:24:37 -07:00
Patrick Fic
ce57752b95 Merged in release/2021-10-08 (pull request #232)
release/2021-10-08

Approved-by: Patrick Fic
2021-10-01 00:49:16 +00:00
Patrick Fic
63163c6459 IO1387 Add tax part override for non-R&R lines & Package Updates 2021-09-30 17:48:31 -07:00
Patrick Fic
2712ee5c0b IO-1416 Add missing LAA to resp center setup. 2021-09-30 09:44:15 -07:00
Patrick Fic
4179943df6 Merged in release/2021-10-01 (pull request #230)
Release/2021 10 01
2021-09-29 22:55:42 +00:00
Patrick Fic
d38dd67c2f Merged in release/2021-10-01 (pull request #229)
release/2021-10-01

Approved-by: Patrick Fic
2021-09-29 15:50:34 +00:00
Patrick Fic
0eacf9a840 Merged in release/2021-10-01 (pull request #228)
release/2021-10-01

Approved-by: Patrick Fic
2021-09-28 20:19:33 +00:00
Patrick Fic
a7c9dde5e3 Merged in release/2021-10-01 (pull request #227)
release/2021-10-01

Approved-by: Patrick Fic
2021-09-27 23:52:21 +00:00
115 changed files with 5040 additions and 928 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project version="1.2" be_version="2.7.1">
<babeledit_project be_version="2.7.1" version="1.2">
<!--
BabelEdit project file
@@ -6134,6 +6134,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>laa</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>lab</name>
<definition_loaded>false</definition_loaded>
@@ -16857,6 +16878,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>prt_dsmk_m</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>prt_dsmk_p</name>
<definition_loaded>false</definition_loaded>
@@ -16899,6 +16941,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>tax_part</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>total</name>
<definition_loaded>false</definition_loaded>
@@ -19548,6 +19611,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>date_last_contacted</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>
@@ -21348,6 +21432,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>ownr_ph2</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>paa</name>
<definition_loaded>false</definition_loaded>
@@ -22282,6 +22387,48 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>referral_source_extra</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>referral_source_other</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>referralsource</name>
<definition_loaded>false</definition_loaded>
@@ -25834,6 +25981,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>savebeforeconversion</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>scheduledinchange</name>
<definition_loaded>false</definition_loaded>
@@ -29289,6 +29457,32 @@
</concept_node>
</children>
</folder_node>
<folder_node>
<name>errors</name>
<children>
<concept_node>
<name>inserting</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>
<name>fields</name>
<children>
@@ -29423,6 +29617,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>notetoadd</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>
@@ -29826,6 +30041,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>ownr_ph2</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>ownr_st</name>
<definition_loaded>false</definition_loaded>
@@ -30354,6 +30590,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>comments</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>cost</name>
<definition_loaded>false</definition_loaded>
@@ -32869,6 +33126,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>iou_form</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>job_costing_ro</name>
<definition_loaded>false</definition_loaded>

View File

@@ -4,37 +4,37 @@
"private": true,
"proxy": "http://localhost:5000",
"dependencies": {
"@apollo/client": "^3.4.14",
"@apollo/client": "^3.4.16",
"@craco/craco": "^6.3.0",
"@fingerprintjs/fingerprintjs": "^3.3.0",
"@lourenci/react-kanban": "^2.1.0",
"@openreplay/tracker": "^3.4.0",
"@openreplay/tracker-assist": "^3.4.0",
"@openreplay/tracker": "^3.4.4",
"@openreplay/tracker-assist": "^3.4.3",
"@openreplay/tracker-graphql": "^3.0.0",
"@openreplay/tracker-redux": "^3.0.0",
"@sentry/react": "^6.13.2",
"@sentry/tracing": "^6.13.2",
"@stripe/react-stripe-js": "^1.5.0",
"@stripe/stripe-js": "^1.18.0",
"@tanem/react-nprogress": "^3.0.79",
"@sentry/react": "^6.13.3",
"@sentry/tracing": "^6.13.3",
"@stripe/react-stripe-js": "^1.6.0",
"@stripe/stripe-js": "^1.19.1",
"@tanem/react-nprogress": "^3.0.80",
"antd": "^4.16.13",
"apollo-link-logger": "^2.0.0",
"axios": "^0.21.4",
"axios": "^0.23.0",
"craco-less": "^1.20.0",
"dinero.js": "^1.9.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.0",
"graphql": "^15.6.0",
"i18next": "^21.1.1",
"firebase": "^9.1.2",
"graphql": "^15.6.1",
"i18next": "^21.3.0",
"i18next-browser-languagedetector": "^6.1.2",
"jsoneditor": "^9.5.6",
"jsreport-browser-client-dist": "^1.3.0",
"libphonenumber-js": "^1.9.34",
"logrocket": "^2.0.0",
"markerjs2": "^2.12.0",
"libphonenumber-js": "^1.9.37",
"logrocket": "^2.1.0",
"markerjs2": "^2.14.0",
"moment-business-days": "^1.2.0",
"phone": "^3.1.8",
"preval.macro": "^5.0.0",
@@ -43,7 +43,7 @@
"rc-queue-anim": "^2.0.0",
"rc-scroll-anim": "^2.7.6",
"react": "^17.0.1",
"react-big-calendar": "^0.35.0",
"react-big-calendar": "^0.36.1",
"react-color": "^2.19.3",
"react-cookie": "^4.1.1",
"react-dom": "^17.0.1",
@@ -51,7 +51,7 @@
"react-grid-gallery": "^0.5.5",
"react-grid-layout": "^1.3.0",
"react-i18next": "^11.12.0",
"react-icons": "^4.2.0",
"react-icons": "^4.3.1",
"react-number-format": "^4.7.3",
"react-redux": "^7.2.5",
"react-resizable": "^3.0.4",
@@ -69,7 +69,7 @@
"socket.io-client": "^4.2.0",
"styled-components": "^5.3.1",
"subscriptions-transport-ws": "^0.9.18",
"web-vitals": "^2.1.0",
"web-vitals": "^2.1.2",
"workbox-background-sync": "^6.3.0",
"workbox-broadcast-update": "^6.3.0",
"workbox-cacheable-response": "^6.3.0",
@@ -114,7 +114,7 @@
]
},
"devDependencies": {
"@sentry/webpack-plugin": "^1.17.1",
"@sentry/webpack-plugin": "^1.18.0",
"patch-package": "^6.4.7",
"redux-logger": "^3.0.6",
"source-map-explorer": "^2.5.2"

View File

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

View File

@@ -124,3 +124,7 @@
z-index: 2 !important;
}
}
.react-kanban-column {
background-color: #ddd !important;
}

View File

@@ -8,8 +8,26 @@ import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
import { alphaSort, dateSort } from "../../utils/sorters";
import PaymentExportButton from "../payment-export-button/payment-export-button.component";
import PaymentsExportAllButton from "../payments-export-all-button/payments-export-all-button.component";
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
export default function AccountingPayablesTableComponent({
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(AccountingPayablesTableComponent);
export function AccountingPayablesTableComponent({
bodyshop,
loading,
payments,
}) {
@@ -163,6 +181,9 @@ export default function AccountingPayablesTableComponent({
loadingCallback={setTransInProgress}
completedCallback={setSelectedPayments}
/>
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
<QboAuthorizeComponent />
)}
<Input
value={state.search}
onChange={handleSearch}

View File

@@ -12,7 +12,18 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => {
disabled={disabled}
ref={ref}
showSearch
optionFilterProp="line_desc"
// optionFilterProp="line_desc"
filterOption={(inputValue, option) => {
console.log(inputValue);
return (
(option.line_desc &&
option.line_desc
.toLowerCase()
.includes(inputValue.toLowerCase())) ||
(option.oem_partno &&
option.oem_partno.toLowerCase().includes(inputValue.toLowerCase()))
);
}}
notFoundContent={"Removed."}
{...restProps}
>
@@ -29,6 +40,7 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => {
part_type={item.part_type}
line_desc={item.line_desc}
part_qty={item.part_qty}
oem_partno={item.oem_partno}
style={{
...(item.removed ? { textDecoration: "line-through" } : {}),
}}

View File

@@ -259,7 +259,6 @@ export function DmsPostForm({ bodyshop, socket, job }) {
))}
<Form.Item>
<Button
type="dashed"
disabled={!(fields.length < 3)}
onClick={() => {
if (fields.length < 3) add();

View File

@@ -62,13 +62,16 @@ export default function GlobalSearch() {
}`,
label: (
<Link to={`/manage/owners/${owner.id}`}>
<Space size="small" split={<Divider type="vertical" />}>
<Space size="small" split={<Divider type="vertical" />} wrap>
<span>{`${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${
owner.ownr_co_nm || ""
}`}</span>
<PhoneNumberFormatter>
{owner.ownr_ph1}
</PhoneNumberFormatter>
<PhoneNumberFormatter>
{owner.ownr_ph2}
</PhoneNumberFormatter>
</Space>
</Link>
),

View File

@@ -106,6 +106,12 @@ export function ScheduleEventComponent({
jobid={event.job.id}
/>
</DataLabel>
<DataLabel label={t("jobs.fields.ownr_ph2")}>
<ChatOpenButton
phone={event.job && event.job.ownr_ph2}
jobid={event.job.id}
/>
</DataLabel>
<DataLabel label={t("jobs.fields.alt_transport")}>
{(event.job && event.job.alt_transport) || ""}
<ScheduleAtChange job={event && event.job} />

View File

@@ -167,7 +167,11 @@ export function JobChecklistForm({
title={t("checklist.labels.checklist")}
extra={
!readOnly && (
<Button loading={loading} onClick={() => form.submit()}>
<Button
loading={loading}
type="primary"
onClick={() => form.submit()}
>
{t("general.actions.submit")}
</Button>
)
@@ -182,12 +186,14 @@ export function JobChecklistForm({
allow_text_message: job.owner && job.owner.allow_text_message,
scheduled_completion:
(job && job.scheduled_completion) ||
moment().businessAdd(
(job.labhrs.aggregate.sum.mod_lb_hrs +
job.larhrs.aggregate.sum.mod_lb_hrs) /
bodyshop.target_touchtime,
"days"
),
(job.labbrs && job.larhrs
? moment().businessAdd(
(job.labhrs.aggregate.sum.mod_lb_hrs +
job.larhrs.aggregate.sum.mod_lb_hrs) /
bodyshop.target_touchtime,
"days"
)
: null),
scheduled_delivery: job && job.scheduled_delivery,
}),
...(type === "deliver" && {

View File

@@ -112,60 +112,46 @@ export function JobDetailCards({ setPrintCenterContext }) {
<Divider type="horizontal" />
<Row gutter={[16, 16]}>
<Col {...span}>
<Card.Grid style={{ width: "100%", height: "100%" }}>
<JobDetailCardsInsuranceComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Card.Grid>
<JobDetailCardsInsuranceComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Col>
<Col {...span}>
<Card.Grid style={{ width: "100%", height: "100%" }}>
<JobDetailCardsTotalsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Card.Grid>
<JobDetailCardsTotalsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Col>
<Col {...span}>
<Card.Grid style={{ width: "100%", height: "100%" }}>
<JobDetailCardsDatesComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Card.Grid>
<JobDetailCardsDatesComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Col>
<Col {...span}>
<Card.Grid style={{ width: "100%", height: "100%" }}>
<JobDetailCardsPartsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Card.Grid>
<JobDetailCardsPartsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Col>
<Col {...span}>
<Card.Grid style={{ width: "100%", height: "100%" }}>
<JobDetailCardsNotesComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Card.Grid>
<JobDetailCardsNotesComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Col>
<Col {...span}>
<Card.Grid style={{ width: "100%", height: "100%" }}>
<JobDetailCardsDocumentsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Card.Grid>
<JobDetailCardsDocumentsComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Col>
<Col {...span}>
<Card.Grid style={{ width: "100%", height: "100%" }}>
<JobDetailCardsDamageComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Card.Grid>
<JobDetailCardsDamageComponent
loading={loading}
data={data ? data.jobs_by_pk : null}
/>
</Col>
</Row>
</Card>

View File

@@ -1,7 +1,7 @@
import { Timeline } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { DateFormatter } from "../../utils/DateFormatter";
import { DateTimeFormatter } from "../../utils/DateFormatter";
import CardTemplate from "./job-detail-cards.template.component";
export default function JobDetailCardsDatesComponent({ loading, data }) {
@@ -26,80 +26,86 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
) ? (
<div>{t("jobs.errors.nodates")}</div>
) : null}
{data.date_last_contacted ? (
<Timeline.Item>
<label>{t("jobs.fields.date_last_contacted")}: </label>
<DateTimeFormatter>{data.date_last_contacted}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.date_open ? (
<Timeline.Item>
<label>{t("jobs.fields.date_open")}: </label>
<DateFormatter>{data.date_open}</DateFormatter>
<DateTimeFormatter>{data.date_open}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.date_estimated ? (
<Timeline.Item>
<label>{t("jobs.fields.date_estimated")}: </label>
<DateFormatter>{data.date_estimated}</DateFormatter>
<DateTimeFormatter>{data.date_estimated}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.date_scheduled ? (
<Timeline.Item>
<label>{t("jobs.fields.date_scheduled")}: </label>
<DateFormatter>{data.date_scheduled}</DateFormatter>
<DateTimeFormatter>{data.date_scheduled}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.scheduled_in ? (
<Timeline.Item>
<label>{t("jobs.fields.scheduled_in")}: </label>
<DateFormatter>{data.scheduled_in}</DateFormatter>
<DateTimeFormatter>{data.scheduled_in}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.actual_in ? (
<Timeline.Item>
<label>{t("jobs.fields.actual_in")}: </label>
<DateFormatter>{data.actual_in}</DateFormatter>
<DateTimeFormatter>{data.actual_in}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.scheduled_completion ? (
<Timeline.Item>
<label>{t("jobs.fields.scheduled_completion")}: </label>
<DateFormatter>{data.scheduled_completion}</DateFormatter>
<DateTimeFormatter>{data.scheduled_completion}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.actual_completion ? (
<Timeline.Item>
<label>{t("jobs.fields.actual_completion")}: </label>
<DateFormatter>{data.actual_completion}</DateFormatter>
<DateTimeFormatter>{data.actual_completion}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.scheduled_delivery ? (
<Timeline.Item>
<label>{t("jobs.fields.scheduled_delivery")}: </label>
<DateFormatter>{data.scheduled_delivery}</DateFormatter>
<DateTimeFormatter>{data.scheduled_delivery}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.actual_delivery ? (
<Timeline.Item>
<label>{t("jobs.fields.actual_delivery")}: </label>
<DateFormatter>{data.actual_delivery}</DateFormatter>
<DateTimeFormatter>{data.actual_delivery}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.date_invoiced ? (
<Timeline.Item>
<label>{t("jobs.fields.date_invoiced")}: </label>
<DateFormatter>{data.date_invoiced}</DateFormatter>
<DateTimeFormatter>{data.date_invoiced}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.date_exported ? (
<Timeline.Item>
<label>{t("jobs.fields.date_exported")}: </label>
<DateFormatter>{data.date_exported}</DateFormatter>
<DateTimeFormatter>{data.date_exported}</DateTimeFormatter>
</Timeline.Item>
) : null}
</Timeline>

View File

@@ -1,8 +1,8 @@
import { Carousel } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { GenerateThumbUrl } from "../jobs-documents-gallery/job-documents.utility";
import CardTemplate from "./job-detail-cards.template.component";
import { DetermineFileType } from "../documents-upload/documents-upload.utility";
export default function JobDetailCardsDocumentsComponent({ loading, data }) {
const { t } = useTranslation();
@@ -22,15 +22,7 @@ export default function JobDetailCardsDocumentsComponent({ loading, data }) {
{data.documents.length > 0 ? (
<Carousel autoplay>
{data.documents.map((item) => (
<img
key={item.id}
src={`${
process.env.REACT_APP_CLOUDINARY_ENDPOINT
}/${DetermineFileType(item.type)}/upload/${
process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS
}/${item.key}`}
alt={item.name}
/>
<img key={item.id} src={GenerateThumbUrl(item)} alt={item.name} />
))}
</Carousel>
) : (

View File

@@ -12,11 +12,13 @@ export default function JobDetailCardTemplate({
if (extraLink) extra = { extra: <Link to={extraLink}>More</Link> };
return (
<Card
size='small'
className='job-card'
size="small"
className="job-card"
title={title}
loading={loading}
{...extra}>
style={{ height: "100%" }}
{...extra}
>
{otherProps.children}
</Card>
);

View File

@@ -36,6 +36,7 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re
// import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
// import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
import _ from "lodash";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -161,7 +162,11 @@ export function JobLinesComponent({
ellipsis: true,
render: (text, record) => (
<>
<CurrencyFormatter>{record.act_price}</CurrencyFormatter>
<CurrencyFormatter>
{record.db_ref === "900510" || record.db_ref === "900511"
? record.prt_dsmk_m
: record.act_price}
</CurrencyFormatter>
{record.prt_dsmk_p && record.prt_dsmk_p !== 0 ? (
<span
style={{ marginLeft: ".2rem" }}
@@ -295,18 +300,17 @@ export function JobLinesComponent({
onClick={async () => {
await deleteJobLine({
variables: { joblineId: record.id },
// update(cache) {
// cache.modify({
// id: cache.identify(job),
// fields: {
// joblines(existingJobLines, { readField }) {
// return existingJobLines.filter(
// (jlRef) => record.id !== readField("id", jlRef)
// );
// },
// },
// });
// },
update(cache) {
cache.modify({
fields: {
joblines(existingJobLines, { readField }) {
return existingJobLines.filter(
(jlRef) => record.id !== readField("id", jlRef)
);
},
},
});
},
});
await axios.post("/job/totalsssu", {
id: job.id,
@@ -334,10 +338,12 @@ export function JobLinesComponent({
const markedTypes = [e.key];
if (e.key === "PAN") markedTypes.push("PAP");
if (e.key === "PAS") markedTypes.push("PASL");
setSelectedLines([
...selectedLines,
...jobLines.filter((item) => markedTypes.includes(item.part_type)),
]);
setSelectedLines(
_.uniq([
...selectedLines,
...jobLines.filter((item) => markedTypes.includes(item.part_type)),
])
);
}
};

View File

@@ -1,4 +1,4 @@
import { Form, Input, InputNumber, Modal, Select } from "antd";
import { Form, Input, InputNumber, Modal, Select, Switch } from "antd";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import InputCurrency from "../form-items-formatted/currency-form-item.component";
@@ -184,9 +184,9 @@ export default function JobLinesUpsertModalComponent({
>
<InputNumber precision={0} min={0} />
</Form.Item>
<Form.Item label={t("joblines.fields.db_price")} name="db_price">
{/* <Form.Item label={t("joblines.fields.db_price")} name="db_price">
<InputCurrency precision={2} min={0} />
</Form.Item>
</Form.Item> */}
<Form.Item
label={t("joblines.fields.act_price")}
name="act_price"
@@ -222,6 +222,14 @@ export default function JobLinesUpsertModalComponent({
>
<InputNumber precision={0} min={0} max={100} />
</Form.Item>
<Form.Item
label={t("joblines.fields.tax_part")}
name="tax_part"
valuePropName="checked"
initialValue={true}
>
<Switch />
</Form.Item>
</LayoutFormRow>
</Form>
</Modal>

View File

@@ -44,6 +44,7 @@ function JobLinesUpsertModalContainer({
},
],
},
refetchQueries: ["GET_LINE_TICKET_BY_PK"],
});
if (!r.errors) {
await Axios.post("/job/totalsssu", {
@@ -69,6 +70,7 @@ function JobLinesUpsertModalContainer({
lineId: jobLineEditModal.context.id,
line: values,
},
refetchQueries: ["GET_LINE_TICKET_BY_PK"],
});
if (!r.errors) {
notification["success"]({

View File

@@ -108,6 +108,9 @@ export default function JobReconciliationBillsTable({
rowSelection={{
onChange: handleOnRowClick,
selectedRowKeys: selectedLines,
getCheckboxProps: (record) => {
return { disabled: record.deductedfromlbr };
},
}}
/>
</div>

View File

@@ -11,7 +11,7 @@ export const reconcileByAssocLine = (
const [selectedJobLines, setSelectedJobLines] = jobLineState;
const allJoblinesFromBills = billLines
.filter((bl) => bl.joblineid && !(bl.jobline && bl.jobline.removed))
.filter((bl) => bl.joblineid && bl.jobline && !bl.jobline.removed)
.map((bl) => bl.joblineid);
const duplicatedJobLinesbyInvoiceId = _.filter(

View File

@@ -74,7 +74,12 @@ export default function JobsAdminDatesChange({ job }) {
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
<DateTimePicker />
</Form.Item>
<Form.Item
label={t("jobs.fields.date_last_contacted")}
name="date_last_contacted"
>
<DateTimePicker />
</Form.Item>
<Form.Item
label={t("jobs.fields.scheduled_completion")}
name="scheduled_completion"

View File

@@ -100,7 +100,7 @@ export function JobsAvailableContainer({
}
//IO-539 Check for Parts Rate on PAL for SGI use case.
await CheckTaxRates(estData.est_data, bodyshop);
console.log(estData);
const newTotals = (
await Axios.post("/job/totals", {
job: {
@@ -395,10 +395,6 @@ function replaceEmpty(someObj, replaceValue = null) {
}
async function CheckTaxRates(estData, bodyshop) {
console.log(
"🚀 ~ file: jobs-available-table.container.jsx ~ line 398 ~ estData",
estData
);
//LKQ Check
if (
!estData.parts_tax_rates?.PAL ||
@@ -491,4 +487,23 @@ async function CheckTaxRates(estData, bodyshop) {
estData.parts_tax_rates.PAR.prt_tax_in = true;
}
}
//IO-1387 If a sublet line is NOT R&R, use the labor tax. If it is, use the sublet tax rate.
//Currently limited to SK shops only.
//if (bodyshop.region_config === "CA_SK") {
estData.joblines.data.forEach((jl, index) => {
if (
(jl.part_type === "PASL" || jl.part_type === "PAS") &&
jl.lbr_op !== "OP11"
) {
estData.joblines.data[index].tax_part = jl.lbr_tax;
}
//Set markup lines and tax lines as taxable.
//900510 is a mark up. 900510 is a discount.
if (jl.db_ref === "900510") {
estData.joblines.data[index].tax_part = true;
}
});
//}
}

View File

@@ -14,6 +14,7 @@ import {
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { useHistory } from "react-router-dom";
import { useCookies } from "react-cookie";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -32,6 +33,7 @@ export function JobsCloseExportButton({
const [updateJob] = useMutation(UPDATE_JOB);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [loading, setLoading] = useState(false);
const [cookies] = useCookies();
const handleQbxml = async () => {
//Check if it's a CDK setup.
@@ -45,10 +47,13 @@ export function JobsCloseExportButton({
//Check if it's a QBO Setup.
let PartnerResponse;
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/receivables`, {
withCredentials: true,
jobIds: [jobId],
});
PartnerResponse = await axios.post(
`/qbo/receivables`,
{
jobIds: [jobId],
},
{ withCredentials: true }
);
} else {
//Default is QBD
@@ -177,7 +182,16 @@ export function JobsCloseExportButton({
};
return (
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
<Button
onClick={handleQbxml}
loading={loading}
disabled={
disabled ||
(bodyshop.accountingconfig &&
bodyshop.accountingconfig.qbo &&
!cookies.qbo_realmId)
}
>
{t("jobs.actions.export")}
</Button>
);

View File

@@ -31,6 +31,7 @@ export function JobsCloseLines({ bodyshop, job, jobRO }) {
<th>{t("joblines.fields.line_desc")}</th>
<th>{t("joblines.fields.part_type")}</th>
<th>{t("joblines.fields.act_price")}</th>
<th>{t("joblines.fields.prt_dsmk_m")}</th>
<th>{t("joblines.fields.op_code_desc")}</th>
<th>{t("joblines.fields.mod_lbr_ty")}</th>
<th>{t("joblines.fields.mod_lb_hrs")}</th>
@@ -70,6 +71,16 @@ export function JobsCloseLines({ bodyshop, job, jobRO }) {
<ReadOnlyFormItem type="currency" />
</Form.Item>
</td>
<td>
<Form.Item
span={2}
// label={t("joblines.fields.prt_dsmk_m")}
key={`${index}prt_dsmk_m`}
name={[field.name, "prt_dsmk_m"]}
>
<ReadOnlyFormItem type="currency" />
</Form.Item>
</td>
<td>
<Form.Item
span={2}
@@ -108,7 +119,9 @@ export function JobsCloseLines({ bodyshop, job, jobRO }) {
labelCol={{ span: 0 }}
rules={[
{
required: !!job.joblines[index].act_price,
required:
!!job.joblines[index].act_price ||
!!job.joblines[index].prt_dsmk_m,
//message: t("general.validation.required"),
},
]}

View File

@@ -2,6 +2,7 @@ import { useMutation } from "@apollo/client";
import {
Button,
Form,
Input,
notification,
Popover,
Select,
@@ -34,6 +35,7 @@ export function JobsConvertButton({
refetch,
jobRO,
insertAuditTrail,
parentFormIsFieldsTouched,
}) {
const [visible, setVisible] = useState(false);
const [loading, setLoading] = useState(false);
@@ -42,6 +44,10 @@ export function JobsConvertButton({
const [form] = Form.useForm();
const handleConvert = async (values) => {
if (parentFormIsFieldsTouched()) {
alert(t("jobs.labels.savebeforeconversion"));
return;
}
setLoading(true);
const res = await mutationConvertJob({
variables: { jobId: job.id, ...values },
@@ -112,24 +118,32 @@ export function JobsConvertButton({
</Form.Item>
)}
{bodyshop.enforce_referral && (
<Form.Item
name={"referral_source"}
label={t("jobs.fields.referralsource")}
rules={[
{
required: bodyshop.enforce_referral,
//message: t("general.validation.required"),
},
]}
>
<Select>
{bodyshop.md_referral_sources.map((s) => (
<Select.Option key={s} value={s}>
{s}
</Select.Option>
))}
</Select>
</Form.Item>
<>
<Form.Item
name={"referral_source"}
label={t("jobs.fields.referralsource")}
rules={[
{
required: bodyshop.enforce_referral,
//message: t("general.validation.required"),
},
]}
>
<Select>
{bodyshop.md_referral_sources.map((s) => (
<Select.Option key={s} value={s}>
{s}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("jobs.fields.referral_source_extra")}
name="referral_source_extra"
>
<Input />
</Form.Item>
</>
)}
<Form.Item
label={t("jobs.fields.ca_gst_registrant")}

View File

@@ -181,6 +181,12 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
))}
</Select>
</Form.Item>
<Form.Item
label={t("jobs.fields.referral_source_extra")}
name="referral_source_extra"
>
<Input />
</Form.Item>
</LayoutFormRow>
</Collapse.Panel>
<Collapse.Panel
@@ -191,7 +197,7 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
<JobsMarkPstExempt form={form} />
<LayoutFormRow>
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item label={t("jobs.fields.ded_status")} name="ded_status">
<Select>

View File

@@ -129,6 +129,19 @@ export default function JobsCreateOwnerInfoNewComponent() {
>
<FormItemPhone disabled={!state.owner.new} />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_ph2")}
name={["owner", "data", "ownr_ph2"]}
rules={[
({ getFieldValue }) =>
PhoneItemFormatterValidation(
getFieldValue,
"owner.data.ownr_ph2"
),
]}
>
<FormItemPhone disabled={!state.owner.new} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow grow>
<Form.Item

View File

@@ -84,6 +84,18 @@ export default function JobsCreateOwnerInfoSearchComponent({
tableState.sortedInfo.columnKey === "ownr_ph1" &&
tableState.sortedInfo.order,
},
{
title: t("owners.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
render: (text, record) => (
<PhoneFormatter>{record.ownr_ph2}</PhoneFormatter>
),
sorter: (a, b) => alphaSort(a.ownr_ph2, b.ownr_ph2),
sortOrder:
tableState.sortedInfo.columnKey === "ownr_ph2" &&
tableState.sortedInfo.order,
},
];
const handleTableChange = (pagination, filters, sorter) => {

View File

@@ -69,6 +69,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
</Tooltip>
</FormRow>
<FormRow header={t("jobs.forms.repairdates")}>
<Form.Item
label={t("jobs.fields.date_last_contacted")}
name="date_last_contacted"
>
<DateTimePicker />
</Form.Item>
<Form.Item
label={t("jobs.fields.scheduled_completion")}
name="scheduled_completion"
@@ -93,7 +99,6 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
);
}}
</Form.Item>
<Form.Item
label={t("jobs.fields.scheduled_delivery")}
name="scheduled_delivery"

View File

@@ -44,7 +44,7 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
<CurrencyInput disabled={jobRO} />
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no">
<Input disabled={jobRO} />
@@ -114,6 +114,12 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
))}
</Select>
</Form.Item>
<Form.Item
label={t("jobs.fields.referral_source_extra")}
name="referral_source_extra"
>
<Input />
</Form.Item>
<Form.Item label={t("jobs.fields.alt_transport")} name="alt_transport">
<Select disabled={jobRO} allowClear>
{bodyshop.appt_alt_transport.map((s) => (

View File

@@ -21,47 +21,61 @@ export function JobsDetailHeaderActionexportCustomerData({
const handleExportCustData = async (e) => {
logImEXEvent("job_export_cust_data");
let QbXmlResponse;
try {
QbXmlResponse = await axios.post(
"/accounting/qbxml/receivables",
{ jobIds: [job.id], custDataOnly: true },
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
message: t("jobs.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
}),
});
return;
}
let PartnerResponse;
try {
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(
"http://localhost:1337/qb/",
QbXmlResponse.data,
`/qbo/receivables`,
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
},
}
jobIds: [job.id],
custDataOnly: true,
},
{ withCredentials: true }
);
} catch (error) {
console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({
message: t("jobs.errors.exporting-partner"),
});
} else {
//Default is QBD
return;
let QbXmlResponse;
try {
QbXmlResponse = await axios.post(
"/accounting/qbxml/receivables",
{ jobIds: [job.id], custDataOnly: true },
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
message: t("jobs.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
}),
});
return;
}
//let PartnerResponse;
try {
PartnerResponse = await axios.post(
"http://localhost:1337/qb/",
QbXmlResponse.data,
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
},
}
);
} catch (error) {
console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({
message: t("jobs.errors.exporting-partner"),
});
return;
}
}
//Check to see if any of them failed. If they didn't don't execute the update.
const failedTransactions = PartnerResponse.data.filter((r) => !r.success);

View File

@@ -141,6 +141,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
<DataLabel key="2" label={t("jobs.fields.ownr_ph1")}>
<ChatOpenButton phone={job.ownr_ph1} jobid={job.id} />
</DataLabel>
<DataLabel key="22" label={t("jobs.fields.ownr_ph2")}>
<ChatOpenButton phone={job.ownr_ph2} jobid={job.id} />
</DataLabel>
<DataLabel key="3" label={t("owners.fields.address")}>
{`${job.ownr_addr1 || ""} ${job.ownr_addr2 || ""} ${
job.ownr_city || ""

View File

@@ -38,7 +38,7 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
label={t("jobs.fields.depreciation_taxes")}
name="depreciation_taxes"
>
<CurrencyInput disabled={jobRO} />
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Tooltip title={t("jobs.labels.ca_gst_all_if_null")}>
<Form.Item
@@ -47,6 +47,7 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
>
<CurrencyInput
disabled={jobRO}
min={0}
max={
Math.round(
(job.job_totals &&
@@ -61,19 +62,19 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
label={t("jobs.fields.other_amount_payable")}
name="other_amount_payable"
>
<CurrencyInput disabled={jobRO} />
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.towing_payable")}
name="towing_payable"
>
<CurrencyInput disabled={jobRO} />
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.storage_payable")}
name="storage_payable"
>
<CurrencyInput disabled={jobRO} />
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.adjustment_bottom_line")}
@@ -83,7 +84,7 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
</Form.Item>
<Space align="end">
<Form.Item label={t("jobs.fields.ca_bc_pvrt")} name="ca_bc_pvrt">
<CurrencyInput disabled={jobRO} />
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<CABCpvrtCalculator form={form} disabled={jobRO} />
</Space>
@@ -135,72 +136,72 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
{
// <Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
// <CurrencyInput disabled={jobRO} />
// <CurrencyInput min={0}disabled={jobRO} />
// </Form.Item>
// <Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
// <CurrencyInput disabled={jobRO} />
// <CurrencyInput min={0}disabled={jobRO} />
// </Form.Item>
}
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
<CurrencyInput disabled={jobRO} />
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
</FormRow>
<JobsDetailRatesParts form={form} />

View File

@@ -29,20 +29,6 @@ function JobsDocumentsComponent({
setIndex(index);
};
// useEffect(() => {
// console.log("Added event listening for reteching.");
// window.addEventListener("storage", (ev) => {
// if (ev.key === "refetch" && ev.newValue === true) {
// refetch && refetch();
// localStorage.setItem("refetch", false);
// }
// });
// return () => {
// window.removeEventListener("storage");
// };
// }, [refetch]);
useEffect(() => {
let documents = data.reduce(
(acc, value) => {

View File

@@ -13,6 +13,7 @@ import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { useCookies } from "react-cookie";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -30,6 +31,7 @@ export function JobsExportAllButton({
const { t } = useTranslation();
const [updateJob] = useMutation(UPDATE_JOBS);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [cookies] = useCookies();
const [loading, setLoading] = useState(false);
const handleQbxml = async () => {
@@ -37,10 +39,13 @@ export function JobsExportAllButton({
let PartnerResponse;
setLoading(true);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/receivables`, {
withCredentials: true,
jobIds: jobIds,
});
PartnerResponse = await axios.post(
`/qbo/receivables`,
{
jobIds: jobIds,
},
{ withCredentials: true }
);
} else {
let QbXmlResponse;
try {
@@ -173,8 +178,12 @@ export function JobsExportAllButton({
<Button
onClick={handleQbxml}
loading={loading}
disabled={disabled}
type="dashed"
disabled={
disabled ||
(bodyshop.accountingconfig &&
bodyshop.accountingconfig.qbo &&
!cookies.qbo_realmId)
}
>
{t("jobs.actions.export")}
</Button>

View File

@@ -69,6 +69,20 @@ export default function JobsFindModalComponent({
);
},
},
{
title: t("jobs.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
width: "12%",
ellipsis: true,
render: (text, record) => {
return record.ownr_ph2 ? (
<PhoneFormatter>{record.ownr_ph2}</PhoneFormatter>
) : (
t("general.labels.unknown")
);
},
},
{
title: t("jobs.fields.status"),
dataIndex: "status",

View File

@@ -73,6 +73,16 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
<StartChatButton phone={record.ownr_ph1} jobid={record.id} />
),
},
{
title: t("jobs.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
width: "12%",
ellipsis: true,
render: (text, record) => (
<StartChatButton phone={record.ownr_ph2} jobid={record.id} />
),
},
{
title: t("jobs.fields.status"),
dataIndex: "status",

View File

@@ -145,6 +145,16 @@ export function JobsList({ bodyshop }) {
<ChatOpenButton phone={record.ownr_ph1} jobid={record.id} />
),
},
{
title: t("jobs.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
ellipsis: true,
responsive: ["md"],
render: (text, record) => (
<ChatOpenButton phone={record.ownr_ph2} jobid={record.id} />
),
},
{
title: t("jobs.fields.status"),

View File

@@ -81,6 +81,16 @@ export default function OwnerDetailFormComponent({ form, loading }) {
>
<FormItemPhone />
</Form.Item>
<Form.Item
label={t("owners.fields.ownr_ph2")}
name="ownr_ph2"
rules={[
({ getFieldValue }) =>
PhoneItemFormatterValidation(getFieldValue, "ownr_ph2"),
]}
>
<FormItemPhone />
</Form.Item>
<Form.Item
label={t("owners.fields.preferred_contact")}
name="preferred_contact"

View File

@@ -51,6 +51,14 @@ export default function OwnerFindModalComponent({
<PhoneFormatter>{record.ownr_ph1}</PhoneFormatter>
),
},
{
title: t("owners.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
render: (text, record) => (
<PhoneFormatter>{record.ownr_ph2}</PhoneFormatter>
),
},
];
const handleOnRowClick = (record) => {
@@ -66,7 +74,6 @@ export default function OwnerFindModalComponent({
return (
<div>
<Table
title={() => t("owners.labels.existing_owners")}
pagination={{ position: "bottom" }}
columns={columns}
rowKey="id"

View File

@@ -1,6 +1,6 @@
import { Modal } from "antd";
import React from "react";
import { useQuery } from "@apollo/client";
import { useLazyQuery } from "@apollo/client";
import { Input, Modal } from "antd";
import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { QUERY_SEARCH_OWNER_BY_IDX } from "../../graphql/owners.queries";
import AlertComponent from "../alert/alert.component";
@@ -17,14 +17,27 @@ export default function OwnerFindModalContainer({
}) {
//use owner object to run query and find what possible owners there are.
const { t } = useTranslation();
const [searchText, setSearchText] = useState(null);
const ownersList = useQuery(QUERY_SEARCH_OWNER_BY_IDX, {
variables: {
search: owner ? `${owner.ownr_fn || ""} ${owner.ownr_ln || ""}` : null,
},
skip: !owner,
fetchPolicy: "network-only",
});
const [callSearchowners, ownersList] = useLazyQuery(
QUERY_SEARCH_OWNER_BY_IDX,
{
variables: {
search: searchText,
},
}
);
useEffect(() => {
if (modalProps.visible && owner) {
const s = `${owner.ownr_fn || ""} ${owner.ownr_ln || ""} ${
owner.ownr_co_nm || ""
}`;
setSearchText(s.trim());
callSearchowners({ variables: { search: s.trim() } });
}
}, [callSearchowners, modalProps.visible, owner]);
return (
<Modal
@@ -35,16 +48,25 @@ export default function OwnerFindModalContainer({
{loading ? <LoadingSpinner /> : null}
{error ? <AlertComponent message={error.message} type="error" /> : null}
{owner ? (
<OwnerFindModalComponent
selectedOwner={selectedOwner}
setSelectedOwner={setSelectedOwner}
ownersListLoading={ownersList.loading}
ownersList={
ownersList.data && ownersList.data.search_owners
? ownersList.data.search_owners
: null
}
/>
<>
<Input.Search
value={searchText}
onChange={(e) => setSearchText(e.target.value)}
onSearch={(val) =>
callSearchowners({ variables: { search: val.trim() } })
}
/>
<OwnerFindModalComponent
selectedOwner={selectedOwner}
setSelectedOwner={setSelectedOwner}
ownersListLoading={ownersList.loading}
ownersList={
ownersList.data && ownersList.data.search_owners
? ownersList.data.search_owners
: null
}
/>
</>
) : null}
</Modal>
);

View File

@@ -16,6 +16,9 @@ export default function OwnerTagPopoverComponent({ job }) {
<Descriptions.Item key="2" label={t("jobs.fields.ownr_ph1")}>
<PhoneFormatter>{job.ownr_ph1 || ""}</PhoneFormatter>
</Descriptions.Item>
<Descriptions.Item key="22" label={t("jobs.fields.ownr_ph2")}>
<PhoneFormatter>{job.ownr_ph2 || ""}</PhoneFormatter>
</Descriptions.Item>
<Descriptions.Item key="3" label={t("owners.fields.address")}>
{`${job.ownr_addr1 || ""} ${job.ownr_addr2 || ""} ${
job.ownr_city || ""
@@ -36,6 +39,12 @@ export default function OwnerTagPopoverComponent({ job }) {
<Descriptions.Item key="2" label={t("jobs.fields.ownr_ph1")}>
<PhoneFormatter>{job.owner.ownr_ph1 || ""}</PhoneFormatter>
</Descriptions.Item>
<Descriptions.Item key="22" label={t("jobs.fields.ownr_ph2")}>
<PhoneFormatter>{job.owner.ownr_ph2 || ""}</PhoneFormatter>
</Descriptions.Item>
<Descriptions.Item key="2" label={t("jobs.fields.ownr_ph2")}>
<PhoneFormatter>{job.owner.ownr_ph2 || ""}</PhoneFormatter>
</Descriptions.Item>
<Descriptions.Item key="3" label={t("owners.fields.address")}>
{`${job.owner.ownr_addr1 || ""} ${job.owner.ownr_addr2 || ""} ${
job.owner.ownr_city || ""

View File

@@ -47,6 +47,14 @@ export default function OwnersListComponent({
return <PhoneFormatter>{record.ownr_ph1}</PhoneFormatter>;
},
},
{
title: t("owners.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
render: (text, record) => {
return <PhoneFormatter>{record.ownr_ph2}</PhoneFormatter>;
},
},
{
title: t("owners.fields.ownr_ea"),
dataIndex: "ownr_ea",

View File

@@ -27,6 +27,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters";
import { TemplateList } from "../../utils/TemplateConstants";
import DataLabel from "../data-label/data-label.component";
import PartsOrderBackorderEta from "../parts-order-backorder-eta/parts-order-backorder-eta.component";
import PartsOrderLineBackorderButton from "../parts-order-line-backorder-button/parts-order-line-backorder-button.component";
import PartsReceiveModalContainer from "../parts-receive-modal/parts-receive-modal.container";
@@ -379,6 +380,9 @@ export function PartsOrderListTableComponent({
rowKey="id"
dataSource={record.parts_order_lines}
/>
<DataLabel label={t("parts_orders.fields.comments")}>
<div style={{ whiteSpace: "pre" }}>{record.comments}</div>
</DataLabel>
</div>
);
};

View File

@@ -73,7 +73,7 @@ export default function PartsOrderModalComponent({
<Form.Item required={false} key={field.key}>
<LayoutFormRow grow noDivider>
<Form.Item
span={8}
//span={8}
label={t("parts_orders.fields.line_desc")}
key={`${index}line_desc`}
name={[field.name, "line_desc"]}
@@ -132,19 +132,21 @@ export default function PartsOrderModalComponent({
</Form.Item>
)}
<div>
<DeleteFilled
style={{ margin: "1rem" }}
onClick={() => {
remove(field.name);
}}
/>
<Space wrap align="center">
<div>
<DeleteFilled
style={{ margin: "1rem" }}
onClick={() => {
remove(field.name);
}}
/>
</div>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
</div>
</Space>
</LayoutFormRow>
</Form.Item>
))}
@@ -152,6 +154,9 @@ export default function PartsOrderModalComponent({
);
}}
</Form.List>
<Form.Item name="comments" label={t("parts_orders.fields.comments")}>
<Input.TextArea rows={3} />
</Form.Item>
<Radio.Group
defaultValue={sendType}
onChange={(e) => setSendType(e.target.value)}

View File

@@ -260,7 +260,7 @@ export function PartsOrderModalContainer({
onCancel={() => toggleModalVisible()}
onOk={() => form.submit()}
destroyOnClose
width="50%"
width="75%"
forceRender
>
{error ? <AlertComponent message={error.message} type="error" /> : null}

View File

@@ -14,6 +14,7 @@ import {
import { logImEXEvent } from "../../firebase/firebase.utils";
import _ from "lodash";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { useCookies } from "react-cookie";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -32,6 +33,7 @@ export function PayableExportAll({
const [updateBill] = useMutation(UPDATE_BILLS);
const [loading, setLoading] = useState(false);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [cookies] = useCookies();
const handleQbxml = async () => {
logImEXEvent("accounting_payables_export_all");
@@ -40,10 +42,13 @@ export function PayableExportAll({
setLoading(true);
if (!!loadingCallback) loadingCallback(true);
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/receivables`, {
withCredentials: true,
bills: billids,
});
PartnerResponse = await axios.post(
`/qbo/receivables`,
{
bills: billids,
},
{ withCredentials: true }
);
} else {
let QbXmlResponse;
try {
@@ -172,8 +177,12 @@ export function PayableExportAll({
<Button
onClick={handleQbxml}
loading={loading}
disabled={disabled}
type="dashed"
disabled={
disabled ||
(bodyshop.accountingconfig &&
bodyshop.accountingconfig.qbo &&
!cookies.qbo_realmId)
}
>
{t("jobs.actions.exportselected")}
</Button>

View File

@@ -13,6 +13,7 @@ import {
} from "../../redux/user/user.selectors";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { useCookies } from "react-cookie";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -31,6 +32,7 @@ export function PayableExportButton({
const [updateBill] = useMutation(UPDATE_BILLS);
const [loading, setLoading] = useState(false);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [cookies] = useCookies();
const handleQbxml = async () => {
logImEXEvent("accounting_export_payable");
@@ -41,10 +43,13 @@ export function PayableExportButton({
//Check if it's a QBO Setup.
let PartnerResponse;
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(`/qbo/payables`, {
withCredentials: true,
bills: [billId],
});
PartnerResponse = await axios.post(
`/qbo/payables`,
{
bills: [billId],
},
{ withCredentials: true }
);
} else {
//Default is QBD
@@ -174,8 +179,12 @@ export function PayableExportButton({
<Button
onClick={handleQbxml}
loading={loading}
disabled={disabled}
type="dashed"
disabled={
disabled ||
(bodyshop.accountingconfig &&
bodyshop.accountingconfig.qbo &&
!cookies.qbo_realmId)
}
>
{t("jobs.actions.export")}
</Button>

View File

@@ -8,6 +8,8 @@ import { createStructuredSelector } from "reselect";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { UPDATE_PAYMENTS } from "../../graphql/payments.queries";
import { useCookies } from "react-cookie";
import {
selectBodyshop,
selectCurrentUser,
@@ -30,58 +32,71 @@ export function PaymentExportButton({
const [updatePayment] = useMutation(UPDATE_PAYMENTS);
const [loading, setLoading] = useState(false);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [cookies] = useCookies();
const handleQbxml = async () => {
logImEXEvent("accounting_payment_export");
setLoading(true);
if (!!loadingCallback) loadingCallback(true);
let QbXmlResponse;
try {
QbXmlResponse = await axios.post(
"/accounting/qbxml/payments",
{ payments: [paymentId] },
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
message: t("payments.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
}),
});
if (loadingCallback) loadingCallback(false);
setLoading(false);
return;
}
//Check if it's a QBO Setup.
let PartnerResponse;
try {
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(
"http://localhost:1337/qb/",
//"http://609feaeae986.ngrok.io/qb/",
QbXmlResponse.data
`/qbo/payments`,
{
payments: [paymentId],
},
{ withCredentials: true }
);
} catch (error) {
console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({
message: t("payments.errors.exporting-partner"),
});
if (!!loadingCallback) loadingCallback(false);
setLoading(false);
return;
} else {
//Default is QBD
if (!!loadingCallback) loadingCallback(true);
let QbXmlResponse;
try {
QbXmlResponse = await axios.post(
"/accounting/qbxml/payments",
{ payments: [paymentId] },
{
headers: {
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
},
}
);
console.log("handle -> XML", QbXmlResponse);
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
message: t("payments.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
}),
});
if (loadingCallback) loadingCallback(false);
setLoading(false);
return;
}
try {
PartnerResponse = await axios.post(
"http://localhost:1337/qb/",
QbXmlResponse.data
);
} catch (error) {
console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({
message: t("payments.errors.exporting-partner"),
});
if (!!loadingCallback) loadingCallback(false);
setLoading(false);
return;
}
}
console.log("handleQbxml -> PartnerResponse", PartnerResponse);
const failedTransactions = PartnerResponse.data.filter((r) => !r.success);
const successfulTransactions = PartnerResponse.data.filter(
(r) => r.success
);
if (failedTransactions.length > 0) {
//Uh oh. At least one was no good.
failedTransactions.map((ft) =>
@@ -123,7 +138,14 @@ export function PaymentExportButton({
const paymentUpdateResponse = await updatePayment({
variables: {
paymentIdList: [paymentId],
paymentIdList: successfulTransactions.map(
(st) =>
st[
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
? "paymentid"
: "id"
]
),
payment: {
exportedat: new Date(),
},
@@ -158,8 +180,12 @@ export function PaymentExportButton({
<Button
onClick={handleQbxml}
loading={loading}
disabled={disabled}
type="dashed"
disabled={
disabled ||
(bodyshop.accountingconfig &&
bodyshop.accountingconfig.qbo &&
!cookies.qbo_realmId)
}
>
{t("jobs.actions.export")}
</Button>

View File

@@ -8,6 +8,8 @@ import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
import { UPDATE_PAYMENTS } from "../../graphql/payments.queries";
import { useCookies } from "react-cookie";
import {
selectBodyshop,
selectCurrentUser,
@@ -29,46 +31,58 @@ export function PaymentsExportAllButton({
const [updatePayments] = useMutation(UPDATE_PAYMENTS);
const [loading, setLoading] = useState(false);
const [insertExportLog] = useMutation(INSERT_EXPORT_LOG);
const [cookies] = useCookies();
const handleQbxml = async () => {
setLoading(true);
if (!!loadingCallback) loadingCallback(true);
let QbXmlResponse;
try {
QbXmlResponse = await axios.post("/accounting/qbxml/payments", {
payments: paymentIds,
});
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
message: t("payments.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
}),
});
if (loadingCallback) loadingCallback(false);
setLoading(false);
return;
}
let PartnerResponse;
try {
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
PartnerResponse = await axios.post(
"http://localhost:1337/qb/",
QbXmlResponse.data
`/qbo/payments`,
{
payments: paymentIds,
},
{ withCredentials: true }
);
} catch (error) {
console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({
message: t("payments.errors.exporting-partner"),
});
if (!!loadingCallback) loadingCallback(false);
setLoading(false);
return;
} else {
let QbXmlResponse;
try {
QbXmlResponse = await axios.post("/accounting/qbxml/payments", {
payments: paymentIds,
});
} catch (error) {
console.log("Error getting QBXML from Server.", error);
notification["error"]({
message: t("payments.errors.exporting", {
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
}),
});
if (loadingCallback) loadingCallback(false);
setLoading(false);
return;
}
try {
PartnerResponse = await axios.post(
"http://localhost:1337/qb/",
QbXmlResponse.data
);
} catch (error) {
console.log("Error connecting to quickbooks or partner.", error);
notification["error"]({
message: t("payments.errors.exporting-partner"),
});
if (!!loadingCallback) loadingCallback(false);
setLoading(false);
return;
}
}
const groupedData = _.groupBy(PartnerResponse.data, "id");
const groupedData = _.groupBy(
PartnerResponse.data,
bodyshop.accountingconfig.qbo ? "paymentid" : "id"
);
const proms = [];
Object.keys(groupedData).forEach((key) => {
proms.push(
@@ -147,8 +161,12 @@ export function PaymentsExportAllButton({
<Button
onClick={handleQbxml}
loading={loading}
disabled={disabled}
type="dashed"
disabled={
disabled ||
(bodyshop.accountingconfig &&
bodyshop.accountingconfig.qbo &&
!cookies.qbo_realmId)
}
>
{t("jobs.actions.exportselected")}
</Button>

View File

@@ -38,6 +38,7 @@ export function ProductionBoardFilters({
}}
/>
<EmployeeSearchSelectComponent
style={{ minWidth: "20rem" }}
options={bodyshop.employees.filter((e) => e.active)}
value={filter.employeeId}
placeholder={t("production.labels.employeesearch")}

View File

@@ -6,9 +6,11 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
technician: selectTechnician,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
@@ -21,6 +23,7 @@ export default connect(
export function ProductionColumnsComponent({
columnState,
technician,
bodyshop,
tableState,
}) {
const [columns, setColumns] = columnState;
@@ -29,9 +32,11 @@ export function ProductionColumnsComponent({
const handleAdd = (e) => {
setColumns([
...columns,
...dataSource({ technician, state: tableState }).filter(
(i) => i.key === e.key
),
...dataSource({
technician,
state: tableState,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
}).filter((i) => i.key === e.key),
]);
};
@@ -39,7 +44,11 @@ export function ProductionColumnsComponent({
const menu = (
<Menu onClick={handleAdd}>
{dataSource({ technician, state: tableState })
{dataSource({
technician,
state: tableState,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
})
.filter((i) => !columnKeys.includes(i.key))
.map((item) => (
<Menu.Item key={item.key}>{item.title}</Menu.Item>

View File

@@ -3,7 +3,7 @@ import React from "react";
import { Link } from "react-router-dom";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import PhoneFormatter from "../../utils/PhoneFormatter";
import { alphaSort, dateSort } from "../../utils/sorters";
import { alphaSort, dateSort, statusSort } from "../../utils/sorters";
import JobAltTransportChange from "../job-at-change/job-at-change.component";
import ProductionSubletsManageComponent from "../production-sublets-manage/production-sublets-manage.component";
import ProductionListColumnAlert from "./production-list-columns.alert.component";
@@ -15,8 +15,9 @@ import ProductionListColumnPaintPriority from "./production-list-columns.paintpr
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 }) => {
const r = ({ technician, state, activeStatuses }) => {
return [
{
title: i18n.t("jobs.actions.viewdetail"),
@@ -97,6 +98,17 @@ const r = ({ technician, state }) => {
<ProductionListDate record={record} field="scheduled_completion" />
),
},
{
title: i18n.t("jobs.fields.date_last_contacted"),
dataIndex: "date_last_contacted",
key: "date_last_contacted",
ellipsis: true,
sorter: (a, b) => dateSort(a.date_last_contacted, b.date_last_contacted),
sortOrder:
state.sortedInfo.columnKey === "date_last_contacted" &&
state.sortedInfo.order,
render: (text, record) => <ProductionListLastContacted record={record} />,
},
{
title: i18n.t("jobs.fields.scheduled_delivery"),
dataIndex: "scheduled_delivery",
@@ -161,6 +173,15 @@ const r = ({ technician, state }) => {
<PhoneFormatter>{record.ownr_ph1}</PhoneFormatter>
),
},
{
title: i18n.t("jobs.fields.ownr_ph2"),
dataIndex: "ownr_ph2",
key: "ownr_ph2",
ellipsis: true,
render: (text, record) => (
<PhoneFormatter>{record.ownr_ph2}</PhoneFormatter>
),
},
{
title: i18n.t("jobs.fields.specialcoveragepolicy"),
dataIndex: "special_coverage_policy",
@@ -189,7 +210,7 @@ const r = ({ technician, state }) => {
dataIndex: "status",
key: "status",
ellipsis: true,
sorter: (a, b) => alphaSort(a.status, b.status),
sorter: (a, b) => statusSort(a.status, b.status, activeStatuses),
sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
render: (text, record) => <ProductionListColumnStatus record={record} />,

View File

@@ -1,17 +1,20 @@
import { useMutation } from "@apollo/client";
import { DatePicker, Dropdown } from "antd";
import { DatePicker, Dropdown, TimePicker, Button, Card } from "antd";
import moment from "moment";
import React from "react";
import React, { useState } from "react";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { DateFormatter } from "../../utils/DateFormatter";
import { useTranslation } from "react-i18next";
const OneCalendarDay = 60 * 60 * 24 * 1000;
const Now = new Date();
export default function ProductionListDate({ record, field }) {
export default function ProductionListDate({ record, field, time }) {
const [updateAlert] = useMutation(UPDATE_JOB);
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
const handleChange = (date) => {
logImEXEvent("product_toggle_date", { field });
@@ -25,27 +28,47 @@ export default function ProductionListDate({ record, field }) {
},
}).then(() => {
if (record.refetch) record.refetch();
if (!time) {
setVisible(false);
}
});
};
return (
<div>
<Dropdown
trigger={["click"]}
//trigger={["click"]}
visible={visible}
style={{
height: "19px",
}}
overlay={
<div onClick={(e) => e.stopPropagation()}>
<Card
style={{ padding: "1rem" }}
onClick={(e) => e.stopPropagation()}
>
<DatePicker
onClick={(e) => e.stopPropagation()}
value={(record[field] && moment(record[field])) || null}
onChange={handleChange}
format="MM/DD/YYYY"
/>
</div>
{time && (
<TimePicker
onClick={(e) => e.stopPropagation()}
value={(record[field] && moment(record[field])) || null}
onChange={handleChange}
format="hh:mm a"
/>
)}
<Button onClick={() => setVisible(false)}>
{t("general.actions.close")}
</Button>
</Card>
}
>
<div
onClick={() => setVisible(true)}
style={{
height: "19px",
}}

View File

@@ -0,0 +1,132 @@
import { useMutation } from "@apollo/client";
import { Button, Card, Dropdown, Form, Input, notification, Space } from "antd";
import moment from "moment";
import React, { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
import { selectCurrentUser } from "../../redux/user/user.selectors";
import { DateFormatter } from "../../utils/DateFormatter";
import FormDateTimePickerComponent from "../form-date-time-picker/form-date-time-picker.component";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(ProductionLastContacted);
export function ProductionLastContacted({ currentUser, record }) {
const [updateAlert] = useMutation(UPDATE_JOB);
const [insertNote] = useMutation(INSERT_NEW_NOTE);
const [visible, setVisible] = useState(false);
const { t } = useTranslation();
const [form] = Form.useForm();
const handleFinish = async ({ date_last_contacted, note }) => {
logImEXEvent("production_last_contacted");
//e.stopPropagation();
const res = await updateAlert({
variables: {
jobId: record.id,
job: {
date_last_contacted,
},
},
});
if (res.errors) {
notification.open({
type: "error",
message: t("jobs.errors.saving", {
error: JSON.stringify(res.errors),
}),
});
}
if (note && note.trim() !== "") {
//Insert a note.
const res2 = await insertNote({
variables: {
noteInput: {
jobid: record.id,
text: note,
created_by: currentUser.email,
},
},
});
if (res2.errors) {
notification.open({
type: "error",
message: t("notes.errors.inserting", {
error: JSON.stringify(res.errors),
}),
});
}
}
if (record.refetch) record.refetch();
setVisible(false);
};
useEffect(() => {
if (visible) {
form.setFieldsValue({
note: null,
date_last_contacted:
record.date_last_contacted && moment(record.date_last_contacted),
});
}
}, [visible, form, record.date_last_contacted]);
return (
<div>
<Dropdown
//trigger={["click"]}
visible={visible}
style={{
height: "19px",
}}
overlay={
<Card
style={{ padding: "1rem" }}
onClick={(e) => e.stopPropagation()}
>
<Form form={form} onFinish={handleFinish} layout="vertical">
<Form.Item name="date_last_contacted">
<FormDateTimePickerComponent />
</Form.Item>
<Form.Item label={t("notes.labels.notetoadd")} name="note">
<Input.TextArea rows={4} />
</Form.Item>
<Space>
<Button type="primary" htmlType="submit">
{t("general.actions.save")}
</Button>
<Button onClick={() => setVisible(false)}>
{t("general.actions.close")}
</Button>
</Space>
</Form>
</Card>
}
>
<div
onClick={() => setVisible(true)}
style={{
height: "19px",
}}
>
<DateFormatter bordered={false}>
{record.date_last_contacted}
</DateFormatter>
</div>
</Dropdown>
</div>
);
}

View File

@@ -77,6 +77,10 @@ export default function ProductionListDetail({ jobs }) {
phone={data.jobs_by_pk.ownr_ph1}
jobid={data.jobs_by_pk.id}
/>
<StartChatButton
phone={data.jobs_by_pk.ownr_ph2}
jobid={data.jobs_by_pk.id}
/>
</Descriptions.Item>
<Descriptions.Item label={t("jobs.fields.vehicle")}>
{`${theJob.v_model_yr || ""} ${theJob.v_color || ""} ${

View File

@@ -66,12 +66,7 @@ export function ProductionListSaveConfigButton({
};
const popMenu = (
<div>
<Form
layout="vertical"
form={form}
onFinish={handleSaveConfig}
initialValues={{ driveable: true, towin: false }}
>
<Form layout="vertical" form={form} onFinish={handleSaveConfig}>
<Form.Item
label={t("production.labels.viewname")}
name="name"

View File

@@ -37,9 +37,11 @@ export function ProductionListTable({
.filter((pc) => pc.name === value)[0]
.columns.columnKeys.map((k) => {
return {
...ProductionListColumns({ technician, state }).find(
(e) => e.key === k.key
),
...ProductionListColumns({
technician,
state,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
}).find((e) => e.key === k.key),
width: k.width,
};
})
@@ -55,6 +57,19 @@ export function ProductionListTable({
if (assoc) {
await updateDefaultProdView({
variables: { assocId: assoc.id, view: value },
update(cache) {
cache.modify({
id: cache.identify(bodyshop),
fields: {
associations(existingAssociations, { readField }) {
return existingAssociations.map((a) => {
if (a.useremail !== currentUser.email) return a;
return { ...a, default_prod_list_view: value };
});
},
},
});
},
});
}
};
@@ -75,9 +90,11 @@ export function ProductionListTable({
setColumns(
bodyshop.production_config[0].columns.columnKeys.map((k) => {
return {
...ProductionListColumns({ technician, state }).find(
(e) => e.key === k.key
),
...ProductionListColumns({
technician,
state,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
}).find((e) => e.key === k.key),
width: k.width,
};
})
@@ -85,13 +102,18 @@ export function ProductionListTable({
setState(bodyshop.production_config[0].columns.tableState);
};
const assoc = bodyshop.associations.find(
(a) => a.useremail === currentUser.email
);
const defaultView = assoc && assoc.default_prod_list_view;
return (
<div style={{ width: "10rem" }}>
<Select
onSelect={handleSelect}
placeholder={t("production.labels.selectview")}
optionLabelProp="label"
defaultValue={defaultView}
>
{bodyshop.production_config.map((config) => (
<Select.Option key={config.name} label={config.name}>

View File

@@ -1,4 +1,12 @@
import { Dropdown, Input, Menu, PageHeader, Space, Table } from "antd";
import {
Dropdown,
Input,
Menu,
PageHeader,
Space,
Statistic,
Table,
} from "antd";
import React, { useMemo, useState } from "react";
import ReactDragListView from "react-drag-listview";
import { useTranslation } from "react-i18next";
@@ -32,12 +40,11 @@ export function ProductionListTable({
}) {
const [searchText, setSearchText] = useState("");
const defaultView = useMemo(() => {
const assoc = bodyshop.associations.find(
(a) => a.useremail === currentUser.email
);
return assoc && assoc.default_prod_list_view;
}, [bodyshop.associations, currentUser.email]);
const assoc = bodyshop.associations.find(
(a) => a.useremail === currentUser.email
);
const defaultView = assoc && assoc.default_prod_list_view;
const [state, setState] = useState(
(bodyshop.production_config &&
@@ -60,9 +67,11 @@ export function ProductionListTable({
matchingColumnConfig &&
matchingColumnConfig.columns.columnKeys.map((k) => {
return {
...ProductionListColumns({ technician, state }).find(
(e) => e.key === k.key
),
...ProductionListColumns({
technician,
state,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
}).find((e) => e.key === k.key),
width: k.width,
};
})) ||
@@ -156,10 +165,26 @@ export function ProductionListTable({
// };
if (!!!columns) return <div>No columns found.</div>;
console.log(data);
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);
return (
<div>
<PageHeader
title={
<Statistic
title={t("dashboard.titles.productionhours")}
value={totalHrs}
/>
}
extra={
<Space wrap>
<ProductionListColumnsAdd

View File

@@ -33,6 +33,10 @@ export default function QboAuthorizeComponent() {
setCookie("qbo_realmId", realmId, {
path: "/",
expires,
...(process.env.NODE_ENV !== "development"
? { domain: `.${window.location.host}` }
: {}),
});
history.push({ pathname: `/manage/accounting/receivables` });

View File

@@ -124,7 +124,7 @@ export function ScheduleJobModalComponent({
handleDateBlur();
}}
>
<DateFormatter>{d}</DateFormatter>
<DateFormatter includeDay>{d}</DateFormatter>
</Button>
))}
</Space>

View File

@@ -42,7 +42,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lab")}
@@ -55,7 +55,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lad")}
@@ -68,7 +68,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lae")}
@@ -81,7 +81,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_laf")}
@@ -94,7 +94,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lag")}
@@ -107,7 +107,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lam")}
@@ -120,7 +120,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_lar")}
@@ -133,7 +133,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_las")}
@@ -146,7 +146,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la1")}
@@ -159,7 +159,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la2")}
@@ -172,7 +172,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la3")}
@@ -185,7 +185,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_la4")}
@@ -198,7 +198,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_mash")}
@@ -211,7 +211,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_mapa")}
@@ -224,7 +224,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_ma2s")}
@@ -237,7 +237,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_ma3s")}
@@ -250,7 +250,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
{
// <Form.Item
@@ -264,7 +264,7 @@ export default function ShopInfoLaborRates({ form }) {
// },
// ]}
// >
// <CurrencyInput />
// <CurrencyInput min={0} />
// </Form.Item>
// <Form.Item
// label={t("jobs.fields.rate_macs")}
@@ -277,7 +277,7 @@ export default function ShopInfoLaborRates({ form }) {
// },
// ]}
// >
// <CurrencyInput />
// <CurrencyInput min={0} />
// </Form.Item>
}
<Form.Item
@@ -291,7 +291,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<Form.Item
label={t("jobs.fields.rate_mahw")}
@@ -304,7 +304,7 @@ export default function ShopInfoLaborRates({ form }) {
},
]}
>
<CurrencyInput />
<CurrencyInput min={0} />
</Form.Item>
<DeleteFilled
onClick={() => {

View File

@@ -515,6 +515,27 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
))}
</Select>
</Form.Item>
<Form.Item
label={t(
"bodyshop.fields.responsibilitycenters.laa"
)}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
key={`${index}costs-LAA`}
name={[field.name, "costs", "LAA"]}
>
<Select>
{costOptions.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t(
"bodyshop.fields.responsibilitycenters.lab"
@@ -1086,6 +1107,27 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
))}
</Select>
</Form.Item>
<Form.Item
label={t(
"bodyshop.fields.responsibilitycenters.laa"
)}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
key={`${index}profits-LAA`}
name={[field.name, "profits", "LAA"]}
>
<Select>
{profitOptions.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t(
"bodyshop.fields.responsibilitycenters.lab"
@@ -1673,6 +1715,24 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.responsibilitycenters.laa")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={["md_responsibility_centers", "defaults", "costs", "LAA"]}
>
<Select>
{costOptions.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.responsibilitycenters.lab")}
rules={[
@@ -2161,6 +2221,24 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.responsibilitycenters.laa")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={["md_responsibility_centers", "defaults", "profits", "LAA"]}
>
<Select>
{profitOptions.map((item, idx) => (
<Select.Option key={idx} value={item}>
{item}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
label={t("bodyshop.fields.responsibilitycenters.lab")}
rules={[

View File

@@ -50,7 +50,9 @@ export function TechClockInComponent({ form, bodyshop, technician }) {
{emps &&
emps.rates.map((item) => (
<Select.Option key={item.cost_center}>
{item.cost_center}
{item.cost_center === "timetickets.labels.shift"
? t(item.cost_center)
: item.cost_center}
</Select.Option>
))}
</Select>

View File

@@ -139,7 +139,9 @@ export function TechClockOffButton({
emps &&
emps.rates.map((item) => (
<Select.Option key={item.cost_center}>
{item.cost_center}
{item.cost_center === "timetickets.labels.shift"
? t(item.cost_center)
: item.cost_center}
</Select.Option>
))
)}

View File

@@ -83,7 +83,9 @@ export function TechClockedInList({ technician }) {
<DateTimeFormatter>{ticket.clockon}</DateTimeFormatter>
</DataLabel>
<DataLabel label={t("timetickets.fields.cost_center")}>
{ticket.cost_center}
{ticket.cost_center === "timetickets.labels.shift"
? t(ticket.cost_center)
: ticket.cost_center}
</DataLabel>
</Card>
</List.Item>

View File

@@ -28,6 +28,7 @@ export const QUERY_ALL_ACTIVE_APPOINTMENTS = gql`
ownr_co_nm
ownr_fn
ownr_ph1
ownr_ph2
ownr_ea
clm_total
id
@@ -126,6 +127,7 @@ export const QUERY_APPOINTMENT_BY_DATE = gql`
ownr_ln
ownr_fn
ownr_ph1
ownr_ph2
ownr_ea
clm_total
id

View File

@@ -93,6 +93,7 @@ export const QUERY_BILLS_BY_JOBID = gql`
backordered_on
}
order_number
comments
user_email
}
bills(where: { jobid: { _eq: $jobid } }, order_by: { date: desc }) {

View File

@@ -10,6 +10,7 @@ export const QUERY_ALL_ACTIVE_JOBS = gql`
ownr_ln
ownr_co_nm
ownr_ph1
ownr_ph2
ownr_ea
owner {
id
@@ -79,6 +80,7 @@ export const QUERY_PARTS_QUEUE = gql`
ownr_ln
ownr_co_nm
ownr_ph1
ownr_ph2
ownr_ea
plate_no
plate_st
@@ -122,9 +124,11 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
actual_in
scheduled_completion
scheduled_delivery
date_last_contacted
ins_co_nm
clm_total
ownr_ph1
ownr_ph2
special_coverage_policy
owner_owing
production_vars
@@ -359,6 +363,7 @@ export const GET_JOB_BY_PK = gql`
kmin
kmout
referral_source
referral_source_extra
unit_number
po_number
special_coverage_policy
@@ -454,6 +459,7 @@ export const GET_JOB_BY_PK = gql`
ownr_zip
ownr_ctry
ownr_ph1
ownr_ph2
production_vars
ca_gst_registrant
ownerid
@@ -470,6 +476,7 @@ export const GET_JOB_BY_PK = gql`
ownr_zip
ownr_ctry
ownr_ph1
ownr_ph2
}
labor_rate_desc
rate_la1
@@ -508,6 +515,7 @@ export const GET_JOB_BY_PK = gql`
date_open
date_scheduled
date_invoiced
date_last_contacted
date_exported
status
owner_owing
@@ -563,6 +571,7 @@ export const GET_JOB_BY_PK = gql`
parts_order {
id
order_number
comments
order_date
user_email
vendor {
@@ -626,7 +635,7 @@ export const GET_JOB_RECONCILIATION_BY_PK = gql`
is_credit_memo
isinhouse
exported
billlines {
billlines(where: { deductedfromlbr: { _eq: false } }) {
actual_price
quantity
actual_cost
@@ -684,8 +693,10 @@ export const QUERY_JOB_CARD_DETAILS = gql`
ownr_ln
ownr_co_nm
ownr_ph1
ownr_ph2
ownr_ea
ca_gst_registrant
owner_owing
special_coverage_policy
available_jobs {
id
@@ -745,6 +756,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
scheduled_in
scheduled_delivery
date_invoiced
date_last_contacted
date_open
date_exported
@@ -830,6 +842,7 @@ export const QUERY_TECH_JOB_DETAILS = gql`
scheduled_in
scheduled_delivery
date_invoiced
date_last_contacted
date_open
date_exported
voided
@@ -964,6 +977,7 @@ export const CONVERT_JOB_TO_RO = gql`
$driveable: Boolean
$towin: Boolean
$referral_source: String
$referral_source_extra: String
) {
update_jobs(
where: { id: { _eq: $jobId } }
@@ -975,6 +989,7 @@ export const CONVERT_JOB_TO_RO = gql`
towin: $towin
driveable: $driveable
referral_source: $referral_source
referral_source_extra: $referral_source_extra
}
) {
returning {
@@ -984,6 +999,7 @@ export const CONVERT_JOB_TO_RO = gql`
class
ins_co_nm
referral_source
referral_source_extra
}
}
}
@@ -1008,6 +1024,7 @@ export const GET_JOB_INFO_FOR_STRIPE = gql`
ownr_ln
ownr_co_nm
ownr_ph1
ownr_ph2
ownr_ea
}
}
@@ -1497,6 +1514,7 @@ export const QUERY_ALL_JOB_FIELDS = gql`
rate_mash
rate_matd
referral_source
referral_source_extra
regie_number
selling_dealer
selling_dealer_contact
@@ -1643,6 +1661,7 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql`
ownr_co_nm
ownerid
ownr_ph1
ownr_ph2
ownr_ea
plate_no
plate_st
@@ -1750,7 +1769,7 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
actual_in
kmin
kmout
joblines(where: { removed: { _eq: false } }) {
joblines(where: { removed: { _eq: false } }, order_by: { line_no: asc }) {
id
removed
tax_part
@@ -1858,6 +1877,7 @@ export const GET_JOB_FOR_CC_CONTRACT = gql`
ownr_city
ownr_zip
ownr_ph1
ownr_ph2
}
}
`;

View File

@@ -2,7 +2,7 @@ import { gql } from "@apollo/client";
export const QUERY_SEARCH_OWNER_BY_IDX = gql`
query QUERY_SEARCH_OWNER_BY_IDX($search: String!) {
search_owners(args: { search: $search }) {
search_owners(args: { search: $search }, limit: 100) {
ownr_fn
ownr_ln
ownr_ph1

View File

@@ -23,6 +23,7 @@ export const GLOBAL_SEARCH_QUERY = gql`
ownr_ln
ownr_co_nm
ownr_ph1
ownr_ph2
}
search_vehicles(args: { search: $search }) {
id

View File

@@ -612,7 +612,7 @@ export const Pricing11DataSource = {
<br /> 14500GB流量包
<br /> 14国内按峰值宽带账单
<br /> 14弹性计算
<br /> 14云服务器 ECS{" "}
<br /> 14云服务器 ECS
</span>
),
},

View File

@@ -196,7 +196,11 @@ export function JobsDetailPage({
<PrinterFilled />
{t("jobs.actions.printCenter")}
</Button>
<JobsConvertButton job={job} refetch={refetch} />
<JobsConvertButton
job={job}
refetch={refetch}
parentFormIsFieldsTouched={form.isFieldsTouched}
/>
<JobsDetailHeaderActions key="actions" job={job} refetch={refetch} />
<Button
type="primary"

View File

@@ -396,6 +396,7 @@
"la2": "LA2",
"la3": "LA3",
"la4": "LA4",
"laa": "Aluminum",
"lab": "Body",
"lad": "Diagnostic",
"lae": "Electrical",
@@ -1052,8 +1053,10 @@
},
"profitcenter_labor": "Profit Center: Labor",
"profitcenter_part": "Profit Center: Part",
"prt_dsmk_p": "Line Markup %",
"prt_dsmk_m": "Line Discount/Markup $",
"prt_dsmk_p": "Line Discount/Markup %",
"status": "Status",
"tax_part": "Tax Part",
"total": "Total",
"unq_seq": "Seq #"
},
@@ -1196,6 +1199,7 @@
"date_estimated": "Date Estimated",
"date_exported": "Exported",
"date_invoiced": "Invoiced",
"date_last_contacted": "Last Contacted Date",
"date_open": "Open",
"date_scheduled": "Scheduled",
"ded_amt": "Deductible",
@@ -1287,6 +1291,7 @@
"owner_owing": "Cust. Owes",
"ownr_ea": "Email",
"ownr_ph1": "Phone 1",
"ownr_ph2": "Phone 2",
"paa": "Aftermarket",
"pac": "Rechromed",
"pae": "Existing",
@@ -1335,6 +1340,8 @@
"rate_mapa": "Paint Materials",
"rate_mash": "Shop Material",
"rate_matd": "Tire Disposal",
"referral_source_extra": "Other Referral Source",
"referral_source_other": "",
"referralsource": "Referral Source",
"regie_number": "Registration #",
"repairtotal": "Repair Total",
@@ -1520,6 +1527,7 @@
"sale_labor": "Sales - Labor",
"sale_parts": "Sales - Parts & Sublet",
"sales": "Sales",
"savebeforeconversion": "You have unsaved changes on the job. Please save them before converting it. ",
"scheduledinchange": "The scheduled in is based off the latest appointment. To change this date, please schedule or reschedule the job. ",
"specialcoveragepolicy": "Special Coverage Policy Applies",
"state_tax_amt": "Provincial/State Taxes",
@@ -1733,6 +1741,9 @@
"edit": "Edit Note",
"new": "New Note"
},
"errors": {
"inserting": "Error inserting note. {{error}}"
},
"fields": {
"createdby": "Created By",
"critical": "Critical",
@@ -1741,7 +1752,8 @@
"updatedat": "Updated At"
},
"labels": {
"newnoteplaceholder": "Add a note..."
"newnoteplaceholder": "Add a note...",
"notetoadd": "Note to Add"
},
"successes": {
"create": "Note created successfully.",
@@ -1770,6 +1782,7 @@
"ownr_fn": "First Name",
"ownr_ln": "Last Name",
"ownr_ph1": "Phone 1",
"ownr_ph2": "Phone 2",
"ownr_st": "Province/State",
"ownr_title": "Title",
"ownr_zip": "Zip/Postal Code",
@@ -1811,9 +1824,10 @@
"act_price": "Price",
"backordered_eta": "B.O. ETA",
"backordered_on": "B.O. On",
"comments": "Comments",
"cost": "Cost",
"db_price": "List Price",
"deliver_by": "Date",
"deliver_by": "Deliver By",
"job_line_id": "Job Line Id",
"line_desc": "Line Description",
"line_remarks": "Remarks",
@@ -1966,6 +1980,7 @@
"guarantee": "Repair Guarantee",
"invoice_customer_payable": "Invoice (Customer Payable)",
"invoice_total_payable": "Invoice (Total Payable)",
"iou_form": "IOU Form",
"job_costing_ro": "Job Costing",
"job_notes": "Job Notes",
"key_tag": "Key Tag",
@@ -2020,7 +2035,7 @@
},
"subjects": {
"jobs": {
"parts_order": "$t(printcenter.jobs.parts_order) PO: {{ro_number}}"
"parts_order": "Parts Order PO: {{ro_number}}"
}
},
"vendors": {

View File

@@ -396,6 +396,7 @@
"la2": "",
"la3": "",
"la4": "",
"laa": "",
"lab": "",
"lad": "",
"lae": "",
@@ -1052,8 +1053,10 @@
},
"profitcenter_labor": "",
"profitcenter_part": "",
"prt_dsmk_m": "",
"prt_dsmk_p": "",
"status": "Estado",
"tax_part": "",
"total": "",
"unq_seq": "Seq #"
},
@@ -1196,6 +1199,7 @@
"date_estimated": "Fecha estimada",
"date_exported": "Exportado",
"date_invoiced": "Facturado",
"date_last_contacted": "",
"date_open": "Abierto",
"date_scheduled": "Programado",
"ded_amt": "Deducible",
@@ -1287,6 +1291,7 @@
"owner_owing": "Cust. Debe",
"ownr_ea": "Email",
"ownr_ph1": "Teléfono 1",
"ownr_ph2": "",
"paa": "",
"pac": "",
"pae": "",
@@ -1335,6 +1340,8 @@
"rate_mapa": "Tasa de materiales de pintura",
"rate_mash": "Comprar material de tarifa",
"rate_matd": "Tasa de eliminación de neumáticos",
"referral_source_extra": "",
"referral_source_other": "",
"referralsource": "Fuente de referencia",
"regie_number": "N. ° de registro",
"repairtotal": "Reparación total",
@@ -1520,6 +1527,7 @@
"sale_labor": "",
"sale_parts": "",
"sales": "",
"savebeforeconversion": "",
"scheduledinchange": "",
"specialcoveragepolicy": "",
"state_tax_amt": "",
@@ -1733,6 +1741,9 @@
"edit": "Editar nota",
"new": "Nueva nota"
},
"errors": {
"inserting": ""
},
"fields": {
"createdby": "Creado por",
"critical": "Crítico",
@@ -1741,7 +1752,8 @@
"updatedat": "Actualizado en"
},
"labels": {
"newnoteplaceholder": "Agrega una nota..."
"newnoteplaceholder": "Agrega una nota...",
"notetoadd": ""
},
"successes": {
"create": "Nota creada con éxito.",
@@ -1770,6 +1782,7 @@
"ownr_fn": "Nombre de pila",
"ownr_ln": "Apellido",
"ownr_ph1": "Teléfono 1",
"ownr_ph2": "",
"ownr_st": "Provincia del estado",
"ownr_title": "Título",
"ownr_zip": "código postal",
@@ -1811,6 +1824,7 @@
"act_price": "",
"backordered_eta": "",
"backordered_on": "",
"comments": "",
"cost": "",
"db_price": "",
"deliver_by": "",
@@ -1966,6 +1980,7 @@
"guarantee": "",
"invoice_customer_payable": "",
"invoice_total_payable": "",
"iou_form": "",
"job_costing_ro": "",
"job_notes": "",
"key_tag": "",

View File

@@ -396,6 +396,7 @@
"la2": "",
"la3": "",
"la4": "",
"laa": "",
"lab": "",
"lad": "",
"lae": "",
@@ -1052,8 +1053,10 @@
},
"profitcenter_labor": "",
"profitcenter_part": "",
"prt_dsmk_m": "",
"prt_dsmk_p": "",
"status": "Statut",
"tax_part": "",
"total": "",
"unq_seq": "Seq #"
},
@@ -1196,6 +1199,7 @@
"date_estimated": "Date estimée",
"date_exported": "Exportés",
"date_invoiced": "Facturé",
"date_last_contacted": "",
"date_open": "Ouvrir",
"date_scheduled": "Prévu",
"ded_amt": "Déductible",
@@ -1287,6 +1291,7 @@
"owner_owing": "Cust. Owes",
"ownr_ea": "Email",
"ownr_ph1": "Téléphone 1",
"ownr_ph2": "",
"paa": "",
"pac": "",
"pae": "",
@@ -1335,6 +1340,8 @@
"rate_mapa": "Taux de matériaux de peinture",
"rate_mash": "Tarif du matériel de la boutique",
"rate_matd": "Taux d'élimination des pneus",
"referral_source_extra": "",
"referral_source_other": "",
"referralsource": "Source de référence",
"regie_number": "Enregistrement #",
"repairtotal": "Réparation totale",
@@ -1520,6 +1527,7 @@
"sale_labor": "",
"sale_parts": "",
"sales": "",
"savebeforeconversion": "",
"scheduledinchange": "",
"specialcoveragepolicy": "",
"state_tax_amt": "",
@@ -1733,6 +1741,9 @@
"edit": "Note éditée",
"new": "Nouvelle note"
},
"errors": {
"inserting": ""
},
"fields": {
"createdby": "Créé par",
"critical": "Critique",
@@ -1741,7 +1752,8 @@
"updatedat": "Mis à jour à"
},
"labels": {
"newnoteplaceholder": "Ajouter une note..."
"newnoteplaceholder": "Ajouter une note...",
"notetoadd": ""
},
"successes": {
"create": "Remarque créée avec succès.",
@@ -1770,6 +1782,7 @@
"ownr_fn": "Prénom",
"ownr_ln": "Nom de famille",
"ownr_ph1": "Téléphone 1",
"ownr_ph2": "",
"ownr_st": "Etat / Province",
"ownr_title": "Titre",
"ownr_zip": "Zip / code postal",
@@ -1811,6 +1824,7 @@
"act_price": "",
"backordered_eta": "",
"backordered_on": "",
"comments": "",
"cost": "",
"db_price": "",
"deliver_by": "",
@@ -1966,6 +1980,7 @@
"guarantee": "",
"invoice_customer_payable": "",
"invoice_total_payable": "",
"iou_form": "",
"job_costing_ro": "",
"job_notes": "",
"key_tag": "",

View File

@@ -3,7 +3,11 @@ import moment from "moment";
import React from "react";
export function DateFormatter(props) {
return props.children ? moment(props.children).format("MM/DD/YYYY") : null;
return props.children
? moment(props.children).format(
props.includeDay ? "ddd MM/DD/YYYY" : "MM/DD/YYYY"
)
: null;
}
export function DateTimeFormatter(props) {

View File

@@ -2,13 +2,13 @@ import { gql } from "@apollo/client";
import { notification } from "antd";
import axios from "axios";
import jsreport from "jsreport-browser-client-dist";
import _ from "lodash";
import moment from "moment";
import { auth } from "../firebase/firebase.utils";
import { setEmailOptions } from "../redux/email/email.actions";
import { store } from "../redux/store";
import client from "../utils/GraphQLClient";
import { TemplateList } from "./TemplateConstants";
import _ from "lodash";
const server = process.env.REACT_APP_REPORTS_SERVER_URL;
jsreport.serverUrl = server;
@@ -144,6 +144,7 @@ export async function RenderTemplates(
// ...rootTemplate.templateObject.context,
headerpath: `/${bodyshop.imexshopid}/header.html`,
bodyshop: bodyshop,
offset: moment().utcOffset(),
},
};
@@ -195,35 +196,40 @@ export const GenerateDocuments = async (templates) => {
const fetchContextData = async (templateObject) => {
console.log("Fetching context data", templateObject);
const bodyshop = store.getState().user.bodyshop;
jsreport.headers["Authorization"] =
"Bearer " + (await auth.currentUser.getIdToken());
const folders = await axios.get(`${server}/odata/folders`);
const shopSpecificFolder = folders.data.value.find(
(f) => f.name === bodyshop.imexshopid
);
const jsReportQueries = await axios.get(
`${server}/odata/assets?$filter=name eq '${templateObject.name}.query'`
);
let templateQueryToExecute,
useShopSpecificTemplate = false;
if (jsReportQueries.data.value.length === 0) {
//We have no query to execute. Just render the template.
} else if (jsReportQueries.data.value.length === 1) {
//We're using the default template. Get the query and execute.
templateQueryToExecute = atob(jsReportQueries.data.value[0].content);
} else if (jsReportQueries.data.value.length === 2) {
//There's a custom template. Use that query instead and execute. We find it because it has a parent folder.
templateQueryToExecute = atob(
jsReportQueries.data.value.filter((v) => !!v.folder)[0].content
);
useShopSpecificTemplate = true;
} else {
//We have too many queries to choose from. Throw an error.
alert(
"There are too many queries to choose from. Please ensure there are no conflicting keys."
);
throw new Error(
"There are too many queries to choose from. Please ensure there are no conflicting keys."
let templateQueryToExecute;
let useShopSpecificTemplate = false;
// let shopSpecificTemplate;
if (shopSpecificFolder) {
let shopSpecificTemplate = jsReportQueries.data.value.find(
(f) => f?.folder?.shortid === shopSpecificFolder.shortid
);
if (shopSpecificTemplate) {
useShopSpecificTemplate = true;
templateQueryToExecute = atob(shopSpecificTemplate.content);
}
}
if (!templateQueryToExecute) {
const generalTemplate = jsReportQueries.data.value.find((f) => !f.folder);
useShopSpecificTemplate = false;
templateQueryToExecute = atob(generalTemplate.content);
}
let contextData = {};
if (templateQueryToExecute) {
const { data } = await client.query({

View File

@@ -382,6 +382,14 @@ export const TemplateList = (type, context) => {
// disabled: false,
// group: "ro",
// },
iou_form: {
title: i18n.t("printcenter.jobs.iou_form"),
description: "CASL Authorization",
subject: i18n.t("printcenter.jobs.iou_form"),
key: "iou_form",
disabled: false,
group: "post",
},
}
: {}),
...(!type || type === "job_special"

View File

@@ -9,5 +9,11 @@ export function alphaSort(a, b) {
}
export function dateSort(a, b) {
return new Date(b) - new Date(a);
return new Date(a) - new Date(b);
}
export function statusSort(a, b, statusList) {
return (
statusList.findIndex((x) => x === a) - statusList.findIndex((x) => x === b)
);
}

View File

@@ -36,10 +36,10 @@
lodash "^4.17.21"
resize-observer-polyfill "^1.5.0"
"@apollo/client@^3.4.14":
version "3.4.14"
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.4.14.tgz#069adcaef53d96c84eea5c0022efeace5cd09afb"
integrity sha512-9yrxbPwQbQ3n/+TeOGtalrf8mT4XyOcBBDlRPWC1E5JJp5exrl9n2GIgrUvd2KsVZLUT876kUJY3zfyyjW5Udg==
"@apollo/client@^3.4.16":
version "3.4.16"
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.4.16.tgz#67090d5655aa843fa64d26f1913315e384a5fa0f"
integrity sha512-iF4zEYwvebkri0BZQyv8zfavPfVEafsK0wkOofa6eC2yZu50J18uTutKtC174rjHZ2eyxZ8tV7NvAPKRT+OtZw==
dependencies:
"@graphql-typed-document-node/core" "^3.0.0"
"@wry/context" "^0.6.0"
@@ -1209,7 +1209,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.1.2", "@babel/runtime@^7.1.5", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.1.2", "@babel/runtime@^7.1.5", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.4", "@babel/runtime@^7.11.1", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.2", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.15.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a"
integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw==
@@ -1357,12 +1357,12 @@
"@firebase/util" "1.4.0"
tslib "^2.1.0"
"@firebase/app-check-compat@0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.1.2.tgz#1e5480a9f83c1cec814b3a11032a797b1a50eaec"
integrity sha512-JB+OHk4Cp9ZgT+UfX0A+lwH1AoM5Y2X1rDhmhCsEXcKKwz1w9DpL9PjStciP8UYg1dpqbp5p9OMxmty+21EBsA==
"@firebase/app-check-compat@0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.1.3.tgz#b10c34a44d4bfdd86911506367e86705fb2e3ff0"
integrity sha512-ka5ggmfucQDwEJTcFsXPJJ+ygPZz4Q44D5yb0sksfOAsUSpzAR83jDSxebOgTvvk+axNCFamxOsrZEV6KKDjEg==
dependencies:
"@firebase/app-check" "0.4.1"
"@firebase/app-check" "0.4.2"
"@firebase/component" "0.5.7"
"@firebase/logger" "0.3.0"
"@firebase/util" "1.4.0"
@@ -1373,22 +1373,22 @@
resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.1.0.tgz#83afd9d41f99166c2bdb2d824e5032e9edd8fe53"
integrity sha512-uZfn9s4uuRsaX5Lwx+gFP3B6YsyOKUE+Rqa6z9ojT4VSRAsZFko9FRn6OxQUA1z5t5d08fY4pf+/+Dkd5wbdbA==
"@firebase/app-check@0.4.1":
version "0.4.1"
resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.4.1.tgz#60e329b3871574a0431536edca69e0d0a8cbd674"
integrity sha512-Kpqh0Y2zpx+acTL7eOVYIWBOmAwoconJpqOAlByGNXuxm/ccP00XREo+HsqaC7wapZRXh+h8BK0jZjvdV36qow==
"@firebase/app-check@0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.4.2.tgz#33ca60f439d679ced9a593b392c8a4934d14d81f"
integrity sha512-DFYt22lUMvvncN3v6x9ZRE2/HHBQdRQyYtHwakAcZrRUALJiU16iDwl2CABuW4JKytTmMj+xXo0fjSIRWtwT/w==
dependencies:
"@firebase/component" "0.5.7"
"@firebase/logger" "0.3.0"
"@firebase/util" "1.4.0"
tslib "^2.1.0"
"@firebase/app-compat@0.1.2":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.1.2.tgz#ed9682325bbec6e177449f4b7403c60b088c89db"
integrity sha512-kF1maoqA8bZqJ4v/ojVvA7kIyyXEPkJmL48otGrC8LIgdcen7xCx3JFDe0DGeQywg+qujvdkJz/TptFN1cvAgw==
"@firebase/app-compat@0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.1.4.tgz#16810596a9a0d1460cdfbdc305739004731b2eb8"
integrity sha512-+nxJUeELZflyy0a95Xg2LUwa5ulNnzQzhqyOyzNKTjzfEoi/uLKK2R4ibZ8yb/vLqN7mNySqjbRpfp9Lk/fiQw==
dependencies:
"@firebase/app" "0.7.1"
"@firebase/app" "0.7.3"
"@firebase/component" "0.5.7"
"@firebase/logger" "0.3.0"
"@firebase/util" "1.4.0"
@@ -1399,26 +1399,26 @@
resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.7.0.tgz#c9e16d1b8bed1a991840b8d2a725fb58d0b5899f"
integrity sha512-6fbHQwDv2jp/v6bXhBw2eSRbNBpxHcd1NBF864UksSMVIqIyri9qpJB1Mn6sGZE+bnDsSQBC5j2TbMxYsJQkQg==
"@firebase/app@0.7.1":
version "0.7.1"
resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.7.1.tgz#b594ac4cd15bf94d2a3b97681354a52fa5cfca29"
integrity sha512-B4z6E1EPQc0mOjF35IPKdDRCFnT/fNQIHfM+v7F9obB7ItPhGILK3LxaQfuampSQpF6GG6TPFDbrWK6myXAq+g==
"@firebase/app@0.7.3":
version "0.7.3"
resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.7.3.tgz#c5a8d89569840ca7798844c9cbd34143963a3cb8"
integrity sha512-IsSsPzVEOxKWpvYkNdkBmTntYKjKhEUNhBdWrM3SC0pKdEDAmk5T/JIZ5gAK3K7B4bTvWo2iNQ+qMCbtSZoLWw==
dependencies:
"@firebase/component" "0.5.7"
"@firebase/logger" "0.3.0"
"@firebase/util" "1.4.0"
tslib "^2.1.0"
"@firebase/auth-compat@0.1.3":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.1.3.tgz#0110398e665e7b709dfbb81ab9410f58e3d1a98d"
integrity sha512-eDDtY5If+ERJxalt+plvX6avZspuwo4/kPXssvV+csm414awhDzQBtSDPDajgbH3YB9V+O3LAFHeWcP3rrHS5w==
"@firebase/auth-compat@0.1.5":
version "0.1.5"
resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.1.5.tgz#58e25ac929c5de5d716e211f632f731db1280b6e"
integrity sha512-b6kHy4qVkeHetQDzGDbe7oF5iC9pt9DtwByt2QpDJpm4PjUNzAupQm6knSAmqf4RNo7Sh7UkCSWvE/zlzIectw==
dependencies:
"@firebase/auth" "0.18.0"
"@firebase/auth" "0.18.2"
"@firebase/auth-types" "0.11.0"
"@firebase/component" "0.5.7"
"@firebase/util" "1.4.0"
node-fetch "2.6.2"
node-fetch "2.6.5"
selenium-webdriver "^4.0.0-beta.2"
tslib "^2.1.0"
@@ -1432,15 +1432,15 @@
resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.11.0.tgz#b9c73c60ca07945b3bbd7a097633e5f78fa9e886"
integrity sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==
"@firebase/auth@0.18.0":
version "0.18.0"
resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.18.0.tgz#00de488a43f84bd9b1e2f8e1d9887a499d30b93d"
integrity sha512-iK+VXkdDkum8SmJNgz9ZcOboRLrUN1VW7AHHkpZb76VJvoYRoCPD+A9O/v/ziI0LpwIZJwi1GFes9XjZTlfLiA==
"@firebase/auth@0.18.2":
version "0.18.2"
resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.18.2.tgz#0a89d861806724226113413deae027d138c58060"
integrity sha512-0y/yvlN7YD5o1bN4OKMRPiekrWaczWq5aQUh7Wo+eahbPb1LywT27ClFGavgAOygk0fXGjhNjp5UL3ItugvFlg==
dependencies:
"@firebase/component" "0.5.7"
"@firebase/logger" "0.3.0"
"@firebase/util" "1.4.0"
node-fetch "2.6.2"
node-fetch "2.6.5"
selenium-webdriver "4.0.0-rc-1"
tslib "^2.1.0"
@@ -2005,10 +2005,10 @@
mkdirp "^1.0.4"
rimraf "^3.0.2"
"@openreplay/tracker-assist@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@openreplay/tracker-assist/-/tracker-assist-3.4.0.tgz#93a5e5314b3af55c23979cfe654e7617f76844af"
integrity sha512-tKxb0FuUmSo76gH7fBeZ+KYj+G7nDe0N8Ii7dwPCmljfi+0gCXNEtju1+ioQM1XVlT0IWl3a3/JUBvE5MXLEAA==
"@openreplay/tracker-assist@^3.4.3":
version "3.4.3"
resolved "https://registry.yarnpkg.com/@openreplay/tracker-assist/-/tracker-assist-3.4.3.tgz#02eb6c41ec7a78f38e6fc30df9f637e79c4c1877"
integrity sha512-N+HdVdNZiJcIsakxDzhGr4qGrWLeYNaYgfW7kzbAOxZXWJ9hKU5OH/LUZPl74QfYN0cw0/AbXqBi2sJc71a3aw==
dependencies:
npm-dragndrop "^1.2.0"
peerjs "^1.3.2"
@@ -2023,10 +2023,10 @@
resolved "https://registry.yarnpkg.com/@openreplay/tracker-redux/-/tracker-redux-3.0.0.tgz#7d71c8d2b58b08229e6af2c677d53980cee0b9ef"
integrity sha512-ctybOquoDj8QNj82pETftgXjEoAzwEoKSxIhwstJaUv5xUkBVv0rDIjMBgCSys8cB/vbRkI/QhvksDaFr9hY0g==
"@openreplay/tracker@^3.4.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/@openreplay/tracker/-/tracker-3.4.0.tgz#ad53936b501d98b365b1252b3388c8466c6cac90"
integrity sha512-i4Lv4c5097gLCRAr9ZuU0mWEmQYWL6W+y2AlF1oqLCdzmYFvsRKSpSa/ytS7iPNRbJRSfau7BTZoeUvLU/ugeA==
"@openreplay/tracker@^3.4.4":
version "3.4.4"
resolved "https://registry.yarnpkg.com/@openreplay/tracker/-/tracker-3.4.4.tgz#4d79fb738f7704aefbea55117d52d61999beb571"
integrity sha512-IcuxwwTt1RtLZw9QlQVAVNqoybv0ZkD2ZDk2FeHEQ/+BItsMhG61/4/lB2yXKLTLr6ydeKTzwYvxfr1vwxn2dw==
dependencies:
"@medv/finder" "^2.0.0"
error-stack-parser "^2.0.6"
@@ -2180,14 +2180,14 @@
estree-walker "^1.0.1"
picomatch "^2.2.2"
"@sentry/browser@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.13.2.tgz#8b731ecf8c3cdd92a4b6893a26f975fd5844056d"
integrity sha512-bkFXK4vAp2UX/4rQY0pj2Iky55Gnwr79CtveoeeMshoLy5iDgZ8gvnLNAz7om4B9OQk1u7NzLEa4IXAmHTUyag==
"@sentry/browser@6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.13.3.tgz#d4511791b1e484ad48785eba3bce291fdf115c1e"
integrity sha512-jwlpsk2/u1cofvfYsjmqcnx50JJtf/T6HTgdW+ih8+rqWC5ABEZf4IiB/H+KAyjJ3wVzCOugMq5irL83XDCfqQ==
dependencies:
"@sentry/core" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
"@sentry/core" "6.13.3"
"@sentry/types" "6.13.3"
"@sentry/utils" "6.13.3"
tslib "^1.9.3"
"@sentry/cli@^1.68.0":
@@ -2202,75 +2202,75 @@
progress "^2.0.3"
proxy-from-env "^1.1.0"
"@sentry/core@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.13.2.tgz#2ce164f81667aa89cd116f807d772b4718434583"
integrity sha512-snXNNFLwlS7yYxKTX4DBXebvJK+6ikBWN6noQ1CHowvM3ReFBlrdrs0Z0SsSFEzXm2S4q7f6HHbm66GSQZ/8FQ==
"@sentry/core@6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.13.3.tgz#5cbbb995128e793ebebcbf1d3b7514e0e5e8b221"
integrity sha512-obm3SjgCk8A7nB37b2AU1eq1q7gMoJRrGMv9VRIyfcG0Wlz/5lJ9O3ohUk+YZaaVfZMxXn6hFtsBiOWmlv7IIA==
dependencies:
"@sentry/hub" "6.13.2"
"@sentry/minimal" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
"@sentry/hub" "6.13.3"
"@sentry/minimal" "6.13.3"
"@sentry/types" "6.13.3"
"@sentry/utils" "6.13.3"
tslib "^1.9.3"
"@sentry/hub@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.13.2.tgz#ebc66fd55c96c7686a53ffd3521b6a63f883bb79"
integrity sha512-sppSuJdNMiMC/vFm/dQowCBh11uTrmvks00fc190YWgxHshodJwXMdpc+pN61VSOmy2QA4MbQ5aMAgHzPzel3A==
"@sentry/hub@6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.13.3.tgz#cc09623a69b5343315fdb61c7fdd0be74b72299f"
integrity sha512-eYppBVqvhs5cvm33snW2sxfcw6G20/74RbBn+E4WDo15hozis89kU7ZCJDOPkXuag3v1h9igns/kM6PNBb41dw==
dependencies:
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
"@sentry/types" "6.13.3"
"@sentry/utils" "6.13.3"
tslib "^1.9.3"
"@sentry/minimal@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.13.2.tgz#de3ecc62b9463bf56ccdbcf4c75f7ea1aeeebc11"
integrity sha512-6iJfEvHzzpGBHDfLxSHcGObh73XU1OSQKWjuhDOe7UQDyI4BQmTfcXAC+Fr8sm8C/tIsmpVi/XJhs8cubFdSMw==
"@sentry/minimal@6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.13.3.tgz#a675a79bcc830142e4f95e6198a2efde2cd3901e"
integrity sha512-63MlYYRni3fs5Bh8XBAfVZ+ctDdWg0fapSTP1ydIC37fKvbE+5zhyUqwrEKBIiclEApg1VKX7bkKxVdu/vsFdw==
dependencies:
"@sentry/hub" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/hub" "6.13.3"
"@sentry/types" "6.13.3"
tslib "^1.9.3"
"@sentry/react@^6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.13.2.tgz#481f1549b1509b4d94eb943934ebeba6430a1a8f"
integrity sha512-aLkWyn697LTcmK1PPnUg5UJcyBUPoI68motqgBY53SIYDAwOeYNUQt2aanDuOTY5aE2PdnJwU48klA8vuYkoRQ==
"@sentry/react@^6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.13.3.tgz#f9607e0a60d52efd0baa96a14e694b6059f9379a"
integrity sha512-fdfmD9XNpGDwdkeLyd+iq+kqtNeghpH3wiez2rD81ZBvrn70uKaO2/yYDE71AXC6fUOwQuJmdfAuqBcNJkYIEw==
dependencies:
"@sentry/browser" "6.13.2"
"@sentry/minimal" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
"@sentry/browser" "6.13.3"
"@sentry/minimal" "6.13.3"
"@sentry/types" "6.13.3"
"@sentry/utils" "6.13.3"
hoist-non-react-statics "^3.3.2"
tslib "^1.9.3"
"@sentry/tracing@^6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.13.2.tgz#512389ba459f48ae75e14f1528ab062dc46e4956"
integrity sha512-bHJz+C/nd6biWTNcYAu91JeRilsvVgaye4POkdzWSmD0XoLWHVMrpCQobGpXe7onkp2noU3YQjhqgtBqPHtnpw==
"@sentry/tracing@^6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.13.3.tgz#ca657d4afa99c50f15e638fe38405bac33e780ee"
integrity sha512-yyOFIhqlprPM0g4f35Icear3eZk2mwyYcGEzljJfY2iU6pJwj1lzia5PfSwiCW7jFGMmlBJNhOAIpfhlliZi8Q==
dependencies:
"@sentry/hub" "6.13.2"
"@sentry/minimal" "6.13.2"
"@sentry/types" "6.13.2"
"@sentry/utils" "6.13.2"
"@sentry/hub" "6.13.3"
"@sentry/minimal" "6.13.3"
"@sentry/types" "6.13.3"
"@sentry/utils" "6.13.3"
tslib "^1.9.3"
"@sentry/types@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.13.2.tgz#8388d5b92ea8608936e7aae842801dc90e0184e6"
integrity sha512-6WjGj/VjjN8LZDtqJH5ikeB1o39rO1gYS6anBxiS3d0sXNBb3Ux0pNNDFoBxQpOhmdDHXYS57MEptX9EV82gmg==
"@sentry/types@6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.13.3.tgz#63ad5b6735b0dfd90b3a256a9f8e77b93f0f66b2"
integrity sha512-Vrz5CdhaTRSvCQjSyIFIaV9PodjAVFkzJkTRxyY7P77RcegMsRSsG1yzlvCtA99zG9+e6MfoJOgbOCwuZids5A==
"@sentry/utils@6.13.2":
version "6.13.2"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.13.2.tgz#fb8010e7b67cc8c084d8067d64ef25289269cda5"
integrity sha512-foF4PbxqPMWNbuqdXkdoOmKm3quu3PP7Q7j/0pXkri4DtCuvF/lKY92mbY0V9rHS/phCoj+3/Se5JvM2ymh2/w==
"@sentry/utils@6.13.3":
version "6.13.3"
resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.13.3.tgz#188754d40afe693c3fcae410f9322531588a9926"
integrity sha512-zYFuFH3MaYtBZTeJ4Yajg7pDf0pM3MWs3+9k5my9Fd+eqNcl7dYQYJbT9gyC0HXK1QI4CAMNNlHNl4YXhF91ag==
dependencies:
"@sentry/types" "6.13.2"
"@sentry/types" "6.13.3"
tslib "^1.9.3"
"@sentry/webpack-plugin@^1.17.1":
version "1.17.1"
resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.17.1.tgz#1b3ebbe9991e4d77125ace2b24594059a088268a"
integrity sha512-L47a0hxano4a+9jbvQSBzHCT1Ph8fYAvGGUvFg8qc69yXS9si5lXRNIH/pavN6mqJjhQjAcEsEp+vxgvT4xZDQ==
"@sentry/webpack-plugin@^1.18.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@sentry/webpack-plugin/-/webpack-plugin-1.18.0.tgz#45bc0c2afe1bbabac777f51af6a634c557ea4888"
integrity sha512-wO6QECiRkvh66TQh1/qUgxCwi8WSB4XF8o5fGTZS+jzOye4TKOGHwnzNQ3ZkIW14U6yTq2cr1e8nRfcGXm+EyA==
dependencies:
"@sentry/cli" "^1.68.0"
@@ -2293,17 +2293,17 @@
resolved "https://registry.yarnpkg.com/@sphinxxxx/color-conversion/-/color-conversion-2.2.2.tgz#03ecc29279e3c0c832f6185a5bfa3497858ac8ca"
integrity sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw==
"@stripe/react-stripe-js@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.5.0.tgz#7e4d80077e88e1f2c1f10ac255f2838d7c9488c2"
integrity sha512-A7+bNeb0O/kw3JdtMeiB6frokPcks5obi+TIjuFRXUMZ5o/o1Qe7eLgLnsb0KOO/g3KJqNCpHiYcKCLESZJJbQ==
"@stripe/react-stripe-js@^1.6.0":
version "1.6.0"
resolved "https://registry.yarnpkg.com/@stripe/react-stripe-js/-/react-stripe-js-1.6.0.tgz#e3adf6a6ea6d839193164fa3cfe73cf52db3a080"
integrity sha512-tMmsPD+wkpiiVJZgQ1E06tklG5MZHG462s6OWja9abpxq76kerAxMFN+KdhUg0LIEY79THbzvH3s/WGHasnV3w==
dependencies:
prop-types "^15.7.2"
"@stripe/stripe-js@^1.18.0":
version "1.18.0"
resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.18.0.tgz#687268d7cd68b44b92b86300d7c7f2a6e4df0b98"
integrity sha512-yBRHAMKHnF3kbzv0tpKB82kSow43wW5qXLK8ofg3V9NaaCyObSTO7wJfktWAtG/NBgkJOdUL+pV8dHBj0qvDkQ==
"@stripe/stripe-js@^1.19.1":
version "1.19.1"
resolved "https://registry.yarnpkg.com/@stripe/stripe-js/-/stripe-js-1.19.1.tgz#51017bb1c6e12f0e74747534667e42e77b2c9978"
integrity sha512-gvaQ51FXHHKMypXMlSPZbpb7e5671oqySqEfU2MviAQCsikV/+vnvPPxOged4RvNwNM7v4ocsKadQwqIwPhgrQ==
"@surma/rollup-plugin-off-main-thread@^1.1.1":
version "1.4.2"
@@ -2416,15 +2416,15 @@
"@svgr/plugin-svgo" "^5.5.0"
loader-utils "^2.0.0"
"@tanem/react-nprogress@^3.0.79":
version "3.0.79"
resolved "https://registry.yarnpkg.com/@tanem/react-nprogress/-/react-nprogress-3.0.79.tgz#6b9b90fbe574d171a5c885262110e250e53ece33"
integrity sha512-xIwebE5GmqLSVRHalnOeCpsXRwlrXHbodaCp97LHbYESCBsLDumkGdRU8cmnHFnNK8IaJ2T0EBJXmbSAWLuh8Q==
"@tanem/react-nprogress@^3.0.80":
version "3.0.80"
resolved "https://registry.yarnpkg.com/@tanem/react-nprogress/-/react-nprogress-3.0.80.tgz#a0ef56231b051cc84e40e1c7e25d20954f1589ed"
integrity sha512-762eLjDbYcVy2g7YktqPyzLJ1iFRSt8W+ldJXoFIAetu1SR9e44XCuOn/Mg6IItMNvfEUrFyAi18zGyhChySww==
dependencies:
"@babel/runtime" "^7.15.3"
"@babel/runtime" "^7.15.4"
hoist-non-react-statics "^3.3.2"
prop-types "^15.7.2"
react-use "^17.2.4"
react-use "^17.3.1"
"@tootallnate/once@1":
version "1.1.2"
@@ -3492,12 +3492,12 @@ axe-core@^4.0.2:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.3.3.tgz#b55cd8e8ddf659fe89b064680e1c6a4dceab0325"
integrity sha512-/lqqLAmuIPi79WYfRpy2i8z+x+vxU3zX2uAm0gs1q52qTuKwolOj1P8XbufpXcsydrpKx2yGn2wzAnxCMV86QA==
axios@^0.21.4:
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
axios@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.23.0.tgz#b0fa5d0948a8d1d75e3d5635238b6c4625b05149"
integrity sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==
dependencies:
follow-redirects "^1.14.0"
follow-redirects "^1.14.4"
axobject-query@^2.2.0:
version "2.2.0"
@@ -5305,10 +5305,10 @@ diffie-hellman@^5.0.0:
miller-rabin "^4.0.0"
randombytes "^2.0.0"
dinero.js@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/dinero.js/-/dinero.js-1.9.0.tgz#15cd6b8290538077cf80c35f4a26884d8806050f"
integrity sha512-gbDFhCCe/ba9pU2P232FS54LFPCLeGTb8vcrgsjmXHknu/VDHIgFecA8mxLYQsqVKkHoHSCUq95ojYOakzuweA==
dinero.js@^1.9.1:
version "1.9.1"
resolved "https://registry.yarnpkg.com/dinero.js/-/dinero.js-1.9.1.tgz#64b10ce7277a07805dac9c8cd6500e9b7d0aee96"
integrity sha512-1HXiF2vv3ZeRQ23yr+9lFxj/PbZqutuYWJnE0qfCB9xYBPnuaJ8lXtli1cJM0TvUXW1JTOaePldmqN5JVNxKSA==
dir-glob@^3.0.1:
version "3.0.1"
@@ -6367,20 +6367,20 @@ find-yarn-workspace-root@^2.0.0:
dependencies:
micromatch "^4.0.2"
firebase@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/firebase/-/firebase-9.1.0.tgz#f284634ae4f4e7c789ff36494f4534cba5dffbf2"
integrity sha512-Pj9/FwNzT4pdSS6vpXZzm4mFscI73N+AH70gaWZPnZrQBvyMAPTuKXXscjrFePPlqs94b4Emq+2mSwLGcwod/A==
firebase@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/firebase/-/firebase-9.1.2.tgz#21555fcdde10f38e7e3e74488a4a587a7d88502e"
integrity sha512-lLccGDhOosNhCXuywyGQ7ICJvcXoCRu4UUUyS42kMU3JYDNvxGhJX5DWtTQ4W+c/jZm444dVpJVK7QHS98XNqg==
dependencies:
"@firebase/analytics" "0.7.1"
"@firebase/analytics-compat" "0.1.2"
"@firebase/app" "0.7.1"
"@firebase/app-check" "0.4.1"
"@firebase/app-check-compat" "0.1.2"
"@firebase/app-compat" "0.1.2"
"@firebase/app" "0.7.3"
"@firebase/app-check" "0.4.2"
"@firebase/app-check-compat" "0.1.3"
"@firebase/app-compat" "0.1.4"
"@firebase/app-types" "0.7.0"
"@firebase/auth" "0.18.0"
"@firebase/auth-compat" "0.1.3"
"@firebase/auth" "0.18.2"
"@firebase/auth-compat" "0.1.5"
"@firebase/database" "0.12.1"
"@firebase/database-compat" "0.1.1"
"@firebase/firestore" "3.1.0"
@@ -6437,11 +6437,16 @@ flush-write-stream@^1.0.0:
inherits "^2.0.3"
readable-stream "^2.3.6"
follow-redirects@^1.0.0, follow-redirects@^1.14.0:
follow-redirects@^1.0.0:
version "1.14.3"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.3.tgz#6ada78118d8d24caee595595accdc0ac6abd022e"
integrity sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw==
follow-redirects@^1.14.4:
version "1.14.4"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.4.tgz#838fdf48a8bbdd79e52ee51fb1c94e3ed98b9379"
integrity sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==
for-in@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
@@ -6731,10 +6736,10 @@ graphql-tag@^2.12.3:
dependencies:
tslib "^2.1.0"
graphql@^15.6.0:
version "15.6.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.6.0.tgz#e69323c6a9780a1a4b9ddf7e35ca8904bb04df02"
integrity sha512-WJR872Zlc9hckiEPhXgyUftXH48jp2EjO5tgBBOyNMRJZ9fviL2mJBD6CAysk6N5S0r9BTs09Qk39nnJBkvOXQ==
graphql@^15.6.1:
version "15.6.1"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.6.1.tgz#9125bdf057553525da251e19e96dab3d3855ddfc"
integrity sha512-3i5lu0z6dRvJ48QP9kFxBkJ7h4Kso7PS8eahyTFz5Jm6CvQfLtNIE8LX9N6JLnXTuwR+sIYnXzaWp6anOg0QQw==
growly@^1.3.0:
version "1.3.0"
@@ -7088,10 +7093,10 @@ i18next-browser-languagedetector@^6.1.2:
dependencies:
"@babel/runtime" "^7.14.6"
i18next@^21.1.1:
version "21.1.1"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.1.1.tgz#e7569de4d9fea2972c28ca4c334d13799b94ce76"
integrity sha512-oBEi+3MI/jEv0DifAmA+e47WAS55Sv6yG2CmZ0Kpz/VGu8rTQARJGRkwhMcLhcIi+JYmxmfBD/DQ/7Ho3FYryw==
i18next@^21.3.0:
version "21.3.0"
resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.3.0.tgz#679b9bdc27a26ccca4799436cf2195107ad6feeb"
integrity sha512-MiarmWb/a+5z8C7QvihkcJf2YofuyhGvH28Wlip/c1YTSvHijYBFmc7dH6RrNkc2O44ApTdHnkK4FaM/S33C0w==
dependencies:
"@babel/runtime" "^7.12.0"
@@ -8494,10 +8499,10 @@ levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
libphonenumber-js@^1.9.34:
version "1.9.34"
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.9.34.tgz#ddddc778a9b2f53c70500fcf10c9483596e3574f"
integrity sha512-gHTNU9xTtVgSp30IDX/57W4pETMXDIYXFfwEOJVXiYosiY7Hc7ogJwlBjOqlCcU04X0aA8DT57hdwUC1sJBJnA==
libphonenumber-js@^1.9.37:
version "1.9.37"
resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.9.37.tgz#944f59a3618a8f85d9b619767a0b6fb87523f285"
integrity sha512-RnUR4XwiVhMLnT7uFSdnmLeprspquuDtaShAgKTA+g/ms9/S4hQU3/QpFdh3iXPHtxD52QscXLm2W2+QBmvYAg==
lie@~3.3.0:
version "3.3.0"
@@ -8656,10 +8661,10 @@ loglevel@^1.6.8:
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.1.tgz#005fde2f5e6e47068f935ff28573e125ef72f197"
integrity sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==
logrocket@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/logrocket/-/logrocket-2.0.0.tgz#331065873429cf70fb7cf84b676900baf9988a4e"
integrity sha512-O+YdrtpQn7oOmrxCqOyUcaB1+ONrhyJuB9CX57PQ0JJzNrYstxd0Oyg6UdLisA7UjNmwTr6fixMO3WOysDTFFA==
logrocket@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/logrocket/-/logrocket-2.1.0.tgz#f62a2e0fbdb32f8350d19ee1ee1dc4e67a79ce8d"
integrity sha512-TAL4OlwNt3ZH0P7yZf8Aw0VjRzYussYi/BMjK14ee0gKu1IIinrdRGuci3LV3BKvYyIm64pL7Cbe/z1HREVm0Q==
long@^4.0.0:
version "4.0.0"
@@ -8735,10 +8740,10 @@ map-visit@^1.0.0:
dependencies:
object-visit "^1.0.0"
markerjs2@^2.12.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/markerjs2/-/markerjs2-2.12.0.tgz#07cd918d9185991e219c16b54fd66020d58a34ea"
integrity sha512-7lo5HFA9ehHnyzii8QcvuZWqHpfI6KEIr5lmbFiaEvyA9uW2ZbyNuVzMR4rkgfyJuIvdITqNmyQbd5j8eZHWiQ==
markerjs2@^2.14.0:
version "2.14.0"
resolved "https://registry.yarnpkg.com/markerjs2/-/markerjs2-2.14.0.tgz#f10e95edd3c5b3087de58b9dd4a31faf92a36447"
integrity sha512-pAta3DaynP3dBYVqmJCSct7qGZSXhN/tXyB9qvwu4/Cfo/luxNXxz4iFQozT7GgR6q48p7S3831v9q9Sex40Ig==
material-colors@^1.2.1:
version "1.2.6"
@@ -9156,6 +9161,13 @@ node-fetch@2.6.2:
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.2.tgz#986996818b73785e47b1965cc34eb093a1d464d0"
integrity sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA==
node-fetch@2.6.5:
version "2.6.5"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.5.tgz#42735537d7f080a7e5f78b6c549b7146be1742fd"
integrity sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==
dependencies:
whatwg-url "^5.0.0"
node-fetch@^2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
@@ -11286,10 +11298,10 @@ react-beautiful-dnd@^13.0.0:
redux "^4.0.4"
use-memo-one "^1.1.1"
react-big-calendar@^0.35.0:
version "0.35.0"
resolved "https://registry.yarnpkg.com/react-big-calendar/-/react-big-calendar-0.35.0.tgz#4bf927ab488ba1f7f3a1ea0b1b19a3bee5776b2b"
integrity sha512-2jjPhfKRM6ka3pdzdqqYUPLEgoeyyP5ICPhgUZBitozM3nskz7B3tNaLpqNgTWCaAc7KJbe2TJiqCcCbHiZtRA==
react-big-calendar@^0.36.1:
version "0.36.1"
resolved "https://registry.yarnpkg.com/react-big-calendar/-/react-big-calendar-0.36.1.tgz#3a74db72dc293de899759e01bfb72ec1715f8787"
integrity sha512-pzg8X/Tc1szg//KoV2GP9YnPPRhE3uCIXSP10Jlr46jMcBiMZ/wP7WGhpgaGVKEL30rR/BDLz7rhXaAYDX/UuQ==
dependencies:
"@babel/runtime" "^7.1.5"
clsx "^1.0.4"
@@ -11412,10 +11424,10 @@ react-i18next@^11.12.0:
"@babel/runtime" "^7.14.5"
html-parse-stringify "^3.0.1"
react-icons@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.2.0.tgz#6dda80c8a8f338ff96a1851424d63083282630d0"
integrity sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==
react-icons@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.3.1.tgz#2fa92aebbbc71f43d2db2ed1aed07361124e91ca"
integrity sha512-cB10MXLTs3gVuXimblAdI71jrJx8njrJZmNMEMC+sQu5B/BIOmlsAjskdqpn81y8UBVEGuHODd7/ci5DvoSzTQ==
react-images@^0.5.16:
version "0.5.19"
@@ -11655,7 +11667,7 @@ react-universal-interface@^0.6.2:
resolved "https://registry.yarnpkg.com/react-universal-interface/-/react-universal-interface-0.6.2.tgz#5e8d438a01729a4dbbcbeeceb0b86be146fe2b3b"
integrity sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==
react-use@^17.2.4:
react-use@^17.3.1:
version "17.3.1"
resolved "https://registry.yarnpkg.com/react-use/-/react-use-17.3.1.tgz#12b248555775519aa2b900b22f1928d029bf99d1"
integrity sha512-hs7+tS4rRm1QLHPfanLCqXIi632tP4V7Sai1ENUP2WTufU6am++tU9uSw9YrNCFqbABiEv0ndKU1XCUcfu2tXA==
@@ -13478,6 +13490,11 @@ tr46@^2.1.0:
dependencies:
punycode "^2.1.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
tryer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
@@ -13986,10 +14003,15 @@ wbuf@^1.1.0, wbuf@^1.7.3:
dependencies:
minimalistic-assert "^1.0.0"
web-vitals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.0.tgz#ebf5428875ab5bfc1056c2e80cd177001287de7b"
integrity sha512-npEyJP8jHf3J71t1tRTEtz9FeKp8H2udWJUUq5ykfPhhstr//TUxiYhIEzLNwk4zv2ybAilMn7v7N6Mxmuitmg==
web-vitals@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.2.tgz#3a6c8faebf9097a6ccd17f5f45c9485d8d62dab1"
integrity sha512-nZnEH8dj+vJFqCRYdvYv0a59iLXsb8jJkt+xvXfwgnkyPdsSLtKNlYmtTDiHmTNGXeSXtpjTTUcNvFtrAk6VMQ==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
webidl-conversions@^5.0.0:
version "5.0.0"
@@ -14157,6 +14179,14 @@ whatwg-mimetype@^2.3.0:
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
whatwg-url@^8.0.0, whatwg-url@^8.5.0:
version "8.7.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"

View File

@@ -2581,6 +2581,7 @@
- date_estimated
- date_exported
- date_invoiced
- date_last_contacted
- date_open
- date_scheduled
- ded_amt
@@ -2716,6 +2717,7 @@
- rate_mash
- rate_matd
- referral_source
- referral_source_extra
- regie_number
- ro_number
- scheduled_completion
@@ -2828,6 +2830,7 @@
- date_estimated
- date_exported
- date_invoiced
- date_last_contacted
- date_open
- date_scheduled
- ded_amt
@@ -2963,6 +2966,7 @@
- rate_mash
- rate_matd
- referral_source
- referral_source_extra
- regie_number
- ro_number
- scheduled_completion
@@ -3085,6 +3089,7 @@
- date_estimated
- date_exported
- date_invoiced
- date_last_contacted
- date_open
- date_scheduled
- ded_amt
@@ -3220,6 +3225,7 @@
- rate_mash
- rate_matd
- referral_source
- referral_source_extra
- regie_number
- ro_number
- scheduled_completion
@@ -3779,6 +3785,7 @@
- active:
_eq: true
columns:
- comments
- created_at
- deliver_by
- id
@@ -3796,6 +3803,7 @@
- role: user
permission:
columns:
- comments
- created_at
- deliver_by
- id
@@ -3823,6 +3831,7 @@
- role: user
permission:
columns:
- comments
- created_at
- deliver_by
- id

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"."jobs" add column "referral_soure_other" text
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "referral_soure_other" text
null;

View File

@@ -0,0 +1 @@
alter table "public"."jobs" rename column "referral_source_other" to "referral_soure_other";

View File

@@ -0,0 +1 @@
alter table "public"."jobs" rename column "referral_soure_other" to "referral_source_other";

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"."parts_orders" add column "comments" text
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."parts_orders" add column "comments" text
null;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" alter column "referral_source_other" drop not null;
alter table "public"."jobs" add column "referral_source_other" text;

View File

@@ -0,0 +1 @@
alter table "public"."jobs" drop column "referral_source_other" cascade;

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"."jobs" add column "referral_source_other" text
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "referral_source_other" text
null;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" alter column "referral_source_other" drop not null;
alter table "public"."jobs" add column "referral_source_other" text;

View File

@@ -0,0 +1 @@
alter table "public"."jobs" drop column "referral_source_other" cascade;

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"."jobs" add column "referral_source_extra" text
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "referral_source_extra" text
null;

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"."jobs" add column "date_last_contacted" timestamptz
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "date_last_contacted" timestamptz
null;

View File

@@ -0,0 +1,51 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- CREATE
-- OR REPLACE FUNCTION public.search_owners (search text) RETURNS SETOF owners LANGUAGE plpgsql STABLE AS $function$
-- BEGIN
-- IF search = ''
-- THEN
-- RETURN query
-- SELECT
-- *
-- FROM
-- owners;
-- ELSE
-- RETURN query
-- SELECT
-- *
-- FROM
-- owners
-- WHERE
-- (
-- ownr_fn || ' ' || ownr_ln
-- )
-- ILIKE '%' || search || '%'
-- OR ownr_ln ILIKE '%' || search || '%'
-- OR ownr_fn ILIKE '%' || search || '%'
-- OR ownr_fn ILIKE '%' || search || '%'
-- OR ownr_co_nm ILIKE '%' || search || '%'
-- OR ownr_ph1 ILIKE '%' || search || '%'
-- OR ownr_ph2 ILIKE '%' || search || '%'
-- OR ownr_addr1 ILIKE '%' || search || '%'
-- ORDER BY
-- (ownr_fn || ' ' || ownr_ln) ILIKE '%' || search || '%'
-- OR NULL,
-- ownr_ln ILIKE '%' || search || '%'
-- OR NULL,
-- ownr_fn ILIKE '%' || search || '%'
-- OR NULL,
-- ownr_co_nm ILIKE '%' || search || '%'
-- OR NULL,
-- ownr_fn ILIKE '%' || search || '%'
-- OR NULL,
-- ownr_ph1 ILIKE '%' || search || '%'
-- OR NULL,
-- ownr_ph2 ILIKE '%' || search || '%'
-- OR NULL,
-- ownr_addr1 ILIKE '%' || search || '%'
-- OR NULL;
-- END
-- IF;
-- END
-- $function$;

View File

@@ -0,0 +1,49 @@
CREATE
OR REPLACE FUNCTION public.search_owners (search text) RETURNS SETOF owners LANGUAGE plpgsql STABLE AS $function$
BEGIN
IF search = ''
THEN
RETURN query
SELECT
*
FROM
owners;
ELSE
RETURN query
SELECT
*
FROM
owners
WHERE
(
ownr_fn || ' ' || ownr_ln
)
ILIKE '%' || search || '%'
OR ownr_ln ILIKE '%' || search || '%'
OR ownr_fn ILIKE '%' || search || '%'
OR ownr_fn ILIKE '%' || search || '%'
OR ownr_co_nm ILIKE '%' || search || '%'
OR ownr_ph1 ILIKE '%' || search || '%'
OR ownr_ph2 ILIKE '%' || search || '%'
OR ownr_addr1 ILIKE '%' || search || '%'
ORDER BY
(ownr_fn || ' ' || ownr_ln) ILIKE '%' || search || '%'
OR NULL,
ownr_ln ILIKE '%' || search || '%'
OR NULL,
ownr_fn ILIKE '%' || search || '%'
OR NULL,
ownr_co_nm ILIKE '%' || search || '%'
OR NULL,
ownr_fn ILIKE '%' || search || '%'
OR NULL,
ownr_ph1 ILIKE '%' || search || '%'
OR NULL,
ownr_ph2 ILIKE '%' || search || '%'
OR NULL,
ownr_addr1 ILIKE '%' || search || '%'
OR NULL;
END
IF;
END
$function$;

2561
logs/oAuthClient-log.log Normal file

File diff suppressed because it is too large Load Diff

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