Merge branch 'master-AIO' into feature/IO-2458-RO-Closer
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
<babeledit_project version="1.2" be_version="2.7.1">
|
||||
<babeledit_project be_version="2.7.1" version="1.2">
|
||||
<!--
|
||||
|
||||
BabelEdit project file
|
||||
@@ -14791,6 +14791,27 @@
|
||||
<folder_node>
|
||||
<name>titles</name>
|
||||
<children>
|
||||
<concept_node>
|
||||
<name>joblifecycle</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>labhours</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -37126,6 +37147,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>parts</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
<description></description>
|
||||
<comment></comment>
|
||||
<default_text></default_text>
|
||||
<translations>
|
||||
<translation>
|
||||
<language>en-US</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>es-MX</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
<translation>
|
||||
<language>fr-CA</language>
|
||||
<approved>false</approved>
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>partssublet</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
|
||||
1613
client/package-lock.json
generated
1613
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,48 +12,34 @@
|
||||
"@ant-design/pro-layout": "^7.17.16",
|
||||
"@apollo/client": "^3.8.10",
|
||||
"@asseinfo/react-kanban": "^2.2.0",
|
||||
"@craco/craco": "^7.1.0",
|
||||
"@fingerprintjs/fingerprintjs": "^4.2.2",
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^2.2.1",
|
||||
"@sentry/cli": "^2.28.6",
|
||||
"@sentry/react": "^7.104.0",
|
||||
"@sentry/tracing": "^7.104.0",
|
||||
"@splitsoftware/splitio-react": "^1.11.0",
|
||||
"@tanem/react-nprogress": "^5.0.51",
|
||||
"@vitejs/plugin-legacy": "^5.3.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@vitejs/plugin-react-refresh": "^1.3.6",
|
||||
"@vitejs/plugin-react-swc": "^3.6.0",
|
||||
"antd": "^5.14.2",
|
||||
"antd": "^5.15.3",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
"apollo-link-sentry": "^3.3.0",
|
||||
"axios": "^1.6.7",
|
||||
"consola": "^3.2.3",
|
||||
"dayjs": "^1.11.10",
|
||||
"dayjs-business-days2": "^1.2.2",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"esbuild": "^0.20.0",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^10.8.1",
|
||||
"graphql": "^16.6.0",
|
||||
"i18next": "^23.10.0",
|
||||
"i18next-browser-languagedetector": "^7.0.2",
|
||||
"jsoneditor": "^10.0.1",
|
||||
"jsreport-browser-client-dist": "^1.3.0",
|
||||
"libphonenumber-js": "^1.10.57",
|
||||
"logrocket": "^8.0.1",
|
||||
"markerjs2": "^2.32.0",
|
||||
"normalize-url": "^8.0.0",
|
||||
"phone": "^3.1.42",
|
||||
"preval.macro": "^5.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"query-string": "^9.0.0",
|
||||
"rc-queue-anim": "^2.0.0",
|
||||
"rc-scroll-anim": "^2.7.6",
|
||||
"react": "^18.2.0",
|
||||
"react-big-calendar": "^1.11.0",
|
||||
"react-color": "^2.19.3",
|
||||
@@ -65,16 +51,15 @@
|
||||
"react-i18next": "^14.0.5",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
"react-intersection-observer": "^9.8.1",
|
||||
"react-joyride": "^2.7.4",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-number-format": "^5.3.3",
|
||||
"react-product-fruits": "^2.2.6",
|
||||
"react-redux": "^9.1.0",
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-router-dom": "^6.22.2",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.5",
|
||||
"recharts": "^2.12.2",
|
||||
"redux": "^5.0.1",
|
||||
@@ -87,17 +72,15 @@
|
||||
"styled-components": "^6.1.8",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"userpilot": "^1.3.1",
|
||||
"vite-plugin-ejs": "^1.7.0",
|
||||
"vite-plugin-svgr": "^4.2.0",
|
||||
"web-vitals": "^3.5.2",
|
||||
"workbox-core": "^7.0.0",
|
||||
"workbox-expiration": "^7.0.0",
|
||||
"workbox-navigation-preload": "^7.0.0",
|
||||
"workbox-precaching": "^7.0.0",
|
||||
"workbox-routing": "^7.0.0",
|
||||
"workbox-strategies": "^7.0.0",
|
||||
"yauzl": "^3.1.1"
|
||||
"workbox-strategies": "^7.0.0"
|
||||
},
|
||||
"scripts": {
|
||||
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||
@@ -152,7 +135,6 @@
|
||||
"@testing-library/cypress": "^10.0.1",
|
||||
"browserslist": "^4.22.3",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"craco-less": "^3.0.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"cypress": "^13.6.6",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
|
||||
@@ -12,6 +12,12 @@ import App from "./App";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
||||
import themeProvider from "./themeProvider";
|
||||
import { Userpilot } from 'userpilot'
|
||||
|
||||
// Initialize Userpilot
|
||||
if(import.meta.env.DEV){
|
||||
Userpilot.initialize('NX-69145f08');
|
||||
}
|
||||
|
||||
dayjs.locale("en");
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ import "./App.styles.scss";
|
||||
import handleBeta from "../utils/betaHandler";
|
||||
import Eula from "../components/eula/eula.component";
|
||||
import InstanceRenderMgr from "../utils/instanceRenderMgr";
|
||||
import { ProductFruits } from 'react-product-fruits';
|
||||
|
||||
const ResetPassword = lazy(() =>
|
||||
import("../pages/reset-password/reset-password.component")
|
||||
);
|
||||
@@ -149,6 +151,7 @@ export function App({
|
||||
|
||||
// Any route that is not assigned and matched will default to the Landing Page component
|
||||
return (
|
||||
|
||||
<Suspense
|
||||
fallback={
|
||||
<LoadingSpinner
|
||||
@@ -160,6 +163,12 @@ export function App({
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ProductFruits //workspaceCode="aoJoEifvezYI0Z0P"
|
||||
language="en" user={{
|
||||
email: currentUser.email,
|
||||
username: currentUser.email,
|
||||
}} />
|
||||
|
||||
<Routes>
|
||||
<Route
|
||||
path="*"
|
||||
|
||||
BIN
client/src/assets/promanager/ProManagerLogo.gif
Normal file
BIN
client/src/assets/promanager/ProManagerLogo.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 38 KiB |
@@ -1,5 +1,5 @@
|
||||
import {useMutation, useQuery} from "@apollo/client";
|
||||
import {Button, Form, Popconfirm, Space} from "antd";
|
||||
import {Button, Divider, Form, Popconfirm, Space} from "antd";
|
||||
import dayjs from "../../utils/day";
|
||||
import queryString from "query-string";
|
||||
import React, {useState} from "react";
|
||||
@@ -203,7 +203,7 @@ export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail,
|
||||
layout="vertical"
|
||||
>
|
||||
<BillFormContainer form={form} billEdit disabled={exported}/>
|
||||
|
||||
<Divider orientation="left">{t("general.labels.media")}</Divider>
|
||||
{bodyshop.uselocalmediaserver ? (
|
||||
<JobsDocumentsLocalGallery
|
||||
job={{id: data ? data.bills_by_pk.jobid : null}}
|
||||
|
||||
@@ -173,7 +173,11 @@ export function BillDetailEditReturn({
|
||||
</Form>
|
||||
</Modal>
|
||||
<Button
|
||||
disabled={data.bills_by_pk.is_credit_memo || disabled}
|
||||
disabled={
|
||||
data.bills_by_pk.is_credit_memo ||
|
||||
data.bills_by_pk.isinhouse ||
|
||||
disabled
|
||||
}
|
||||
onClick={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
|
||||
@@ -172,6 +172,7 @@ function BillEnterModalContainer({
|
||||
],
|
||||
},
|
||||
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID", "GET_JOB_BY_PK"],
|
||||
awaitRefetchQueries: true
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
@@ -239,6 +240,7 @@ function BillEnterModalContainer({
|
||||
if (markPolReceived && markPolReceived.length > 0) {
|
||||
const r2 = await updatePartsOrderLines({
|
||||
variables: {partsLineIds: markPolReceived.map((p) => p.id)},
|
||||
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID" ],
|
||||
});
|
||||
if (!!r2.errors) {
|
||||
setLoading(false);
|
||||
@@ -373,12 +375,13 @@ function BillEnterModalContainer({
|
||||
});
|
||||
|
||||
if (enterAgain) {
|
||||
// form.resetFields();
|
||||
form.setFieldsValue({
|
||||
...formValues,
|
||||
billlines: [],
|
||||
});
|
||||
form.resetFields();
|
||||
form.resetFields();
|
||||
form.setFieldsValue({
|
||||
...formValues,
|
||||
vendorid:values.vendorid,
|
||||
billlines: [],
|
||||
});
|
||||
// form.resetFields();
|
||||
} else {
|
||||
toggleModalVisible();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -689,14 +689,14 @@ export function BillEnterModalLinesComponent({
|
||||
|
||||
formItemProps: (field) => {
|
||||
return {
|
||||
key: `${field.index}fedtax`,
|
||||
valuePropName: "checked",
|
||||
// initialValue: true,
|
||||
name: [
|
||||
field.name,
|
||||
"applicable_taxes",
|
||||
"federal",
|
||||
],
|
||||
key: `${field.index}fedtax`,
|
||||
valuePropName: 'checked',
|
||||
initialValue: InstanceRenderManager({
|
||||
imex: true,
|
||||
rome: false,
|
||||
promanager: false,
|
||||
}),
|
||||
name: [field.name, 'applicable_taxes', 'federal'],
|
||||
};
|
||||
},
|
||||
formInput: (record, index) => (
|
||||
|
||||
@@ -12,6 +12,7 @@ import "./chat-affix.styles.scss";
|
||||
export function ChatAffixContainer({bodyshop, chatVisible}) {
|
||||
const {t} = useTranslation();
|
||||
const client = useApolloClient();
|
||||
|
||||
useEffect(() => {
|
||||
if (!bodyshop || !bodyshop.messagingservicesid) return;
|
||||
|
||||
@@ -31,6 +32,7 @@ export function ChatAffixContainer({bodyshop, chatVisible}) {
|
||||
error
|
||||
);
|
||||
notification.open({
|
||||
key: 'fcm',
|
||||
type: "warning",
|
||||
message: t("general.errors.fcm"),
|
||||
btn: (
|
||||
@@ -62,7 +64,7 @@ export function ChatAffixContainer({bodyshop, chatVisible}) {
|
||||
|
||||
SubscribeToTopic();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [bodyshop]);
|
||||
|
||||
useEffect(() => {
|
||||
function handleMessage(payload) {
|
||||
|
||||
@@ -61,6 +61,10 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
value: "courtesycars.status.in",
|
||||
},
|
||||
{
|
||||
text: t("courtesycars.status.inservice"),
|
||||
value: "courtesycars.status.inservice",
|
||||
},
|
||||
{
|
||||
text: t("courtesycars.status.out"),
|
||||
value: "courtesycars.status.out",
|
||||
},
|
||||
@@ -73,7 +77,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
value: "courtesycars.status.leasereturn",
|
||||
},
|
||||
],
|
||||
onFilter: (value, record) => value.includes(record.status),
|
||||
onFilter: (value, record) => record.status === value,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||
render: (text, record) => {
|
||||
@@ -176,7 +180,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
title: t("courtesycars.fields.fuel"),
|
||||
dataIndex: "fuel",
|
||||
key: "fuel",
|
||||
sorter: (a, b) => alphaSort(a.fuel, b.fuel),
|
||||
sorter: (a, b) => a.fuel - b.fuel,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "fuel" && state.sortedInfo.order,
|
||||
render: (text, record) => {
|
||||
@@ -185,12 +189,14 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
return t("courtesycars.labels.fuel.full");
|
||||
case 88:
|
||||
return t("courtesycars.labels.fuel.78");
|
||||
case 63:
|
||||
case 75:
|
||||
return t("courtesycars.labels.fuel.34");
|
||||
case 63:
|
||||
return t("courtesycars.labels.fuel.58");
|
||||
case 50:
|
||||
return t("courtesycars.labels.fuel.12");
|
||||
case 38:
|
||||
return t("courtesycars.labels.fuel.34");
|
||||
return t("courtesycars.labels.fuel.38");
|
||||
case 25:
|
||||
return t("courtesycars.labels.fuel.14");
|
||||
case 13:
|
||||
|
||||
@@ -9,6 +9,7 @@ import axios from "axios";
|
||||
const fortyFiveDaysAgo = () => dayjs().subtract(45, 'day').toLocaleString();
|
||||
|
||||
export default function JobLifecycleDashboardComponent({data, bodyshop, ...cardProps}) {
|
||||
console.log("🚀 ~ JobLifecycleDashboardComponent ~ bodyshop:", bodyshop)
|
||||
const {t} = useTranslation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [lifecycleData, setLifecycleData] = useState(null);
|
||||
@@ -19,7 +20,7 @@ export default function JobLifecycleDashboardComponent({data, bodyshop, ...cardP
|
||||
setLoading(true);
|
||||
const response = await axios.post("/job/lifecycle", {
|
||||
jobids: data.job_lifecycle.map(x => x.id),
|
||||
statuses: bodyshop.md_order_statuses
|
||||
statuses: bodyshop.md_ro_statuses
|
||||
});
|
||||
setLifecycleData(response.data.durations);
|
||||
setLoading(false);
|
||||
|
||||
@@ -184,7 +184,7 @@ export function DashboardGridComponent({currentUser, bodyshop}) {
|
||||
}}
|
||||
onClick={() => handleRemoveComponent(item.i)}
|
||||
/>
|
||||
<TheComponent className="dashboard-card" data={dashboarddata}/>
|
||||
<TheComponent className="dashboard-card" bodyshop={bodyshop} data={dashboarddata}/>
|
||||
</LoadingSkeleton>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
import dayjs from "../../utils/day";
|
||||
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";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import dayjs from '../../utils/day';
|
||||
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';
|
||||
import AlertComponent from '../alert/alert.component';
|
||||
import InstanceRenderManager from '../../utils/instanceRenderMgr';
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
function FeatureWrapper({
|
||||
bodyshop,
|
||||
featureName,
|
||||
noauth,
|
||||
children,
|
||||
...restProps
|
||||
}) {
|
||||
function FeatureWrapper({ bodyshop, featureName, noauth, children, ...restProps }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
if (HasFeatureAccess({ featureName, bodyshop })) return children;
|
||||
@@ -25,7 +19,13 @@ function FeatureWrapper({
|
||||
return (
|
||||
noauth || (
|
||||
<AlertComponent
|
||||
message={t("general.messages.nofeatureaccess", {app: InstanceRenderManager({imex:'$t(titles.imexonline)', rome: '$t(titles.romeonline)', promanager: '$t(titles.promanager)'})})}
|
||||
message={t('general.messages.nofeatureaccess', {
|
||||
app: InstanceRenderManager({
|
||||
imex: '$t(titles.imexonline)',
|
||||
rome: '$t(titles.romeonline)',
|
||||
promanager: '$t(titles.promanager)',
|
||||
}),
|
||||
})}
|
||||
type="warning"
|
||||
/>
|
||||
)
|
||||
@@ -33,10 +33,7 @@ function FeatureWrapper({
|
||||
}
|
||||
|
||||
export function HasFeatureAccess({ featureName, bodyshop }) {
|
||||
return (
|
||||
bodyshop?.features.allAccess ||
|
||||
dayjs(bodyshop?.features[featureName]).isAfter(dayjs())
|
||||
);
|
||||
return bodyshop?.features.allAccess || dayjs(bodyshop?.features[featureName]).isAfter(dayjs());
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(FeatureWrapper);
|
||||
|
||||
@@ -5,6 +5,7 @@ import {useTranslation} from "react-i18next";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||
import "./job-bills-total.styles.scss";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
export default function JobBillsTotalComponent({
|
||||
loading,
|
||||
@@ -89,7 +90,7 @@ export default function JobBillsTotalComponent({
|
||||
.add(Dinero(totals.parts.sublets.total))
|
||||
.add(Dinero(totals.additional.shipping))
|
||||
.add(Dinero(totals.additional.towing))
|
||||
.add(Dinero(totals.additional.additionalCosts)); //TODO:AIO Additional costs were captured for Rome, but not imex. This may need to be evaluated?
|
||||
.add( InstanceRenderManager({imex: Dinero(), rome: Dinero(totals.additional.additionalCosts),promanager: "USE_ROME" })) ; // Additional costs were captured for Rome, but not imex.
|
||||
|
||||
const discrepancy = totalPartsSublet.subtract(billTotals);
|
||||
|
||||
|
||||
@@ -290,7 +290,7 @@ export function JobLinesComponent({
|
||||
key: 'location',
|
||||
render: (text, record) => <JobLineLocationPopup jobline={record} disabled={jobRO} />,
|
||||
},
|
||||
...(HasFeatureAccess({ featureName: 'bills' })
|
||||
...(HasFeatureAccess({ featureName: 'bills', bodyshop })
|
||||
? [
|
||||
{
|
||||
title: t('joblines.labels.billref'),
|
||||
|
||||
@@ -23,7 +23,6 @@ export function JobEmployeeAssignments({
|
||||
jobRO,
|
||||
body,
|
||||
refinish,
|
||||
|
||||
prep,
|
||||
csr,
|
||||
handleAdd,
|
||||
@@ -78,7 +77,7 @@ export function JobEmployeeAssignments({
|
||||
setVisibility(false);
|
||||
}}
|
||||
>
|
||||
Assign
|
||||
{t("allocations.actions.assign")}
|
||||
</Button>
|
||||
<Button onClick={() => setVisibility(false)}>Close</Button>
|
||||
</Space>
|
||||
|
||||
@@ -44,13 +44,13 @@ export function JobEmployeeAssignmentsContainer({
|
||||
});
|
||||
if (refetch) refetch();
|
||||
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobassignmentchange(operation, name),
|
||||
type: "jobassignmentchange",
|
||||
});
|
||||
|
||||
if (!!result.errors) {
|
||||
if (!!!result.errors) {
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobassignmentchange(operation, name),
|
||||
type: "jobassignmentchange",
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.assigning", {
|
||||
message: JSON.stringify(result.errors),
|
||||
@@ -68,19 +68,21 @@ export function JobEmployeeAssignmentsContainer({
|
||||
variables: {jobId: job.id, job: {[empAssignment]: null}},
|
||||
});
|
||||
|
||||
if (!!result.errors) {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.assigning", {
|
||||
message: JSON.stringify(result.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobassignmentremoved(operation),
|
||||
type: "jobassignmentremoved",});
|
||||
setLoading(false);
|
||||
};
|
||||
if (!!!result.errors) {
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobassignmentremoved(operation),
|
||||
type: "jobassignmentremoved",
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.assigning", {
|
||||
message: JSON.stringify(result.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -82,7 +82,7 @@ export default function JobReconciliationBillsTable({
|
||||
state.sortedInfo.order,
|
||||
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.bill.is_credit_memo}/>
|
||||
<Checkbox checked={record.bill.is_credit_memo}/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -6,6 +6,7 @@ import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import InstanceRenderManager from '../../utils/instanceRenderMgr';
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -29,108 +30,130 @@ export function JobTotalsTableTotals({bodyshop, job}) {
|
||||
total: job.job_totals.totals.subtotal,
|
||||
bold: true,
|
||||
},
|
||||
...InstanceRenderManager({imex: [ {
|
||||
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: t("jobs.fields.ca_bc_pvrt"),
|
||||
total: job.job_totals.additional.pvrt,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
key: t("jobs.labels.federal_tax_amt"),
|
||||
total: job.job_totals.totals.federal_tax,
|
||||
},],
|
||||
promanager: "USE_ROME",
|
||||
rome: [(job.job_totals.totals.us_sales_tax_breakdown
|
||||
? [
|
||||
{
|
||||
key: `${
|
||||
bodyshop.md_responsibility_centers.taxes.tax_ty1?.tax_type1 ||
|
||||
"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"
|
||||
} - ${[
|
||||
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,
|
||||
},
|
||||
])]
|
||||
}),
|
||||
|
||||
...(job.job_totals.totals.us_sales_tax_breakdown
|
||||
? [
|
||||
{
|
||||
key: `${
|
||||
bodyshop.md_responsibility_centers.taxes.tax_ty1?.tax_type1 ||
|
||||
"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"
|
||||
} - ${[
|
||||
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"),
|
||||
|
||||
@@ -6,6 +6,7 @@ import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {logImEXEvent} from "../../firebase/firebase.utils";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -29,19 +30,25 @@ export function JobsCloseAutoAllocate({bodyshop, joblines, form, disabled}) {
|
||||
ret.profitcenter_labor = null;
|
||||
}
|
||||
//Verify that this is also manually updated in server/job-costing
|
||||
if (!jl.part_type && !jl.mod_lbr_ty) {
|
||||
const lineDesc = jl.line_desc ? jl.line_desc.toLowerCase() : "";
|
||||
if (lineDesc.includes("shop materials")) {
|
||||
ret.profitcenter_part = defaults.profits["MASH"];
|
||||
} else if (lineDesc.includes("paint/materials")) {
|
||||
ret.profitcenter_part = defaults.profits["MAPA"];
|
||||
} else if (lineDesc.includes("ats amount")) {
|
||||
ret.profitcenter_part = defaults.profits["ATS"];
|
||||
} else if (jl.act_price > 0) {
|
||||
ret.profitcenter_part = defaults.profits["PAO"];
|
||||
} else {
|
||||
ret.profitcenter_part = null;
|
||||
}
|
||||
if (
|
||||
InstanceRenderManager({
|
||||
imex: !jl.part_type && !jl.mod_lbr_ty,
|
||||
rome: !ret.profitcenter_part,
|
||||
promanager: 'USE_ROME',
|
||||
})
|
||||
) {
|
||||
const lineDesc = jl.line_desc ? jl.line_desc.toLowerCase() : '';
|
||||
if (lineDesc.includes('shop materials')) {
|
||||
ret.profitcenter_part = defaults.profits['MASH'];
|
||||
} else if (lineDesc.includes('paint/materials')) {
|
||||
ret.profitcenter_part = defaults.profits['MAPA'];
|
||||
} else if (lineDesc.includes('ats amount')) {
|
||||
ret.profitcenter_part = defaults.profits['ATS'];
|
||||
} else if (jl.act_price > 0) {
|
||||
ret.profitcenter_part = defaults.profits['PAO'];
|
||||
} else {
|
||||
ret.profitcenter_part = null;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}),
|
||||
|
||||
@@ -1,261 +1,225 @@
|
||||
import {Divider, Form, Input, InputNumber, Select, Space, Switch, Tooltip,} 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";
|
||||
import CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.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 JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.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 JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
|
||||
import JobsDetailRatesProfileOVerride from "./jobs-detail-rates.profile-override.component";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import { Divider, Form, Input, InputNumber, Select, Space, Switch, Tooltip } 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';
|
||||
import CABCpvrtCalculator from '../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.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 JobsMarkPstExempt from '../jobs-mark-pst-exempt/jobs-mark-pst-exempt.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 JobsDetailRatesTaxes from './jobs-detail-rates.taxes.component';
|
||||
import JobsDetailRatesProfileOVerride from './jobs-detail-rates.profile-override.component';
|
||||
import InstanceRenderManager from '../../utils/instanceRenderMgr';
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
jobRO: selectJobReadOnly,
|
||||
bodyshop: selectBodyshop,
|
||||
jobRO: selectJobReadOnly,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
export function JobsDetailRates({jobRO, form, job, bodyshop}) {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<div>
|
||||
<FormRow>
|
||||
<Form.Item label={t("jobs.fields.class")} name="class">
|
||||
<Select disabled={true}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.depreciation_taxes")}
|
||||
name="depreciation_taxes"
|
||||
>
|
||||
<CurrencyInput disabled={jobRO} min={0}/>
|
||||
</Form.Item>
|
||||
{bodyshop.region_config.toLowerCase().startsWith("ca") && (
|
||||
<Tooltip title={t("jobs.labels.ca_gst_all_if_null")}>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.ca_customer_gst")}
|
||||
name="ca_customer_gst"
|
||||
>
|
||||
<CurrencyInput
|
||||
disabled={jobRO}
|
||||
min={0}
|
||||
max={
|
||||
Math.round(
|
||||
(job.job_totals &&
|
||||
job.job_totals.totals.federal_tax.amount) ||
|
||||
0
|
||||
) / 100
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Form.Item
|
||||
label={t("jobs.fields.other_amount_payable")}
|
||||
name="other_amount_payable"
|
||||
>
|
||||
<CurrencyInput disabled={jobRO} min={0}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.towing_payable")}
|
||||
name="towing_payable"
|
||||
>
|
||||
<CurrencyInput disabled={jobRO} min={0}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.storage_payable")}
|
||||
name="storage_payable"
|
||||
>
|
||||
<CurrencyInput disabled={jobRO} min={0}/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.adjustment_bottom_line")}
|
||||
name="adjustment_bottom_line"
|
||||
>
|
||||
<CurrencyInput disabled={jobRO || bodyshop.cdk_dealerid}/>
|
||||
</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
|
||||
label={t("jobs.fields.auto_add_ats")}
|
||||
name="auto_add_ats"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
noStyle
|
||||
shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}
|
||||
>
|
||||
{() => {
|
||||
if (form.getFieldValue("auto_add_ats"))
|
||||
return (
|
||||
<Form.Item
|
||||
label={t("jobs.fields.rate_ats")}
|
||||
name="rate_ats"
|
||||
initialValue={bodyshop.shoprates.rate_atp}
|
||||
>
|
||||
<CurrencyInput disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
);
|
||||
|
||||
return null;
|
||||
}}
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
{
|
||||
InstanceRenderManager({imex:
|
||||
<FormRow>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.federal_tax_rate")}
|
||||
name="federal_tax_rate"
|
||||
>
|
||||
<InputNumber min={0} max={1} precision={2} disabled={jobRO}/>
|
||||
export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div>
|
||||
<FormRow>
|
||||
<Form.Item label={t('jobs.fields.class')} name="class">
|
||||
<Select disabled={true} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.depreciation_taxes')} name="depreciation_taxes">
|
||||
<CurrencyInput disabled={jobRO} min={0} />
|
||||
</Form.Item>
|
||||
{bodyshop.region_config.toLowerCase().startsWith('ca') && (
|
||||
<Tooltip title={t('jobs.labels.ca_gst_all_if_null')}>
|
||||
<Form.Item label={t('jobs.fields.ca_customer_gst')} name="ca_customer_gst">
|
||||
<CurrencyInput
|
||||
disabled={jobRO}
|
||||
min={0}
|
||||
max={
|
||||
Math.round((job.job_totals && job.job_totals.totals.federal_tax.amount) || 0) /
|
||||
100
|
||||
}
|
||||
/>
|
||||
</Form.Item>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Form.Item label={t('jobs.fields.other_amount_payable')} name="other_amount_payable">
|
||||
<CurrencyInput disabled={jobRO} min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.towing_payable')} name="towing_payable">
|
||||
<CurrencyInput disabled={jobRO} min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.storage_payable')} name="storage_payable">
|
||||
<CurrencyInput disabled={jobRO} min={0} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.adjustment_bottom_line')} name="adjustment_bottom_line">
|
||||
<CurrencyInput disabled={jobRO || bodyshop.cdk_dealerid} />
|
||||
</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
|
||||
label={t("jobs.fields.state_tax_rate")}
|
||||
name="state_tax_rate"
|
||||
label={t('jobs.fields.auto_add_ats')}
|
||||
name="auto_add_ats"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<InputNumber
|
||||
<Switch disabled={jobRO} />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item noStyle shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}>
|
||||
{() => {
|
||||
if (form.getFieldValue('auto_add_ats'))
|
||||
return (
|
||||
<Form.Item
|
||||
label={t('jobs.fields.rate_ats')}
|
||||
name="rate_ats"
|
||||
initialValue={bodyshop.shoprates.rate_atp}
|
||||
>
|
||||
<CurrencyInput disabled={jobRO} />
|
||||
</Form.Item>
|
||||
);
|
||||
|
||||
return null;
|
||||
}}
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
{InstanceRenderManager({
|
||||
imex: (
|
||||
<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")}
|
||||
/>
|
||||
</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
|
||||
orientation="left"
|
||||
type="horizontal"
|
||||
style={{marginTop: ".8rem", float: "right"}}
|
||||
>
|
||||
{t("jobs.forms.laborrates")}
|
||||
</Divider>
|
||||
<Space>
|
||||
<JobsDetailRatesChangeButton form={form} disabled={jobRO}/>
|
||||
<JobsMarkPstExempt form={form}/>
|
||||
</Space>
|
||||
<FormRow noDivider>
|
||||
<Form.Item
|
||||
label={t("jobs.fields.labor_rate_desc")}
|
||||
name="labor_rate_desc"
|
||||
>
|
||||
<Input disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
{
|
||||
// <Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
|
||||
// <CurrencyInput min={0}disabled={jobRO} />
|
||||
// </Form.Item>
|
||||
// <Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
|
||||
// <CurrencyInput min={0}disabled={jobRO} />
|
||||
// </Form.Item>
|
||||
}
|
||||
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
|
||||
<CurrencyInput min={0} disabled={jobRO}/>
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
{
|
||||
InstanceRenderManager({rome: <>
|
||||
<Divider orientation="left">Tax Profile</Divider>
|
||||
<JobsDetailRatesProfileOVerride form={form}/>
|
||||
<JobsDetailRatesParts form={form}/>
|
||||
<JobsDetailRatesLabor form={form}/>
|
||||
<JobsDetailRatesMaterials form={form}/>
|
||||
<JobsDetailRatesOther form={form}/>
|
||||
<JobsDetailRatesTaxes form={form}/>
|
||||
|
||||
</>})
|
||||
}
|
||||
</div>
|
||||
);
|
||||
>
|
||||
<Switch disabled={jobRO} />
|
||||
</Form.Item>
|
||||
)}
|
||||
</FormRow>
|
||||
),
|
||||
})}
|
||||
<Divider orientation="left" type="horizontal" style={{ marginTop: '.8rem', float: 'right' }}>
|
||||
{t('jobs.forms.laborrates')}
|
||||
</Divider>
|
||||
<Space>
|
||||
<JobsDetailRatesChangeButton form={form} disabled={jobRO} />
|
||||
<JobsMarkPstExempt form={form} />
|
||||
</Space>
|
||||
<FormRow noDivider>
|
||||
<Form.Item label={t('jobs.fields.labor_rate_desc')} name="labor_rate_desc">
|
||||
<Input disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_laa')} name="rate_laa">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_lab')} name="rate_lab">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_lad')} name="rate_lad">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_lae')} name="rate_lae">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_lar')} name="rate_lar">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_las')} name="rate_las">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_laf')} name="rate_laf">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_lam')} name="rate_lam">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_lag')} name="rate_lag">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_la1')} name="rate_la1">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_la2')} name="rate_la2">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_la3')} name="rate_la3">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_la4')} name="rate_la4">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_lau')} name="rate_lau">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_mapa')} name="rate_mapa">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_mash')} name="rate_mash">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_mahw')} name="rate_mahw">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_ma2s')} name="rate_ma2s">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
<Form.Item label={t('jobs.fields.rate_ma3s')} name="rate_ma3s">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
{
|
||||
// <Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
|
||||
// <CurrencyInput min={0}disabled={jobRO} />
|
||||
// </Form.Item>
|
||||
// <Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
|
||||
// <CurrencyInput min={0}disabled={jobRO} />
|
||||
// </Form.Item>
|
||||
}
|
||||
<Form.Item label={t('jobs.fields.rate_matd')} name="rate_matd">
|
||||
<CurrencyInput min={0} disabled={jobRO} />
|
||||
</Form.Item>
|
||||
</FormRow>
|
||||
{InstanceRenderManager({
|
||||
imex: <JobsDetailRatesParts form={form} />,
|
||||
rome: (
|
||||
<>
|
||||
<Divider orientation="left">Tax Profile</Divider>
|
||||
<JobsDetailRatesProfileOVerride form={form} />
|
||||
<JobsDetailRatesParts form={form} />
|
||||
<JobsDetailRatesLabor form={form} />
|
||||
<JobsDetailRatesMaterials form={form} />
|
||||
<JobsDetailRatesOther form={form} />
|
||||
<JobsDetailRatesTaxes form={form} />
|
||||
</>
|
||||
),
|
||||
promanager: "USE_ROME"
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(JobsDetailRates);
|
||||
|
||||
@@ -34,19 +34,20 @@ export function PartDispatchTableComponent({
|
||||
// const selectedBill = search.billid;
|
||||
const [searchText, setSearchText] = useState("");
|
||||
|
||||
const Templates = TemplateList("job_special");
|
||||
const Templates = TemplateList("job_special", job);
|
||||
|
||||
const {refetch} = billsQuery;
|
||||
|
||||
const recordActions = (record) => (
|
||||
<Space wrap>
|
||||
<PrintWrapperComponent
|
||||
templateObject={{
|
||||
name: Templates.parts_dispatch.key,
|
||||
variables: {id: record.id},
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
<Space wrap>
|
||||
<PrintWrapperComponent
|
||||
templateObject={{
|
||||
name: Templates.parts_dispatch.key,
|
||||
variables: { id: record.id },
|
||||
}}
|
||||
messageObject={{ subject: Templates.parts_dispatch.subject }}
|
||||
/>
|
||||
</Space>
|
||||
);
|
||||
const columns = [
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {selectTechnician} from "../../redux/tech/tech.selectors";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -31,7 +32,13 @@ export function ProductionColumnsComponent({
|
||||
}) {
|
||||
const [columns, setColumns] = columnState;
|
||||
const {t} = useTranslation();
|
||||
|
||||
const {
|
||||
treatments: { Enhanced_Payroll },
|
||||
} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ['Enhanced_Payroll'],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
const handleAdd = (e) => {
|
||||
setColumns([
|
||||
...columns,
|
||||
@@ -41,6 +48,7 @@ export function ProductionColumnsComponent({
|
||||
state: tableState,
|
||||
data,
|
||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||
treatments:{Enhanced_Payroll}
|
||||
}).filter((i) => i.key === e.key),
|
||||
]);
|
||||
};
|
||||
@@ -52,6 +60,7 @@ export function ProductionColumnsComponent({
|
||||
state: tableState,
|
||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||
refetch,
|
||||
treatments:{Enhanced_Payroll}
|
||||
});
|
||||
|
||||
const menu = {
|
||||
|
||||
@@ -29,7 +29,8 @@ import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.co
|
||||
import {store} from "../../redux/store";
|
||||
import {setModalContext} from "../../redux/modals/modals.actions";
|
||||
|
||||
const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
|
||||
const r = ({technician, state, activeStatuses, data, bodyshop, refetch, treatments}) => {
|
||||
const {Enhanced_Payroll} = treatments;
|
||||
return [
|
||||
{
|
||||
title: i18n.t("jobs.actions.viewdetail"),
|
||||
@@ -42,7 +43,7 @@ const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
...Enhanced_Payroll.treatment === "on" ? [ {
|
||||
title: i18n.t("timetickets.actions.claimtasks"),
|
||||
dataIndex: "claimtasks",
|
||||
key: "claimtasks",
|
||||
@@ -64,7 +65,7 @@ const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
|
||||
{i18n.t("timetickets.actions.claimtasks")}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
},] : [],
|
||||
{
|
||||
title: i18n.t("jobs.fields.ro_number"),
|
||||
dataIndex: "ro_number",
|
||||
@@ -326,7 +327,7 @@ const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
|
||||
onFilter: (value, record) =>
|
||||
value.includes(record.special_coverage_policy),
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.special_coverage_policy} />
|
||||
<Checkbox checked={record.special_coverage_policy} />
|
||||
),
|
||||
},
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {UPDATE_SHOP} from "../../graphql/bodyshop.queries";
|
||||
import {selectTechnician} from "../../redux/tech/tech.selectors";
|
||||
import {selectBodyshop, selectCurrentUser,} from "../../redux/user/user.selectors";
|
||||
import ProductionListColumns from "../production-list-columns/production-list-columns.data";
|
||||
import {useSplitTreatments} from '@splitsoftware/splitio-react';
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -31,6 +32,12 @@ export function ProductionListTable({
|
||||
const [updateDefaultProdView] = useMutation(UPDATE_ACTIVE_PROD_LIST_VIEW);
|
||||
const [updateShop] = useMutation(UPDATE_SHOP);
|
||||
|
||||
const {treatments: {Enhanced_Payroll}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Enhanced_Payroll"],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
const handleSelect = async (value, option) => {
|
||||
setColumns(
|
||||
bodyshop.production_config
|
||||
@@ -44,6 +51,7 @@ export function ProductionListTable({
|
||||
state,
|
||||
data: data,
|
||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||
treatments:{Enhanced_Payroll}
|
||||
}).find((e) => e.key === k.key),
|
||||
width: k.width,
|
||||
};
|
||||
@@ -100,6 +108,7 @@ export function ProductionListTable({
|
||||
refetch,
|
||||
data: data,
|
||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||
treatments: {Enhanced_Payroll}
|
||||
}).find((e) => e.key === k.key),
|
||||
width: k.width,
|
||||
};
|
||||
|
||||
@@ -28,13 +28,12 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia
|
||||
|
||||
const [searchText, setSearchText] = useState("");
|
||||
|
||||
const {treatments: {Production_List_Status_Colors}} = useSplitTreatments({
|
||||
const {treatments: {Production_List_Status_Colors, Enhanced_Payroll}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Production_List_Status_Colors"],
|
||||
names: ["Production_List_Status_Colors","Enhanced_Payroll"],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
|
||||
const assoc = bodyshop.associations.find(
|
||||
(a) => a.useremail === currentUser.email
|
||||
);
|
||||
@@ -69,6 +68,7 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia
|
||||
state,
|
||||
data,
|
||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||
treatments: {Production_List_Status_Colors, Enhanced_Payroll}
|
||||
}).find((e) => e.key === k.key),
|
||||
width: k.width ?? 100,
|
||||
};
|
||||
@@ -89,6 +89,7 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia
|
||||
state,
|
||||
data: data,
|
||||
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
|
||||
treatments: {Production_List_Status_Colors, Enhanced_Payroll}
|
||||
}).find((e) => e.key === k.key),
|
||||
width: k.width ?? 100,
|
||||
};
|
||||
|
||||
@@ -141,9 +141,10 @@ export function ReportCenterModalComponent({reportCenterModal, bodyshop}) {
|
||||
|
||||
const grouped = _.groupBy(FilteredReportsList, "group");
|
||||
|
||||
const groupExcludeKeyFilter = [...!HasFeatureAccess({featureName: 'bills'})? ["purchases"]:[],
|
||||
...!HasFeatureAccess({featureName: 'timetickets'})? ["payroll"]:[],
|
||||
]
|
||||
const groupExcludeKeyFilter = [
|
||||
...(!HasFeatureAccess({ featureName: 'bills', bodyshop }) ? ['purchases'] : []),
|
||||
...(!HasFeatureAccess({ featureName: 'timetickets', bodyshop }) ? ['payroll'] : []),
|
||||
];
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -18,7 +18,6 @@ import ShopInfoSpeedPrint from "./shop-info.speedprint.component";
|
||||
import {useLocation, useNavigate} from "react-router-dom";
|
||||
import ShopInfoTaskPresets from "./shop-info.task-presets.component";
|
||||
import queryString from "query-string";
|
||||
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
|
||||
@@ -241,17 +241,17 @@ export function ShopInfoResponsibilityCenterComponent({bodyshop, form}) {
|
||||
</Select>
|
||||
</Form.Item>
|
||||
|
||||
<Space align="center">
|
||||
d
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
<FormListMoveArrows
|
||||
move={move}
|
||||
index={index}
|
||||
total={fields.length}
|
||||
/>
|
||||
<Space align="center">
|
||||
<DeleteFilled
|
||||
onClick={() => {
|
||||
remove(field.name);
|
||||
}}
|
||||
/>
|
||||
<FormListMoveArrows
|
||||
move={move}
|
||||
index={index}
|
||||
total={fields.length}
|
||||
/>
|
||||
</Space>
|
||||
</LayoutFormRow>
|
||||
</Form.Item>
|
||||
|
||||
@@ -8,6 +8,7 @@ import {Link, useLocation, useNavigate} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import RomeLogo from "../../assets/RomeOnlineBlue.png";
|
||||
import ImEXOnlineLogo from "../../assets/logo192.png";
|
||||
import ProManagerLogo from '../../assets/promanager/ProManagerLogo.gif';
|
||||
import InstanceRenderManager from '../../utils/instanceRenderMgr';
|
||||
import {emailSignInStart, sendPasswordReset,} from "../../redux/user/user.actions";
|
||||
import {selectCurrentUser, selectLoginLoading, selectSignInError,} from "../../redux/user/user.selectors";
|
||||
@@ -53,9 +54,9 @@ export function SignInComponent({
|
||||
return (
|
||||
<div className="login-container">
|
||||
<div className="login-logo-container">
|
||||
<img src={InstanceRenderManager({imex:ImEXOnlineLogo, rome:RomeLogo, promanager:'https://www.web-est.com/img/web_est_logo_software.gif'})} width={200} alt={InstanceRenderManager({imex:t("titles.imexonline"), rome: t("titles.romeonline"), promanager:t("titles.promanager")})}/>
|
||||
<img src={InstanceRenderManager({imex:ImEXOnlineLogo, rome:RomeLogo, promanager:ProManagerLogo})} width={InstanceRenderManager({imex:200, rome:200,promanager:450})} alt={InstanceRenderManager({imex:t("titles.imexonline"), rome: t("titles.romeonline"), promanager:t("titles.promanager")})}/>
|
||||
<Typography.Title>{
|
||||
InstanceRenderManager({imex: t("titles.imexonline"), rome: t("titles.romeonline"), promanager:t("titles.promanager")})
|
||||
InstanceRenderManager({imex: t("titles.imexonline"), rome: t("titles.romeonline"), promanager:null})
|
||||
}</Typography.Title>
|
||||
</div>
|
||||
<Form onFinish={handleFinish} form={form} size="large">
|
||||
|
||||
@@ -65,14 +65,19 @@ export function TimeTicketList({
|
||||
}, [timetickets]);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: t("timetickets.fields.committed"),
|
||||
dataIndex: "committed_at",
|
||||
key: "committed_at",
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.committed_at}/>
|
||||
),
|
||||
},
|
||||
...(Enhanced_Payroll.treatment === "on"
|
||||
? [{
|
||||
title: t("timetickets.fields.committed"),
|
||||
dataIndex: "committed_at",
|
||||
key: "committed_at",
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.committed_at}/>
|
||||
),
|
||||
},]
|
||||
: [
|
||||
|
||||
]),
|
||||
|
||||
{
|
||||
title: t("timetickets.fields.date"),
|
||||
dataIndex: "date",
|
||||
|
||||
@@ -16,7 +16,6 @@ import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||
import {HasRbacAccess} from "../rbac-wrapper/rbac-wrapper.component";
|
||||
import TimeTicketList from "../time-ticket-list/time-ticket-list.component";
|
||||
import TimeTicketCalculatorComponent from "../time-ticket-calculator/time-ticket-calculator.component";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
|
||||
@@ -178,7 +178,7 @@ export function TimeTicketModalContainer({
|
||||
onCancel={handleCancel}
|
||||
afterClose={() => form.resetFields()}
|
||||
footer={
|
||||
<span>
|
||||
<Space>
|
||||
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
|
||||
<Button
|
||||
loading={loading}
|
||||
@@ -198,7 +198,7 @@ export function TimeTicketModalContainer({
|
||||
{t("general.actions.saveandnew")}
|
||||
</Button>
|
||||
)}
|
||||
</span>
|
||||
</Space>
|
||||
}
|
||||
destroyOnClose
|
||||
>
|
||||
@@ -229,9 +229,12 @@ export function TimeTicketModalContainer({
|
||||
<PageHeader
|
||||
extra={
|
||||
<Space>
|
||||
{
|
||||
Enhanced_Payroll.treatment === 'on' &&
|
||||
<TimeTicketsCommitToggleComponent
|
||||
timeticket={timeTicketModal.context?.timeticket}
|
||||
/>
|
||||
}
|
||||
<Button onClick={handleCancel}>
|
||||
{t("general.actions.cancel")}
|
||||
</Button>
|
||||
|
||||
@@ -1,92 +1,91 @@
|
||||
import {HeartOutlined} from "@ant-design/icons";
|
||||
import {Select, Space, Tag} from "antd";
|
||||
import React, {forwardRef, useEffect, useState} from "react";
|
||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||
import { HeartOutlined } from '@ant-design/icons';
|
||||
import { Select, Space, Tag } from 'antd';
|
||||
import React, { forwardRef, useEffect, useState } from 'react';
|
||||
import PhoneNumberFormatter from '../../utils/PhoneFormatter';
|
||||
|
||||
const {Option} = Select;
|
||||
const { Option } = Select;
|
||||
|
||||
//To be used as a form element only.
|
||||
|
||||
const VendorSearchSelect = (
|
||||
{value, onChange, options, onSelect, disabled, preferredMake, showPhone},
|
||||
ref
|
||||
{ value, onChange, options, onSelect, disabled, preferredMake, showPhone },
|
||||
ref
|
||||
) => {
|
||||
const [option, setOption] = useState(value);
|
||||
const [option, setOption] = useState(value);
|
||||
|
||||
useEffect(() => {
|
||||
if (value !== option && onChange) {
|
||||
onChange(option);
|
||||
}
|
||||
}, [value, option, onChange]);
|
||||
useEffect(() => {
|
||||
if (value !== option && onChange) {
|
||||
onChange(option);
|
||||
}
|
||||
}, [value, option, onChange]);
|
||||
|
||||
const favorites =
|
||||
preferredMake && options
|
||||
? options.filter(
|
||||
(o) =>
|
||||
o.favorite.filter(
|
||||
(f) => f.toLowerCase() === preferredMake.toLowerCase()
|
||||
).length > 0
|
||||
)
|
||||
: [];
|
||||
const favorites =
|
||||
preferredMake && options
|
||||
? options.filter(
|
||||
(o) =>
|
||||
o.favorite.filter((f) => f.toLowerCase() === preferredMake.toLowerCase()).length > 0
|
||||
)
|
||||
: [];
|
||||
|
||||
return (
|
||||
<Select
|
||||
ref={ref}
|
||||
showSearch
|
||||
value={option}
|
||||
style={{
|
||||
width: "100%",
|
||||
}}
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={setOption}
|
||||
optionFilterProp="name"
|
||||
onSelect={onSelect}
|
||||
disabled={disabled || false}
|
||||
optionLabelProp={"name"}
|
||||
>
|
||||
{favorites
|
||||
? favorites.map((o) => (
|
||||
<Option
|
||||
key={`favorite-${o.id}`}
|
||||
value={o.id}
|
||||
name={o.name}
|
||||
discount={o.discount}
|
||||
>
|
||||
<div className="imex-flex-row">
|
||||
<div style={{flex: 1}}>{o.name}</div>
|
||||
<Space style={{marginLeft: "1rem"}}>
|
||||
<HeartOutlined style={{color: "red"}}/>
|
||||
{o.phone && showPhone && (
|
||||
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||
)}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
{options
|
||||
? options.map((o) => (
|
||||
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
|
||||
<div className="imex-flex-row" style={{width: "100%"}}>
|
||||
<div style={{flex: 1}}>{o.name}</div>
|
||||
return (
|
||||
<Select
|
||||
ref={ref}
|
||||
showSearch
|
||||
value={option}
|
||||
style={{
|
||||
width: '100%',
|
||||
}}
|
||||
labelRender={({ label, value, ...rest }) => {
|
||||
if (!value || !options) return label;
|
||||
const discount = options?.find((o) => o.id === value)?.discount;
|
||||
return (
|
||||
<div className="imex-flex-row" style={{ width: '100%' }}>
|
||||
<div style={{ flex: 1 }}>{label}</div>
|
||||
|
||||
<Space style={{marginLeft: "1rem"}}>
|
||||
{o.phone && showPhone && (
|
||||
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
|
||||
)}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
{discount && discount !== 0 ? <Tag color="green">{`${discount * 100}%`}</Tag> : null}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
popupMatchSelectWidth={false}
|
||||
onChange={setOption}
|
||||
optionFilterProp="name"
|
||||
onSelect={onSelect}
|
||||
disabled={disabled || false}
|
||||
optionLabelProp={'name'}
|
||||
>
|
||||
{favorites
|
||||
? favorites.map((o) => (
|
||||
<Option key={`favorite-${o.id}`} value={o.id} name={o.name} discount={o.discount}>
|
||||
<div className="imex-flex-row">
|
||||
<div style={{ flex: 1 }}>{o.name}</div>
|
||||
<Space style={{ marginLeft: '1rem' }}>
|
||||
<HeartOutlined style={{ color: 'red' }} />
|
||||
{o.phone && showPhone && <PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
{options
|
||||
? options.map((o) => (
|
||||
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
|
||||
<div className="imex-flex-row" style={{ width: '100%' }}>
|
||||
<div style={{ flex: 1 }}>{o.name}</div>
|
||||
|
||||
))
|
||||
: null}
|
||||
</Select>
|
||||
);
|
||||
<Space style={{ marginLeft: '1rem' }}>
|
||||
{o.phone && showPhone && <PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>}
|
||||
{o.discount && o.discount !== 0 ? (
|
||||
<Tag color="green">{`${o.discount * 100}%`}</Tag>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
</Option>
|
||||
))
|
||||
: null}
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
export default forwardRef(VendorSearchSelect);
|
||||
|
||||
@@ -126,7 +126,7 @@ export function BillsListPage({
|
||||
state.sortedInfo.columnKey === "is_credit_memo" &&
|
||||
state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.is_credit_memo}/>
|
||||
<Checkbox checked={record.is_credit_memo}/>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -136,7 +136,7 @@ export function BillsListPage({
|
||||
sorter: (a, b) => a.exported - b.exported,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "exported" && state.sortedInfo.order,
|
||||
render: (text, record) => <Checkbox disabled checked={record.exported}/>,
|
||||
render: (text, record) => <Checkbox checked={record.exported}/>,
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
|
||||
@@ -41,8 +41,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(DmsContainer);
|
||||
export const socket = SocketIO(
|
||||
import.meta.env.PROD
|
||||
? import.meta.env.VITE_APP_AXIOS_BASE_API_URL
|
||||
: window.location.origin,
|
||||
// "http://localhost:4000", // for dev testing,
|
||||
: "http://localhost:4000", // for dev testing,
|
||||
{
|
||||
path: "/ws",
|
||||
withCredentials: true,
|
||||
|
||||
@@ -162,26 +162,24 @@ sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||
{ text: "False", value: false },
|
||||
],
|
||||
onFilter: (value, record) => record.successful === value,
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.successful}/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t("general.labels.message"),
|
||||
dataIndex: "message",
|
||||
key: "message",
|
||||
render: (text, record) =>
|
||||
record.message && (
|
||||
<div>
|
||||
<ul>
|
||||
{JSON.parse(record.message).map((m, idx) => (
|
||||
<li key={idx}>{m}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
render: (text, record) => <Checkbox checked={record.successful} />,
|
||||
},
|
||||
{
|
||||
title: t("general.labels.message"),
|
||||
dataIndex: "message",
|
||||
key: "message",
|
||||
render: (text, record) =>
|
||||
record.message && (
|
||||
<div>
|
||||
<ul>
|
||||
{JSON.parse(record.message).map((m, idx) => (
|
||||
<li key={idx}>{m}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<Card
|
||||
|
||||
@@ -372,8 +372,9 @@ export function JobsCloseComponent({job, bodyshop, jobRO, insertAuditTrail}) {
|
||||
</Form.Item>
|
||||
)}
|
||||
</LayoutFormRow>
|
||||
<Divider>{t("jobs.labels.multipayers")}</Divider>
|
||||
|
||||
{Qb_Multi_Ar.treatment === "on" && (
|
||||
<><Divider>{t("jobs.labels.multipayers")}</Divider>
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col lg={8} md={24}>
|
||||
<Form.List
|
||||
@@ -452,7 +453,9 @@ export function JobsCloseComponent({job, bodyshop, jobRO, insertAuditTrail}) {
|
||||
<DeleteFilled
|
||||
disabled={jobRO}
|
||||
onClick={() => {
|
||||
if(!jobRO){
|
||||
remove(field.name);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
@@ -530,6 +533,7 @@ export function JobsCloseComponent({job, bodyshop, jobRO, insertAuditTrail}) {
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
)}
|
||||
<Divider/>
|
||||
<JobsCloseLines job={job}/>
|
||||
|
||||
@@ -332,7 +332,7 @@ export function JobsDetailPage({
|
||||
{
|
||||
key: "partssublet",
|
||||
icon: <ToolFilled/>,
|
||||
label: t("menus.jobsdetail.partssublet"),
|
||||
label: HasFeatureAccess({featureName: "bills", bodyshop}) ? t("menus.jobsdetail.partssublet") : t("menus.jobsdetail.parts"),
|
||||
children: <JobsDetailPliContainer job={job}/>,
|
||||
},
|
||||
...InstanceRenderManager({ imex: true, rome: true, promanager: HasFeatureAccess({ featureName: 'timetickets', bodyshop }) }) ? [ {
|
||||
|
||||
@@ -521,13 +521,12 @@ export function Manage({conflict, bodyshop,enableJoyRide,joyRideSteps,setJoyRide
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex' }}>
|
||||
{`Joy Ride Status: ${enableJoyRide}`}
|
||||
<div>
|
||||
{`${InstanceRenderManager({
|
||||
imex: t('titles.imexonline'),
|
||||
rome: t('titles.romeonline'),
|
||||
promanager: t('titles.promanager'),
|
||||
})} ${import.meta.env.VITE_APP_GIT_SHA || 'Local Build'} - ${
|
||||
})} - ${
|
||||
import.meta.env.VITE_APP_GIT_SHA_DATE
|
||||
}`}
|
||||
</div>
|
||||
|
||||
@@ -72,7 +72,7 @@ export function ShopPage({bodyshop, setSelectedHeader, setBreadcrumbs}) {
|
||||
},
|
||||
);
|
||||
|
||||
if(HasFeatureAccess("csi")){
|
||||
if(HasFeatureAccess({featureName:"csi", bodyshop})){
|
||||
items.push({
|
||||
key: "csiq",
|
||||
label: t("bodyshop.labels.csiq"),
|
||||
|
||||
@@ -1,103 +1,110 @@
|
||||
import {useQuery} from "@apollo/client";
|
||||
import {Col, Row, Space} from "antd";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, {useEffect} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {useSearchParams} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import AlertComponent from "../../components/alert/alert.component";
|
||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
import TimeTicketsDatesSelector
|
||||
from "../../components/ticket-tickets-dates-selector/time-tickets-dates-selector.component";
|
||||
import TimeTicketList from "../../components/time-ticket-list/time-ticket-list.component";
|
||||
import TimeTicketsPayrollTable from "../../components/time-tickets-payroll-table/time-tickets-payroll-table.component";
|
||||
import TimeTicketsSummaryEmployees
|
||||
from "../../components/time-tickets-summary-employees/time-tickets-summary-employees.component";
|
||||
import {QUERY_TIME_TICKETS_IN_RANGE} from "../../graphql/timetickets.queries";
|
||||
import TimeTicketsAttendanceTable
|
||||
from "../../components/time-tickets-attendance-table/time-tickets-attendance-table.component";
|
||||
import {setBreadcrumbs, setSelectedHeader,} from "../../redux/application/application.actions";
|
||||
import TimeTicketsCommit from "../../components/time-tickets-commit/time-tickets-commit.component";
|
||||
import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component";
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { Col, Row, Space } from 'antd';
|
||||
import dayjs from '../../utils/day';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { connect } from 'react-redux';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import AlertComponent from '../../components/alert/alert.component';
|
||||
import RbacWrapper from '../../components/rbac-wrapper/rbac-wrapper.component';
|
||||
import TimeTicketsDatesSelector from '../../components/ticket-tickets-dates-selector/time-tickets-dates-selector.component';
|
||||
import TimeTicketList from '../../components/time-ticket-list/time-ticket-list.component';
|
||||
import TimeTicketsPayrollTable from '../../components/time-tickets-payroll-table/time-tickets-payroll-table.component';
|
||||
import TimeTicketsSummaryEmployees from '../../components/time-tickets-summary-employees/time-tickets-summary-employees.component';
|
||||
import { QUERY_TIME_TICKETS_IN_RANGE } from '../../graphql/timetickets.queries';
|
||||
import TimeTicketsAttendanceTable from '../../components/time-tickets-attendance-table/time-tickets-attendance-table.component';
|
||||
import { setBreadcrumbs, setSelectedHeader } from '../../redux/application/application.actions';
|
||||
import TimeTicketsCommit from '../../components/time-tickets-commit/time-tickets-commit.component';
|
||||
import FeatureWrapperComponent from '../../components/feature-wrapper/feature-wrapper.component';
|
||||
import InstanceRenderManager from '../../utils/instanceRenderMgr';
|
||||
import { useSplitTreatments } from '@splitsoftware/splitio-react';
|
||||
import { selectBodyshop } from '../../redux/user/user.selectors';
|
||||
|
||||
const mapStateToProps = createStructuredSelector({});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop:selectBodyshop
|
||||
});
|
||||
|
||||
export function TimeTicketsContainer({
|
||||
bodyshop,
|
||||
setBreadcrumbs,
|
||||
setSelectedHeader,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
const [searchParams] = useSearchParams();
|
||||
const {start, end} = Object.fromEntries(searchParams);
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
|
||||
});
|
||||
|
||||
const startDate = start
|
||||
? dayjs(start)
|
||||
: dayjs().startOf("week").subtract(7, "day");
|
||||
const endDate = end ? dayjs(end) : dayjs().endOf("week");
|
||||
export function TimeTicketsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
const {
|
||||
treatments: { Enhanced_Payroll },
|
||||
} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ['Enhanced_Payroll'],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
const { t } = useTranslation();
|
||||
const [searchParams] = useSearchParams();
|
||||
const { start, end } = Object.fromEntries(searchParams);
|
||||
|
||||
const {loading, error, data} = useQuery(QUERY_TIME_TICKETS_IN_RANGE, {
|
||||
variables: {
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
},
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
const startDate = start ? dayjs(start) : dayjs().startOf('week').subtract(7, 'day');
|
||||
const endDate = end ? dayjs(end) : dayjs().endOf('week');
|
||||
|
||||
const { loading, error, data } = useQuery(QUERY_TIME_TICKETS_IN_RANGE, {
|
||||
variables: {
|
||||
start: startDate,
|
||||
end: endDate,
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
nextFetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
document.title = t('titles.timetickets', {
|
||||
app: InstanceRenderManager({
|
||||
imex: '$t(titles.imexonline)',
|
||||
rome: '$t(titles.romeonline)',
|
||||
promanager: '$t(titles.promanager)',
|
||||
}),
|
||||
});
|
||||
setSelectedHeader('timetickets');
|
||||
setBreadcrumbs([
|
||||
{
|
||||
link: '/manage/timetickets',
|
||||
label: t('titles.bc.timetickets'),
|
||||
},
|
||||
]);
|
||||
}, [t, setBreadcrumbs, setSelectedHeader]);
|
||||
|
||||
useEffect(() => {
|
||||
document.title = t("titles.timetickets",{app: InstanceRenderManager({imex:'$t(titles.imexonline)', rome: '$t(titles.romeonline)', promanager: '$t(titles.promanager)'})} );
|
||||
setSelectedHeader("timetickets");
|
||||
setBreadcrumbs([
|
||||
{
|
||||
link: "/manage/timetickets",
|
||||
label: t("titles.bc.timetickets"),
|
||||
},
|
||||
]);
|
||||
}, [t, setBreadcrumbs, setSelectedHeader]);
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
|
||||
if (error) return <AlertComponent message={error.message} type="error"/>;
|
||||
|
||||
return (
|
||||
<FeatureWrapperComponent featureName='timetickets'>
|
||||
<RbacWrapper action="timetickets:list">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<TimeTicketList
|
||||
loading={loading}
|
||||
timetickets={data ? data.timetickets : []}
|
||||
extra={
|
||||
<Space wrap>
|
||||
<TimeTicketsAttendanceTable/>
|
||||
<TimeTicketsPayrollTable/>
|
||||
<TimeTicketsCommit timetickets={data ? data.timetickets : []}/>
|
||||
<TimeTicketsDatesSelector/>
|
||||
</Space>
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<TimeTicketsSummaryEmployees
|
||||
loading={loading}
|
||||
timetickets={data ? data.timetickets : []}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</RbacWrapper>
|
||||
</FeatureWrapperComponent>
|
||||
);
|
||||
return (
|
||||
<FeatureWrapperComponent featureName="timetickets">
|
||||
<RbacWrapper action="timetickets:list">
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col span={24}>
|
||||
<TimeTicketList
|
||||
loading={loading}
|
||||
timetickets={data ? data.timetickets : []}
|
||||
extra={
|
||||
<Space wrap>
|
||||
<TimeTicketsAttendanceTable />
|
||||
<TimeTicketsPayrollTable />
|
||||
{Enhanced_Payroll.treatment === 'on' && (
|
||||
<TimeTicketsCommit timetickets={data ? data.timetickets : []} />
|
||||
)}
|
||||
<TimeTicketsDatesSelector />
|
||||
</Space>
|
||||
}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={24}>
|
||||
<TimeTicketsSummaryEmployees
|
||||
loading={loading}
|
||||
timetickets={data ? data.timetickets : []}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
/>
|
||||
</Col>
|
||||
</Row>
|
||||
</RbacWrapper>
|
||||
</FeatureWrapperComponent>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(TimeTicketsContainer);
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TimeTicketsContainer);
|
||||
|
||||
@@ -47,6 +47,7 @@ import client from "../../utils/GraphQLClient";
|
||||
import {QUERY_EULA} from "../../graphql/bodyshop.queries";
|
||||
import day from "../../utils/day";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import { Userpilot } from "userpilot";
|
||||
|
||||
const fpPromise = FingerprintJS.load();
|
||||
|
||||
@@ -227,6 +228,15 @@ export function* signInSuccessSaga({payload}) {
|
||||
window.$crisp.push(['set', 'user:nickname', [payload.displayName || payload.email]]);
|
||||
window.$crisp.push(['set', 'session:segments', [['user']]]);
|
||||
},
|
||||
promanager: () =>{
|
||||
Userpilot.identify(
|
||||
payload.email,
|
||||
{
|
||||
email: payload.email,
|
||||
}
|
||||
);
|
||||
console.log("*** Userpilot identified.")
|
||||
}
|
||||
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -749,7 +749,7 @@
|
||||
"refuelcharge": "Refuel Charge (per liter/gallon)",
|
||||
"scheduledreturn": "Scheduled Return",
|
||||
"start": "Contract Start",
|
||||
"statetax": "State Taxes",
|
||||
"statetax": "Provincial/State Taxes",
|
||||
"status": "Status"
|
||||
},
|
||||
"labels": {
|
||||
@@ -899,6 +899,7 @@
|
||||
"refhrs": "Refinish Hrs"
|
||||
},
|
||||
"titles": {
|
||||
"joblifecycle": "Job Life Cycles",
|
||||
"labhours": "Total Body Hours",
|
||||
"larhours": "Total Refinish Hours",
|
||||
"monthlyemployeeefficiency": "Monthly Employee Efficiency",
|
||||
@@ -1164,6 +1165,7 @@
|
||||
"loadingshop": "Loading shop data...",
|
||||
"loggingin": "Authorizing...",
|
||||
"markedexported": "Manually marked as exported.",
|
||||
"media": "Media",
|
||||
"message": "Message",
|
||||
"monday": "Monday",
|
||||
"na": "N/A",
|
||||
@@ -2002,7 +2004,7 @@
|
||||
"savebeforeconversion": "You have unsaved changes on the Job. Please save them before converting it. ",
|
||||
"scheduledinchange": "The scheduled in is based off the latest appointment. To change this date, please schedule or reschedule the Job. ",
|
||||
"specialcoveragepolicy": "Special Coverage Policy Applies",
|
||||
"state_tax_amt": "State Taxes",
|
||||
"state_tax_amt": "Provincial/State Taxes",
|
||||
"subletstotal": "Sublets Total",
|
||||
"subtotal": "Subtotal",
|
||||
"supplementnote": "The Job had a supplement imported.",
|
||||
@@ -2174,6 +2176,7 @@
|
||||
"insurance": "Insurance Information",
|
||||
"labor": "Labor",
|
||||
"lifecycle": "Lifecycle",
|
||||
"parts": "Parts",
|
||||
"partssublet": "Parts & Bills",
|
||||
"rates": "Rates",
|
||||
"repairdata": "Repair Data",
|
||||
@@ -2558,7 +2561,7 @@
|
||||
"invoice_total_payable": "Invoice (Total Payable)",
|
||||
"iou_form": "IOU Form",
|
||||
"job_costing_ro": "Job Costing",
|
||||
"job_lifecycle_ro": "",
|
||||
"job_lifecycle_ro": "Job Lifecycle",
|
||||
"job_notes": "Job Notes",
|
||||
"key_tag": "Key Tag",
|
||||
"labels": {
|
||||
|
||||
@@ -899,6 +899,7 @@
|
||||
"refhrs": ""
|
||||
},
|
||||
"titles": {
|
||||
"joblifecycle": "",
|
||||
"labhours": "",
|
||||
"larhours": "",
|
||||
"monthlyemployeeefficiency": "",
|
||||
@@ -2174,6 +2175,7 @@
|
||||
"insurance": "",
|
||||
"labor": "Labor",
|
||||
"lifecycle": "",
|
||||
"parts": "",
|
||||
"partssublet": "Piezas / Subarrendamiento",
|
||||
"rates": "",
|
||||
"repairdata": "Datos de reparación",
|
||||
|
||||
@@ -899,6 +899,7 @@
|
||||
"refhrs": ""
|
||||
},
|
||||
"titles": {
|
||||
"joblifecycle": "",
|
||||
"labhours": "",
|
||||
"larhours": "",
|
||||
"monthlyemployeeefficiency": "",
|
||||
@@ -2174,6 +2175,7 @@
|
||||
"insurance": "",
|
||||
"labor": "La main d'oeuvre",
|
||||
"lifecycle": "",
|
||||
"parts": "",
|
||||
"partssublet": "Pièces / Sous-location",
|
||||
"rates": "",
|
||||
"repairdata": "Données de réparation",
|
||||
|
||||
@@ -4,6 +4,7 @@ import { initReactI18next } from 'react-i18next';
|
||||
import en_Translation from './en_us/common.json';
|
||||
import es_Translation from './es/common.json';
|
||||
import fr_Translation from './fr/common.json';
|
||||
import { GenerateTemplates } from '../utils/RenderTemplate';
|
||||
|
||||
// the translations
|
||||
// (tip move them in a JSON file and import them)
|
||||
@@ -13,19 +14,27 @@ const resources = {
|
||||
'es-MX': es_Translation,
|
||||
};
|
||||
i18n
|
||||
.use(initReactI18next)
|
||||
.use(LanguageDetector) // passes i18n down to react-i18next
|
||||
.init({
|
||||
resources,
|
||||
//lng: "en",
|
||||
detection: {},
|
||||
fallbackLng: 'en-US',
|
||||
debug: import.meta.env.DEV,
|
||||
//keySeparator: false, // we do not use keys in form messages.welcome
|
||||
interpolation: {
|
||||
escapeValue: false, // react already safes from xss
|
||||
skipOnVariables: false,
|
||||
.use(initReactI18next)
|
||||
.init(
|
||||
{
|
||||
resources,
|
||||
//lng: "en",
|
||||
detection: {},
|
||||
fallbackLng: 'en-US',
|
||||
debug: import.meta.env.DEV,
|
||||
react: {
|
||||
useSuspense: true,
|
||||
},
|
||||
//keySeparator: false, // we do not use keys in form messages.welcome
|
||||
interpolation: {
|
||||
escapeValue: false, // react already safes from xss
|
||||
skipOnVariables: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
(error) => {
|
||||
GenerateTemplates();
|
||||
}
|
||||
);
|
||||
|
||||
export default i18n;
|
||||
|
||||
@@ -14,7 +14,12 @@ const server = import.meta.env.VITE_APP_REPORTS_SERVER_URL;
|
||||
|
||||
jsreport.serverUrl = server;
|
||||
|
||||
const Templates = TemplateList();
|
||||
let Templates;
|
||||
export function GenerateTemplates(){
|
||||
//Required as a part of the transition to Vite.
|
||||
//Previous method had the template hash generating before translations loaded, resulting in empty files.
|
||||
Templates = TemplateList()
|
||||
}
|
||||
|
||||
export default async function RenderTemplate(
|
||||
templateObject,
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as path from 'path';
|
||||
import * as url from 'url';
|
||||
import { defineConfig } from 'vite';
|
||||
import { ViteEjsPlugin } from 'vite-plugin-ejs';
|
||||
import CompressionPlugin from 'vite-plugin-compression';
|
||||
//import CompressionPlugin from 'vite-plugin-compression';
|
||||
import { VitePWA } from 'vite-plugin-pwa';
|
||||
import InstanceRenderManager from './src/utils/instanceRenderMgr';
|
||||
|
||||
@@ -103,8 +103,11 @@ export default defineConfig({
|
||||
}),
|
||||
reactVirtualized(),
|
||||
react(),
|
||||
CompressionPlugin(),
|
||||
// CompressionPlugin(), //Cloudfront already compresses assets, so not needed.
|
||||
],
|
||||
define:{
|
||||
"APP_VERSION": JSON.stringify(process.env.npm_package_version)
|
||||
},
|
||||
server: {
|
||||
host: true,
|
||||
port: 3000,
|
||||
|
||||
@@ -569,6 +569,13 @@
|
||||
table:
|
||||
name: parts_orders
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: billid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -818,6 +825,13 @@
|
||||
table:
|
||||
name: inventory
|
||||
schema: public
|
||||
- name: ioevents
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: bodyshopid
|
||||
table:
|
||||
name: ioevents
|
||||
schema: public
|
||||
- name: jobs
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -846,6 +860,13 @@
|
||||
table:
|
||||
name: phonebook
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: bodyshopid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: timetickets
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -2675,6 +2696,13 @@
|
||||
- table:
|
||||
name: ioevents
|
||||
schema: public
|
||||
object_relationships:
|
||||
- name: bodyshop
|
||||
using:
|
||||
foreign_key_constraint_on: bodyshopid
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: useremail
|
||||
- table:
|
||||
name: job_ar_schema
|
||||
schema: public
|
||||
@@ -2824,6 +2852,13 @@
|
||||
table:
|
||||
name: parts_order_lines
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: joblineid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -3311,6 +3346,13 @@
|
||||
table:
|
||||
name: scoreboard
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: jobid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: timetickets
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -5008,6 +5050,13 @@
|
||||
table:
|
||||
name: parts_order_lines
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: partsorderid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -5623,6 +5672,128 @@
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
- table:
|
||||
name: tasks
|
||||
schema: public
|
||||
object_relationships:
|
||||
- name: bill
|
||||
using:
|
||||
foreign_key_constraint_on: billid
|
||||
- name: bodyshop
|
||||
using:
|
||||
foreign_key_constraint_on: bodyshopid
|
||||
- name: job
|
||||
using:
|
||||
foreign_key_constraint_on: jobid
|
||||
- name: jobline
|
||||
using:
|
||||
foreign_key_constraint_on: joblineid
|
||||
- name: parts_order
|
||||
using:
|
||||
foreign_key_constraint_on: partsorderid
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: assigned_to
|
||||
- name: userByCreatedBy
|
||||
using:
|
||||
foreign_key_constraint_on: created_by
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
check:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
columns:
|
||||
- completed
|
||||
- deleted
|
||||
- priority
|
||||
- assigned_to
|
||||
- created_by
|
||||
- description
|
||||
- title
|
||||
- completed_at
|
||||
- created_at
|
||||
- deleted_at
|
||||
- due_date
|
||||
- remind_at
|
||||
- updated_at
|
||||
- billid
|
||||
- bodyshopid
|
||||
- id
|
||||
- jobid
|
||||
- joblineid
|
||||
- partsorderid
|
||||
select_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- completed
|
||||
- deleted
|
||||
- priority
|
||||
- assigned_to
|
||||
- created_by
|
||||
- description
|
||||
- title
|
||||
- completed_at
|
||||
- created_at
|
||||
- deleted_at
|
||||
- due_date
|
||||
- remind_at
|
||||
- updated_at
|
||||
- billid
|
||||
- bodyshopid
|
||||
- id
|
||||
- jobid
|
||||
- joblineid
|
||||
- partsorderid
|
||||
filter:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
update_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- completed
|
||||
- deleted
|
||||
- priority
|
||||
- assigned_to
|
||||
- created_by
|
||||
- description
|
||||
- title
|
||||
- completed_at
|
||||
- created_at
|
||||
- deleted_at
|
||||
- due_date
|
||||
- remind_at
|
||||
- updated_at
|
||||
- billid
|
||||
- bodyshopid
|
||||
- id
|
||||
- jobid
|
||||
- joblineid
|
||||
- partsorderid
|
||||
filter:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
check: null
|
||||
- table:
|
||||
name: timetickets
|
||||
schema: public
|
||||
@@ -6006,6 +6177,13 @@
|
||||
table:
|
||||
name: exportlog
|
||||
schema: public
|
||||
- name: ioevents
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: useremail
|
||||
table:
|
||||
name: ioevents
|
||||
schema: public
|
||||
- name: messages
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -6034,6 +6212,20 @@
|
||||
table:
|
||||
name: parts_orders
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: assigned_to
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: tasksByCreatedBy
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: created_by
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: timetickets
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE "public"."tasks";
|
||||
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE "public"."tasks" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "title" text NOT NULL, "description" Text, "deleted" boolean NOT NULL DEFAULT false, "deleted_at" timestamptz, "due_date" timestamptz, "created_by" text NOT NULL, "assigned_to" Text, "completed" boolean NOT NULL DEFAULT false, "completed_at" timestamptz, "remind_at" timestamptz, "priority" numeric, "bodyshopid" UUID NOT NULL, "jobid" UUID NOT NULL, "joblineid" UUID, "partsorderid" UUID, "billid" UUID, PRIMARY KEY ("id") , FOREIGN KEY ("created_by") REFERENCES "public"."users"("email") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("assigned_to") REFERENCES "public"."users"("email") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("bodyshopid") REFERENCES "public"."bodyshops"("id") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("jobid") REFERENCES "public"."jobs"("id") ON UPDATE cascade ON DELETE cascade, FOREIGN KEY ("joblineid") REFERENCES "public"."joblines"("id") ON UPDATE set null ON DELETE set null, FOREIGN KEY ("partsorderid") REFERENCES "public"."parts_orders"("id") ON UPDATE set null ON DELETE set null, FOREIGN KEY ("billid") REFERENCES "public"."bills"("id") ON UPDATE set null ON DELETE set null);
|
||||
CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
_new record;
|
||||
BEGIN
|
||||
_new := NEW;
|
||||
_new."updated_at" = NOW();
|
||||
RETURN _new;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
CREATE TRIGGER "set_public_tasks_updated_at"
|
||||
BEFORE UPDATE ON "public"."tasks"
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"();
|
||||
COMMENT ON TRIGGER "set_public_tasks_updated_at" ON "public"."tasks"
|
||||
IS 'trigger to set value of column "updated_at" to current timestamp on row update';
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
@@ -16,7 +16,7 @@ const CalculateAllocations =
|
||||
const CdkBase = require("../../web-sockets/web-socket");
|
||||
const moment = require("moment-timezone");
|
||||
const Dinero = require("dinero.js");
|
||||
const { default: InstanceManager } = require("../../utils/instanceMgr");
|
||||
const { default: InstanceManager } = require("../../utils/instanceMgr").default;
|
||||
const axios = AxiosLib.create();
|
||||
|
||||
axios.interceptors.request.use((x) => {
|
||||
|
||||
@@ -605,9 +605,9 @@ exports.default = function ({
|
||||
const state_tax = Dinero(job_totals.totals.state_tax);
|
||||
const local_tax = Dinero(job_totals.totals.local_tax);
|
||||
|
||||
const RulesetToUse = InstanceManager({imex:"CANADA",rome: "US"})
|
||||
const RulesetToUse = InstanceManager({ imex: 'CANADA', rome: 'US', promanager: 'US' });
|
||||
|
||||
if(RulesetToUse = "CANADA"){
|
||||
if(RulesetToUse === "CANADA"){
|
||||
if (federal_tax.getAmount() > 0) {
|
||||
if (qbo) {
|
||||
// do qbo
|
||||
|
||||
@@ -7,7 +7,7 @@ const builder = require("xmlbuilder2");
|
||||
const QbXmlUtils = require("./qbxml-utils");
|
||||
const moment = require("moment-timezone");
|
||||
const logger = require('../../utils/logger');
|
||||
const InstanceManager = require("../../utils/instanceMgr");
|
||||
const InstanceManager = require("../../utils/instanceMgr").default;
|
||||
|
||||
require("dotenv").config({
|
||||
path: path.resolve(
|
||||
|
||||
@@ -7,7 +7,7 @@ const builder = require("xmlbuilder2");
|
||||
const QbXmlUtils = require("./qbxml-utils");
|
||||
const CreateInvoiceLines = require("../qb-receivables-lines").default;
|
||||
const logger = require('../../utils/logger');
|
||||
const InstanceManager = require('../../utils/instanceMgr');
|
||||
const InstanceManager = require('../../utils/instanceMgr').default;
|
||||
|
||||
require("dotenv").config({
|
||||
path: path.resolve(
|
||||
|
||||
@@ -13,7 +13,7 @@ const CdkBase = require("../web-sockets/web-socket");
|
||||
const Dinero = require("dinero.js");
|
||||
const _ = require("lodash");
|
||||
const {DiscountNotAlreadyCounted} = require("../job/job-totals");
|
||||
const InstanceManager = require('../utils/instanceMgr');
|
||||
const InstanceManager = require('../utils/instanceMgr').default;
|
||||
|
||||
exports.default = async function (socket, jobid) {
|
||||
try {
|
||||
@@ -26,7 +26,11 @@ exports.default = async function (socket, jobid) {
|
||||
const {bodyshop} = job;
|
||||
|
||||
const taxAllocations =
|
||||
InstanceManager({imex: {
|
||||
InstanceManager({
|
||||
executeFunction:true,
|
||||
deubg:true,
|
||||
args: [],
|
||||
imex: () => ({
|
||||
local: {
|
||||
center: bodyshop.md_responsibility_centers.taxes.local.name,
|
||||
sale: Dinero(job.job_totals.totals.local_tax),
|
||||
@@ -48,7 +52,7 @@ exports.default = async function (socket, jobid) {
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes.federal,
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes.federal,
|
||||
},
|
||||
}, rome:{
|
||||
}), rome: () => ({
|
||||
tax_ty1: {
|
||||
center: bodyshop.md_responsibility_centers.taxes[`tax_ty1`].name,
|
||||
sale: Dinero(job.job_totals.totals.us_sales_tax_breakdown[`ty1Tax`]),
|
||||
@@ -84,7 +88,7 @@ exports.default = async function (socket, jobid) {
|
||||
profitCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty5`],
|
||||
costCenter: bodyshop.md_responsibility_centers.taxes[`tax_ty5`],
|
||||
},
|
||||
} })
|
||||
}) })
|
||||
|
||||
|
||||
//Determine if there are MAPA and MASH lines already on the estimate.
|
||||
@@ -439,6 +443,7 @@ if(InstanceManager({rome:true})){
|
||||
}),
|
||||
];
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
CdkBase.createLogEvent(
|
||||
socket,
|
||||
"ERROR",
|
||||
|
||||
@@ -12,6 +12,7 @@ const CdkBase = require("../web-sockets/web-socket");
|
||||
const CdkWsdl = require("./cdk-wsdl").default;
|
||||
const {CDK_CREDENTIALS, CheckCdkResponseForError} = require("./cdk-wsdl");
|
||||
const CalcualteAllocations = require("./cdk-calculate-allocations").default;
|
||||
const InstanceMgr = require("../utils/instanceMgr").default;
|
||||
|
||||
const moment = require("moment-timezone");
|
||||
|
||||
@@ -599,12 +600,11 @@ async function InsertDmsCustomer(socket, newCustomerNumber) {
|
||||
country:
|
||||
socket.JobData.ownr_ctry &&
|
||||
socket.JobData.ownr_ctry.replace(replaceSpecialRegex, ""),
|
||||
postalCode:
|
||||
socket.JobData.ownr_zip &&
|
||||
socket.JobData.ownr_zip //TODO Need to remove for US Based customers.
|
||||
.toUpperCase()
|
||||
.replace(/\W/g, "")
|
||||
.replace(/(...)/, "$1 "),
|
||||
postalCode: InstanceMgr({imex: socket.JobData.ownr_zip &&
|
||||
socket.JobData.ownr_zip //TODO Need to remove for US Based customers.
|
||||
.toUpperCase()
|
||||
.replace(/\W/g, "")
|
||||
.replace(/(...)/, "$1 "), rome: socket.JobData.ownr_zip }),
|
||||
stateOrProvince:
|
||||
socket.JobData.ownr_st &&
|
||||
socket.JobData.ownr_st.replace(replaceSpecialRegex, ""),
|
||||
|
||||
@@ -11,7 +11,7 @@ const queries = require("../graphql-client/queries");
|
||||
const {phone} = require("phone");
|
||||
const {admin} = require("../firebase/firebase-handler");
|
||||
const logger = require("../utils/logger");
|
||||
const InstanceManager = require("../utils/instanceMgr");
|
||||
const InstanceManager = require("../utils/instanceMgr").default;
|
||||
|
||||
exports.receive = async (req, res) => {
|
||||
//Perform request validation
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @property { string | object | function } imex Return this prop if Rome.
|
||||
*/
|
||||
|
||||
function InstanceManager({ instance, debug, executeFunction, rome, promanager, imex }) {
|
||||
function InstanceManager({ args, instance, debug, executeFunction, rome, promanager, imex }) {
|
||||
let propToReturn = null;
|
||||
|
||||
switch (instance || process.env.INSTANCE) {
|
||||
|
||||
Reference in New Issue
Block a user