Compare commits
54 Commits
feature/cd
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bb8eee384 | ||
|
|
85d79a8d7f | ||
|
|
e73d082eab | ||
|
|
2637538d9a | ||
|
|
eb58274f90 | ||
|
|
aa410d6847 | ||
|
|
97f1be9d6f | ||
|
|
8ec5bc049b | ||
|
|
1f2bec06ef | ||
|
|
1cad57bec2 | ||
|
|
10f3c01677 | ||
|
|
fc68b669db | ||
|
|
6e22091b81 | ||
|
|
545db54c14 | ||
|
|
aa69fef9ba | ||
|
|
1e30642d28 | ||
|
|
c1dfba949e | ||
|
|
dfa9592755 | ||
|
|
8f2b1f0f78 | ||
|
|
cf91ec14c0 | ||
|
|
dfe0f99bea | ||
|
|
591022c097 | ||
|
|
c76da54b93 | ||
|
|
186f6101ff | ||
|
|
e95cf0a026 | ||
|
|
3eaa3a0189 | ||
|
|
0ba445aad2 | ||
|
|
637c718b05 | ||
|
|
a01019b1b3 | ||
|
|
f6e2393a40 | ||
|
|
715857a587 | ||
|
|
186ad2d7a2 | ||
|
|
c64c49ab6e | ||
|
|
3e067e2103 | ||
|
|
4cc1f77b14 | ||
|
|
334dd5fe94 | ||
|
|
d73f37cacc | ||
|
|
c6a7e3dcb1 | ||
|
|
4bdc02d22c | ||
|
|
afa8e04008 | ||
|
|
990c1bb2bf | ||
|
|
a5a59c526c | ||
|
|
2d5bef4b7b | ||
|
|
5893b1e3b3 | ||
|
|
0af452b8a4 | ||
|
|
3d82198c90 | ||
|
|
01bca360c7 | ||
|
|
59e994ac29 | ||
|
|
d5f3105341 | ||
|
|
92920f69d4 | ||
|
|
61ac520192 | ||
|
|
45176cc2e2 | ||
|
|
7a515c35d2 | ||
|
|
1942103985 |
@@ -1369,6 +1369,69 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>jobnoteadded</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>jobnotedeleted</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>jobnoteupdated</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>jobspartsorder</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -2779,6 +2842,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>savewithdiscrepancy</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>state_tax</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -8145,6 +8229,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>qbo</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>rbac</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -11095,6 +11200,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>sold</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>
|
||||
@@ -11267,6 +11393,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>created_at</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>
|
||||
@@ -32449,6 +32596,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>csi_invitation_action</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>diagnostic_authorization</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -33079,6 +33247,48 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>sgi_certificate_of_repairs</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>sgi_windshield_auth</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>stolen_recovery_checklist</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -33621,6 +33831,37 @@
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>subjects</name>
|
||||
<children>
|
||||
<folder_node>
|
||||
<name>jobs</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>parts_order</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
</children>
|
||||
</folder_node>
|
||||
<folder_node>
|
||||
<name>vendors</name>
|
||||
<children>
|
||||
@@ -34503,6 +34744,116 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<folder_node>
|
||||
<name>groups</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>customers</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>jobs</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>payroll</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>purchases</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>sales</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>
|
||||
<concept_node>
|
||||
<name>key</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34569,6 +34920,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>csi</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>exportlogs</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -34828,6 +35200,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>csi</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>estimator_detail</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
"private": true,
|
||||
"proxy": "http://localhost:5000",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.4.10",
|
||||
"@craco/craco": "^6.2.0",
|
||||
"@apollo/client": "^3.4.14",
|
||||
"@craco/craco": "^6.3.0",
|
||||
"@fingerprintjs/fingerprintjs": "^3.3.0",
|
||||
"@lourenci/react-kanban": "^2.1.0",
|
||||
"@openreplay/tracker": "^3.3.1",
|
||||
"@openreplay/tracker-assist": "^3.1.1",
|
||||
"@openreplay/tracker": "^3.4.0",
|
||||
"@openreplay/tracker-assist": "^3.4.0",
|
||||
"@openreplay/tracker-graphql": "^3.0.0",
|
||||
"@openreplay/tracker-redux": "^3.0.0",
|
||||
"@sentry/react": "^6.11.0",
|
||||
"@sentry/tracing": "^6.11.0",
|
||||
"@stripe/react-stripe-js": "^1.4.0",
|
||||
"@stripe/stripe-js": "^1.17.1",
|
||||
"@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",
|
||||
"antd": "^4.16.13",
|
||||
"apollo-link-logger": "^2.0.0",
|
||||
@@ -26,17 +26,17 @@
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^9.0.0",
|
||||
"graphql": "^15.5.3",
|
||||
"i18next": "^20.4.0",
|
||||
"firebase": "^9.1.0",
|
||||
"graphql": "^15.6.0",
|
||||
"i18next": "^21.1.1",
|
||||
"i18next-browser-languagedetector": "^6.1.2",
|
||||
"jsoneditor": "^9.5.4",
|
||||
"jsoneditor": "^9.5.6",
|
||||
"jsreport-browser-client-dist": "^1.3.0",
|
||||
"libphonenumber-js": "^1.9.26",
|
||||
"libphonenumber-js": "^1.9.34",
|
||||
"logrocket": "^2.0.0",
|
||||
"markerjs2": "^2.11.2",
|
||||
"markerjs2": "^2.12.0",
|
||||
"moment-business-days": "^1.2.0",
|
||||
"phone": "^3.1.6",
|
||||
"phone": "^3.1.8",
|
||||
"preval.macro": "^5.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
"query-string": "^7.0.1",
|
||||
@@ -50,7 +50,7 @@
|
||||
"react-drag-listview": "^0.1.8",
|
||||
"react-grid-gallery": "^0.5.5",
|
||||
"react-grid-layout": "^1.3.0",
|
||||
"react-i18next": "^11.11.4",
|
||||
"react-i18next": "^11.12.0",
|
||||
"react-icons": "^4.2.0",
|
||||
"react-number-format": "^4.7.3",
|
||||
"react-redux": "^7.2.5",
|
||||
@@ -59,29 +59,29 @@
|
||||
"react-scripts": "^4.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"recharts": "^2.1.2",
|
||||
"recharts": "^2.1.4",
|
||||
"redux": "^4.1.1",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.1.3",
|
||||
"redux-state-sync": "^3.1.2",
|
||||
"reselect": "^4.0.0",
|
||||
"sass": "^1.38.2",
|
||||
"sass": "^1.42.1",
|
||||
"socket.io-client": "^4.2.0",
|
||||
"styled-components": "^5.3.1",
|
||||
"subscriptions-transport-ws": "^0.9.18",
|
||||
"web-vitals": "^2.1.0",
|
||||
"workbox-background-sync": "^6.2.4",
|
||||
"workbox-broadcast-update": "^6.2.4",
|
||||
"workbox-cacheable-response": "^6.2.4",
|
||||
"workbox-core": "^6.2.4",
|
||||
"workbox-expiration": "^6.2.4",
|
||||
"workbox-google-analytics": "^6.2.4",
|
||||
"workbox-navigation-preload": "^6.2.4",
|
||||
"workbox-precaching": "^6.2.4",
|
||||
"workbox-range-requests": "^6.2.4",
|
||||
"workbox-routing": "^6.2.4",
|
||||
"workbox-strategies": "^6.2.4",
|
||||
"workbox-streams": "^6.2.4"
|
||||
"workbox-background-sync": "^6.3.0",
|
||||
"workbox-broadcast-update": "^6.3.0",
|
||||
"workbox-cacheable-response": "^6.3.0",
|
||||
"workbox-core": "^6.3.0",
|
||||
"workbox-expiration": "^6.3.0",
|
||||
"workbox-google-analytics": "^6.3.0",
|
||||
"workbox-navigation-preload": "^6.3.0",
|
||||
"workbox-precaching": "^6.3.0",
|
||||
"workbox-range-requests": "^6.3.0",
|
||||
"workbox-routing": "^6.3.0",
|
||||
"workbox-strategies": "^6.3.0",
|
||||
"workbox-streams": "^6.3.0"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "patch-package",
|
||||
|
||||
@@ -12,6 +12,7 @@ import trackerGraphQL from "@openreplay/tracker-graphql";
|
||||
//import trackerRedux from "@openreplay/tracker-redux";
|
||||
import Tracker from "@openreplay/tracker";
|
||||
//import trackerAssist from "@openreplay/tracker-assist";
|
||||
import { getCurrentUser } from "../firebase/firebase.utils";
|
||||
moment.locale("en-US");
|
||||
|
||||
export const tracker = new Tracker({
|
||||
@@ -21,7 +22,11 @@ export const tracker = new Tracker({
|
||||
? { __DISABLE_SECURE_MODE: true }
|
||||
: {}),
|
||||
// beaconSize: 10485760,
|
||||
onStart: ({ sessionID }) => console.log("ORS SESSION ", sessionID),
|
||||
onStart: async ({ sessionID }) => {
|
||||
const user = await getCurrentUser();
|
||||
tracker.setUserID(user.email);
|
||||
console.log("ORS SESSION ", sessionID, user.email);
|
||||
},
|
||||
});
|
||||
|
||||
// tracker.use(
|
||||
|
||||
24
client/src/assets/C2QB_composite_English.svg
Normal file
|
After Width: | Height: | Size: 51 KiB |
24
client/src/assets/C2QB_transparent_English.svg
Normal file
|
After Width: | Height: | Size: 51 KiB |
4
client/src/assets/qbo/C2QB_green_btn_med_default.svg
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
5
client/src/assets/qbo/C2QB_green_btn_med_hover.svg
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
4
client/src/assets/qbo/C2QB_green_btn_short_default.svg
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
5
client/src/assets/qbo/C2QB_green_btn_short_hover.svg
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
4
client/src/assets/qbo/C2QB_green_btn_tall_default.svg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
5
client/src/assets/qbo/C2QB_green_btn_tall_hover.svg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
5
client/src/assets/qbo/C2QB_transparent_btn_med_hover.svg
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
@@ -9,8 +9,25 @@ import PayableExportAll from "../payable-export-all-button/payable-export-all-bu
|
||||
import { DateFormatter } from "../../utils/DateFormatter";
|
||||
import queryString from "query-string";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
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({ loading, bills }) {
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(AccountingPayablesTableComponent);
|
||||
|
||||
export function AccountingPayablesTableComponent({ bodyshop, loading, bills }) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedBills, setSelectedBills] = useState([]);
|
||||
const [transInProgress, setTransInProgress] = useState(false);
|
||||
@@ -166,6 +183,9 @@ export default function AccountingPayablesTableComponent({ loading, bills }) {
|
||||
loadingCallback={setTransInProgress}
|
||||
completedCallback={setSelectedBills}
|
||||
/>
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
)}
|
||||
<Input
|
||||
value={state.search}
|
||||
onChange={handleSearch}
|
||||
|
||||
@@ -11,6 +11,7 @@ import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-butto
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
@@ -206,6 +207,9 @@ export function AccountingReceivablesTableComponent({
|
||||
completedCallback={setSelectedJobs}
|
||||
/>
|
||||
)}
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
)}
|
||||
<Input.Search
|
||||
value={state.search}
|
||||
onChange={handleSearch}
|
||||
|
||||
@@ -18,8 +18,10 @@ import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import confirmDialog from "../../utils/asyncConfirm";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import BillFormContainer from "../bill-form/bill-form.container";
|
||||
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
||||
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -48,7 +50,31 @@ function BillEnterModalContainer({
|
||||
const [loading, setLoading] = useState(false);
|
||||
const client = useApolloClient();
|
||||
|
||||
const formValues = useMemo(() => {
|
||||
return {
|
||||
...billEnterModal.context.bill,
|
||||
jobid:
|
||||
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
||||
federal_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.federal_tax_rate) ||
|
||||
0,
|
||||
state_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.state_tax_rate) ||
|
||||
0,
|
||||
local_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.local_tax_rate) ||
|
||||
0,
|
||||
};
|
||||
}, [billEnterModal, bodyshop]);
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
let totals = CalculateBillTotal(values);
|
||||
if (totals.discrepancy.getAmount() !== 0) {
|
||||
if (!(await confirmDialog(t("bills.labels.savewithdiscrepancy")))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setLoading(true);
|
||||
const { upload, location, ...remainingValues } = values;
|
||||
|
||||
@@ -190,7 +216,7 @@ function BillEnterModalContainer({
|
||||
|
||||
if (enterAgain) {
|
||||
form.resetFields();
|
||||
form.setFieldsValue({ billlines: [] });
|
||||
form.setFieldsValue(formValues);
|
||||
} else {
|
||||
toggleModalVisible();
|
||||
}
|
||||
@@ -208,23 +234,6 @@ function BillEnterModalContainer({
|
||||
if (enterAgain) form.submit();
|
||||
}, [enterAgain, form]);
|
||||
|
||||
const formValues = useMemo(() => {
|
||||
return {
|
||||
...billEnterModal.context.bill,
|
||||
jobid:
|
||||
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
||||
federal_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.federal_tax_rate) ||
|
||||
0,
|
||||
state_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.state_tax_rate) ||
|
||||
0,
|
||||
local_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.local_tax_rate) ||
|
||||
0,
|
||||
};
|
||||
}, [billEnterModal, bodyshop]);
|
||||
|
||||
useEffect(() => {
|
||||
if (billEnterModal.visible) {
|
||||
form.setFieldsValue(formValues);
|
||||
|
||||
@@ -13,6 +13,7 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => {
|
||||
ref={ref}
|
||||
showSearch
|
||||
optionFilterProp="line_desc"
|
||||
notFoundContent={"Removed."}
|
||||
{...restProps}
|
||||
>
|
||||
<Select.Option key={null} value={"noline"} cost={0} line_desc={""}>
|
||||
@@ -21,14 +22,18 @@ const BillLineSearchSelect = ({ options, disabled, ...restProps }, ref) => {
|
||||
{options
|
||||
? options.map((item) => (
|
||||
<Option
|
||||
disabled={item.removed}
|
||||
key={item.id}
|
||||
value={item.id}
|
||||
cost={item.act_price ? item.act_price : 0}
|
||||
part_type={item.part_type}
|
||||
line_desc={item.line_desc}
|
||||
part_qty={item.part_qty}
|
||||
style={{
|
||||
...(item.removed ? { textDecoration: "line-through" } : {}),
|
||||
}}
|
||||
>
|
||||
{`${item.line_desc}${
|
||||
{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
||||
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
||||
}`}
|
||||
</Option>
|
||||
|
||||
@@ -8,6 +8,7 @@ import { selectSelectedConversation } from "../../redux/messaging/messaging.sele
|
||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||
import "./chat-conversation-list.styles.scss";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
selectedConversation: selectSelectedConversation,
|
||||
@@ -60,13 +61,18 @@ export function ChatConversationListComponent({
|
||||
) : (
|
||||
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
||||
)}
|
||||
{item.job_conversations.length > 0
|
||||
? item.job_conversations.map((j, idx) => (
|
||||
<Tag key={idx} className="ro-number-tag">
|
||||
{j.job.ro_number}
|
||||
</Tag>
|
||||
))
|
||||
: null}
|
||||
<div sryle={{ display: "inline-block" }}>
|
||||
<div>
|
||||
{item.job_conversations.length > 0
|
||||
? item.job_conversations.map((j, idx) => (
|
||||
<Tag key={idx} className="ro-number-tag">
|
||||
{j.job.ro_number}
|
||||
</Tag>
|
||||
))
|
||||
: null}
|
||||
</div>
|
||||
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
|
||||
</div>
|
||||
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
||||
</List.Item>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Icon from "@ant-design/icons";
|
||||
import { Tooltip } from "antd";
|
||||
import i18n from "i18next";
|
||||
import moment from "moment";
|
||||
import React, { useEffect, useRef } from "react";
|
||||
@@ -9,6 +10,7 @@ import {
|
||||
CellMeasurerCache,
|
||||
List,
|
||||
} from "react-virtualized";
|
||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import "./chat-message-list.styles.scss";
|
||||
|
||||
export default function ChatMessageListComponent({ messages }) {
|
||||
@@ -85,17 +87,22 @@ export default function ChatMessageListComponent({ messages }) {
|
||||
|
||||
const MessageRender = (message) => {
|
||||
return (
|
||||
<div>
|
||||
{message.image_path &&
|
||||
message.image_path.map((i, idx) => (
|
||||
<div key={idx} style={{ display: "flex", justifyContent: "center" }}>
|
||||
<a href={i} target="__blank">
|
||||
<img alt="Received" className="message-img" src={i} />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
<div>{message.text}</div>
|
||||
</div>
|
||||
<Tooltip title={DateTimeFormatter({ children: message.created_at })}>
|
||||
<div>
|
||||
{message.image_path &&
|
||||
message.image_path.map((i, idx) => (
|
||||
<div
|
||||
key={idx}
|
||||
style={{ display: "flex", justifyContent: "center" }}
|
||||
>
|
||||
<a href={i} target="__blank">
|
||||
<img alt="Received" className="message-img" src={i} />
|
||||
</a>
|
||||
</div>
|
||||
))}
|
||||
<div>{message.text}</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -31,6 +31,9 @@ const CourtesyCarStatusComponent = ({ value, onChange }, ref) => {
|
||||
<Option value="courtesycars.status.out">
|
||||
{t("courtesycars.status.out")}
|
||||
</Option>
|
||||
<Option value="courtesycars.status.sold">
|
||||
{t("courtesycars.status.sold")}
|
||||
</Option>
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -45,6 +45,10 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
text: t("courtesycars.status.out"),
|
||||
value: "courtesycars.status.out",
|
||||
},
|
||||
{
|
||||
text: t("courtesycars.status.sold"),
|
||||
value: "courtesycars.status.sold",
|
||||
},
|
||||
],
|
||||
onFilter: (value, record) => value.includes(record.status),
|
||||
sortOrder:
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import { tracker } from "../../App/App.container";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
@@ -36,6 +37,7 @@ class ErrorBoundary extends React.Component {
|
||||
componentDidCatch(error, info) {
|
||||
console.log("Exception Caught by Error Boundary.", error, info);
|
||||
this.setState({ ...this.state, error, info });
|
||||
tracker.event("error_boundary", error, true);
|
||||
}
|
||||
|
||||
handleErrorSubmit = () => {
|
||||
|
||||
@@ -400,7 +400,7 @@ export function JobLinesComponent({
|
||||
setState({
|
||||
...state,
|
||||
filteredInfo: {
|
||||
part_type: ["PAN,PAC,PAR,PAL,PAA,PAM,PAP,PAS,PASL"],
|
||||
part_type: ["PAN,PAC,PAR,PAL,PAA,PAM,PAP,PAS,PASL,PAG"],
|
||||
},
|
||||
});
|
||||
}}
|
||||
@@ -435,7 +435,7 @@ export function JobLinesComponent({
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
loading={loading}
|
||||
pagination={{ position: "top", defaultPageSize: 50 }}
|
||||
pagination={false}
|
||||
dataSource={jobLines}
|
||||
onChange={handleTableChange}
|
||||
scroll={{
|
||||
|
||||
@@ -21,7 +21,8 @@ export default function JobReconciliationBillsTable({
|
||||
title: t("billlines.fields.line_desc"),
|
||||
dataIndex: "line_desc",
|
||||
key: "line_desc",
|
||||
width: "35%",
|
||||
ellipsis: true,
|
||||
minWidth: "65rem",
|
||||
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
||||
@@ -30,7 +31,7 @@ export default function JobReconciliationBillsTable({
|
||||
title: t("billlines.labels.from"),
|
||||
dataIndex: "from",
|
||||
key: "from",
|
||||
width: "20%",
|
||||
|
||||
ellipsis: true,
|
||||
render: (text, record) =>
|
||||
`${record.bill.vendor && record.bill.vendor.name} / ${
|
||||
@@ -42,6 +43,7 @@ export default function JobReconciliationBillsTable({
|
||||
dataIndex: "actual_price",
|
||||
key: "actual_price",
|
||||
sorter: (a, b) => a.actual_price - b.actual_price,
|
||||
width: "7rem",
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "actual_price" && state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
@@ -53,6 +55,7 @@ export default function JobReconciliationBillsTable({
|
||||
dataIndex: "actual_cost",
|
||||
key: "actual_cost",
|
||||
sorter: (a, b) => a.actual_cost - b.actual_cost,
|
||||
width: "7rem",
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "actual_cost" && state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
@@ -64,6 +67,7 @@ export default function JobReconciliationBillsTable({
|
||||
dataIndex: "quantity",
|
||||
key: "quantity",
|
||||
sorter: (a, b) => a.quantity - b.quantity,
|
||||
width: "4rem",
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "quantity" && state.sortedInfo.order,
|
||||
},
|
||||
@@ -72,9 +76,11 @@ export default function JobReconciliationBillsTable({
|
||||
dataIndex: "is_credit_memo",
|
||||
key: "is_credit_memo",
|
||||
sorter: (a, b) => a.bill.is_credit_memo - b.bill.is_credit_memo,
|
||||
width: "8rem",
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "is_credit_memo" &&
|
||||
state.sortedInfo.order,
|
||||
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.bill.is_credit_memo} />
|
||||
),
|
||||
@@ -94,7 +100,7 @@ export default function JobReconciliationBillsTable({
|
||||
<Table
|
||||
pagination={false}
|
||||
size="small"
|
||||
scroll={{ y: "80vh", x: true }}
|
||||
scroll={{ y: "60vh" }}
|
||||
columns={columns}
|
||||
rowKey="id"
|
||||
dataSource={invoiceLineData}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
.imex-reconciliation-modal {
|
||||
top: 20px;
|
||||
.ant-modal-content {
|
||||
height: 95vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.ant-modal-body {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
// .ant-modal-content {
|
||||
// height: 95vh;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// .ant-modal-body {
|
||||
// display: flex;
|
||||
// flex: 1;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ export default function JobReconcilitionPartsTable({
|
||||
dataIndex: "line_desc",
|
||||
key: "line_desc",
|
||||
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
||||
ellipses: true,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
||||
},
|
||||
@@ -57,6 +58,7 @@ export default function JobReconcilitionPartsTable({
|
||||
dataIndex: "act_price",
|
||||
key: "act_price",
|
||||
sorter: (a, b) => a.act_price - b.act_price,
|
||||
width: "7rem",
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
|
||||
|
||||
@@ -68,10 +70,12 @@ export default function JobReconcilitionPartsTable({
|
||||
title: t("joblines.fields.part_qty"),
|
||||
dataIndex: "part_qty",
|
||||
key: "part_qty",
|
||||
width: "4rem",
|
||||
},
|
||||
{
|
||||
title: t("joblines.fields.total"),
|
||||
dataIndex: "total",
|
||||
width: "7rem",
|
||||
key: "total",
|
||||
sorter: (a, b) => a.act_price * a.part_qty - b.act_price * b.part_qty,
|
||||
sortOrder:
|
||||
@@ -89,6 +93,7 @@ export default function JobReconcilitionPartsTable({
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
sorter: (a, b) => alphaSort(a.status, b.status),
|
||||
width: "6rem",
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||
},
|
||||
@@ -108,7 +113,7 @@ export default function JobReconcilitionPartsTable({
|
||||
pagination={false}
|
||||
columns={columns}
|
||||
size="small"
|
||||
scroll={{ y: "80vh", x: true }}
|
||||
scroll={{ y: "60vh" }}
|
||||
rowKey="id"
|
||||
dataSource={jobLineData}
|
||||
onChange={handleTableChange}
|
||||
|
||||
@@ -1,11 +1,24 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { Button, Card, Form, InputNumber, notification, Popover } from "antd";
|
||||
import { useMutation, useLazyQuery } from "@apollo/client";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Form,
|
||||
InputNumber,
|
||||
notification,
|
||||
Popover,
|
||||
Space,
|
||||
} from "antd";
|
||||
import moment from "moment";
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { INSERT_SCOREBOARD_ENTRY } from "../../graphql/scoreboard.queries";
|
||||
import {
|
||||
INSERT_SCOREBOARD_ENTRY,
|
||||
QUERY_SCOREBOARD_ENTRY,
|
||||
UPDATE_SCOREBOARD_ENTRY,
|
||||
} from "../../graphql/scoreboard.queries";
|
||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
|
||||
export default function ScoreboardAddButton({
|
||||
job,
|
||||
@@ -14,17 +27,46 @@ export default function ScoreboardAddButton({
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [insertScoreboardEntry] = useMutation(INSERT_SCOREBOARD_ENTRY);
|
||||
const [updateScoreboardEntry] = useMutation(UPDATE_SCOREBOARD_ENTRY);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
const [visibility, setVisibility] = useState(false);
|
||||
const [callQuery, { loading: entryLoading, data: entryData }] = useLazyQuery(
|
||||
QUERY_SCOREBOARD_ENTRY
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (visibility) {
|
||||
callQuery({ variables: { jobid: job.id } });
|
||||
}
|
||||
}, [visibility, job.id, callQuery]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log("UE", entryData);
|
||||
if (entryData && entryData.scoreboard && entryData.scoreboard[0]) {
|
||||
console.log("Setting FOrm");
|
||||
form.setFieldsValue(entryData.scoreboard[0]);
|
||||
}
|
||||
}, [entryData, form]);
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
logImEXEvent("job_close_add_to_scoreboard");
|
||||
|
||||
setLoading(true);
|
||||
const result = await insertScoreboardEntry({
|
||||
variables: { sbInput: [{ jobid: job.id, ...values }] },
|
||||
});
|
||||
let result;
|
||||
|
||||
if (entryData && entryData.scoreboard && entryData.scoreboard[0]) {
|
||||
result = await updateScoreboardEntry({
|
||||
variables: {
|
||||
sbId: entryData.scoreboard[0].id,
|
||||
sbInput: values,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
result = await insertScoreboardEntry({
|
||||
variables: { sbInput: [{ jobid: job.id, ...values }] },
|
||||
});
|
||||
}
|
||||
|
||||
if (!!result.errors) {
|
||||
notification["error"]({
|
||||
@@ -44,53 +86,62 @@ export default function ScoreboardAddButton({
|
||||
const overlay = (
|
||||
<Card>
|
||||
<div>
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={handleFinish}
|
||||
initialValues={{}}
|
||||
>
|
||||
<Form.Item
|
||||
label={t("scoreboard.fields.date")}
|
||||
name="date"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
{entryLoading ? (
|
||||
<LoadingSpinner />
|
||||
) : (
|
||||
<Form
|
||||
form={form}
|
||||
layout="vertical"
|
||||
onFinish={handleFinish}
|
||||
initialValues={{}}
|
||||
>
|
||||
<FormDatePicker />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("scoreboard.fields.bodyhrs")}
|
||||
name="bodyhrs"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber precision={1} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("scoreboard.fields.painthrs")}
|
||||
name="painthrs"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber precision={1} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("scoreboard.fields.date")}
|
||||
name="date"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<FormDatePicker />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("scoreboard.fields.bodyhrs")}
|
||||
name="bodyhrs"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber precision={1} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("scoreboard.fields.painthrs")}
|
||||
name="painthrs"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
//message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<InputNumber precision={1} />
|
||||
</Form.Item>
|
||||
|
||||
<Button type="primary" htmlType="submit">
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
</Form>
|
||||
<Space wrap>
|
||||
<Button type="primary" htmlType="submit">
|
||||
{t("general.actions.save")}
|
||||
</Button>
|
||||
<Button onClick={() => setVisibility(false)}>
|
||||
{t("general.actions.cancel")}
|
||||
</Button>
|
||||
</Space>
|
||||
</Form>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
@@ -99,7 +150,7 @@ export default function ScoreboardAddButton({
|
||||
setLoading(true);
|
||||
const v = job.joblines.reduce(
|
||||
(acc, val) => {
|
||||
if (val.mod_lbr_ty === "LAB")
|
||||
if (val.mod_lbr_ty !== "LAR")
|
||||
acc = { ...acc, bodyhrs: acc.bodyhrs + val.mod_lb_hrs };
|
||||
if (val.mod_lbr_ty === "LAR")
|
||||
acc = { ...acc, painthrs: acc.painthrs + val.mod_lb_hrs };
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import confirmDialog from "../../utils/asyncConfirm";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import JobsAvailableScan from "../jobs-available-scan/jobs-available-scan.component";
|
||||
@@ -98,7 +99,7 @@ export function JobsAvailableContainer({
|
||||
return;
|
||||
}
|
||||
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
||||
await CheckTaxRates(estData, bodyshop);
|
||||
await CheckTaxRates(estData.est_data, bodyshop);
|
||||
|
||||
const newTotals = (
|
||||
await Axios.post("/job/totals", {
|
||||
@@ -139,16 +140,17 @@ export function JobsAvailableContainer({
|
||||
: {}),
|
||||
};
|
||||
|
||||
if (selectedOwner) {
|
||||
newJob.ownerid = selectedOwner;
|
||||
delete newJob.owner;
|
||||
}
|
||||
if (newJob.vehicleid) {
|
||||
delete newJob.vehicle;
|
||||
}
|
||||
|
||||
insertNewJob({
|
||||
variables: {
|
||||
job: selectedOwner
|
||||
? Object.assign(
|
||||
{},
|
||||
newJob,
|
||||
{ owner: null },
|
||||
{ ownerid: selectedOwner }
|
||||
)
|
||||
: newJob,
|
||||
job: newJob,
|
||||
},
|
||||
})
|
||||
.then((r) => {
|
||||
@@ -198,11 +200,10 @@ export function JobsAvailableContainer({
|
||||
message: t("jobs.errors.creating", { error: "No job data present." }),
|
||||
});
|
||||
} else {
|
||||
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
||||
await CheckTaxRates(estData, bodyshop);
|
||||
|
||||
//create upsert job
|
||||
let supp = replaceEmpty({ ...estData.est_data });
|
||||
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
||||
await CheckTaxRates(supp, bodyshop);
|
||||
|
||||
delete supp.owner;
|
||||
delete supp.vehicle;
|
||||
@@ -390,109 +391,104 @@ function replaceEmpty(someObj, replaceValue = null) {
|
||||
value === "" ? replaceValue || null : value;
|
||||
//^ because you seem to want to replace (strings) "null" or "undefined" too
|
||||
const temp = JSON.stringify(someObj, replacer);
|
||||
console.log("Parsed", JSON.parse(temp));
|
||||
return JSON.parse(temp);
|
||||
}
|
||||
|
||||
function confirmDialog(msg) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let confirmed = window.confirm(msg);
|
||||
|
||||
return confirmed ? resolve(true) : resolve(false);
|
||||
});
|
||||
}
|
||||
|
||||
async function CheckTaxRates(estData, bodyshop) {
|
||||
console.log(
|
||||
"🚀 ~ file: jobs-available-table.container.jsx ~ line 398 ~ estData",
|
||||
estData
|
||||
);
|
||||
//LKQ Check
|
||||
if (
|
||||
!estData.est_data.parts_tax_rates?.PAL ||
|
||||
estData.est_data.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
||||
estData.est_data.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
||||
!estData.parts_tax_rates?.PAL ||
|
||||
estData.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`ImEX Online has detected that there is a missing tax rate for LKQ parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.est_data.parts_tax_rates.PAL) {
|
||||
estData.est_data.parts_tax_rates.PAL = {
|
||||
if (!estData.parts_tax_rates.PAL) {
|
||||
estData.parts_tax_rates.PAL = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAL",
|
||||
};
|
||||
}
|
||||
estData.est_data.parts_tax_rates.PAL.prt_tax_rt =
|
||||
estData.parts_tax_rates.PAL.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.est_data.parts_tax_rates.PAL.prt_tax_in = true;
|
||||
estData.parts_tax_rates.PAL.prt_tax_in = true;
|
||||
}
|
||||
}
|
||||
//PAC Check
|
||||
if (
|
||||
!estData.est_data.parts_tax_rates?.PAC ||
|
||||
estData.est_data.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
||||
estData.est_data.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
||||
!estData.parts_tax_rates?.PAC ||
|
||||
estData.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`ImEX Online has detected that there is a missing tax rate for rechromed parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.est_data.parts_tax_rates.PAC) {
|
||||
estData.est_data.parts_tax_rates.PAC = {
|
||||
if (!estData.parts_tax_rates.PAC) {
|
||||
estData.parts_tax_rates.PAC = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAC",
|
||||
};
|
||||
}
|
||||
estData.est_data.parts_tax_rates.PAC.prt_tax_rt =
|
||||
estData.parts_tax_rates.PAC.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.est_data.parts_tax_rates.PAC.prt_tax_in = true;
|
||||
estData.parts_tax_rates.PAC.prt_tax_in = true;
|
||||
}
|
||||
}
|
||||
//PAM Check
|
||||
if (
|
||||
!estData.est_data.parts_tax_rates?.PAM ||
|
||||
estData.est_data.parts_tax_rates?.PAM?.prt_tax_rt === null ||
|
||||
estData.est_data.parts_tax_rates?.PAM?.prt_tax_rt === 0
|
||||
!estData.parts_tax_rates?.PAM ||
|
||||
estData.parts_tax_rates?.PAM?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAM?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`ImEX Online has detected that there is a missing tax rate for remanufactured parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.est_data.parts_tax_rates.PAM) {
|
||||
estData.est_data.parts_tax_rates.PAM = {
|
||||
if (!estData.parts_tax_rates.PAM) {
|
||||
estData.parts_tax_rates.PAM = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAM",
|
||||
};
|
||||
}
|
||||
estData.est_data.parts_tax_rates.PAM.prt_tax_rt =
|
||||
estData.parts_tax_rates.PAM.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.est_data.parts_tax_rates.PAM.prt_tax_in = true;
|
||||
estData.parts_tax_rates.PAM.prt_tax_in = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!estData.est_data.parts_tax_rates?.PAR ||
|
||||
estData.est_data.parts_tax_rates?.PAR?.prt_tax_rt === null ||
|
||||
estData.est_data.parts_tax_rates?.PAR?.prt_tax_rt === 0
|
||||
!estData.parts_tax_rates?.PAR ||
|
||||
estData.parts_tax_rates?.PAR?.prt_tax_rt === null ||
|
||||
estData.parts_tax_rates?.PAR?.prt_tax_rt === 0
|
||||
) {
|
||||
const res = await confirmDialog(
|
||||
`ImEX Online has detected that there is a missing tax rate for recored parts. Pressing OK will set the tax rate to ${bodyshop.bill_tax_rates.state_tax_rate}% and enable the rate. Pressing cancel will keep the tax rate as is.`
|
||||
);
|
||||
if (res) {
|
||||
if (!estData.est_data.parts_tax_rates.PAR) {
|
||||
estData.est_data.parts_tax_rates.PAR = {
|
||||
if (!estData.parts_tax_rates.PAR) {
|
||||
estData.parts_tax_rates.PAR = {
|
||||
prt_discp: 0,
|
||||
prt_mktyp: true,
|
||||
prt_mkupp: 0,
|
||||
prt_type: "PAR",
|
||||
};
|
||||
}
|
||||
estData.est_data.parts_tax_rates.PAR.prt_tax_rt =
|
||||
estData.parts_tax_rates.PAR.prt_tax_rt =
|
||||
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||
estData.est_data.parts_tax_rates.PAR.prt_tax_in = true;
|
||||
estData.parts_tax_rates.PAR.prt_tax_in = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export function JobsCloseExportButton({
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleQbxml = async () => {
|
||||
//Check if it's a CDK setup.
|
||||
if (bodyshop.cdk_dealerid) {
|
||||
history.push(`/manage/dms?jobId=${jobId}`);
|
||||
return;
|
||||
@@ -41,48 +42,58 @@ export function JobsCloseExportButton({
|
||||
logImEXEvent("jobs_close_export");
|
||||
|
||||
setLoading(true);
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: [jobId] },
|
||||
{
|
||||
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),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if it's a QBO Setup.
|
||||
let PartnerResponse;
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/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"),
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/receivables`, {
|
||||
withCredentials: true,
|
||||
jobIds: [jobId],
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
} else {
|
||||
//Default is QBD
|
||||
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: [jobId] },
|
||||
{
|
||||
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),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/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"),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("PartnerResponse", PartnerResponse);
|
||||
|
||||
@@ -104,7 +104,7 @@ export function JobsDetailHeaderCsi({
|
||||
replyTo: bodyshop.email,
|
||||
},
|
||||
template: {
|
||||
name: TemplateList("job").csi_invitation.key,
|
||||
name: TemplateList("job_special").csi_invitation_action.key,
|
||||
variables: {
|
||||
id: result.data.insert_csi.returning[0].id,
|
||||
},
|
||||
|
||||
@@ -76,6 +76,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
||||
{job.ins_co_nm}
|
||||
</DataLabel>
|
||||
<DataLabel label={t("jobs.fields.clm_no")}>{job.clm_no}</DataLabel>
|
||||
<DataLabel label={t("jobs.fields.ponumber")} hideIfNull>
|
||||
{job.po_number}
|
||||
</DataLabel>
|
||||
<DataLabel label={t("jobs.fields.repairtotal")}>
|
||||
<CurrencyFormatter>{job.clm_total}</CurrencyFormatter>
|
||||
<span style={{ margin: "0rem .5rem" }}>/</span>
|
||||
|
||||
@@ -34,53 +34,61 @@ export function JobsExportAllButton({
|
||||
const [loading, setLoading] = useState(false);
|
||||
const handleQbxml = async () => {
|
||||
logImEXEvent("jobs_export_all");
|
||||
|
||||
setLoading(true);
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: jobIds },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} 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),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let PartnerResponse;
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/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"),
|
||||
setLoading(true);
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/receivables`, {
|
||||
withCredentials: true,
|
||||
jobIds: jobIds,
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: jobIds },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} 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),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/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"),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log("PartnerResponse", PartnerResponse);
|
||||
const groupedData = _.groupBy(PartnerResponse.data, "id");
|
||||
const groupedData = _.groupBy(
|
||||
PartnerResponse.data,
|
||||
bodyshop.accountingconfig.qbo ? "jobid" : "id"
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
Object.keys(groupedData).map(async (key) => {
|
||||
@@ -157,6 +165,7 @@ export function JobsExportAllButton({
|
||||
|
||||
if (!!completedCallback) completedCallback([]);
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -130,13 +130,10 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
||||
ellipsis: true,
|
||||
sorter: true, //(a, b) => alphaSort(a.clm_no, b.clm_no),
|
||||
sortOrder: sortcolumn === "clm_no" && sortorder,
|
||||
render: (text, record) => {
|
||||
return record.clm_no ? (
|
||||
<span>{record.clm_no}</span>
|
||||
) : (
|
||||
t("general.labels.unknown")
|
||||
);
|
||||
},
|
||||
render: (text, record) =>
|
||||
`${record.clm_no || ""}${
|
||||
record.po_number ? ` (PO: ${record.po_number})` : ""
|
||||
}`,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.ins_co_nm"),
|
||||
|
||||
@@ -208,6 +208,10 @@ export function JobsList({ bodyshop }) {
|
||||
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
|
||||
render: (text, record) =>
|
||||
`${record.clm_no || ""}${
|
||||
record.po_number ? ` (PO: ${record.po_number})` : ""
|
||||
}`,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.ins_co_nm"),
|
||||
|
||||
@@ -10,8 +10,21 @@ import {
|
||||
QUERY_NOTES_BY_JOB_PK,
|
||||
} from "../../graphql/notes.queries";
|
||||
import JobNotesComponent from "./jobs.notes.component";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
|
||||
export default function JobNotesContainer({ jobId }) {
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
insertAuditTrail: ({ jobid, operation }) =>
|
||||
dispatch(insertAuditTrail({ jobid, operation })),
|
||||
});
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(JobNotesContainer);
|
||||
|
||||
export function JobNotesContainer({ jobId, insertAuditTrail }) {
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_NOTES_BY_JOB_PK, {
|
||||
variables: { id: jobId },
|
||||
fetchPolicy: "network-only",
|
||||
@@ -32,6 +45,10 @@ export default function JobNotesContainer({ jobId }) {
|
||||
notification["success"]({
|
||||
message: t("notes.successes.deleted"),
|
||||
});
|
||||
insertAuditTrail({
|
||||
jobid: jobId,
|
||||
operation: AuditTrailMapping.jobnotedeleted(),
|
||||
});
|
||||
});
|
||||
setDeleteLoading(false);
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@ import { selectNoteUpsert } from "../../redux/modals/modals.selectors";
|
||||
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import NoteUpsertModalComponent from "./note-upsert-modal.component";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
@@ -17,12 +19,15 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
toggleModalVisible: () => dispatch(toggleModalVisible("noteUpsert")),
|
||||
insertAuditTrail: ({ jobid, operation }) =>
|
||||
dispatch(insertAuditTrail({ jobid, operation })),
|
||||
});
|
||||
|
||||
export function NoteUpsertModalContainer({
|
||||
currentUser,
|
||||
noteUpsertModal,
|
||||
toggleModalVisible,
|
||||
insertAuditTrail,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [insertNote] = useMutation(INSERT_NEW_NOTE);
|
||||
@@ -56,6 +61,10 @@ export function NoteUpsertModalContainer({
|
||||
notification["success"]({
|
||||
message: t("notes.successes.updated"),
|
||||
});
|
||||
insertAuditTrail({
|
||||
jobid: context.jobId,
|
||||
operation: AuditTrailMapping.jobnoteupdated(),
|
||||
});
|
||||
});
|
||||
if (refetch) refetch();
|
||||
toggleModalVisible();
|
||||
@@ -75,6 +84,10 @@ export function NoteUpsertModalContainer({
|
||||
notification["success"]({
|
||||
message: t("notes.successes.create"),
|
||||
});
|
||||
insertAuditTrail({
|
||||
jobid: context.jobId,
|
||||
operation: AuditTrailMapping.jobnoteadded(),
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -176,7 +176,7 @@ export function PartsOrderModalContainer({
|
||||
|
||||
if (refetch) refetch();
|
||||
toggleModalVisible();
|
||||
const Templates = TemplateList("partsorder");
|
||||
const Templates = TemplateList("partsorder", context);
|
||||
|
||||
if (sendType === "e") {
|
||||
const matchingVendor = data.vendors.filter(
|
||||
|
||||
@@ -35,52 +35,61 @@ export function PayableExportAll({
|
||||
|
||||
const handleQbxml = async () => {
|
||||
logImEXEvent("accounting_payables_export_all");
|
||||
let PartnerResponse;
|
||||
|
||||
setLoading(true);
|
||||
if (!!loadingCallback) loadingCallback(true);
|
||||
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/payables",
|
||||
{ bills: billids },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("bills.errors.exporting", {
|
||||
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
|
||||
}),
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/receivables`, {
|
||||
withCredentials: true,
|
||||
bills: billids,
|
||||
});
|
||||
if (loadingCallback) loadingCallback(false);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/payables",
|
||||
{ bills: billids },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("bills.errors.exporting", {
|
||||
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
|
||||
}),
|
||||
});
|
||||
if (loadingCallback) loadingCallback(false);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let PartnerResponse;
|
||||
|
||||
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("bills.errors.exporting-partner"),
|
||||
});
|
||||
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("bills.errors.exporting-partner"),
|
||||
});
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("handleQbxml -> PartnerResponse", PartnerResponse);
|
||||
const groupedData = _.groupBy(PartnerResponse.data, "id");
|
||||
const groupedData = _.groupBy(
|
||||
PartnerResponse.data,
|
||||
bodyshop.accountingconfig.qbo ? "billid" : "id"
|
||||
);
|
||||
|
||||
const proms = [];
|
||||
Object.keys(groupedData).forEach((key) => {
|
||||
proms.push(
|
||||
|
||||
@@ -38,44 +38,53 @@ export function PayableExportButton({
|
||||
setLoading(true);
|
||||
if (!!loadingCallback) loadingCallback(true);
|
||||
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/payables",
|
||||
{ bills: [billId] },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("bills.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 {
|
||||
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("bills.errors.exporting-partner"),
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/payables`, {
|
||||
withCredentials: true,
|
||||
bills: [billId],
|
||||
});
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
setLoading(false);
|
||||
return;
|
||||
} else {
|
||||
//Default is QBD
|
||||
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/payables",
|
||||
{ bills: [billId] },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("bills.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("bills.errors.exporting-partner"),
|
||||
});
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("handleQbxml -> PartnerResponse", PartnerResponse);
|
||||
@@ -123,7 +132,14 @@ export function PayableExportButton({
|
||||
});
|
||||
const billUpdateResponse = await updateBill({
|
||||
variables: {
|
||||
billIdList: successfulTransactions.map((st) => st.id),
|
||||
billIdList: successfulTransactions.map(
|
||||
(st) =>
|
||||
st[
|
||||
bodyshop.accountingconfig && bodyshop.accountingconfig.qbo
|
||||
? "billid"
|
||||
: "id"
|
||||
]
|
||||
),
|
||||
bill: {
|
||||
exported: true,
|
||||
exported_at: new Date(),
|
||||
|
||||
@@ -1,28 +1,35 @@
|
||||
import { Card, Col, Input, Row, Space, Typography } from "antd";
|
||||
import _ from "lodash";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectPrintCenter } from "../../redux/modals/modals.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import Jobd3RdPartyModal from "../job-3rd-party-modal/job-3rd-party-modal.component";
|
||||
import PrintCenterItem from "../print-center-item/print-center-item.component";
|
||||
import PrintCenterSpeedPrint from "../print-center-speed-print/print-center-speed-print.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
printCenterModal: selectPrintCenter,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
|
||||
export function PrintCenterJobsComponent({ printCenterModal }) {
|
||||
export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
|
||||
const [search, setSearch] = useState("");
|
||||
const { id: jobId } = printCenterModal.context;
|
||||
const tempList = TemplateList("job", {});
|
||||
const { t } = useTranslation();
|
||||
const JobsReportsList = Object.keys(tempList).map((key) => {
|
||||
return tempList[key];
|
||||
});
|
||||
const JobsReportsList = Object.keys(tempList)
|
||||
.map((key) => {
|
||||
return tempList[key];
|
||||
})
|
||||
.filter(
|
||||
(temp) =>
|
||||
!temp.regions || (temp.regions && temp.regions[bodyshop.region_config])
|
||||
);
|
||||
|
||||
const filteredJobsReportsList =
|
||||
search !== ""
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { Button, Space } from "antd";
|
||||
import { Space, Tag } from "antd";
|
||||
import Axios from "axios";
|
||||
import React, { useEffect } from "react";
|
||||
//import QboImg from "./qbo_signin.png";
|
||||
import queryString from "query-string";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import React, { useEffect } from "react";
|
||||
import { useCookies } from "react-cookie";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import QboSignIn from "../../assets/qbo/C2QB_green_btn_med_default.svg";
|
||||
|
||||
export default function QboAuthorizeComponent() {
|
||||
const location = useLocation();
|
||||
|
||||
const [, setCookie] = useCookies(["access_token", "refresh_token"]);
|
||||
const history = useHistory();
|
||||
const [cookies, setCookie] = useCookies(["access_token", "refresh_token"]);
|
||||
|
||||
const handleQbSignIn = async () => {
|
||||
const result = await Axios.post("/qbo/authorize");
|
||||
console.log("pushing to history", result.data);
|
||||
window.location.href = result.data;
|
||||
};
|
||||
const qs = queryString.parse(location.search);
|
||||
@@ -35,42 +34,24 @@ export default function QboAuthorizeComponent() {
|
||||
path: "/",
|
||||
expires,
|
||||
});
|
||||
|
||||
history.push({ pathname: `/manage/accounting/receivables` });
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [qs, location, setCookie]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Space wrap>
|
||||
<Button onClick={handleQbSignIn}>
|
||||
{/* <img
|
||||
src={QboImg}
|
||||
alt="Sign in with Intuit"
|
||||
onClick={handleQbSignIn}
|
||||
/> */}
|
||||
auth
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const response = await Axios.get(`/qbo/refresh`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
console.log(response);
|
||||
}}
|
||||
>
|
||||
Refresh Token
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const response = await Axios.post(`/qbo/receivables`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
console.log(response);
|
||||
}}
|
||||
>
|
||||
REC
|
||||
</Button>
|
||||
</Space>
|
||||
<Space>
|
||||
<img
|
||||
onClick={handleQbSignIn}
|
||||
alt="Sign In to QuickBooks Online"
|
||||
src={QboSignIn}
|
||||
style={{ cursor: "pointer" }}
|
||||
/>
|
||||
{!cookies.qbo_realmId && (
|
||||
<Tag color="red">No QuickBooks company has been connected.</Tag>
|
||||
)}
|
||||
{error && JSON.parse(decodeURIComponent(error)).error_description}
|
||||
</div>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
import { useLazyQuery } from "@apollo/client";
|
||||
import { Button, DatePicker, Form, Radio, Space } from "antd";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
DatePicker,
|
||||
Form,
|
||||
Input,
|
||||
Radio,
|
||||
Row,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import _ from "lodash";
|
||||
import moment from "moment";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -14,7 +25,6 @@ import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import EmployeeSearchSelect from "../employee-search-select/employee-search-select.component";
|
||||
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
||||
import "./report-center-modal.styles.scss";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
reportCenterModal: selectReportCenter,
|
||||
});
|
||||
@@ -28,9 +38,14 @@ export default connect(
|
||||
|
||||
export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||
const [form] = Form.useForm();
|
||||
const [search, setSearch] = useState("");
|
||||
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
const Templates = TemplateList("report_center");
|
||||
const ReportsList = Object.keys(Templates).map((key) => {
|
||||
return Templates[key];
|
||||
});
|
||||
const { visible } = reportCenterModal;
|
||||
|
||||
const [callVendorQuery, { data: vendorData, called: vendorCalled }] =
|
||||
@@ -67,6 +82,9 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||
...(end
|
||||
? { end: moment(end).endOf("day").format("YYYY-MM-DD") }
|
||||
: {}),
|
||||
...(start ? { starttz: moment(start).startOf("day") } : {}),
|
||||
...(end ? { endtz: moment(end).endOf("day") } : {}),
|
||||
|
||||
...(id ? { id: id } : {}),
|
||||
},
|
||||
},
|
||||
@@ -80,6 +98,17 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
const FilteredReportsList =
|
||||
search !== ""
|
||||
? ReportsList.filter((r) =>
|
||||
r.title.toLowerCase().includes(search.toLowerCase())
|
||||
)
|
||||
: ReportsList;
|
||||
|
||||
//Group it, create cards, and then filter out.
|
||||
|
||||
const grouped = _.groupBy(FilteredReportsList, "group");
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form
|
||||
@@ -88,6 +117,10 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||
layout="vertical"
|
||||
form={form}
|
||||
>
|
||||
<Input.Search
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
value={search}
|
||||
/>
|
||||
<Form.Item
|
||||
name="key"
|
||||
label={t("reportcenter.labels.key")}
|
||||
@@ -100,23 +133,42 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||
]}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Space
|
||||
direction="vertical"
|
||||
wrap
|
||||
size="small"
|
||||
style={{
|
||||
maxHeight: "50vh",
|
||||
}}
|
||||
>
|
||||
{Object.keys(Templates).map((key) => (
|
||||
{/* {Object.keys(Templates).map((key) => (
|
||||
<Radio key={key} value={key}>
|
||||
{Templates[key].title}
|
||||
</Radio>
|
||||
))} */}
|
||||
|
||||
<Row gutter={[16, 16]}>
|
||||
{Object.keys(grouped).map((key) => (
|
||||
<Col md={8} sm={12} key={key}>
|
||||
<Card.Grid
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
maxHeight: "33vh",
|
||||
overflowY: "scroll",
|
||||
}}
|
||||
>
|
||||
<Typography.Title level={4}>
|
||||
{t(`reportcenter.labels.groups.${key}`)}
|
||||
</Typography.Title>
|
||||
<ul style={{ columns: "2 auto" }}>
|
||||
{grouped[key].map((item) => (
|
||||
<li key={item.key}>
|
||||
<Radio key={item.key} value={item.key}>
|
||||
{item.title}
|
||||
</Radio>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Card.Grid>
|
||||
</Col>
|
||||
))}
|
||||
</Space>
|
||||
</Row>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
<Form.Item dependencies={["key"]}>
|
||||
<Form.Item style={{ margin: 0, padding: 0 }} dependencies={["key"]}>
|
||||
{() => {
|
||||
const key = form.getFieldValue("key");
|
||||
if (!key) return null;
|
||||
@@ -137,14 +189,14 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||
shouldUpdate={(prev, cur) =>
|
||||
Templates[prev.key]?.idtype !== Templates[cur.key]?.idtype
|
||||
}
|
||||
style={{ display: "none" }}
|
||||
style={{ display: "none", margin: 0, padding: 0 }}
|
||||
>
|
||||
{() => {
|
||||
form.setFieldsValue({ id: null });
|
||||
return null;
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item dependencies={["key"]}>
|
||||
<Form.Item style={{ margin: 0, padding: 0 }} dependencies={["key"]}>
|
||||
{() => {
|
||||
const key = form.getFieldValue("key");
|
||||
if (!key) return null;
|
||||
@@ -204,7 +256,7 @@ export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||
]}
|
||||
>
|
||||
<DatePicker.RangePicker
|
||||
format="YYYY-MM-DD"
|
||||
format="MM/DD/YYYY"
|
||||
ranges={DatePIckerRanges}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
@@ -18,6 +18,11 @@ import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import * as Utils from "../scoreboard-targets-table/scoreboard-targets-table.util";
|
||||
import _ from "lodash";
|
||||
|
||||
const graphProps = {
|
||||
strokeWidth: 3,
|
||||
};
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
@@ -51,7 +56,7 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) {
|
||||
}
|
||||
|
||||
const theValue = {
|
||||
date: moment(val).format("D dd"),
|
||||
date: moment(val).format("D ddd"),
|
||||
paintHrs: _.round(dayhrs.painthrs, 1),
|
||||
bodyHrs: _.round(dayhrs.bodyhrs, 1),
|
||||
accTargetHrs: _.round(
|
||||
@@ -81,36 +86,37 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) {
|
||||
margin={{ top: 20, right: 20, bottom: 20, left: 20 }}
|
||||
>
|
||||
<CartesianGrid stroke="#f5f5f5" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis />
|
||||
<XAxis dataKey="date" strokeWidth={graphProps.strokeWidth} />
|
||||
<YAxis strokeWidth={graphProps.strokeWidth} />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Area
|
||||
type="monotone"
|
||||
name="Accumulated Hours"
|
||||
dataKey="accHrs"
|
||||
fill="#8884d8"
|
||||
stroke="#8884d8"
|
||||
fill="lightgreen"
|
||||
stroke="green"
|
||||
/>
|
||||
<Bar
|
||||
name="Body Hours"
|
||||
dataKey="bodyHrs"
|
||||
stackId="day"
|
||||
barSize={20}
|
||||
fill="#cecece"
|
||||
fill="darkblue"
|
||||
/>
|
||||
<Bar
|
||||
name="Paint Hours"
|
||||
dataKey="paintHrs"
|
||||
stackId="day"
|
||||
barSize={20}
|
||||
fill="#413ea0"
|
||||
fill="darkred"
|
||||
/>
|
||||
<Line
|
||||
name="Target Hours"
|
||||
type="monotone"
|
||||
dataKey="accTargetHrs"
|
||||
stroke="#ff7300"
|
||||
strokeWidth={graphProps.strokeWidth}
|
||||
/>
|
||||
</ComposedChart>
|
||||
</ResponsiveContainer>
|
||||
|
||||
@@ -1,12 +1,33 @@
|
||||
import { Col, Row } from "antd";
|
||||
import React from "react";
|
||||
import React, { useEffect } from "react";
|
||||
import ScoreboardChart from "../scoreboard-chart/scoreboard-chart.component";
|
||||
import ScoreboardLastDays from "../scoreboard-last-days/scoreboard-last-days.component";
|
||||
import ScoreboardTargetsTable from "../scoreboard-targets-table/scoreboard-targets-table.component";
|
||||
|
||||
export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
|
||||
const { data } = scoreboardSubscription;
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import moment from "moment";
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import { GET_BLOCKED_DAYS } from "../../graphql/scoreboard.queries";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(ScoreboardDisplayComponent);
|
||||
|
||||
export function ScoreboardDisplayComponent({
|
||||
bodyshop,
|
||||
scoreboardSubscription,
|
||||
}) {
|
||||
const { data } = scoreboardSubscription;
|
||||
const client = useApolloClient();
|
||||
const scoreBoardlist = (data && data.scoreboard) || [];
|
||||
|
||||
const sbEntriesByDate = {};
|
||||
@@ -19,6 +40,29 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
|
||||
sbEntriesByDate[entryDate].push(i);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
//Update the locals.
|
||||
async function setMomentSettings() {
|
||||
const {
|
||||
data: { appointments },
|
||||
} = await client.query({
|
||||
query: GET_BLOCKED_DAYS,
|
||||
variables: {
|
||||
start: moment().startOf("month"),
|
||||
end: moment().endOf("month"),
|
||||
},
|
||||
});
|
||||
|
||||
moment.updateLocale("ca", {
|
||||
workingWeekdays: translateSettingsToWorkingDays(bodyshop.workingdays),
|
||||
holidays: appointments.map((h) => moment(h.start).format("MM-DD-YYYY")),
|
||||
holidayFormat: "MM-DD-YYYY",
|
||||
});
|
||||
}
|
||||
|
||||
setMomentSettings();
|
||||
}, [client, bodyshop]);
|
||||
|
||||
return (
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
@@ -35,3 +79,30 @@ export default function ScoreboardDisplayComponent({ scoreboardSubscription }) {
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
function translateSettingsToWorkingDays(workingdays) {
|
||||
const days = [];
|
||||
|
||||
if (workingdays.monday) {
|
||||
days.push(1);
|
||||
}
|
||||
if (workingdays.tuesday) {
|
||||
days.push(2);
|
||||
}
|
||||
if (workingdays.wednesday) {
|
||||
days.push(3);
|
||||
}
|
||||
if (workingdays.thursday) {
|
||||
days.push(4);
|
||||
}
|
||||
if (workingdays.friday) {
|
||||
days.push(5);
|
||||
}
|
||||
if (workingdays.saturday) {
|
||||
days.push(6);
|
||||
}
|
||||
if (workingdays.sunday) {
|
||||
days.push(0);
|
||||
}
|
||||
return days;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import moment from "moment-business-days";
|
||||
|
||||
moment.updateLocale("ca", {
|
||||
workingWeekdays: [1, 2, 3, 4, 5],
|
||||
});
|
||||
// moment.updateLocale("ca", {
|
||||
// workingWeekdays: [1, 2, 3, 4, 5, 6],
|
||||
// });
|
||||
|
||||
export const CalculateWorkingDaysThisMonth = () => {
|
||||
return moment().endOf("month").businessDaysIntoMonth();
|
||||
|
||||
@@ -121,6 +121,13 @@ export default function ShopInfoGeneral({ form }) {
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("bodyshop.labels.accountingsetup")}>
|
||||
<Form.Item
|
||||
label={t("bodyshop.labels.qbo")}
|
||||
valuePropName="checked"
|
||||
name={["accountingconfig", "qbo"]}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bodyshop.labels.accountingtiers")}
|
||||
rules={[
|
||||
|
||||
@@ -132,8 +132,8 @@ const JobRelatedTicketsTable = ({
|
||||
return {
|
||||
id: `${item.jobKey}${costCenter}`,
|
||||
item,
|
||||
actHrs,
|
||||
prodHrs,
|
||||
actHrs: actHrs.toFixed(1),
|
||||
prodHrs: prodHrs.toFixed(1),
|
||||
clockHrs,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -153,7 +153,7 @@ export default function VendorsFormComponent({
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow grow>
|
||||
<Form.Item label={t("vendors.fields.discount")} name="discount">
|
||||
<InputNumber min={0} max={1} precision={2} />
|
||||
<InputNumber min={0} max={1} precision={2} step={0.01} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("vendors.fields.due_date")} name="due_date">
|
||||
<InputNumber />
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { getAnalytics, logEvent } from "firebase/analytics";
|
||||
import { initializeApp } from "firebase/app";
|
||||
import { getAuth } from "firebase/auth";
|
||||
import { getAuth, updatePassword, updateProfile } from "firebase/auth";
|
||||
import { getFirestore } from "firebase/firestore";
|
||||
import { tracker } from "../App/App.container";
|
||||
//import { getMessaging } from "firebase/messaging";
|
||||
import { store } from "../redux/store";
|
||||
|
||||
@@ -25,7 +26,7 @@ export const getCurrentUser = () => {
|
||||
export const updateCurrentUser = (userDetails) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const unsubscribe = auth.onAuthStateChanged((userAuth) => {
|
||||
userAuth.updateProfile(userDetails).then((r) => {
|
||||
updateProfile(userAuth, userDetails).then((r) => {
|
||||
unsubscribe();
|
||||
resolve(userAuth);
|
||||
});
|
||||
@@ -36,19 +37,7 @@ export const updateCurrentUser = (userDetails) => {
|
||||
export const updateCurrentPassword = async (password) => {
|
||||
const currentUser = await getCurrentUser();
|
||||
|
||||
return currentUser.updatePassword(password);
|
||||
|
||||
// return new Promise((resolve, reject) => {
|
||||
// const unsubscribe = auth.onAuthStateChanged(
|
||||
// (userAuth) => {
|
||||
// userAuth.updatePassword(password).then((r) => {
|
||||
// unsubscribe();
|
||||
// resolve(userAuth);
|
||||
// });
|
||||
// },
|
||||
// (error) => reject(error)
|
||||
// );
|
||||
// });
|
||||
return updatePassword(currentUser, password);
|
||||
};
|
||||
|
||||
//let messaging;
|
||||
@@ -74,13 +63,16 @@ export const logImEXEvent = (eventName, additionalParams, stateProp = null) => {
|
||||
null,
|
||||
...additionalParams,
|
||||
};
|
||||
console.log(
|
||||
"%c[Analytics]",
|
||||
"background-color: green ;font-weight:bold;",
|
||||
eventName,
|
||||
eventParams
|
||||
);
|
||||
// console.log(
|
||||
// "%c[Analytics]",
|
||||
// "background-color: green ;font-weight:bold;",
|
||||
// eventName,
|
||||
// eventParams
|
||||
// );
|
||||
logEvent(analytics, eventName, eventParams);
|
||||
|
||||
//Log event to OpenReplay server.
|
||||
tracker.event(eventName, eventParams);
|
||||
};
|
||||
|
||||
// if (messaging) {
|
||||
|
||||
@@ -9,6 +9,7 @@ export const CONVERSATION_LIST_SUBSCRIPTION = gql`
|
||||
) {
|
||||
phone_num
|
||||
id
|
||||
updated_at
|
||||
job_conversations {
|
||||
job {
|
||||
id
|
||||
|
||||
@@ -160,7 +160,8 @@ export const UPDATE_JOB_LINE = gql`
|
||||
|
||||
export const GET_JOB_LINES_TO_ENTER_BILL = gql`
|
||||
query GET_JOB_LINES_TO_ENTER_BILL($id: uuid!) {
|
||||
joblines(where: { jobid: { _eq: $id }, removed: { _eq: false } }) {
|
||||
joblines(where: { jobid: { _eq: $id } }) {
|
||||
removed
|
||||
id
|
||||
line_desc
|
||||
part_type
|
||||
|
||||
@@ -31,6 +31,7 @@ export const QUERY_ALL_ACTIVE_JOBS = gql`
|
||||
id
|
||||
ins_co_nm
|
||||
clm_no
|
||||
po_number
|
||||
clm_total
|
||||
owner_owing
|
||||
ro_number
|
||||
@@ -76,6 +77,7 @@ export const QUERY_PARTS_QUEUE = gql`
|
||||
) {
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ownr_ph1
|
||||
ownr_ea
|
||||
plate_no
|
||||
@@ -97,6 +99,7 @@ export const QUERY_PARTS_QUEUE = gql`
|
||||
status
|
||||
updated_at
|
||||
vehicleid
|
||||
ownerid
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -109,6 +112,7 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
||||
ro_number
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
v_model_yr
|
||||
v_model_desc
|
||||
clm_no
|
||||
@@ -362,6 +366,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
converted
|
||||
lbr_adjustments
|
||||
ro_number
|
||||
po_number
|
||||
clm_total
|
||||
inproduction
|
||||
vehicleid
|
||||
@@ -440,6 +445,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
job_totals
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ownr_ea
|
||||
ownr_addr1
|
||||
ownr_addr2
|
||||
@@ -455,6 +461,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
id
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ownr_ea
|
||||
ownr_addr1
|
||||
ownr_addr2
|
||||
@@ -536,6 +543,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
db_ref
|
||||
manual_line
|
||||
prt_dsmk_p
|
||||
prt_dsmk_m
|
||||
billlines(limit: 1, order_by: { bill: { date: desc } }) {
|
||||
id
|
||||
quantity
|
||||
@@ -674,6 +682,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
|
||||
inproduction
|
||||
production_vars
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ownr_ph1
|
||||
ownr_ea
|
||||
ca_gst_registrant
|
||||
@@ -715,7 +724,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
|
||||
actual_completion
|
||||
actual_delivery
|
||||
actual_in
|
||||
|
||||
po_number
|
||||
id
|
||||
ins_co_nm
|
||||
ins_ct_fn
|
||||
@@ -1631,6 +1640,7 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql`
|
||||
) {
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ownerid
|
||||
ownr_ph1
|
||||
ownr_ea
|
||||
@@ -1660,6 +1670,7 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql`
|
||||
clm_total
|
||||
owner_owing
|
||||
ro_number
|
||||
po_number
|
||||
scheduled_completion
|
||||
scheduled_in
|
||||
scheduled_delivery
|
||||
|
||||
@@ -51,3 +51,34 @@ export const UPDATE_SCOREBOARD_ENTRY = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const QUERY_SCOREBOARD_ENTRY = gql`
|
||||
query QUERY_SCOREBOARD_ENTRY($jobid: uuid!) {
|
||||
scoreboard(where: { jobid: { _eq: $jobid } }) {
|
||||
bodyhrs
|
||||
date
|
||||
id
|
||||
painthrs
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const GET_BLOCKED_DAYS = gql`
|
||||
query GET_BLOCKED_DAYS($start: timestamptz, $end: timestamptz) {
|
||||
appointments(
|
||||
where: {
|
||||
_and: [
|
||||
{ block: { _eq: true } }
|
||||
{ canceled: { _eq: false } }
|
||||
{ start: { _gte: $start } }
|
||||
{ end: { _lte: $end } }
|
||||
]
|
||||
}
|
||||
) {
|
||||
id
|
||||
block
|
||||
start
|
||||
end
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -85,7 +85,6 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
});
|
||||
};
|
||||
|
||||
console.log("Manual State", state);
|
||||
const handleFinish = (values) => {
|
||||
let job = Object.assign(
|
||||
{},
|
||||
@@ -142,6 +141,10 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
}
|
||||
|
||||
job = { ...job, ...ownerData };
|
||||
|
||||
if (job.owner === null) delete job.owner;
|
||||
if (job.vehicle === null) delete job.vehicle;
|
||||
|
||||
runInsertJob(job);
|
||||
};
|
||||
|
||||
|
||||
@@ -116,8 +116,8 @@ export function PartsQueuePageComponent({ bodyshop }) {
|
||||
// sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
||||
// sortOrder: sortcolumn === "owner" && sortorder,
|
||||
render: (text, record) => {
|
||||
return record.owner ? (
|
||||
<Link to={"/manage/owners/" + record.owner.id}>
|
||||
return record.ownerid ? (
|
||||
<Link to={"/manage/owners/" + record.ownerid}>
|
||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
||||
record.ownr_co_nm || ""
|
||||
}`}
|
||||
|
||||
@@ -90,8 +90,6 @@ export function* onSendMessage() {
|
||||
}
|
||||
export function* sendMessage({ payload }) {
|
||||
try {
|
||||
yield logImEXEvent("messaging_send_message");
|
||||
|
||||
const response = yield call(axios.post, "/sms/send", payload);
|
||||
if (response.status === 200) {
|
||||
yield put(sendMessageSuccess(payload));
|
||||
|
||||
@@ -96,6 +96,9 @@
|
||||
"jobimported": "Job imported.",
|
||||
"jobinproductionchange": "Job production status set to {{inproduction}}",
|
||||
"jobmodifylbradj": "Labor adjustments modified.",
|
||||
"jobnoteadded": "Note added to job.",
|
||||
"jobnotedeleted": "Note deleted from job.",
|
||||
"jobnoteupdated": "Note updated on job.",
|
||||
"jobspartsorder": "Parts order {{order_number}} added to job.",
|
||||
"jobspartsreturn": "Parts return {{order_number}} added to job.",
|
||||
"jobstatuschange": "Job status changed to {{status}}.",
|
||||
@@ -179,6 +182,7 @@
|
||||
"noneselected": "No bill selected.",
|
||||
"onlycmforinvoiced": "Only credit memos can be entered for any job that has been invoiced, exported, or voided.",
|
||||
"retailtotal": "Bills Retail Total",
|
||||
"savewithdiscrepancy": "You are about to save this bill with a discrepancy. The system will continue to use the calculated amount using the bill lines. Press cancel to return to the bill.",
|
||||
"state_tax": "Provincial/State Tax",
|
||||
"subtotal": "Subtotal",
|
||||
"totalreturns": "Total Returns"
|
||||
@@ -505,6 +509,7 @@
|
||||
"orderstatuses": "Order Statuses",
|
||||
"partslocations": "Parts Locations",
|
||||
"printlater": "Print Later",
|
||||
"qbo": "Use QuickBooks Online?",
|
||||
"rbac": "Role Based Access Control",
|
||||
"responsibilitycenters": {
|
||||
"costs": "Cost Centers",
|
||||
@@ -685,7 +690,8 @@
|
||||
"status": {
|
||||
"in": "Available",
|
||||
"inservice": "In Service",
|
||||
"out": "Rented"
|
||||
"out": "Rented",
|
||||
"sold": "Sold"
|
||||
},
|
||||
"successes": {
|
||||
"saved": "Courtesy Car saved successfully."
|
||||
@@ -702,7 +708,8 @@
|
||||
"notfoundtitle": "No survey found."
|
||||
},
|
||||
"fields": {
|
||||
"completedon": "Completed On"
|
||||
"completedon": "Completed On",
|
||||
"created_at": "Created At"
|
||||
},
|
||||
"labels": {
|
||||
"nologgedinuser": "Please log out of ImEX Online",
|
||||
@@ -1946,6 +1953,7 @@
|
||||
"coversheet_landscape": "Coversheet (Landscape)",
|
||||
"coversheet_portrait": "Coversheet Portrait",
|
||||
"csi_invitation": "CSI Invitation",
|
||||
"csi_invitation_action": "CSI Invite",
|
||||
"diagnostic_authorization": "Diagnostic Authorization",
|
||||
"estimate": "Estimate Only",
|
||||
"estimate_detail": "Estimate Details",
|
||||
@@ -1976,6 +1984,8 @@
|
||||
"qc_sheet": "Quality Control Sheet",
|
||||
"ro_totals": "RO Totals",
|
||||
"ro_with_description": "RO Summary with Descriptions",
|
||||
"sgi_certificate_of_repairs": "SGI - Certificate of Repairs",
|
||||
"sgi_windshield_auth": "SGI - Windshield Authorization",
|
||||
"stolen_recovery_checklist": "Stolen Recovery Checklist",
|
||||
"supplement_request": "Supplement Request",
|
||||
"thank_you_ro": "Thank You Letter",
|
||||
@@ -2008,6 +2018,11 @@
|
||||
"payments": {
|
||||
"ca_bc_etf_table": "ICBC ETF Table"
|
||||
},
|
||||
"subjects": {
|
||||
"jobs": {
|
||||
"parts_order": "$t(printcenter.jobs.parts_order) PO: {{ro_number}}"
|
||||
}
|
||||
},
|
||||
"vendors": {
|
||||
"purchases_by_vendor_detailed": "Purchases by Vendor - Detailed",
|
||||
"purchases_by_vendor_summary": "Purchases by Vendor - Summary"
|
||||
@@ -2072,10 +2087,18 @@
|
||||
"employee": "Employee",
|
||||
"filterson": "Filters on {{object}}: {{field}}",
|
||||
"generateasemail": "Generate as Email?",
|
||||
"groups": {
|
||||
"customers": "Customers",
|
||||
"jobs": "Jobs & Costing",
|
||||
"payroll": "Payroll",
|
||||
"purchases": "Purchases",
|
||||
"sales": "Sales"
|
||||
},
|
||||
"key": "Report",
|
||||
"objects": {
|
||||
"appointments": "Appointments",
|
||||
"bills": "Bills",
|
||||
"csi": "CSI",
|
||||
"exportlogs": "Export Logs",
|
||||
"jobs": "Jobs",
|
||||
"parts_orders": "Parts Orders",
|
||||
@@ -2091,6 +2114,7 @@
|
||||
"attendance_employee": "Employee Attendance",
|
||||
"attendance_summary": "Attendance Summary (All Employees)",
|
||||
"credits_not_received_date": "Credits not Received by Date",
|
||||
"csi": "CSI Responses",
|
||||
"estimator_detail": "Jobs by Estimator (Detail)",
|
||||
"estimator_summary": "Jobs by Estimator (Summary)",
|
||||
"export_payables": "Export Log - Payables",
|
||||
|
||||
@@ -96,6 +96,9 @@
|
||||
"jobimported": "",
|
||||
"jobinproductionchange": "",
|
||||
"jobmodifylbradj": "",
|
||||
"jobnoteadded": "",
|
||||
"jobnotedeleted": "",
|
||||
"jobnoteupdated": "",
|
||||
"jobspartsorder": "",
|
||||
"jobspartsreturn": "",
|
||||
"jobstatuschange": "",
|
||||
@@ -179,6 +182,7 @@
|
||||
"noneselected": "",
|
||||
"onlycmforinvoiced": "",
|
||||
"retailtotal": "",
|
||||
"savewithdiscrepancy": "",
|
||||
"state_tax": "",
|
||||
"subtotal": "",
|
||||
"totalreturns": ""
|
||||
@@ -505,6 +509,7 @@
|
||||
"orderstatuses": "",
|
||||
"partslocations": "",
|
||||
"printlater": "",
|
||||
"qbo": "",
|
||||
"rbac": "",
|
||||
"responsibilitycenters": {
|
||||
"costs": "",
|
||||
@@ -685,7 +690,8 @@
|
||||
"status": {
|
||||
"in": "",
|
||||
"inservice": "",
|
||||
"out": ""
|
||||
"out": "",
|
||||
"sold": ""
|
||||
},
|
||||
"successes": {
|
||||
"saved": ""
|
||||
@@ -702,7 +708,8 @@
|
||||
"notfoundtitle": ""
|
||||
},
|
||||
"fields": {
|
||||
"completedon": ""
|
||||
"completedon": "",
|
||||
"created_at": ""
|
||||
},
|
||||
"labels": {
|
||||
"nologgedinuser": "",
|
||||
@@ -1946,6 +1953,7 @@
|
||||
"coversheet_landscape": "",
|
||||
"coversheet_portrait": "",
|
||||
"csi_invitation": "",
|
||||
"csi_invitation_action": "",
|
||||
"diagnostic_authorization": "",
|
||||
"estimate": "",
|
||||
"estimate_detail": "",
|
||||
@@ -1976,6 +1984,8 @@
|
||||
"qc_sheet": "",
|
||||
"ro_totals": "",
|
||||
"ro_with_description": "",
|
||||
"sgi_certificate_of_repairs": "",
|
||||
"sgi_windshield_auth": "",
|
||||
"stolen_recovery_checklist": "",
|
||||
"supplement_request": "",
|
||||
"thank_you_ro": "",
|
||||
@@ -2008,6 +2018,11 @@
|
||||
"payments": {
|
||||
"ca_bc_etf_table": ""
|
||||
},
|
||||
"subjects": {
|
||||
"jobs": {
|
||||
"parts_order": ""
|
||||
}
|
||||
},
|
||||
"vendors": {
|
||||
"purchases_by_vendor_detailed": "",
|
||||
"purchases_by_vendor_summary": ""
|
||||
@@ -2072,10 +2087,18 @@
|
||||
"employee": "",
|
||||
"filterson": "",
|
||||
"generateasemail": "",
|
||||
"groups": {
|
||||
"customers": "",
|
||||
"jobs": "",
|
||||
"payroll": "",
|
||||
"purchases": "",
|
||||
"sales": ""
|
||||
},
|
||||
"key": "",
|
||||
"objects": {
|
||||
"appointments": "",
|
||||
"bills": "",
|
||||
"csi": "",
|
||||
"exportlogs": "",
|
||||
"jobs": "",
|
||||
"parts_orders": "",
|
||||
@@ -2091,6 +2114,7 @@
|
||||
"attendance_employee": "",
|
||||
"attendance_summary": "",
|
||||
"credits_not_received_date": "",
|
||||
"csi": "",
|
||||
"estimator_detail": "",
|
||||
"estimator_summary": "",
|
||||
"export_payables": "",
|
||||
|
||||
@@ -96,6 +96,9 @@
|
||||
"jobimported": "",
|
||||
"jobinproductionchange": "",
|
||||
"jobmodifylbradj": "",
|
||||
"jobnoteadded": "",
|
||||
"jobnotedeleted": "",
|
||||
"jobnoteupdated": "",
|
||||
"jobspartsorder": "",
|
||||
"jobspartsreturn": "",
|
||||
"jobstatuschange": "",
|
||||
@@ -179,6 +182,7 @@
|
||||
"noneselected": "",
|
||||
"onlycmforinvoiced": "",
|
||||
"retailtotal": "",
|
||||
"savewithdiscrepancy": "",
|
||||
"state_tax": "",
|
||||
"subtotal": "",
|
||||
"totalreturns": ""
|
||||
@@ -505,6 +509,7 @@
|
||||
"orderstatuses": "",
|
||||
"partslocations": "",
|
||||
"printlater": "",
|
||||
"qbo": "",
|
||||
"rbac": "",
|
||||
"responsibilitycenters": {
|
||||
"costs": "",
|
||||
@@ -685,7 +690,8 @@
|
||||
"status": {
|
||||
"in": "",
|
||||
"inservice": "",
|
||||
"out": ""
|
||||
"out": "",
|
||||
"sold": ""
|
||||
},
|
||||
"successes": {
|
||||
"saved": ""
|
||||
@@ -702,7 +708,8 @@
|
||||
"notfoundtitle": ""
|
||||
},
|
||||
"fields": {
|
||||
"completedon": ""
|
||||
"completedon": "",
|
||||
"created_at": ""
|
||||
},
|
||||
"labels": {
|
||||
"nologgedinuser": "",
|
||||
@@ -1946,6 +1953,7 @@
|
||||
"coversheet_landscape": "",
|
||||
"coversheet_portrait": "",
|
||||
"csi_invitation": "",
|
||||
"csi_invitation_action": "",
|
||||
"diagnostic_authorization": "",
|
||||
"estimate": "",
|
||||
"estimate_detail": "",
|
||||
@@ -1976,6 +1984,8 @@
|
||||
"qc_sheet": "",
|
||||
"ro_totals": "",
|
||||
"ro_with_description": "",
|
||||
"sgi_certificate_of_repairs": "",
|
||||
"sgi_windshield_auth": "",
|
||||
"stolen_recovery_checklist": "",
|
||||
"supplement_request": "",
|
||||
"thank_you_ro": "",
|
||||
@@ -2008,6 +2018,11 @@
|
||||
"payments": {
|
||||
"ca_bc_etf_table": ""
|
||||
},
|
||||
"subjects": {
|
||||
"jobs": {
|
||||
"parts_order": ""
|
||||
}
|
||||
},
|
||||
"vendors": {
|
||||
"purchases_by_vendor_detailed": "",
|
||||
"purchases_by_vendor_summary": ""
|
||||
@@ -2072,10 +2087,18 @@
|
||||
"employee": "",
|
||||
"filterson": "",
|
||||
"generateasemail": "",
|
||||
"groups": {
|
||||
"customers": "",
|
||||
"jobs": "",
|
||||
"payroll": "",
|
||||
"purchases": "",
|
||||
"sales": ""
|
||||
},
|
||||
"key": "",
|
||||
"objects": {
|
||||
"appointments": "",
|
||||
"bills": "",
|
||||
"csi": "",
|
||||
"exportlogs": "",
|
||||
"jobs": "",
|
||||
"parts_orders": "",
|
||||
@@ -2091,6 +2114,7 @@
|
||||
"attendance_employee": "",
|
||||
"attendance_summary": "",
|
||||
"credits_not_received_date": "",
|
||||
"csi": "",
|
||||
"estimator_detail": "",
|
||||
"estimator_summary": "",
|
||||
"export_payables": "",
|
||||
|
||||
@@ -26,6 +26,9 @@ const AuditTrailMapping = {
|
||||
i18n.t("audit_trail.messages.jobinproductionchange", { inproduction }),
|
||||
jobchecklist: (type, inproduction, status) =>
|
||||
i18n.t("audit_trail.messages.jobchecklist", { type, inproduction, status }),
|
||||
jobnoteadded: () => i18n.t("audit_trail.messages.jobnoteadded"),
|
||||
jobnoteupdated: () => i18n.t("audit_trail.messages.jobnoteupdated"),
|
||||
jobnotedeleted: () => i18n.t("audit_trail.messages.jobnotedeleted"),
|
||||
};
|
||||
|
||||
export default AuditTrailMapping;
|
||||
|
||||
@@ -38,9 +38,9 @@ const roundTripLink = new ApolloLink((operation, forward) => {
|
||||
return forward(operation).map((data) => {
|
||||
// Called after server responds
|
||||
const time = new Date() - operation.getContext().start;
|
||||
console.log(
|
||||
`Operation ${operation.operationName} took ${time} to complete`
|
||||
);
|
||||
// console.log(
|
||||
// `Operation ${operation.operationName} took ${time} to complete`
|
||||
// );
|
||||
TrackExecutionTime(operation.operationName, time);
|
||||
return data;
|
||||
});
|
||||
|
||||
@@ -352,6 +352,28 @@ export const TemplateList = (type, context) => {
|
||||
disabled: false,
|
||||
group: "ro",
|
||||
},
|
||||
sgi_certificate_of_repairs: {
|
||||
title: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
||||
description: "Thank You Letter by RO",
|
||||
key: "sgi_certificate_of_repairs",
|
||||
subject: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
||||
disabled: false,
|
||||
group: "ro",
|
||||
regions: {
|
||||
CA_SK: true,
|
||||
},
|
||||
},
|
||||
sgi_windshield_auth: {
|
||||
title: i18n.t("printcenter.jobs.sgi_windshield_auth"),
|
||||
description: "Thank You Letter by RO",
|
||||
key: "sgi_windshield_auth",
|
||||
subject: i18n.t("printcenter.jobs.sgi_windshield_auth"),
|
||||
disabled: false,
|
||||
group: "pre",
|
||||
regions: {
|
||||
CA_SK: true,
|
||||
},
|
||||
},
|
||||
// parts_label_multi: {
|
||||
// title: i18n.t("printcenter.jobs.parts_label_multi"),
|
||||
// description: "Thank You Letter by RO",
|
||||
@@ -370,6 +392,13 @@ export const TemplateList = (type, context) => {
|
||||
key: "special_thirdpartypayer",
|
||||
disabled: false,
|
||||
},
|
||||
csi_invitation_action: {
|
||||
title: i18n.t("printcenter.jobs.csi_invitation_action"),
|
||||
description: "CSI invite",
|
||||
key: "csi_invitation_action",
|
||||
subject: i18n.t("printcenter.jobs.csi_invitation_action"),
|
||||
disabled: false,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(!type || type === "appointment"
|
||||
@@ -391,7 +420,9 @@ export const TemplateList = (type, context) => {
|
||||
title: i18n.t("printcenter.jobs.parts_order"),
|
||||
description: "Parts Order",
|
||||
key: "parts_order",
|
||||
subject: i18n.t("printcenter.jobs.parts_order"),
|
||||
subject: i18n.t("printcenter.subjects.jobs.parts_order", {
|
||||
ro_number: context && context.job && context.job.ro_number,
|
||||
}),
|
||||
disabled: false,
|
||||
},
|
||||
parts_return_slip: {
|
||||
@@ -417,222 +448,6 @@ export const TemplateList = (type, context) => {
|
||||
...(!type || type === "csi" ? {} : {}),
|
||||
...(!type || type === "report_center"
|
||||
? {
|
||||
payments_by_date: {
|
||||
title: i18n.t("reportcenter.templates.payments_by_date"),
|
||||
subject: i18n.t("reportcenter.templates.payments_by_date"),
|
||||
key: "payments_by_date",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.payments"),
|
||||
field: i18n.t("payments.fields.date"),
|
||||
},
|
||||
},
|
||||
payments_by_date_type: {
|
||||
title: i18n.t("reportcenter.templates.payments_by_date_type"),
|
||||
subject: i18n.t("reportcenter.templates.payments_by_date_type"),
|
||||
key: "payments_by_date_type",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.payments"),
|
||||
field: i18n.t("payments.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_by_date_range_detail: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_detail"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_detail"
|
||||
),
|
||||
key: "purchases_by_date_range_detail",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_by_date_range_summary: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_summary"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_summary"
|
||||
),
|
||||
key: "purchases_by_date_range_summary",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_by_vendor_detailed_date_range: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_detailed_date_range"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_detailed_date_range"
|
||||
),
|
||||
key: "purchases_by_vendor_detailed_date_range",
|
||||
idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_by_vendor_summary_date_range: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_summary_date_range"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_summary_date_range"
|
||||
),
|
||||
key: "purchases_by_vendor_summary_date_range",
|
||||
idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_by_cost_center_detail: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_detail"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_detail"
|
||||
),
|
||||
key: "purchases_by_cost_center_detail",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_by_cost_center_summary: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_summary"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_summary"
|
||||
),
|
||||
key: "purchases_by_cost_center_summary",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_grouped_by_vendor_detailed: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_detailed"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_detailed"
|
||||
),
|
||||
key: "purchases_grouped_by_vendor_detailed",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
purchases_grouped_by_vendor_summary: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_summary"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_summary"
|
||||
),
|
||||
key: "purchases_grouped_by_vendor_summary",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
},
|
||||
schedule: {
|
||||
title: i18n.t("reportcenter.templates.schedule"),
|
||||
subject: i18n.t("reportcenter.templates.schedule"),
|
||||
key: "schedule",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.appointments"),
|
||||
field: i18n.t("appointments.fields.time"),
|
||||
},
|
||||
},
|
||||
|
||||
timetickets: {
|
||||
title: i18n.t("reportcenter.templates.timetickets"),
|
||||
subject: i18n.t("reportcenter.templates.timetickets"),
|
||||
key: "timetickets",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
},
|
||||
timetickets_employee: {
|
||||
title: i18n.t("reportcenter.templates.timetickets_employee"),
|
||||
subject: i18n.t("reportcenter.templates.timetickets_employee"),
|
||||
key: "timetickets_employee",
|
||||
idtype: "employee",
|
||||
disabled: false,
|
||||
},
|
||||
attendance_detail: {
|
||||
title: i18n.t("reportcenter.templates.attendance_detail"),
|
||||
subject: i18n.t("reportcenter.templates.attendance_detail"),
|
||||
key: "attendance_detail",
|
||||
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
},
|
||||
attendance_summary: {
|
||||
title: i18n.t("reportcenter.templates.attendance_summary"),
|
||||
subject: i18n.t("reportcenter.templates.attendance_summary"),
|
||||
key: "attendance_summary",
|
||||
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
},
|
||||
attendance_employee: {
|
||||
title: i18n.t("reportcenter.templates.attendance_employee"),
|
||||
subject: i18n.t("reportcenter.templates.attendance_employee"),
|
||||
key: "attendance_employee",
|
||||
idtype: "employee",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
},
|
||||
|
||||
timetickets_summary: {
|
||||
title: i18n.t("reportcenter.templates.timetickets_summary"),
|
||||
subject: i18n.t("reportcenter.templates.timetickets_summary"),
|
||||
key: "timetickets_summary",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
},
|
||||
|
||||
hours_sold_detail_closed: {
|
||||
title: i18n.t("reportcenter.templates.hours_sold_detail_closed"),
|
||||
description: "",
|
||||
@@ -644,6 +459,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_detail_closed_ins_co: {
|
||||
@@ -661,6 +477,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_summary_closed: {
|
||||
@@ -674,6 +491,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_summary_closed_ins_co: {
|
||||
@@ -691,6 +509,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_detail_open: {
|
||||
@@ -704,6 +523,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_detail_open_ins_co: {
|
||||
@@ -721,6 +541,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_summary_open: {
|
||||
@@ -734,6 +555,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_summary_open_ins_co: {
|
||||
@@ -751,6 +573,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
hours_sold_detail_closed_csr: {
|
||||
@@ -768,6 +591,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
hours_sold_detail_open_csr: {
|
||||
title: i18n.t("reportcenter.templates.hours_sold_detail_open_csr"),
|
||||
@@ -782,6 +606,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
hours_sold_summary_closed_csr: {
|
||||
title: i18n.t(
|
||||
@@ -798,6 +623,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
hours_sold_summary_open_csr: {
|
||||
title: i18n.t("reportcenter.templates.hours_sold_summary_open_csr"),
|
||||
@@ -812,54 +638,137 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
estimator_detail: {
|
||||
title: i18n.t("reportcenter.templates.estimator_detail"),
|
||||
purchases_by_date_range_detail: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_detail"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_detail"
|
||||
),
|
||||
key: "purchases_by_date_range_detail",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
purchases_by_date_range_summary: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_summary"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_date_range_summary"
|
||||
),
|
||||
key: "purchases_by_date_range_summary",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
purchases_by_vendor_detailed_date_range: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_detailed_date_range"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_detailed_date_range"
|
||||
),
|
||||
key: "purchases_by_vendor_detailed_date_range",
|
||||
idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
purchases_by_vendor_summary_date_range: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_summary_date_range"
|
||||
),
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_vendor_summary_date_range"
|
||||
),
|
||||
key: "purchases_by_vendor_summary_date_range",
|
||||
idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
purchases_by_cost_center_detail: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_detail"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.estimator_detail"),
|
||||
key: "estimator_detail",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_detail"
|
||||
),
|
||||
key: "purchases_by_cost_center_detail",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
purchases_by_cost_center_summary: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_summary"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_by_cost_center_summary"
|
||||
),
|
||||
key: "purchases_by_cost_center_summary",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
purchases_grouped_by_vendor_detailed: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_detailed"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_detailed"
|
||||
),
|
||||
key: "purchases_grouped_by_vendor_detailed",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
estimator_summary: {
|
||||
title: i18n.t("reportcenter.templates.estimator_summary"),
|
||||
purchases_grouped_by_vendor_summary: {
|
||||
title: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_summary"
|
||||
),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.estimator_summary"),
|
||||
key: "estimator_summary",
|
||||
subject: i18n.t(
|
||||
"reportcenter.templates.purchases_grouped_by_vendor_summary"
|
||||
),
|
||||
key: "purchases_grouped_by_vendor_summary",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
},
|
||||
supplement_ratio_ins_co: {
|
||||
title: i18n.t("reportcenter.templates.supplement_ratio_ins_co"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.supplement_ratio_ins_co"),
|
||||
key: "supplement_ratio_ins_co",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
},
|
||||
credits_not_received_date: {
|
||||
title: i18n.t("reportcenter.templates.credits_not_received_date"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.credits_not_received_date"),
|
||||
key: "credits_not_received_date",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
field: i18n.t("bills.fields.date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
job_costing_ro_date_summary: {
|
||||
title: i18n.t("reportcenter.templates.job_costing_ro_date_summary"),
|
||||
@@ -874,6 +783,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
job_costing_ro_csr: {
|
||||
title: i18n.t("reportcenter.templates.job_costing_ro_csr"),
|
||||
@@ -886,6 +796,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
job_costing_ro_ins_co: {
|
||||
title: i18n.t("reportcenter.templates.job_costing_ro_ins_co"),
|
||||
@@ -898,6 +809,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
job_costing_ro_date_detail: {
|
||||
title: i18n.t("reportcenter.templates.job_costing_ro_date_detail"),
|
||||
@@ -912,6 +824,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
job_costing_ro_estimator: {
|
||||
title: i18n.t("reportcenter.templates.job_costing_ro_estimator"),
|
||||
@@ -924,7 +837,165 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
payments_by_date: {
|
||||
title: i18n.t("reportcenter.templates.payments_by_date"),
|
||||
subject: i18n.t("reportcenter.templates.payments_by_date"),
|
||||
key: "payments_by_date",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.payments"),
|
||||
field: i18n.t("payments.fields.date"),
|
||||
},
|
||||
group: "customers",
|
||||
},
|
||||
payments_by_date_type: {
|
||||
title: i18n.t("reportcenter.templates.payments_by_date_type"),
|
||||
subject: i18n.t("reportcenter.templates.payments_by_date_type"),
|
||||
key: "payments_by_date_type",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.payments"),
|
||||
field: i18n.t("payments.fields.date"),
|
||||
},
|
||||
group: "customers",
|
||||
},
|
||||
|
||||
schedule: {
|
||||
title: i18n.t("reportcenter.templates.schedule"),
|
||||
subject: i18n.t("reportcenter.templates.schedule"),
|
||||
key: "schedule",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.appointments"),
|
||||
field: i18n.t("appointments.fields.time"),
|
||||
},
|
||||
group: "customers",
|
||||
},
|
||||
|
||||
timetickets: {
|
||||
title: i18n.t("reportcenter.templates.timetickets"),
|
||||
subject: i18n.t("reportcenter.templates.timetickets"),
|
||||
key: "timetickets",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
timetickets_employee: {
|
||||
title: i18n.t("reportcenter.templates.timetickets_employee"),
|
||||
subject: i18n.t("reportcenter.templates.timetickets_employee"),
|
||||
key: "timetickets_employee",
|
||||
idtype: "employee",
|
||||
disabled: false,
|
||||
group: "payroll",
|
||||
},
|
||||
attendance_detail: {
|
||||
title: i18n.t("reportcenter.templates.attendance_detail"),
|
||||
subject: i18n.t("reportcenter.templates.attendance_detail"),
|
||||
key: "attendance_detail",
|
||||
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
attendance_summary: {
|
||||
title: i18n.t("reportcenter.templates.attendance_summary"),
|
||||
subject: i18n.t("reportcenter.templates.attendance_summary"),
|
||||
key: "attendance_summary",
|
||||
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
attendance_employee: {
|
||||
title: i18n.t("reportcenter.templates.attendance_employee"),
|
||||
subject: i18n.t("reportcenter.templates.attendance_employee"),
|
||||
key: "attendance_employee",
|
||||
idtype: "employee",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
|
||||
timetickets_summary: {
|
||||
title: i18n.t("reportcenter.templates.timetickets_summary"),
|
||||
subject: i18n.t("reportcenter.templates.timetickets_summary"),
|
||||
key: "timetickets_summary",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||
field: i18n.t("timetickets.fields.date"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
|
||||
estimator_detail: {
|
||||
title: i18n.t("reportcenter.templates.estimator_detail"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.estimator_detail"),
|
||||
key: "estimator_detail",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
estimator_summary: {
|
||||
title: i18n.t("reportcenter.templates.estimator_summary"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.estimator_summary"),
|
||||
key: "estimator_summary",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
supplement_ratio_ins_co: {
|
||||
title: i18n.t("reportcenter.templates.supplement_ratio_ins_co"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.supplement_ratio_ins_co"),
|
||||
key: "supplement_ratio_ins_co",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
credits_not_received_date: {
|
||||
title: i18n.t("reportcenter.templates.credits_not_received_date"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.credits_not_received_date"),
|
||||
key: "credits_not_received_date",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
|
||||
void_ros: {
|
||||
title: i18n.t("reportcenter.templates.void_ros"),
|
||||
description: "",
|
||||
@@ -936,6 +1007,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_by_csr: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_csr"),
|
||||
@@ -948,6 +1020,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_by_make: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_make"),
|
||||
@@ -960,6 +1033,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_by_delivery_date: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_delivery_date"),
|
||||
@@ -972,6 +1046,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.actual_delivery"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_by_referral: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_referral"),
|
||||
@@ -984,6 +1059,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_by_ro: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_ro"),
|
||||
@@ -996,6 +1072,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_by_ins_co: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_ins_co"),
|
||||
@@ -1008,6 +1085,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_by_exported_date: {
|
||||
title: i18n.t("reportcenter.templates.gsr_by_exported_date"),
|
||||
@@ -1020,6 +1098,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_exported"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
|
||||
gsr_by_estimator: {
|
||||
@@ -1033,6 +1112,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
gsr_labor_only: {
|
||||
title: i18n.t("reportcenter.templates.gsr_labor_only"),
|
||||
@@ -1045,6 +1125,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
open_orders: {
|
||||
title: i18n.t("reportcenter.templates.open_orders"),
|
||||
@@ -1057,6 +1138,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
open_orders_csr: {
|
||||
title: i18n.t("reportcenter.templates.open_orders_csr"),
|
||||
@@ -1069,6 +1151,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
open_orders_estimator: {
|
||||
title: i18n.t("reportcenter.templates.open_orders_estimator"),
|
||||
@@ -1081,6 +1164,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
open_orders_ins_co: {
|
||||
title: i18n.t("reportcenter.templates.open_orders_ins_co"),
|
||||
@@ -1093,6 +1177,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
export_payables: {
|
||||
title: i18n.t("reportcenter.templates.export_payables"),
|
||||
@@ -1105,6 +1190,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.exportlogs"),
|
||||
field: i18n.t("exportlogs.fields.createdat"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
export_payments: {
|
||||
title: i18n.t("reportcenter.templates.export_payments"),
|
||||
@@ -1117,6 +1203,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.exportlogs"),
|
||||
field: i18n.t("exportlogs.fields.createdat"),
|
||||
},
|
||||
group: "customers",
|
||||
},
|
||||
export_receivables: {
|
||||
title: i18n.t("reportcenter.templates.export_receivables"),
|
||||
@@ -1129,6 +1216,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.exportlogs"),
|
||||
field: i18n.t("exportlogs.fields.createdat"),
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
parts_backorder: {
|
||||
title: i18n.t("reportcenter.templates.parts_backorder"),
|
||||
@@ -1141,6 +1229,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.actual_in"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
thank_you_date: {
|
||||
title: i18n.t("reportcenter.templates.thank_you_date"),
|
||||
@@ -1153,6 +1242,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "customers",
|
||||
},
|
||||
unclaimed_hrs: {
|
||||
title: i18n.t("reportcenter.templates.unclaimed_hrs"),
|
||||
@@ -1165,6 +1255,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
work_in_progress_labour: {
|
||||
title: i18n.t("reportcenter.templates.work_in_progress_labour"),
|
||||
@@ -1177,6 +1268,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
work_in_progress_payables: {
|
||||
title: i18n.t("reportcenter.templates.work_in_progress_payables"),
|
||||
@@ -1189,6 +1281,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
lag_time: {
|
||||
title: i18n.t("reportcenter.templates.lag_time"),
|
||||
@@ -1201,6 +1294,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
parts_not_recieved: {
|
||||
title: i18n.t("reportcenter.templates.parts_not_recieved"),
|
||||
@@ -1213,6 +1307,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.parts_orders"),
|
||||
field: i18n.t("parts_orders.fields.order_date"),
|
||||
},
|
||||
group: "purchases",
|
||||
},
|
||||
scoreboard_detail: {
|
||||
title: i18n.t("reportcenter.templates.scoreboard_detail"),
|
||||
@@ -1225,6 +1320,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.scoreboard"),
|
||||
field: i18n.t("scoreboard.fields.date"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
scoreboard_summary: {
|
||||
title: i18n.t("reportcenter.templates.scoreboard_summary"),
|
||||
@@ -1237,6 +1333,7 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.scoreboard"),
|
||||
field: i18n.t("scoreboard.fields.date"),
|
||||
},
|
||||
group: "payroll",
|
||||
},
|
||||
anticipated_revenue: {
|
||||
title: i18n.t("reportcenter.templates.anticipated_revenue"),
|
||||
@@ -1249,6 +1346,20 @@ export const TemplateList = (type, context) => {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.scheduled_completion"), // Also date invoice.
|
||||
},
|
||||
group: "sales",
|
||||
},
|
||||
csi: {
|
||||
title: i18n.t("reportcenter.templates.csi"),
|
||||
description: "",
|
||||
subject: i18n.t("reportcenter.templates.csi"),
|
||||
key: "csi",
|
||||
//idtype: "vendor",
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.csi"),
|
||||
field: i18n.t("csi.fields.created_at"), // Also date invoice.
|
||||
},
|
||||
group: "customers",
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
|
||||
9
client/src/utils/asyncConfirm.js
Normal file
@@ -0,0 +1,9 @@
|
||||
function confirmDialog(msg) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let confirmed = window.confirm(msg);
|
||||
|
||||
return confirmed ? resolve(true) : resolve(false);
|
||||
});
|
||||
}
|
||||
|
||||
export default confirmDialog;
|
||||
867
client/yarn.lock
@@ -1,2 +1,7 @@
|
||||
version: 2
|
||||
endpoint: https://bodyshop-dev-db.herokuapp.com
|
||||
admin_secret: Dev-BodyShopApp!
|
||||
metadata_directory: metadata
|
||||
actions:
|
||||
kind: synchronous
|
||||
handler_webhook_baseurl: http://localhost:3000
|
||||
|
||||
0
hasura/metadata/actions.graphql
Normal file
6
hasura/metadata/actions.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
actions: []
|
||||
custom_types:
|
||||
enums: []
|
||||
input_objects: []
|
||||
objects: []
|
||||
scalars: []
|
||||
1
hasura/metadata/allow_list.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
hasura/metadata/cron_triggers.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
27
hasura/metadata/functions.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
- function:
|
||||
schema: public
|
||||
name: search_bills
|
||||
- function:
|
||||
schema: public
|
||||
name: search_cccontracts
|
||||
- function:
|
||||
schema: public
|
||||
name: search_dms_vehicles
|
||||
- function:
|
||||
schema: public
|
||||
name: search_exportlog
|
||||
- function:
|
||||
schema: public
|
||||
name: search_jobs
|
||||
- function:
|
||||
schema: public
|
||||
name: search_owners
|
||||
- function:
|
||||
schema: public
|
||||
name: search_payments
|
||||
- function:
|
||||
schema: public
|
||||
name: search_phonebook
|
||||
- function:
|
||||
schema: public
|
||||
name: search_vehicles
|
||||
1
hasura/metadata/query_collections.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
hasura/metadata/remote_schemas.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
4775
hasura/metadata/tables.yaml
Normal file
1
hasura/metadata/version.yaml
Normal file
@@ -0,0 +1 @@
|
||||
version: 2
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "website";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "website" text NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."documents" DROP COLUMN "takenat";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."documents" ADD COLUMN "takenat" timestamptz NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD CONSTRAINT "bodyshops_autohouseid_key" UNIQUE ("autohouseid");
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP CONSTRAINT "bodyshops_autohouseid_key";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "jc_hourly_rates";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "jc_hourly_rates" jsonb NULL DEFAULT jsonb_build_object();
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."vehicles" ALTER COLUMN "v_vin" SET NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."vehicles" ALTER COLUMN "v_vin" DROP NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE ONLY "public"."joblines" ALTER COLUMN "prt_dsmk_p" DROP DEFAULT;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE ONLY "public"."joblines" ALTER COLUMN "prt_dsmk_p" SET DEFAULT 0;
|
||||
3
hasura/migrations/1622571551101_run_sql_migration/up.sql
Executable file
@@ -0,0 +1,3 @@
|
||||
|
||||
update joblines
|
||||
set prt_dsmk_p = 0 where joblines.prt_dsmk_p is null;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."conversations" DROP COLUMN "archived";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."conversations" ADD COLUMN "archived" boolean NOT NULL DEFAULT false;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."parts_orders" DROP COLUMN "orderedby";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."parts_orders" ADD COLUMN "orderedby" text NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
alter table "public"."parts_orders" drop constraint "parts_orders_orderedby_fkey";
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."parts_orders"
|
||||
add constraint "parts_orders_orderedby_fkey"
|
||||
foreign key ("orderedby")
|
||||
references "public"."users"
|
||||
("email") on update set null on delete set null;
|
||||
8
hasura/migrations/1622650359491_set_fk_public_exportlog_billid/down.sql
Executable file
@@ -0,0 +1,8 @@
|
||||
|
||||
alter table "public"."exportlog" drop constraint "exportlog_billid_fkey",
|
||||
add constraint "exportlog_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id")
|
||||
on update restrict
|
||||
on delete restrict;
|
||||
6
hasura/migrations/1622650359491_set_fk_public_exportlog_billid/up.sql
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."exportlog" drop constraint "exportlog_billid_fkey",
|
||||
add constraint "exportlog_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id") on update cascade on delete cascade;
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
ALTER TABLE ONLY "public"."users" ALTER COLUMN "dashboardlayout" SET DEFAULT jsonb_build_array();
|
||||
ALTER TABLE "public"."users" ALTER COLUMN "dashboardlayout" SET NOT NULL;
|
||||