IO-733 IO-594 IO-739
This commit is contained in:
@@ -1,7 +1,39 @@
|
||||
// craco.config.js
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const CracoLessPlugin = require("craco-less");
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
{
|
||||
plugin: CracoLessPlugin,
|
||||
options: {
|
||||
lessLoaderOptions: {
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
...(process.env.NODE_ENV === "development"
|
||||
? { "@primary-color": "#a51d1d" }
|
||||
: { "@primary-color": "#1DA57A" }),
|
||||
// "@primary-color": " #1890ff", // primary color for all components
|
||||
// "@link-color": "#1890ff", // link color
|
||||
// "@success-color": "#52c41a", // success state color
|
||||
// "@warning-color": "#faad14", // warning state color
|
||||
// "@error-color": "#f5222d", // error state color
|
||||
// "@font-size-base": "14px", // major text font size
|
||||
// " @heading-color": "rgba(0, 0, 0, 0.85)", // heading text color
|
||||
// "@text-color": "rgba(0, 0, 0, 0.65)", // major text color
|
||||
// "@text-color-secondary": "rgba(0, 0, 0, 0.45)", // secondary text color
|
||||
// "@disabled-color": "rgba(0, 0, 0, 0.25)", // disable state color
|
||||
// "@border-radius-base": "2px", // major border radius
|
||||
// "@border-color-base": "#d9d9d9", // major border color
|
||||
// "@box-shadow-base":
|
||||
// "0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 6px 16px 0 rgba(0, 0, 0, 0.08),0 9px 28px 8px rgba(0, 0, 0, 0.05); // major shadow for layers }",
|
||||
},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
webpack: {
|
||||
configure: (webpackConfig) => ({
|
||||
...webpackConfig,
|
||||
|
||||
106
client/package-lock.json
generated
106
client/package-lock.json
generated
@@ -1593,9 +1593,9 @@
|
||||
"integrity": "sha512-wYn6r8zVZyQJ6rQaALBEln5B1pzxb9shV5Ef97kTvn6yVGrqyXVnDqnU24MXnFubR+rZjBY9NWuxX3FB2sTsjg=="
|
||||
},
|
||||
"@grpc/grpc-js": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.8.tgz",
|
||||
"integrity": "sha512-9C1xiCbnYe/3OFpSuRqz2JgFSOxv6+SlqFhXgRC1nHfXYbLnXvtmsI/NpaMs6k9ZNyV4gyaOOh5Z4McfegQGew==",
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.2.9.tgz",
|
||||
"integrity": "sha512-hUNM2G8EP/dHN6cLFk8BXV6ae8zR7A0TPXGCERdwUiJv9yb6BL7FrTb73gUrrx4Dje6tUeomH6urSDEDz5mE7g==",
|
||||
"requires": {
|
||||
"@types/node": ">=12.12.47",
|
||||
"google-auth-library": "^6.1.1",
|
||||
@@ -2526,9 +2526,9 @@
|
||||
"integrity": "sha512-XExJS3cLqgrmNBIP3bBw6+1oQ1ksGjFh0+oClDKFYpCCqx/hlqwWO5KO/S63fzUo67SxI9dMrF0y5T/Ey7h8Zw=="
|
||||
},
|
||||
"@stripe/react-stripe-js": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.3.0.tgz",
|
||||
"integrity": "sha512-880MjCEEcU4sQNNJxawjFhLrGUbnV/jHbfZsrL7nAUpKZRBtoSPw7DFlEYRt1v0NimtxCkMmCFUSGxRynn990A==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.4.0.tgz",
|
||||
"integrity": "sha512-Pz5QmG8PgJ3pi8gOWxlngk+ns63p2L1Ds192fn55ykZNRKfGz3G6sfssUVThHn/NAt2Hp1eCEsy/hvlKnXJI6g==",
|
||||
"requires": {
|
||||
"prop-types": "^15.7.2"
|
||||
}
|
||||
@@ -2697,20 +2697,20 @@
|
||||
}
|
||||
},
|
||||
"@tanem/react-nprogress": {
|
||||
"version": "3.0.56",
|
||||
"resolved": "https://registry.npmjs.org/@tanem/react-nprogress/-/react-nprogress-3.0.56.tgz",
|
||||
"integrity": "sha512-Z7Rf/6da3noFqNKKURsIt5BodHi02YAPI6emYMm1qC0orubO06huDRbXvdsp/vnz0B4BJwd11UVbSfVS+seSLw==",
|
||||
"version": "3.0.57",
|
||||
"resolved": "https://registry.npmjs.org/@tanem/react-nprogress/-/react-nprogress-3.0.57.tgz",
|
||||
"integrity": "sha512-hYNDAENoAQK3LttNs4IfWF4ByLoAaxJ/rxBTXeTR+x4kk5lLdRBqR0rcU6XrX0oyx+mXLqJk5IXterui6usBfg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.12.13",
|
||||
"@babel/runtime": "^7.12.18",
|
||||
"hoist-non-react-statics": "^3.3.2",
|
||||
"prop-types": "^15.7.2",
|
||||
"react-use": "^15.3.8"
|
||||
}
|
||||
},
|
||||
"@tinymce/tinymce-react": {
|
||||
"version": "3.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@tinymce/tinymce-react/-/tinymce-react-3.10.2.tgz",
|
||||
"integrity": "sha512-PcCGYuepfTidkNwSaTyEg5nVRrqQa9KJDBiCrfb7xRCkoNXeYKY4lFhnT84AcBe9BEcJ4HnCXoqCTnjOaF/R2w==",
|
||||
"version": "3.10.3",
|
||||
"resolved": "https://registry.npmjs.org/@tinymce/tinymce-react/-/tinymce-react-3.10.3.tgz",
|
||||
"integrity": "sha512-Rn7dKd7+0IzDLqYAj+GzOzIZPDJ5F/ojviRk0HH7MvKLZWtAj+sBQP5Xv8SFGlxA9B6Cj1Rpv+Zyhuj3lo9p3w==",
|
||||
"requires": {
|
||||
"prop-types": "^15.6.2",
|
||||
"tinymce": "^5.7.0"
|
||||
@@ -4968,6 +4968,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"clone": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
|
||||
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18="
|
||||
},
|
||||
"clsx": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz",
|
||||
@@ -5240,6 +5245,14 @@
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||
},
|
||||
"copy-anything": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.3.tgz",
|
||||
"integrity": "sha512-GK6QUtisv4fNS+XcI7shX0Gx9ORg7QqIznyfho79JTnX1XhLiyZHfftvGiziqzRiEi/Bjhgpi+D2o7HxJFPnDQ==",
|
||||
"requires": {
|
||||
"is-what": "^3.12.0"
|
||||
}
|
||||
},
|
||||
"copy-concurrently": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
|
||||
@@ -5309,6 +5322,15 @@
|
||||
"yaml": "^1.7.2"
|
||||
}
|
||||
},
|
||||
"craco-less": {
|
||||
"version": "1.17.1",
|
||||
"resolved": "https://registry.npmjs.org/craco-less/-/craco-less-1.17.1.tgz",
|
||||
"integrity": "sha512-T6V1aF3+eQZ22gUigHInX/i+ExPbWrnmdAhtuEXc4mOyhneDifmEzZFseq/BdRy1aUEs9s4z26jTxP+1I6P//g==",
|
||||
"requires": {
|
||||
"less": "^3.11.1",
|
||||
"less-loader": "^6.1.0"
|
||||
}
|
||||
},
|
||||
"create-ecdh": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
|
||||
@@ -7766,9 +7788,9 @@
|
||||
}
|
||||
},
|
||||
"firebase": {
|
||||
"version": "8.2.9",
|
||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-8.2.9.tgz",
|
||||
"integrity": "sha512-0QNPgKre9OHuBHwXKIs1wW1aPrO0wx1si3JMA46vPOmx/vkpQQD2OCxdZdVUc+y5u9d/yNMvVBR6j85H0O15rA==",
|
||||
"version": "8.2.10",
|
||||
"resolved": "https://registry.npmjs.org/firebase/-/firebase-8.2.10.tgz",
|
||||
"integrity": "sha512-fGDrVWEDbFf4uaRhOMmbLf4CfW3D98GsMsbnvfd/5lPw5wTpUUcVjHyhXxcB+qfu66WeNW5kEKlEKLJmQXTkYw==",
|
||||
"requires": {
|
||||
"@firebase/analytics": "0.6.4",
|
||||
"@firebase/app": "0.6.15",
|
||||
@@ -8831,6 +8853,12 @@
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
|
||||
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg=="
|
||||
},
|
||||
"image-size": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
|
||||
"integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
|
||||
"optional": true
|
||||
},
|
||||
"immer": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/immer/-/immer-8.0.1.tgz",
|
||||
@@ -9228,6 +9256,11 @@
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||
},
|
||||
"is-what": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz",
|
||||
"integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA=="
|
||||
},
|
||||
"is-windows": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
|
||||
@@ -10982,6 +11015,41 @@
|
||||
"webpack-sources": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"less": {
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/less/-/less-3.13.1.tgz",
|
||||
"integrity": "sha512-SwA1aQXGUvp+P5XdZslUOhhLnClSLIjWvJhmd+Vgib5BFIr9lMNlQwmwUNOjXThF/A0x+MCYYPeWEfeWiLRnTw==",
|
||||
"requires": {
|
||||
"copy-anything": "^2.0.1",
|
||||
"errno": "^0.1.1",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"image-size": "~0.5.0",
|
||||
"make-dir": "^2.1.0",
|
||||
"mime": "^1.4.1",
|
||||
"native-request": "^1.0.5",
|
||||
"source-map": "~0.6.0",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"less-loader": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/less-loader/-/less-loader-6.2.0.tgz",
|
||||
"integrity": "sha512-Cl5h95/Pz/PWub/tCBgT1oNMFeH1WTD33piG80jn5jr12T4XbxZcjThwNXDQ7AG649WEynuIzO4b0+2Tn9Qolg==",
|
||||
"requires": {
|
||||
"clone": "^2.1.2",
|
||||
"less": "^3.11.3",
|
||||
"loader-utils": "^2.0.0",
|
||||
"schema-utils": "^2.7.0"
|
||||
}
|
||||
},
|
||||
"leven": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
|
||||
@@ -11565,6 +11633,12 @@
|
||||
"to-regex": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"native-request": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/native-request/-/native-request-1.0.8.tgz",
|
||||
"integrity": "sha512-vU2JojJVelUGp6jRcLwToPoWGxSx23z/0iX+I77J3Ht17rf2INGjrhOoQnjVo60nQd8wVsgzKkPfRXBiVdD2ag==",
|
||||
"optional": true
|
||||
},
|
||||
"native-url": {
|
||||
"version": "0.2.6",
|
||||
"resolved": "https://registry.npmjs.org/native-url/-/native-url-0.2.6.tgz",
|
||||
|
||||
@@ -10,16 +10,17 @@
|
||||
"@lourenci/react-kanban": "^2.1.0",
|
||||
"@sentry/react": "^6.2.0",
|
||||
"@sentry/tracing": "^6.2.0",
|
||||
"@stripe/react-stripe-js": "^1.2.2",
|
||||
"@stripe/react-stripe-js": "^1.4.0",
|
||||
"@stripe/stripe-js": "^1.12.1",
|
||||
"@tanem/react-nprogress": "^3.0.56",
|
||||
"@tinymce/tinymce-react": "^3.10.2",
|
||||
"@tanem/react-nprogress": "^3.0.57",
|
||||
"@tinymce/tinymce-react": "^3.10.3",
|
||||
"antd": "^4.12.3",
|
||||
"apollo-link-logger": "^2.0.0",
|
||||
"axios": "^0.21.1",
|
||||
"craco-less": "^1.17.1",
|
||||
"dinero.js": "^1.8.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"firebase": "^8.2.9",
|
||||
"firebase": "^8.2.10",
|
||||
"graphql": "^15.5.0",
|
||||
"i18next": "^19.8.9",
|
||||
"i18next-browser-languagedetector": "^6.0.1",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import "antd/dist/antd.css";
|
||||
|
||||
import React, { lazy, Suspense, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useApolloClient, useMutation } from "@apollo/client";
|
||||
import { Button, Form, Modal, notification } from "antd";
|
||||
import _ from "lodash";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import React, { useEffect, useState, useMemo } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
@@ -197,9 +197,28 @@ function BillEnterModalContainer({
|
||||
if (enterAgain) form.submit();
|
||||
}, [enterAgain, form]);
|
||||
|
||||
const formValues = useMemo(() => {
|
||||
return {
|
||||
...billEnterModal.context.bill,
|
||||
jobid:
|
||||
(billEnterModal.context.job && billEnterModal.context.job.id) || null,
|
||||
federal_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.federal_tax_rate) ||
|
||||
0,
|
||||
state_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.state_tax_rate) ||
|
||||
0,
|
||||
local_tax_rate:
|
||||
(bodyshop.bill_tax_rates && bodyshop.bill_tax_rates.local_tax_rate) ||
|
||||
0,
|
||||
};
|
||||
}, [billEnterModal, bodyshop]);
|
||||
|
||||
useEffect(() => {
|
||||
if (billEnterModal.visible) form.resetFields();
|
||||
}, [billEnterModal.visible, form]);
|
||||
if (billEnterModal.visible) {
|
||||
form.setFieldsValue(formValues);
|
||||
}
|
||||
}, [billEnterModal.visible, form, formValues]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
@@ -239,24 +258,7 @@ function BillEnterModalContainer({
|
||||
onFinishFailed={() => {
|
||||
setEnterAgain(false);
|
||||
}}
|
||||
initialValues={{
|
||||
...billEnterModal.context.bill,
|
||||
jobid:
|
||||
(billEnterModal.context.job && billEnterModal.context.job.id) ||
|
||||
null,
|
||||
federal_tax_rate:
|
||||
(bodyshop.bill_tax_rates &&
|
||||
bodyshop.bill_tax_rates.federal_tax_rate) ||
|
||||
0,
|
||||
state_tax_rate:
|
||||
(bodyshop.bill_tax_rates &&
|
||||
bodyshop.bill_tax_rates.state_tax_rate) ||
|
||||
0,
|
||||
local_tax_rate:
|
||||
(bodyshop.bill_tax_rates &&
|
||||
bodyshop.bill_tax_rates.local_tax_rate) ||
|
||||
0,
|
||||
}}
|
||||
initialValues={formValues}
|
||||
>
|
||||
<BillFormContainer
|
||||
form={form}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
} from "antd";
|
||||
import React from "react";
|
||||
@@ -48,6 +49,7 @@ export function BillEnterModalLinesComponent({
|
||||
<div style={{ display: "flex", alignItems: "center" }}>
|
||||
<LayoutFormRow style={{ flex: 1 }} grow>
|
||||
<Form.Item
|
||||
span={8}
|
||||
label={t("billlines.fields.jobline")}
|
||||
key={`${index}joblinename`}
|
||||
name={[field.name, "joblineid"]}
|
||||
@@ -154,37 +156,38 @@ export function BillEnterModalLinesComponent({
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.actual_cost")}
|
||||
key={`${index}actual_cost`}
|
||||
name={[field.name, "actual_cost"]}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} disabled={disabled} />
|
||||
</Form.Item>
|
||||
<Form.Item shouldUpdate>
|
||||
{() => {
|
||||
const line = getFieldsValue(["billlines"]).billlines[
|
||||
index
|
||||
];
|
||||
if (!!!line) return null;
|
||||
const lineDiscount = (
|
||||
1 -
|
||||
Math.round(
|
||||
(line.actual_cost / line.actual_price) * 100
|
||||
) /
|
||||
100
|
||||
).toPrecision(2);
|
||||
<div>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.actual_cost")}
|
||||
key={`${index}actual_cost`}
|
||||
name={[field.name, "actual_cost"]}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t("general.validation.required"),
|
||||
},
|
||||
]}
|
||||
>
|
||||
<CurrencyInput min={0} disabled={disabled} />
|
||||
</Form.Item>
|
||||
<Form.Item shouldUpdate>
|
||||
{() => {
|
||||
const line = getFieldsValue(["billlines"])
|
||||
.billlines[index];
|
||||
if (!!!line) return null;
|
||||
const lineDiscount = (
|
||||
1 -
|
||||
Math.round(
|
||||
(line.actual_cost / line.actual_price) * 100
|
||||
) /
|
||||
100
|
||||
).toPrecision(2);
|
||||
|
||||
if (lineDiscount - discount === 0) return <div />;
|
||||
return <WarningOutlined style={{ color: "red" }} />;
|
||||
}}
|
||||
</Form.Item>
|
||||
if (lineDiscount - discount === 0) return <div />;
|
||||
return <WarningOutlined style={{ color: "red" }} />;
|
||||
}}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.cost_center")}
|
||||
key={`${index}cost_center`}
|
||||
@@ -204,30 +207,45 @@ export function BillEnterModalLinesComponent({
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Space flex>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.federal_tax_applicable")}
|
||||
key={`${index}fedtax`}
|
||||
initialValue={true}
|
||||
valuePropName="checked"
|
||||
name={[field.name, "applicable_taxes", "federal"]}
|
||||
>
|
||||
<Switch disabled={disabled} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.state_tax_applicable")}
|
||||
key={`${index}statetax`}
|
||||
valuePropName="checked"
|
||||
name={[field.name, "applicable_taxes", "state"]}
|
||||
>
|
||||
<Switch disabled={disabled} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.local_tax_applicable")}
|
||||
key={`${index}localtax`}
|
||||
valuePropName="checked"
|
||||
name={[field.name, "applicable_taxes", "local"]}
|
||||
>
|
||||
<Switch disabled={disabled} />
|
||||
</Form.Item>
|
||||
</Space>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.federal_tax_applicable")}
|
||||
key={`${index}fedtax`}
|
||||
initialValue={true}
|
||||
valuePropName="checked"
|
||||
name={[field.name, "applicable_taxes", "federal"]}
|
||||
label={t("billlines.fields.location")}
|
||||
key={`${index}location`}
|
||||
name={[field.name, "location"]}
|
||||
>
|
||||
<Switch disabled={disabled} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.state_tax_applicable")}
|
||||
key={`${index}statetax`}
|
||||
valuePropName="checked"
|
||||
name={[field.name, "applicable_taxes", "state"]}
|
||||
>
|
||||
<Switch disabled={disabled} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.local_tax_applicable")}
|
||||
key={`${index}localtax`}
|
||||
valuePropName="checked"
|
||||
name={[field.name, "applicable_taxes", "local"]}
|
||||
>
|
||||
<Switch disabled={disabled} />
|
||||
<Select style={{ width: "10rem" }} disabled={disabled}>
|
||||
{bodyshop.md_parts_locations.map((loc, idx) => (
|
||||
<Select.Option key={idx} value={loc}>
|
||||
{loc}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("billlines.labels.deductfromlabor")}
|
||||
@@ -335,19 +353,6 @@ export function BillEnterModalLinesComponent({
|
||||
return <span />;
|
||||
}}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("billlines.fields.location")}
|
||||
key={`${index}location`}
|
||||
name={[field.name, "location"]}
|
||||
>
|
||||
<Select style={{ width: "10rem" }} disabled={disabled}>
|
||||
{bodyshop.md_parts_locations.map((loc, idx) => (
|
||||
<Select.Option key={idx} value={loc}>
|
||||
{loc}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<FormListMoveArrows
|
||||
move={move}
|
||||
|
||||
@@ -46,23 +46,17 @@ const BillLineSearchSelect = (
|
||||
line_desc={item.line_desc}
|
||||
part_qty={item.part_qty}
|
||||
>
|
||||
<Row justify="center" align="middle">
|
||||
<Col span={12}>{item.line_desc}</Col>
|
||||
<Col span={8}>
|
||||
{item.oem_partno ? (
|
||||
<Tag color="blue">{item.oem_partno}</Tag>
|
||||
) : null}
|
||||
</Col>
|
||||
<Col span={4}>
|
||||
{item.act_price ? (
|
||||
<Tag color="green">
|
||||
<CurrencyFormatter>
|
||||
{item.act_price || 0}
|
||||
</CurrencyFormatter>
|
||||
</Tag>
|
||||
) : null}
|
||||
</Col>
|
||||
</Row>
|
||||
<div className="imex-flex-row">
|
||||
<div style={{ flex: 1 }}>{item.line_desc}</div>
|
||||
{item.oem_partno ? (
|
||||
<Tag color="blue">{item.oem_partno}</Tag>
|
||||
) : null}
|
||||
{item.act_price ? (
|
||||
<Tag color="green">
|
||||
<CurrencyFormatter>{item.act_price || 0}</CurrencyFormatter>
|
||||
</Tag>
|
||||
) : null}
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { GET_JOB_LINES_BY_PK } from "../../graphql/jobs-lines.queries";
|
||||
import { GET_ALL_JOBLINES_BY_PK } from "../../graphql/jobs-lines.queries";
|
||||
import { gql } from "@apollo/client";
|
||||
import _ from "lodash";
|
||||
|
||||
@@ -8,7 +8,7 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
|
||||
const {
|
||||
data: { joblines: existingLinesFromDb },
|
||||
} = await client.query({
|
||||
query: GET_JOB_LINES_BY_PK,
|
||||
query: GET_ALL_JOBLINES_BY_PK,
|
||||
variables: { id: jobId },
|
||||
});
|
||||
const existingLines = _.cloneDeep(existingLinesFromDb);
|
||||
|
||||
@@ -10,6 +10,7 @@ export default function PartnerPingComponent() {
|
||||
// Create an scoped async function in the hook
|
||||
async function checkPartnerStatus() {
|
||||
try {
|
||||
if (process.env.NODE_ENV === "development") return;
|
||||
const PartnerResponse = await axios.post("http://localhost:1337/ping/");
|
||||
const { appver, qbpath } = PartnerResponse.data;
|
||||
console.log({ appver, qbpath });
|
||||
|
||||
@@ -146,7 +146,6 @@ export default function TimeTicketModalComponent({
|
||||
}
|
||||
|
||||
function LaborAllocationContainer({ jobid }) {
|
||||
console.log("jobid", jobid);
|
||||
const { loading, data: lineTicketData } = useQuery(GET_LINE_TICKET_BY_PK, {
|
||||
variables: { id: jobid },
|
||||
skip: !jobid,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Col, Row, Select, Tag } from "antd";
|
||||
import React, { useEffect, useState, forwardRef } from "react";
|
||||
import { HeartOutlined } from "@ant-design/icons";
|
||||
import { Select, Tag } from "antd";
|
||||
import React, { forwardRef, useEffect, useState } from "react";
|
||||
const { Option } = Select;
|
||||
|
||||
//To be used as a form element only.
|
||||
@@ -45,31 +45,22 @@ const VendorSearchSelect = (
|
||||
name={o.name}
|
||||
discount={o.discount}
|
||||
>
|
||||
<Row>
|
||||
<Col span={16}>{o.name}</Col>
|
||||
<Col span={4}>
|
||||
<HeartOutlined />
|
||||
</Col>
|
||||
{o.discount && (
|
||||
<Col span={4}>
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<div className="imex-flex-row">
|
||||
<div style={{ flex: 1 }}>{o.name}</div>
|
||||
<HeartOutlined />
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
{options
|
||||
? options.map((o) => (
|
||||
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
|
||||
<Row>
|
||||
<Col span={20}>{o.name}</Col>
|
||||
{o.discount && (
|
||||
<Col span={4}>
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
</Col>
|
||||
)}
|
||||
</Row>
|
||||
<div className="imex-flex-row" style={{ width: "100%" }}>
|
||||
<div style={{ flex: 1 }}>{o.name}</div>
|
||||
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { gql } from "@apollo/client";
|
||||
|
||||
export const GET_JOB_LINES_BY_PK = gql`
|
||||
query GET_JOB_LINES_BY_PK($id: uuid!) {
|
||||
export const GET_ALL_JOBLINES_BY_PK = gql`
|
||||
query GET_ALL_JOBLINES_BY_PK($id: uuid!) {
|
||||
joblines(where: { jobid: { _eq: $id } }, order_by: { line_no: asc }) {
|
||||
id
|
||||
line_no
|
||||
@@ -46,7 +46,7 @@ export const GET_LINE_TICKET_BY_PK = gql`
|
||||
id
|
||||
lbr_adjustments
|
||||
}
|
||||
joblines(where: { jobid: { _eq: $id } }) {
|
||||
joblines(where: { jobid: { _eq: $id }, removed: { _eq: false } }) {
|
||||
id
|
||||
line_desc
|
||||
part_type
|
||||
@@ -126,6 +126,7 @@ export const UPDATE_JOB_LINE = gql`
|
||||
notes
|
||||
location
|
||||
status
|
||||
removed
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -133,7 +134,7 @@ export const UPDATE_JOB_LINE = gql`
|
||||
|
||||
export const GET_JOB_LINES_TO_ENTER_BILL = gql`
|
||||
query GET_JOB_LINES_TO_ENTER_BILL($id: uuid!) {
|
||||
joblines(where: { jobid: { _eq: $id } }) {
|
||||
joblines(where: { jobid: { _eq: $id }, removed: { _eq: false } }) {
|
||||
id
|
||||
line_desc
|
||||
part_type
|
||||
|
||||
@@ -115,7 +115,6 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
||||
id
|
||||
status
|
||||
ro_number
|
||||
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
v_model_yr
|
||||
@@ -157,20 +156,27 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
||||
first_name
|
||||
last_name
|
||||
}
|
||||
partcount: joblines_aggregate {
|
||||
partcount: joblines_aggregate(where: { removed: { _eq: false } }) {
|
||||
nodes {
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" } }) {
|
||||
labhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
}
|
||||
}
|
||||
}
|
||||
larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" } }) {
|
||||
larhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
@@ -196,14 +202,22 @@ export const QUERY_LBR_HRS_BY_PK = gql`
|
||||
query QUERY_LBR_HRS_BY_PK($id: uuid!) {
|
||||
jobs_by_pk(id: $id) {
|
||||
id
|
||||
labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" } }) {
|
||||
labhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
}
|
||||
}
|
||||
}
|
||||
larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" } }) {
|
||||
larhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
@@ -484,7 +498,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
deliverchecklist
|
||||
voided
|
||||
ca_bc_pvrt
|
||||
joblines(where: { jobid: { _eq: $id } }, order_by: { line_no: asc }) {
|
||||
joblines(where: { removed: { _eq: false } }, order_by: { line_no: asc }) {
|
||||
id
|
||||
line_no
|
||||
unq_seq
|
||||
@@ -1072,7 +1086,7 @@ export const QUERY_ALL_JOB_FIELDS = gql`
|
||||
v_model_yr
|
||||
v_vin
|
||||
vehicleid
|
||||
joblines {
|
||||
joblines(where: { removed: { _eq: false } }) {
|
||||
act_price
|
||||
alt_co_id
|
||||
alt_overrd
|
||||
@@ -1136,7 +1150,6 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
|
||||
) {
|
||||
id
|
||||
ro_number
|
||||
|
||||
ownr_co_nm
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
@@ -1144,15 +1157,22 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
|
||||
v_make_desc
|
||||
v_model_desc
|
||||
scheduled_completion
|
||||
|
||||
labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" } }) {
|
||||
labhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
}
|
||||
}
|
||||
}
|
||||
larhrs: joblines_aggregate(where: { mod_lbr_ty: { _eq: "LAR" } }) {
|
||||
larhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
|
||||
@@ -16,7 +16,8 @@ import { persistor, store } from "./redux/store";
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
import "./translations/i18n";
|
||||
import "./utils/CleanAxios";
|
||||
|
||||
//import "antd/dist/antd.css";
|
||||
import "antd/dist/antd.less";
|
||||
require("dotenv").config();
|
||||
|
||||
Dinero.defaultCurrency = "CAD";
|
||||
|
||||
@@ -153,8 +153,6 @@ const { Content, Header } = Layout;
|
||||
|
||||
const stripePromise = new Promise((resolve, reject) => {
|
||||
client.query({ query: QUERY_STRIPE_ID }).then((resp) => {
|
||||
console.log(resp);
|
||||
|
||||
resolve(
|
||||
loadStripe(process.env.REACT_APP_STRIPE_PUBLIC_KEY, {
|
||||
stripeAccount:
|
||||
|
||||
3213
package-lock.json
generated
Normal file
3213
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,7 @@
|
||||
"xmlbuilder": "^15.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^5.3.0",
|
||||
"concurrently": "^6.0.0",
|
||||
"eslint": "^7.20.0",
|
||||
"eslint-plugin-promise": "^4.3.1",
|
||||
"source-map-explorer": "^2.5.2"
|
||||
|
||||
@@ -354,7 +354,7 @@ const StatusMapping = (status, md_ro_statuses) => {
|
||||
else if (status === default_invoiced || status === default_exported)
|
||||
return "CLO";
|
||||
else if (status === default_void) return "CLO";
|
||||
else if (md_ro_statuses.production_statuses.include(status)) return "IPR";
|
||||
else if (md_ro_statuses.production_statuses.includes(status)) return "IPR";
|
||||
else return "UNDEFINED";
|
||||
|
||||
// default: return "UNDEFINED"
|
||||
@@ -362,7 +362,7 @@ const StatusMapping = (status, md_ro_statuses) => {
|
||||
|
||||
const GenerateDetailLines = (line, statuses) => {
|
||||
const ret = {
|
||||
BackOrdered: line.status === statuses.default_bo ? "Y" : "N",
|
||||
BackOrdered: line.status === statuses.default_bo ? "1" : "0",
|
||||
Cost:
|
||||
line.billlines[0] &&
|
||||
(line.billlines[0].actual_cost * line.billlines[0].quantity).toFixed(2),
|
||||
|
||||
@@ -205,7 +205,7 @@ query QUERY_UPCOMING_APPOINTMENTS($now: timestamptz!, $jobId: uuid!) {
|
||||
target_touchtime
|
||||
workingdays
|
||||
}
|
||||
jobhrs: joblines_aggregate {
|
||||
jobhrs: joblines_aggregate(where: { removed: { _eq: false } }) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
@@ -219,7 +219,7 @@ query QUERY_UPCOMING_APPOINTMENTS($now: timestamptz!, $jobId: uuid!) {
|
||||
id
|
||||
block
|
||||
job {
|
||||
joblines_aggregate {
|
||||
joblines_aggregate(where: { removed: { _eq: false } }) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
@@ -231,14 +231,22 @@ query QUERY_UPCOMING_APPOINTMENTS($now: timestamptz!, $jobId: uuid!) {
|
||||
jobs(where: {inproduction: {_eq: true}}) {
|
||||
id
|
||||
scheduled_completion
|
||||
labhrs: joblines_aggregate(where: {mod_lbr_ty: {_neq: "LAR"}}) {
|
||||
labhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
}
|
||||
}
|
||||
}
|
||||
larhrs: joblines_aggregate(where: {mod_lbr_ty: {_eq: "LAR"}}) {
|
||||
larhrs: joblines_aggregate(
|
||||
where: {
|
||||
_and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }]
|
||||
}
|
||||
) {
|
||||
aggregate {
|
||||
sum {
|
||||
mod_lb_hrs
|
||||
@@ -532,7 +540,7 @@ exports.GET_JOB_BY_PK = ` query GET_JOB_BY_PK($id: uuid!) {
|
||||
deliverchecklist
|
||||
voided
|
||||
ca_bc_pvrt
|
||||
joblines{
|
||||
joblines(where: { removed: { _eq: false } }){
|
||||
id
|
||||
line_no
|
||||
unq_seq
|
||||
|
||||
Reference in New Issue
Block a user