IO-233 CDK Allocations Summary
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
|
BabelEdit project file
|
||||||
@@ -3620,6 +3620,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>mappingname</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
@@ -16893,6 +16914,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>dmsautoallocate</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>
|
<concept_node>
|
||||||
<name>export</name>
|
<name>export</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -72,9 +72,11 @@ export function BillEnterModalLinesComponent({
|
|||||||
quantity: opt.part_qty || 1,
|
quantity: opt.part_qty || 1,
|
||||||
actual_price: opt.cost,
|
actual_price: opt.cost,
|
||||||
cost_center: opt.part_type
|
cost_center: opt.part_type
|
||||||
? responsibilityCenters.defaults.costs[
|
? responsibilityCenters.defaults &&
|
||||||
|
(responsibilityCenters.defaults.costs[
|
||||||
opt.part_type
|
opt.part_type
|
||||||
] || null
|
] ||
|
||||||
|
null)
|
||||||
: null,
|
: null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import { Table } from "antd";
|
||||||
|
import React, { useMemo } from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import Dinero from "dinero.js";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import _ from "lodash";
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
//currentUser: selectCurrentUser
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(DmsAllocationsSummary);
|
||||||
|
|
||||||
|
export function DmsAllocationsSummary({ bodyshop, job }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const allocationsSummary = useMemo(() => {
|
||||||
|
const profitCenterHash = job.joblines.reduce((acc, val) => {
|
||||||
|
//Check the Parts Assignment
|
||||||
|
if (val.profitcenter_part) {
|
||||||
|
if (!acc[val.profitcenter_part]) acc[val.profitcenter_part] = Dinero();
|
||||||
|
|
||||||
|
acc[val.profitcenter_part] = acc[val.profitcenter_part].add(
|
||||||
|
Dinero({ amount: Math.round((val.act_price || 0) * 100) }).multiply(
|
||||||
|
val.part_qty || 0
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (val.profitcenter_labor) {
|
||||||
|
//Check the Labor Assignment.
|
||||||
|
|
||||||
|
if (!acc[val.profitcenter_labor])
|
||||||
|
acc[val.profitcenter_labor] = Dinero();
|
||||||
|
|
||||||
|
acc[val.profitcenter_labor] = acc[val.profitcenter_labor].add(
|
||||||
|
Dinero({
|
||||||
|
amount: Math.round(
|
||||||
|
job[`rate_${val.mod_lbr_ty.toLowerCase()}`] * 100
|
||||||
|
),
|
||||||
|
}).multiply(val.mod_lb_hrs)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
const costCenterHash = job.bills.reduce((bill_acc, bill_val) => {
|
||||||
|
bill_val.billlines.map((line_val) => {
|
||||||
|
if (!bill_acc[line_val.cost_center])
|
||||||
|
bill_acc[line_val.cost_center] = Dinero();
|
||||||
|
|
||||||
|
bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(
|
||||||
|
Dinero({
|
||||||
|
amount: Math.round((line_val.actual_cost || 0) * 100),
|
||||||
|
})
|
||||||
|
.multiply(line_val.quantity)
|
||||||
|
.multiply(bill_val.is_credit_memo ? -1 : 1)
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return bill_acc;
|
||||||
|
}, {});
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: dms-allocations-summary.component.jsx ~ line 69 ~ costCenterHash",
|
||||||
|
costCenterHash
|
||||||
|
);
|
||||||
|
|
||||||
|
return _.union(
|
||||||
|
Object.keys(profitCenterHash),
|
||||||
|
Object.keys(costCenterHash)
|
||||||
|
).map((key) => {
|
||||||
|
console.log("Key", key);
|
||||||
|
const profitCenter = bodyshop.md_responsibility_centers.profits.find(
|
||||||
|
(c) => c.name === key
|
||||||
|
);
|
||||||
|
const costCenter = bodyshop.md_responsibility_centers.costs.find(
|
||||||
|
(c) => c.name === key
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
center: key,
|
||||||
|
sale: profitCenterHash[key]
|
||||||
|
? profitCenterHash[key].toFormat()
|
||||||
|
: Dinero().toFormat(),
|
||||||
|
cost: costCenterHash[key]
|
||||||
|
? costCenterHash[key].toFormat()
|
||||||
|
: Dinero().toFormat(),
|
||||||
|
profitCenter,
|
||||||
|
costCenter,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, [job, bodyshop.md_responsibility_centers]);
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: t("job.fields.dms.center"),
|
||||||
|
dataIndex: "center",
|
||||||
|
key: "center",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("job.fields.dms.sale"),
|
||||||
|
dataIndex: "sale",
|
||||||
|
key: "sale",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("job.fields.dms.cost"),
|
||||||
|
dataIndex: "cost",
|
||||||
|
key: "cost",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("job.fields.dms.sale_dms_acctnumber"),
|
||||||
|
dataIndex: "sale_dms_acctnumber",
|
||||||
|
key: "sale_dms_acctnumber",
|
||||||
|
render: (text, record) =>
|
||||||
|
record.profitCenter && record.profitCenter.dms_acctnumber,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("job.fields.dms.cost_dms_acctnumber"),
|
||||||
|
dataIndex: "cost_dms_acctnumber",
|
||||||
|
key: "cost_dms_acctnumber",
|
||||||
|
render: (text, record) =>
|
||||||
|
record.costCenter && record.costCenter.dms_acctnumber,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("job.fields.dms.dms_wip_acctnumber"),
|
||||||
|
dataIndex: "dms_wip_acctnumber",
|
||||||
|
key: "dms_wip_acctnumber",
|
||||||
|
render: (text, record) =>
|
||||||
|
record.costCenter && record.costCenter.dms_wip_acctnumber,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
pagination={{ position: "top", defaultPageSize: 50 }}
|
||||||
|
columns={columns}
|
||||||
|
rowKey="center"
|
||||||
|
dataSource={allocationsSummary}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
import { Divider, Space, Tag, Timeline } from "antd";
|
||||||
|
import moment from "moment";
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import {
|
||||||
|
setBreadcrumbs,
|
||||||
|
setSelectedHeader,
|
||||||
|
} from "../../redux/application/application.actions";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||||
|
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(DmsLogEvents);
|
||||||
|
|
||||||
|
export function DmsLogEvents({ socket, logs, bodyshop }) {
|
||||||
|
return (
|
||||||
|
<Timeline pending reverse={true}>
|
||||||
|
{logs.map((log, idx) => (
|
||||||
|
<Timeline.Item key={idx} color={LogLevelHierarchy(log.level)}>
|
||||||
|
<Space wrap align="start" style={{}}>
|
||||||
|
<Tag color={LogLevelHierarchy(log.level)}>{log.level}</Tag>
|
||||||
|
<span>{moment(log.timestamp).format("MM/DD/YYYY HH:MM:ss")}</span>
|
||||||
|
<Divider type="vertical" />
|
||||||
|
<span>{log.message}</span>
|
||||||
|
</Space>
|
||||||
|
</Timeline.Item>
|
||||||
|
))}
|
||||||
|
</Timeline>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function LogLevelHierarchy(level) {
|
||||||
|
switch (level) {
|
||||||
|
case "TRACE":
|
||||||
|
return "pink";
|
||||||
|
case "DEBUG":
|
||||||
|
return "orange";
|
||||||
|
case "INFO":
|
||||||
|
return "blue";
|
||||||
|
case "WARNING":
|
||||||
|
return "yellow";
|
||||||
|
case "ERROR":
|
||||||
|
return "red";
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Button } from "antd";
|
import { Button, Dropdown, Menu } from "antd";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -12,11 +12,8 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
|
|
||||||
export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const handleAllocate = () => {
|
|
||||||
logImEXEvent("jobs_close_allocate_auto");
|
|
||||||
|
|
||||||
const { defaults } = bodyshop.md_responsibility_centers;
|
|
||||||
|
|
||||||
|
const handleAllocate = (defaults) => {
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
joblines: joblines.map((jl) => {
|
joblines: joblines.map((jl) => {
|
||||||
const ret = _.cloneDeep(jl);
|
const ret = _.cloneDeep(jl);
|
||||||
@@ -32,7 +29,7 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
|||||||
}
|
}
|
||||||
//Verify that this is also manually updated in server/job-costing
|
//Verify that this is also manually updated in server/job-costing
|
||||||
if (!jl.part_type && !jl.mod_lbr_ty) {
|
if (!jl.part_type && !jl.mod_lbr_ty) {
|
||||||
const lineDesc = jl.line_desc.toLowerCase();
|
const lineDesc = jl.line_desc && jl.line_desc.toLowerCase();
|
||||||
if (lineDesc.includes("shop materials")) {
|
if (lineDesc.includes("shop materials")) {
|
||||||
ret.profitcenter_part = defaults.profits["MASH"];
|
ret.profitcenter_part = defaults.profits["MASH"];
|
||||||
} else if (lineDesc.includes("paint/materials")) {
|
} else if (lineDesc.includes("paint/materials")) {
|
||||||
@@ -48,8 +45,36 @@ export function JobsCloseAutoAllocate({ bodyshop, joblines, form, disabled }) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
const handleAutoAllocateClick = () => {
|
||||||
<Button onClick={handleAllocate} disabled={disabled}>
|
logImEXEvent("jobs_close_allocate_auto");
|
||||||
|
|
||||||
|
const { defaults } = bodyshop.md_responsibility_centers;
|
||||||
|
handleAllocate(defaults);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMenuClick = ({ item, key, keyPath, domEvent }) => {
|
||||||
|
logImEXEvent("jobs_close_allocate_auto_dms");
|
||||||
|
handleAllocate(
|
||||||
|
bodyshop.md_responsibility_centers.dms_defaults.find(
|
||||||
|
(x) => x.name === key
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const overlay = (
|
||||||
|
<Menu onClick={handleMenuClick}>
|
||||||
|
{bodyshop.md_responsibility_centers.dms_defaults.map((mapping) => (
|
||||||
|
<Menu.Item key={mapping.name}>{mapping.name}</Menu.Item>
|
||||||
|
))}
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
|
||||||
|
return bodyshop.cdk_dealerid ? (
|
||||||
|
<Dropdown overlay={overlay}>
|
||||||
|
<Button disabled={disabled}>{t("jobs.actions.dmsautoallocate")}</Button>
|
||||||
|
</Dropdown>
|
||||||
|
) : (
|
||||||
|
<Button onClick={handleAutoAllocateClick} disabled={disabled}>
|
||||||
{t("jobs.actions.autoallocate")}
|
{t("jobs.actions.autoallocate")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1871,3 +1871,100 @@ export const FIND_JOBS_BY_CLAIM = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const QUERY_JOB_EXPORT_DMS = gql`
|
||||||
|
query QUERY_JOB_CLOSE_DETAILS($id: uuid!) {
|
||||||
|
jobs_by_pk(id: $id) {
|
||||||
|
ro_number
|
||||||
|
invoice_allocation
|
||||||
|
ins_co_id
|
||||||
|
id
|
||||||
|
ded_amt
|
||||||
|
ded_status
|
||||||
|
depreciation_taxes
|
||||||
|
other_amount_payable
|
||||||
|
towing_payable
|
||||||
|
storage_payable
|
||||||
|
adjustment_bottom_line
|
||||||
|
federal_tax_rate
|
||||||
|
state_tax_rate
|
||||||
|
local_tax_rate
|
||||||
|
tax_tow_rt
|
||||||
|
tax_str_rt
|
||||||
|
tax_paint_mat_rt
|
||||||
|
tax_sub_rt
|
||||||
|
tax_lbr_rt
|
||||||
|
tax_levies_rt
|
||||||
|
parts_tax_rates
|
||||||
|
job_totals
|
||||||
|
rate_la1
|
||||||
|
rate_la2
|
||||||
|
rate_la3
|
||||||
|
rate_la4
|
||||||
|
rate_laa
|
||||||
|
rate_lab
|
||||||
|
rate_lad
|
||||||
|
rate_lae
|
||||||
|
rate_laf
|
||||||
|
rate_lag
|
||||||
|
rate_lam
|
||||||
|
rate_lar
|
||||||
|
rate_las
|
||||||
|
rate_lau
|
||||||
|
rate_ma2s
|
||||||
|
rate_ma2t
|
||||||
|
rate_ma3s
|
||||||
|
rate_mabl
|
||||||
|
rate_macs
|
||||||
|
rate_mahw
|
||||||
|
rate_mapa
|
||||||
|
rate_mash
|
||||||
|
rate_matd
|
||||||
|
status
|
||||||
|
date_exported
|
||||||
|
date_invoiced
|
||||||
|
voided
|
||||||
|
scheduled_completion
|
||||||
|
actual_completion
|
||||||
|
scheduled_delivery
|
||||||
|
actual_delivery
|
||||||
|
scheduled_in
|
||||||
|
actual_in
|
||||||
|
bills {
|
||||||
|
id
|
||||||
|
federal_tax_rate
|
||||||
|
local_tax_rate
|
||||||
|
state_tax_rate
|
||||||
|
is_credit_memo
|
||||||
|
billlines {
|
||||||
|
actual_cost
|
||||||
|
cost_center
|
||||||
|
id
|
||||||
|
quantity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
joblines(where: { removed: { _eq: false } }) {
|
||||||
|
id
|
||||||
|
removed
|
||||||
|
tax_part
|
||||||
|
line_desc
|
||||||
|
prt_dsmk_p
|
||||||
|
prt_dsmk_m
|
||||||
|
part_type
|
||||||
|
oem_partno
|
||||||
|
db_price
|
||||||
|
act_price
|
||||||
|
part_qty
|
||||||
|
mod_lbr_ty
|
||||||
|
db_hrs
|
||||||
|
mod_lb_hrs
|
||||||
|
lbr_op
|
||||||
|
lbr_amt
|
||||||
|
op_code_desc
|
||||||
|
profitcenter_labor
|
||||||
|
profitcenter_part
|
||||||
|
prt_dsmk_p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
@@ -1,16 +1,23 @@
|
|||||||
import { Result, Timeline, Space, Tag, Divider, Button } from "antd";
|
import { useQuery } from "@apollo/client";
|
||||||
|
import { Button, Result } from "antd";
|
||||||
|
import queryString from "query-string";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
import { useLocation } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import SocketIO from "socket.io-client";
|
||||||
|
import AlertComponent from "../../components/alert/alert.component";
|
||||||
|
import DmsAllocationsSummary from "../../components/dms-allocations-summary/dms-allocations-summary.component";
|
||||||
|
import DmsLogEvents from "../../components/dms-log-events/dms-log-events.component";
|
||||||
|
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||||
|
import { auth } from "../../firebase/firebase.utils";
|
||||||
|
import { QUERY_JOB_EXPORT_DMS } from "../../graphql/jobs.queries";
|
||||||
import {
|
import {
|
||||||
setBreadcrumbs,
|
setBreadcrumbs,
|
||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import SocketIO from "socket.io-client";
|
|
||||||
import { auth } from "../../firebase/firebase.utils";
|
|
||||||
import moment from "moment";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -39,6 +46,13 @@ export const socket = SocketIO(
|
|||||||
export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [logs, setLogs] = useState([]);
|
const [logs, setLogs] = useState([]);
|
||||||
|
const search = queryString.parse(useLocation().search);
|
||||||
|
const { jobId } = search;
|
||||||
|
|
||||||
|
const { loading, error, data } = useQuery(QUERY_JOB_EXPORT_DMS, {
|
||||||
|
variables: { id: jobId },
|
||||||
|
skip: !jobId,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = t("titles.dms");
|
document.title = t("titles.dms");
|
||||||
@@ -71,10 +85,13 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!bodyshop.cdk_dealerid) return <Result status="404" />;
|
if (!jobId || !bodyshop.cdk_dealerid) return <Result status="404" />;
|
||||||
|
|
||||||
const dmsType = determineDmsType(bodyshop);
|
const dmsType = determineDmsType(bodyshop);
|
||||||
|
|
||||||
|
if (loading) return <LoadingSpinner />;
|
||||||
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
@@ -98,39 +115,18 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
|||||||
reconnect
|
reconnect
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Timeline pending={socket.connected && "Processing..."} reverse={true}>
|
<DmsAllocationsSummary
|
||||||
{logs.map((log, idx) => (
|
socket={socket}
|
||||||
<Timeline.Item key={idx} color={LogLevelHierarchy(log.level)}>
|
job={data ? data.jobs_by_pk : null}
|
||||||
<Space wrap align="start" style={{}}>
|
/>
|
||||||
<Tag color={LogLevelHierarchy(log.level)}>{log.level}</Tag>
|
|
||||||
<span>{moment(log.timestamp).format("MM/DD/YYYY HH:MM:ss")}</span>
|
<div>
|
||||||
<Divider type="vertical" />
|
<DmsLogEvents socket={socket} logs={logs} />
|
||||||
<span>{log.message}</span>
|
</div>
|
||||||
</Space>
|
|
||||||
</Timeline.Item>
|
|
||||||
))}
|
|
||||||
</Timeline>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function LogLevelHierarchy(level) {
|
|
||||||
switch (level) {
|
|
||||||
case "TRACE":
|
|
||||||
return "pink";
|
|
||||||
case "DEBUG":
|
|
||||||
return "orange";
|
|
||||||
case "INFO":
|
|
||||||
return "blue";
|
|
||||||
case "WARNING":
|
|
||||||
return "yellow";
|
|
||||||
case "ERROR":
|
|
||||||
return "red";
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const determineDmsType = (bodyshop) => {
|
const determineDmsType = (bodyshop) => {
|
||||||
if (bodyshop.cdk_dealerid) return "cdk";
|
if (bodyshop.cdk_dealerid) return "cdk";
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -233,7 +233,8 @@
|
|||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
"dms_acctnumber": "DMS Account #",
|
"dms_acctnumber": "DMS Account #",
|
||||||
"dms_wip_acctnumber": "DMS W.I.P. Account #"
|
"dms_wip_acctnumber": "DMS W.I.P. Account #",
|
||||||
|
"mappingname": "DMS Mapping Name"
|
||||||
},
|
},
|
||||||
"email": "General Shop Email",
|
"email": "General Shop Email",
|
||||||
"enforce_class": "Enforce Class on Conversion?",
|
"enforce_class": "Enforce Class on Conversion?",
|
||||||
@@ -1059,6 +1060,7 @@
|
|||||||
"changestatus": "Change Status",
|
"changestatus": "Change Status",
|
||||||
"convert": "Convert",
|
"convert": "Convert",
|
||||||
"deliver": "Deliver",
|
"deliver": "Deliver",
|
||||||
|
"dmsautoallocate": "DMS Auto Allocate",
|
||||||
"export": "Export",
|
"export": "Export",
|
||||||
"exportcustdata": "Export Customer Data",
|
"exportcustdata": "Export Customer Data",
|
||||||
"exportselected": "Export Selected",
|
"exportselected": "Export Selected",
|
||||||
|
|||||||
@@ -233,7 +233,8 @@
|
|||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
"dms_acctnumber": "",
|
"dms_acctnumber": "",
|
||||||
"dms_wip_acctnumber": ""
|
"dms_wip_acctnumber": "",
|
||||||
|
"mappingname": ""
|
||||||
},
|
},
|
||||||
"email": "",
|
"email": "",
|
||||||
"enforce_class": "",
|
"enforce_class": "",
|
||||||
@@ -1059,6 +1060,7 @@
|
|||||||
"changestatus": "Cambiar Estado",
|
"changestatus": "Cambiar Estado",
|
||||||
"convert": "Convertir",
|
"convert": "Convertir",
|
||||||
"deliver": "",
|
"deliver": "",
|
||||||
|
"dmsautoallocate": "",
|
||||||
"export": "",
|
"export": "",
|
||||||
"exportcustdata": "",
|
"exportcustdata": "",
|
||||||
"exportselected": "",
|
"exportselected": "",
|
||||||
|
|||||||
@@ -233,7 +233,8 @@
|
|||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
"dms_acctnumber": "",
|
"dms_acctnumber": "",
|
||||||
"dms_wip_acctnumber": ""
|
"dms_wip_acctnumber": "",
|
||||||
|
"mappingname": ""
|
||||||
},
|
},
|
||||||
"email": "",
|
"email": "",
|
||||||
"enforce_class": "",
|
"enforce_class": "",
|
||||||
@@ -1059,6 +1060,7 @@
|
|||||||
"changestatus": "Changer le statut",
|
"changestatus": "Changer le statut",
|
||||||
"convert": "Convertir",
|
"convert": "Convertir",
|
||||||
"deliver": "",
|
"deliver": "",
|
||||||
|
"dmsautoallocate": "",
|
||||||
"export": "",
|
"export": "",
|
||||||
"exportcustdata": "",
|
"exportcustdata": "",
|
||||||
"exportselected": "",
|
"exportselected": "",
|
||||||
|
|||||||
Reference in New Issue
Block a user