IO-1708 Add shop timezone & update server side calculations.

This commit is contained in:
Patrick Fic
2022-02-07 17:43:34 -08:00
parent 356928ce77
commit 91c5560fe8
29 changed files with 303 additions and 93 deletions

View File

@@ -7794,6 +7794,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>

View File

@@ -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",

View File

@@ -38,6 +38,7 @@ export default function DashboardMonthlyEmployeeEfficiency({
if (!!ticketsByDate[val]) { if (!!ticketsByDate[val]) {
dailyHrs = ticketsByDate[val].reduce( dailyHrs = ticketsByDate[val].reduce(
(dayAcc, dayVal) => { (dayAcc, dayVal) => {
console.log(dayAcc);
return { return {
actual: dayAcc.actual + dayVal.actualhrs, actual: dayAcc.actual + dayVal.actualhrs,
productive: dayAcc.actual + dayVal.productivehrs, productive: dayAcc.actual + dayVal.productivehrs,

View File

@@ -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") {

View File

@@ -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,
}; };
}), }),

View File

@@ -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"

View File

@@ -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

View File

@@ -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);

View File

@@ -483,6 +483,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",

View File

@@ -483,6 +483,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": "",

View File

@@ -483,6 +483,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": "",

View File

@@ -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==

View File

@@ -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

View File

@@ -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;

View File

@@ -0,0 +1,2 @@
alter table "public"."bodyshops" add column "timezone" text
null;

View File

@@ -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",

View File

@@ -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",

View File

@@ -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,7 +178,9 @@ 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)
.tz(bill.job.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: 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] } } : {}),

View File

@@ -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 } }

View File

@@ -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: {

View File

@@ -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,14 @@ 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)
.tz(bill.job.bodyshop.timezone)
.format("YYYY-MM-DD"),
DueDate: DueDate:
bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"), bill.due_date &&
moment(bill.due_date)
.tz(bill.job.bodyshop.timezone)
.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) =>

View File

@@ -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,

View File

@@ -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

View File

@@ -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 &&

View File

@@ -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",
}, },
}, },

View File

@@ -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,

View File

@@ -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{
@@ -411,6 +415,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 +465,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 +564,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
@@ -1234,6 +1240,7 @@ exports.GET_AUTOHOUSE_SHOPS = `query GET_AUTOHOUSE_SHOPS {
md_responsibility_centers md_responsibility_centers
jc_hourly_rates jc_hourly_rates
imexshopid imexshopid
timezone
} }
} }
`; `;

View File

@@ -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 (

View File

@@ -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==