Compare commits
31 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c0dab92d0e | ||
|
|
1a4bc720c2 | ||
|
|
18998c4dbe | ||
|
|
e236d6e912 | ||
|
|
523df670df | ||
|
|
ce58181fc3 | ||
|
|
bed0669f73 | ||
|
|
bdb2951330 | ||
|
|
87a01208fb | ||
|
|
2daee84fbf | ||
|
|
cdbf58f3ac | ||
|
|
f6a59bdf55 | ||
|
|
e12edd977e | ||
|
|
b925c991eb | ||
|
|
1e7f43fe3d | ||
|
|
6f21de1901 | ||
|
|
25e8eaa1d4 | ||
|
|
6fe736ce06 | ||
|
|
482b03c2d1 | ||
|
|
ce3c72fc47 | ||
|
|
1ff5ed4141 | ||
|
|
10e3421572 | ||
|
|
0117237988 | ||
|
|
373fd817d0 | ||
|
|
0ef2d9646d | ||
|
|
c8ac417200 | ||
|
|
661bedbe5b | ||
|
|
2dd56590d3 | ||
|
|
98b760251c | ||
|
|
b97de32a44 | ||
|
|
92c8b54f85 |
@@ -68,120 +68,6 @@ jobs:
|
|||||||
from: build
|
from: build
|
||||||
to: "s3://imex-online-production/"
|
to: "s3://imex-online-production/"
|
||||||
- jira/notify
|
- jira/notify
|
||||||
|
|
||||||
rome-api-deploy:
|
|
||||||
docker:
|
|
||||||
- image: "cimg/base:stable"
|
|
||||||
steps:
|
|
||||||
- checkout
|
|
||||||
- eb/setup
|
|
||||||
- run:
|
|
||||||
command: |
|
|
||||||
eb init romeonline-productionapi -r us-east-2 -p "Node.js 18 running on 64bit Amazon Linux 2"
|
|
||||||
eb status --verbose
|
|
||||||
eb deploy
|
|
||||||
eb status
|
|
||||||
- jira/notify
|
|
||||||
|
|
||||||
rome-hasura-migrate:
|
|
||||||
docker:
|
|
||||||
- image: cimg/node:16.15.0
|
|
||||||
parameters:
|
|
||||||
secret:
|
|
||||||
type: string
|
|
||||||
default: $HASURA_PROD_SECRET
|
|
||||||
working_directory: ~/repo/hasura
|
|
||||||
steps:
|
|
||||||
- checkout:
|
|
||||||
path: ~/repo
|
|
||||||
- run:
|
|
||||||
name: Execute migration
|
|
||||||
command: |
|
|
||||||
npm install hasura-cli -g
|
|
||||||
hasura migrate apply --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
|
||||||
hasura metadata apply --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
|
||||||
hasura metadata reload --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
|
||||||
|
|
||||||
rome-app-build:
|
|
||||||
docker:
|
|
||||||
- image: cimg/node:16.15.0
|
|
||||||
|
|
||||||
working_directory: ~/repo/client
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- checkout:
|
|
||||||
path: ~/repo
|
|
||||||
|
|
||||||
- restore_cache:
|
|
||||||
name: Restore Yarn Package Cache
|
|
||||||
keys:
|
|
||||||
- yarn-packages-{{ checksum "yarn.lock" }}
|
|
||||||
- run:
|
|
||||||
name: Install Dependencies
|
|
||||||
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
|
||||||
- save_cache:
|
|
||||||
name: Save Yarn Package Cache
|
|
||||||
key: yarn-packages-{{ checksum "yarn.lock" }}
|
|
||||||
paths:
|
|
||||||
- ~/.cache/yarn
|
|
||||||
|
|
||||||
- run: yarn run build
|
|
||||||
|
|
||||||
- aws-s3/sync:
|
|
||||||
from: build
|
|
||||||
to: "s3://rome-online-production/"
|
|
||||||
- jira/notify
|
|
||||||
|
|
||||||
test-rome-hasura-migrate:
|
|
||||||
docker:
|
|
||||||
- image: cimg/node:16.15.0
|
|
||||||
parameters:
|
|
||||||
secret:
|
|
||||||
type: string
|
|
||||||
default: $HASURA_ROME_TEST_SECRET
|
|
||||||
working_directory: ~/repo/hasura
|
|
||||||
steps:
|
|
||||||
- checkout:
|
|
||||||
path: ~/repo
|
|
||||||
- run:
|
|
||||||
name: Execute migration
|
|
||||||
command: |
|
|
||||||
npm install hasura-cli -g
|
|
||||||
echo ${HASURA_TEST_SECRET}
|
|
||||||
hasura migrate apply --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
|
||||||
hasura metadata apply --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
|
||||||
hasura metadata reload --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
|
||||||
|
|
||||||
test-rome-app-build:
|
|
||||||
docker:
|
|
||||||
- image: cimg/node:16.15.0
|
|
||||||
|
|
||||||
working_directory: ~/repo/client
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- checkout:
|
|
||||||
path: ~/repo
|
|
||||||
|
|
||||||
- restore_cache:
|
|
||||||
name: Restore Yarn Package Cache
|
|
||||||
keys:
|
|
||||||
- yarn-packages-{{ checksum "yarn.lock" }}
|
|
||||||
- run:
|
|
||||||
name: Install Dependencies
|
|
||||||
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
|
|
||||||
- save_cache:
|
|
||||||
name: Save Yarn Package Cache
|
|
||||||
key: yarn-packages-{{ checksum "yarn.lock" }}
|
|
||||||
paths:
|
|
||||||
- ~/.cache/yarn
|
|
||||||
|
|
||||||
- run: yarn run build:test
|
|
||||||
|
|
||||||
- aws-s3/sync:
|
|
||||||
from: build
|
|
||||||
to: "s3://rome-online-test/"
|
|
||||||
- jira/notify
|
|
||||||
|
|
||||||
|
|
||||||
test-hasura-migrate:
|
test-hasura-migrate:
|
||||||
docker:
|
docker:
|
||||||
@@ -279,19 +165,6 @@ workflows:
|
|||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: master
|
only: master
|
||||||
- rome-api-deploy:
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: rome/master
|
|
||||||
- rome-app-build:
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: rome/master
|
|
||||||
- rome-hasura-migrate:
|
|
||||||
secret: ${HASURA_PROD_SECRET}
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: rome/master
|
|
||||||
- test-app-build:
|
- test-app-build:
|
||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
@@ -301,15 +174,6 @@ workflows:
|
|||||||
filters:
|
filters:
|
||||||
branches:
|
branches:
|
||||||
only: test
|
only: test
|
||||||
- test-rome-app-build:
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: rome/test
|
|
||||||
- test-rome-hasura-migrate:
|
|
||||||
secret: ${HASURA_ROME_TEST_SECRET}
|
|
||||||
filters:
|
|
||||||
branches:
|
|
||||||
only: rome/test
|
|
||||||
#- admin-app-build:
|
#- admin-app-build:
|
||||||
#filters:
|
#filters:
|
||||||
#branches:
|
#branches:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,13 @@
|
|||||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
REACT_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||||
REACT_APP_GA_CODE=231099835
|
REACT_APP_GA_CODE=231099835
|
||||||
REACT_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
REACT_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
||||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||||
REACT_APP_CLOUDINARY_API_KEY=957865933348715
|
REACT_APP_CLOUDINARY_API_KEY=957865933348715
|
||||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
|
||||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||||
REACT_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
REACT_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||||
REACT_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
REACT_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||||
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||||
REACT_APP_COUNTRY=USA
|
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.romeonline.io/v1/graphql
|
GENERATE_SOURCEMAP=false
|
||||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.romeonline.io/v1/graphql
|
REACT_APP_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql
|
||||||
|
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.imex.online/v1/graphql
|
||||||
REACT_APP_GA_CODE=231103507
|
REACT_APP_GA_CODE=231103507
|
||||||
REACT_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
REACT_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU","authDomain":"imex-prod.firebaseapp.com","databaseURL":"https://imex-prod.firebaseio.com","projectId":"imex-prod","storageBucket":"imex-prod.appspot.com","messagingSenderId":"253497221485","appId":"1:253497221485:web:3c81c483b94db84b227a64","measurementId":"G-NTWBKG2L0M"}
|
||||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||||
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
||||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BMgZT1NZztW2DsJl8Mg2L04hgY9FzAg6b8fbzgNAfww2VDzH3VE63Ot9EaP_U7KWS2JT-7HPHaw0T_Tw_5vkZc8'
|
||||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||||
REACT_APP_AXIOS_BASE_API_URL=https://api.romeonline.io/
|
REACT_APP_AXIOS_BASE_API_URL=https://api.imex.online/
|
||||||
REACT_APP_REPORTS_SERVER_URL=https://reports.romeonline.io
|
REACT_APP_REPORTS_SERVER_URL=https://reports.imex.online
|
||||||
REACT_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
REACT_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.test.romeonline.io/v1/graphql
|
REACT_APP_GRAPHQL_ENDPOINT=https://db.test.bodyshop.app/v1/graphql
|
||||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.romeonline.io/v1/graphql
|
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.bodyshop.app/v1/graphql
|
||||||
REACT_APP_GA_CODE=231103507
|
REACT_APP_GA_CODE=231099835
|
||||||
REACT_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
REACT_APP_FIREBASE_CONFIG={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"}
|
||||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||||
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
||||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
|
||||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||||
REACT_APP_AXIOS_BASE_API_URL=https://api.test.romeonline.io/
|
REACT_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/
|
||||||
REACT_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io
|
REACT_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||||
REACT_APP_IS_TEST=true
|
REACT_APP_IS_TEST=true
|
||||||
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||||
@@ -12,7 +12,7 @@ module.exports = {
|
|||||||
authToken:
|
authToken:
|
||||||
"6b45b028a02342db97a9a2f92c0959058665443d379d4a3a876430009e744260",
|
"6b45b028a02342db97a9a2f92c0959058665443d379d4a3a876430009e744260",
|
||||||
org: "snapt-software",
|
org: "snapt-software",
|
||||||
project: "rome-online",
|
project: "imexonline",
|
||||||
release: process.env.REACT_APP_GIT_SHA,
|
release: process.env.REACT_APP_GIT_SHA,
|
||||||
|
|
||||||
// webpack-specific configuration
|
// webpack-specific configuration
|
||||||
@@ -27,7 +27,7 @@ module.exports = {
|
|||||||
lessOptions: {
|
lessOptions: {
|
||||||
modifyVars: {
|
modifyVars: {
|
||||||
...(process.env.NODE_ENV === "development"
|
...(process.env.NODE_ENV === "development"
|
||||||
? { "@primary-color": "#B22234" }
|
? { "@primary-color": "#a51d1d" }
|
||||||
: {
|
: {
|
||||||
//"@primary-color": "#1DA57A"
|
//"@primary-color": "#1DA57A"
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -28,17 +28,6 @@ switch (this.location.hostname) {
|
|||||||
// measurementId: "${config.measurementId}",
|
// measurementId: "${config.measurementId}",
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case "romeonline.io":
|
|
||||||
firebaseConfig = {
|
|
||||||
apiKey: "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE",
|
|
||||||
authDomain: "rome-prod-1.firebaseapp.com",
|
|
||||||
projectId: "rome-prod-1",
|
|
||||||
storageBucket: "rome-prod-1.appspot.com",
|
|
||||||
messagingSenderId: "147786367145",
|
|
||||||
appId: "1:147786367145:web:9d4cba68071c3f29a8a9b8",
|
|
||||||
measurementId: "G-G8Z9DRHTZS",
|
|
||||||
};
|
|
||||||
break;
|
|
||||||
case "imex.online":
|
case "imex.online":
|
||||||
default:
|
default:
|
||||||
firebaseConfig = {
|
firebaseConfig = {
|
||||||
|
|||||||
@@ -2,81 +2,23 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%PUBLIC_URL%/ro-favicon.png" />
|
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="theme-color" content="#002366" />
|
<meta name="theme-color" content="#002366" />
|
||||||
<meta name="description" content="Rome Online" />
|
<meta name="description" content="ImEX Online" />
|
||||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||||
|
|
||||||
<!--Use the below code snippet to provide real time updates to the live chat plugin without the need of copying and paste each time to your website when changes are made via PBX-->
|
|
||||||
|
|
||||||
<call-us-selector phonesystem-url=https://rometech.east.3cx.us:5001 party="LiveChat528346"></call-us-selector>
|
|
||||||
|
|
||||||
<!--Incase you don't want real time updates to the live chat plugin when options are changed, use the below code snippet. Please note that each time you change the settings you will need to copy and paste the snippet code to your website-->
|
|
||||||
|
|
||||||
<!--<call-us
|
|
||||||
|
|
||||||
phonesystem-url=https://rometech.east.3cx.us:5001
|
|
||||||
|
|
||||||
style="position:fixed;font-size:16px;line-height:17px;z-index: 99999;right: 20px; bottom: 20px;"
|
|
||||||
|
|
||||||
id="wp-live-chat-by-3CX"
|
|
||||||
|
|
||||||
minimized="true"
|
|
||||||
|
|
||||||
animation-style="noanimation"
|
|
||||||
|
|
||||||
party="LiveChat528346"
|
|
||||||
|
|
||||||
minimized-style="bubbleright"
|
|
||||||
|
|
||||||
allow-call="true"
|
|
||||||
|
|
||||||
allow-video="false"
|
|
||||||
|
|
||||||
allow-soundnotifications="true"
|
|
||||||
|
|
||||||
enable-mute="true"
|
|
||||||
|
|
||||||
enable-onmobile="true"
|
|
||||||
|
|
||||||
offline-enabled="true"
|
|
||||||
|
|
||||||
enable="true"
|
|
||||||
|
|
||||||
ignore-queueownership="false"
|
|
||||||
|
|
||||||
authentication="both"
|
|
||||||
|
|
||||||
show-operator-actual-name="true"
|
|
||||||
|
|
||||||
aknowledge-received="true"
|
|
||||||
|
|
||||||
gdpr-enabled="false"
|
|
||||||
|
|
||||||
message-userinfo-format="name"
|
|
||||||
|
|
||||||
message-dateformat="both"
|
|
||||||
|
|
||||||
lang="browser"
|
|
||||||
|
|
||||||
button-icon-type="default"
|
|
||||||
|
|
||||||
greeting-visibility="none"
|
|
||||||
|
|
||||||
greeting-offline-visibility="none"
|
|
||||||
|
|
||||||
chat-delay="2000"
|
|
||||||
|
|
||||||
enable-direct-call="true"
|
|
||||||
|
|
||||||
enable-ga="false"
|
|
||||||
|
|
||||||
></call-us>-->
|
|
||||||
|
|
||||||
<script defer src=https://downloads-global.3cx.com/downloads/livechatandtalk/v1/callus.js id="tcx-callus-js" charset="utf-8"></script>
|
|
||||||
|
|
||||||
<link rel="apple-touch-icon" href="logo192.png" />
|
<link rel="apple-touch-icon" href="logo192.png" />
|
||||||
|
<script type="text/javascript">
|
||||||
|
window.$crisp = [];
|
||||||
|
window.CRISP_WEBSITE_ID = "36724f62-2eb0-4b29-9cdd-9905fb99913e";
|
||||||
|
(function () {
|
||||||
|
d = document;
|
||||||
|
s = d.createElement("script");
|
||||||
|
s.src = "https://client.crisp.chat/l.js";
|
||||||
|
s.async = 1;
|
||||||
|
d.getElementsByTagName("head")[0].appendChild(s);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
<script>
|
<script>
|
||||||
!(function () {
|
!(function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
@@ -135,7 +77,7 @@ enable-ga="false"
|
|||||||
work correctly both with client-side routing and a non-root public URL.
|
work correctly both with client-side routing and a non-root public URL.
|
||||||
Learn how to configure a non-root public URL by running `npm run build`.
|
Learn how to configure a non-root public URL by running `npm run build`.
|
||||||
-->
|
-->
|
||||||
<title>Rome Online</title>
|
<title>ImEX Online</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"short_name": "Rome Online",
|
"short_name": "ImEX Online",
|
||||||
"name": "Rome Online",
|
"name": "ImEX Online",
|
||||||
"description": "The ultimate bodyshop management system.",
|
"description": "The ultimate bodyshop management system.",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 376 B |
@@ -27,12 +27,6 @@ export default function AppContainer() {
|
|||||||
//componentSize="small"
|
//componentSize="small"
|
||||||
input={{ autoComplete: "new-password" }}
|
input={{ autoComplete: "new-password" }}
|
||||||
locale={enLocale}
|
locale={enLocale}
|
||||||
theme={{
|
|
||||||
token: {
|
|
||||||
colorPrimary: "#326ade",
|
|
||||||
colorInfo: "#326ade"
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
form={{
|
form={{
|
||||||
validateMessages: {
|
validateMessages: {
|
||||||
// eslint-disable-next-line no-template-curly-in-string
|
// eslint-disable-next-line no-template-curly-in-string
|
||||||
|
|||||||
@@ -77,9 +77,9 @@ export function App({
|
|||||||
if (currentUser.authorized && bodyshop) {
|
if (currentUser.authorized && bodyshop) {
|
||||||
client.setAttribute("imexshopid", bodyshop.imexshopid);
|
client.setAttribute("imexshopid", bodyshop.imexshopid);
|
||||||
|
|
||||||
LogRocket.init("rome-online/rome-online");
|
|
||||||
if (client.getTreatment("LogRocket_Tracking") === "on") {
|
if (client.getTreatment("LogRocket_Tracking") === "on") {
|
||||||
LogRocket.init("rome-online/rome-online");
|
console.log("LR Start");
|
||||||
|
LogRocket.init("gvfvfw/bodyshopapp");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [bodyshop, client, currentUser.authorized]);
|
}, [bodyshop, client, currentUser.authorized]);
|
||||||
@@ -109,7 +109,7 @@ export function App({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Suspense fallback={<LoadingSpinner />}>
|
<Suspense fallback={<LoadingSpinner message="ImEX Online" />}>
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Route exact path="/" component={LandingPage} />
|
<Route exact path="/" component={LandingPage} />
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 72 KiB |
@@ -10,7 +10,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import {
|
import {
|
||||||
DELETE_BILL_LINE,
|
DELETE_BILL_LINE,
|
||||||
INSERT_NEW_BILL_LINES,
|
INSERT_NEW_BILL_LINES,
|
||||||
UPDATE_BILL_LINE
|
UPDATE_BILL_LINE,
|
||||||
} from "../../graphql/bill-lines.queries";
|
} from "../../graphql/bill-lines.queries";
|
||||||
import { QUERY_BILL_BY_PK, UPDATE_BILL } from "../../graphql/bills.queries";
|
import { QUERY_BILL_BY_PK, UPDATE_BILL } from "../../graphql/bills.queries";
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
@@ -20,6 +20,7 @@ import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
|||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import BillFormContainer from "../bill-form/bill-form.container";
|
import BillFormContainer from "../bill-form/bill-form.container";
|
||||||
import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component";
|
import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component";
|
||||||
|
import BillPrintButton from "../bill-print-button/bill-print-button.component";
|
||||||
import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-button.component";
|
import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-button.component";
|
||||||
import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-gallery.container";
|
import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-gallery.container";
|
||||||
import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container";
|
import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container";
|
||||||
@@ -176,7 +177,7 @@ export function BillDetailEditcontainer({
|
|||||||
extra={
|
extra={
|
||||||
<Space>
|
<Space>
|
||||||
<BillDetailEditReturn data={data} />
|
<BillDetailEditReturn data={data} />
|
||||||
|
<BillPrintButton billid={search.billid} />
|
||||||
<Popconfirm
|
<Popconfirm
|
||||||
visible={visible}
|
visible={visible}
|
||||||
onConfirm={() => form.submit()}
|
onConfirm={() => form.submit()}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useApolloClient, useMutation } from "@apollo/client";
|
import { useApolloClient, useMutation } from "@apollo/client";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
import { Button, Checkbox, Form, Modal, Space, notification } from "antd";
|
import { Button, Checkbox, Form, Modal, Space, notification } from "antd";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
@@ -64,19 +63,9 @@ function BillEnterModalContainer({
|
|||||||
"enter_bill_generate_label",
|
"enter_bill_generate_label",
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
const formValues = useMemo(() => {
|
const formValues = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
...billEnterModal.context.bill,
|
...billEnterModal.context.bill,
|
||||||
//Added as a part of IO-2436 for capturing parts price changes.
|
|
||||||
billlines: billEnterModal.context?.bill?.billlines?.map((line) => ({
|
|
||||||
...line,
|
|
||||||
original_actual_price: line.actual_price,
|
|
||||||
})),
|
|
||||||
jobid:
|
jobid:
|
||||||
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
||||||
federal_tax_rate:
|
federal_tax_rate:
|
||||||
@@ -109,7 +98,6 @@ function BillEnterModalContainer({
|
|||||||
} = values;
|
} = values;
|
||||||
|
|
||||||
let adjustmentsToInsert = {};
|
let adjustmentsToInsert = {};
|
||||||
let payrollAdjustmentsToInsert = [];
|
|
||||||
|
|
||||||
const r1 = await insertBill({
|
const r1 = await insertBill({
|
||||||
variables: {
|
variables: {
|
||||||
@@ -125,33 +113,14 @@ function BillEnterModalContainer({
|
|||||||
lbr_adjustment,
|
lbr_adjustment,
|
||||||
location: lineLocation,
|
location: lineLocation,
|
||||||
part_type,
|
part_type,
|
||||||
create_ppc,
|
|
||||||
original_actual_price,
|
|
||||||
...restI
|
...restI
|
||||||
} = i;
|
} = i;
|
||||||
|
|
||||||
if (Enhanced_Payroll.treatment === "on") {
|
if (deductedfromlbr) {
|
||||||
if (
|
adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] =
|
||||||
deductedfromlbr &&
|
(adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] || 0) -
|
||||||
true //payroll is on
|
restI.actual_price / lbr_adjustment.rate;
|
||||||
) {
|
|
||||||
payrollAdjustmentsToInsert.push({
|
|
||||||
id: i.joblineid,
|
|
||||||
convertedtolbr: true,
|
|
||||||
convertedtolbr_data: {
|
|
||||||
mod_lb_hrs: lbr_adjustment.mod_lb_hrs * -1,
|
|
||||||
mod_lbr_ty: lbr_adjustment.mod_lbr_ty,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (deductedfromlbr) {
|
|
||||||
adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] =
|
|
||||||
(adjustmentsToInsert[lbr_adjustment.mod_lbr_ty] || 0) -
|
|
||||||
restI.actual_price / lbr_adjustment.rate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...restI,
|
...restI,
|
||||||
deductedfromlbr: deductedfromlbr,
|
deductedfromlbr: deductedfromlbr,
|
||||||
@@ -177,20 +146,6 @@ function BillEnterModalContainer({
|
|||||||
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID", "GET_JOB_BY_PK"],
|
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID", "GET_JOB_BY_PK"],
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
payrollAdjustmentsToInsert.map((li) => {
|
|
||||||
return updateJobLines({
|
|
||||||
variables: {
|
|
||||||
lineId: li.id,
|
|
||||||
line: {
|
|
||||||
convertedtolbr: li.convertedtolbr,
|
|
||||||
convertedtolbr_data: li.convertedtolbr_data,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const adjKeys = Object.keys(adjustmentsToInsert);
|
const adjKeys = Object.keys(adjustmentsToInsert);
|
||||||
if (adjKeys.length > 0) {
|
if (adjKeys.length > 0) {
|
||||||
//Query the adjustments, merge, and update them.
|
//Query the adjustments, merge, and update them.
|
||||||
@@ -299,14 +254,6 @@ function BillEnterModalContainer({
|
|||||||
location: li.location || location,
|
location: li.location || location,
|
||||||
status:
|
status:
|
||||||
bodyshop.md_order_statuses.default_received || "Received*",
|
bodyshop.md_order_statuses.default_received || "Received*",
|
||||||
//Added parts price changes.
|
|
||||||
...(li.create_ppc &&
|
|
||||||
li.original_actual_price !== li.actual_price
|
|
||||||
? {
|
|
||||||
act_price_before_ppc: li.original_actual_price,
|
|
||||||
act_price: li.actual_price,
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -375,12 +322,12 @@ function BillEnterModalContainer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (enterAgain) {
|
if (enterAgain) {
|
||||||
// form.resetFields();
|
form.resetFields();
|
||||||
|
form.resetFields();
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
...formValues,
|
...formValues,
|
||||||
billlines: [],
|
billlines: [],
|
||||||
});
|
});
|
||||||
form.resetFields();
|
|
||||||
} else {
|
} else {
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
}
|
}
|
||||||
@@ -455,9 +402,6 @@ function BillEnterModalContainer({
|
|||||||
setEnterAgain(false);
|
setEnterAgain(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<button onClick={() => console.log(form.getFieldsValue("billlines"))}>
|
|
||||||
get billlines
|
|
||||||
</button>
|
|
||||||
<BillFormContainer
|
<BillFormContainer
|
||||||
form={form}
|
form={form}
|
||||||
disableInvNumber={billEnterModal.context.disableInvNumber}
|
disableInvNumber={billEnterModal.context.disableInvNumber}
|
||||||
|
|||||||
@@ -79,6 +79,20 @@ export function BillFormComponent({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleFederalTaxExemptSwitchToggle = (checked) => {
|
||||||
|
// Early gate
|
||||||
|
if (!checked) return;
|
||||||
|
const values = form.getFieldsValue("billlines");
|
||||||
|
// Gate bill lines
|
||||||
|
if (!values?.billlines?.length) return;
|
||||||
|
|
||||||
|
const billlines = values.billlines.map((b) => {
|
||||||
|
b.applicable_taxes.federal = false;
|
||||||
|
return b;
|
||||||
|
});
|
||||||
|
form.setFieldsValue({ billlines });
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (job) form.validateFields(["is_credit_memo"]);
|
if (job) form.validateFields(["is_credit_memo"]);
|
||||||
}, [job, form]);
|
}, [job, form]);
|
||||||
@@ -366,15 +380,13 @@ export function BillFormComponent({
|
|||||||
)}
|
)}
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow>
|
<LayoutFormRow>
|
||||||
{
|
<Form.Item
|
||||||
// <Form.Item
|
span={3}
|
||||||
// span={3}
|
label={t("bills.fields.federal_tax_rate")}
|
||||||
// label={t("bills.fields.federal_tax_rate")}
|
name="federal_tax_rate"
|
||||||
// name="federal_tax_rate"
|
>
|
||||||
// >
|
<CurrencyInput min={0} disabled={disabled} />
|
||||||
// <CurrencyInput min={0} disabled={disabled} />
|
</Form.Item>
|
||||||
// </Form.Item>
|
|
||||||
}
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
span={3}
|
span={3}
|
||||||
label={t("bills.fields.state_tax_rate")}
|
label={t("bills.fields.state_tax_rate")}
|
||||||
@@ -382,16 +394,23 @@ export function BillFormComponent({
|
|||||||
>
|
>
|
||||||
<CurrencyInput min={0} disabled={disabled} />
|
<CurrencyInput min={0} disabled={disabled} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
<Form.Item
|
||||||
// <Form.Item
|
span={3}
|
||||||
// span={3}
|
label={t("bills.fields.local_tax_rate")}
|
||||||
// label={t("bills.fields.local_tax_rate")}
|
name="local_tax_rate"
|
||||||
// name="local_tax_rate"
|
>
|
||||||
// >
|
<CurrencyInput min={0} />
|
||||||
// <CurrencyInput min={0} />
|
</Form.Item>
|
||||||
// </Form.Item>
|
{bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (
|
||||||
}
|
<Form.Item
|
||||||
<Form.Item shouldUpdate span={15}>
|
span={2}
|
||||||
|
label={t("bills.labels.federal_tax_exempt")}
|
||||||
|
name="federal_tax_exempt"
|
||||||
|
>
|
||||||
|
<Switch onChange={handleFederalTaxExemptSwitchToggle} />
|
||||||
|
</Form.Item>
|
||||||
|
) : null}
|
||||||
|
<Form.Item shouldUpdate span={13}>
|
||||||
{() => {
|
{() => {
|
||||||
const values = form.getFieldsValue([
|
const values = form.getFieldsValue([
|
||||||
"billlines",
|
"billlines",
|
||||||
@@ -409,32 +428,28 @@ export function BillFormComponent({
|
|||||||
totals = CalculateBillTotal(values);
|
totals = CalculateBillTotal(values);
|
||||||
if (!!totals)
|
if (!!totals)
|
||||||
return (
|
return (
|
||||||
<div>
|
<div align="right">
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
<Statistic
|
<Statistic
|
||||||
title={t("bills.labels.subtotal")}
|
title={t("bills.labels.subtotal")}
|
||||||
value={totals.subtotal.toFormat()}
|
value={totals.subtotal.toFormat()}
|
||||||
precision={2}
|
precision={2}
|
||||||
/>
|
/>
|
||||||
{
|
<Statistic
|
||||||
// <Statistic
|
title={t("bills.labels.federal_tax")}
|
||||||
// title={t("bills.labels.federal_tax")}
|
value={totals.federalTax.toFormat()}
|
||||||
// value={totals.federalTax.toFormat()}
|
precision={2}
|
||||||
// precision={2}
|
/>
|
||||||
// />
|
|
||||||
}
|
|
||||||
<Statistic
|
<Statistic
|
||||||
title={t("bills.labels.state_tax")}
|
title={t("bills.labels.state_tax")}
|
||||||
value={totals.stateTax.toFormat()}
|
value={totals.stateTax.toFormat()}
|
||||||
precision={2}
|
precision={2}
|
||||||
/>
|
/>
|
||||||
{
|
<Statistic
|
||||||
// <Statistic
|
title={t("bills.labels.local_tax")}
|
||||||
// title={t("bills.labels.local_tax")}
|
value={totals.localTax.toFormat()}
|
||||||
// value={totals.localTax.toFormat()}
|
precision={2}
|
||||||
// precision={2}
|
/>
|
||||||
// />
|
|
||||||
}
|
|
||||||
<Statistic
|
<Statistic
|
||||||
title={t("bills.labels.entered_total")}
|
title={t("bills.labels.entered_total")}
|
||||||
value={totals.enteredTotal.toFormat()}
|
value={totals.enteredTotal.toFormat()}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { DeleteFilled, DollarCircleFilled } from "@ant-design/icons";
|
|||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
@@ -47,13 +46,6 @@ export function BillEnterModalLinesComponent({
|
|||||||
{},
|
{},
|
||||||
bodyshop && bodyshop.imexshopid
|
bodyshop && bodyshop.imexshopid
|
||||||
);
|
);
|
||||||
|
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
|
|
||||||
const columns = (remove) => {
|
const columns = (remove) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@@ -102,7 +94,6 @@ export function BillEnterModalLinesComponent({
|
|||||||
line_desc: opt.line_desc,
|
line_desc: opt.line_desc,
|
||||||
quantity: opt.part_qty || 1,
|
quantity: opt.part_qty || 1,
|
||||||
actual_price: opt.cost,
|
actual_price: opt.cost,
|
||||||
original_actual_price: opt.cost,
|
|
||||||
cost_center: opt.part_type
|
cost_center: opt.part_type
|
||||||
? bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid
|
? bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid
|
||||||
? opt.part_type !== "PAE"
|
? opt.part_type !== "PAE"
|
||||||
@@ -229,43 +220,6 @@ export function BillEnterModalLinesComponent({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
additional: (record, index) => (
|
|
||||||
<Form.Item
|
|
||||||
dependencies={["billlines", record.name, "actual_price"]}
|
|
||||||
noStyle
|
|
||||||
>
|
|
||||||
{() => {
|
|
||||||
const billLine = getFieldValue(["billlines", record.name]);
|
|
||||||
const jobLine = lineData.find(
|
|
||||||
(line) => line.id === billLine?.joblineid
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
|
||||||
!billEdit &&
|
|
||||||
billLine &&
|
|
||||||
jobLine &&
|
|
||||||
billLine?.actual_price !== jobLine?.act_price
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
<Space size="small">
|
|
||||||
<Form.Item
|
|
||||||
noStyle
|
|
||||||
label={t("joblines.fields.create_ppc")}
|
|
||||||
key={`${index}ppc`}
|
|
||||||
valuePropName="checked"
|
|
||||||
name={[record.name, "create_ppc"]}
|
|
||||||
>
|
|
||||||
<Checkbox />
|
|
||||||
</Form.Item>
|
|
||||||
{t("joblines.fields.create_ppc")}
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
</Form.Item>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("billlines.fields.actual_cost"),
|
title: t("billlines.fields.actual_cost"),
|
||||||
@@ -407,7 +361,7 @@ export function BillEnterModalLinesComponent({
|
|||||||
},
|
},
|
||||||
formInput: (record, index) => <Switch disabled={disabled} />,
|
formInput: (record, index) => <Switch disabled={disabled} />,
|
||||||
additional: (record, index) => (
|
additional: (record, index) => (
|
||||||
<Form.Item shouldUpdate noStyle style={{ display: "inline-block" }}>
|
<Form.Item shouldUpdate style={{ display: "inline-block" }}>
|
||||||
{() => {
|
{() => {
|
||||||
const price = getFieldValue([
|
const price = getFieldValue([
|
||||||
"billlines",
|
"billlines",
|
||||||
@@ -422,31 +376,12 @@ export function BillEnterModalLinesComponent({
|
|||||||
"rate",
|
"rate",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const billline = getFieldValue(["billlines", record.name]);
|
|
||||||
|
|
||||||
const jobline = lineData.find(
|
|
||||||
(line) => line.id === billline?.joblineid
|
|
||||||
);
|
|
||||||
|
|
||||||
const employeeTeamName = bodyshop.employee_teams.find(
|
|
||||||
(team) => team.id === jobline?.assigned_team
|
|
||||||
);
|
|
||||||
|
|
||||||
if (getFieldValue(["billlines", record.name, "deductedfromlbr"]))
|
if (getFieldValue(["billlines", record.name, "deductedfromlbr"]))
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Space>
|
|
||||||
{t("joblines.fields.assigned_team", {
|
|
||||||
name: employeeTeamName?.name,
|
|
||||||
})}
|
|
||||||
{`${jobline.mod_lb_hrs} units/${t(
|
|
||||||
`joblines.fields.lbr_types.${jobline.mod_lbr_ty}`
|
|
||||||
)}`}
|
|
||||||
</Space>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("joblines.fields.mod_lbr_ty")}
|
label={t("joblines.fields.mod_lbr_ty")}
|
||||||
key={`${index}modlbrty`}
|
key={`${index}modlbrty`}
|
||||||
initialValue={jobline ? jobline.mod_lbr_ty : null}
|
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
@@ -500,44 +435,22 @@ export function BillEnterModalLinesComponent({
|
|||||||
</Select.Option>
|
</Select.Option>
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{Enhanced_Payroll.treatment === "on" ? (
|
<Form.Item
|
||||||
<Form.Item
|
label={t("jobs.labels.adjustmentrate")}
|
||||||
label={t("billlines.labels.mod_lbr_adjustment")}
|
name={[record.name, "lbr_adjustment", "rate"]}
|
||||||
name={[record.name, "lbr_adjustment", "mod_lb_hrs"]}
|
initialValue={bodyshop.default_adjustment_rate}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber precision={2} min={0.01} />
|
||||||
precision={5}
|
</Form.Item>
|
||||||
min={0.01}
|
{price &&
|
||||||
max={jobline ? jobline.mod_lb_hrs : 0}
|
adjustmentRate &&
|
||||||
/>
|
`${(price / adjustmentRate).toFixed(1)} hrs`}
|
||||||
</Form.Item>
|
|
||||||
) : (
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.labels.adjustmentrate")}
|
|
||||||
name={[record.name, "lbr_adjustment", "rate"]}
|
|
||||||
initialValue={bodyshop.default_adjustment_rate}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<InputNumber precision={2} min={0.01} />
|
|
||||||
</Form.Item>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Space>
|
|
||||||
{price &&
|
|
||||||
adjustmentRate &&
|
|
||||||
`${(price / adjustmentRate).toFixed(1)} hrs`}
|
|
||||||
</Space>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return <></>;
|
return <></>;
|
||||||
@@ -545,21 +458,22 @@ export function BillEnterModalLinesComponent({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// title: t("billlines.fields.federal_tax_applicable"),
|
title: t("billlines.fields.federal_tax_applicable"),
|
||||||
// dataIndex: "applicable_taxes.federal",
|
dataIndex: "applicable_taxes.federal",
|
||||||
// editable: true,
|
editable: true,
|
||||||
|
|
||||||
// formItemProps: (field) => {
|
formItemProps: (field) => {
|
||||||
// return {
|
return {
|
||||||
// key: `${field.index}fedtax`,
|
key: `${field.index}fedtax`,
|
||||||
// valuePropName: "checked",
|
valuePropName: "checked",
|
||||||
// // initialValue: true,
|
initialValue:
|
||||||
// name: [field.name, "applicable_taxes", "federal"],
|
form.getFieldValue("federal_tax_exempt") === true ? false : true,
|
||||||
// };
|
name: [field.name, "applicable_taxes", "federal"],
|
||||||
// },
|
};
|
||||||
// formInput: (record, index) => <Switch disabled={disabled} />,
|
},
|
||||||
// },
|
formInput: (record, index) => <Switch disabled={disabled} />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("billlines.fields.state_tax_applicable"),
|
title: t("billlines.fields.state_tax_applicable"),
|
||||||
dataIndex: "applicable_taxes.state",
|
dataIndex: "applicable_taxes.state",
|
||||||
@@ -574,20 +488,20 @@ export function BillEnterModalLinesComponent({
|
|||||||
},
|
},
|
||||||
formInput: (record, index) => <Switch disabled={disabled} />,
|
formInput: (record, index) => <Switch disabled={disabled} />,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// title: t("billlines.fields.local_tax_applicable"),
|
title: t("billlines.fields.local_tax_applicable"),
|
||||||
// dataIndex: "applicable_taxes.local",
|
dataIndex: "applicable_taxes.local",
|
||||||
// editable: true,
|
editable: true,
|
||||||
|
|
||||||
// formItemProps: (field) => {
|
formItemProps: (field) => {
|
||||||
// return {
|
return {
|
||||||
// key: `${field.index}localtax`,
|
key: `${field.index}localtax`,
|
||||||
// valuePropName: "checked",
|
valuePropName: "checked",
|
||||||
// name: [field.name, "applicable_taxes", "local"],
|
name: [field.name, "applicable_taxes", "local"],
|
||||||
// };
|
};
|
||||||
// },
|
},
|
||||||
// formInput: (record, index) => <Switch disabled={disabled} />,
|
formInput: (record, index) => <Switch disabled={disabled} />,
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
title: t("general.labels.actions"),
|
title: t("general.labels.actions"),
|
||||||
|
|
||||||
@@ -712,7 +626,7 @@ const EditableCell = ({
|
|||||||
if (additional)
|
if (additional)
|
||||||
return (
|
return (
|
||||||
<td {...restProps}>
|
<td {...restProps}>
|
||||||
<div size="small">
|
<Space size="small">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={dataIndex}
|
name={dataIndex}
|
||||||
labelCol={{ span: 0 }}
|
labelCol={{ span: 0 }}
|
||||||
@@ -721,7 +635,7 @@ const EditableCell = ({
|
|||||||
{(formInput && formInput(record, record.name)) || children}
|
{(formInput && formInput(record, record.name)) || children}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{additional && additional(record, record.name)}
|
{additional && additional(record, record.name)}
|
||||||
</div>
|
</Space>
|
||||||
</td>
|
</td>
|
||||||
);
|
);
|
||||||
if (wrapper)
|
if (wrapper)
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ export const CalculateBillTotal = (invoice) => {
|
|||||||
}).multiply(i.quantity || 1);
|
}).multiply(i.quantity || 1);
|
||||||
|
|
||||||
subtotal = subtotal.add(itemTotal);
|
subtotal = subtotal.add(itemTotal);
|
||||||
if (i.applicable_taxes?.federal) {
|
if (i.applicable_taxes.federal) {
|
||||||
federalTax = federalTax.add(
|
federalTax = federalTax.add(
|
||||||
itemTotal.percentage(federal_tax_rate || 0)
|
itemTotal.percentage(federal_tax_rate || 0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (i.applicable_taxes?.state)
|
if (i.applicable_taxes.state)
|
||||||
stateTax = stateTax.add(itemTotal.percentage(state_tax_rate || 0));
|
stateTax = stateTax.add(itemTotal.percentage(state_tax_rate || 0));
|
||||||
if (i.applicable_taxes?.local)
|
if (i.applicable_taxes.local)
|
||||||
localTax = localTax.add(itemTotal.percentage(local_tax_rate || 0));
|
localTax = localTax.add(itemTotal.percentage(local_tax_rate || 0));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -63,12 +63,6 @@ const BillLineSearchSelect = (
|
|||||||
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
||||||
}${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim()}
|
}${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim()}
|
||||||
</span>
|
</span>
|
||||||
{item.act_price === 0 && item.mod_lb_hrs > 0 && (
|
|
||||||
<span style={{ float: "right", paddingleft: "1rem" }}>
|
|
||||||
{`${item.mod_lb_hrs} units`}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<span style={{ float: "right", paddingleft: "1rem" }}>
|
<span style={{ float: "right", paddingleft: "1rem" }}>
|
||||||
{item.act_price
|
{item.act_price
|
||||||
? `$${item.act_price && item.act_price.toFixed(2)}`
|
? `$${item.act_price && item.act_price.toFixed(2)}`
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import { Button, Space } from "antd";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||||
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
|
|
||||||
|
export default function BillPrintButton({ billid }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const Templates = TemplateList("job_special");
|
||||||
|
|
||||||
|
const submitHandler = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
await GenerateDocument(
|
||||||
|
{
|
||||||
|
name: Templates.parts_invoice_label_single.key,
|
||||||
|
variables: {
|
||||||
|
id: billid,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
"p"
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("Warning: Error generating a document.");
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space wrap>
|
||||||
|
<Button loading={loading} onClick={submitHandler}>
|
||||||
|
{t("bills.labels.printlabels")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
|||||||
import ChatArchiveButton from "../chat-archive-button/chat-archive-button.component";
|
import ChatArchiveButton from "../chat-archive-button/chat-archive-button.component";
|
||||||
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
||||||
import ChatLabelComponent from "../chat-label/chat-label.component";
|
import ChatLabelComponent from "../chat-label/chat-label.component";
|
||||||
|
import ChatPrintButton from "../chat-print-button/chat-print-button.component";
|
||||||
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
||||||
|
|
||||||
export default function ChatConversationTitle({ conversation }) {
|
export default function ChatConversationTitle({ conversation }) {
|
||||||
@@ -13,6 +14,7 @@ export default function ChatConversationTitle({ conversation }) {
|
|||||||
{conversation && conversation.phone_num}
|
{conversation && conversation.phone_num}
|
||||||
</PhoneNumberFormatter>
|
</PhoneNumberFormatter>
|
||||||
<ChatLabelComponent conversation={conversation} />
|
<ChatLabelComponent conversation={conversation} />
|
||||||
|
<ChatPrintButton conversation={conversation} />
|
||||||
<ChatConversationTitleTags
|
<ChatConversationTitleTags
|
||||||
jobConversations={
|
jobConversations={
|
||||||
(conversation && conversation.job_conversations) || []
|
(conversation && conversation.job_conversations) || []
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { MailOutlined, PrinterOutlined } from "@ant-design/icons";
|
||||||
|
import { Space, Spin } from "antd";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { setEmailOptions } from "../../redux/email/email.actions";
|
||||||
|
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||||
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export function ChatPrintButton({ conversation }) {
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Space wrap>
|
||||||
|
<PrinterOutlined
|
||||||
|
onClick={() => {
|
||||||
|
setLoading(true);
|
||||||
|
GenerateDocument(
|
||||||
|
{
|
||||||
|
name: TemplateList("messaging").conversation_list.key,
|
||||||
|
variables: { id: conversation.id },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: TemplateList("messaging").conversation_list.subject,
|
||||||
|
},
|
||||||
|
"p",
|
||||||
|
conversation.id
|
||||||
|
);
|
||||||
|
setLoading(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<MailOutlined
|
||||||
|
onClick={() => {
|
||||||
|
setLoading(true);
|
||||||
|
GenerateDocument(
|
||||||
|
{
|
||||||
|
name: TemplateList("messaging").conversation_list.key,
|
||||||
|
variables: { id: conversation.id },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
subject: TemplateList("messaging").conversation_list.subject,
|
||||||
|
},
|
||||||
|
"e",
|
||||||
|
conversation.id
|
||||||
|
);
|
||||||
|
setLoading(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{loading && <Spin />}
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ChatPrintButton);
|
||||||
@@ -35,6 +35,15 @@ export default function ContractsCarsComponent({
|
|||||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||||
render: (text, record) => <div>{t(record.status)}</div>,
|
render: (text, record) => <div>{t(record.status)}</div>,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("courtesycars.fields.readiness"),
|
||||||
|
dataIndex: "readiness",
|
||||||
|
key: "readiness",
|
||||||
|
sorter: (a, b) => alphaSort(a.readiness, b.readiness),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "readiness" && state.sortedInfo.order,
|
||||||
|
render: (text, record) => t(record.readiness),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("courtesycars.fields.year"),
|
title: t("courtesycars.fields.year"),
|
||||||
dataIndex: "year",
|
dataIndex: "year",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { CHECK_CC_FLEET_NUMBER } from "../../graphql/courtesy-car.queries";
|
import { CHECK_CC_FLEET_NUMBER } from "../../graphql/courtesy-car.queries";
|
||||||
import { DateFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
|
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
|
||||||
|
import CourtesyCarReadiness from "../courtesy-car-readiness-select/courtesy-car-readiness-select.component";
|
||||||
import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component";
|
import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component";
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||||
//import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
//import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||||
@@ -213,6 +214,12 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
|
|||||||
>
|
>
|
||||||
<CourtesyCarStatus />
|
<CourtesyCarStatus />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("courtesycars.fields.readiness")}
|
||||||
|
name="readiness"
|
||||||
|
>
|
||||||
|
<CourtesyCarReadiness />
|
||||||
|
</Form.Item>
|
||||||
<div>
|
<div>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("courtesycars.fields.nextservicekm")}
|
label={t("courtesycars.fields.nextservicekm")}
|
||||||
|
|||||||
@@ -34,6 +34,32 @@ const CourtesyCarFuelComponent = (props, ref) => {
|
|||||||
step={null}
|
step={null}
|
||||||
style={{ marginLeft: "2rem", marginRight: "2rem" }}
|
style={{ marginLeft: "2rem", marginRight: "2rem" }}
|
||||||
{...props}
|
{...props}
|
||||||
|
tooltip={{
|
||||||
|
formatter: (value) => {
|
||||||
|
switch (value) {
|
||||||
|
case 0:
|
||||||
|
return t("courtesycars.labels.fuel.empty");
|
||||||
|
case 13:
|
||||||
|
return t("courtesycars.labels.fuel.18");
|
||||||
|
case 25:
|
||||||
|
return t("courtesycars.labels.fuel.14");
|
||||||
|
case 38:
|
||||||
|
return t("courtesycars.labels.fuel.38");
|
||||||
|
case 50:
|
||||||
|
return t("courtesycars.labels.fuel.12");
|
||||||
|
case 63:
|
||||||
|
return t("courtesycars.labels.fuel.58");
|
||||||
|
case 75:
|
||||||
|
return t("courtesycars.labels.fuel.34");
|
||||||
|
case 88:
|
||||||
|
return t("courtesycars.labels.fuel.78");
|
||||||
|
case 100:
|
||||||
|
return t("courtesycars.labels.fuel.full");
|
||||||
|
default:
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import { Select } from "antd";
|
||||||
|
import React, { forwardRef, useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
const { Option } = Select;
|
||||||
|
|
||||||
|
const CourtesyCarReadinessComponent = ({ value, onChange }, ref) => {
|
||||||
|
const [option, setOption] = useState(value);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (value !== option && onChange) {
|
||||||
|
onChange(option);
|
||||||
|
}
|
||||||
|
}, [value, option, onChange]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
allowClear
|
||||||
|
ref={ref}
|
||||||
|
value={option}
|
||||||
|
style={{
|
||||||
|
width: 100,
|
||||||
|
}}
|
||||||
|
onChange={setOption}
|
||||||
|
>
|
||||||
|
<Option value="courtesycars.readiness.ready">
|
||||||
|
{t("courtesycars.readiness.ready")}
|
||||||
|
</Option>
|
||||||
|
<Option value="courtesycars.readiness.notready">
|
||||||
|
{t("courtesycars.readiness.notready")}
|
||||||
|
</Option>
|
||||||
|
</Select>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default forwardRef(CourtesyCarReadinessComponent);
|
||||||
@@ -91,6 +91,26 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("courtesycars.fields.readiness"),
|
||||||
|
dataIndex: "readiness",
|
||||||
|
key: "readiness",
|
||||||
|
sorter: (a, b) => alphaSort(a.readiness, b.readiness),
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
text: t("courtesycars.readiness.ready"),
|
||||||
|
value: "courtesycars.readiness.ready",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: t("courtesycars.readiness.notready"),
|
||||||
|
value: "courtesycars.readiness.notready",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
onFilter: (value, record) => value.includes(record.readiness),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "readiness" && state.sortedInfo.order,
|
||||||
|
render: (text, record) => t(record.readiness),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("courtesycars.fields.year"),
|
title: t("courtesycars.fields.year"),
|
||||||
dataIndex: "year",
|
dataIndex: "year",
|
||||||
@@ -131,6 +151,36 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "plate" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "plate" && state.sortedInfo.order,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("courtesycars.fields.fuel"),
|
||||||
|
dataIndex: "fuel",
|
||||||
|
key: "fuel",
|
||||||
|
sorter: (a, b) => alphaSort(a.fuel, b.fuel),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "fuel" && state.sortedInfo.order,
|
||||||
|
render: (text, record) => {
|
||||||
|
switch (record.fuel) {
|
||||||
|
case 100:
|
||||||
|
return t("courtesycars.labels.fuel.full");
|
||||||
|
case 88:
|
||||||
|
return t("courtesycars.labels.fuel.78");
|
||||||
|
case 63:
|
||||||
|
return t("courtesycars.labels.fuel.58");
|
||||||
|
case 50:
|
||||||
|
return t("courtesycars.labels.fuel.12");
|
||||||
|
case 38:
|
||||||
|
return t("courtesycars.labels.fuel.34");
|
||||||
|
case 25:
|
||||||
|
return t("courtesycars.labels.fuel.14");
|
||||||
|
case 13:
|
||||||
|
return t("courtesycars.labels.fuel.18");
|
||||||
|
case 0:
|
||||||
|
return t("courtesycars.labels.fuel.empty");
|
||||||
|
default:
|
||||||
|
return record.fuel;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("courtesycars.labels.outwith"),
|
title: t("courtesycars.labels.outwith"),
|
||||||
dataIndex: "outwith",
|
dataIndex: "outwith",
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Select, Space, Tag } from "antd";
|
import { Select, Space, Tag } from "antd";
|
||||||
import React from "react";
|
import React, { forwardRef } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
//To be used as a form element only.
|
//To be used as a form element only.
|
||||||
|
|
||||||
const EmployeeSearchSelect = ({ options, ...props }) => {
|
const EmployeeSearchSelect = ({ options, ...props }, ref) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -39,4 +39,4 @@ const EmployeeSearchSelect = ({ options, ...props }) => {
|
|||||||
</Select>
|
</Select>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default EmployeeSearchSelect;
|
export default forwardRef(EmployeeSearchSelect);
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import { useQuery } from "@apollo/client";
|
|
||||||
import { Select } from "antd";
|
|
||||||
import React, { forwardRef } from "react";
|
|
||||||
import { QUERY_TEAMS } from "../../graphql/employee_teams.queries";
|
|
||||||
import AlertComponent from "../alert/alert.component";
|
|
||||||
|
|
||||||
//To be used as a form element only.
|
|
||||||
|
|
||||||
const EmployeeTeamSearchSelect = ({ ...props }, ref) => {
|
|
||||||
const { loading, error, data } = useQuery(QUERY_TEAMS);
|
|
||||||
|
|
||||||
if (error) return <AlertComponent message={JSON.stringify(error)} />;
|
|
||||||
return (
|
|
||||||
<Select
|
|
||||||
showSearch
|
|
||||||
allowClear
|
|
||||||
loading={loading}
|
|
||||||
style={{
|
|
||||||
width: 400,
|
|
||||||
}}
|
|
||||||
options={
|
|
||||||
data
|
|
||||||
? data.employee_teams.map((e) => ({
|
|
||||||
value: JSON.stringify(e),
|
|
||||||
label: e.name,
|
|
||||||
}))
|
|
||||||
: []
|
|
||||||
}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export default forwardRef(EmployeeTeamSearchSelect);
|
|
||||||
@@ -40,22 +40,22 @@ class ErrorBoundary extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleErrorSubmit = () => {
|
handleErrorSubmit = () => {
|
||||||
// window.$crisp.push([
|
window.$crisp.push([
|
||||||
// "do",
|
"do",
|
||||||
// "message:send",
|
"message:send",
|
||||||
// [
|
[
|
||||||
// "text",
|
"text",
|
||||||
// `I hit the following error: \n\n
|
`I hit the following error: \n\n
|
||||||
// ${this.state.error.message}\n\n
|
${this.state.error.message}\n\n
|
||||||
// ${this.state.error.stack}\n\n
|
${this.state.error.stack}\n\n
|
||||||
// URL:${window.location} as ${this.props.currentUser.email} for ${
|
URL:${window.location} as ${this.props.currentUser.email} for ${
|
||||||
// this.props.bodyshop && this.props.bodyshop.name
|
this.props.bodyshop && this.props.bodyshop.name
|
||||||
// }
|
}
|
||||||
// `,
|
`,
|
||||||
// ],
|
],
|
||||||
// ]);
|
]);
|
||||||
|
|
||||||
// window.$crisp.push(["do", "chat:open"]);
|
window.$crisp.push(["do", "chat:open"]);
|
||||||
// const errorDescription = `**Please add relevant details about what you were doing before you encountered this issue**
|
// const errorDescription = `**Please add relevant details about what you were doing before you encountered this issue**
|
||||||
|
|
||||||
// ----
|
// ----
|
||||||
|
|||||||
@@ -1,26 +1,9 @@
|
|||||||
import Dinero from "dinero.js";
|
import Dinero from "dinero.js";
|
||||||
import React, { forwardRef } from "react";
|
import React, { forwardRef } from "react";
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
const ReadOnlyFormItem = ({ value, type = "text", onChange }, ref) => {
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
|
|
||||||
const ReadOnlyFormItem = (
|
|
||||||
{ bodyshop, value, type = "text", onChange },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
if (!value) return null;
|
if (!value) return null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "employee":
|
|
||||||
const emp = bodyshop.employees.find((e) => e.id === value);
|
|
||||||
return `${emp?.first_name} ${emp?.last_name}`;
|
|
||||||
|
|
||||||
case "text":
|
case "text":
|
||||||
return <div>{value}</div>;
|
return <div>{value}</div>;
|
||||||
case "currency":
|
case "currency":
|
||||||
@@ -31,8 +14,4 @@ const ReadOnlyFormItem = (
|
|||||||
return <div>{value}</div>;
|
return <div>{value}</div>;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
export default forwardRef(ReadOnlyFormItem);
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(forwardRef(ReadOnlyFormItem));
|
|
||||||
|
|||||||
@@ -268,13 +268,6 @@ function Header({
|
|||||||
{t("menus.header.timetickets")}
|
{t("menus.header.timetickets")}
|
||||||
</Link>
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
{bodyshop?.md_tasks_presets?.use_approvals && (
|
|
||||||
<Menu.Item key="ttapprovals" icon={<FieldTimeOutlined />}>
|
|
||||||
<Link to="/manage/ttapprovals">
|
|
||||||
{t("menus.header.ttapprovals")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
)}
|
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="entertimetickets"
|
key="entertimetickets"
|
||||||
icon={<Icon component={GiPlayerTime} />}
|
icon={<Icon component={GiPlayerTime} />}
|
||||||
@@ -389,12 +382,20 @@ function Header({
|
|||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="help"
|
key="help"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open("https://rometech.com/", "_blank");
|
window.open("https://help.imex.online/", "_blank");
|
||||||
}}
|
}}
|
||||||
icon={<Icon component={QuestionCircleFilled} />}
|
icon={<Icon component={QuestionCircleFilled} />}
|
||||||
>
|
>
|
||||||
{t("menus.header.help")}
|
{t("menus.header.help")}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
key="rescue"
|
||||||
|
onClick={() => {
|
||||||
|
window.open("https://imexrescue.com/", "_blank");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("menus.header.rescueme")}
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item key="shiftclock">
|
<Menu.Item key="shiftclock">
|
||||||
<Link to="/manage/shiftclock">{t("menus.header.shiftclock")}</Link>
|
<Link to="/manage/shiftclock">{t("menus.header.shiftclock")}</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
|||||||
@@ -87,8 +87,7 @@ export default function JobBillsTotalComponent({
|
|||||||
const totalPartsSublet = Dinero(totals.parts.parts.total)
|
const totalPartsSublet = Dinero(totals.parts.parts.total)
|
||||||
.add(Dinero(totals.parts.sublets.total))
|
.add(Dinero(totals.parts.sublets.total))
|
||||||
.add(Dinero(totals.additional.shipping))
|
.add(Dinero(totals.additional.shipping))
|
||||||
.add(Dinero(totals.additional.towing))
|
.add(Dinero(totals.additional.towing));
|
||||||
.add(Dinero(totals.additional.additionalCosts));
|
|
||||||
|
|
||||||
const discrepancy = totalPartsSublet.subtract(billTotals);
|
const discrepancy = totalPartsSublet.subtract(billTotals);
|
||||||
|
|
||||||
|
|||||||
@@ -1,52 +1,47 @@
|
|||||||
import { Button, notification } from "antd";
|
import { Button, notification } from "antd";
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
import { useMutation } from "@apollo/client";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
export default function JobCalculateTotals({ job, disabled, refetch }) {
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
|
import Dinero from "dinero.js";
|
||||||
|
export default function JobCalculateTotals({ job, disabled }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [updateJob] = useMutation(UPDATE_JOB);
|
||||||
|
|
||||||
const handleCalculate = async () => {
|
const handleCalculate = async () => {
|
||||||
try {
|
setLoading(true);
|
||||||
setLoading(true);
|
const newTotals = (
|
||||||
|
await Axios.post("/job/totals", {
|
||||||
|
job: job,
|
||||||
|
})
|
||||||
|
).data;
|
||||||
|
|
||||||
await Axios.post("/job/totalsssu", {
|
const result = await updateJob({
|
||||||
id: job.id,
|
refetchQueries: ["GET_JOB_BY_PK"],
|
||||||
});
|
awaitRefetchQueries: true,
|
||||||
|
variables: {
|
||||||
if (refetch) refetch();
|
jobId: job.id,
|
||||||
// const result = await updateJob({
|
job: {
|
||||||
// refetchQueries: ["GET_JOB_BY_PK"],
|
job_totals: newTotals,
|
||||||
// awaitRefetchQueries: true,
|
clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
||||||
// variables: {
|
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat(
|
||||||
// jobId: job.id,
|
"0.00"
|
||||||
// job: {
|
),
|
||||||
// job_totals: newTotals,
|
},
|
||||||
// clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
},
|
||||||
// owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat(
|
});
|
||||||
// "0.00"
|
if (!!!result.errors) {
|
||||||
// ),
|
notification["success"]({ message: t("jobs.successes.updated") });
|
||||||
// },
|
} else {
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// if (!!!result.errors) {
|
|
||||||
// notification["success"]({ message: t("jobs.successes.updated") });
|
|
||||||
// } else {
|
|
||||||
// notification["error"]({
|
|
||||||
// message: t("jobs.errors.updating", {
|
|
||||||
// error: JSON.stringify(result.errors),
|
|
||||||
// }),
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
} catch (error) {
|
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("jobs.errors.updating", {
|
message: t("jobs.errors.updating", {
|
||||||
error: JSON.stringify(error),
|
error: JSON.stringify(result.errors),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -32,9 +32,9 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const span = {
|
const span = {
|
||||||
lg: { span: 24 },
|
sm: { span: 24 },
|
||||||
xl: { span: 12 },
|
md: { span: 12 },
|
||||||
xxl: { span: 8 },
|
lg: { span: 8 },
|
||||||
};
|
};
|
||||||
|
|
||||||
export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
|
export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
|
||||||
@@ -137,6 +137,12 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
|
|||||||
data={data ? data.jobs_by_pk : null}
|
data={data ? data.jobs_by_pk : null}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...span}>
|
||||||
|
<JobDetailCardsPartsComponent
|
||||||
|
loading={loading}
|
||||||
|
data={data ? data.jobs_by_pk : null}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
<Col {...span}>
|
<Col {...span}>
|
||||||
<JobDetailCardsNotesComponent
|
<JobDetailCardsNotesComponent
|
||||||
loading={loading}
|
loading={loading}
|
||||||
@@ -157,12 +163,6 @@ export function JobDetailCards({ bodyshop, setPrintCenterContext }) {
|
|||||||
data={data ? data.jobs_by_pk : null}
|
data={data ? data.jobs_by_pk : null}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
|
||||||
<JobDetailCardsPartsComponent
|
|
||||||
loading={loading}
|
|
||||||
data={data ? data.jobs_by_pk : null}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</Card>
|
</Card>
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -1,119 +1,16 @@
|
|||||||
import { Table } from "antd";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import JobLineNotePopup from "../job-line-note-popup/job-line-note-popup.component";
|
|
||||||
import PartsStatusPie from "../parts-status-pie/parts-status-pie.component";
|
import PartsStatusPie from "../parts-status-pie/parts-status-pie.component";
|
||||||
import CardTemplate from "./job-detail-cards.template.component";
|
import CardTemplate from "./job-detail-cards.template.component";
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
export default function JobDetailCardsPartsComponent({ loading, data }) {
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import { onlyUnique } from "../../utils/arrayHelper";
|
|
||||||
import { alphaSort } from "../../utils/sorters";
|
|
||||||
import JobLineLocationPopup from "../job-line-location-popup/job-line-location-popup.component";
|
|
||||||
import JobLineStatusPopup from "../job-line-status-popup/job-line-status-popup.component";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
//currentUser: selectCurrentUser
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(JobDetailCardsPartsComponent);
|
|
||||||
|
|
||||||
export function JobDetailCardsPartsComponent({ loading, data, jobRO }) {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { joblines_status } = data;
|
const { joblines_status } = data;
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.line_desc"),
|
|
||||||
dataIndex: "line_desc",
|
|
||||||
fixed: "left",
|
|
||||||
key: "line_desc",
|
|
||||||
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
|
||||||
onCell: (record) => ({
|
|
||||||
className: record.manual_line && "job-line-manual",
|
|
||||||
style: {
|
|
||||||
...(record.critical ? { boxShadow: " -.5em 0 0 #FFC107" } : {}),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
width: "30%",
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.part_type"),
|
|
||||||
dataIndex: "part_type",
|
|
||||||
key: "part_type",
|
|
||||||
width: "15%",
|
|
||||||
sorter: (a, b) =>
|
|
||||||
alphaSort(
|
|
||||||
t(`joblines.fields.part_types.${a.part_type}`),
|
|
||||||
t(`joblines.fields.part_types.${b.part_type}`)
|
|
||||||
),
|
|
||||||
render: (text, record) =>
|
|
||||||
record.part_type
|
|
||||||
? t(`joblines.fields.part_types.${record.part_type}`)
|
|
||||||
: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.part_qty"),
|
|
||||||
dataIndex: "part_qty",
|
|
||||||
key: "part_qty",
|
|
||||||
width: "10%",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.notes"),
|
|
||||||
dataIndex: "notes",
|
|
||||||
key: "notes",
|
|
||||||
render: (text, record) => (
|
|
||||||
<JobLineNotePopup disabled={jobRO} jobline={record} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.location"),
|
|
||||||
dataIndex: "location",
|
|
||||||
key: "location",
|
|
||||||
sorter: (a, b) => alphaSort(a.location, b.location),
|
|
||||||
render: (text, record) => (
|
|
||||||
<JobLineLocationPopup jobline={record} disabled={jobRO} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.status"),
|
|
||||||
dataIndex: "status",
|
|
||||||
key: "status",
|
|
||||||
sorter: (a, b) => alphaSort(a.status, b.status),
|
|
||||||
filters:
|
|
||||||
(data &&
|
|
||||||
data.joblines
|
|
||||||
?.map((l) => l.status)
|
|
||||||
.filter(onlyUnique)
|
|
||||||
.map((s) => {
|
|
||||||
return {
|
|
||||||
text: s || "No Status*",
|
|
||||||
value: [s],
|
|
||||||
};
|
|
||||||
})) ||
|
|
||||||
[],
|
|
||||||
onFilter: (value, record) => value.includes(record.status),
|
|
||||||
render: (text, record) => (
|
|
||||||
<JobLineStatusPopup jobline={record} disabled={jobRO} />
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<CardTemplate loading={loading} title={t("jobs.labels.cards.parts")}>
|
<CardTemplate loading={loading} title={t("jobs.labels.cards.parts")}>
|
||||||
<PartsStatusPie joblines_status={joblines_status} />
|
<PartsStatusPie joblines_status={joblines_status} />
|
||||||
<Table
|
|
||||||
key="id"
|
|
||||||
columns={columns}
|
|
||||||
dataSource={data ? data.joblines : []}
|
|
||||||
/>
|
|
||||||
</CardTemplate>
|
</CardTemplate>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,18 +8,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
|||||||
import { DateFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
export default function JobLinesExpander({ jobline, jobid }) {
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(JobLinesExpander);
|
|
||||||
|
|
||||||
export function JobLinesExpander({ jobline, jobid, bodyshop }) {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { loading, error, data } = useQuery(GET_JOB_LINE_ORDERS, {
|
const { loading, error, data } = useQuery(GET_JOB_LINE_ORDERS, {
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
@@ -34,7 +23,7 @@ export function JobLinesExpander({ jobline, jobid, bodyshop }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Row>
|
<Row>
|
||||||
<Col md={24} lg={8}>
|
<Col md={24} lg={12}>
|
||||||
<Typography.Title level={4}>
|
<Typography.Title level={4}>
|
||||||
{t("parts_orders.labels.parts_orders")}
|
{t("parts_orders.labels.parts_orders")}
|
||||||
</Typography.Title>
|
</Typography.Title>
|
||||||
@@ -60,7 +49,7 @@ export function JobLinesExpander({ jobline, jobid, bodyshop }) {
|
|||||||
)}
|
)}
|
||||||
</Timeline>
|
</Timeline>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md={24} lg={8}>
|
<Col md={24} lg={12}>
|
||||||
<Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title>
|
<Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title>
|
||||||
<Timeline>
|
<Timeline>
|
||||||
{data.billlines.length > 0 ? (
|
{data.billlines.length > 0 ? (
|
||||||
@@ -82,7 +71,7 @@ export function JobLinesExpander({ jobline, jobid, bodyshop }) {
|
|||||||
</Col>
|
</Col>
|
||||||
<Col span={4}>
|
<Col span={4}>
|
||||||
<span>
|
<span>
|
||||||
{`${t("billlines.fields.actual_cost")}: `}
|
{`${t("billlines.fields.actual_cost")}: `}
|
||||||
<CurrencyFormatter>{line.actual_cost}</CurrencyFormatter>
|
<CurrencyFormatter>{line.actual_cost}</CurrencyFormatter>
|
||||||
</span>
|
</span>
|
||||||
</Col>
|
</Col>
|
||||||
@@ -100,37 +89,6 @@ export function JobLinesExpander({ jobline, jobid, bodyshop }) {
|
|||||||
)}
|
)}
|
||||||
</Timeline>
|
</Timeline>
|
||||||
</Col>
|
</Col>
|
||||||
<Col md={24} lg={8}>
|
|
||||||
<Typography.Title level={4}>
|
|
||||||
{t("parts_dispatch.labels.parts_dispatch")}
|
|
||||||
</Typography.Title>
|
|
||||||
<Timeline>
|
|
||||||
{data.parts_dispatch_lines.length > 0 ? (
|
|
||||||
data.parts_dispatch_lines.map((line) => (
|
|
||||||
<Timeline.Item key={line.id}>
|
|
||||||
<Space split={<Divider type="vertical" />} wrap>
|
|
||||||
<Link to={`/manage/jobs/${jobid}?partsorderid=${line.id}`}>
|
|
||||||
{line.parts_dispatch.number}
|
|
||||||
</Link>
|
|
||||||
{
|
|
||||||
bodyshop.employees.find(
|
|
||||||
(e) => e.id === line.parts_dispatch.employeeid
|
|
||||||
)?.first_name
|
|
||||||
}
|
|
||||||
<Space>
|
|
||||||
{t("parts_dispatch_lines.fields.accepted_at")}
|
|
||||||
<DateFormatter>{line.accepted_at}</DateFormatter>
|
|
||||||
</Space>
|
|
||||||
</Space>
|
|
||||||
</Timeline.Item>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<Timeline.Item>
|
|
||||||
{t("parts_orders.labels.notyetordered")}
|
|
||||||
</Timeline.Item>
|
|
||||||
)}
|
|
||||||
</Timeline>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { Button, Form, notification, Popover, Tooltip } from "antd";
|
|
||||||
import { t } from "i18next";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { UPDATE_LINE_PPC } from "../../graphql/jobs-lines.queries";
|
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
|
||||||
import CurrencyFormItemComponent from "../form-items-formatted/currency-form-item.component";
|
|
||||||
import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component";
|
|
||||||
import axios from "axios";
|
|
||||||
export default function JobLinesPartPriceChange({ job, line, refetch }) {
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [updatePartPrice] = useMutation(UPDATE_LINE_PPC);
|
|
||||||
|
|
||||||
const handleFinish = async (values) => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
const result = await updatePartPrice({
|
|
||||||
variables: {
|
|
||||||
id: line.id,
|
|
||||||
jobline: {
|
|
||||||
act_price_before_ppc: line.act_price_before_ppc
|
|
||||||
? line.act_price_before_ppc
|
|
||||||
: line.act_price,
|
|
||||||
act_price: values.act_price,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
await axios.post("/job/totalsssu", {
|
|
||||||
id: job.id,
|
|
||||||
});
|
|
||||||
if (result.errors) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("joblines.errors.saving", {
|
|
||||||
error: JSON.stringify(result.errors),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
if (refetch) refetch();
|
|
||||||
} else {
|
|
||||||
notification.open({
|
|
||||||
type: "success",
|
|
||||||
message: t("joblines.successes.saved"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("joblines.errors.saving", { error: JSON.stringify(error) }),
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const popcontent = (
|
|
||||||
<Form layout="vertical" onFinish={handleFinish} initialValues={{ act_price: line.act_price }}>
|
|
||||||
<Form.Item
|
|
||||||
name="act_price"
|
|
||||||
label={t("jobs.labels.act_price_ppc")}
|
|
||||||
rules={[{ required: true }]}
|
|
||||||
>
|
|
||||||
<CurrencyFormItemComponent />
|
|
||||||
</Form.Item>
|
|
||||||
<Button loading={loading} htmlType="primary">
|
|
||||||
{t("general.actions.save")}
|
|
||||||
</Button>
|
|
||||||
</Form>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<JobLineConvertToLabor jobline={line} job={job}>
|
|
||||||
<Popover trigger="click" disabled={line.manual_line} content={popcontent}>
|
|
||||||
<CurrencyFormatter>
|
|
||||||
{line.db_ref === "900510" || line.db_ref === "900511"
|
|
||||||
? line.prt_dsmk_m
|
|
||||||
: line.act_price}
|
|
||||||
</CurrencyFormatter>
|
|
||||||
{line.prt_dsmk_p && line.prt_dsmk_p !== 0 ? (
|
|
||||||
<span style={{ marginLeft: ".2rem" }}>{`(${line.prt_dsmk_p}%)`}</span>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
{line.act_price_before_ppc && line.act_price_before_ppc !== 0 ? (
|
|
||||||
<Tooltip title={t("jobs.labels.ppc")}>
|
|
||||||
<span style={{ marginLeft: ".2rem", color: "tomato" }}>
|
|
||||||
(
|
|
||||||
<CurrencyFormatter>{line.act_price_before_ppc}</CurrencyFormatter>
|
|
||||||
)
|
|
||||||
</span>
|
|
||||||
</Tooltip>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</Popover>
|
|
||||||
</JobLineConvertToLabor>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
DeleteFilled,
|
DeleteFilled,
|
||||||
EditFilled,
|
|
||||||
FilterFilled,
|
FilterFilled,
|
||||||
HomeOutlined,
|
|
||||||
MinusCircleTwoTone,
|
|
||||||
PlusCircleTwoTone,
|
|
||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
WarningFilled,
|
WarningFilled,
|
||||||
|
EditFilled,
|
||||||
|
PlusCircleTwoTone,
|
||||||
|
MinusCircleTwoTone,
|
||||||
|
HomeOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { useMutation } from "@apollo/client";
|
import { useMutation } from "@apollo/client";
|
||||||
import {
|
import {
|
||||||
@@ -29,6 +29,7 @@ import { selectJobReadOnly } from "../../redux/application/application.selectors
|
|||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
import { onlyUnique } from "../../utils/arrayHelper";
|
import { onlyUnique } from "../../utils/arrayHelper";
|
||||||
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
import JobLineLocationPopup from "../job-line-location-popup/job-line-location-popup.component";
|
import JobLineLocationPopup from "../job-line-location-popup/job-line-location-popup.component";
|
||||||
import JobLineNotePopup from "../job-line-note-popup/job-line-note-popup.component";
|
import JobLineNotePopup from "../job-line-note-popup/job-line-note-popup.component";
|
||||||
@@ -37,18 +38,13 @@ import JobLinesBillRefernece from "../job-lines-bill-reference/job-lines-bill-re
|
|||||||
// import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
|
// import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
|
||||||
// import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
|
// import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
|
||||||
// import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
|
// import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
|
||||||
import _ from "lodash";
|
|
||||||
import moment from "moment";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import JobCreateIOU from "../job-create-iou/job-create-iou.component";
|
|
||||||
import JobSendPartPriceChangeComponent from "../job-send-parts-price-change/job-send-parts-price-change.component";
|
|
||||||
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
|
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
|
||||||
|
import _ from "lodash";
|
||||||
|
import JobCreateIOU from "../job-create-iou/job-create-iou.component";
|
||||||
import JobLinesExpander from "./job-lines-expander.component";
|
import JobLinesExpander from "./job-lines-expander.component";
|
||||||
import JobLinesPartPriceChange from "./job-lines-part-price-change.component";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import JoblineTeamAssignment from "../job-line-team-assignment/job-line-team-assignmnent.component";
|
import moment from "moment";
|
||||||
import JobLineDispatchButton from "../job-line-dispatch-button/job-line-dispatch-button.component";
|
import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component";
|
||||||
import JobLineBulkAssignComponent from "../job-line-bulk-assign/job-line-bulk-assign.component";
|
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -80,16 +76,8 @@ export function JobLinesComponent({
|
|||||||
setBillEnterContext,
|
setBillEnterContext,
|
||||||
}) {
|
}) {
|
||||||
const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK);
|
const [deleteJobLine] = useMutation(DELETE_JOB_LINE_BY_PK);
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
const [selectedLines, setSelectedLines] = useState([]);
|
const [selectedLines, setSelectedLines] = useState([]);
|
||||||
console.log(
|
|
||||||
"🚀 ~ file: job-lines.component.jsx:89 ~ selectedLines:",
|
|
||||||
selectedLines
|
|
||||||
);
|
|
||||||
const [state, setState] = useState({
|
const [state, setState] = useState({
|
||||||
sortedInfo: {},
|
sortedInfo: {},
|
||||||
filteredInfo: {},
|
filteredInfo: {},
|
||||||
@@ -133,21 +121,10 @@ export function JobLinesComponent({
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "oem_partno" && state.sortedInfo.order,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
onCell: (record) => ({
|
render: (text, record) =>
|
||||||
className: record.manual_line && "job-line-manual",
|
`${record.oem_partno || ""} ${
|
||||||
style: {
|
record.alt_partno ? `(${record.alt_partno})` : ""
|
||||||
...(record.parts_dispatch_lines[0]?.accepted_at
|
}`.trim(),
|
||||||
? { boxShadow: " -.5em 0 0 #FFC107" }
|
|
||||||
: {}),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
render: (text, record) => (
|
|
||||||
<span class="ant-table-cell-content">
|
|
||||||
{`${record.oem_partno || ""} ${
|
|
||||||
record.alt_partno ? `(${record.alt_partno})` : ""
|
|
||||||
}`.trim()}
|
|
||||||
</span>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("joblines.fields.op_code_desc"),
|
title: t("joblines.fields.op_code_desc"),
|
||||||
@@ -243,7 +220,20 @@ export function JobLinesComponent({
|
|||||||
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<JobLinesPartPriceChange line={record} job={job} refetch={refetch} />
|
<JobLineConvertToLabor jobline={record} job={job}>
|
||||||
|
<CurrencyFormatter>
|
||||||
|
{record.db_ref === "900510" || record.db_ref === "900511"
|
||||||
|
? record.prt_dsmk_m
|
||||||
|
: record.act_price}
|
||||||
|
</CurrencyFormatter>
|
||||||
|
{record.prt_dsmk_p && record.prt_dsmk_p !== 0 ? (
|
||||||
|
<span
|
||||||
|
style={{ marginLeft: ".2rem" }}
|
||||||
|
>{`(${record.prt_dsmk_p}%)`}</span>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</JobLineConvertToLabor>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -296,23 +286,6 @@ export function JobLinesComponent({
|
|||||||
state.sortedInfo.columnKey === "line_ind" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "line_ind" && state.sortedInfo.order,
|
||||||
responsive: ["md"],
|
responsive: ["md"],
|
||||||
},
|
},
|
||||||
...(Enhanced_Payroll.treatment === "on"
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.assigned_team"),
|
|
||||||
dataIndex: "assigned_team",
|
|
||||||
key: "assigned_team",
|
|
||||||
render: (text, record) => (
|
|
||||||
<JoblineTeamAssignment
|
|
||||||
disabled={jobRO}
|
|
||||||
jobline={record}
|
|
||||||
jobId={job.id}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("joblines.fields.notes"),
|
title: t("joblines.fields.notes"),
|
||||||
dataIndex: "notes",
|
dataIndex: "notes",
|
||||||
@@ -431,11 +404,7 @@ export function JobLinesComponent({
|
|||||||
setSelectedLines((selectedLines) =>
|
setSelectedLines((selectedLines) =>
|
||||||
_.uniq([
|
_.uniq([
|
||||||
...selectedLines,
|
...selectedLines,
|
||||||
...jobLines.filter(
|
...jobLines.filter((item) => markedTypes.includes(item.part_type)),
|
||||||
(item) =>
|
|
||||||
markedTypes.includes(item.part_type) ||
|
|
||||||
markedTypes.includes(item.mod_lbr_ty)
|
|
||||||
),
|
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -448,21 +417,6 @@ export function JobLinesComponent({
|
|||||||
<Menu.Item key="PAL">{t("joblines.fields.part_types.PAL")}</Menu.Item>
|
<Menu.Item key="PAL">{t("joblines.fields.part_types.PAL")}</Menu.Item>
|
||||||
<Menu.Item key="PAS">{t("joblines.fields.part_types.PAS")}</Menu.Item>
|
<Menu.Item key="PAS">{t("joblines.fields.part_types.PAS")}</Menu.Item>
|
||||||
<Menu.Divider />
|
<Menu.Divider />
|
||||||
<Menu.Item key="LAA">{t("joblines.fields.lbr_types.LAA")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAB">{t("joblines.fields.lbr_types.LAB")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAD">{t("joblines.fields.lbr_types.LAD")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAE">{t("joblines.fields.lbr_types.LAE")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAF">{t("joblines.fields.lbr_types.LAF")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAG">{t("joblines.fields.lbr_types.LAG")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAM">{t("joblines.fields.lbr_types.LAM")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAR">{t("joblines.fields.lbr_types.LAR")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAS">{t("joblines.fields.lbr_types.LAS")}</Menu.Item>
|
|
||||||
<Menu.Item key="LAU">{t("joblines.fields.lbr_types.LAU")}</Menu.Item>
|
|
||||||
<Menu.Item key="LA1">{t("joblines.fields.lbr_types.LA1")}</Menu.Item>
|
|
||||||
<Menu.Item key="LA2">{t("joblines.fields.lbr_types.LA2")}</Menu.Item>
|
|
||||||
<Menu.Item key="LA3">{t("joblines.fields.lbr_types.LA3")}</Menu.Item>
|
|
||||||
<Menu.Item key="LA4">{t("joblines.fields.lbr_types.LA2")}</Menu.Item>
|
|
||||||
<Menu.Divider />
|
|
||||||
<Menu.Item key="clear">{t("general.labels.clear")}</Menu.Item>
|
<Menu.Item key="clear">{t("general.labels.clear")}</Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
@@ -486,18 +440,6 @@ export function JobLinesComponent({
|
|||||||
</Space>
|
</Space>
|
||||||
</Tag>
|
</Tag>
|
||||||
)}
|
)}
|
||||||
<JobLineDispatchButton
|
|
||||||
selectedLines={selectedLines}
|
|
||||||
setSelectedLines={setSelectedLines}
|
|
||||||
job={job}
|
|
||||||
/>
|
|
||||||
{Enhanced_Payroll.treatment === "on" && (
|
|
||||||
<JobLineBulkAssignComponent
|
|
||||||
selectedLines={selectedLines}
|
|
||||||
setSelectedLines={setSelectedLines}
|
|
||||||
job={job}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<Button
|
<Button
|
||||||
disabled={
|
disabled={
|
||||||
(job && !job.converted) ||
|
(job && !job.converted) ||
|
||||||
@@ -506,6 +448,15 @@ export function JobLinesComponent({
|
|||||||
technician
|
technician
|
||||||
}
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
// setPartsOrderContext({
|
||||||
|
// actions: { refetch: refetch },
|
||||||
|
// context: {
|
||||||
|
// jobId: job.id,
|
||||||
|
// job: job,
|
||||||
|
// linesToOrder: selectedLines,
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
setBillEnterContext({
|
setBillEnterContext({
|
||||||
actions: { refetch: refetch },
|
actions: { refetch: refetch },
|
||||||
context: {
|
context: {
|
||||||
@@ -612,9 +563,6 @@ export function JobLinesComponent({
|
|||||||
>
|
>
|
||||||
{t("joblines.actions.new")}
|
{t("joblines.actions.new")}
|
||||||
</Button>
|
</Button>
|
||||||
{bodyshop.region_config.toLowerCase().startsWith("us") && (
|
|
||||||
<JobSendPartPriceChangeComponent job={job} />
|
|
||||||
)}
|
|
||||||
<JobCreateIOU job={job} selectedJobLines={selectedLines} />
|
<JobCreateIOU job={job} selectedJobLines={selectedLines} />
|
||||||
<Input.Search
|
<Input.Search
|
||||||
placeholder={t("general.labels.search")}
|
placeholder={t("general.labels.search")}
|
||||||
|
|||||||
@@ -1,149 +0,0 @@
|
|||||||
import React, { useState } from "react";
|
|
||||||
|
|
||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { Button, Form, Popover, Select, Space, notification } from "antd";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { UPDATE_LINE_BULK_ASSIGN } from "../../graphql/jobs-lines.queries";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import {
|
|
||||||
selectBodyshop,
|
|
||||||
selectCurrentUser,
|
|
||||||
} from "../../redux/user/user.selectors";
|
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
currentUser: selectCurrentUser,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
insertAuditTrail: ({ jobid, operation }) =>
|
|
||||||
dispatch(insertAuditTrail({ jobid, operation })),
|
|
||||||
});
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(JoblineBulkAssign);
|
|
||||||
|
|
||||||
export function JoblineBulkAssign({
|
|
||||||
setSelectedLines,
|
|
||||||
selectedLines,
|
|
||||||
insertAuditTrail,
|
|
||||||
bodyshop,
|
|
||||||
jobRO,
|
|
||||||
job,
|
|
||||||
currentUser,
|
|
||||||
}) {
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [assignLines] = useMutation(UPDATE_LINE_BULK_ASSIGN);
|
|
||||||
|
|
||||||
const handleConvert = async (values) => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
const result = await assignLines({
|
|
||||||
variables: {
|
|
||||||
jobline: {
|
|
||||||
assigned_team: values.assigned_team,
|
|
||||||
},
|
|
||||||
ids: selectedLines.map((l) => l.id),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (result.errors) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("parts_dispatch.errors.creating", {
|
|
||||||
error: JSON.stringify(result.errors),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
//Insert the audit trail here.
|
|
||||||
|
|
||||||
const teamName = bodyshop.employee_teams.find(
|
|
||||||
(et) => et.id === values.assigned_team
|
|
||||||
)?.name;
|
|
||||||
|
|
||||||
const hours = selectedLines.reduce(
|
|
||||||
(acc, val) => (acc += val.mod_lb_hrs),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
insertAuditTrail({
|
|
||||||
jobid: job.id,
|
|
||||||
operation: AuditTrailMapping.assignedlinehours(
|
|
||||||
teamName,
|
|
||||||
hours.toFixed(1)
|
|
||||||
),
|
|
||||||
});
|
|
||||||
setSelectedLines([]);
|
|
||||||
setVisible(false);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("parts_dispatch.errors.creating", {
|
|
||||||
error: error,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const popMenu = (
|
|
||||||
<div>
|
|
||||||
<Form layout="vertical" form={form} onFinish={handleConvert}>
|
|
||||||
<Form.Item
|
|
||||||
name={"assigned_team"}
|
|
||||||
label={t("joblines.fields.assigned_team")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
showSearch
|
|
||||||
style={{ width: 200 }}
|
|
||||||
optionFilterProp="children"
|
|
||||||
filterOption={(input, option) =>
|
|
||||||
option.props.children
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(input.toLowerCase()) >= 0
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{bodyshop.employee_teams.map((team) => (
|
|
||||||
<Select.Option value={team.id} key={team.id} name={team.name}>
|
|
||||||
{team.name}
|
|
||||||
</Select.Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Space wrap>
|
|
||||||
<Button type="danger" onClick={() => form.submit()} loading={loading}>
|
|
||||||
{t("general.actions.save")}
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => setVisible(false)}>
|
|
||||||
{t("general.actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover open={visible} content={popMenu}>
|
|
||||||
<Button
|
|
||||||
disabled={selectedLines.length === 0 || jobRO}
|
|
||||||
loading={loading}
|
|
||||||
onClick={() => setVisible(true)}
|
|
||||||
>
|
|
||||||
{t("joblines.actions.assign_team", { count: selectedLines.length })}
|
|
||||||
</Button>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
import React, { useState } from "react";
|
|
||||||
|
|
||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { Button, Form, Popover, Select, Space, notification } from "antd";
|
|
||||||
import moment from "moment";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { INSERT_PARTS_DISPATCH } from "../../graphql/parts-dispatch.queries";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import {
|
|
||||||
selectBodyshop,
|
|
||||||
selectCurrentUser,
|
|
||||||
} from "../../redux/user/user.selectors";
|
|
||||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
currentUser: selectCurrentUser,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(JobLineDispatchButton);
|
|
||||||
|
|
||||||
export function JobLineDispatchButton({
|
|
||||||
setSelectedLines,
|
|
||||||
selectedLines,
|
|
||||||
|
|
||||||
bodyshop,
|
|
||||||
jobRO,
|
|
||||||
job,
|
|
||||||
currentUser,
|
|
||||||
}) {
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const Templates = TemplateList("job_special", {
|
|
||||||
ro_number: job.ro_number,
|
|
||||||
});
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [dispatchLines] = useMutation(INSERT_PARTS_DISPATCH);
|
|
||||||
|
|
||||||
const handleConvert = async (values) => {
|
|
||||||
try {
|
|
||||||
setLoading(true);
|
|
||||||
//THIS HAS NOT YET BEEN TESTED. START BY FINISHING THIS FUNCTION.
|
|
||||||
const result = await dispatchLines({
|
|
||||||
variables: {
|
|
||||||
partsDispatch: {
|
|
||||||
dispatched_at: moment(),
|
|
||||||
employeeid: values.employeeid,
|
|
||||||
jobid: job.id,
|
|
||||||
dispatched_by: currentUser.email,
|
|
||||||
parts_dispatch_lines: {
|
|
||||||
data: selectedLines.map((l) => ({
|
|
||||||
joblineid: l.id,
|
|
||||||
quantity: l.part_qty,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
//joblineids: selectedLines.map((l) => l.id),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (result.errors) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("parts_dispatch.errors.creating", {
|
|
||||||
error: result.errors,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setSelectedLines([]);
|
|
||||||
await GenerateDocument(
|
|
||||||
{
|
|
||||||
name: Templates.parts_dispatch.key,
|
|
||||||
variables: {
|
|
||||||
id: result.data.insert_parts_dispatch_one.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{},
|
|
||||||
"p"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
setVisible(false);
|
|
||||||
} catch (error) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("parts_dispatch.errors.creating", {
|
|
||||||
error: error,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const popMenu = (
|
|
||||||
<div>
|
|
||||||
<Form layout="vertical" form={form} onFinish={handleConvert}>
|
|
||||||
<Form.Item
|
|
||||||
name={"employeeid"}
|
|
||||||
label={t("timetickets.fields.employee")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
showSearch
|
|
||||||
style={{ width: 200 }}
|
|
||||||
optionFilterProp="children"
|
|
||||||
filterOption={(input, option) =>
|
|
||||||
option.props.children
|
|
||||||
.toLowerCase()
|
|
||||||
.indexOf(input.toLowerCase()) >= 0
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{bodyshop.employees
|
|
||||||
.filter((emp) => emp.active)
|
|
||||||
.map((emp) => (
|
|
||||||
<Select.Option
|
|
||||||
value={emp.id}
|
|
||||||
key={emp.id}
|
|
||||||
name={`${emp.first_name} ${emp.last_name}`}
|
|
||||||
>
|
|
||||||
{`${emp.first_name} ${emp.last_name}`}
|
|
||||||
</Select.Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Space wrap>
|
|
||||||
<Button
|
|
||||||
type="danger"
|
|
||||||
onClick={() => form.submit()}
|
|
||||||
loading={loading}
|
|
||||||
disabled={selectedLines.length === 0}
|
|
||||||
>
|
|
||||||
{t("general.actions.save")}
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => setVisible(false)}>
|
|
||||||
{t("general.actions.cancel")}
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover open={visible} content={popMenu}>
|
|
||||||
<Button
|
|
||||||
disabled={selectedLines.length === 0 || jobRO}
|
|
||||||
loading={loading}
|
|
||||||
onClick={() => setVisible(true)}
|
|
||||||
>
|
|
||||||
{t("joblines.actions.dispatchparts", { count: selectedLines.length })}
|
|
||||||
</Button>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useMutation } from "@apollo/client";
|
import { useMutation } from "@apollo/client";
|
||||||
import { notification, Select, Space } from "antd";
|
import { notification, Select } from "antd";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -77,10 +77,7 @@ export function JobLineLocationPopup({ bodyshop, jobline, disabled }) {
|
|||||||
style={{ width: "100%", minHeight: "2rem", cursor: "pointer" }}
|
style={{ width: "100%", minHeight: "2rem", cursor: "pointer" }}
|
||||||
onClick={() => !disabled && setEditing(true)}
|
onClick={() => !disabled && setEditing(true)}
|
||||||
>
|
>
|
||||||
<Space wrap>
|
{jobline.location}
|
||||||
{jobline.location}
|
|
||||||
{jobline.parts_dispatch_lines?.length > 0 && "-Disp"}
|
|
||||||
</Space>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
import { notification, Select } from "antd";
|
|
||||||
import React, { useEffect, useState } from "react";
|
|
||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
//currentUser: selectCurrentUser
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
insertAuditTrail: ({ jobid, operation }) =>
|
|
||||||
dispatch(insertAuditTrail({ jobid, operation })),
|
|
||||||
});
|
|
||||||
|
|
||||||
export function JoblineTeamAssignment({
|
|
||||||
bodyshop,
|
|
||||||
jobline,
|
|
||||||
disabled,
|
|
||||||
jobId,
|
|
||||||
insertAuditTrail,
|
|
||||||
}) {
|
|
||||||
const [editing, setEditing] = useState(false);
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [assignedTeam, setAssignedTeam] = useState(jobline.assigned_team);
|
|
||||||
const [updateJob] = useMutation(UPDATE_JOB_LINE);
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (editing) setAssignedTeam(jobline.assigned_team);
|
|
||||||
}, [editing, jobline.assigned_team]);
|
|
||||||
|
|
||||||
const handleChange = (e) => {
|
|
||||||
setAssignedTeam(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSave = async (e) => {
|
|
||||||
setLoading(true);
|
|
||||||
const result = await updateJob({
|
|
||||||
variables: {
|
|
||||||
lineId: jobline.id,
|
|
||||||
line: { assigned_team: assignedTeam },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!!!result.errors) {
|
|
||||||
notification["success"]({ message: t("joblines.successes.saved") });
|
|
||||||
//insert the audit trail here.
|
|
||||||
const teamName = bodyshop.employee_teams.find(
|
|
||||||
(et) => et.id === assignedTeam
|
|
||||||
)?.name;
|
|
||||||
insertAuditTrail({
|
|
||||||
jobid: jobId,
|
|
||||||
operation: AuditTrailMapping.assignedlinehours(
|
|
||||||
teamName,
|
|
||||||
jobline.mod_lb_hrs
|
|
||||||
),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: t("joblines.errors.saving", {
|
|
||||||
error: JSON.stringify(result.errors),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
setEditing(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (editing)
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<LoadingSpinner loading={loading}>
|
|
||||||
<Select
|
|
||||||
autoFocus
|
|
||||||
allowClear
|
|
||||||
dropdownMatchSelectWidth={100}
|
|
||||||
value={assignedTeam}
|
|
||||||
onSelect={handleChange}
|
|
||||||
onBlur={handleSave}
|
|
||||||
onClear={() => handleChange(null)}
|
|
||||||
>
|
|
||||||
{Object.values(bodyshop.employee_teams).map((s, idx) => (
|
|
||||||
<Select.Option key={idx} value={s.id}>
|
|
||||||
{s.name}
|
|
||||||
</Select.Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
</LoadingSpinner>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
const team = bodyshop.employee_teams.find(
|
|
||||||
(tm) => tm.id === jobline.assigned_team
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={{ width: "100%", minHeight: "1rem", cursor: "pointer" }}
|
|
||||||
onClick={() => !disabled && setEditing(true)}
|
|
||||||
>
|
|
||||||
{team?.name}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(JoblineTeamAssignment);
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
import { Alert } from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
export default function JobProfileDataWarning({ job }) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
let missingProfileInfo =
|
|
||||||
Object.keys(job.cieca_pft).length === 0 ||
|
|
||||||
Object.keys(job.cieca_pfl).length === 0 ||
|
|
||||||
Object.keys(job.materials).length === 0;
|
|
||||||
|
|
||||||
if (missingProfileInfo)
|
|
||||||
return (
|
|
||||||
<Alert type="error" message={t("jobs.labels.missingprofileinfo")}></Alert>
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@@ -19,8 +19,7 @@ export default function JobReconciliationModalComponent({ job, bills }) {
|
|||||||
|
|
||||||
const jobLineData = job.joblines.filter(
|
const jobLineData = job.joblines.filter(
|
||||||
(j) =>
|
(j) =>
|
||||||
(j.part_type !== "PAE" && j.act_price !== 0 && j.part_qty !== 0) ||
|
(j.part_type !== null && j.part_type !== "PAE") ||
|
||||||
j.misc_amt !== 0 ||
|
|
||||||
(j.line_desc &&
|
(j.line_desc &&
|
||||||
j.line_desc.toLowerCase().includes("towing") &&
|
j.line_desc.toLowerCase().includes("towing") &&
|
||||||
j.lbr_op === "OP13") ||
|
j.lbr_op === "OP13") ||
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
import { Button, notification } from "antd";
|
|
||||||
import axios from "axios";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
export default function JobSendPartPriceChangeComponent({ job }) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const handleClick = async () => {
|
|
||||||
setLoading(true);
|
|
||||||
try {
|
|
||||||
const ppcData = await axios.post("/job/ppc", { jobid: job.id });
|
|
||||||
await axios.post("http://localhost:1337/ppc/", ppcData.data);
|
|
||||||
} catch (error) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("jobs.errors.partspricechange", {
|
|
||||||
error: JSON.stringify(error),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Button onClick={handleClick} loading={loading}>
|
|
||||||
{t("jobs.actions.sendpartspricechange")}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -67,8 +67,7 @@ export function JobsTotalsTableComponent({ jobRO, currentUser, job }) {
|
|||||||
<JobTotalsTableTotals job={job} />
|
<JobTotalsTableTotals job={job} />
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
{(currentUser.email.includes("@imex.") ||
|
{currentUser.email.includes("@imex.") && (
|
||||||
currentUser.email.includes("@rome.")) && (
|
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Card title="DEVELOPMENT USE ONLY">
|
<Card title="DEVELOPMENT USE ONLY">
|
||||||
<JobCalculateTotals job={job} disabled={jobRO} />
|
<JobCalculateTotals job={job} disabled={jobRO} />
|
||||||
|
|||||||
@@ -123,10 +123,11 @@ export default function JobTotalsTableLabor({ job }) {
|
|||||||
<Space>
|
<Space>
|
||||||
{t("jobs.labels.mapa")}
|
{t("jobs.labels.mapa")}
|
||||||
{job.materials &&
|
{job.materials &&
|
||||||
job.materials.MAPA &&
|
job.materials.mapa &&
|
||||||
job.materials.MAPA.cal_maxdlr !== undefined &&
|
job.materials.mapa.cal_maxdlr &&
|
||||||
|
job.materials.mapa.cal_maxdlr > 0 &&
|
||||||
t("jobs.labels.threshhold", {
|
t("jobs.labels.threshhold", {
|
||||||
amount: job.materials.MAPA.cal_maxdlr,
|
amount: job.materials.mapa.cal_maxdlr,
|
||||||
})}
|
})}
|
||||||
</Space>
|
</Space>
|
||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
@@ -147,10 +148,11 @@ export default function JobTotalsTableLabor({ job }) {
|
|||||||
<Space wrap>
|
<Space wrap>
|
||||||
{t("jobs.labels.mash")}
|
{t("jobs.labels.mash")}
|
||||||
{job.materials &&
|
{job.materials &&
|
||||||
job.materials.MASH &&
|
job.materials.mash &&
|
||||||
job.materials.MASH.cal_maxdlr !== undefined &&
|
job.materials.mash.cal_maxdlr &&
|
||||||
|
job.materials.mash.cal_maxdlr > 0 &&
|
||||||
t("jobs.labels.threshhold", {
|
t("jobs.labels.threshhold", {
|
||||||
amount: job.materials.MASH.cal_maxdlr,
|
amount: job.materials.mash.cal_maxdlr,
|
||||||
})}
|
})}
|
||||||
</Space>
|
</Space>
|
||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
|
|||||||
@@ -11,22 +11,6 @@ export default function JobTotalsTableParts({ job }) {
|
|||||||
filteredInfo: {},
|
filteredInfo: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
const insuranceAdjustments = useMemo(() => {
|
|
||||||
if (!job.job_totals) return [];
|
|
||||||
if (!job.job_totals?.parts?.adjustments) return [];
|
|
||||||
const adjs = [];
|
|
||||||
Object.keys(job.job_totals?.parts?.adjustments).forEach((key) => {
|
|
||||||
if (Dinero(job.job_totals?.parts?.adjustments[key]).getAmount() !== 0) {
|
|
||||||
adjs.push({
|
|
||||||
id: key,
|
|
||||||
amount: Dinero(job.job_totals.parts.adjustments[key]),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return adjs;
|
|
||||||
}, [job.job_totals]);
|
|
||||||
|
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
return Object.keys(job.job_totals.parts.parts.list)
|
return Object.keys(job.job_totals.parts.parts.list)
|
||||||
.filter(
|
.filter(
|
||||||
@@ -90,11 +74,11 @@ export default function JobTotalsTableParts({ job }) {
|
|||||||
<Table.Summary.Cell>
|
<Table.Summary.Cell>
|
||||||
{t("jobs.labels.prt_dsmk_total")}
|
{t("jobs.labels.prt_dsmk_total")}
|
||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
|
|
||||||
<Table.Summary.Cell align="right">
|
<Table.Summary.Cell align="right">
|
||||||
{Dinero(job.job_totals.parts.parts.prt_dsmk_total).toFormat()}
|
{Dinero(job.job_totals.parts.parts.prt_dsmk_total).toFormat()}
|
||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
</Table.Summary.Row>
|
</Table.Summary.Row>
|
||||||
|
|
||||||
<Table.Summary.Row>
|
<Table.Summary.Row>
|
||||||
<Table.Summary.Cell>
|
<Table.Summary.Cell>
|
||||||
<strong>{t("jobs.labels.partstotal")}</strong>
|
<strong>{t("jobs.labels.partstotal")}</strong>
|
||||||
@@ -106,24 +90,6 @@ export default function JobTotalsTableParts({ job }) {
|
|||||||
</strong>
|
</strong>
|
||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
</Table.Summary.Row>
|
</Table.Summary.Row>
|
||||||
{insuranceAdjustments.length > 0 && (
|
|
||||||
<Table.Summary.Row>
|
|
||||||
<Table.Summary.Cell colSpan={24}>
|
|
||||||
{t("jobs.labels.profileadjustments")}
|
|
||||||
</Table.Summary.Cell>
|
|
||||||
</Table.Summary.Row>
|
|
||||||
)}
|
|
||||||
{insuranceAdjustments.map((adj, idx) => (
|
|
||||||
<Table.Summary.Row key={idx}>
|
|
||||||
<Table.Summary.Cell>
|
|
||||||
{t(`jobs.fields.${adj.id.toLowerCase()}`)}
|
|
||||||
</Table.Summary.Cell>
|
|
||||||
|
|
||||||
<Table.Summary.Cell align="right">
|
|
||||||
{adj.amount.toFormat()}
|
|
||||||
</Table.Summary.Cell>
|
|
||||||
</Table.Summary.Row>
|
|
||||||
))}
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -28,109 +28,26 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
|
|||||||
total: job.job_totals.totals.subtotal,
|
total: job.job_totals.totals.subtotal,
|
||||||
bold: true,
|
bold: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
...(job.job_totals.totals.us_sales_tax_breakdown
|
key: t("jobs.labels.local_tax_amt"),
|
||||||
|
total: job.job_totals.totals.local_tax,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: t("jobs.labels.state_tax_amt"),
|
||||||
|
total: job.job_totals.totals.state_tax,
|
||||||
|
},
|
||||||
|
...(bodyshop.region_config === "CA_BC"
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
key: `${
|
key: t("jobs.fields.ca_bc_pvrt"),
|
||||||
bodyshop.md_responsibility_centers.taxes.tax_ty1?.tax_type1 ||
|
total: job.job_totals.additional.pvrt,
|
||||||
"T1"
|
|
||||||
} - ${[
|
|
||||||
job.cieca_pft.ty1_rate1,
|
|
||||||
job.cieca_pft.ty1_rate2,
|
|
||||||
job.cieca_pft.ty1_rate3,
|
|
||||||
job.cieca_pft.ty1_rate4,
|
|
||||||
job.cieca_pft.ty1_rate5,
|
|
||||||
]
|
|
||||||
.filter((i) => i > 0)
|
|
||||||
.join(", ")}%`,
|
|
||||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty1Tax,
|
|
||||||
},
|
},
|
||||||
{
|
]
|
||||||
key: `${
|
: []),
|
||||||
bodyshop.md_responsibility_centers.taxes.tax_ty2?.tax_type2 ||
|
{
|
||||||
"T2"
|
key: t("jobs.labels.federal_tax_amt"),
|
||||||
} - ${[
|
total: job.job_totals.totals.federal_tax,
|
||||||
job.cieca_pft.ty2_rate1,
|
},
|
||||||
job.cieca_pft.ty2_rate2,
|
|
||||||
job.cieca_pft.ty2_rate3,
|
|
||||||
job.cieca_pft.ty2_rate4,
|
|
||||||
job.cieca_pft.ty2_rate5,
|
|
||||||
]
|
|
||||||
.filter((i) => i > 0)
|
|
||||||
.join(", ")}%`,
|
|
||||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty2Tax,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: `${
|
|
||||||
bodyshop.md_responsibility_centers.taxes.tax_ty3?.tax_type3 ||
|
|
||||||
"T3"
|
|
||||||
} - ${[
|
|
||||||
job.cieca_pft.ty3_rate1,
|
|
||||||
job.cieca_pft.ty3_rate2,
|
|
||||||
job.cieca_pft.ty3_rate3,
|
|
||||||
job.cieca_pft.ty3_rate4,
|
|
||||||
job.cieca_pft.ty3_rate5,
|
|
||||||
]
|
|
||||||
.filter((i) => i > 0)
|
|
||||||
.join(", ")}%`,
|
|
||||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty3Tax,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: `${
|
|
||||||
bodyshop.md_responsibility_centers.taxes.tax_ty4?.tax_type4 ||
|
|
||||||
"T4"
|
|
||||||
} - ${[
|
|
||||||
job.cieca_pft.ty4_rate1,
|
|
||||||
job.cieca_pft.ty4_rate2,
|
|
||||||
job.cieca_pft.ty4_rate3,
|
|
||||||
job.cieca_pft.ty4_rate4,
|
|
||||||
job.cieca_pft.ty4_rate5,
|
|
||||||
]
|
|
||||||
.filter((i) => i > 0)
|
|
||||||
.join(", ")}%`,
|
|
||||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty4Tax,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: `${
|
|
||||||
bodyshop.md_responsibility_centers.taxes.tax_ty5?.tax_type5 ||
|
|
||||||
"TT"
|
|
||||||
} - ${[
|
|
||||||
job.cieca_pft.ty5_rate1,
|
|
||||||
job.cieca_pft.ty5_rate2,
|
|
||||||
job.cieca_pft.ty5_rate3,
|
|
||||||
job.cieca_pft.ty5_rate4,
|
|
||||||
job.cieca_pft.ty5_rate5,
|
|
||||||
]
|
|
||||||
.filter((i) => i > 0)
|
|
||||||
.join(", ")}%`,
|
|
||||||
total: job.job_totals.totals.us_sales_tax_breakdown.ty5Tax,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: t("jobs.labels.total_sales_tax"),
|
|
||||||
bold: true,
|
|
||||||
total: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty1Tax)
|
|
||||||
.add(
|
|
||||||
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty2Tax)
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty3Tax)
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty4Tax)
|
|
||||||
)
|
|
||||||
.add(
|
|
||||||
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty5Tax)
|
|
||||||
).toJSON(),
|
|
||||||
},
|
|
||||||
].filter((item) => item.total.amount !== 0)
|
|
||||||
: [
|
|
||||||
{
|
|
||||||
key: t("jobs.labels.state_tax_amt"),
|
|
||||||
total: job.job_totals.totals.state_tax,
|
|
||||||
},
|
|
||||||
]),
|
|
||||||
|
|
||||||
{
|
{
|
||||||
key: t("jobs.labels.total_repairs"),
|
key: t("jobs.labels.total_repairs"),
|
||||||
total: job.job_totals.totals.total_repairs,
|
total: job.job_totals.totals.total_repairs,
|
||||||
@@ -140,10 +57,10 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
|
|||||||
key: t("jobs.fields.ded_amt"),
|
key: t("jobs.fields.ded_amt"),
|
||||||
total: job.job_totals.totals.custPayable.deductible,
|
total: job.job_totals.totals.custPayable.deductible,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// key: t("jobs.fields.federal_tax_payable"),
|
key: t("jobs.fields.federal_tax_payable"),
|
||||||
// total: job.job_totals.totals.custPayable.federal_tax,
|
total: job.job_totals.totals.custPayable.federal_tax,
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
key: t("jobs.fields.other_amount_payable"),
|
key: t("jobs.fields.other_amount_payable"),
|
||||||
total: job.job_totals.totals.custPayable.other_customer_amount,
|
total: job.job_totals.totals.custPayable.other_customer_amount,
|
||||||
@@ -164,7 +81,7 @@ export function JobTotalsTableTotals({ bodyshop, job }) {
|
|||||||
bold: true,
|
bold: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [job.job_totals, job.cieca_pft, t, bodyshop.md_responsibility_centers]);
|
}, [job.job_totals, t, bodyshop.region_config]);
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
|
|||||||
//Found a relevant matching line. Add it to lines to update.
|
//Found a relevant matching line. Add it to lines to update.
|
||||||
linesToUpdate.push({
|
linesToUpdate.push({
|
||||||
id: existingLines[matchingIndex].id,
|
id: existingLines[matchingIndex].id,
|
||||||
newData: { ...newLine, removed: false, act_price_before_ppc: null },
|
newData: { ...newLine, removed: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
//Splice out item we found for performance.
|
//Splice out item we found for performance.
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import {
|
|||||||
useQuery,
|
useQuery,
|
||||||
} from "@apollo/client";
|
} from "@apollo/client";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import { Button, Col, Row, notification } from "antd";
|
import { Col, notification, Row } from "antd";
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import _ from "lodash";
|
import Dinero from "dinero.js";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
@@ -30,6 +30,7 @@ import {
|
|||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser,
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
|
import confirmDialog from "../../utils/asyncConfirm";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import CriticalPartsScan from "../../utils/criticalPartsScan";
|
import CriticalPartsScan from "../../utils/criticalPartsScan";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
@@ -91,15 +92,14 @@ export function JobsAvailableContainer({
|
|||||||
const modalSearchState = useState("");
|
const modalSearchState = useState("");
|
||||||
|
|
||||||
//Import Scenario
|
//Import Scenario
|
||||||
const onOwnerFindModalOk = async (lazyData) => {
|
const onOwnerFindModalOk = async () => {
|
||||||
logImEXEvent("job_import_new");
|
logImEXEvent("job_import_new");
|
||||||
|
|
||||||
setOwnerModalVisible(false);
|
setOwnerModalVisible(false);
|
||||||
|
|
||||||
setInsertLoading(true);
|
setInsertLoading(true);
|
||||||
const estData = replaceEmpty(
|
|
||||||
lazyData?.available_jobs_by_pk || estDataRaw.data.available_jobs_by_pk
|
const estData = replaceEmpty(estDataRaw.data.available_jobs_by_pk);
|
||||||
);
|
|
||||||
|
|
||||||
if (!(estData && estData.est_data)) {
|
if (!(estData && estData.est_data)) {
|
||||||
//We don't have the right data. Error!
|
//We don't have the right data. Error!
|
||||||
@@ -109,21 +109,17 @@ export function JobsAvailableContainer({
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// if (process.env.REACT_APP_COUNTRY === "USA") {
|
|
||||||
//Massage the CCC file set to remove duplicate UNQ_SEQ.
|
|
||||||
await ResolveCCCLineIssues(estData.est_data, bodyshop);
|
|
||||||
// } else {
|
|
||||||
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
||||||
await CheckTaxRates(estData.est_data, bodyshop);
|
await CheckTaxRates(estData.est_data, bodyshop);
|
||||||
// }
|
|
||||||
// const newTotals = (
|
const newTotals = (
|
||||||
// await Axios.post("/job/totals", {
|
await Axios.post("/job/totals", {
|
||||||
// job: {
|
job: {
|
||||||
// ...estData.est_data,
|
...estData.est_data,
|
||||||
// joblines: estData.est_data.joblines.data,
|
joblines: estData.est_data.joblines.data,
|
||||||
// },
|
},
|
||||||
// })
|
})
|
||||||
// ).data;
|
).data;
|
||||||
|
|
||||||
let existingVehicles;
|
let existingVehicles;
|
||||||
if (estData.est_data.v_vin) {
|
if (estData.est_data.v_vin) {
|
||||||
@@ -138,9 +134,9 @@ export function JobsAvailableContainer({
|
|||||||
|
|
||||||
const newJob = {
|
const newJob = {
|
||||||
...estData.est_data,
|
...estData.est_data,
|
||||||
// clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
||||||
// owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
|
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
|
||||||
// job_totals: newTotals,
|
job_totals: newTotals,
|
||||||
date_open: moment(),
|
date_open: moment(),
|
||||||
status: bodyshop.md_ro_statuses.default_imported,
|
status: bodyshop.md_ro_statuses.default_imported,
|
||||||
notes: {
|
notes: {
|
||||||
@@ -164,23 +160,17 @@ export function JobsAvailableContainer({
|
|||||||
delete newJob.vehicle;
|
delete newJob.vehicle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof newJob.kmin === "string") {
|
|
||||||
newJob.kmin = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const r = await insertNewJob({
|
const r = await insertNewJob({
|
||||||
variables: {
|
variables: {
|
||||||
job: newJob,
|
job: newJob,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
await Axios.post("/job/totalsssu", {
|
|
||||||
id: r.data.insert_jobs.returning[0].id,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (CriticalPartsScanning.treatment === "on") {
|
if (CriticalPartsScanning.treatment === "on") {
|
||||||
CriticalPartsScan(r.data.insert_jobs.returning[0].id);
|
CriticalPartsScan(r.data.insert_jobs.returning[0].id);
|
||||||
}
|
}
|
||||||
|
|
||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("jobs.successes.created"),
|
message: t("jobs.successes.created"),
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
@@ -194,7 +184,7 @@ export function JobsAvailableContainer({
|
|||||||
operation: AuditTrailMapping.jobimported(),
|
operation: AuditTrailMapping.jobimported(),
|
||||||
});
|
});
|
||||||
|
|
||||||
await deleteJob({
|
deleteJob({
|
||||||
variables: { id: estData.id },
|
variables: { id: estData.id },
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
refetch();
|
refetch();
|
||||||
@@ -202,16 +192,16 @@ export function JobsAvailableContainer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle);
|
setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle);
|
||||||
} catch (r) {
|
} catch (err) {
|
||||||
//error while inserting
|
//error while inserting
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("jobs.errors.creating", { error: r.message }),
|
message: t("jobs.errors.creating", { error: err.message }),
|
||||||
});
|
});
|
||||||
refetch();
|
refetch().catch(e => {console.error(`Something went wrong in jobs available table container - ${err.message || ''}`)});
|
||||||
setInsertLoading(false);
|
setInsertLoading(false);
|
||||||
setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle);
|
setPartsQueueToggle(bodyshop.md_functionality_toggles.parts_queue_toggle);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//Supplement scenario
|
//Supplement scenario
|
||||||
@@ -234,7 +224,6 @@ export function JobsAvailableContainer({
|
|||||||
let supp = replaceEmpty({ ...estData.est_data });
|
let supp = replaceEmpty({ ...estData.est_data });
|
||||||
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
||||||
await CheckTaxRates(supp, bodyshop);
|
await CheckTaxRates(supp, bodyshop);
|
||||||
await ResolveCCCLineIssues(supp, bodyshop);
|
|
||||||
|
|
||||||
delete supp.owner;
|
delete supp.owner;
|
||||||
delete supp.vehicle;
|
delete supp.vehicle;
|
||||||
@@ -410,25 +399,6 @@ export function JobsAvailableContainer({
|
|||||||
partsQueueToggle={partsQueueToggle}
|
partsQueueToggle={partsQueueToggle}
|
||||||
setPartsQueueToggle={setPartsQueueToggle}
|
setPartsQueueToggle={setPartsQueueToggle}
|
||||||
/>
|
/>
|
||||||
{currentUser.email.includes("@rome.") ||
|
|
||||||
currentUser.email.includes("@imex.") ? (
|
|
||||||
<Button
|
|
||||||
onClick={async () => {
|
|
||||||
for (const record of data.available_jobs) {
|
|
||||||
//Query the data
|
|
||||||
console.log("Start Job", record.id);
|
|
||||||
const { data } = await loadEstData({
|
|
||||||
variables: { id: record.id },
|
|
||||||
});
|
|
||||||
console.log("Query has been awaited and is complete");
|
|
||||||
await onOwnerFindModalOk(data);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Add all jobs as new.
|
|
||||||
</Button>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<JobsAvailableTableComponent
|
<JobsAvailableTableComponent
|
||||||
@@ -460,158 +430,115 @@ function replaceEmpty(someObj, replaceValue = null) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function CheckTaxRates(estData, bodyshop) {
|
async function CheckTaxRates(estData, bodyshop) {
|
||||||
// //LKQ Check
|
//LKQ Check
|
||||||
// if (
|
if (
|
||||||
// !estData.parts_tax_rates?.PAL ||
|
!estData.parts_tax_rates?.PAL ||
|
||||||
// estData.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
estData.parts_tax_rates?.PAL?.prt_tax_rt === null ||
|
||||||
// estData.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
estData.parts_tax_rates?.PAL?.prt_tax_rt === 0
|
||||||
// ) {
|
) {
|
||||||
// const res = await confirmDialog(
|
const res = await confirmDialog(
|
||||||
// `Rome 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.`
|
`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 (res) {
|
||||||
// if (!estData.parts_tax_rates.PAL) {
|
if (!estData.parts_tax_rates.PAL) {
|
||||||
// estData.parts_tax_rates.PAL = {
|
estData.parts_tax_rates.PAL = {
|
||||||
// prt_discp: 0,
|
prt_discp: 0,
|
||||||
// prt_mktyp: true,
|
prt_mktyp: true,
|
||||||
// prt_mkupp: 0,
|
prt_mkupp: 0,
|
||||||
// prt_type: "PAL",
|
prt_type: "PAL",
|
||||||
// };
|
};
|
||||||
// }
|
}
|
||||||
// estData.parts_tax_rates.PAL.prt_tax_rt =
|
estData.parts_tax_rates.PAL.prt_tax_rt =
|
||||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
// estData.parts_tax_rates.PAL.prt_tax_in = true;
|
estData.parts_tax_rates.PAL.prt_tax_in = true;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// //PAC Check
|
//PAC Check
|
||||||
// if (
|
if (
|
||||||
// !estData.parts_tax_rates?.PAC ||
|
!estData.parts_tax_rates?.PAC ||
|
||||||
// estData.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
estData.parts_tax_rates?.PAC?.prt_tax_rt === null ||
|
||||||
// estData.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
estData.parts_tax_rates?.PAC?.prt_tax_rt === 0
|
||||||
// ) {
|
) {
|
||||||
// const res = await confirmDialog(
|
const res = await confirmDialog(
|
||||||
// `Rome 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.`
|
`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 (res) {
|
||||||
// if (!estData.parts_tax_rates.PAC) {
|
if (!estData.parts_tax_rates.PAC) {
|
||||||
// estData.parts_tax_rates.PAC = {
|
estData.parts_tax_rates.PAC = {
|
||||||
// prt_discp: 0,
|
prt_discp: 0,
|
||||||
// prt_mktyp: true,
|
prt_mktyp: true,
|
||||||
// prt_mkupp: 0,
|
prt_mkupp: 0,
|
||||||
// prt_type: "PAC",
|
prt_type: "PAC",
|
||||||
// };
|
};
|
||||||
// }
|
}
|
||||||
// estData.parts_tax_rates.PAC.prt_tax_rt =
|
estData.parts_tax_rates.PAC.prt_tax_rt =
|
||||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
// estData.parts_tax_rates.PAC.prt_tax_in = true;
|
estData.parts_tax_rates.PAC.prt_tax_in = true;
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
//PAM Check
|
//PAM Check
|
||||||
if (!estData.parts_tax_rates?.PAM) {
|
if (
|
||||||
estData.parts_tax_rates.PAM = estData.parts_tax_rates.PAC;
|
!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.parts_tax_rates.PAM) {
|
||||||
|
estData.parts_tax_rates.PAM = {
|
||||||
|
prt_discp: 0,
|
||||||
|
prt_mktyp: true,
|
||||||
|
prt_mkupp: 0,
|
||||||
|
prt_type: "PAM",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
estData.parts_tax_rates.PAM.prt_tax_rt =
|
||||||
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
|
estData.parts_tax_rates.PAM.prt_tax_in = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// //PAM Check
|
if (
|
||||||
// if (
|
!estData.parts_tax_rates?.PAR ||
|
||||||
// !estData.parts_tax_rates?.PAM ||
|
estData.parts_tax_rates?.PAR?.prt_tax_rt === null ||
|
||||||
// estData.parts_tax_rates?.PAM?.prt_tax_rt === null ||
|
estData.parts_tax_rates?.PAR?.prt_tax_rt === 0
|
||||||
// estData.parts_tax_rates?.PAM?.prt_tax_rt === 0
|
) {
|
||||||
// ) {
|
const res = await confirmDialog(
|
||||||
// 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.`
|
||||||
// `Rome 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 (res) {
|
if (!estData.parts_tax_rates.PAR) {
|
||||||
// if (!estData.parts_tax_rates.PAM) {
|
estData.parts_tax_rates.PAR = {
|
||||||
// estData.parts_tax_rates.PAM = {
|
prt_discp: 0,
|
||||||
// prt_discp: 0,
|
prt_mktyp: true,
|
||||||
// prt_mktyp: true,
|
prt_mkupp: 0,
|
||||||
// prt_mkupp: 0,
|
prt_type: "PAR",
|
||||||
// prt_type: "PAM",
|
};
|
||||||
// };
|
}
|
||||||
// }
|
estData.parts_tax_rates.PAR.prt_tax_rt =
|
||||||
// estData.parts_tax_rates.PAM.prt_tax_rt =
|
bodyshop.bill_tax_rates.state_tax_rate / 100;
|
||||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
estData.parts_tax_rates.PAR.prt_tax_in = true;
|
||||||
// estData.parts_tax_rates.PAM.prt_tax_in = true;
|
}
|
||||||
// }
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// if (
|
|
||||||
// !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(
|
|
||||||
// `Rome 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.parts_tax_rates.PAR) {
|
|
||||||
// estData.parts_tax_rates.PAR = {
|
|
||||||
// prt_discp: 0,
|
|
||||||
// prt_mktyp: true,
|
|
||||||
// prt_mkupp: 0,
|
|
||||||
// prt_type: "PAR",
|
|
||||||
// };
|
|
||||||
// }
|
|
||||||
// estData.parts_tax_rates.PAR.prt_tax_rt =
|
|
||||||
// bodyshop.bill_tax_rates.state_tax_rate / 100;
|
|
||||||
// estData.parts_tax_rates.PAR.prt_tax_in = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//IO-1387 If a sublet line is NOT R&R, use the labor tax. If it is, use the sublet tax rate.
|
//IO-1387 If a sublet line is NOT R&R, use the labor tax. If it is, use the sublet tax rate.
|
||||||
//Currently limited to SK shops only.
|
//Currently limited to SK shops only.
|
||||||
if (bodyshop.region_config === "CA_SK") {
|
//if (bodyshop.region_config === "CA_SK") {
|
||||||
estData.joblines.data.forEach((jl, index) => {
|
estData.joblines.data.forEach((jl, index) => {
|
||||||
if (
|
if (
|
||||||
(jl.part_type === "PASL" || jl.part_type === "PAS") &&
|
(jl.part_type === "PASL" || jl.part_type === "PAS") &&
|
||||||
jl.lbr_op !== "OP11"
|
jl.lbr_op !== "OP11"
|
||||||
) {
|
) {
|
||||||
estData.joblines.data[index].tax_part = jl.lbr_tax;
|
estData.joblines.data[index].tax_part = jl.lbr_tax;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set markup lines and tax lines as taxable.
|
//Set markup lines and tax lines as taxable.
|
||||||
//900510 is a mark up. 900510 is a discount.
|
//900510 is a mark up. 900510 is a discount.
|
||||||
if (jl.db_ref === "900510") {
|
if (jl.db_ref === "900510") {
|
||||||
estData.joblines.data[index].tax_part = true;
|
estData.joblines.data[index].tax_part = true;
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ResolveCCCLineIssues(estData, bodyshop) {
|
|
||||||
//Find all misc amounts, populate them to the act price.
|
|
||||||
//TODO Ensure that this doesnt get violated
|
|
||||||
//This needs to be done before cleansing unq_seq since some misc prices could move over.
|
|
||||||
estData.joblines.data.forEach((line) => {
|
|
||||||
if (line.misc_amt && line.misc_amt !== 0) {
|
|
||||||
line.act_price = line.act_price + line.misc_amt;
|
|
||||||
line.tax_part = !!line.misc_tax;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
//}
|
||||||
//Generate the list of duplicated UNQ_SEQ that will feed into the next section to scrub the lines.
|
|
||||||
const unqSeqHash = _.groupBy(estData.joblines.data, "unq_seq");
|
|
||||||
const duplicatedUnqSeq = Object.keys(unqSeqHash).filter(
|
|
||||||
(key) => unqSeqHash[key].length > 1
|
|
||||||
);
|
|
||||||
|
|
||||||
duplicatedUnqSeq.forEach((unq_seq) => {
|
|
||||||
//Keys are strings, convert to int.
|
|
||||||
const int_unq_seq = parseInt(unq_seq);
|
|
||||||
|
|
||||||
//When line splitting, the first line is always the non-refinish line. We will keep it as is.
|
|
||||||
//We will cleanse the second line, which is always the next line.
|
|
||||||
const nonRefLineIndex = estData.joblines.data.findIndex(
|
|
||||||
(line) => line.unq_seq === int_unq_seq
|
|
||||||
);
|
|
||||||
estData.joblines.data[nonRefLineIndex + 1] = {
|
|
||||||
...estData.joblines.data[nonRefLineIndex + 1],
|
|
||||||
part_type: null,
|
|
||||||
act_price: 0,
|
|
||||||
db_price: 0,
|
|
||||||
prt_dsmk_p: 0,
|
|
||||||
prt_dsmk_m: 0,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,6 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
|||||||
ret.profitcenter_part = defaults.profits["MAPA"];
|
ret.profitcenter_part = defaults.profits["MAPA"];
|
||||||
} else if (lineDesc.includes("ats amount")) {
|
} else if (lineDesc.includes("ats amount")) {
|
||||||
ret.profitcenter_part = defaults.profits["ATS"];
|
ret.profitcenter_part = defaults.profits["ATS"];
|
||||||
} else if (jl.act_price > 0) {
|
|
||||||
ret.profitcenter_part = defaults.profits["PAO"];
|
|
||||||
} else {
|
} else {
|
||||||
ret.profitcenter_part = null;
|
ret.profitcenter_part = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Collapse, Form, Input, Select, Switch } from "antd";
|
import { Collapse, Form, Input, InputNumber, Select, Switch } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -12,12 +12,6 @@ import FormItemPhone, {
|
|||||||
} from "../form-items-formatted/phone-form-item.component";
|
} from "../form-items-formatted/phone-form-item.component";
|
||||||
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
|
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
|
||||||
import JobsDetailRatesParts from "../jobs-detail-rates/jobs-detail-rates.parts.component";
|
import JobsDetailRatesParts from "../jobs-detail-rates/jobs-detail-rates.parts.component";
|
||||||
|
|
||||||
import JobsDetailRatesLabor from "../jobs-detail-rates/jobs-detail-rates.labor.component";
|
|
||||||
import JobsDetailRatesMaterials from "../jobs-detail-rates/jobs-detail-rates.materials.component";
|
|
||||||
import JobsDetailRatesOther from "../jobs-detail-rates/jobs-detail-rates.other.component";
|
|
||||||
import JobsDetailRatesTaxes from "../jobs-detail-rates/jobs-detail-rates.taxes.component";
|
|
||||||
|
|
||||||
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
|
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
@@ -264,28 +258,26 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
|
|||||||
<CurrencyInput />
|
<CurrencyInput />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
{
|
<LayoutFormRow>
|
||||||
// <LayoutFormRow>
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("jobs.fields.federal_tax_rate")}
|
||||||
// label={t("jobs.fields.federal_tax_rate")}
|
name="federal_tax_rate"
|
||||||
// name="federal_tax_rate"
|
>
|
||||||
// >
|
<InputNumber min={0} max={1} precision={2} />
|
||||||
// <InputNumber min={0} max={1} precision={2} />
|
</Form.Item>
|
||||||
// </Form.Item>
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("jobs.fields.state_tax_rate")}
|
||||||
// label={t("jobs.fields.state_tax_rate")}
|
name="state_tax_rate"
|
||||||
// name="state_tax_rate"
|
>
|
||||||
// >
|
<InputNumber min={0} max={1} precision={2} />
|
||||||
// <InputNumber min={0} max={1} precision={2} />
|
</Form.Item>
|
||||||
// </Form.Item>
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("jobs.fields.local_tax_rate")}
|
||||||
// label={t("jobs.fields.local_tax_rate")}
|
name="local_tax_rate"
|
||||||
// name="local_tax_rate"
|
>
|
||||||
// >
|
<InputNumber min={0} max={1} precision={2} />
|
||||||
// <InputNumber min={0} max={1} precision={2} />
|
</Form.Item>
|
||||||
// </Form.Item>
|
</LayoutFormRow>
|
||||||
// </LayoutFormRow>
|
|
||||||
}
|
|
||||||
<LayoutFormRow>
|
<LayoutFormRow>
|
||||||
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
|
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
|
||||||
<CurrencyInput />
|
<CurrencyInput />
|
||||||
@@ -364,10 +356,6 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
|
|||||||
required={selected && true}
|
required={selected && true}
|
||||||
form={form}
|
form={form}
|
||||||
/>
|
/>
|
||||||
<JobsDetailRatesLabor form={form} />
|
|
||||||
<JobsDetailRatesMaterials form={form} />
|
|
||||||
<JobsDetailRatesOther form={form} />
|
|
||||||
<JobsDetailRatesTaxes form={form} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,6 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
dispatch(setModalContext({ context: context, modal: "jobCosting" })),
|
dispatch(setModalContext({ context: context, modal: "jobCosting" })),
|
||||||
setTimeTicketContext: (context) =>
|
setTimeTicketContext: (context) =>
|
||||||
dispatch(setModalContext({ context: context, modal: "timeTicket" })),
|
dispatch(setModalContext({ context: context, modal: "timeTicket" })),
|
||||||
setTimeTicketTaskContext: (context) =>
|
|
||||||
dispatch(setModalContext({ context: context, modal: "timeTicketTask" })),
|
|
||||||
setCardPaymentContext: (context) =>
|
setCardPaymentContext: (context) =>
|
||||||
dispatch(setModalContext({ context: context, modal: "cardPayment" })),
|
dispatch(setModalContext({ context: context, modal: "cardPayment" })),
|
||||||
insertAuditTrail: ({ jobid, operation }) =>
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
@@ -69,7 +67,6 @@ export function JobsDetailHeaderActions({
|
|||||||
setJobCostingContext,
|
setJobCostingContext,
|
||||||
jobRO,
|
jobRO,
|
||||||
setTimeTicketContext,
|
setTimeTicketContext,
|
||||||
setTimeTicketTaskContext,
|
|
||||||
setCardPaymentContext,
|
setCardPaymentContext,
|
||||||
insertAuditTrail,
|
insertAuditTrail,
|
||||||
}) {
|
}) {
|
||||||
@@ -111,6 +108,14 @@ export function JobsDetailHeaderActions({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: job.id,
|
||||||
|
operation: AuditTrailMapping.alertToggle(
|
||||||
|
!!job.production_vars && !!job.production_vars.alert
|
||||||
|
? !job.production_vars.alert
|
||||||
|
: true
|
||||||
|
),
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSuspend = (e) => {
|
const handleSuspend = (e) => {
|
||||||
@@ -271,24 +276,6 @@ export function JobsDetailHeaderActions({
|
|||||||
>
|
>
|
||||||
{t("timetickets.actions.enter")}
|
{t("timetickets.actions.enter")}
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
{bodyshop.md_tasks_presets.enable_tasks && (
|
|
||||||
<Menu.Item
|
|
||||||
key="claimtimetickettasks"
|
|
||||||
disabled={
|
|
||||||
!job.converted ||
|
|
||||||
(!bodyshop.tt_allow_post_to_invoiced && job.date_invoiced)
|
|
||||||
}
|
|
||||||
onClick={() => {
|
|
||||||
setTimeTicketTaskContext({
|
|
||||||
actions: {},
|
|
||||||
context: { jobid: job.id },
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("timetickets.actions.claimtasks")}
|
|
||||||
</Menu.Item>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="enterpayments"
|
key="enterpayments"
|
||||||
disabled={!job.converted}
|
disabled={!job.converted}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import {
|
import {
|
||||||
|
BranchesOutlined,
|
||||||
ExclamationCircleFilled,
|
ExclamationCircleFilled,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
WarningFilled,
|
WarningFilled,
|
||||||
BranchesOutlined,
|
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { Card, Col, Row, Space, Tag, Tooltip } from "antd";
|
import { Card, Col, Row, Space, Tag, Tooltip } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
@@ -222,6 +222,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
{`${job.v_vin || t("general.labels.na")}`}
|
{`${job.v_vin || t("general.labels.na")}`}
|
||||||
</VehicleVinDisplay>
|
</VehicleVinDisplay>
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
|
<DataLabel label={t("jobs.fields.regie_number")}>
|
||||||
|
{job.regie_number || t("general.labels.na")}
|
||||||
|
</DataLabel>
|
||||||
<DataLabel label={t("jobs.labels.relatedros")}>
|
<DataLabel label={t("jobs.labels.relatedros")}>
|
||||||
<JobsRelatedRos jobid={job.id} job={job} />
|
<JobsRelatedRos jobid={job.id} job={job} />
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
|
|||||||
@@ -5,13 +5,9 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||||
import LaborAllocationsTableComponent from "../labor-allocations-table/labor-allocations-table.component";
|
import LaborAllocationsTableComponent from "../labor-allocations-table/labor-allocations-table.component";
|
||||||
import TimeTicketList from "../time-ticket-list/time-ticket-list.component";
|
import TimeTicketList from "../time-ticket-list/time-ticket-list.component";
|
||||||
import PayrollLaborAllocationsTable from "../labor-allocations-table/labor-allocations-table.payroll.component";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(mapStateToProps, null)(JobsDetailLaborContainer);
|
export default connect(mapStateToProps, null)(JobsDetailLaborContainer);
|
||||||
@@ -52,7 +48,6 @@ const adjSpan = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function JobsDetailLaborContainer({
|
export function JobsDetailLaborContainer({
|
||||||
bodyshop,
|
|
||||||
jobRO,
|
jobRO,
|
||||||
job,
|
job,
|
||||||
jobId,
|
jobId,
|
||||||
@@ -63,12 +58,6 @@ export function JobsDetailLaborContainer({
|
|||||||
techConsole,
|
techConsole,
|
||||||
adjustments,
|
adjustments,
|
||||||
}) {
|
}) {
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col {...ticketSpan}>
|
<Col {...ticketSpan}>
|
||||||
@@ -81,28 +70,14 @@ export function JobsDetailLaborContainer({
|
|||||||
jobId={jobId}
|
jobId={jobId}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...adjSpan}>
|
||||||
{Enhanced_Payroll.treatment === "on" ? (
|
<LaborAllocationsTableComponent
|
||||||
<Col {...adjSpan}>
|
jobId={jobId}
|
||||||
<PayrollLaborAllocationsTable
|
joblines={joblines}
|
||||||
jobId={jobId}
|
timetickets={timetickets}
|
||||||
joblines={joblines}
|
adjustments={adjustments}
|
||||||
timetickets={timetickets}
|
/>
|
||||||
refetch={refetch}
|
</Col>
|
||||||
adjustments={adjustments}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
) : (
|
|
||||||
<Col {...adjSpan}>
|
|
||||||
<LaborAllocationsTableComponent
|
|
||||||
jobId={jobId}
|
|
||||||
joblines={joblines}
|
|
||||||
timetickets={timetickets}
|
|
||||||
refetch={refetch}
|
|
||||||
adjustments={adjustments}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
)}
|
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ import BillsListTable from "../bills-list-table/bills-list-table.component";
|
|||||||
import JobBillsTotal from "../job-bills-total/job-bills-total.component";
|
import JobBillsTotal from "../job-bills-total/job-bills-total.component";
|
||||||
import PartsOrderListTableComponent from "../parts-order-list-table/parts-order-list-table.component";
|
import PartsOrderListTableComponent from "../parts-order-list-table/parts-order-list-table.component";
|
||||||
import PartsOrderModal from "../parts-order-modal/parts-order-modal.container";
|
import PartsOrderModal from "../parts-order-modal/parts-order-modal.container";
|
||||||
import PartsDispatchTable from "../parts-dispatch-table/parts-dispatch-table.component";
|
|
||||||
|
|
||||||
export default function JobsDetailPliComponent({
|
export default function JobsDetailPliComponent({
|
||||||
job,
|
job,
|
||||||
billsQuery,
|
billsQuery,
|
||||||
handleBillOnRowClick,
|
handleBillOnRowClick,
|
||||||
handlePartsOrderOnRowClick,
|
handlePartsOrderOnRowClick,
|
||||||
handlePartsDispatchOnRowClick,
|
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -45,13 +43,6 @@ export default function JobsDetailPliComponent({
|
|||||||
billsQuery={billsQuery}
|
billsQuery={billsQuery}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
|
||||||
<PartsDispatchTable
|
|
||||||
job={job}
|
|
||||||
handleOnRowClick={handlePartsDispatchOnRowClick}
|
|
||||||
billsQuery={billsQuery}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
</Row>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -39,24 +39,12 @@ export default function JobsDetailPliContainer({ job }) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePartsDispatchOnRowClick = (record) => {
|
|
||||||
if (record) {
|
|
||||||
if (record.id) {
|
|
||||||
search.partsdispatchid = record.id;
|
|
||||||
history.push({ search: queryString.stringify(search) });
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete search.partsdispatchid;
|
|
||||||
history.push({ search: queryString.stringify(search) });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<JobsDetailPliComponent
|
<JobsDetailPliComponent
|
||||||
job={job}
|
job={job}
|
||||||
billsQuery={billsQuery}
|
billsQuery={billsQuery}
|
||||||
handleBillOnRowClick={handleBillOnRowClick}
|
handleBillOnRowClick={handleBillOnRowClick}
|
||||||
handlePartsOrderOnRowClick={handlePartsOrderOnRowClick}
|
handlePartsOrderOnRowClick={handlePartsOrderOnRowClick}
|
||||||
handlePartsDispatchOnRowClick={handlePartsDispatchOnRowClick}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,25 @@
|
|||||||
import { Divider, Form, Input, Select, Space, Switch, Tooltip } from "antd";
|
import {
|
||||||
|
Divider,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
InputNumber,
|
||||||
|
Select,
|
||||||
|
Space,
|
||||||
|
Switch,
|
||||||
|
Tooltip,
|
||||||
|
} from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component";
|
||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
|
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
|
||||||
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
|
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
|
||||||
import FormRow from "../layout-form-row/layout-form-row.component";
|
import FormRow from "../layout-form-row/layout-form-row.component";
|
||||||
import JobsDetailRatesLabor from "./jobs-detail-rates.labor.component";
|
|
||||||
import JobsDetailRatesMaterials from "./jobs-detail-rates.materials.component";
|
|
||||||
import JobsDetailRatesOther from "./jobs-detail-rates.other.component";
|
|
||||||
import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
|
import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
|
||||||
import JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
|
|
||||||
import JobsDetailRatesProfileOVerride from "./jobs-detail-rates.profile-override.component";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
@@ -80,7 +84,14 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<CurrencyInput disabled={jobRO || bodyshop.cdk_dealerid} />
|
<CurrencyInput disabled={jobRO || bodyshop.cdk_dealerid} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{bodyshop.region_config === "CA_BC" && (
|
||||||
|
<Space align="center">
|
||||||
|
<Form.Item label={t("jobs.fields.ca_bc_pvrt")} name="ca_bc_pvrt">
|
||||||
|
<CurrencyInput disabled={jobRO} min={0} />
|
||||||
|
</Form.Item>
|
||||||
|
<CABCpvrtCalculator form={form} disabled={jobRO} />
|
||||||
|
</Space>
|
||||||
|
)}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.auto_add_ats")}
|
label={t("jobs.fields.auto_add_ats")}
|
||||||
name="auto_add_ats"
|
name="auto_add_ats"
|
||||||
@@ -109,7 +120,41 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
|||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
|
<FormRow>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.federal_tax_rate")}
|
||||||
|
name="federal_tax_rate"
|
||||||
|
>
|
||||||
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.state_tax_rate")}
|
||||||
|
name="state_tax_rate"
|
||||||
|
>
|
||||||
|
<InputNumber
|
||||||
|
min={0}
|
||||||
|
max={1}
|
||||||
|
precision={2}
|
||||||
|
disabled={jobRO}
|
||||||
|
autoComplete="new-password"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.local_tax_rate")}
|
||||||
|
name="local_tax_rate"
|
||||||
|
>
|
||||||
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
|
</Form.Item>
|
||||||
|
{bodyshop.region_config.toLowerCase().startsWith("ca") && (
|
||||||
|
<Form.Item
|
||||||
|
label={t("jobs.fields.ca_gst_registrant")}
|
||||||
|
name="ca_gst_registrant"
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
|
<Switch disabled={jobRO} />
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</FormRow>
|
||||||
<Divider
|
<Divider
|
||||||
orientation="left"
|
orientation="left"
|
||||||
type="horizontal"
|
type="horizontal"
|
||||||
@@ -197,15 +242,7 @@ export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
|||||||
<CurrencyInput min={0} disabled={jobRO} />
|
<CurrencyInput min={0} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
<Divider orientation="left">Tax Profile</Divider>
|
|
||||||
|
|
||||||
<JobsDetailRatesProfileOVerride form={form} />
|
|
||||||
|
|
||||||
<JobsDetailRatesParts form={form} />
|
<JobsDetailRatesParts form={form} />
|
||||||
<JobsDetailRatesLabor form={form} />
|
|
||||||
<JobsDetailRatesMaterials form={form} />
|
|
||||||
<JobsDetailRatesOther form={form} />
|
|
||||||
<JobsDetailRatesTaxes form={form} />
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,427 +0,0 @@
|
|||||||
import { Collapse, Form, Switch } from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function JobsDetailRatesLabor({
|
|
||||||
jobRO,
|
|
||||||
expanded,
|
|
||||||
required = true,
|
|
||||||
form,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
|
||||||
<Collapse.Panel
|
|
||||||
forceRender
|
|
||||||
header={t("jobs.labels.cieca_pfl")}
|
|
||||||
key="cieca_pfl"
|
|
||||||
>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAB")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAB", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAB", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAB", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAB", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAB", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAB", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAD")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAD", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAD", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAD", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAD", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAD", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAD", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAE")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAE", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAE", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAE", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAE", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAE", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAE", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAF")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAF", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAF", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAF", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAF", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAF", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAF", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAG")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAG", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAG", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAG", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAG", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAG", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAG", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAM")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAM", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAM", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAM", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAM", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAM", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAM", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAR")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAR", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAR", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAR", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAR", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAR", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAR", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAS")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAS", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAS", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAS", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAS", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAS", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAS", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("joblines.fields.lbr_types.LAU")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tax_in")}
|
|
||||||
name={["cieca_pfl", "LAU", "lbr_tax_in"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in1")}
|
|
||||||
name={["cieca_pfl", "LAU", "lbr_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in2")}
|
|
||||||
name={["cieca_pfl", "LAU", "lbr_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in3")}
|
|
||||||
name={["cieca_pfl", "LAU", "lbr_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in4")}
|
|
||||||
name={["cieca_pfl", "LAU", "lbr_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfl.lbr_tx_in5")}
|
|
||||||
name={["cieca_pfl", "LAU", "lbr_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
</Collapse.Panel>
|
|
||||||
</Collapse>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(mapStateToProps, null)(JobsDetailRatesLabor);
|
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
import { Collapse, Form, Input, InputNumber, Switch } from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function JobsDetailRatesMaterials({
|
|
||||||
jobRO,
|
|
||||||
expanded,
|
|
||||||
required = true,
|
|
||||||
form,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
|
||||||
<Collapse.Panel
|
|
||||||
forceRender
|
|
||||||
header={t("jobs.fields.materials.materials")}
|
|
||||||
key="materials"
|
|
||||||
>
|
|
||||||
<LayoutFormRow header={t("jobs.fields.materials.MAPA")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.cal_maxdlr")}
|
|
||||||
name={["materials", "MAPA", "cal_maxdlr"]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} precision={2} disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.cal_opcode")}
|
|
||||||
name={["materials", "MAPA", "cal_opcode"]}
|
|
||||||
>
|
|
||||||
<Input disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.tax_ind")}
|
|
||||||
name={["materials", "MAPA", "tax_ind"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in1")}
|
|
||||||
name={["materials", "MAPA", "mat_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in2")}
|
|
||||||
name={["materials", "MAPA", "mat_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in3")}
|
|
||||||
name={["materials", "MAPA", "mat_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in4")}
|
|
||||||
name={["materials", "MAPA", "mat_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in5")}
|
|
||||||
name={["materials", "MAPA", "mat_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<LayoutFormRow header={t("jobs.fields.materials.MASH")}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.cal_maxdlr")}
|
|
||||||
name={["materials", "MASH", "cal_maxdlr"]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} precision={2} disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.cal_opcode")}
|
|
||||||
name={["materials", "MASH", "cal_opcode"]}
|
|
||||||
>
|
|
||||||
<Input disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.tax_ind")}
|
|
||||||
name={["materials", "MASH", "tax_ind"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in1")}
|
|
||||||
name={["materials", "MASH", "mat_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in2")}
|
|
||||||
name={["materials", "MASH", "mat_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in3")}
|
|
||||||
name={["materials", "MASH", "mat_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in4")}
|
|
||||||
name={["materials", "MASH", "mat_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.materials.mat_tx_in5")}
|
|
||||||
name={["materials", "MASH", "mat_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
</Collapse.Panel>
|
|
||||||
</Collapse>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(mapStateToProps, null)(JobsDetailRatesMaterials);
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
import { Collapse, Form, Switch } from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function JobsDetailRatesOther({
|
|
||||||
jobRO,
|
|
||||||
expanded,
|
|
||||||
required = true,
|
|
||||||
form,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
|
||||||
<Collapse.Panel
|
|
||||||
forceRender
|
|
||||||
header={t("jobs.labels.cieca_pfo")}
|
|
||||||
key="cieca_pfo"
|
|
||||||
>
|
|
||||||
<LayoutFormRow noDivider>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.tow_t_in1")}
|
|
||||||
name={["cieca_pfo", "tow_t_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.tow_t_in2")}
|
|
||||||
name={["cieca_pfo", "tow_t_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.tow_t_in3")}
|
|
||||||
name={["cieca_pfo", "tow_t_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.tow_t_in4")}
|
|
||||||
name={["cieca_pfo", "tow_t_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.tow_t_in5")}
|
|
||||||
name={["cieca_pfo", "tow_t_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.stor_t_in1")}
|
|
||||||
name={["cieca_pfo", "stor_t_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.stor_t_in2")}
|
|
||||||
name={["cieca_pfo", "stor_t_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.stor_t_in3")}
|
|
||||||
name={["cieca_pfo", "stor_t_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.stor_t_in4")}
|
|
||||||
name={["cieca_pfo", "stor_t_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.cieca_pfo.stor_t_in5")}
|
|
||||||
name={["cieca_pfo", "stor_t_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
</Collapse.Panel>
|
|
||||||
</Collapse>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(mapStateToProps, null)(JobsDetailRatesOther);
|
|
||||||
@@ -29,7 +29,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAA", "prt_discp"]}
|
name={["parts_tax_rates", "PAA", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -42,7 +42,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAA", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAA", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -68,58 +68,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAA", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAA", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAA", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAA", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAA", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAC")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAC")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAC", "prt_discp"]}
|
name={["parts_tax_rates", "PAC", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -132,7 +92,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAC", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAC", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -158,58 +118,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAC", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAC", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAC", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAC", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAC", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAL")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAL")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAL", "prt_discp"]}
|
name={["parts_tax_rates", "PAL", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -222,7 +142,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAL", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAL", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -248,58 +168,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAL", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAL", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAL", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAL", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAL", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAG")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAG")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAG", "prt_discp"]}
|
name={["parts_tax_rates", "PAG", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -312,7 +192,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAG", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAG", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -338,58 +218,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAG", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAG", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAG", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAG", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAG", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAM")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAM")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAM", "prt_discp"]}
|
name={["parts_tax_rates", "PAM", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -402,7 +242,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAM", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAM", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -428,58 +268,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAM", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAM", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAM", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAM", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAM", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAN")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAN")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAN", "prt_discp"]}
|
name={["parts_tax_rates", "PAN", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -492,7 +292,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAN", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAN", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -518,58 +318,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAN", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAN", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAN", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAN", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAN", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAO")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAO")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAO", "prt_discp"]}
|
name={["parts_tax_rates", "PAO", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -582,7 +342,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAO", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAO", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -608,58 +368,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAO", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAO", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAO", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAO", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAO", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAP")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAP")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAP", "prt_discp"]}
|
name={["parts_tax_rates", "PAP", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -672,7 +392,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAP", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAP", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -698,58 +418,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAP", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAP", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAP", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAP", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAP", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAR")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAR")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAR", "prt_discp"]}
|
name={["parts_tax_rates", "PAR", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -762,7 +442,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAR", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAR", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -788,58 +468,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAR", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAR", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAR", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAR", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAR", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PAS")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PAS")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PAS", "prt_discp"]}
|
name={["parts_tax_rates", "PAS", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -852,7 +492,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PAS", "prt_mkupp"]}
|
name={["parts_tax_rates", "PAS", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -878,58 +518,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PAS", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PAS", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PAS", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PAS", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PAS", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.PASL")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.PASL")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "PASL", "prt_discp"]}
|
name={["parts_tax_rates", "PASL", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -942,7 +542,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "PASL", "prt_mkupp"]}
|
name={["parts_tax_rates", "PASL", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -968,58 +568,18 @@ export function JobsDetailRatesParts({
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
min={0}
|
|
||||||
max={100}
|
|
||||||
precision={4}
|
|
||||||
disabled={jobRO}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in1")}
|
|
||||||
name={["parts_tax_rates", "PASL", "prt_tx_in1"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in2")}
|
|
||||||
name={["parts_tax_rates", "PASL", "prt_tx_in2"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in3")}
|
|
||||||
name={["parts_tax_rates", "PASL", "prt_tx_in3"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in4")}
|
|
||||||
name={["parts_tax_rates", "PASL", "prt_tx_in4"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tx_in5")}
|
|
||||||
name={["parts_tax_rates", "PASL", "prt_tx_in5"]}
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.CCDR")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.CCDR")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "CCDR", "prt_discp"]}
|
name={["parts_tax_rates", "CCDR", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -1032,7 +592,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "CCDR", "prt_mkupp"]}
|
name={["parts_tax_rates", "CCDR", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -1045,7 +605,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
||||||
name={["parts_tax_rates", "CCDR", "prt_tax_rt"]}
|
name={["parts_tax_rates", "CCDR", "prt_tax_rt"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.CCF")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.CCF")}>
|
||||||
@@ -1053,7 +613,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "CCF", "prt_discp"]}
|
name={["parts_tax_rates", "CCF", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -1066,7 +626,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "CCF", "prt_mkupp"]}
|
name={["parts_tax_rates", "CCF", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -1079,7 +639,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
||||||
name={["parts_tax_rates", "CCF", "prt_tax_rt"]}
|
name={["parts_tax_rates", "CCF", "prt_tax_rt"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.CCM")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.CCM")}>
|
||||||
@@ -1087,7 +647,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "CCM", "prt_discp"]}
|
name={["parts_tax_rates", "CCM", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -1100,7 +660,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "CCM", "prt_mkupp"]}
|
name={["parts_tax_rates", "CCM", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -1113,7 +673,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
||||||
name={["parts_tax_rates", "CCM", "prt_tax_rt"]}
|
name={["parts_tax_rates", "CCM", "prt_tax_rt"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.CCC")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.CCC")}>
|
||||||
@@ -1121,7 +681,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "CCC", "prt_discp"]}
|
name={["parts_tax_rates", "CCC", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -1134,7 +694,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "CCC", "prt_mkupp"]}
|
name={["parts_tax_rates", "CCC", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -1147,7 +707,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
||||||
name={["parts_tax_rates", "CCC", "prt_tax_rt"]}
|
name={["parts_tax_rates", "CCC", "prt_tax_rt"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("joblines.fields.part_types.CCD")}>
|
<LayoutFormRow header={t("joblines.fields.part_types.CCD")}>
|
||||||
@@ -1155,7 +715,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
label={t("jobs.fields.parts_tax_rates.prt_discp")}
|
||||||
name={["parts_tax_rates", "CCD", "prt_discp"]}
|
name={["parts_tax_rates", "CCD", "prt_discp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mktyp")}
|
||||||
@@ -1168,7 +728,7 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
label={t("jobs.fields.parts_tax_rates.prt_mkupp")}
|
||||||
name={["parts_tax_rates", "CCD", "prt_mkupp"]}
|
name={["parts_tax_rates", "CCD", "prt_mkupp"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_in")}
|
||||||
@@ -1181,39 +741,39 @@ export function JobsDetailRatesParts({
|
|||||||
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
label={t("jobs.fields.parts_tax_rates.prt_tax_rt")}
|
||||||
name={["parts_tax_rates", "CCD", "prt_tax_rt"]}
|
name={["parts_tax_rates", "CCD", "prt_tax_rt"]}
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow>
|
<LayoutFormRow>
|
||||||
<Form.Item label={t("jobs.fields.tax_tow_rt")} name="tax_tow_rt">
|
<Form.Item label={t("jobs.fields.tax_tow_rt")} name="tax_tow_rt">
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.tax_str_rt")} name="tax_str_rt">
|
<Form.Item label={t("jobs.fields.tax_str_rt")} name="tax_str_rt">
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.tax_paint_mat_rt")}
|
label={t("jobs.fields.tax_paint_mat_rt")}
|
||||||
name="tax_paint_mat_rt"
|
name="tax_paint_mat_rt"
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.tax_shop_mat_rt")}
|
label={t("jobs.fields.tax_shop_mat_rt")}
|
||||||
name="tax_shop_mat_rt"
|
name="tax_shop_mat_rt"
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.tax_sub_rt")} name="tax_sub_rt">
|
<Form.Item label={t("jobs.fields.tax_sub_rt")} name="tax_sub_rt">
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.tax_lbr_rt")} name="tax_lbr_rt">
|
<Form.Item label={t("jobs.fields.tax_lbr_rt")} name="tax_lbr_rt">
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("jobs.fields.tax_levies_rt")}
|
label={t("jobs.fields.tax_levies_rt")}
|
||||||
name="tax_levies_rt"
|
name="tax_levies_rt"
|
||||||
>
|
>
|
||||||
<InputNumber min={0} max={100} precision={4} disabled={jobRO} />
|
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
import { Button, Popconfirm } from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(JobsDetailRatesProfileOVerride);
|
|
||||||
|
|
||||||
export function JobsDetailRatesProfileOVerride({ bodyshop, form }) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
return (
|
|
||||||
<Popconfirm
|
|
||||||
onConfirm={() => {
|
|
||||||
form.setFieldsValue({
|
|
||||||
cieca_pft: {
|
|
||||||
...bodyshop.md_responsibility_centers.taxes.tax_ty1,
|
|
||||||
...bodyshop.md_responsibility_centers.taxes.tax_ty2,
|
|
||||||
...bodyshop.md_responsibility_centers.taxes.tax_ty3,
|
|
||||||
...bodyshop.md_responsibility_centers.taxes.tax_ty4,
|
|
||||||
...bodyshop.md_responsibility_centers.taxes.tax_ty5,
|
|
||||||
},
|
|
||||||
materials: bodyshop.md_responsibility_centers.cieca_pfm,
|
|
||||||
cieca_pfl: bodyshop.md_responsibility_centers.cieca_pfl,
|
|
||||||
parts_tax_rates: bodyshop.md_responsibility_centers.parts_tax_rates,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
title={t("jobs.actions.taxprofileoverride_confirm")}
|
|
||||||
>
|
|
||||||
<Button type="link">{t("jobs.actions.taxprofileoverride")}</Button>
|
|
||||||
</Popconfirm>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
import { Collapse, Divider, Form, Input, InputNumber, Space } from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function JobsDetailRatesTaxes({
|
|
||||||
jobRO,
|
|
||||||
expanded,
|
|
||||||
bodyshop,
|
|
||||||
required = true,
|
|
||||||
form,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const formItems = [];
|
|
||||||
for (let tyCounter = 1; tyCounter <= 5; tyCounter++) {
|
|
||||||
const section = [];
|
|
||||||
|
|
||||||
section.push(
|
|
||||||
TaxFormItems({
|
|
||||||
typeNum: tyCounter,
|
|
||||||
rootElements: true,
|
|
||||||
bodyshop,
|
|
||||||
jobRO,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let iterator = 1; iterator <= 5; iterator++) {
|
|
||||||
section.push(
|
|
||||||
TaxFormItems({
|
|
||||||
typeNum: tyCounter,
|
|
||||||
typeNumIterator: iterator,
|
|
||||||
rootElements: false,
|
|
||||||
jobRO,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
formItems.push(Space({ children: section, wrap: true }));
|
|
||||||
formItems.push(<Divider />);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Collapse defaultActiveKey={expanded && "rates"}>
|
|
||||||
<Collapse.Panel
|
|
||||||
forceRender
|
|
||||||
header={t("jobs.labels.cieca_pft")}
|
|
||||||
key="cieca_pft"
|
|
||||||
>
|
|
||||||
{formItems}
|
|
||||||
</Collapse.Panel>
|
|
||||||
</Collapse>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(mapStateToProps, null)(JobsDetailRatesTaxes);
|
|
||||||
|
|
||||||
function TaxFormItems({
|
|
||||||
typeNum,
|
|
||||||
typeNumIterator,
|
|
||||||
rootElements,
|
|
||||||
bodyshopjobRO,
|
|
||||||
jobRO,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
if (rootElements)
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.responsibilitycenter_tax_type", {
|
|
||||||
typeNum,
|
|
||||||
typeNumIterator,
|
|
||||||
})}
|
|
||||||
// rules={[
|
|
||||||
// {
|
|
||||||
// required: true,
|
|
||||||
// //message: t("general.validation.required"),
|
|
||||||
// },
|
|
||||||
// ]}
|
|
||||||
name={["cieca_pft", `tax_type${typeNum}`]}
|
|
||||||
>
|
|
||||||
<Input disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.responsibilitycenter_tax_tier", {
|
|
||||||
typeNum,
|
|
||||||
typeNumIterator,
|
|
||||||
})}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["cieca_pft", `ty${typeNum}_tier${typeNumIterator}`]}
|
|
||||||
>
|
|
||||||
<InputNumber precision={0} min={0} disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.responsibilitycenter_tax_thres", {
|
|
||||||
typeNum,
|
|
||||||
typeNumIterator,
|
|
||||||
})}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["cieca_pft", `ty${typeNum}_thres${typeNumIterator}`]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} precision={2} disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.responsibilitycenter_tax_rate", {
|
|
||||||
typeNum,
|
|
||||||
typeNumIterator,
|
|
||||||
})}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["cieca_pft", `ty${typeNum}_rate${typeNumIterator}`]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} precision={2} disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.responsibilitycenter_tax_sur", {
|
|
||||||
typeNum,
|
|
||||||
typeNumIterator,
|
|
||||||
})}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["cieca_pft", `ty${typeNum}_sur${typeNumIterator}`]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} precision={2} disabled={jobRO} />
|
|
||||||
</Form.Item>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,333 +0,0 @@
|
|||||||
import {
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Col,
|
|
||||||
Row,
|
|
||||||
Space,
|
|
||||||
Table,
|
|
||||||
Typography,
|
|
||||||
notification,
|
|
||||||
} from "antd";
|
|
||||||
import { SyncOutlined } from "@ant-design/icons";
|
|
||||||
import axios from "axios";
|
|
||||||
import _ from "lodash";
|
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
|
||||||
import "./labor-allocations-table.styles.scss";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
technician: selectTechnician,
|
|
||||||
});
|
|
||||||
|
|
||||||
export function PayrollLaborAllocationsTable({
|
|
||||||
jobId,
|
|
||||||
joblines,
|
|
||||||
timetickets,
|
|
||||||
bodyshop,
|
|
||||||
adjustments,
|
|
||||||
technician,
|
|
||||||
refetch,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [totals, setTotals] = useState([]);
|
|
||||||
const [state, setState] = useState({
|
|
||||||
sortedInfo: {
|
|
||||||
columnKey: "cost_center",
|
|
||||||
field: "cost_center",
|
|
||||||
order: "ascend",
|
|
||||||
},
|
|
||||||
filteredInfo: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
async function CalculateTotals() {
|
|
||||||
const { data } = await axios.post("/payroll/calculatelabor", {
|
|
||||||
jobid: jobId,
|
|
||||||
});
|
|
||||||
setTotals(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!!joblines && !!timetickets && !!bodyshop) {
|
|
||||||
CalculateTotals();
|
|
||||||
}
|
|
||||||
if (!jobId) setTotals([]);
|
|
||||||
}, [joblines, timetickets, bodyshop, adjustments, jobId]);
|
|
||||||
|
|
||||||
const convertedLines = useMemo(
|
|
||||||
() => joblines && joblines.filter((j) => j.convertedtolbr),
|
|
||||||
[joblines]
|
|
||||||
);
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: t("timetickets.fields.employee"),
|
|
||||||
dataIndex: "employeeid",
|
|
||||||
key: "employeeid",
|
|
||||||
render: (text, record) => {
|
|
||||||
if (record.employeeid === undefined) {
|
|
||||||
return (
|
|
||||||
<span style={{ color: "tomato", fontWeight: "bolder" }}>
|
|
||||||
{t("timetickets.labels.unassigned")}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const emp = bodyshop.employees.find((e) => e.id === record.employeeid);
|
|
||||||
return `${emp?.first_name} ${emp?.last_name}`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.mod_lbr_ty"),
|
|
||||||
dataIndex: "mod_lbr_ty",
|
|
||||||
key: "mod_lbr_ty",
|
|
||||||
render: (text, record) =>
|
|
||||||
record.employeeid === undefined ? (
|
|
||||||
<span style={{ color: "tomato", fontWeight: "bolder" }}>
|
|
||||||
{t("timetickets.labels.unassigned")}
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
t(`joblines.fields.lbr_types.${record.mod_lbr_ty?.toUpperCase()}`)
|
|
||||||
),
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// title: t("timetickets.fields.rate"),
|
|
||||||
// dataIndex: "rate",
|
|
||||||
// key: "rate",
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
title: t("jobs.labels.hrs_total"),
|
|
||||||
dataIndex: "expectedHours",
|
|
||||||
key: "expectedHours",
|
|
||||||
sorter: (a, b) => a.expectedHours - b.expectedHours,
|
|
||||||
sortOrder:
|
|
||||||
state.sortedInfo.columnKey === "expectedHours" &&
|
|
||||||
state.sortedInfo.order,
|
|
||||||
render: (text, record) => record.expectedHours.toFixed(5),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("jobs.labels.hrs_claimed"),
|
|
||||||
dataIndex: "claimedHours",
|
|
||||||
key: "claimedHours",
|
|
||||||
sorter: (a, b) => a.claimedHours - b.claimedHours,
|
|
||||||
sortOrder:
|
|
||||||
state.sortedInfo.columnKey === "claimedHours" && state.sortedInfo.order,
|
|
||||||
render: (text, record) =>
|
|
||||||
record.claimedHours && record.claimedHours.toFixed(5),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("jobs.labels.difference"),
|
|
||||||
dataIndex: "difference",
|
|
||||||
|
|
||||||
key: "difference",
|
|
||||||
sorter: (a, b) => a.difference - b.difference,
|
|
||||||
sortOrder:
|
|
||||||
state.sortedInfo.columnKey === "difference" && state.sortedInfo.order,
|
|
||||||
render: (text, record) => {
|
|
||||||
const difference = _.round(
|
|
||||||
record.expectedHours - record.claimedHours,
|
|
||||||
5
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<strong
|
|
||||||
style={{
|
|
||||||
color: difference >= 0 ? "green" : "red",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{difference}
|
|
||||||
</strong>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const convertedTableCols = [
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.line_desc"),
|
|
||||||
dataIndex: "line_desc",
|
|
||||||
key: "line_desc",
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.op_code_desc"),
|
|
||||||
dataIndex: "op_code_desc",
|
|
||||||
key: "op_code_desc",
|
|
||||||
ellipsis: true,
|
|
||||||
render: (text, record) =>
|
|
||||||
`${record.op_code_desc || ""}${
|
|
||||||
record.alt_partm ? ` ${record.alt_partm}` : ""
|
|
||||||
}`,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.act_price"),
|
|
||||||
dataIndex: "act_price",
|
|
||||||
key: "act_price",
|
|
||||||
ellipsis: true,
|
|
||||||
render: (text, record) => (
|
|
||||||
<>
|
|
||||||
<CurrencyFormatter>
|
|
||||||
{record.db_ref === "900510" || record.db_ref === "900511"
|
|
||||||
? record.prt_dsmk_m
|
|
||||||
: record.act_price}
|
|
||||||
</CurrencyFormatter>
|
|
||||||
{record.prt_dsmk_p && record.prt_dsmk_p !== 0 ? (
|
|
||||||
<span
|
|
||||||
style={{ marginLeft: ".2rem" }}
|
|
||||||
>{`(${record.prt_dsmk_p}%)`}</span>
|
|
||||||
) : (
|
|
||||||
<></>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.part_qty"),
|
|
||||||
dataIndex: "part_qty",
|
|
||||||
key: "part_qty",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.mod_lbr_ty"),
|
|
||||||
dataIndex: "conv_mod_lbr_ty",
|
|
||||||
key: "conv_mod_lbr_ty",
|
|
||||||
render: (text, record) =>
|
|
||||||
record.convertedtolbr_data && record.convertedtolbr_data.mod_lbr_ty,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.mod_lb_hrs"),
|
|
||||||
dataIndex: "conv_mod_lb_hrs",
|
|
||||||
key: "conv_mod_lb_hrs",
|
|
||||||
render: (text, record) =>
|
|
||||||
record.convertedtolbr_data &&
|
|
||||||
record.convertedtolbr_data.mod_lb_hrs &&
|
|
||||||
record.convertedtolbr_data.mod_lb_hrs.toFixed(5),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleTableChange = (pagination, filters, sorter) => {
|
|
||||||
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
|
||||||
};
|
|
||||||
|
|
||||||
const summary =
|
|
||||||
totals &&
|
|
||||||
totals.reduce(
|
|
||||||
(acc, val) => {
|
|
||||||
acc.hrs_total += val.expectedHours;
|
|
||||||
acc.hrs_claimed += val.claimedHours;
|
|
||||||
// acc.adjustments += val.adjustments;
|
|
||||||
acc.difference += val.expectedHours - val.claimedHours;
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{ hrs_total: 0, hrs_claimed: 0, adjustments: 0, difference: 0 }
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Row gutter={[16, 16]}>
|
|
||||||
<Col span={24}>
|
|
||||||
<Card
|
|
||||||
title={t("jobs.labels.laborallocations")}
|
|
||||||
extra={
|
|
||||||
<Space>
|
|
||||||
<Button
|
|
||||||
onClick={async () => {
|
|
||||||
const response = await axios.post("/payroll/payall", {
|
|
||||||
jobid: jobId,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.status === 200) {
|
|
||||||
if (response.data.success !== false) {
|
|
||||||
notification.open({
|
|
||||||
type: "success",
|
|
||||||
message: t("timetickets.successes.payall"),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("timetickets.errors.payall", {
|
|
||||||
error: response.data.error,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (refetch) refetch();
|
|
||||||
} else {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("timetickets.errors.payall", {
|
|
||||||
error: JSON.stringify(""),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("timetickets.actions.payall")}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={async () => {
|
|
||||||
const { data } = await axios.post("/payroll/calculatelabor", {
|
|
||||||
jobid: jobId,
|
|
||||||
});
|
|
||||||
setTotals(data);
|
|
||||||
refetch();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SyncOutlined />
|
|
||||||
</Button>
|
|
||||||
</Space>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Table
|
|
||||||
columns={columns}
|
|
||||||
rowKey={(record) => `${record.employeeid} ${record.mod_lbr_ty}`}
|
|
||||||
pagination={false}
|
|
||||||
onChange={handleTableChange}
|
|
||||||
dataSource={totals}
|
|
||||||
scroll={{
|
|
||||||
x: true,
|
|
||||||
}}
|
|
||||||
summary={() => (
|
|
||||||
<Table.Summary.Row>
|
|
||||||
<Table.Summary.Cell>
|
|
||||||
<Typography.Title level={4}>
|
|
||||||
{t("general.labels.totals")}
|
|
||||||
</Typography.Title>
|
|
||||||
</Table.Summary.Cell>
|
|
||||||
<Table.Summary.Cell></Table.Summary.Cell>
|
|
||||||
<Table.Summary.Cell>
|
|
||||||
{summary.hrs_total.toFixed(5)}
|
|
||||||
</Table.Summary.Cell>
|
|
||||||
<Table.Summary.Cell>
|
|
||||||
{summary.hrs_claimed.toFixed(5)}
|
|
||||||
</Table.Summary.Cell>
|
|
||||||
|
|
||||||
<Table.Summary.Cell>
|
|
||||||
{summary.difference.toFixed(5)}
|
|
||||||
</Table.Summary.Cell>
|
|
||||||
</Table.Summary.Row>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
{convertedLines && convertedLines.length > 0 && (
|
|
||||||
<Col span={24}>
|
|
||||||
<Card title={t("jobs.labels.convertedtolabor")}>
|
|
||||||
<Table
|
|
||||||
columns={convertedTableCols}
|
|
||||||
rowKey="id"
|
|
||||||
pagination={false}
|
|
||||||
dataSource={convertedLines}
|
|
||||||
scroll={{
|
|
||||||
x: true,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</Col>
|
|
||||||
)}
|
|
||||||
</Row>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(mapStateToProps, null)(PayrollLaborAllocationsTable);
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { Button, Card, Col, Row, Table, notification } from "antd";
|
|
||||||
import moment from "moment-business-days";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { UPDATE_PARTS_DISPATCH_LINE } from "../../graphql/parts-dispatch.queries";
|
|
||||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
|
||||||
|
|
||||||
export default function PartsDispatchExpander({ dispatch, job }) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [updateDispatchLine] = useMutation(UPDATE_PARTS_DISPATCH_LINE);
|
|
||||||
|
|
||||||
const handleAccept = async ({ partsDispatchLineId }) => {
|
|
||||||
const accepted_at = moment();
|
|
||||||
const result = await updateDispatchLine({
|
|
||||||
variables: { id: partsDispatchLineId, line: { accepted_at } },
|
|
||||||
optimisticResponse: {
|
|
||||||
update_parts_dispatch_lines_by_pk: {
|
|
||||||
accepted_at,
|
|
||||||
id: partsDispatchLineId,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (result.errors) {
|
|
||||||
notification.open({
|
|
||||||
type: "error",
|
|
||||||
message: t("parts_dispatch.errors.accepting", {
|
|
||||||
error: JSON.stringify(result.errors),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.part_qty"),
|
|
||||||
dataIndex: "quantity",
|
|
||||||
key: "quantity",
|
|
||||||
width: "10%",
|
|
||||||
//sorter: (a, b) => alphaSort(a.number, b.number),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("joblines.fields.line_desc"),
|
|
||||||
dataIndex: "joblineid",
|
|
||||||
key: "joblineid",
|
|
||||||
//sorter: (a, b) => alphaSort(a.number, b.number),
|
|
||||||
render: (text, record) => record.jobline.line_desc,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("parts_dispatch_lines.fields.accepted_at"),
|
|
||||||
dataIndex: "accepted_at",
|
|
||||||
key: "accepted_at",
|
|
||||||
width: "20%",
|
|
||||||
|
|
||||||
//sorter: (a, b) => alphaSort(a.number, b.number),
|
|
||||||
render: (text, record) =>
|
|
||||||
record.accepted_at ? (
|
|
||||||
<DateTimeFormatter>{record.accepted_at}</DateTimeFormatter>
|
|
||||||
) : (
|
|
||||||
<Button
|
|
||||||
onClick={() => handleAccept({ partsDispatchLineId: record.id })}
|
|
||||||
>
|
|
||||||
{t("parts_dispatch.actions.accept")}
|
|
||||||
</Button>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
<Row gutter={[16, 16]}>
|
|
||||||
<Col span={24}>
|
|
||||||
<Table
|
|
||||||
rowKey={"id"}
|
|
||||||
dataSource={dispatch.parts_dispatch_lines}
|
|
||||||
columns={columns}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
import {
|
|
||||||
MinusCircleTwoTone,
|
|
||||||
PlusCircleTwoTone,
|
|
||||||
SyncOutlined,
|
|
||||||
} from "@ant-design/icons";
|
|
||||||
import { Button, Card, Input, Space, Table } from "antd";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
|
||||||
import { alphaSort } from "../../utils/sorters";
|
|
||||||
import PartsDispatchExpander from "../parts-dispatch-expander/parts-dispatch-expander.component";
|
|
||||||
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
jobRO: selectJobReadOnly,
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({});
|
|
||||||
|
|
||||||
export function PartDispatchTableComponent({
|
|
||||||
bodyshop,
|
|
||||||
jobRO,
|
|
||||||
job,
|
|
||||||
billsQuery,
|
|
||||||
handleOnRowClick,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const [state, setState] = useState({
|
|
||||||
sortedInfo: {},
|
|
||||||
});
|
|
||||||
// const search = queryString.parse(useLocation().search);
|
|
||||||
// const selectedBill = search.billid;
|
|
||||||
const [searchText, setSearchText] = useState("");
|
|
||||||
|
|
||||||
const Templates = TemplateList("job_special");
|
|
||||||
|
|
||||||
const { refetch } = billsQuery;
|
|
||||||
|
|
||||||
const recordActions = (record) => (
|
|
||||||
<Space wrap>
|
|
||||||
<PrintWrapperComponent
|
|
||||||
templateObject={{
|
|
||||||
name: Templates.parts_dispatch.key,
|
|
||||||
variables: { id: record.id },
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
);
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: t("parts_dispatch.fields.number"),
|
|
||||||
dataIndex: "number",
|
|
||||||
key: "number",
|
|
||||||
sorter: (a, b) => alphaSort(a.number, b.number),
|
|
||||||
width: "10%",
|
|
||||||
sortOrder:
|
|
||||||
state.sortedInfo.columnKey === "number" && state.sortedInfo.order,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("timetickets.fields.employee"),
|
|
||||||
dataIndex: "employeeid",
|
|
||||||
key: "employeeid",
|
|
||||||
sorter: (a, b) => alphaSort(a.employeeid, b.employeeid),
|
|
||||||
sortOrder:
|
|
||||||
state.sortedInfo.columnKey === "employeeid" && state.sortedInfo.order,
|
|
||||||
render: (text, record) => {
|
|
||||||
const e = bodyshop.employees.find((e) => e.id === record.employeeid);
|
|
||||||
return `${e?.first_name || ""} ${e?.last_name || ""}`.trim();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("parts_dispatch.fields.percent_accepted"),
|
|
||||||
dataIndex: "percent_accepted",
|
|
||||||
key: "percent_accepted",
|
|
||||||
|
|
||||||
render: (text, record) =>
|
|
||||||
record.parts_dispatch_lines.length > 0
|
|
||||||
? `
|
|
||||||
${(
|
|
||||||
(record.parts_dispatch_lines.filter((l) => l.accepted_at)
|
|
||||||
.length /
|
|
||||||
record.parts_dispatch_lines.length) *
|
|
||||||
100
|
|
||||||
).toFixed(0)}%`
|
|
||||||
: "0%",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("general.labels.actions"),
|
|
||||||
dataIndex: "actions",
|
|
||||||
key: "actions",
|
|
||||||
width: "10%",
|
|
||||||
render: (text, record) => recordActions(record, true),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const handleTableChange = (pagination, filters, sorter) => {
|
|
||||||
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
title={t("parts_dispatch.labels.parts_dispatch")}
|
|
||||||
extra={
|
|
||||||
<Space wrap>
|
|
||||||
<Button onClick={() => refetch()}>
|
|
||||||
<SyncOutlined />
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Input.Search
|
|
||||||
placeholder={t("general.labels.search")}
|
|
||||||
value={searchText}
|
|
||||||
onChange={(e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
setSearchText(e.target.value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Table
|
|
||||||
loading={billsQuery.loading}
|
|
||||||
scroll={{
|
|
||||||
x: true, // y: "50rem"
|
|
||||||
}}
|
|
||||||
expandable={{
|
|
||||||
expandedRowRender: (record) => (
|
|
||||||
<PartsDispatchExpander dispatch={record} job={job} />
|
|
||||||
),
|
|
||||||
rowExpandable: (record) => true,
|
|
||||||
|
|
||||||
expandIcon: ({ expanded, onExpand, record }) =>
|
|
||||||
expanded ? (
|
|
||||||
<MinusCircleTwoTone onClick={(e) => onExpand(record, e)} />
|
|
||||||
) : (
|
|
||||||
<PlusCircleTwoTone onClick={(e) => onExpand(record, e)} />
|
|
||||||
),
|
|
||||||
}}
|
|
||||||
columns={columns}
|
|
||||||
rowKey="id"
|
|
||||||
dataSource={billsQuery.data ? billsQuery.data.parts_dispatch : []}
|
|
||||||
onChange={handleTableChange}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(PartDispatchTableComponent);
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
import { Card, Col, Input, Row, Space, Typography } from "antd";
|
import { Card, Col, Input, Row, Space, Typography } from "antd";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
@@ -24,13 +23,8 @@ export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
|
|||||||
const { id: jobId, job } = printCenterModal.context;
|
const { id: jobId, job } = printCenterModal.context;
|
||||||
const tempList = TemplateList("job", {});
|
const tempList = TemplateList("job", {});
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
|
|
||||||
const Templates =
|
const JobsReportsList =
|
||||||
bodyshop.cdk_dealerid === null && bodyshop.pbs_serialnumber === null
|
bodyshop.cdk_dealerid === null && bodyshop.pbs_serialnumber === null
|
||||||
? Object.keys(tempList)
|
? Object.keys(tempList)
|
||||||
.map((key) => {
|
.map((key) => {
|
||||||
@@ -57,26 +51,7 @@ export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
|
|||||||
bodyshop.region_config.includes(Object.keys(temp.regions)) ===
|
bodyshop.region_config.includes(Object.keys(temp.regions)) ===
|
||||||
true)
|
true)
|
||||||
);
|
);
|
||||||
const JobsReportsList =
|
|
||||||
Enhanced_Payroll.treatment === "on"
|
|
||||||
? Object.keys(Templates)
|
|
||||||
.map((key) => {
|
|
||||||
return Templates[key];
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(temp) =>
|
|
||||||
temp.enhanced_payroll === undefined ||
|
|
||||||
temp.enhanced_payroll === true
|
|
||||||
)
|
|
||||||
: Object.keys(Templates)
|
|
||||||
.map((key) => {
|
|
||||||
return Templates[key];
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(temp) =>
|
|
||||||
temp.enhanced_payroll === undefined ||
|
|
||||||
temp.enhanced_payroll === false
|
|
||||||
);
|
|
||||||
const filteredJobsReportsList =
|
const filteredJobsReportsList =
|
||||||
search !== ""
|
search !== ""
|
||||||
? JobsReportsList.filter((r) =>
|
? JobsReportsList.filter((r) =>
|
||||||
|
|||||||
@@ -9,11 +9,9 @@ export default function PrintWrapperComponent({
|
|||||||
children,
|
children,
|
||||||
id,
|
id,
|
||||||
emailOnly = false,
|
emailOnly = false,
|
||||||
disabled,
|
|
||||||
}) {
|
}) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const handlePrint = async (type) => {
|
const handlePrint = async (type) => {
|
||||||
if (disabled) return;
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
await GenerateDocument(templateObject, messageObject, type, id);
|
await GenerateDocument(templateObject, messageObject, type, id);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@@ -22,18 +20,8 @@ export default function PrintWrapperComponent({
|
|||||||
return (
|
return (
|
||||||
<Space>
|
<Space>
|
||||||
{children || null}
|
{children || null}
|
||||||
{!emailOnly && (
|
{!emailOnly && <PrinterFilled onClick={() => handlePrint("p")} />}
|
||||||
<PrinterFilled
|
<MailFilled onClick={() => handlePrint("e")} />
|
||||||
disabled={disabled}
|
|
||||||
onClick={() => handlePrint("p")}
|
|
||||||
style={{ cursor: disabled ? "not-allowed" : null }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<MailFilled
|
|
||||||
disabled={disabled}
|
|
||||||
onClick={() => handlePrint("e")}
|
|
||||||
style={{ cursor: disabled ? "not-allowed" : null }}
|
|
||||||
/>
|
|
||||||
{loading && <Spin />}
|
{loading && <Spin />}
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,12 +1,23 @@
|
|||||||
import { ExclamationCircleFilled } from "@ant-design/icons";
|
import { ExclamationCircleFilled } from "@ant-design/icons";
|
||||||
|
import { useMutation } from "@apollo/client";
|
||||||
import { Dropdown, Menu } from "antd";
|
import { Dropdown, Menu } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useMutation } from "@apollo/client";
|
import { connect } from "react-redux";
|
||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
|
||||||
export default function ProductionListColumnAlert({ record }) {
|
const mapStateToProps = createStructuredSelector({});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
|
});
|
||||||
|
|
||||||
|
export function ProductionListColumnAlert({ record, insertAuditTrail }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const [updateAlert] = useMutation(UPDATE_JOB);
|
const [updateAlert] = useMutation(UPDATE_JOB);
|
||||||
@@ -27,6 +38,14 @@ export default function ProductionListColumnAlert({ record }) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: record.id,
|
||||||
|
operation: AuditTrailMapping.alertToggle(
|
||||||
|
!!record.production_vars && !!record.production_vars.alert
|
||||||
|
? !record.production_vars.alert
|
||||||
|
: true
|
||||||
|
),
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
if (record.refetch) record.refetch();
|
if (record.refetch) record.refetch();
|
||||||
});
|
});
|
||||||
@@ -58,3 +77,8 @@ export default function ProductionListColumnAlert({ record }) {
|
|||||||
</Dropdown>
|
</Dropdown>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(ProductionListColumnAlert);
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ import ProductionListColumnNote from "./production-list-columns.productionnote.c
|
|||||||
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
||||||
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
||||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||||
import { store } from "../../redux/store";
|
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
|
||||||
|
|
||||||
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
||||||
return [
|
return [
|
||||||
@@ -40,29 +38,6 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: i18n.t("timetickets.actions.claimtasks"),
|
|
||||||
dataIndex: "claimtasks",
|
|
||||||
key: "claimtasks",
|
|
||||||
ellipsis: true,
|
|
||||||
render: (text, record) => (
|
|
||||||
<div
|
|
||||||
onClick={() => {
|
|
||||||
store.dispatch(
|
|
||||||
setModalContext({
|
|
||||||
context: {
|
|
||||||
actions: {},
|
|
||||||
context: { jobid: record.id },
|
|
||||||
},
|
|
||||||
modal: "timeTicketTask",
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{i18n.t("timetickets.actions.claimtasks")}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: i18n.t("jobs.fields.ro_number"),
|
title: i18n.t("jobs.fields.ro_number"),
|
||||||
dataIndex: "ro_number",
|
dataIndex: "ro_number",
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ export function ProductionListDetail({
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
placement="right"
|
placement="right"
|
||||||
width={"50%"}
|
width={"33%"}
|
||||||
onClose={handleClose}
|
onClose={handleClose}
|
||||||
visible={selected}
|
visible={selected}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -55,10 +55,11 @@ const ret = {
|
|||||||
"shiftclock:view": 2,
|
"shiftclock:view": 2,
|
||||||
|
|
||||||
"shop:config": 4,
|
"shop:config": 4,
|
||||||
"shop:rbac": 5,
|
|
||||||
"shop:vendors": 2,
|
|
||||||
"shop:dashboard": 3,
|
"shop:dashboard": 3,
|
||||||
|
"shop:rbac": 5,
|
||||||
|
"shop:reportcenter": 2,
|
||||||
"shop:templates": 4,
|
"shop:templates": 4,
|
||||||
|
"shop:vendors": 2,
|
||||||
|
|
||||||
"temporarydocs:view": 2,
|
"temporarydocs:view": 2,
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useLazyQuery } from "@apollo/client";
|
import { useLazyQuery } from "@apollo/client";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@@ -20,7 +19,6 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { QUERY_ACTIVE_EMPLOYEES } from "../../graphql/employees.queries";
|
import { QUERY_ACTIVE_EMPLOYEES } from "../../graphql/employees.queries";
|
||||||
import { QUERY_ALL_VENDORS } from "../../graphql/vendors.queries";
|
import { QUERY_ALL_VENDORS } from "../../graphql/vendors.queries";
|
||||||
import { selectReportCenter } from "../../redux/modals/modals.selectors";
|
import { selectReportCenter } from "../../redux/modals/modals.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import DatePIckerRanges from "../../utils/DatePickerRanges";
|
import DatePIckerRanges from "../../utils/DatePickerRanges";
|
||||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
@@ -29,7 +27,6 @@ import VendorSearchSelect from "../vendor-search-select/vendor-search-select.com
|
|||||||
import "./report-center-modal.styles.scss";
|
import "./report-center-modal.styles.scss";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
reportCenterModal: selectReportCenter,
|
reportCenterModal: selectReportCenter,
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
@@ -39,38 +36,16 @@ export default connect(
|
|||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(ReportCenterModalComponent);
|
)(ReportCenterModalComponent);
|
||||||
|
|
||||||
export function ReportCenterModalComponent({ reportCenterModal, bodyshop }) {
|
export function ReportCenterModalComponent({ reportCenterModal }) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
|
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const Templates = TemplateList("report_center");
|
const Templates = TemplateList("report_center");
|
||||||
const ReportsList =
|
const ReportsList = Object.keys(Templates).map((key) => {
|
||||||
Enhanced_Payroll.treatment === "on"
|
return Templates[key];
|
||||||
? Object.keys(Templates)
|
});
|
||||||
.map((key) => {
|
|
||||||
return Templates[key];
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(temp) =>
|
|
||||||
temp.enhanced_payroll === undefined ||
|
|
||||||
temp.enhanced_payroll === true
|
|
||||||
)
|
|
||||||
: Object.keys(Templates)
|
|
||||||
.map((key) => {
|
|
||||||
return Templates[key];
|
|
||||||
})
|
|
||||||
.filter(
|
|
||||||
(temp) =>
|
|
||||||
temp.enhanced_payroll === undefined ||
|
|
||||||
temp.enhanced_payroll === false
|
|
||||||
);
|
|
||||||
const { visible } = reportCenterModal;
|
const { visible } = reportCenterModal;
|
||||||
|
|
||||||
const [callVendorQuery, { data: vendorData, called: vendorCalled }] =
|
const [callVendorQuery, { data: vendorData, called: vendorCalled }] =
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { connect } from "react-redux";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
||||||
import { selectReportCenter } from "../../redux/modals/modals.selectors";
|
import { selectReportCenter } from "../../redux/modals/modals.selectors";
|
||||||
|
import RbacWrapperComponent from "../rbac-wrapper/rbac-wrapper.component";
|
||||||
import ReportCenterModalComponent from "./report-center-modal.component";
|
import ReportCenterModalComponent from "./report-center-modal.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
@@ -33,7 +34,9 @@ export function ReportCenterModalContainer({
|
|||||||
destroyOnClose
|
destroyOnClose
|
||||||
width="80%"
|
width="80%"
|
||||||
>
|
>
|
||||||
<ReportCenterModalComponent />
|
<RbacWrapperComponent action="shop:reportcenter">
|
||||||
|
<ReportCenterModalComponent />
|
||||||
|
</RbacWrapperComponent>
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default connect(
|
|||||||
|
|
||||||
export function ScoreboardTimeTicketsStats({ bodyshop }) {
|
export function ScoreboardTimeTicketsStats({ bodyshop }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const startDate = moment().startOf("month")
|
const startDate = moment().startOf("month");
|
||||||
const endDate = moment().endOf("month");
|
const endDate = moment().endOf("month");
|
||||||
|
|
||||||
const fixedPeriods = useMemo(() => {
|
const fixedPeriods = useMemo(() => {
|
||||||
@@ -84,6 +84,8 @@ export function ScoreboardTimeTicketsStats({ bodyshop }) {
|
|||||||
end: endDate.format("YYYY-MM-DD"),
|
end: endDate.format("YYYY-MM-DD"),
|
||||||
fixedStart: fixedPeriods.start.format("YYYY-MM-DD"),
|
fixedStart: fixedPeriods.start.format("YYYY-MM-DD"),
|
||||||
fixedEnd: fixedPeriods.end.format("YYYY-MM-DD"),
|
fixedEnd: fixedPeriods.end.format("YYYY-MM-DD"),
|
||||||
|
jobStart: startDate,
|
||||||
|
jobEnd: endDate,
|
||||||
},
|
},
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
nextFetchPolicy: "network-only",
|
nextFetchPolicy: "network-only",
|
||||||
@@ -340,11 +342,21 @@ export function ScoreboardTimeTicketsStats({ bodyshop }) {
|
|||||||
larData.push({ ...r, ...lar });
|
larData.push({ ...r, ...lar });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const jobData = {};
|
||||||
|
data.jobs.forEach((job) => {
|
||||||
|
job.tthrs = job.joblines.reduce((acc, val) => acc + val.mod_lb_hrs, 0);
|
||||||
|
});
|
||||||
|
jobData.tthrs = data.jobs
|
||||||
|
.reduce((acc, val) => acc + val.tthrs, 0)
|
||||||
|
.toFixed(1);
|
||||||
|
jobData.count = data.jobs.length.toFixed(0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fixed: ret,
|
fixed: ret,
|
||||||
combinedData: combinedData,
|
combinedData: combinedData,
|
||||||
labData: labData,
|
labData: labData,
|
||||||
larData: larData,
|
larData: larData,
|
||||||
|
jobData: jobData,
|
||||||
};
|
};
|
||||||
}, [fixedPeriods, data, bodyshop]);
|
}, [fixedPeriods, data, bodyshop]);
|
||||||
|
|
||||||
@@ -356,7 +368,10 @@ export function ScoreboardTimeTicketsStats({ bodyshop }) {
|
|||||||
<ScoreboardTimeticketsTargetsTable />
|
<ScoreboardTimeticketsTargetsTable />
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<ScoreboardTicketsStats data={calculatedData.fixed} />
|
<ScoreboardTicketsStats
|
||||||
|
data={calculatedData.fixed}
|
||||||
|
jobData={calculatedData.jobData}
|
||||||
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<ScoreboardTimeTicketsChart
|
<ScoreboardTimeTicketsChart
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ function useLocalStorage(key, initialValue) {
|
|||||||
return [storedValue, setStoredValue];
|
return [storedValue, setStoredValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ScoreboardTicketsStats({ data, bodyshop }) {
|
export function ScoreboardTicketsStats({ data, jobData, bodyshop }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [isLarge, setIsLarge] = useLocalStorage("isLargeStatistic", false);
|
const [isLarge, setIsLarge] = useLocalStorage("isLargeStatistic", false);
|
||||||
|
|
||||||
@@ -408,7 +408,7 @@ export function ScoreboardTicketsStats({ data, bodyshop }) {
|
|||||||
{/* Monthly Stats */}
|
{/* Monthly Stats */}
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
{/* This Month */}
|
{/* This Month */}
|
||||||
<Col span={8} align="center">
|
<Col span={7} align="center">
|
||||||
<Card size="small" title={t("scoreboard.labels.thismonth")}>
|
<Card size="small" title={t("scoreboard.labels.thismonth")}>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
@@ -482,7 +482,7 @@ export function ScoreboardTicketsStats({ data, bodyshop }) {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
{/* Last Month */}
|
{/* Last Month */}
|
||||||
<Col span={8} align="center">
|
<Col span={7} align="center">
|
||||||
<Card size="small" title={t("scoreboard.labels.lastmonth")}>
|
<Card size="small" title={t("scoreboard.labels.lastmonth")}>
|
||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
@@ -556,7 +556,7 @@ export function ScoreboardTicketsStats({ data, bodyshop }) {
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
{/* Efficiency Over Period */}
|
{/* Efficiency Over Period */}
|
||||||
<Col span={8} align="center">
|
<Col span={7} align="center">
|
||||||
<Card
|
<Card
|
||||||
size="small"
|
size="small"
|
||||||
title={t("scoreboard.labels.efficiencyoverperiod")}
|
title={t("scoreboard.labels.efficiencyoverperiod")}
|
||||||
@@ -604,6 +604,40 @@ export function ScoreboardTicketsStats({ data, bodyshop }) {
|
|||||||
</Row>
|
</Row>
|
||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col span={3} align="center">
|
||||||
|
<Card
|
||||||
|
size="small"
|
||||||
|
title={t("scoreboard.labels.jobscompletednotinvoiced")}
|
||||||
|
>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
|
<Statistic
|
||||||
|
value={jobData.count}
|
||||||
|
valueStyle={{
|
||||||
|
fontSize: statisticSize,
|
||||||
|
fontWeight: statisticWeight,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col span={24}>
|
||||||
|
<Statistic
|
||||||
|
title={
|
||||||
|
<Typography.Text strong>
|
||||||
|
{t("scoreboard.labels.totalhrs")}
|
||||||
|
</Typography.Text>
|
||||||
|
}
|
||||||
|
value={jobData.tthrs}
|
||||||
|
valueStyle={{
|
||||||
|
fontSize: statisticSize,
|
||||||
|
fontWeight: statisticWeight,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Space>
|
</Space>
|
||||||
{/* Disclaimer */}
|
{/* Disclaimer */}
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ export default function ScoreboardTimeTickets() {
|
|||||||
end: endDate.format("YYYY-MM-DD"),
|
end: endDate.format("YYYY-MM-DD"),
|
||||||
fixedStart: fixedPeriods.start.format("YYYY-MM-DD"),
|
fixedStart: fixedPeriods.start.format("YYYY-MM-DD"),
|
||||||
fixedEnd: fixedPeriods.end.format("YYYY-MM-DD"),
|
fixedEnd: fixedPeriods.end.format("YYYY-MM-DD"),
|
||||||
|
jobStart: startDate,
|
||||||
|
jobEnd: endDate,
|
||||||
},
|
},
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
nextFetchPolicy: "network-only",
|
nextFetchPolicy: "network-only",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
Table,
|
Table,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
|
import { useForm } from "antd/es/form/Form";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import querystring from "query-string";
|
import querystring from "query-string";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
@@ -36,7 +36,6 @@ import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
|||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
import ShopEmployeeAddVacation from "./shop-employees-add-vacation.component";
|
import ShopEmployeeAddVacation from "./shop-employees-add-vacation.component";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -47,7 +46,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
|
|
||||||
export function ShopEmployeesFormComponent({ bodyshop }) {
|
export function ShopEmployeesFormComponent({ bodyshop }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [form] = Form.useForm();
|
const [form] = useForm();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const search = querystring.parse(useLocation().search);
|
const search = querystring.parse(useLocation().search);
|
||||||
const [deleteVacation] = useMutation(DELETE_VACATION);
|
const [deleteVacation] = useMutation(DELETE_VACATION);
|
||||||
@@ -57,11 +56,7 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
|
|||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
nextFetchPolicy: "network-only",
|
nextFetchPolicy: "network-only",
|
||||||
});
|
});
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data && data.employees_by_pk) form.setFieldsValue(data.employees_by_pk);
|
if (data && data.employees_by_pk) form.setFieldsValue(data.employees_by_pk);
|
||||||
@@ -367,7 +362,7 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
|
|||||||
{t("timetickets.labels.shift")}
|
{t("timetickets.labels.shift")}
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
|
|
||||||
{bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === "on"
|
{bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
|
||||||
? CiecaSelect(false, true)
|
? CiecaSelect(false, true)
|
||||||
: bodyshop.md_responsibility_centers.costs.map(
|
: bodyshop.md_responsibility_centers.costs.map(
|
||||||
(c) => (
|
(c) => (
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import ShopInfoResponsibilityCenterComponent from "./shop-info.responsibilitycen
|
|||||||
import ShopInfoROStatusComponent from "./shop-info.rostatus.component";
|
import ShopInfoROStatusComponent from "./shop-info.rostatus.component";
|
||||||
import ShopInfoSchedulingComponent from "./shop-info.scheduling.component";
|
import ShopInfoSchedulingComponent from "./shop-info.scheduling.component";
|
||||||
import ShopInfoSpeedPrint from "./shop-info.speedprint.component";
|
import ShopInfoSpeedPrint from "./shop-info.speedprint.component";
|
||||||
import ShopInfoTaskPresets from "./shop-info.task-presets.component";
|
|
||||||
import { useHistory, useLocation } from "react-router-dom";
|
import { useHistory, useLocation } from "react-router-dom";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
|
||||||
@@ -97,12 +96,6 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) {
|
|||||||
<ShopInfoPartsScan form={form} />
|
<ShopInfoPartsScan form={form} />
|
||||||
</Tabs.TabPane>
|
</Tabs.TabPane>
|
||||||
)}
|
)}
|
||||||
<Tabs.TabPane
|
|
||||||
key="task-presets"
|
|
||||||
tab={t("bodyshop.labels.task-presets")}
|
|
||||||
>
|
|
||||||
<ShopInfoTaskPresets form={form} />
|
|
||||||
</Tabs.TabPane>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -189,22 +189,20 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
|||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
{
|
<Form.Item shouldUpdate noStyle>
|
||||||
// <Form.Item shouldUpdate noStyle>
|
{() => (
|
||||||
// {() => (
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.labels.qbo_usa")}
|
||||||
// label={t("bodyshop.labels.qbo_usa")}
|
shouldUpdate
|
||||||
// shouldUpdate
|
valuePropName="checked"
|
||||||
// valuePropName="checked"
|
name={["accountingconfig", "qbo_usa"]}
|
||||||
// name={["accountingconfig", "qbo_usa"]}
|
>
|
||||||
// >
|
<Switch
|
||||||
// <Switch
|
disabled={!form.getFieldValue(["accountingconfig", "qbo"])}
|
||||||
// disabled={!form.getFieldValue(["accountingconfig", "qbo"])}
|
/>
|
||||||
// />
|
</Form.Item>
|
||||||
// </Form.Item>
|
)}
|
||||||
// )}
|
</Form.Item>
|
||||||
// </Form.Item>
|
|
||||||
}
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.labels.qbo_departmentid")}
|
label={t("bodyshop.labels.qbo_departmentid")}
|
||||||
name={["accountingconfig", "qbo_departmentid"]}
|
name={["accountingconfig", "qbo_departmentid"]}
|
||||||
@@ -293,34 +291,36 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber min={0} precision={2} />
|
<InputNumber min={0} precision={2} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.federal_tax_id")}
|
||||||
// label={t("bodyshop.fields.federal_tax_id")}
|
name="federal_tax_id"
|
||||||
// name="federal_tax_id"
|
rules={[
|
||||||
// >
|
{
|
||||||
// <Input />
|
required: true,
|
||||||
// </Form.Item>
|
//message: t("general.validation.required"),
|
||||||
}
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.state_tax_id")}
|
label={t("bodyshop.fields.state_tax_id")}
|
||||||
name="state_tax_id"
|
name="state_tax_id"
|
||||||
>
|
>
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.invoice_federal_tax_rate")}
|
||||||
// label={t("bodyshop.fields.invoice_federal_tax_rate")}
|
name={["bill_tax_rates", "federal_tax_rate"]}
|
||||||
// name={["bill_tax_rates", "federal_tax_rate"]}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<InputNumber />
|
||||||
// <InputNumber />
|
</Form.Item>
|
||||||
// </Form.Item>
|
|
||||||
}
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.invoice_state_tax_rate")}
|
label={t("bodyshop.fields.invoice_state_tax_rate")}
|
||||||
name={["bill_tax_rates", "state_tax_rate"]}
|
name={["bill_tax_rates", "state_tax_rate"]}
|
||||||
|
|||||||
@@ -28,18 +28,6 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
return (
|
return (
|
||||||
<RbacWrapper action="shop:rbac">
|
<RbacWrapper action="shop:rbac">
|
||||||
<LayoutFormRow>
|
<LayoutFormRow>
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.accounting.payables")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "accounting:payables"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.accounting.exportlog")}
|
label={t("bodyshop.fields.rbac.accounting.exportlog")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -52,6 +40,18 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.accounting.payables")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "accounting:payables"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.accounting.payments")}
|
label={t("bodyshop.fields.rbac.accounting.payments")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -77,26 +77,62 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.csi.page")}
|
label={t("bodyshop.fields.rbac.bills.delete")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "csi:page"]}
|
name={["md_rbac", "bills:delete"]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.csi.export")}
|
label={t("bodyshop.fields.rbac.bills.enter")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "csi:export"]}
|
name={["md_rbac", "bills:enter"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.bills.list")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "bills:list"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.bills.reexport")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "bills:reexport"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.bills.view")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "bills:view"]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -173,26 +209,38 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.jobs.list-active")}
|
label={t("bodyshop.fields.rbac.csi.export")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "jobs:list-active"]}
|
name={["md_rbac", "csi:export"]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.jobs.list-ready")}
|
label={t("bodyshop.fields.rbac.csi.page")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "jobs:list-ready"]}
|
name={["md_rbac", "csi:page"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.employees.page")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "employees:page"]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -208,30 +256,6 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.jobs.partsqueue")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "jobs:partsqueue"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.jobs.list-all")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "jobs:list-all"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.jobs.available-list")}
|
label={t("bodyshop.fields.rbac.jobs.available-list")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -245,26 +269,14 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.jobs.create")}
|
label={t("bodyshop.fields.rbac.jobs.checklist-view")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "jobs:create"]}
|
name={["md_rbac", "jobs:checklist-view"]}
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.jobs.intake")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "jobs:intake"]}
|
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -280,6 +292,18 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.jobs.create")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "jobs:create"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.jobs.deliver")}
|
label={t("bodyshop.fields.rbac.jobs.deliver")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -305,14 +329,62 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.jobs.checklist-view")}
|
label={t("bodyshop.fields.rbac.jobs.intake")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "jobs:checklist-view"]}
|
name={["md_rbac", "jobs:intake"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.jobs.list-active")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "jobs:list-active"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.jobs.list-all")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "jobs:list-all"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.jobs.list-ready")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "jobs:list-ready"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.jobs.partsqueue")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "jobs:partsqueue"]}
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -329,86 +401,14 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.bills.enter")}
|
label={t("bodyshop.fields.rbac.owners.detail")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "bills:enter"]}
|
name={["md_rbac", "owners:detail"]}
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.bills.delete")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "bills:delete"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.bills.reexport")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "bills:reexport"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.bills.view")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "bills:view"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.bills.list")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "bills:list"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.employees.page")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "employees:page"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.employee_teams.page")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "employee_teams:page"]}
|
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -424,18 +424,6 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.owners.detail")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "owners:detail"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.payments.enter")}
|
label={t("bodyshop.fields.rbac.payments.enter")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -460,6 +448,30 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.phonebook.edit")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "phonebook:edit"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.phonebook.view")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "phonebook:view"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.production.board")}
|
label={t("bodyshop.fields.rbac.production.board")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -521,74 +533,14 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.timetickets.edit")}
|
label={t("bodyshop.fields.rbac.shop.config")}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
name={["md_rbac", "timetickets:edit"]}
|
name={["md_rbac", "shop:config"]}
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.timetickets.shiftedit")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "timetickets:shiftedit"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.timetickets.editcommitted")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "timetickets:editcommitted"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.ttapprovals.view")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "ttapprovals:view"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.ttapprovals.approve")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "ttapprovals:approve"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.shop.vendors")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "shop:vendors"]}
|
|
||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
@@ -604,18 +556,6 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.shop.config")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "shop:config"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.shop.rbac")}
|
label={t("bodyshop.fields.rbac.shop.rbac")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -628,6 +568,18 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.shop.reportcenter")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "shop:reportcenter"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.shop.templates")}
|
label={t("bodyshop.fields.rbac.shop.templates")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -640,6 +592,42 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.shop.vendors")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "shop:vendors"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.temporarydocs.view")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "temporarydocs:view"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.timetickets.edit")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "timetickets:edit"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.timetickets.enter")}
|
label={t("bodyshop.fields.rbac.timetickets.enter")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -664,6 +652,18 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.rbac.timetickets.shiftedit")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name={["md_rbac", "timetickets:shiftedit"]}
|
||||||
|
>
|
||||||
|
<InputNumber />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.rbac.users.editaccess")}
|
label={t("bodyshop.fields.rbac.users.editaccess")}
|
||||||
rules={[
|
rules={[
|
||||||
@@ -676,42 +676,6 @@ export function ShopInfoRbacComponent({ form, bodyshop }) {
|
|||||||
>
|
>
|
||||||
<InputNumber />
|
<InputNumber />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.temporarydocs.view")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "temporarydocs:view"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.phonebook.view")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "phonebook:view"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.rbac.phonebook.edit")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={["md_rbac", "phonebook:edit"]}
|
|
||||||
>
|
|
||||||
<InputNumber />
|
|
||||||
</Form.Item>
|
|
||||||
{Simple_Inventory.treatment === "on" && (
|
{Simple_Inventory.treatment === "on" && (
|
||||||
<>
|
<>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import ShopInfoResponsibilitycentersTaxesComponent from "./shop-info.responsibilitycenters.taxes.component";
|
|
||||||
|
|
||||||
const SelectorDiv = styled.div`
|
const SelectorDiv = styled.div`
|
||||||
.ant-form-item .ant-select {
|
.ant-form-item .ant-select {
|
||||||
@@ -4117,124 +4116,122 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
|||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
</SelectorDiv>
|
</SelectorDiv>
|
||||||
|
|
||||||
{
|
<LayoutFormRow
|
||||||
// <LayoutFormRow
|
header={t("bodyshop.labels.responsibilitycenters.tax_accounts")}
|
||||||
// header={t("bodyshop.labels.responsibilitycenters.tax_accounts")}
|
id="tax_accounts"
|
||||||
// id="tax_accounts"
|
>
|
||||||
// >
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenters.federal_tax")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenters.federal_tax")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={["md_responsibility_centers", "taxes", "federal", "name"]}
|
||||||
// name={["md_responsibility_centers", "taxes", "federal", "name"]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
{/* <Form.Item
|
||||||
// {/* <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountnumber")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountnumber")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={[
|
||||||
// name={[
|
"md_responsibility_centers",
|
||||||
// "md_responsibility_centers",
|
"taxes",
|
||||||
// "taxes",
|
"federal",
|
||||||
// "federal",
|
"accountnumber",
|
||||||
// "accountnumber",
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item> */}
|
||||||
// </Form.Item> */}
|
{/* <Form.Item
|
||||||
// {/* <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountname")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountname")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={[
|
||||||
// name={[
|
"md_responsibility_centers",
|
||||||
// "md_responsibility_centers",
|
"taxes",
|
||||||
// "taxes",
|
"federal",
|
||||||
// "federal",
|
"accountname",
|
||||||
// "accountname",
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item> */}
|
||||||
// </Form.Item> */}
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountdesc")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountdesc")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={[
|
||||||
// name={[
|
"md_responsibility_centers",
|
||||||
// "md_responsibility_centers",
|
"taxes",
|
||||||
// "taxes",
|
"federal",
|
||||||
// "federal",
|
"accountdesc",
|
||||||
// "accountdesc",
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountitem")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountitem")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={[
|
||||||
// name={[
|
"md_responsibility_centers",
|
||||||
// "md_responsibility_centers",
|
"taxes",
|
||||||
// "taxes",
|
"federal",
|
||||||
// "federal",
|
"accountitem",
|
||||||
// "accountitem",
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||||
// {(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.dms.dms_acctnumber")}
|
||||||
// label={t("bodyshop.fields.dms.dms_acctnumber")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={[
|
||||||
// name={[
|
"md_responsibility_centers",
|
||||||
// "md_responsibility_centers",
|
"taxes",
|
||||||
// "taxes",
|
"federal",
|
||||||
// "federal",
|
"dms_acctnumber",
|
||||||
// "dms_acctnumber",
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
)}
|
||||||
// )}
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_rate")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_rate")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={["md_responsibility_centers", "taxes", "federal", "rate"]}
|
||||||
// name={["md_responsibility_centers", "taxes", "federal", "rate"]}
|
>
|
||||||
// >
|
<InputNumber precision={2} />
|
||||||
// <InputNumber precision={2} />
|
</Form.Item>
|
||||||
// </Form.Item>
|
</LayoutFormRow>
|
||||||
// </LayoutFormRow>
|
|
||||||
}
|
|
||||||
{DmsAp.treatment === "on" && (
|
{DmsAp.treatment === "on" && (
|
||||||
<LayoutFormRow id="federal_tax_itc">
|
<LayoutFormRow id="federal_tax_itc">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -4350,242 +4347,202 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
)}
|
)}
|
||||||
{
|
<LayoutFormRow id="state_tax">
|
||||||
// <LayoutFormRow id="state_tax">
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenters.state_tax")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenters.state_tax")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={["md_responsibility_centers", "taxes", "state", "name"]}
|
||||||
// name={["md_responsibility_centers", "taxes", "state", "name"]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
{/* <Form.Item
|
||||||
// {/* <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountnumber")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountnumber")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={[
|
||||||
// name={[
|
"md_responsibility_centers",
|
||||||
// "md_responsibility_centers",
|
"taxes",
|
||||||
// "taxes",
|
"state",
|
||||||
// "state",
|
"accountnumber",
|
||||||
// "accountnumber",
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountname")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountname")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={["md_responsibility_centers", "taxes", "state", "accountname"]}
|
||||||
// name={["md_responsibility_centers", "taxes", "state", "accountname"]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item> */}
|
||||||
// </Form.Item> */}
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountdesc")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountdesc")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={["md_responsibility_centers", "taxes", "state", "accountdesc"]}
|
||||||
// name={["md_responsibility_centers", "taxes", "state", "accountdesc"]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_accountitem")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountitem")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={["md_responsibility_centers", "taxes", "state", "accountitem"]}
|
||||||
// name={["md_responsibility_centers", "taxes", "state", "accountitem"]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||||
// {(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.dms.dms_acctnumber")}
|
||||||
// label={t("bodyshop.fields.dms.dms_acctnumber")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={[
|
||||||
// name={[
|
"md_responsibility_centers",
|
||||||
// "md_responsibility_centers",
|
"taxes",
|
||||||
// "taxes",
|
"state",
|
||||||
// "state",
|
"dms_acctnumber",
|
||||||
// "dms_acctnumber",
|
]}
|
||||||
// ]}
|
>
|
||||||
// >
|
<Input />
|
||||||
// <Input />
|
</Form.Item>
|
||||||
// </Form.Item>
|
)}
|
||||||
// )}
|
<Form.Item
|
||||||
// <Form.Item
|
label={t("bodyshop.fields.responsibilitycenter_rate")}
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_rate")}
|
rules={[
|
||||||
// rules={[
|
{
|
||||||
// {
|
required: true,
|
||||||
// required: true,
|
//message: t("general.validation.required"),
|
||||||
// //message: t("general.validation.required"),
|
},
|
||||||
// },
|
]}
|
||||||
// ]}
|
name={["md_responsibility_centers", "taxes", "state", "rate"]}
|
||||||
// name={["md_responsibility_centers", "taxes", "state", "rate"]}
|
>
|
||||||
// >
|
<InputNumber precision={2} />
|
||||||
// <InputNumber precision={2} />
|
</Form.Item>
|
||||||
// </Form.Item>
|
</LayoutFormRow>
|
||||||
// </LayoutFormRow>
|
<LayoutFormRow id="local_tax">
|
||||||
}
|
<Form.Item
|
||||||
<ShopInfoResponsibilitycentersTaxesComponent form={form} />
|
label={t("bodyshop.fields.responsibilitycenters.local_tax")}
|
||||||
<Form.Item
|
rules={[
|
||||||
label={t("bodyshop.fields.responsibilitycenters.itemexemptcode")}
|
{
|
||||||
rules={[
|
required: true,
|
||||||
{
|
//message: t("general.validation.required"),
|
||||||
required: true,
|
},
|
||||||
//message: t("general.validation.required"),
|
]}
|
||||||
},
|
name={["md_responsibility_centers", "taxes", "local", "name"]}
|
||||||
]}
|
>
|
||||||
name={["md_responsibility_centers", "taxes", "itemexemptcode"]}
|
<Input />
|
||||||
>
|
</Form.Item>
|
||||||
<Input />
|
{/* <Form.Item
|
||||||
</Form.Item>
|
label={t("bodyshop.fields.responsibilitycenter_accountnumber")}
|
||||||
<Form.Item
|
rules={[
|
||||||
label={t("bodyshop.fields.responsibilitycenters.invoiceexemptcode")}
|
{
|
||||||
rules={[
|
required: true,
|
||||||
{
|
//message: t("general.validation.required"),
|
||||||
required: true,
|
},
|
||||||
//message: t("general.validation.required"),
|
]}
|
||||||
},
|
name={[
|
||||||
]}
|
"md_responsibility_centers",
|
||||||
name={["md_responsibility_centers", "taxes", "invoiceexemptcode"]}
|
"taxes",
|
||||||
>
|
"local",
|
||||||
<Input />
|
"accountnumber",
|
||||||
</Form.Item>
|
]}
|
||||||
|
>
|
||||||
{
|
<Input />
|
||||||
// <LayoutFormRow id="local_tax">
|
</Form.Item>
|
||||||
// <Form.Item
|
<Form.Item
|
||||||
// label={t("bodyshop.fields.responsibilitycenters.local_tax")}
|
label={t("bodyshop.fields.responsibilitycenter_accountname")}
|
||||||
// rules={[
|
rules={[
|
||||||
// {
|
{
|
||||||
// required: true,
|
required: true,
|
||||||
// //message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
// },
|
},
|
||||||
// ]}
|
]}
|
||||||
// name={["md_responsibility_centers", "taxes", "local", "name"]}
|
name={["md_responsibility_centers", "taxes", "local", "accountname"]}
|
||||||
// >
|
>
|
||||||
// <Input />
|
<Input />
|
||||||
// </Form.Item>
|
</Form.Item> */}
|
||||||
// {/* <Form.Item
|
<Form.Item
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountnumber")}
|
label={t("bodyshop.fields.responsibilitycenter_accountdesc")}
|
||||||
// rules={[
|
rules={[
|
||||||
// {
|
{
|
||||||
// required: true,
|
required: true,
|
||||||
// //message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
// },
|
},
|
||||||
// ]}
|
]}
|
||||||
// name={[
|
name={["md_responsibility_centers", "taxes", "local", "accountdesc"]}
|
||||||
// "md_responsibility_centers",
|
>
|
||||||
// "taxes",
|
<Input />
|
||||||
// "local",
|
</Form.Item>
|
||||||
// "accountnumber",
|
<Form.Item
|
||||||
// ]}
|
label={t("bodyshop.fields.responsibilitycenter_accountitem")}
|
||||||
// >
|
rules={[
|
||||||
// <Input />
|
{
|
||||||
// </Form.Item>
|
required: true,
|
||||||
// <Form.Item
|
//message: t("general.validation.required"),
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountname")}
|
},
|
||||||
// rules={[
|
]}
|
||||||
// {
|
name={["md_responsibility_centers", "taxes", "local", "accountitem"]}
|
||||||
// required: true,
|
>
|
||||||
// //message: t("general.validation.required"),
|
<Input />
|
||||||
// },
|
</Form.Item>
|
||||||
// ]}
|
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||||
// name={["md_responsibility_centers", "taxes", "local", "accountname"]}
|
<Form.Item
|
||||||
// >
|
label={t("bodyshop.fields.dms.dms_acctnumber")}
|
||||||
// <Input />
|
rules={[
|
||||||
// </Form.Item> */}
|
{
|
||||||
// <Form.Item
|
required: true,
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountdesc")}
|
//message: t("general.validation.required"),
|
||||||
// rules={[
|
},
|
||||||
// {
|
]}
|
||||||
// required: true,
|
name={[
|
||||||
// //message: t("general.validation.required"),
|
"md_responsibility_centers",
|
||||||
// },
|
"taxes",
|
||||||
// ]}
|
"local",
|
||||||
// name={[
|
"dms_acctnumber",
|
||||||
// "md_responsibility_centers",
|
]}
|
||||||
// "taxes",
|
>
|
||||||
// "local",
|
<Input />
|
||||||
// "accountdesc",
|
</Form.Item>
|
||||||
// ]}
|
)}
|
||||||
// >
|
<Form.Item
|
||||||
// <Input />
|
label={t("bodyshop.fields.responsibilitycenter_rate")}
|
||||||
// </Form.Item>
|
rules={[
|
||||||
// <Form.Item
|
{
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_accountitem")}
|
required: true,
|
||||||
// rules={[
|
//message: t("general.validation.required"),
|
||||||
// {
|
},
|
||||||
// required: true,
|
]}
|
||||||
// //message: t("general.validation.required"),
|
name={["md_responsibility_centers", "taxes", "local", "rate"]}
|
||||||
// },
|
>
|
||||||
// ]}
|
<InputNumber precision={2} />
|
||||||
// name={[
|
</Form.Item>
|
||||||
// "md_responsibility_centers",
|
</LayoutFormRow>
|
||||||
// "taxes",
|
|
||||||
// "local",
|
|
||||||
// "accountitem",
|
|
||||||
// ]}
|
|
||||||
// >
|
|
||||||
// <Input />
|
|
||||||
// </Form.Item>
|
|
||||||
// {(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
|
||||||
// <Form.Item
|
|
||||||
// label={t("bodyshop.fields.dms.dms_acctnumber")}
|
|
||||||
// rules={[
|
|
||||||
// {
|
|
||||||
// required: true,
|
|
||||||
// //message: t("general.validation.required"),
|
|
||||||
// },
|
|
||||||
// ]}
|
|
||||||
// name={[
|
|
||||||
// "md_responsibility_centers",
|
|
||||||
// "taxes",
|
|
||||||
// "local",
|
|
||||||
// "dms_acctnumber",
|
|
||||||
// ]}
|
|
||||||
// >
|
|
||||||
// <Input />
|
|
||||||
// </Form.Item>
|
|
||||||
// )}
|
|
||||||
// <Form.Item
|
|
||||||
// label={t("bodyshop.fields.responsibilitycenter_rate")}
|
|
||||||
// rules={[
|
|
||||||
// {
|
|
||||||
// required: true,
|
|
||||||
// //message: t("general.validation.required"),
|
|
||||||
// },
|
|
||||||
// ]}
|
|
||||||
// name={["md_responsibility_centers", "taxes", "local", "rate"]}
|
|
||||||
// >
|
|
||||||
// <InputNumber precision={2} />
|
|
||||||
// </Form.Item>
|
|
||||||
// </LayoutFormRow>
|
|
||||||
}
|
|
||||||
<LayoutFormRow header={<div>AR</div>} id="AR">
|
<LayoutFormRow header={<div>AR</div>} id="AR">
|
||||||
{/* <Form.Item
|
{/* <Form.Item
|
||||||
label={t("bodyshop.fields.responsibilitycenters.ar")}
|
label={t("bodyshop.fields.responsibilitycenters.ar")}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,269 +0,0 @@
|
|||||||
import { DeleteFilled } from "@ant-design/icons";
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Checkbox,
|
|
||||||
Col,
|
|
||||||
Form,
|
|
||||||
Input,
|
|
||||||
InputNumber,
|
|
||||||
Row,
|
|
||||||
Select,
|
|
||||||
Space,
|
|
||||||
Switch,
|
|
||||||
} from "antd";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(ShopInfoTaskPresets);
|
|
||||||
|
|
||||||
export function ShopInfoTaskPresets({ bodyshop, form }) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<LayoutFormRow noDivider>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.md_tasks_presets.enable_tasks")}
|
|
||||||
valuePropName="checked"
|
|
||||||
name={["md_tasks_presets", "enable_tasks"]}
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.md_tasks_presets.use_approvals")}
|
|
||||||
valuePropName="checked"
|
|
||||||
name={["md_tasks_presets", "use_approvals"]}
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
|
|
||||||
<LayoutFormRow header={t("bodyshop.labels.md_tasks_presets")}>
|
|
||||||
<Form.List name={["md_tasks_presets", "presets"]}>
|
|
||||||
{(fields, { add, remove, move }) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{fields.map((field, index) => (
|
|
||||||
<Form.Item key={field.key}>
|
|
||||||
<LayoutFormRow noDivider>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.md_tasks_presets.name")}
|
|
||||||
key={`${index}name`}
|
|
||||||
name={[field.name, "name"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
span={12}
|
|
||||||
label={t("bodyshop.fields.md_tasks_presets.hourstype")}
|
|
||||||
key={`${index}hourstype`}
|
|
||||||
name={[field.name, "hourstype"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Checkbox.Group>
|
|
||||||
<Row>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAA"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAA")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAB"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAB")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAD"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAD")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAE"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAE")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAF"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAF")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAG"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAG")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAM"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAM")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAR"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAR")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAS"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAS")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LAU"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LAU")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LA1"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LA1")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LA2"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LA2")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LA3"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LA3")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={4}>
|
|
||||||
<Checkbox
|
|
||||||
value="LA4"
|
|
||||||
style={{ lineHeight: "32px" }}
|
|
||||||
>
|
|
||||||
{t("joblines.fields.lbr_types.LA4")}
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Checkbox.Group>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.md_tasks_presets.percent")}
|
|
||||||
key={`${index}percent`}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
name={[field.name, "percent"]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} max={100} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.md_tasks_presets.memo")}
|
|
||||||
key={`${index}memo`}
|
|
||||||
name={[field.name, "memo"]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("bodyshop.fields.md_tasks_presets.nextstatus")}
|
|
||||||
key={`${index}nextstatus`}
|
|
||||||
name={[field.name, "nextstatus"]}
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
options={bodyshop.md_ro_statuses.production_statuses.map(
|
|
||||||
(o) => ({ value: o, label: o })
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Space wrap>
|
|
||||||
<DeleteFilled
|
|
||||||
onClick={() => {
|
|
||||||
remove(field.name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<FormListMoveArrows
|
|
||||||
move={move}
|
|
||||||
index={index}
|
|
||||||
total={fields.length}
|
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
</LayoutFormRow>
|
|
||||||
</Form.Item>
|
|
||||||
))}
|
|
||||||
<Form.Item>
|
|
||||||
<Button
|
|
||||||
type="dashed"
|
|
||||||
onClick={() => {
|
|
||||||
add();
|
|
||||||
}}
|
|
||||||
style={{ width: "100%" }}
|
|
||||||
>
|
|
||||||
{t("bodyshop.actions.add_task_preset")}
|
|
||||||
</Button>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Form.List>
|
|
||||||
</LayoutFormRow>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
|
|
||||||
export default function ShopEmployeeTeamMember({teamMember}) {
|
|
||||||
return (
|
|
||||||
<div>ShopEmployeeTeamMember</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,436 +0,0 @@
|
|||||||
import { DeleteFilled } from "@ant-design/icons";
|
|
||||||
import { useMutation, useQuery } from "@apollo/client";
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Form,
|
|
||||||
Input,
|
|
||||||
InputNumber,
|
|
||||||
Space,
|
|
||||||
Switch,
|
|
||||||
notification,
|
|
||||||
} from "antd";
|
|
||||||
|
|
||||||
import querystring from "query-string";
|
|
||||||
import React, { useEffect } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { useHistory, useLocation } from "react-router-dom";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import AlertComponent from "../alert/alert.component";
|
|
||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
|
||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
|
|
||||||
import {
|
|
||||||
INSERT_EMPLOYEE_TEAM,
|
|
||||||
QUERY_EMPLOYEE_TEAM_BY_ID,
|
|
||||||
UPDATE_EMPLOYEE_TEAM,
|
|
||||||
} from "../../graphql/employee_teams.queries";
|
|
||||||
import EmployeeSearchSelectComponent from "../employee-search-select/employee-search-select.component";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
|
||||||
});
|
|
||||||
|
|
||||||
export function ShopEmployeeTeamsFormComponent({ bodyshop }) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const history = useHistory();
|
|
||||||
const search = querystring.parse(useLocation().search);
|
|
||||||
|
|
||||||
const { error, data } = useQuery(QUERY_EMPLOYEE_TEAM_BY_ID, {
|
|
||||||
variables: { id: search.employeeTeamId },
|
|
||||||
skip: !search.employeeTeamId || search.employeeTeamId === "new",
|
|
||||||
fetchPolicy: "network-only",
|
|
||||||
nextFetchPolicy: "network-only",
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (data && data.employee_teams_by_pk)
|
|
||||||
form.setFieldsValue(data.employee_teams_by_pk);
|
|
||||||
else {
|
|
||||||
form.resetFields();
|
|
||||||
}
|
|
||||||
}, [form, data, search.employeeTeamId]);
|
|
||||||
|
|
||||||
const [updateEmployeeTeam] = useMutation(UPDATE_EMPLOYEE_TEAM);
|
|
||||||
const [insertEmployeeTeam] = useMutation(INSERT_EMPLOYEE_TEAM);
|
|
||||||
|
|
||||||
const handleFinish = async ({ employee_team_members, ...values }) => {
|
|
||||||
if (search.employeeTeamId && search.employeeTeamId !== "new") {
|
|
||||||
//Update a record.
|
|
||||||
logImEXEvent("shop_employee_update");
|
|
||||||
|
|
||||||
const result = await updateEmployeeTeam({
|
|
||||||
variables: {
|
|
||||||
employeeTeamId: search.employeeTeamId,
|
|
||||||
employeeTeam: values,
|
|
||||||
teamMemberUpdates: employee_team_members
|
|
||||||
.filter((e) => e.id)
|
|
||||||
.map((e) => {
|
|
||||||
delete e.__typename;
|
|
||||||
return { where: { id: { _eq: e.id } }, _set: e };
|
|
||||||
}),
|
|
||||||
teamMemberInserts: employee_team_members
|
|
||||||
.filter((e) => e.id === null || e.id === undefined)
|
|
||||||
.map((e) => ({ ...e, teamid: search.employeeTeamId })),
|
|
||||||
teamMemberDeletes:
|
|
||||||
data.employee_teams_by_pk.employee_team_members.filter(
|
|
||||||
(e) => !employee_team_members.find((etm) => etm.id === e.id)
|
|
||||||
),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!result.errors) {
|
|
||||||
notification["success"]({
|
|
||||||
message: t("employees.successes.save"),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
notification["error"]({
|
|
||||||
message: t("employees.errors.save", {
|
|
||||||
message: JSON.stringify(error),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//New record, insert it.
|
|
||||||
logImEXEvent("shop_employee_insert");
|
|
||||||
|
|
||||||
insertEmployeeTeam({
|
|
||||||
variables: {
|
|
||||||
employeeTeam: {
|
|
||||||
...values,
|
|
||||||
employee_team_members: { data: employee_team_members },
|
|
||||||
bodyshopid: bodyshop.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
refetchQueries: ["QUERY_TEAMS"],
|
|
||||||
}).then((r) => {
|
|
||||||
search.employeeTeamId = r.data.insert_employee_teams_one.id;
|
|
||||||
history.push({ search: querystring.stringify(search) });
|
|
||||||
notification["success"]({
|
|
||||||
message: t("employees.successes.save"),
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!search.employeeTeamId) return null;
|
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card
|
|
||||||
extra={
|
|
||||||
<Button type="primary" onClick={() => form.submit()}>
|
|
||||||
{t("general.actions.save")}
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Form
|
|
||||||
onFinish={handleFinish}
|
|
||||||
autoComplete={"off"}
|
|
||||||
layout="vertical"
|
|
||||||
form={form}
|
|
||||||
>
|
|
||||||
<LayoutFormRow>
|
|
||||||
<Form.Item
|
|
||||||
name="name"
|
|
||||||
label={t("employee_teams.fields.name")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("employee_teams.fields.active")}
|
|
||||||
name="active"
|
|
||||||
valuePropName="checked"
|
|
||||||
>
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("employee_teams.fields.max_load")}
|
|
||||||
name="max_load"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} precision={1} />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
<Form.List name={["employee_team_members"]}>
|
|
||||||
{(fields, { add, remove, move }) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{fields.map((field, index) => (
|
|
||||||
<Form.Item key={field.key} style={{ padding: 0, margin: 2 }}>
|
|
||||||
<Form.Item
|
|
||||||
label={t("employees.fields.id")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "id"]}
|
|
||||||
hidden
|
|
||||||
>
|
|
||||||
<Input />
|
|
||||||
</Form.Item>
|
|
||||||
<LayoutFormRow grow>
|
|
||||||
<Form.Item
|
|
||||||
label={t("employee_teams.fields.employeeid")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "employeeid"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<EmployeeSearchSelectComponent
|
|
||||||
options={bodyshop.employees}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("employee_teams.fields.percentage")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "percentage"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<InputNumber min={0} max={100} precision={2} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAA")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAA"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAB")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAB"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAD")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAD"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAE")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAE"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAF")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAF"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAG")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAG"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAM")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAM"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAR")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAR"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAS")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAS"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LAU")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LAU"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LA1")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LA1"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LA2")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LA2"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LA3")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LA3"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("joblines.fields.lbr_types.LA4")}
|
|
||||||
key={`${index}`}
|
|
||||||
name={[field.name, "labor_rates", "LA4"]}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<CurrencyInput />
|
|
||||||
</Form.Item>
|
|
||||||
<Space align="center">
|
|
||||||
<DeleteFilled
|
|
||||||
onClick={() => {
|
|
||||||
remove(field.name);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<FormListMoveArrows
|
|
||||||
move={move}
|
|
||||||
index={index}
|
|
||||||
total={fields.length}
|
|
||||||
/>
|
|
||||||
</Space>
|
|
||||||
</LayoutFormRow>
|
|
||||||
</Form.Item>
|
|
||||||
))}
|
|
||||||
<Form.Item>
|
|
||||||
<Button
|
|
||||||
type="dashed"
|
|
||||||
onClick={() => {
|
|
||||||
add();
|
|
||||||
}}
|
|
||||||
style={{ width: "100%" }}
|
|
||||||
>
|
|
||||||
{t("employee_teams.actions.newmember")}
|
|
||||||
</Button>
|
|
||||||
</Form.Item>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Form.List>
|
|
||||||
</Form>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(ShopEmployeeTeamsFormComponent);
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
import { Button, Table } from "antd";
|
|
||||||
import queryString from "query-string";
|
|
||||||
import React from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { useHistory, useLocation } from "react-router-dom";
|
|
||||||
|
|
||||||
export default function ShopEmployeeTeamsListComponent({
|
|
||||||
loading,
|
|
||||||
employee_teams,
|
|
||||||
}) {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const history = useHistory();
|
|
||||||
const search = queryString.parse(useLocation().search);
|
|
||||||
|
|
||||||
const handleOnRowClick = (record) => {
|
|
||||||
if (record) {
|
|
||||||
search.employeeTeamId = record.id;
|
|
||||||
history.push({ search: queryString.stringify(search) });
|
|
||||||
} else {
|
|
||||||
delete search.employeeTeamId;
|
|
||||||
history.push({ search: queryString.stringify(search) });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
title: t("employee_teams.fields.name"),
|
|
||||||
dataIndex: "name",
|
|
||||||
key: "name",
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Table
|
|
||||||
title={() => {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
onClick={() => {
|
|
||||||
search.employeeTeamId = "new";
|
|
||||||
history.push({ search: queryString.stringify(search) });
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("employee_teams.actions.new")}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
loading={loading}
|
|
||||||
pagination={{ position: "top" }}
|
|
||||||
columns={columns}
|
|
||||||
rowKey="id"
|
|
||||||
dataSource={employee_teams}
|
|
||||||
rowSelection={{
|
|
||||||
onSelect: (props) => {
|
|
||||||
search.employeeTeamId = props.id;
|
|
||||||
history.push({ search: queryString.stringify(search) });
|
|
||||||
},
|
|
||||||
type: "radio",
|
|
||||||
selectedRowKeys: [search.employeeTeamId],
|
|
||||||
}}
|
|
||||||
onRow={(record, rowIndex) => {
|
|
||||||
return {
|
|
||||||
onClick: (event) => {
|
|
||||||
handleOnRowClick(record);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import { useQuery } from "@apollo/client";
|
|
||||||
import React from "react";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { QUERY_TEAMS } from "../../graphql/employee_teams.queries";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import AlertComponent from "../alert/alert.component";
|
|
||||||
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
|
|
||||||
import ShopEmployeeTeamsListComponent from "./shop-employee-teams.list";
|
|
||||||
import ShopEmployeeTeamsFormComponent from "./shop-employee-teams.form.component";
|
|
||||||
import { Col, Row } from "antd";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
|
|
||||||
function ShopTeamsContainer({ bodyshop }) {
|
|
||||||
const { loading, error, data } = useQuery(QUERY_TEAMS, {
|
|
||||||
fetchPolicy: "network-only",
|
|
||||||
nextFetchPolicy: "network-only",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<RbacWrapper action="employee_teams:page">
|
|
||||||
<Row gutter={[16, 16]}>
|
|
||||||
<Col span={6}>
|
|
||||||
<ShopEmployeeTeamsListComponent
|
|
||||||
employee_teams={data ? data.employee_teams : []}
|
|
||||||
loading={loading}
|
|
||||||
/>
|
|
||||||
</Col>
|
|
||||||
<Col span={18}>
|
|
||||||
<ShopEmployeeTeamsFormComponent />
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</RbacWrapper>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default connect(mapStateToProps, null)(ShopTeamsContainer);
|
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { LockOutlined, UserOutlined } from "@ant-design/icons";
|
import { LockOutlined, UserOutlined } from "@ant-design/icons";
|
||||||
import { Button, Form, Input } from "antd";
|
import { Button, Form, Input, Typography } from "antd";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Link, Redirect, useLocation } from "react-router-dom";
|
import { Link, Redirect, useLocation } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import RomeLogo from "../../assets/RomeOnlineBlue.png";
|
import ImEXOnlineLogo from "../../assets/logo192.png";
|
||||||
import {
|
import {
|
||||||
emailSignInStart,
|
emailSignInStart,
|
||||||
sendPasswordReset,
|
sendPasswordReset,
|
||||||
@@ -53,7 +53,8 @@ export function SignInComponent({
|
|||||||
return (
|
return (
|
||||||
<div className="login-container">
|
<div className="login-container">
|
||||||
<div className="login-logo-container">
|
<div className="login-logo-container">
|
||||||
<img src={RomeLogo} width={200} alt="Rome Online" />
|
<img src={ImEXOnlineLogo} height="100" width="100" alt="ImEX Online" />
|
||||||
|
<Typography.Title>{t("titles.app")}</Typography.Title>
|
||||||
</div>
|
</div>
|
||||||
<Form onFinish={handleFinish} form={form} size="large">
|
<Form onFinish={handleFinish} form={form} size="large">
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
|||||||
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
||||||
import JobsDetailLaborContainer from "../jobs-detail-labor/jobs-detail-labor.container";
|
import JobsDetailLaborContainer from "../jobs-detail-labor/jobs-detail-labor.container";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -17,11 +16,6 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
|
|
||||||
export function TechClockInComponent({ form, bodyshop, technician }) {
|
export function TechClockInComponent({ form, bodyshop, technician }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
const emps = bodyshop.employees.filter((e) => e.id === technician.id)[0];
|
const emps = bodyshop.employees.filter((e) => e.id === technician.id)[0];
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -59,7 +53,7 @@ export function TechClockInComponent({ form, bodyshop, technician }) {
|
|||||||
<Select.Option key={item.cost_center} value={item.cost_center}>
|
<Select.Option key={item.cost_center} value={item.cost_center}>
|
||||||
{item.cost_center === "timetickets.labels.shift"
|
{item.cost_center === "timetickets.labels.shift"
|
||||||
? t(item.cost_center)
|
? t(item.cost_center)
|
||||||
: bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === "on"
|
: bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
|
||||||
? t(
|
? t(
|
||||||
`joblines.fields.lbr_types.${item.cost_center.toUpperCase()}`
|
`joblines.fields.lbr_types.${item.cost_center.toUpperCase()}`
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import {
|
|||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
import TechJobPrintTickets from "../tech-job-print-tickets/tech-job-print-tickets.component";
|
import TechJobPrintTickets from "../tech-job-print-tickets/tech-job-print-tickets.component";
|
||||||
import TechClockInComponent from "./tech-job-clock-in-form.component";
|
import TechClockInComponent from "./tech-job-clock-in-form.component";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
@@ -33,10 +32,9 @@ export function TechClockInContainer({
|
|||||||
bodyshop,
|
bodyshop,
|
||||||
currentUser,
|
currentUser,
|
||||||
}) {
|
}) {
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
console.log(
|
||||||
["Enhanced_Payroll"],
|
"🚀 ~ file: tech-job-clock-in-form.container.jsx:30 ~ technician:",
|
||||||
{},
|
technician
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -70,7 +68,7 @@ export function TechClockInContainer({
|
|||||||
jobid: values.jobid,
|
jobid: values.jobid,
|
||||||
cost_center: values.cost_center,
|
cost_center: values.cost_center,
|
||||||
ciecacode:
|
ciecacode:
|
||||||
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === 'on'
|
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
|
||||||
? values.cost_center
|
? values.cost_center
|
||||||
: Object.keys(
|
: Object.keys(
|
||||||
bodyshop.md_responsibility_centers.defaults.costs
|
bodyshop.md_responsibility_centers.defaults.costs
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
|||||||
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
|
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
|
||||||
import TechJobClockoutDelete from "../tech-job-clock-out-delete/tech-job-clock-out-delete.component";
|
import TechJobClockoutDelete from "../tech-job-clock-out-delete/tech-job-clock-out-delete.component";
|
||||||
import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component";
|
import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -44,12 +43,6 @@ export function TechClockOffButton({
|
|||||||
const [updateTimeticket] = useMutation(UPDATE_TIME_TICKET);
|
const [updateTimeticket] = useMutation(UPDATE_TIME_TICKET);
|
||||||
const [updateJobStatus] = useMutation(UPDATE_JOB_STATUS);
|
const [updateJobStatus] = useMutation(UPDATE_JOB_STATUS);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
|
|
||||||
const { queryLoading, data: lineTicketData } = useQuery(
|
const { queryLoading, data: lineTicketData } = useQuery(
|
||||||
GET_LINE_TICKET_BY_PK,
|
GET_LINE_TICKET_BY_PK,
|
||||||
{
|
{
|
||||||
@@ -83,9 +76,7 @@ export function TechClockOffButton({
|
|||||||
?.rate,
|
?.rate,
|
||||||
flat_rate: emps && emps.flat_rate,
|
flat_rate: emps && emps.flat_rate,
|
||||||
ciecacode:
|
ciecacode:
|
||||||
bodyshop.cdk_dealerid ||
|
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
|
||||||
bodyshop.pbs_serialnumber ||
|
|
||||||
Enhanced_Payroll.treatment === "on"
|
|
||||||
? values.cost_center
|
? values.cost_center
|
||||||
: Object.keys(
|
: Object.keys(
|
||||||
bodyshop.md_responsibility_centers.defaults.costs
|
bodyshop.md_responsibility_centers.defaults.costs
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
import Icon, {
|
import Icon, { SearchOutlined, ScheduleOutlined } from "@ant-design/icons";
|
||||||
SearchOutlined,
|
|
||||||
ScheduleOutlined,
|
|
||||||
UserAddOutlined,
|
|
||||||
CarOutlined,
|
|
||||||
} from "@ant-design/icons";
|
|
||||||
import { Layout, Menu } from "antd";
|
import { Layout, Menu } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -16,38 +11,22 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { techLogout } from "../../redux/tech/tech.actions";
|
import { techLogout } from "../../redux/tech/tech.actions";
|
||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
import { BsKanban } from "react-icons/bs";
|
import { BsKanban } from "react-icons/bs";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
|
||||||
|
|
||||||
const { Sider } = Layout;
|
const { Sider } = Layout;
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
techLogout: () => dispatch(techLogout()),
|
techLogout: () => dispatch(techLogout()),
|
||||||
setTimeTicketTaskContext: (context) =>
|
|
||||||
dispatch(setModalContext({ context: context, modal: "timeTicketTask" })),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export function TechSider({
|
export function TechSider({ technician, techLogout }) {
|
||||||
technician,
|
|
||||||
techLogout,
|
|
||||||
bodyshop,
|
|
||||||
setTimeTicketTaskContext,
|
|
||||||
}) {
|
|
||||||
const [collapsed, setCollapsed] = useState(true);
|
const [collapsed, setCollapsed] = useState(true);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const onCollapse = (collapsed) => {
|
const onCollapse = (collapsed) => {
|
||||||
setCollapsed(collapsed);
|
setCollapsed(collapsed);
|
||||||
};
|
};
|
||||||
const { Enhanced_Payroll } = useTreatments(
|
|
||||||
["Enhanced_Payroll"],
|
|
||||||
{},
|
|
||||||
bodyshop.imexshopid
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sider
|
<Sider
|
||||||
@@ -72,38 +51,13 @@ export function TechSider({
|
|||||||
<Menu.Item key="2" disabled={!!!technician} icon={<SearchOutlined />}>
|
<Menu.Item key="2" disabled={!!!technician} icon={<SearchOutlined />}>
|
||||||
<Link to={`/tech/joblookup`}>{t("menus.tech.joblookup")}</Link>
|
<Link to={`/tech/joblookup`}>{t("menus.tech.joblookup")}</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
{Enhanced_Payroll.treatment === "on" ? (
|
<Menu.Item
|
||||||
<>
|
key="3"
|
||||||
<Menu.Item
|
disabled={!!!technician}
|
||||||
key="TechAssignedProdJobs"
|
icon={<Icon component={FaBusinessTime} />}
|
||||||
disabled={!!!technician}
|
>
|
||||||
icon={<UserAddOutlined />}
|
<Link to={`/tech/jobclock`}>{t("menus.tech.jobclockin")}</Link>
|
||||||
>
|
</Menu.Item>
|
||||||
<Link to={`/tech/assigned`}> {t("menus.tech.assignedjobs")}</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item
|
|
||||||
key="3"
|
|
||||||
disabled={!!!technician}
|
|
||||||
icon={<Icon component={FaBusinessTime} />}
|
|
||||||
onClick={() => {
|
|
||||||
setTimeTicketTaskContext({
|
|
||||||
actions: {},
|
|
||||||
context: { jobid: null },
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("menus.tech.claimtask")}
|
|
||||||
</Menu.Item>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<Menu.Item
|
|
||||||
key="3"
|
|
||||||
disabled={!!!technician}
|
|
||||||
icon={<Icon component={FaBusinessTime} />}
|
|
||||||
>
|
|
||||||
<Link to={`/tech/jobclock`}>{t("menus.tech.jobclockin")}</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
)}
|
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="4"
|
key="4"
|
||||||
disabled={!!!technician}
|
disabled={!!!technician}
|
||||||
@@ -114,15 +68,6 @@ export function TechSider({
|
|||||||
<Menu.Item key="5" disabled={!!!technician} icon={<ScheduleOutlined />}>
|
<Menu.Item key="5" disabled={!!!technician} icon={<ScheduleOutlined />}>
|
||||||
<Link to={`/tech/list`}>{t("menus.tech.productionlist")}</Link>
|
<Link to={`/tech/list`}>{t("menus.tech.productionlist")}</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item
|
|
||||||
key="dispatchedparts"
|
|
||||||
disabled={!!!technician}
|
|
||||||
icon={<CarOutlined />}
|
|
||||||
>
|
|
||||||
<Link to={`/tech/dispatchedparts`}>
|
|
||||||
{t("menus.tech.dispatchedparts")}
|
|
||||||
</Link>
|
|
||||||
</Menu.Item>
|
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="6"
|
key="6"
|
||||||
disabled={!!!technician}
|
disabled={!!!technician}
|
||||||
@@ -130,7 +75,6 @@ export function TechSider({
|
|||||||
>
|
>
|
||||||
<Link to={`/tech/board`}> {t("menus.tech.productionboard")}</Link>
|
<Link to={`/tech/board`}> {t("menus.tech.productionboard")}</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
key="7"
|
key="7"
|
||||||
disabled={!!!technician}
|
disabled={!!!technician}
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
import { DownOutlined } from "@ant-design/icons";
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Checkbox,
|
|
||||||
Col,
|
|
||||||
Form,
|
|
||||||
InputNumber,
|
|
||||||
Popover,
|
|
||||||
Radio,
|
|
||||||
Row,
|
|
||||||
Space,
|
|
||||||
Spin,
|
|
||||||
} from "antd";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { GET_JOB_INFO_DRAW_CALCULATIONS } from "../../graphql/jobs-lines.queries";
|
|
||||||
import { useQuery } from "@apollo/client";
|
|
||||||
|
|
||||||
export default function TimeTicketCalculatorComponent({
|
|
||||||
setProductiveHours,
|
|
||||||
|
|
||||||
jobid,
|
|
||||||
}) {
|
|
||||||
const { loading, data: lineTicketData } = useQuery(GET_JOB_INFO_DRAW_CALCULATIONS, {
|
|
||||||
variables: { id: jobid },
|
|
||||||
skip: !jobid,
|
|
||||||
fetchPolicy: "network-only",
|
|
||||||
nextFetchPolicy: "network-only",
|
|
||||||
});
|
|
||||||
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const handleOpenChange = (flag) => setVisible(flag);
|
|
||||||
const handleFinish = ({ type, hourstype, percent }) => {
|
|
||||||
//setProductiveHours(values);
|
|
||||||
//setVisible(false);
|
|
||||||
const eligibleHours = Array.isArray(hourstype)
|
|
||||||
? lineTicketData.joblines.reduce(
|
|
||||||
(acc, val) =>
|
|
||||||
acc + (hourstype.includes(val.mod_lbr_ty) ? val.mod_lb_hrs : 0),
|
|
||||||
0
|
|
||||||
)
|
|
||||||
: lineTicketData.joblines.reduce(
|
|
||||||
(acc, val) =>
|
|
||||||
acc + (hourstype === val.mod_lbr_ty ? val.mod_lb_hrs : 0),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
if (type === "draw") {
|
|
||||||
setProductiveHours(eligibleHours * (percent / 100));
|
|
||||||
} else if (type === "cut") {
|
|
||||||
setProductiveHours(eligibleHours * (percent / 100));
|
|
||||||
console.log(
|
|
||||||
"Cut selected, rate set to: ",
|
|
||||||
lineTicketData.jobs_by_pk[`rate_${hourstype.toLowerCase()}`]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const popContent = (
|
|
||||||
<Spin spinning={loading}>
|
|
||||||
<Form onFinish={handleFinish}>
|
|
||||||
<Form.Item name="type">
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio.Button value="draw">Draw</Radio.Button>
|
|
||||||
<Radio.Button value="cut">Cut of Sale</Radio.Button>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item noStyle shouldUpdate>
|
|
||||||
{({ getFieldValue }) => (
|
|
||||||
<Form.Item name="hourstype">
|
|
||||||
{getFieldValue("type") === "draw" ? (
|
|
||||||
<Checkbox.Group>
|
|
||||||
<Row>
|
|
||||||
<Col span={8}>
|
|
||||||
<Checkbox value="LAB" style={{ lineHeight: "32px" }}>
|
|
||||||
Body
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<Checkbox value="LAR" style={{ lineHeight: "32px" }}>
|
|
||||||
Refinish
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<Checkbox value="LAM" style={{ lineHeight: "32px" }}>
|
|
||||||
Mechanical
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<Checkbox value="LAF" style={{ lineHeight: "32px" }}>
|
|
||||||
Frame
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
<Col span={8}>
|
|
||||||
<Checkbox value="LAG" style={{ lineHeight: "32px" }}>
|
|
||||||
Glass
|
|
||||||
</Checkbox>
|
|
||||||
</Col>
|
|
||||||
</Row>
|
|
||||||
</Checkbox.Group>
|
|
||||||
) : (
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value="LAB">Body</Radio>
|
|
||||||
|
|
||||||
<Radio value="LAR">Refinish</Radio>
|
|
||||||
|
|
||||||
<Radio value="LAM">Mechanical</Radio>
|
|
||||||
|
|
||||||
<Radio value="LAF">Frame</Radio>
|
|
||||||
|
|
||||||
<Radio value="LAG">Glass</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item name="percent">
|
|
||||||
<InputNumber min={0} max={100} precision={1} addonAfter="%" />
|
|
||||||
</Form.Item>
|
|
||||||
<Button htmlType="submit">Calculate</Button>
|
|
||||||
</Form>
|
|
||||||
</Spin>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Popover
|
|
||||||
content={popContent}
|
|
||||||
trigger={["click"]}
|
|
||||||
open={visible}
|
|
||||||
onOpenChange={handleOpenChange}
|
|
||||||
placement="right"
|
|
||||||
destroyTooltipOnHide
|
|
||||||
>
|
|
||||||
<Button onClick={(e) => e.preventDefault()}>
|
|
||||||
<Space>
|
|
||||||
Draw Calculator
|
|
||||||
<DownOutlined />
|
|
||||||
</Space>
|
|
||||||
</Button>
|
|
||||||
</Popover>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,277 +0,0 @@
|
|||||||
import { useQuery } from "@apollo/client";
|
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
Form,
|
|
||||||
InputNumber,
|
|
||||||
Modal,
|
|
||||||
Radio,
|
|
||||||
Select,
|
|
||||||
Space,
|
|
||||||
Table,
|
|
||||||
Typography,
|
|
||||||
} from "antd";
|
|
||||||
import Dinero from "dinero.js";
|
|
||||||
import React, { useState } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { connect } from "react-redux";
|
|
||||||
import { createStructuredSelector } from "reselect";
|
|
||||||
import { GET_JOB_INFO_DRAW_CALCULATIONS } from "../../graphql/jobs-lines.queries";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
|
||||||
import JobSearchSelectComponent from "../job-search-select/job-search-select.component";
|
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
|
||||||
bodyshop: selectBodyshop,
|
|
||||||
});
|
|
||||||
const mapDispatchToProps = (dispatch) => ({});
|
|
||||||
export default connect(
|
|
||||||
mapStateToProps,
|
|
||||||
mapDispatchToProps
|
|
||||||
)(TimeTicketListTeamPay);
|
|
||||||
|
|
||||||
export function TimeTicketListTeamPay({ bodyshop, context, actions }) {
|
|
||||||
//const { refetch } = actions;
|
|
||||||
const { jobId } = context;
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const [form] = Form.useForm();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const {
|
|
||||||
//loading,
|
|
||||||
data: lineTicketData,
|
|
||||||
} = useQuery(GET_JOB_INFO_DRAW_CALCULATIONS, {
|
|
||||||
variables: { id: jobId },
|
|
||||||
skip: !jobId,
|
|
||||||
fetchPolicy: "network-only",
|
|
||||||
nextFetchPolicy: "network-only",
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleOk = () => {
|
|
||||||
setVisible(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Modal
|
|
||||||
width={"80%"}
|
|
||||||
open={visible}
|
|
||||||
destroyOnClose
|
|
||||||
onOk={handleOk}
|
|
||||||
onCancel={() => setVisible(false)}
|
|
||||||
>
|
|
||||||
<Form layout="vertical" form={form} initialValues={{ jobid: jobId }}>
|
|
||||||
<LayoutFormRow grow noDivider>
|
|
||||||
<Form.Item shouldUpdate>
|
|
||||||
{() => (
|
|
||||||
<Form.Item
|
|
||||||
name="jobid"
|
|
||||||
label={t("timetickets.fields.ro_number")}
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: !(
|
|
||||||
form.getFieldValue("cost_center") ===
|
|
||||||
"timetickets.labels.shift"
|
|
||||||
),
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<JobSearchSelectComponent
|
|
||||||
convertedOnly={!bodyshop.tt_allow_post_to_invoiced}
|
|
||||||
notExported={!bodyshop.tt_allow_post_to_invoiced}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label={t("timetickets.fields.date")}
|
|
||||||
name="date"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<FormDatePicker />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
|
|
||||||
<LayoutFormRow grow noDivider>
|
|
||||||
<Form.Item name="team" label="Team">
|
|
||||||
<Select
|
|
||||||
options={Teams.map((team) => ({
|
|
||||||
value: team.name,
|
|
||||||
label: team.name,
|
|
||||||
}))}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item name="hourstype">
|
|
||||||
<Radio.Group>
|
|
||||||
<Radio value="LAB">Body</Radio>
|
|
||||||
<Radio value="LAR">Refinish</Radio>
|
|
||||||
<Radio value="LAM">Mechanical</Radio>
|
|
||||||
<Radio value="LAF">Frame</Radio>
|
|
||||||
<Radio value="LAG">Glass</Radio>
|
|
||||||
</Radio.Group>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item name="percent">
|
|
||||||
<InputNumber min={0} max={100} precision={1} addonAfter="%" />
|
|
||||||
</Form.Item>
|
|
||||||
</LayoutFormRow>
|
|
||||||
|
|
||||||
<Form.Item shouldUpdate noStyle>
|
|
||||||
{({ getFieldsValue }) => {
|
|
||||||
const formData = getFieldsValue();
|
|
||||||
|
|
||||||
let data = [];
|
|
||||||
let eligibleHours = 0;
|
|
||||||
const theTeam = Teams.find((team) => team.name === formData.team);
|
|
||||||
if (theTeam) {
|
|
||||||
eligibleHours =
|
|
||||||
lineTicketData.joblines.reduce(
|
|
||||||
(acc, val) =>
|
|
||||||
acc +
|
|
||||||
(formData.hourstype === val.mod_lbr_ty
|
|
||||||
? val.mod_lb_hrs
|
|
||||||
: 0),
|
|
||||||
0
|
|
||||||
) * (formData.percent / 100 || 0);
|
|
||||||
|
|
||||||
data = theTeam.employees.map((e) => {
|
|
||||||
return {
|
|
||||||
employeeid: e.employeeid,
|
|
||||||
percentage: e.percentage,
|
|
||||||
rate: e.rates[formData.hourstype],
|
|
||||||
cost_center:
|
|
||||||
bodyshop.md_responsibility_centers.defaults.costs[
|
|
||||||
formData.hourstype
|
|
||||||
],
|
|
||||||
productivehrs:
|
|
||||||
Math.round(eligibleHours * 100 * (e.percentage / 100)) /
|
|
||||||
100,
|
|
||||||
pay: Dinero({
|
|
||||||
amount: Math.round(
|
|
||||||
(e.rates[formData.hourstype] || 0) * 100
|
|
||||||
),
|
|
||||||
})
|
|
||||||
.multiply(
|
|
||||||
Math.round(eligibleHours * 100 * (e.percentage / 100)) /
|
|
||||||
100
|
|
||||||
)
|
|
||||||
.toFormat("$0.00"),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Table
|
|
||||||
dataSource={data}
|
|
||||||
rowKey={"employeeid"}
|
|
||||||
title={() => (
|
|
||||||
<Space>
|
|
||||||
<Typography.Title level={4}>
|
|
||||||
Tickets to be Created
|
|
||||||
</Typography.Title>
|
|
||||||
<span>{`(${eligibleHours} hours to split)`}</span>
|
|
||||||
</Space>
|
|
||||||
)}
|
|
||||||
columns={[
|
|
||||||
{
|
|
||||||
title: t("timetickets.fields.employee"),
|
|
||||||
dataIndex: "employee",
|
|
||||||
key: "employee",
|
|
||||||
render: (text, record) => {
|
|
||||||
const emp = bodyshop.employees.find(
|
|
||||||
(e) => e.id === record.employeeid
|
|
||||||
);
|
|
||||||
return `${emp?.first_name} ${emp?.last_name}`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("timetickets.fields.cost_center"),
|
|
||||||
dataIndex: "cost_center",
|
|
||||||
key: "cost_center",
|
|
||||||
|
|
||||||
render: (text, record) =>
|
|
||||||
record.cost_center === "timetickets.labels.shift"
|
|
||||||
? t(record.cost_center)
|
|
||||||
: record.cost_center,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: t("timetickets.fields.productivehrs"),
|
|
||||||
dataIndex: "productivehrs",
|
|
||||||
key: "productivehrs",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Percentage",
|
|
||||||
dataIndex: "percentage",
|
|
||||||
key: "percentage",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Rate",
|
|
||||||
dataIndex: "rate",
|
|
||||||
key: "rate",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "Pay",
|
|
||||||
dataIndex: "pay",
|
|
||||||
key: "pay",
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
<Button onClick={() => setVisible(true)}>Assign Team Pay </Button>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Teams = [
|
|
||||||
{
|
|
||||||
name: "Team A",
|
|
||||||
employees: [
|
|
||||||
{
|
|
||||||
employeeid: "9f1bdc23-8dc2-4b6a-8ca1-5f83a6fdcc22",
|
|
||||||
percentage: 50,
|
|
||||||
rates: {
|
|
||||||
LAB: 10,
|
|
||||||
LAR: 15,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
employeeid: "201db66c-96c7-41ec-bed4-76842ba93087",
|
|
||||||
percentage: 50,
|
|
||||||
rates: {
|
|
||||||
LAB: 20,
|
|
||||||
LAR: 25,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Team B",
|
|
||||||
employees: [
|
|
||||||
{
|
|
||||||
employeeid: "9f1bdc23-8dc2-4b6a-8ca1-5f83a6fdcc22",
|
|
||||||
percentage: 75,
|
|
||||||
rates: {
|
|
||||||
LAB: 100,
|
|
||||||
LAR: 150,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
employeeid: "201db66c-96c7-41ec-bed4-76842ba93087",
|
|
||||||
percentage: 25,
|
|
||||||
rates: {
|
|
||||||
LAB: 200,
|
|
||||||
LAR: 250,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user