@@ -2863,6 +2863,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>markexported</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>markforreexport</name>
|
<name>markforreexport</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -3120,6 +3141,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>markexported</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>reexport</name>
|
<name>reexport</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -7794,6 +7836,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>timezone</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>tt_allow_post_to_invoiced</name>
|
<name>tt_allow_post_to_invoiced</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -20329,6 +20392,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>comment</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>customerowing</name>
|
<name>customerowing</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -36104,6 +36188,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>comment</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>compact</name>
|
<name>compact</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -38903,6 +39008,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>dailyactual</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>dailytarget</name>
|
<name>dailytarget</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -38966,6 +39092,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>todateactual</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>weeklyactual</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>weeklytarget</name>
|
<name>weeklytarget</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
"logrocket": "^2.1.2",
|
"logrocket": "^2.1.2",
|
||||||
"markerjs2": "^2.17.2",
|
"markerjs2": "^2.17.2",
|
||||||
"moment-business-days": "^1.2.0",
|
"moment-business-days": "^1.2.0",
|
||||||
|
"moment-timezone": "^0.5.34",
|
||||||
"phone": "^3.1.10",
|
"phone": "^3.1.10",
|
||||||
"preval.macro": "^5.0.0",
|
"preval.macro": "^5.0.0",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import BillMarkExportedButton from "../bill-mark-exported-button/bill-mark-exported-button.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
@@ -234,6 +235,7 @@ export function BillDetailEditcontainer({
|
|||||||
</Button>
|
</Button>
|
||||||
</Popconfirm>
|
</Popconfirm>
|
||||||
<BillReeportButtonComponent bill={data && data.bills_by_pk} />
|
<BillReeportButtonComponent bill={data && data.bills_by_pk} />
|
||||||
|
<BillMarkExportedButton bill={data && data.bills_by_pk} />
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
import { useMutation } from "@apollo/client";
|
||||||
|
import { Button, notification } from "antd";
|
||||||
|
import { gql } from "@apollo/client";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import {
|
||||||
|
selectAuthLevel,
|
||||||
|
selectBodyshop,
|
||||||
|
} from "../../redux/user/user.selectors";
|
||||||
|
import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component";
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
authLevel: selectAuthLevel,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(BillMarkExportedButton);
|
||||||
|
|
||||||
|
export function BillMarkExportedButton({ bodyshop, authLevel, bill }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
const [updateBill] = useMutation(gql`
|
||||||
|
mutation UPDATE_BILL($billId: uuid!) {
|
||||||
|
update_bills(where: { id: { _eq: $billId } }, _set: { exported: true }) {
|
||||||
|
returning {
|
||||||
|
id
|
||||||
|
exported
|
||||||
|
exported_at
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
|
const handleUpdate = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
const result = await updateBill({
|
||||||
|
variables: { billId: bill.id },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.errors) {
|
||||||
|
notification["success"]({
|
||||||
|
message: t("bills.successes.markexported"),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
notification["error"]({
|
||||||
|
message: t("bills.errors.saving", {
|
||||||
|
error: JSON.stringify(result.errors),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
//Get the owner details, populate it all back into the job.
|
||||||
|
};
|
||||||
|
|
||||||
|
const hasAccess = HasRbacAccess({
|
||||||
|
bodyshop,
|
||||||
|
authLevel,
|
||||||
|
action: "bills:reexport",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasAccess)
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
loading={loading}
|
||||||
|
disabled={bill.exported}
|
||||||
|
onClick={handleUpdate}
|
||||||
|
>
|
||||||
|
{t("bills.labels.markexported")}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
|
return <></>;
|
||||||
|
}
|
||||||
@@ -1,11 +1,24 @@
|
|||||||
import { DatePicker } from "antd";
|
import { DatePicker } from "antd";
|
||||||
import moment from "moment";
|
import moment from "moment-timezone";
|
||||||
import React, { useRef } from "react";
|
import React, { useRef } from "react";
|
||||||
//To be used as a form element only.
|
//To be used as a form element only.
|
||||||
|
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
//currentUser: selectCurrentUser
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(FormDatePicker);
|
||||||
|
|
||||||
const dateFormat = "MM/DD/YYYY";
|
const dateFormat = "MM/DD/YYYY";
|
||||||
|
|
||||||
export default function FormDatePicker({
|
export function FormDatePicker({
|
||||||
|
bodyshop,
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
onBlur,
|
onBlur,
|
||||||
@@ -23,7 +36,7 @@ export default function FormDatePicker({
|
|||||||
const handleKeyDown = (e) => {
|
const handleKeyDown = (e) => {
|
||||||
if (e.key.toLowerCase() === "t") {
|
if (e.key.toLowerCase() === "t") {
|
||||||
if (onChange) {
|
if (onChange) {
|
||||||
onChange(new moment());
|
onChange(moment());
|
||||||
// if (ref.current && ref.current.blur) ref.current.blur();
|
// if (ref.current && ref.current.blur) ref.current.blur();
|
||||||
}
|
}
|
||||||
} else if (e.key.toLowerCase() === "enter") {
|
} else if (e.key.toLowerCase() === "enter") {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ export default function JobBillsTotalComponent({
|
|||||||
|
|
||||||
const discrepWithLbrAdj = discrepancy.add(lbrAdjustments);
|
const discrepWithLbrAdj = discrepancy.add(lbrAdjustments);
|
||||||
|
|
||||||
const discrepWithCms = discrepWithLbrAdj.add(billCms);
|
const discrepWithCms = discrepWithLbrAdj.add(totalReturns);
|
||||||
const creditsNotReceived = totalReturns.subtract(billCms); //billCms is tracked as a negative number.
|
const creditsNotReceived = totalReturns.subtract(billCms); //billCms is tracked as a negative number.
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -171,8 +171,8 @@ export default function JobBillsTotalComponent({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Statistic
|
<Statistic
|
||||||
title={t("bills.labels.billcmtotal")}
|
title={t("bills.labels.totalreturns")}
|
||||||
value={billCms.toFormat()}
|
value={totalReturns.toFormat()}
|
||||||
/>
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Typography.Title>=</Typography.Title>
|
<Typography.Title>=</Typography.Title>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import ProductionListColumnProductionNote from "../production-list-columns/produ
|
|||||||
import "./jobs-detail-header.styles.scss";
|
import "./jobs-detail-header.styles.scss";
|
||||||
import JobsRelatedRos from "../jobs-related-ros/jobs-related-ros.component";
|
import JobsRelatedRos from "../jobs-related-ros/jobs-related-ros.component";
|
||||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
||||||
|
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
@@ -86,6 +87,12 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
) : null}
|
) : null}
|
||||||
</Space>
|
</Space>
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
|
<DataLabel
|
||||||
|
label={t("jobs.fields.comment")}
|
||||||
|
valueStyle={{ overflow: "hidden", textOverflow: "ellipsis" }}
|
||||||
|
>
|
||||||
|
<ProductionListColumnComment record={job} />
|
||||||
|
</DataLabel>
|
||||||
<DataLabel label={t("jobs.fields.ins_co_nm_short")}>
|
<DataLabel label={t("jobs.fields.ins_co_nm_short")}>
|
||||||
{job.ins_co_nm}
|
{job.ins_co_nm}
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.ro_number"),
|
title: t("jobs.fields.ro_number"),
|
||||||
dataIndex: "ro_number",
|
dataIndex: "ro_number",
|
||||||
key: "ro_number",
|
key: "ro_number",
|
||||||
width: "8%",
|
|
||||||
sorter: true, //(a, b) => alphaSort(a.ro_number, b.ro_number),
|
sorter: true, //(a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||||
sortOrder: sortcolumn === "ro_number" && sortorder,
|
sortOrder: sortcolumn === "ro_number" && sortorder,
|
||||||
|
|
||||||
@@ -47,7 +47,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
key: "ownr_ln",
|
key: "ownr_ln",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
//sorter: true, // (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
//sorter: true, // (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
||||||
width: "25%",
|
|
||||||
//sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
//sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.ownerid ? (
|
return record.ownerid ? (
|
||||||
@@ -67,7 +67,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.ownr_ph1"),
|
title: t("jobs.fields.ownr_ph1"),
|
||||||
dataIndex: "ownr_ph1",
|
dataIndex: "ownr_ph1",
|
||||||
key: "ownr_ph1",
|
key: "ownr_ph1",
|
||||||
width: "12%",
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<StartChatButton phone={record.ownr_ph1} jobid={record.id} />
|
<StartChatButton phone={record.ownr_ph1} jobid={record.id} />
|
||||||
@@ -77,7 +77,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.ownr_ph2"),
|
title: t("jobs.fields.ownr_ph2"),
|
||||||
dataIndex: "ownr_ph2",
|
dataIndex: "ownr_ph2",
|
||||||
key: "ownr_ph2",
|
key: "ownr_ph2",
|
||||||
width: "12%",
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<StartChatButton phone={record.ownr_ph2} jobid={record.id} />
|
<StartChatButton phone={record.ownr_ph2} jobid={record.id} />
|
||||||
@@ -87,7 +87,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.status"),
|
title: t("jobs.fields.status"),
|
||||||
dataIndex: "status",
|
dataIndex: "status",
|
||||||
key: "status",
|
key: "status",
|
||||||
width: "10%",
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true, // (a, b) => alphaSort(a.status, b.status),
|
sorter: true, // (a, b) => alphaSort(a.status, b.status),
|
||||||
sortOrder: sortcolumn === "status" && sortorder,
|
sortOrder: sortcolumn === "status" && sortorder,
|
||||||
@@ -104,7 +104,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.vehicle"),
|
title: t("jobs.fields.vehicle"),
|
||||||
dataIndex: "vehicle",
|
dataIndex: "vehicle",
|
||||||
key: "vehicle",
|
key: "vehicle",
|
||||||
width: "15%",
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.vehicleid ? (
|
return record.vehicleid ? (
|
||||||
@@ -124,7 +124,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("vehicles.fields.plate_no"),
|
title: t("vehicles.fields.plate_no"),
|
||||||
dataIndex: "plate_no",
|
dataIndex: "plate_no",
|
||||||
key: "plate_no",
|
key: "plate_no",
|
||||||
width: "8%",
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true, //(a, b) => alphaSort(a.plate_no, b.plate_no),
|
sorter: true, //(a, b) => alphaSort(a.plate_no, b.plate_no),
|
||||||
sortOrder: sortcolumn === "plate_no" && sortorder,
|
sortOrder: sortcolumn === "plate_no" && sortorder,
|
||||||
@@ -136,7 +136,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.clm_no"),
|
title: t("jobs.fields.clm_no"),
|
||||||
dataIndex: "clm_no",
|
dataIndex: "clm_no",
|
||||||
key: "clm_no",
|
key: "clm_no",
|
||||||
width: "12%",
|
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: true, //(a, b) => alphaSort(a.clm_no, b.clm_no),
|
sorter: true, //(a, b) => alphaSort(a.clm_no, b.clm_no),
|
||||||
sortOrder: sortcolumn === "clm_no" && sortorder,
|
sortOrder: sortcolumn === "clm_no" && sortorder,
|
||||||
@@ -155,7 +155,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.clm_total"),
|
title: t("jobs.fields.clm_total"),
|
||||||
dataIndex: "clm_total",
|
dataIndex: "clm_total",
|
||||||
key: "clm_total",
|
key: "clm_total",
|
||||||
width: "10%",
|
|
||||||
sorter: true, //(a, b) => a.clm_total - b.clm_total,
|
sorter: true, //(a, b) => a.clm_total - b.clm_total,
|
||||||
sortOrder: sortcolumn === "clm_total" && sortorder,
|
sortOrder: sortcolumn === "clm_total" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
@@ -170,11 +170,17 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
title: t("jobs.fields.owner_owing"),
|
title: t("jobs.fields.owner_owing"),
|
||||||
dataIndex: "owner_owing",
|
dataIndex: "owner_owing",
|
||||||
key: "owner_owing",
|
key: "owner_owing",
|
||||||
width: "8%",
|
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<CurrencyFormatter>{record.owner_owing}</CurrencyFormatter>
|
<CurrencyFormatter>{record.owner_owing}</CurrencyFormatter>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.comment"),
|
||||||
|
dataIndex: "comment",
|
||||||
|
key: "comment",
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleTableChange = (pagination, filters, sorter) => {
|
const handleTableChange = (pagination, filters, sorter) => {
|
||||||
@@ -224,7 +230,6 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
>
|
>
|
||||||
<Table
|
<Table
|
||||||
loading={loading}
|
loading={loading}
|
||||||
scroll={{ x: true }}
|
|
||||||
pagination={{
|
pagination={{
|
||||||
position: "top",
|
position: "top",
|
||||||
pageSize: 25,
|
pageSize: 25,
|
||||||
|
|||||||
@@ -60,6 +60,9 @@ export function JobsList({ bodyshop }) {
|
|||||||
(j.ownr_co_nm || "")
|
(j.ownr_co_nm || "")
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(searchText.toLowerCase()) ||
|
.includes(searchText.toLowerCase()) ||
|
||||||
|
(j.comments || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchText.toLowerCase()) ||
|
||||||
(j.ownr_fn || "")
|
(j.ownr_fn || "")
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(searchText.toLowerCase()) ||
|
.includes(searchText.toLowerCase()) ||
|
||||||
@@ -262,6 +265,13 @@ export function JobsList({ bodyshop }) {
|
|||||||
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
|
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.comment"),
|
||||||
|
dataIndex: "comment",
|
||||||
|
key: "comment",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
},
|
||||||
// {
|
// {
|
||||||
// title: t("jobs.fields.owner_owing"),
|
// title: t("jobs.fields.owner_owing"),
|
||||||
// dataIndex: "owner_owing",
|
// dataIndex: "owner_owing",
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
import Icon from "@ant-design/icons";
|
||||||
|
import { useMutation } from "@apollo/client";
|
||||||
|
import { Button, Input, Popover } from "antd";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { FaRegStickyNote } from "react-icons/fa";
|
||||||
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
|
export default function ProductionListColumnComment({ record }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const [note, setNote] = useState(record.comment || "");
|
||||||
|
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
|
const [updateAlert] = useMutation(UPDATE_JOB);
|
||||||
|
|
||||||
|
const handleSaveNote = (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setVisible(false);
|
||||||
|
updateAlert({
|
||||||
|
variables: {
|
||||||
|
jobId: record.id,
|
||||||
|
job: {
|
||||||
|
comment: note,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}).then(() => {
|
||||||
|
if (record.refetch) record.refetch();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setNote(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVisibleChange = (flag) => {
|
||||||
|
setVisible(flag);
|
||||||
|
if (flag) setNote(record.comment || "");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
onVisibleChange={handleVisibleChange}
|
||||||
|
visible={visible}
|
||||||
|
content={
|
||||||
|
<div style={{ width: "30em" }}>
|
||||||
|
<Input.TextArea
|
||||||
|
rows={5}
|
||||||
|
value={note}
|
||||||
|
onChange={handleChange}
|
||||||
|
// onPressEnter={handleSaveNote}
|
||||||
|
autoFocus
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
<div>
|
||||||
|
<Button onClick={handleSaveNote}>
|
||||||
|
{t("general.actions.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
trigger={["click"]}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "19px",
|
||||||
|
cursor: "pointer",
|
||||||
|
overflow: "hidden",
|
||||||
|
textOverflow: "ellipsis",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon component={FaRegStickyNote} style={{ marginRight: ".2rem" }} />
|
||||||
|
{record.comment || " "}
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@ import ProductionListColumnNote from "./production-list-columns.productionnote.c
|
|||||||
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
import ProductionListColumnStatus from "./production-list-columns.status.component";
|
||||||
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
||||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||||
|
import ProductionListColumnComment from "./production-list-columns.comment.component";
|
||||||
|
|
||||||
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
||||||
return [
|
return [
|
||||||
@@ -109,7 +110,11 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
state.sortedInfo.columnKey === "scheduled_completion" &&
|
state.sortedInfo.columnKey === "scheduled_completion" &&
|
||||||
state.sortedInfo.order,
|
state.sortedInfo.order,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListDate record={record} field="scheduled_completion" pastIndicator />
|
<ProductionListDate
|
||||||
|
record={record}
|
||||||
|
field="scheduled_completion"
|
||||||
|
pastIndicator
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -156,7 +161,11 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
state.sortedInfo.columnKey === "scheduled_delivery" &&
|
state.sortedInfo.columnKey === "scheduled_delivery" &&
|
||||||
state.sortedInfo.order,
|
state.sortedInfo.order,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListDate record={record} field="scheduled_delivery" pastIndicator/>
|
<ProductionListDate
|
||||||
|
record={record}
|
||||||
|
field="scheduled_delivery"
|
||||||
|
pastIndicator
|
||||||
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -325,6 +334,13 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => <ProductionListColumnNote record={record} />,
|
render: (text, record) => <ProductionListColumnNote record={record} />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18n.t("production.labels.comment"),
|
||||||
|
dataIndex: "comment",
|
||||||
|
key: "comment",
|
||||||
|
ellipsis: true,
|
||||||
|
render: (text, record) => <ProductionListColumnComment record={record} />,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: i18n.t("production.labels.touchtime"),
|
title: i18n.t("production.labels.touchtime"),
|
||||||
dataIndex: "tt",
|
dataIndex: "tt",
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ export function ScheduleCalendarContainer({ calculateScheduleLoad }) {
|
|||||||
color: "red",
|
color: "red",
|
||||||
start: moment(e.start).startOf("day").toDate(),
|
start: moment(e.start).startOf("day").toDate(),
|
||||||
end: moment(e.end).startOf("day").toDate(),
|
end: moment(e.end).startOf("day").toDate(),
|
||||||
|
allDay: true,
|
||||||
vacation: true,
|
vacation: true,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { CalendarOutlined } from "@ant-design/icons";
|
import { CalendarOutlined } from "@ant-design/icons";
|
||||||
import { Card, Col, Row, Statistic } from "antd";
|
import { Card, Col, Row, Statistic } from "antd";
|
||||||
import React from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import ScoreboardJobsList from "../scoreboard-jobs-list/scoreboard-jobs-list.component";
|
import ScoreboardJobsList from "../scoreboard-jobs-list/scoreboard-jobs-list.component";
|
||||||
import * as Util from "./scoreboard-targets-table.util";
|
import * as Util from "./scoreboard-targets-table.util";
|
||||||
|
import _ from "lodash";
|
||||||
|
import moment from "moment";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -16,25 +18,78 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const rowGutter = [16, 16];
|
const rowGutter = [16, 16];
|
||||||
const statSpans = { xs: 24, sm: 6 };
|
const statSpans = { xs: 24, sm: 3 };
|
||||||
|
|
||||||
export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const values = useMemo(() => {
|
||||||
|
const dateHash = _.groupBy(scoreBoardlist, "date");
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: scoreboard-targets-table.component.jsx ~ line 31 ~ values ~ dateHash",
|
||||||
|
dateHash
|
||||||
|
);
|
||||||
|
|
||||||
|
let ret = {
|
||||||
|
todayBody: 0,
|
||||||
|
todayPaint: 0,
|
||||||
|
weeklyPaint: 0,
|
||||||
|
weeklyBody: 0,
|
||||||
|
toDateBody: 0,
|
||||||
|
toDatePaint: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const today = moment().tz(bodyshop.timezone);
|
||||||
|
if (dateHash[today.format("YYYY-MM-DD")]) {
|
||||||
|
dateHash[today.format("YYYY-MM-DD")].forEach((d) => {
|
||||||
|
ret.todayBody = ret.todayBody + d.bodyhrs;
|
||||||
|
ret.todayPaint = ret.todayPaint + d.painthrs;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let StartOfWeek = moment().tz(bodyshop.timezone).startOf("week");
|
||||||
|
while (StartOfWeek.isSameOrBefore(today)) {
|
||||||
|
if (dateHash[StartOfWeek.format("YYYY-MM-DD")]) {
|
||||||
|
dateHash[StartOfWeek.format("YYYY-MM-DD")].forEach((d) => {
|
||||||
|
ret.weeklyBody = ret.weeklyBody + d.bodyhrs;
|
||||||
|
ret.weeklyPaint = ret.weeklyPaint + d.painthrs;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
StartOfWeek = StartOfWeek.add(1, "day");
|
||||||
|
}
|
||||||
|
|
||||||
|
let startOfMonth = moment().tz(bodyshop.timezone).startOf("month");
|
||||||
|
while (startOfMonth.isSameOrBefore(today)) {
|
||||||
|
if (dateHash[startOfMonth.format("YYYY-MM-DD")]) {
|
||||||
|
dateHash[startOfMonth.format("YYYY-MM-DD")].forEach((d) => {
|
||||||
|
ret.toDateBody = ret.toDateBody + d.bodyhrs;
|
||||||
|
ret.toDatePaint = ret.toDatePaint + d.painthrs;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
startOfMonth = startOfMonth.add(1, "day");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}, [scoreBoardlist, bodyshop.timezone]);
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: scoreboard-targets-table.component.jsx ~ line 51 ~ values ~ values",
|
||||||
|
values
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
title={t("scoreboard.labels.targets")}
|
title={t("scoreboard.labels.targets")}
|
||||||
extra={<ScoreboardJobsList scoreBoardlist={scoreBoardlist} />}
|
extra={<ScoreboardJobsList scoreBoardlist={scoreBoardlist} />}
|
||||||
>
|
>
|
||||||
<Row gutter={rowGutter}>
|
<Row gutter={rowGutter}>
|
||||||
<Col xs={24} sm={{ offset: 0, span: 4 }} lg={{ offset: 5, span: 4 }}>
|
<Col xs={24} sm={{ offset: 0, span: 4 }} lg={{ span: 4 }}>
|
||||||
<Statistic
|
<Statistic
|
||||||
title={t("scoreboard.labels.workingdays")}
|
title={t("scoreboard.labels.workingdays")}
|
||||||
value={Util.CalculateWorkingDaysThisMonth()}
|
value={Util.CalculateWorkingDaysThisMonth()}
|
||||||
prefix={<CalendarOutlined />}
|
prefix={<CalendarOutlined />}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<Col xs={24} sm={{ offset: 0, span: 20 }} lg={{ offset: 0, span: 13 }}>
|
<Col xs={24} sm={{ offset: 0, span: 20 }} lg={{ offset: 0, span: 20 }}>
|
||||||
<Row>
|
<Row>
|
||||||
<Col {...statSpans}>
|
<Col {...statSpans}>
|
||||||
<Statistic
|
<Statistic
|
||||||
@@ -43,6 +98,12 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
|||||||
prefix="B"
|
prefix="B"
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...statSpans}>
|
||||||
|
<Statistic
|
||||||
|
title={t("scoreboard.labels.dailyactual")}
|
||||||
|
value={values.todayBody}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
<Col {...statSpans}>
|
<Col {...statSpans}>
|
||||||
<Statistic
|
<Statistic
|
||||||
title={t("scoreboard.labels.weeklytarget")}
|
title={t("scoreboard.labels.weeklytarget")}
|
||||||
@@ -52,6 +113,12 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...statSpans}>
|
||||||
|
<Statistic
|
||||||
|
title={t("scoreboard.labels.weeklyactual")}
|
||||||
|
value={values.weeklyBody}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
<Col {...statSpans}>
|
<Col {...statSpans}>
|
||||||
<Statistic
|
<Statistic
|
||||||
title={t("scoreboard.labels.monthlytarget")}
|
title={t("scoreboard.labels.monthlytarget")}
|
||||||
@@ -70,6 +137,12 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...statSpans}>
|
||||||
|
<Statistic
|
||||||
|
title={t("scoreboard.labels.todateactual")}
|
||||||
|
value={values.toDateBody}
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<Col {...statSpans}>
|
<Col {...statSpans}>
|
||||||
@@ -78,6 +151,9 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
|||||||
prefix="P"
|
prefix="P"
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...statSpans}>
|
||||||
|
<Statistic value={values.todayPaint} />
|
||||||
|
</Col>
|
||||||
<Col {...statSpans}>
|
<Col {...statSpans}>
|
||||||
<Statistic
|
<Statistic
|
||||||
value={Util.WeeklyTargetHrs(
|
value={Util.WeeklyTargetHrs(
|
||||||
@@ -86,6 +162,9 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...statSpans}>
|
||||||
|
<Statistic value={values.weeklyPaint} />
|
||||||
|
</Col>
|
||||||
<Col {...statSpans}>
|
<Col {...statSpans}>
|
||||||
<Statistic
|
<Statistic
|
||||||
value={Util.MonthlyTargetHrs(
|
value={Util.MonthlyTargetHrs(
|
||||||
@@ -102,6 +181,9 @@ export function ScoreboardTargetsTable({ bodyshop, scoreBoardlist }) {
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
|
<Col {...statSpans}>
|
||||||
|
<Statistic value={values.toDatePaint} />
|
||||||
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
import FormItemEmail from "../form-items-formatted/email-form-item.component";
|
import FormItemEmail from "../form-items-formatted/email-form-item.component";
|
||||||
|
|
||||||
|
import momentTZ from "moment-timezone";
|
||||||
|
const timeZonesList = momentTZ.tz.names();
|
||||||
|
|
||||||
export default function ShopInfoGeneral({ form }) {
|
export default function ShopInfoGeneral({ form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
@@ -84,6 +87,7 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
<Form.Item label={t("bodyshop.fields.email")} name="email">
|
<Form.Item label={t("bodyshop.fields.email")} name="email">
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.phone")}
|
label={t("bodyshop.fields.phone")}
|
||||||
name="phone"
|
name="phone"
|
||||||
@@ -97,6 +101,23 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
<Form.Item label={t("bodyshop.fields.website")} name="website">
|
<Form.Item label={t("bodyshop.fields.website")} name="website">
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.timezone")}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
name="timezone"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
showSearch
|
||||||
|
options={timeZonesList.map((z) => {
|
||||||
|
return { label: z, value: z };
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.fields.insurance_vendor_id")}
|
label={t("bodyshop.fields.insurance_vendor_id")}
|
||||||
name="insurance_vendor_id"
|
name="insurance_vendor_id"
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ export default function VendorsFormComponent({
|
|||||||
<InputNumber min={0} max={1} precision={2} step={0.01} />
|
<InputNumber min={0} max={1} precision={2} step={0.01} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("vendors.fields.due_date")} name="due_date">
|
<Form.Item label={t("vendors.fields.due_date")} name="due_date">
|
||||||
<InputNumber />
|
<InputNumber min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{
|
||||||
// <Form.Item
|
// <Form.Item
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ export const QUERY_BODYSHOP = gql`
|
|||||||
pbs_serialnumber
|
pbs_serialnumber
|
||||||
md_filehandlers
|
md_filehandlers
|
||||||
md_email_cc
|
md_email_cc
|
||||||
|
timezone
|
||||||
employees {
|
employees {
|
||||||
user_email
|
user_email
|
||||||
id
|
id
|
||||||
@@ -197,6 +198,7 @@ export const UPDATE_SHOP = gql`
|
|||||||
pbs_serialnumber
|
pbs_serialnumber
|
||||||
md_filehandlers
|
md_filehandlers
|
||||||
md_email_cc
|
md_email_cc
|
||||||
|
timezone
|
||||||
employees {
|
employees {
|
||||||
id
|
id
|
||||||
first_name
|
first_name
|
||||||
|
|||||||
@@ -12,11 +12,7 @@ export const QUERY_ALL_ACTIVE_JOBS = gql`
|
|||||||
ownr_ph1
|
ownr_ph1
|
||||||
ownr_ph2
|
ownr_ph2
|
||||||
ownr_ea
|
ownr_ea
|
||||||
owner {
|
comment
|
||||||
id
|
|
||||||
allow_text_message
|
|
||||||
preferred_contact
|
|
||||||
}
|
|
||||||
plate_no
|
plate_no
|
||||||
plate_st
|
plate_st
|
||||||
v_vin
|
v_vin
|
||||||
@@ -121,6 +117,7 @@ export const QUERY_EXACT_JOB_IN_PRODUCTION = gql`
|
|||||||
id
|
id
|
||||||
status
|
status
|
||||||
ro_number
|
ro_number
|
||||||
|
comment
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
category
|
category
|
||||||
@@ -193,6 +190,7 @@ export const QUERY_EXACT_JOBS_IN_PRODUCTION = gql`
|
|||||||
id
|
id
|
||||||
status
|
status
|
||||||
ro_number
|
ro_number
|
||||||
|
comment
|
||||||
ownr_fn
|
ownr_fn
|
||||||
category
|
category
|
||||||
ownr_ln
|
ownr_ln
|
||||||
@@ -264,6 +262,7 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
|
|||||||
jobs(where: { inproduction: { _eq: true } }) {
|
jobs(where: { inproduction: { _eq: true } }) {
|
||||||
id
|
id
|
||||||
updated_at
|
updated_at
|
||||||
|
comment
|
||||||
status
|
status
|
||||||
category
|
category
|
||||||
ro_number
|
ro_number
|
||||||
@@ -489,6 +488,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
alt_transport
|
alt_transport
|
||||||
intakechecklist
|
intakechecklist
|
||||||
invoice_final_note
|
invoice_final_note
|
||||||
|
comment
|
||||||
loss_desc
|
loss_desc
|
||||||
kmin
|
kmin
|
||||||
kmout
|
kmout
|
||||||
@@ -830,6 +830,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
|
|||||||
ownr_co_nm
|
ownr_co_nm
|
||||||
ownr_ph1
|
ownr_ph1
|
||||||
ownr_ph2
|
ownr_ph2
|
||||||
|
comment
|
||||||
ownr_ea
|
ownr_ea
|
||||||
ca_gst_registrant
|
ca_gst_registrant
|
||||||
owner_owing
|
owner_owing
|
||||||
@@ -1034,7 +1035,7 @@ export const UPDATE_JOB = gql`
|
|||||||
update_jobs(where: { id: { _eq: $jobId } }, _set: $job) {
|
update_jobs(where: { id: { _eq: $jobId } }, _set: $job) {
|
||||||
returning {
|
returning {
|
||||||
id
|
id
|
||||||
|
comment
|
||||||
date_exported
|
date_exported
|
||||||
status
|
status
|
||||||
alt_transport
|
alt_transport
|
||||||
@@ -1766,13 +1767,12 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql`
|
|||||||
order_by: $order
|
order_by: $order
|
||||||
where: { status: { _in: $statusList } }
|
where: { status: { _in: $statusList } }
|
||||||
) {
|
) {
|
||||||
|
comment
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
ownr_co_nm
|
ownr_co_nm
|
||||||
ownerid
|
|
||||||
ownr_ph1
|
ownr_ph1
|
||||||
ownr_ph2
|
ownr_ph2
|
||||||
ownr_ea
|
|
||||||
plate_no
|
plate_no
|
||||||
plate_st
|
plate_st
|
||||||
v_vin
|
v_vin
|
||||||
@@ -1781,32 +1781,16 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql`
|
|||||||
v_make_desc
|
v_make_desc
|
||||||
v_color
|
v_color
|
||||||
vehicleid
|
vehicleid
|
||||||
actual_completion
|
|
||||||
actual_delivery
|
|
||||||
actual_in
|
|
||||||
id
|
id
|
||||||
ins_co_nm
|
ins_co_nm
|
||||||
ins_ct_fn
|
|
||||||
ins_ct_ln
|
|
||||||
ins_ph1
|
|
||||||
ins_ea
|
|
||||||
est_co_nm
|
|
||||||
est_ph1
|
|
||||||
est_ea
|
|
||||||
est_ct_fn
|
|
||||||
est_ct_ln
|
|
||||||
clm_no
|
clm_no
|
||||||
clm_total
|
clm_total
|
||||||
owner_owing
|
owner_owing
|
||||||
ro_number
|
ro_number
|
||||||
po_number
|
po_number
|
||||||
scheduled_completion
|
|
||||||
scheduled_in
|
|
||||||
scheduled_delivery
|
|
||||||
status
|
status
|
||||||
updated_at
|
updated_at
|
||||||
ded_amt
|
ded_amt
|
||||||
vehicleid
|
|
||||||
}
|
}
|
||||||
search_jobs_aggregate(
|
search_jobs_aggregate(
|
||||||
args: { search: $search }
|
args: { search: $search }
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ import UserActionTypes from "./user.types";
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { messaging } from "../../firebase/firebase.utils";
|
import { messaging } from "../../firebase/firebase.utils";
|
||||||
import { getToken } from "firebase/messaging";
|
import { getToken } from "firebase/messaging";
|
||||||
|
|
||||||
|
import moment from "moment-timezone";
|
||||||
|
|
||||||
export function* onEmailSignInStart() {
|
export function* onEmailSignInStart() {
|
||||||
yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
|
yield takeLatest(UserActionTypes.EMAIL_SIGN_IN_START, signInWithEmail);
|
||||||
}
|
}
|
||||||
@@ -266,6 +269,12 @@ export function* onSetShopDetails() {
|
|||||||
export function* SetAuthLevelFromShopDetails({ payload }) {
|
export function* SetAuthLevelFromShopDetails({ payload }) {
|
||||||
try {
|
try {
|
||||||
const userEmail = yield select((state) => state.user.currentUser.email);
|
const userEmail = yield select((state) => state.user.currentUser.email);
|
||||||
|
try {
|
||||||
|
console.log("Setting shop timezone.");
|
||||||
|
moment.tz.setDefault(payload.timezone);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
factory.client(payload.imexshopid);
|
factory.client(payload.imexshopid);
|
||||||
|
|
||||||
|
|||||||
@@ -183,6 +183,7 @@
|
|||||||
"federal_tax": "Federal Tax",
|
"federal_tax": "Federal Tax",
|
||||||
"iouexists": "An IOU exists that is associated to this RO.",
|
"iouexists": "An IOU exists that is associated to this RO.",
|
||||||
"local_tax": "Local Tax",
|
"local_tax": "Local Tax",
|
||||||
|
"markexported": "Mark Exported",
|
||||||
"markforreexport": "Mark for Re-export",
|
"markforreexport": "Mark for Re-export",
|
||||||
"new": "New Bill",
|
"new": "New Bill",
|
||||||
"noneselected": "No bill selected.",
|
"noneselected": "No bill selected.",
|
||||||
@@ -197,6 +198,7 @@
|
|||||||
"created": "Invoice added successfully.",
|
"created": "Invoice added successfully.",
|
||||||
"deleted": "Bill deleted successfully.",
|
"deleted": "Bill deleted successfully.",
|
||||||
"exported": "Bill(s) exported successfully.",
|
"exported": "Bill(s) exported successfully.",
|
||||||
|
"markexported": "Bill marked as exported.",
|
||||||
"reexport": "Bill marked for re-export."
|
"reexport": "Bill marked for re-export."
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
@@ -483,6 +485,7 @@
|
|||||||
"production_statuses": "Production Statuses"
|
"production_statuses": "Production Statuses"
|
||||||
},
|
},
|
||||||
"target_touchtime": "Target Touch Time",
|
"target_touchtime": "Target Touch Time",
|
||||||
|
"timezone": "Timezone",
|
||||||
"tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs",
|
"tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs",
|
||||||
"use_fippa": "Use FIPPA for Names on Generated Documents?",
|
"use_fippa": "Use FIPPA for Names on Generated Documents?",
|
||||||
"website": "Website",
|
"website": "Website",
|
||||||
@@ -1242,6 +1245,7 @@
|
|||||||
"class": "Class",
|
"class": "Class",
|
||||||
"clm_no": "Claim #",
|
"clm_no": "Claim #",
|
||||||
"clm_total": "Claim Total",
|
"clm_total": "Claim Total",
|
||||||
|
"comment": "Comment",
|
||||||
"customerowing": "Customer Owing",
|
"customerowing": "Customer Owing",
|
||||||
"date_estimated": "Date Estimated",
|
"date_estimated": "Date Estimated",
|
||||||
"date_exported": "Exported",
|
"date_exported": "Exported",
|
||||||
@@ -1553,7 +1557,7 @@
|
|||||||
"partstotal": "Parts Total (ex. Taxes)",
|
"partstotal": "Parts Total (ex. Taxes)",
|
||||||
"plitooltips": {
|
"plitooltips": {
|
||||||
"billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).",
|
"billtotal": "The total amount of all bill lines that have been posted against this RO (not including credits, taxes, or labor adjustments).",
|
||||||
"creditmemos": "The total amount of all credit memos entered. This amount does not reflect any parts returns created.",
|
"creditmemos": "The total amount of all returns created. This amount does not reflect credit memos that have been posted.",
|
||||||
"creditsnotreceived": "The total amount of returns created for this job that do not have a corresponding credit memo posted. An amount greater than $0 indicates that vendors have not provided requested credit memos.",
|
"creditsnotreceived": "The total amount of returns created for this job that do not have a corresponding credit memo posted. An amount greater than $0 indicates that vendors have not provided requested credit memos.",
|
||||||
"discrep1": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Too many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned.</li>\n<li>You do not have the latest supplement imported, or, a supplement must be submitted and then imported.</li>\n<li>You have posted a bill line to labor.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>",
|
"discrep1": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Too many bills/bill lines that have been posted against this RO. Check to make sure every bill posted on this RO is correctly posted and assigned.</li>\n<li>You do not have the latest supplement imported, or, a supplement must be submitted and then imported.</li>\n<li>You have posted a bill line to labor.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>",
|
||||||
"discrep2": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Used an incorrect rate when deducting from labor.</li>\n<li>An outstanding imbalance higher in the reconciliation process.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>",
|
"discrep2": "If the discrepancy is not $0, you may have one of the following: <br/><br/>\n\n<ul>\n<li>Used an incorrect rate when deducting from labor.</li>\n<li>An outstanding imbalance higher in the reconciliation process.</li>\n</ul>\n<br/>\n<i>There may be additional issues not listed above that prevent this job from reconciling.</i>",
|
||||||
@@ -2150,6 +2154,7 @@
|
|||||||
"bodypriority": "B/P",
|
"bodypriority": "B/P",
|
||||||
"cardsettings": "Card Settings",
|
"cardsettings": "Card Settings",
|
||||||
"clm_no": "Claim Number",
|
"clm_no": "Claim Number",
|
||||||
|
"comment": "Comment",
|
||||||
"compact": "Compact Cards",
|
"compact": "Compact Cards",
|
||||||
"detailpriority": "D/P",
|
"detailpriority": "D/P",
|
||||||
"employeeassignments": "Employee Assignments",
|
"employeeassignments": "Employee Assignments",
|
||||||
@@ -2315,9 +2320,12 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"asoftodaytarget": "As of Today",
|
"asoftodaytarget": "As of Today",
|
||||||
|
"dailyactual": "Actual (D)",
|
||||||
"dailytarget": "Daily",
|
"dailytarget": "Daily",
|
||||||
"monthlytarget": "Monthly",
|
"monthlytarget": "Monthly",
|
||||||
"targets": "Targets",
|
"targets": "Targets",
|
||||||
|
"todateactual": "Actual (MTD)",
|
||||||
|
"weeklyactual": "Actual (W)",
|
||||||
"weeklytarget": "Weekly",
|
"weeklytarget": "Weekly",
|
||||||
"workingdays": "Working Days / Month"
|
"workingdays": "Working Days / Month"
|
||||||
},
|
},
|
||||||
@@ -2588,7 +2596,7 @@
|
|||||||
"country": "Country",
|
"country": "Country",
|
||||||
"discount": "Discount % (as decimal)",
|
"discount": "Discount % (as decimal)",
|
||||||
"display_name": "Display Name",
|
"display_name": "Display Name",
|
||||||
"due_date": "Payment Due Date",
|
"due_date": "Payment Due Date (# of days)",
|
||||||
"email": "Contact Email",
|
"email": "Contact Email",
|
||||||
"favorite": "Favorite?",
|
"favorite": "Favorite?",
|
||||||
"lkq": "LKQ",
|
"lkq": "LKQ",
|
||||||
|
|||||||
@@ -183,6 +183,7 @@
|
|||||||
"federal_tax": "",
|
"federal_tax": "",
|
||||||
"iouexists": "",
|
"iouexists": "",
|
||||||
"local_tax": "",
|
"local_tax": "",
|
||||||
|
"markexported": "",
|
||||||
"markforreexport": "",
|
"markforreexport": "",
|
||||||
"new": "",
|
"new": "",
|
||||||
"noneselected": "",
|
"noneselected": "",
|
||||||
@@ -197,6 +198,7 @@
|
|||||||
"created": "",
|
"created": "",
|
||||||
"deleted": "",
|
"deleted": "",
|
||||||
"exported": "",
|
"exported": "",
|
||||||
|
"markexported": "",
|
||||||
"reexport": ""
|
"reexport": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
@@ -483,6 +485,7 @@
|
|||||||
"production_statuses": ""
|
"production_statuses": ""
|
||||||
},
|
},
|
||||||
"target_touchtime": "",
|
"target_touchtime": "",
|
||||||
|
"timezone": "",
|
||||||
"tt_allow_post_to_invoiced": "",
|
"tt_allow_post_to_invoiced": "",
|
||||||
"use_fippa": "",
|
"use_fippa": "",
|
||||||
"website": "",
|
"website": "",
|
||||||
@@ -1242,6 +1245,7 @@
|
|||||||
"class": "",
|
"class": "",
|
||||||
"clm_no": "Reclamación #",
|
"clm_no": "Reclamación #",
|
||||||
"clm_total": "Reclamar total",
|
"clm_total": "Reclamar total",
|
||||||
|
"comment": "",
|
||||||
"customerowing": "Cliente debido",
|
"customerowing": "Cliente debido",
|
||||||
"date_estimated": "Fecha estimada",
|
"date_estimated": "Fecha estimada",
|
||||||
"date_exported": "Exportado",
|
"date_exported": "Exportado",
|
||||||
@@ -2150,6 +2154,7 @@
|
|||||||
"bodypriority": "",
|
"bodypriority": "",
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
|
"comment": "",
|
||||||
"compact": "",
|
"compact": "",
|
||||||
"detailpriority": "",
|
"detailpriority": "",
|
||||||
"employeeassignments": "",
|
"employeeassignments": "",
|
||||||
@@ -2315,9 +2320,12 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"asoftodaytarget": "",
|
"asoftodaytarget": "",
|
||||||
|
"dailyactual": "",
|
||||||
"dailytarget": "",
|
"dailytarget": "",
|
||||||
"monthlytarget": "",
|
"monthlytarget": "",
|
||||||
"targets": "",
|
"targets": "",
|
||||||
|
"todateactual": "",
|
||||||
|
"weeklyactual": "",
|
||||||
"weeklytarget": "",
|
"weeklytarget": "",
|
||||||
"workingdays": ""
|
"workingdays": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -183,6 +183,7 @@
|
|||||||
"federal_tax": "",
|
"federal_tax": "",
|
||||||
"iouexists": "",
|
"iouexists": "",
|
||||||
"local_tax": "",
|
"local_tax": "",
|
||||||
|
"markexported": "",
|
||||||
"markforreexport": "",
|
"markforreexport": "",
|
||||||
"new": "",
|
"new": "",
|
||||||
"noneselected": "",
|
"noneselected": "",
|
||||||
@@ -197,6 +198,7 @@
|
|||||||
"created": "",
|
"created": "",
|
||||||
"deleted": "",
|
"deleted": "",
|
||||||
"exported": "",
|
"exported": "",
|
||||||
|
"markexported": "",
|
||||||
"reexport": ""
|
"reexport": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
@@ -483,6 +485,7 @@
|
|||||||
"production_statuses": ""
|
"production_statuses": ""
|
||||||
},
|
},
|
||||||
"target_touchtime": "",
|
"target_touchtime": "",
|
||||||
|
"timezone": "",
|
||||||
"tt_allow_post_to_invoiced": "",
|
"tt_allow_post_to_invoiced": "",
|
||||||
"use_fippa": "",
|
"use_fippa": "",
|
||||||
"website": "",
|
"website": "",
|
||||||
@@ -1242,6 +1245,7 @@
|
|||||||
"class": "",
|
"class": "",
|
||||||
"clm_no": "Prétendre #",
|
"clm_no": "Prétendre #",
|
||||||
"clm_total": "Total réclamation",
|
"clm_total": "Total réclamation",
|
||||||
|
"comment": "",
|
||||||
"customerowing": "Client propriétaire",
|
"customerowing": "Client propriétaire",
|
||||||
"date_estimated": "Date estimée",
|
"date_estimated": "Date estimée",
|
||||||
"date_exported": "Exportés",
|
"date_exported": "Exportés",
|
||||||
@@ -2150,6 +2154,7 @@
|
|||||||
"bodypriority": "",
|
"bodypriority": "",
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
|
"comment": "",
|
||||||
"compact": "",
|
"compact": "",
|
||||||
"detailpriority": "",
|
"detailpriority": "",
|
||||||
"employeeassignments": "",
|
"employeeassignments": "",
|
||||||
@@ -2315,9 +2320,12 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"asoftodaytarget": "",
|
"asoftodaytarget": "",
|
||||||
|
"dailyactual": "",
|
||||||
"dailytarget": "",
|
"dailytarget": "",
|
||||||
"monthlytarget": "",
|
"monthlytarget": "",
|
||||||
"targets": "",
|
"targets": "",
|
||||||
|
"todateactual": "",
|
||||||
|
"weeklyactual": "",
|
||||||
"weeklytarget": "",
|
"weeklytarget": "",
|
||||||
"workingdays": ""
|
"workingdays": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9460,7 +9460,14 @@ moment-business-days@^1.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/moment-business-days/-/moment-business-days-1.2.0.tgz#6172f9f38dbf443c2f859baabeabbd2935f63d65"
|
resolved "https://registry.yarnpkg.com/moment-business-days/-/moment-business-days-1.2.0.tgz#6172f9f38dbf443c2f859baabeabbd2935f63d65"
|
||||||
integrity sha512-QJlceLfMSxy/jZSOgJYCKeKw+qGYHj8W0jMa/fYruyoJ85+bJuLRiYv5DIaflyuRipmYRfD4kDlSwVYteLN+Jw==
|
integrity sha512-QJlceLfMSxy/jZSOgJYCKeKw+qGYHj8W0jMa/fYruyoJ85+bJuLRiYv5DIaflyuRipmYRfD4kDlSwVYteLN+Jw==
|
||||||
|
|
||||||
moment@^2.24.0, moment@^2.25.3:
|
moment-timezone@^0.5.34:
|
||||||
|
version "0.5.34"
|
||||||
|
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c"
|
||||||
|
integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==
|
||||||
|
dependencies:
|
||||||
|
moment ">= 2.9.0"
|
||||||
|
|
||||||
|
"moment@>= 2.9.0", moment@^2.24.0, moment@^2.25.3:
|
||||||
version "2.29.1"
|
version "2.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||||
|
|||||||
@@ -867,6 +867,7 @@
|
|||||||
- target_touchtime
|
- target_touchtime
|
||||||
- template_header
|
- template_header
|
||||||
- textid
|
- textid
|
||||||
|
- timezone
|
||||||
- tt_allow_post_to_invoiced
|
- tt_allow_post_to_invoiced
|
||||||
- updated_at
|
- updated_at
|
||||||
- use_fippa
|
- use_fippa
|
||||||
@@ -939,6 +940,7 @@
|
|||||||
- state
|
- state
|
||||||
- state_tax_id
|
- state_tax_id
|
||||||
- target_touchtime
|
- target_touchtime
|
||||||
|
- timezone
|
||||||
- tt_allow_post_to_invoiced
|
- tt_allow_post_to_invoiced
|
||||||
- updated_at
|
- updated_at
|
||||||
- use_fippa
|
- use_fippa
|
||||||
@@ -2707,6 +2709,7 @@
|
|||||||
- clm_title
|
- clm_title
|
||||||
- clm_total
|
- clm_total
|
||||||
- clm_zip
|
- clm_zip
|
||||||
|
- comment
|
||||||
- converted
|
- converted
|
||||||
- created_at
|
- created_at
|
||||||
- cust_pr
|
- cust_pr
|
||||||
@@ -2963,6 +2966,7 @@
|
|||||||
- clm_title
|
- clm_title
|
||||||
- clm_total
|
- clm_total
|
||||||
- clm_zip
|
- clm_zip
|
||||||
|
- comment
|
||||||
- converted
|
- converted
|
||||||
- created_at
|
- created_at
|
||||||
- cust_pr
|
- cust_pr
|
||||||
@@ -3229,6 +3233,7 @@
|
|||||||
- clm_title
|
- clm_title
|
||||||
- clm_total
|
- clm_total
|
||||||
- clm_zip
|
- clm_zip
|
||||||
|
- comment
|
||||||
- converted
|
- converted
|
||||||
- created_at
|
- created_at
|
||||||
- cust_pr
|
- cust_pr
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."bodyshops" add column "timezone" text
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."bodyshops" add column "timezone" text
|
||||||
|
null;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."jobs" add column "comment" text
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."jobs" add column "comment" text
|
||||||
|
null;
|
||||||
@@ -37,6 +37,7 @@
|
|||||||
"intuit-oauth": "^4.0.0",
|
"intuit-oauth": "^4.0.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment": "^2.29.1",
|
"moment": "^2.29.1",
|
||||||
|
"moment-timezone": "^0.5.34",
|
||||||
"node-mailjet": "^3.3.4",
|
"node-mailjet": "^3.3.4",
|
||||||
"node-quickbooks": "^2.0.39",
|
"node-quickbooks": "^2.0.39",
|
||||||
"nodemailer": "^6.7.1",
|
"nodemailer": "^6.7.1",
|
||||||
|
|||||||
@@ -14,9 +14,10 @@ const { PBS_ENDPOINTS, PBS_CREDENTIALS } = require("./pbs-constants");
|
|||||||
const CalculateAllocations =
|
const CalculateAllocations =
|
||||||
require("../../cdk/cdk-calculate-allocations").default;
|
require("../../cdk/cdk-calculate-allocations").default;
|
||||||
const CdkBase = require("../../web-sockets/web-socket");
|
const CdkBase = require("../../web-sockets/web-socket");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
const axios = AxiosLib.create();
|
const axios = AxiosLib.create();
|
||||||
|
|
||||||
axios.interceptors.request.use((x) => {
|
axios.interceptors.request.use((x) => {
|
||||||
const socket = x.socket;
|
const socket = x.socket;
|
||||||
|
|
||||||
@@ -553,7 +554,9 @@ async function InsertAccountPostingData(socket) {
|
|||||||
//Comment: "String",
|
//Comment: "String",
|
||||||
//AdditionalInfo: "String",
|
//AdditionalInfo: "String",
|
||||||
InvoiceNumber: socket.JobData.ro_number,
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
InvoiceDate: moment(socket.JobData.date_invoiced)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
};
|
};
|
||||||
wips.push(item);
|
wips.push(item);
|
||||||
}
|
}
|
||||||
@@ -567,7 +570,9 @@ async function InsertAccountPostingData(socket) {
|
|||||||
//Comment: "String",
|
//Comment: "String",
|
||||||
//AdditionalInfo: "String",
|
//AdditionalInfo: "String",
|
||||||
InvoiceNumber: socket.JobData.ro_number,
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
InvoiceDate: moment(socket.JobData.date_invoiced)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
};
|
};
|
||||||
wips.push(item);
|
wips.push(item);
|
||||||
|
|
||||||
@@ -578,7 +583,9 @@ async function InsertAccountPostingData(socket) {
|
|||||||
//Comment: "String",
|
//Comment: "String",
|
||||||
//AdditionalInfo: "String",
|
//AdditionalInfo: "String",
|
||||||
InvoiceNumber: socket.JobData.ro_number,
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
InvoiceDate: moment(socket.JobData.date_invoiced)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
};
|
};
|
||||||
wips.push(itemWip);
|
wips.push(itemWip);
|
||||||
//Add to the WIP account.
|
//Add to the WIP account.
|
||||||
@@ -593,7 +600,9 @@ async function InsertAccountPostingData(socket) {
|
|||||||
//Comment: "String",
|
//Comment: "String",
|
||||||
//AdditionalInfo: "String",
|
//AdditionalInfo: "String",
|
||||||
InvoiceNumber: socket.JobData.ro_number,
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
InvoiceDate: moment(socket.JobData.date_invoiced)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
};
|
};
|
||||||
wips.push(item2);
|
wips.push(item2);
|
||||||
}
|
}
|
||||||
@@ -609,7 +618,9 @@ async function InsertAccountPostingData(socket) {
|
|||||||
//Comment: "String",
|
//Comment: "String",
|
||||||
//AdditionalInfo: "String",
|
//AdditionalInfo: "String",
|
||||||
InvoiceNumber: socket.JobData.ro_number,
|
InvoiceNumber: socket.JobData.ro_number,
|
||||||
InvoiceDate: moment(socket.JobData.date_invoiced).toISOString(),
|
InvoiceDate: moment(socket.JobData.date_invoiced)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
wips.push(item);
|
wips.push(item);
|
||||||
@@ -622,7 +633,9 @@ async function InsertAccountPostingData(socket) {
|
|||||||
Posting: {
|
Posting: {
|
||||||
Reference: socket.JobData.ro_number,
|
Reference: socket.JobData.ro_number,
|
||||||
JournalCode: socket.txEnvelope.journal,
|
JournalCode: socket.txEnvelope.journal,
|
||||||
TransactionDate: moment(socket.JobData.date_invoiced).toISOString(), //"0001-01-01T00:00:00.0000000Z",
|
TransactionDate: moment(socket.JobData.date_invoiced)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(), //"0001-01-01T00:00:00.0000000Z",
|
||||||
Description: socket.txEnvelope.story,
|
Description: socket.txEnvelope.story,
|
||||||
//AdditionalInfo: "String",
|
//AdditionalInfo: "String",
|
||||||
Source: "ImEX Online",
|
Source: "ImEX Online",
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const {
|
|||||||
setNewRefreshToken,
|
setNewRefreshToken,
|
||||||
} = require("./qbo-callback");
|
} = require("./qbo-callback");
|
||||||
const OAuthClient = require("intuit-oauth");
|
const OAuthClient = require("intuit-oauth");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||||
const findTaxCode = require("../qb-receivables-lines").findTaxCode;
|
const findTaxCode = require("../qb-receivables-lines").findTaxCode;
|
||||||
|
|
||||||
@@ -178,8 +178,15 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
|||||||
VendorRef: {
|
VendorRef: {
|
||||||
value: vendor.Id,
|
value: vendor.Id,
|
||||||
},
|
},
|
||||||
TxnDate: moment(bill.date).format("YYYY-MM-DD"),
|
TxnDate: moment(bill.date)
|
||||||
//DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
|
.tz(bill.job.bodyshop.timezone)
|
||||||
|
.format("YYYY-MM-DD"),
|
||||||
|
...(bill.vendor.due_date && {
|
||||||
|
DueDate: moment(bill.date)
|
||||||
|
.tz(bill.job.bodyshop.timezone)
|
||||||
|
.add(bill.vendor.due_date, "days")
|
||||||
|
.format("YYYY-MM-DD"),
|
||||||
|
}),
|
||||||
DocNumber: bill.invoice_number,
|
DocNumber: bill.invoice_number,
|
||||||
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const {
|
|||||||
setNewRefreshToken,
|
setNewRefreshToken,
|
||||||
} = require("./qbo-callback");
|
} = require("./qbo-callback");
|
||||||
const OAuthClient = require("intuit-oauth");
|
const OAuthClient = require("intuit-oauth");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||||
const {
|
const {
|
||||||
QueryInsuranceCo,
|
QueryInsuranceCo,
|
||||||
@@ -137,14 +137,22 @@ exports.default = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (payment.amount > 0) {
|
if (payment.amount > 0) {
|
||||||
await InsertPayment(oauthClient, qbo_realmId, req, payment, jobTier);
|
await InsertPayment(
|
||||||
|
oauthClient,
|
||||||
|
qbo_realmId,
|
||||||
|
req,
|
||||||
|
payment,
|
||||||
|
jobTier,
|
||||||
|
bodyshop
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
await InsertCreditMemo(
|
await InsertCreditMemo(
|
||||||
oauthClient,
|
oauthClient,
|
||||||
qbo_realmId,
|
qbo_realmId,
|
||||||
req,
|
req,
|
||||||
payment,
|
payment,
|
||||||
jobTier
|
jobTier,
|
||||||
|
bodyshop
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ret.push({ paymentid: payment.id, success: true });
|
ret.push({ paymentid: payment.id, success: true });
|
||||||
@@ -178,7 +186,8 @@ async function InsertPayment(
|
|||||||
qbo_realmId,
|
qbo_realmId,
|
||||||
req,
|
req,
|
||||||
payment,
|
payment,
|
||||||
parentRef
|
parentRef,
|
||||||
|
bodyshop
|
||||||
) {
|
) {
|
||||||
const { paymentMethods, invoices } = await QueryMetaData(
|
const { paymentMethods, invoices } = await QueryMetaData(
|
||||||
oauthClient,
|
oauthClient,
|
||||||
@@ -198,7 +207,7 @@ async function InsertPayment(
|
|||||||
CustomerRef: {
|
CustomerRef: {
|
||||||
value: parentRef.Id,
|
value: parentRef.Id,
|
||||||
},
|
},
|
||||||
TxnDate: moment(payment.date).format("YYYY-MM-DD"),
|
TxnDate: moment(payment.date).tz(bodyshop.timezone).format("YYYY-MM-DD"),
|
||||||
//DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
|
//DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
|
||||||
DocNumber: payment.paymentnum,
|
DocNumber: payment.paymentnum,
|
||||||
TotalAmt: Dinero({
|
TotalAmt: Dinero({
|
||||||
@@ -362,7 +371,8 @@ async function InsertCreditMemo(
|
|||||||
qbo_realmId,
|
qbo_realmId,
|
||||||
req,
|
req,
|
||||||
payment,
|
payment,
|
||||||
parentRef
|
parentRef,
|
||||||
|
bodyshop
|
||||||
) {
|
) {
|
||||||
const { paymentMethods, invoices, items, taxCodes } = await QueryMetaData(
|
const { paymentMethods, invoices, items, taxCodes } = await QueryMetaData(
|
||||||
oauthClient,
|
oauthClient,
|
||||||
@@ -382,7 +392,7 @@ async function InsertCreditMemo(
|
|||||||
CustomerRef: {
|
CustomerRef: {
|
||||||
value: parentRef.Id,
|
value: parentRef.Id,
|
||||||
},
|
},
|
||||||
TxnDate: moment(payment.date).format("YYYY-MM-DD"),
|
TxnDate: moment(payment.date).tz(bodyshop.timezone).format("YYYY-MM-DD"),
|
||||||
DocNumber: payment.paymentnum,
|
DocNumber: payment.paymentnum,
|
||||||
...(invoices && invoices[0]
|
...(invoices && invoices[0]
|
||||||
? { InvoiceRef: { value: invoices[0].Id } }
|
? { InvoiceRef: { value: invoices[0].Id } }
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const {
|
|||||||
} = require("./qbo-callback");
|
} = require("./qbo-callback");
|
||||||
const OAuthClient = require("intuit-oauth");
|
const OAuthClient = require("intuit-oauth");
|
||||||
const CreateInvoiceLines = require("../qb-receivables-lines").default;
|
const CreateInvoiceLines = require("../qb-receivables-lines").default;
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
|
|
||||||
const GraphQLClient = require("graphql-request").GraphQLClient;
|
const GraphQLClient = require("graphql-request").GraphQLClient;
|
||||||
const { generateOwnerTier } = require("../qbxml/qbxml-utils");
|
const { generateOwnerTier } = require("../qbxml/qbxml-utils");
|
||||||
@@ -440,7 +440,9 @@ async function InsertInvoice(
|
|||||||
|
|
||||||
const invoiceObj = {
|
const invoiceObj = {
|
||||||
Line: InvoiceLineAdd,
|
Line: InvoiceLineAdd,
|
||||||
TxnDate: moment(job.date_invoiced).format("YYYY-MM-DD"),
|
TxnDate: moment(job.date_invoiced)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format("YYYY-MM-DD"),
|
||||||
DocNumber: job.ro_number,
|
DocNumber: job.ro_number,
|
||||||
...(job.class ? { ClassRef: { value: classes[job.class] } } : {}),
|
...(job.class ? { ClassRef: { value: classes[job.class] } } : {}),
|
||||||
CustomerMemo: {
|
CustomerMemo: {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const queries = require("../../graphql-client/queries");
|
|||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
var builder = require("xmlbuilder2");
|
var builder = require("xmlbuilder2");
|
||||||
const QbXmlUtils = require("./qbxml-utils");
|
const QbXmlUtils = require("./qbxml-utils");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
const logger = require("../../utils/logger");
|
const logger = require("../../utils/logger");
|
||||||
require("dotenv").config({
|
require("dotenv").config({
|
||||||
path: path.resolve(
|
path: path.resolve(
|
||||||
@@ -72,9 +72,15 @@ const generateBill = (bill) => {
|
|||||||
VendorRef: {
|
VendorRef: {
|
||||||
FullName: bill.vendor.name,
|
FullName: bill.vendor.name,
|
||||||
},
|
},
|
||||||
TxnDate: moment(bill.date).format("YYYY-MM-DD"),
|
TxnDate: moment(bill.date)
|
||||||
DueDate:
|
.tz(bill.job.bodyshop.timezone)
|
||||||
bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
|
.format("YYYY-MM-DD"),
|
||||||
|
...(bill.vendor.due_date && {
|
||||||
|
DueDate: moment(bill.date)
|
||||||
|
.tz(bill.job.bodyshop.timezone)
|
||||||
|
.add(bill.vendor.due_date, "days")
|
||||||
|
.format("YYYY-MM-DD"),
|
||||||
|
}),
|
||||||
RefNumber: bill.invoice_number,
|
RefNumber: bill.invoice_number,
|
||||||
Memo: `RO ${bill.job.ro_number || ""}`,
|
Memo: `RO ${bill.job.ro_number || ""}`,
|
||||||
ExpenseLineAdd: bill.billlines.map((il) =>
|
ExpenseLineAdd: bill.billlines.map((il) =>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const DineroQbFormat = require("../accounting-constants").DineroQbFormat;
|
|||||||
const queries = require("../../graphql-client/queries");
|
const queries = require("../../graphql-client/queries");
|
||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
var builder = require("xmlbuilder2");
|
var builder = require("xmlbuilder2");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
const QbXmlUtils = require("./qbxml-utils");
|
const QbXmlUtils = require("./qbxml-utils");
|
||||||
const QbxmlReceivables = require("./qbxml-receivables");
|
const QbxmlReceivables = require("./qbxml-receivables");
|
||||||
const logger = require("../../utils/logger");
|
const logger = require("../../utils/logger");
|
||||||
@@ -84,7 +84,7 @@ exports.default = async (req, res) => {
|
|||||||
QbXmlToExecute.push({
|
QbXmlToExecute.push({
|
||||||
id: i.id,
|
id: i.id,
|
||||||
okStatusCodes: ["0"],
|
okStatusCodes: ["0"],
|
||||||
qbxml: generatePayment(i, isThreeTier, twoTierPref),
|
qbxml: generatePayment(i, isThreeTier, twoTierPref, bodyshop),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@ exports.default = async (req, res) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const generatePayment = (payment, isThreeTier, twoTierPref) => {
|
const generatePayment = (payment, isThreeTier, twoTierPref, bodyshop) => {
|
||||||
let paymentQbxmlObj;
|
let paymentQbxmlObj;
|
||||||
if (payment.amount > 0) {
|
if (payment.amount > 0) {
|
||||||
paymentQbxmlObj = {
|
paymentQbxmlObj = {
|
||||||
@@ -128,7 +128,9 @@ const generatePayment = (payment, isThreeTier, twoTierPref) => {
|
|||||||
FullName:
|
FullName:
|
||||||
payment.job.bodyshop.md_responsibility_centers.ar.accountname,
|
payment.job.bodyshop.md_responsibility_centers.ar.accountname,
|
||||||
},
|
},
|
||||||
TxnDate: moment(payment.date).format("YYYY-MM-DD"), //Trim String
|
TxnDate: moment(payment.date)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format("YYYY-MM-DD"), //Trim String
|
||||||
RefNumber: payment.paymentnum || payment.transactionid,
|
RefNumber: payment.paymentnum || payment.transactionid,
|
||||||
TotalAmount: Dinero({
|
TotalAmount: Dinero({
|
||||||
amount: Math.round(payment.amount * 100),
|
amount: Math.round(payment.amount * 100),
|
||||||
@@ -172,7 +174,9 @@ const generatePayment = (payment, isThreeTier, twoTierPref) => {
|
|||||||
FullName:
|
FullName:
|
||||||
payment.job.bodyshop.md_responsibility_centers.ar.accountname,
|
payment.job.bodyshop.md_responsibility_centers.ar.accountname,
|
||||||
},
|
},
|
||||||
TxnDate: moment(payment.date).format("YYYY-MM-DD"), //Trim String
|
TxnDate: moment(payment.date)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format("YYYY-MM-DD"), //Trim String
|
||||||
RefNumber:
|
RefNumber:
|
||||||
payment.paymentnum || payment.stripeid || payment.transactionid,
|
payment.paymentnum || payment.stripeid || payment.transactionid,
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const path = require("path");
|
|||||||
const DineroQbFormat = require("../accounting-constants").DineroQbFormat;
|
const DineroQbFormat = require("../accounting-constants").DineroQbFormat;
|
||||||
const queries = require("../../graphql-client/queries");
|
const queries = require("../../graphql-client/queries");
|
||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
var builder = require("xmlbuilder2");
|
var builder = require("xmlbuilder2");
|
||||||
const QbXmlUtils = require("./qbxml-utils");
|
const QbXmlUtils = require("./qbxml-utils");
|
||||||
const logger = require("../../utils/logger");
|
const logger = require("../../utils/logger");
|
||||||
@@ -254,7 +254,9 @@ const generateInvoiceQbxml = (
|
|||||||
? { ClassRef: { FullName: jobs_by_pk.class } }
|
? { ClassRef: { FullName: jobs_by_pk.class } }
|
||||||
: {}),
|
: {}),
|
||||||
|
|
||||||
TxnDate: moment(jobs_by_pk.date_invoiced).format("YYYY-MM-DD"),
|
TxnDate: moment(jobs_by_pk.date_invoiced)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format("YYYY-MM-DD"),
|
||||||
RefNumber: jobs_by_pk.ro_number,
|
RefNumber: jobs_by_pk.ro_number,
|
||||||
BillAddress: {
|
BillAddress: {
|
||||||
Addr1: jobs_by_pk.ownr_co_nm
|
Addr1: jobs_by_pk.ownr_co_nm
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ const CdkWsdl = require("./cdk-wsdl").default;
|
|||||||
const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl");
|
const { CDK_CREDENTIALS, CheckCdkResponseForError } = require("./cdk-wsdl");
|
||||||
const CalcualteAllocations = require("./cdk-calculate-allocations").default;
|
const CalcualteAllocations = require("./cdk-calculate-allocations").default;
|
||||||
|
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
|
|
||||||
const replaceSpecialRegex = /[^a-zA-Z0-9 .,\n #]+/g;
|
const replaceSpecialRegex = /[^a-zA-Z0-9 .,\n #]+/g;
|
||||||
|
|
||||||
@@ -716,6 +716,7 @@ async function InsertDmsVehicle(socket) {
|
|||||||
dealerNumber: socket.JobData.bodyshop.cdk_dealerid,
|
dealerNumber: socket.JobData.bodyshop.cdk_dealerid,
|
||||||
...(socket.txEnvelope.inservicedate && {
|
...(socket.txEnvelope.inservicedate && {
|
||||||
inServiceDate: moment(socket.txEnvelope.inservicedate)
|
inServiceDate: moment(socket.txEnvelope.inservicedate)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
.startOf("day")
|
.startOf("day")
|
||||||
.toISOString(),
|
.toISOString(),
|
||||||
}),
|
}),
|
||||||
@@ -723,7 +724,9 @@ async function InsertDmsVehicle(socket) {
|
|||||||
},
|
},
|
||||||
manufacturer: {},
|
manufacturer: {},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
deliveryDate: moment().format("YYYYMMDD"),
|
deliveryDate: moment()
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.format("YYYYMMDD"),
|
||||||
licensePlateNo: socket.JobData.plate_no,
|
licensePlateNo: socket.JobData.plate_no,
|
||||||
make: socket.txEnvelope.dms_make,
|
make: socket.txEnvelope.dms_make,
|
||||||
modelAbrev: socket.txEnvelope.dms_model,
|
modelAbrev: socket.txEnvelope.dms_model,
|
||||||
@@ -850,14 +853,16 @@ async function UpdateDmsVehicle(socket) {
|
|||||||
inServiceDate: moment(
|
inServiceDate: moment(
|
||||||
socket.DMSVeh.dealer.inServiceDate ||
|
socket.DMSVeh.dealer.inServiceDate ||
|
||||||
socket.txEnvelope.inservicedate
|
socket.txEnvelope.inservicedate
|
||||||
).toISOString(),
|
)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
...socket.DMSVeh.vehicle,
|
...socket.DMSVeh.vehicle,
|
||||||
deliveryDate: moment(
|
deliveryDate: moment(socket.DMSVeh.vehicle.deliveryDate)
|
||||||
socket.DMSVeh.vehicle.deliveryDate
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
).toISOString(),
|
.toISOString(),
|
||||||
},
|
},
|
||||||
owners: ids,
|
owners: ids,
|
||||||
},
|
},
|
||||||
@@ -912,10 +917,18 @@ async function InsertServiceVehicleHistory(socket) {
|
|||||||
vehID: socket.DMSVid.vehiclesVehId,
|
vehID: socket.DMSVid.vehiclesVehId,
|
||||||
roNumber: socket.JobData.ro_number.match(/\d+/g),
|
roNumber: socket.JobData.ro_number.match(/\d+/g),
|
||||||
mileage: socket.txEnvelope.kmout,
|
mileage: socket.txEnvelope.kmout,
|
||||||
openDate: moment(socket.JobData.actual_in).format("YYYY-MM-DD"),
|
openDate: moment(socket.JobData.actual_in)
|
||||||
openTime: moment(socket.JobData.actual_in).format("HH:mm:ss"),
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
closeDate: moment(socket.JobData.invoice_date).format("YYYY-MM-DD"),
|
.format("YYYY-MM-DD"),
|
||||||
closeTime: moment(socket.JobData.invoice_date).format("HH:mm:ss"),
|
openTime: moment(socket.JobData.actual_in)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.format("HH:mm:ss"),
|
||||||
|
closeDate: moment(socket.JobData.invoice_date)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.format("YYYY-MM-DD"),
|
||||||
|
closeTime: moment(socket.JobData.invoice_date)
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.format("HH:mm:ss"),
|
||||||
comments: socket.txEnvelope.story,
|
comments: socket.txEnvelope.story,
|
||||||
cashierID: socket.JobData.bodyshop.cdk_configuration.cashierid,
|
cashierID: socket.JobData.bodyshop.cdk_configuration.cashierid,
|
||||||
},
|
},
|
||||||
@@ -966,7 +979,9 @@ async function InsertDmsStartWip(socket) {
|
|||||||
arg0: CDK_CREDENTIALS,
|
arg0: CDK_CREDENTIALS,
|
||||||
arg1: { dealerId: socket.JobData.bodyshop.cdk_dealerid },
|
arg1: { dealerId: socket.JobData.bodyshop.cdk_dealerid },
|
||||||
arg2: {
|
arg2: {
|
||||||
acctgDate: moment().format("YYYY-MM-DD"),
|
acctgDate: moment()
|
||||||
|
.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.format("YYYY-MM-DD"),
|
||||||
//socket.JobData.invoice_date
|
//socket.JobData.invoice_date
|
||||||
desc:
|
desc:
|
||||||
socket.txEnvelope.story &&
|
socket.txEnvelope.story &&
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const queries = require("../graphql-client/queries");
|
const queries = require("../graphql-client/queries");
|
||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
|
||||||
const _ = require("lodash");
|
const _ = require("lodash");
|
||||||
@@ -66,24 +66,35 @@ exports.default = async (req, res) => {
|
|||||||
// },
|
// },
|
||||||
RepairEvent: {
|
RepairEvent: {
|
||||||
CreatedDateTime: (job.date_open
|
CreatedDateTime: (job.date_open
|
||||||
? moment(job.date_open)
|
? moment(job.date_open).tz(bodyshop.timezone)
|
||||||
: moment()
|
: moment()
|
||||||
).format(momentFormat),
|
).format(momentFormat),
|
||||||
ArrivalDateTime:
|
ArrivalDateTime:
|
||||||
job.actual_in && moment(job.actual_in).format(momentFormat),
|
job.actual_in &&
|
||||||
|
moment(job.actual_in)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
ArrivalOdometerReading: job.kmin,
|
ArrivalOdometerReading: job.kmin,
|
||||||
TargetCompletionDateTime:
|
TargetCompletionDateTime:
|
||||||
job.scheduled_completion &&
|
job.scheduled_completion &&
|
||||||
moment(job.scheduled_completion).format(momentFormat),
|
moment(job.scheduled_completion)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
ActualCompletionDateTime:
|
ActualCompletionDateTime:
|
||||||
job.actual_completion &&
|
job.actual_completion &&
|
||||||
moment(job.actual_completion).format(momentFormat),
|
moment(job.actual_completion)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
ActualPickUpDateTime:
|
ActualPickUpDateTime:
|
||||||
job.actual_delivery &&
|
job.actual_delivery &&
|
||||||
moment(job.actual_delivery).format(momentFormat),
|
moment(job.actual_delivery)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
CloseDateTime:
|
CloseDateTime:
|
||||||
job.date_exported &&
|
job.date_exported &&
|
||||||
moment(job.date_exported).format(momentFormat),
|
moment(job.date_exported)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
RepairOrderHeader: {
|
RepairOrderHeader: {
|
||||||
@@ -254,7 +265,8 @@ exports.default = async (req, res) => {
|
|||||||
//ProductionDate: "2009-10",
|
//ProductionDate: "2009-10",
|
||||||
ModelYear:
|
ModelYear:
|
||||||
parseInt(job.v_model_yr) < 1900
|
parseInt(job.v_model_yr) < 1900
|
||||||
? parseInt(job.v_model_yr) < moment().format("YY")
|
? parseInt(job.v_model_yr) <
|
||||||
|
moment().tz(bodyshop.timezone).format("YY")
|
||||||
? `20${job.v_model_yr}`
|
? `20${job.v_model_yr}`
|
||||||
: `19${job.v_model_yr}`
|
: `19${job.v_model_yr}`
|
||||||
: job.v_model_yr,
|
: job.v_model_yr,
|
||||||
@@ -288,7 +300,9 @@ exports.default = async (req, res) => {
|
|||||||
Facts: {
|
Facts: {
|
||||||
LossDateTime:
|
LossDateTime:
|
||||||
job.loss_date &&
|
job.loss_date &&
|
||||||
moment(job.loss_date).format(momentFormat),
|
moment(job.loss_date)
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
LossDescCode: "Collision",
|
LossDescCode: "Collision",
|
||||||
PrimaryPOI: {
|
PrimaryPOI: {
|
||||||
POICode: job.area_of_damage && job.area_of_damage.impact1,
|
POICode: job.area_of_damage && job.area_of_damage.impact1,
|
||||||
@@ -750,13 +764,17 @@ exports.default = async (req, res) => {
|
|||||||
ProductionStatus: {
|
ProductionStatus: {
|
||||||
ProductionStage: {
|
ProductionStage: {
|
||||||
ProductionStageCode: GetProductionStageCode(job, bodyshop),
|
ProductionStageCode: GetProductionStageCode(job, bodyshop),
|
||||||
ProductionStageDateTime: moment().format(momentFormat),
|
ProductionStageDateTime: moment()
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
// ProductionStageStatusComment:
|
// ProductionStageStatusComment:
|
||||||
// "Going to be painted this afternoon",
|
// "Going to be painted this afternoon",
|
||||||
},
|
},
|
||||||
RepairStatus: {
|
RepairStatus: {
|
||||||
RepairStatusCode: GetRepairStatusCode(job),
|
RepairStatusCode: GetRepairStatusCode(job),
|
||||||
RepairStatusDateTime: moment().format(momentFormat),
|
RepairStatusDateTime: moment()
|
||||||
|
.tz(bodyshop.timezone)
|
||||||
|
.format(momentFormat),
|
||||||
// RepairStatusMemo: "Waiting on back ordered parts",
|
// RepairStatusMemo: "Waiting on back ordered parts",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const queries = require("../graphql-client/queries");
|
const queries = require("../graphql-client/queries");
|
||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
var builder = require("xmlbuilder2");
|
var builder = require("xmlbuilder2");
|
||||||
const _ = require("lodash");
|
const _ = require("lodash");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
@@ -267,27 +267,50 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
},
|
},
|
||||||
Dates: {
|
Dates: {
|
||||||
DateofLoss:
|
DateofLoss:
|
||||||
(job.loss_date && moment(job.loss_date).format(AhDateFormat)) || "",
|
(job.loss_date &&
|
||||||
|
moment(job.loss_date)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
|
"",
|
||||||
InitialCustomerContactDate: null,
|
InitialCustomerContactDate: null,
|
||||||
FirstFollowUpDate: null,
|
FirstFollowUpDate: null,
|
||||||
ReferralDate: null,
|
ReferralDate: null,
|
||||||
EstimateAppointmentDate: null,
|
EstimateAppointmentDate: null,
|
||||||
SecondFollowUpDate: null,
|
SecondFollowUpDate: null,
|
||||||
AssignedDate:
|
AssignedDate:
|
||||||
(job.asgn_date && moment(job.asgn_date).format(AhDateFormat)) || "",
|
(job.asgn_date &&
|
||||||
|
moment(job.asgn_date)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
|
"",
|
||||||
EstComplete: null,
|
EstComplete: null,
|
||||||
CustomerAuthorizationDate: null,
|
CustomerAuthorizationDate: null,
|
||||||
InsuranceAuthorizationDate: null,
|
InsuranceAuthorizationDate: null,
|
||||||
DateOpened:
|
DateOpened:
|
||||||
(job.date_open && moment(job.date_open).format(AhDateFormat)) || "",
|
(job.date_open &&
|
||||||
|
moment(job.date_open)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
|
"",
|
||||||
ScheduledArrivalDate:
|
ScheduledArrivalDate:
|
||||||
(job.scheduled_in && moment(job.scheduled_in).format(AhDateFormat)) ||
|
(job.scheduled_in &&
|
||||||
|
moment(job.scheduled_in)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
"",
|
"",
|
||||||
CarinShop:
|
CarinShop:
|
||||||
(job.actual_in && moment(job.actual_in).format(AhDateFormat)) || "",
|
(job.actual_in &&
|
||||||
|
moment(job.actual_in)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
|
"",
|
||||||
InsInspDate: null,
|
InsInspDate: null,
|
||||||
StartDate:
|
StartDate:
|
||||||
(job.actual_in && moment(job.actual_in).format(AhDateFormat)) || "",
|
(job.actual_in &&
|
||||||
|
moment(job.actual_in)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
|
"",
|
||||||
PartsOrder: null,
|
PartsOrder: null,
|
||||||
TeardownHold: null,
|
TeardownHold: null,
|
||||||
SupplementSubmittedDate: null,
|
SupplementSubmittedDate: null,
|
||||||
@@ -303,24 +326,35 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
//InsuranceTargetOut: null,
|
//InsuranceTargetOut: null,
|
||||||
CarComplete:
|
CarComplete:
|
||||||
(job.actual_completion &&
|
(job.actual_completion &&
|
||||||
moment(job.actual_completion).format(AhDateFormat)) ||
|
moment(job.actual_completion)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
"",
|
"",
|
||||||
DeliveryAppointmentDate:
|
DeliveryAppointmentDate:
|
||||||
(job.scheduled_delivery &&
|
(job.scheduled_delivery &&
|
||||||
moment(job.scheduled_delivery).format(AhDateFormat)) ||
|
moment(job.scheduled_delivery)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
"",
|
"",
|
||||||
DateClosed:
|
DateClosed:
|
||||||
(job.date_invoiced &&
|
(job.date_invoiced &&
|
||||||
moment(job.date_invoiced).format(AhDateFormat)) ||
|
moment(job.date_invoiced)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
"",
|
"",
|
||||||
CustomerPaidInFullDate: null,
|
CustomerPaidInFullDate: null,
|
||||||
InsurancePaidInFullDate: null,
|
InsurancePaidInFullDate: null,
|
||||||
CustPickup:
|
CustPickup:
|
||||||
(job.actual_delivery &&
|
(job.actual_delivery &&
|
||||||
moment(job.actual_delivery).format(AhDateFormat)) ||
|
moment(job.actual_delivery)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat)) ||
|
||||||
"",
|
"",
|
||||||
AccountPostedDate:
|
AccountPostedDate:
|
||||||
job.date_exported && moment(job.date_exported).format(AhDateFormat),
|
job.date_exported &&
|
||||||
|
moment(job.date_exported)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat),
|
||||||
CSIProcessedDate: null,
|
CSIProcessedDate: null,
|
||||||
ThankYouLetterSent: null,
|
ThankYouLetterSent: null,
|
||||||
AdditionalFollowUpDate: null,
|
AdditionalFollowUpDate: null,
|
||||||
@@ -760,9 +794,9 @@ const GenerateDetailLines = (line, statuses) => {
|
|||||||
MarkUp: null,
|
MarkUp: null,
|
||||||
OrderedOn:
|
OrderedOn:
|
||||||
(line.parts_order_lines[0] &&
|
(line.parts_order_lines[0] &&
|
||||||
moment(line.parts_order_lines[0].parts_order.order_date).format(
|
moment(line.parts_order_lines[0].parts_order.order_date)
|
||||||
AhDateFormat
|
.tz(job.bodyshop.timezone)
|
||||||
)) ||
|
.format(AhDateFormat)) ||
|
||||||
"",
|
"",
|
||||||
OriginalCost: null,
|
OriginalCost: null,
|
||||||
OriginalInvoiceNumber: null,
|
OriginalInvoiceNumber: null,
|
||||||
@@ -786,7 +820,9 @@ const GenerateDetailLines = (line, statuses) => {
|
|||||||
ExpectedOn: null,
|
ExpectedOn: null,
|
||||||
ReceivedOn:
|
ReceivedOn:
|
||||||
line.billlines[0] &&
|
line.billlines[0] &&
|
||||||
moment(line.billlines[0].bill.date).format(AhDateFormat),
|
moment(line.billlines[0].bill.date)
|
||||||
|
.tz(job.bodyshop.timezone)
|
||||||
|
.format(AhDateFormat),
|
||||||
OrderedBy: null,
|
OrderedBy: null,
|
||||||
ShipVia: null,
|
ShipVia: null,
|
||||||
VendorContact: null,
|
VendorContact: null,
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
|
|||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
accountingconfig
|
accountingconfig
|
||||||
md_ins_cos
|
md_ins_cos
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -247,6 +248,7 @@ query QUERY_JOBS_FOR_CDK_EXPORT($id: uuid!) {
|
|||||||
accountingconfig
|
accountingconfig
|
||||||
cdk_dealerid
|
cdk_dealerid
|
||||||
cdk_configuration
|
cdk_configuration
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
owner {
|
owner {
|
||||||
accountingid
|
accountingid
|
||||||
@@ -341,6 +343,7 @@ query QUERY_JOBS_FOR_PBS_EXPORT($id: uuid!) {
|
|||||||
accountingconfig
|
accountingconfig
|
||||||
pbs_serialnumber
|
pbs_serialnumber
|
||||||
pbs_configuration
|
pbs_configuration
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
owner {
|
owner {
|
||||||
id
|
id
|
||||||
@@ -385,6 +388,7 @@ query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
|
|||||||
class
|
class
|
||||||
bodyshop{
|
bodyshop{
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
billlines{
|
billlines{
|
||||||
@@ -400,6 +404,7 @@ query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
|
|||||||
vendor{
|
vendor{
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
due_date
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -411,6 +416,7 @@ exports.QUERY_PAYMENTS_FOR_EXPORT = `
|
|||||||
id
|
id
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
accountingconfig
|
accountingconfig
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
payments(where: {id: {_in: $payments}}) {
|
payments(where: {id: {_in: $payments}}) {
|
||||||
id
|
id
|
||||||
@@ -460,6 +466,7 @@ exports.QUERY_UPCOMING_APPOINTMENTS = `query QUERY_UPCOMING_APPOINTMENTS($now: t
|
|||||||
ssbuckets
|
ssbuckets
|
||||||
target_touchtime
|
target_touchtime
|
||||||
workingdays
|
workingdays
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
jobhrs: joblines_aggregate(where: {removed: {_eq: false}}) {
|
jobhrs: joblines_aggregate(where: {removed: {_eq: false}}) {
|
||||||
aggregate {
|
aggregate {
|
||||||
@@ -558,7 +565,7 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshop
|
|||||||
autohouseid
|
autohouseid
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
jc_hourly_rates
|
jc_hourly_rates
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
jobs(where: {_and: [{converted: {_eq: true}}, {updated_at: {_gt: $start}}, {shopid: {_eq: $bodyshopid}}]}) {
|
jobs(where: {_and: [{converted: {_eq: true}}, {updated_at: {_gt: $start}}, {shopid: {_eq: $bodyshopid}}]}) {
|
||||||
id
|
id
|
||||||
@@ -828,6 +835,7 @@ exports.GET_JOB_BY_PK = ` query GET_JOB_BY_PK($id: uuid!) {
|
|||||||
loss_desc
|
loss_desc
|
||||||
kmin
|
kmin
|
||||||
kmout
|
kmout
|
||||||
|
comment
|
||||||
referral_source
|
referral_source
|
||||||
referral_source_extra
|
referral_source_extra
|
||||||
unit_number
|
unit_number
|
||||||
@@ -1234,6 +1242,7 @@ exports.GET_AUTOHOUSE_SHOPS = `query GET_AUTOHOUSE_SHOPS {
|
|||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
jc_hourly_rates
|
jc_hourly_rates
|
||||||
imexshopid
|
imexshopid
|
||||||
|
timezone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const GraphQLClient = require("graphql-request").GraphQLClient;
|
|||||||
const path = require("path");
|
const path = require("path");
|
||||||
const queries = require("../graphql-client/queries");
|
const queries = require("../graphql-client/queries");
|
||||||
const Dinero = require("dinero.js");
|
const Dinero = require("dinero.js");
|
||||||
const moment = require("moment");
|
const moment = require("moment-timezone");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
const _ = require("lodash");
|
const _ = require("lodash");
|
||||||
require("dotenv").config({
|
require("dotenv").config({
|
||||||
@@ -32,7 +32,7 @@ exports.job = async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { jobs_by_pk, blockedDays, prodJobs, arrJobs, compJobs } = result;
|
const { jobs_by_pk, blockedDays, prodJobs, arrJobs, compJobs } = result;
|
||||||
const { ssbuckets, workingdays } = result.jobs_by_pk.bodyshop;
|
const { ssbuckets, workingdays, timezone } = result.jobs_by_pk.bodyshop;
|
||||||
const jobHrs = result.jobs_by_pk.jobhrs.aggregate.sum.mod_lb_hrs;
|
const jobHrs = result.jobs_by_pk.jobhrs.aggregate.sum.mod_lb_hrs;
|
||||||
|
|
||||||
const JobBucket = ssbuckets.filter(
|
const JobBucket = ssbuckets.filter(
|
||||||
@@ -68,7 +68,9 @@ exports.job = async (req, res) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
filteredArrJobs.forEach((item) => {
|
filteredArrJobs.forEach((item) => {
|
||||||
const itemDate = moment(item.scheduled_in).format("yyyy-MM-DD");
|
const itemDate = moment(item.scheduled_in)
|
||||||
|
.tz(timezone)
|
||||||
|
.format("yyyy-MM-DD");
|
||||||
if (!!load[itemDate]) {
|
if (!!load[itemDate]) {
|
||||||
load[itemDate].hoursIn =
|
load[itemDate].hoursIn =
|
||||||
(load[itemDate].hoursIn || 0) +
|
(load[itemDate].hoursIn || 0) +
|
||||||
@@ -100,18 +102,17 @@ exports.job = async (req, res) => {
|
|||||||
//Job isn't found in production or coming in.
|
//Job isn't found in production or coming in.
|
||||||
//is it going today or scheduled to go today?
|
//is it going today or scheduled to go today?
|
||||||
if (
|
if (
|
||||||
moment(item.actual_completion || item.scheduled_completion).isSame(
|
moment(item.actual_completion || item.scheduled_completion)
|
||||||
moment(),
|
.tz(timezone)
|
||||||
"day"
|
.isSame(moment().tz(timezone), "day")
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
console.log("Job is going today anyways, ignore it.", item);
|
console.log("Job is going today anyways, ignore it.", item);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
moment(item.actual_completion || item.scheduled_completion).isBefore(
|
moment(item.actual_completion || item.scheduled_completion).tz(timezone).isBefore(
|
||||||
moment(),
|
moment().tz(timezone),
|
||||||
"day"
|
"day"
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
@@ -127,7 +128,7 @@ exports.job = async (req, res) => {
|
|||||||
} else {
|
} else {
|
||||||
const itemDate = moment(
|
const itemDate = moment(
|
||||||
item.actual_completion || item.scheduled_completion
|
item.actual_completion || item.scheduled_completion
|
||||||
).format("yyyy-MM-DD");
|
).tz(timezone).format("yyyy-MM-DD");
|
||||||
if (!!load[itemDate]) {
|
if (!!load[itemDate]) {
|
||||||
load[itemDate].hoursOut =
|
load[itemDate].hoursOut =
|
||||||
(load[itemDate].hoursOut || 0) +
|
(load[itemDate].hoursOut || 0) +
|
||||||
@@ -146,20 +147,20 @@ exports.job = async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Propagate the expected load to each day.
|
//Propagate the expected load to each day.
|
||||||
const yesterday = moment().subtract(1, "day");
|
const yesterday = moment().tz(timezone).subtract(1, "day");
|
||||||
const today = moment().startOf("day");
|
const today = moment().tz(timezone).startOf("day");
|
||||||
|
|
||||||
const end = moment.max([
|
const end = moment.tz(timezone).max([
|
||||||
...filteredArrJobs.map((a) => moment(a.scheduled_in)),
|
...filteredArrJobs.map((a) => moment(a.scheduled_in).tz(timezone)),
|
||||||
...filteredCompJobs
|
...filteredCompJobs
|
||||||
.map((p) => moment(p.actual_completion || p.scheduled_completion))
|
.map((p) => moment(p.actual_completion || p.scheduled_completion).tz(timezone))
|
||||||
.filter((p) => p.isValid() && p.isAfter(yesterday)),
|
.filter((p) => p.isValid() && p.isAfter(yesterday)),
|
||||||
moment().add(5, "days"),
|
moment().tz(timezone).add(5, "days"),
|
||||||
]);
|
]);
|
||||||
const range = Math.round(moment.duration(end.diff(today)).asDays());
|
const range = Math.round(moment.duration(end.diff(today)).asDays());
|
||||||
for (var day = 0; day < range; day++) {
|
for (var day = 0; day < range; day++) {
|
||||||
const current = moment(today).add(day, "days").format("yyyy-MM-DD");
|
const current = moment(today).tz(timezone).add(day, "days").format("yyyy-MM-DD");
|
||||||
const prev = moment(today)
|
const prev = moment(today).tz(timezone)
|
||||||
.add(day - 1, "days")
|
.add(day - 1, "days")
|
||||||
.format("yyyy-MM-DD");
|
.format("yyyy-MM-DD");
|
||||||
if (!!!load[current]) {
|
if (!!!load[current]) {
|
||||||
@@ -187,7 +188,7 @@ exports.job = async (req, res) => {
|
|||||||
|
|
||||||
blockedDays.forEach((b) => {
|
blockedDays.forEach((b) => {
|
||||||
//Find it in the load, set it as blocked.
|
//Find it in the load, set it as blocked.
|
||||||
const startIsoFormat = moment(b.start).format("YYYY-MM-DD");
|
const startIsoFormat = moment(b.start).tz(timezone).format("YYYY-MM-DD");
|
||||||
if (load[startIsoFormat]) load[startIsoFormat].blocked = true;
|
if (load[startIsoFormat]) load[startIsoFormat].blocked = true;
|
||||||
else {
|
else {
|
||||||
load[startIsoFormat] = { blocked: true };
|
load[startIsoFormat] = { blocked: true };
|
||||||
@@ -198,12 +199,12 @@ exports.job = async (req, res) => {
|
|||||||
const possibleDates = [];
|
const possibleDates = [];
|
||||||
delete load.productionTotal;
|
delete load.productionTotal;
|
||||||
const loadKeys = Object.keys(load).sort((a, b) =>
|
const loadKeys = Object.keys(load).sort((a, b) =>
|
||||||
moment(a).isAfter(moment(b)) ? 1 : -1
|
moment(a).tz(timezone).isAfter(moment(b).tz(timezone)) ? 1 : -1
|
||||||
);
|
);
|
||||||
|
|
||||||
loadKeys.forEach((loadKey) => {
|
loadKeys.forEach((loadKey) => {
|
||||||
const isShopOpen =
|
const isShopOpen =
|
||||||
(workingdays[dayOfWeekMapper(moment(loadKey).day())] || false) &&
|
(workingdays[dayOfWeekMapper(moment(loadKey).tz(timezone).day())] || false) &&
|
||||||
!load[loadKey].blocked;
|
!load[loadKey].blocked;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
@@ -2740,7 +2740,14 @@ mkdirp@^0.5.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimist "^1.2.5"
|
minimist "^1.2.5"
|
||||||
|
|
||||||
moment@^2.29.1:
|
moment-timezone@^0.5.34:
|
||||||
|
version "0.5.34"
|
||||||
|
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c"
|
||||||
|
integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==
|
||||||
|
dependencies:
|
||||||
|
moment ">= 2.9.0"
|
||||||
|
|
||||||
|
"moment@>= 2.9.0", moment@^2.29.1:
|
||||||
version "2.29.1"
|
version "2.29.1"
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
||||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
||||||
|
|||||||
Reference in New Issue
Block a user