@@ -4598,6 +4598,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>md_from_emails</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>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>md_hour_split</name>
|
<name>md_hour_split</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -7280,6 +7301,32 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>ss_configuration</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>dailyhrslimit</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>ssbuckets</name>
|
<name>ssbuckets</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -13205,6 +13252,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>from</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>subject</name>
|
<name>subject</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -16,9 +16,14 @@ import EmailDocumentsComponent from "../email-documents/email-documents.componen
|
|||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
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,
|
||||||
|
selectCurrentUser,
|
||||||
|
} from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
currentUser: selectCurrentUser,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
@@ -28,7 +33,12 @@ export default connect(
|
|||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(EmailOverlayComponent);
|
)(EmailOverlayComponent);
|
||||||
|
|
||||||
export function EmailOverlayComponent({ form, selectedMediaState, bodyshop }) {
|
export function EmailOverlayComponent({
|
||||||
|
form,
|
||||||
|
selectedMediaState,
|
||||||
|
bodyshop,
|
||||||
|
currentUser,
|
||||||
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const handleClick = ({ item, key, keyPath }) => {
|
const handleClick = ({ item, key, keyPath }) => {
|
||||||
const email = item.props.value;
|
const email = item.props.value;
|
||||||
@@ -51,6 +61,27 @@ export function EmailOverlayComponent({ form, selectedMediaState, bodyshop }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Form.Item
|
||||||
|
label={t("emails.fields.from")}
|
||||||
|
name="from"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Select>
|
||||||
|
<Select.Option key={currentUser.email}>
|
||||||
|
{currentUser.email}
|
||||||
|
</Select.Option>
|
||||||
|
<Select.Option key={bodyshop.email}>{bodyshop.email}</Select.Option>
|
||||||
|
{bodyshop.md_from_emails &&
|
||||||
|
bodyshop.md_from_emails.map((e) => (
|
||||||
|
<Select.Option key={e}>{e}</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={
|
label={
|
||||||
<Space>
|
<Space>
|
||||||
|
|||||||
@@ -56,13 +56,9 @@ export function EmailOverlayContainer({
|
|||||||
: bodyshop.shopname,
|
: bodyshop.shopname,
|
||||||
address: EmailSettings.fromAddress,
|
address: EmailSettings.fromAddress,
|
||||||
},
|
},
|
||||||
ReplyTo: {
|
|
||||||
Email: currentUser.validemail ? currentUser.email : bodyshop.email,
|
|
||||||
Name: currentUser.displayName,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (allValues) => {
|
||||||
logImEXEvent("email_send_from_modal");
|
logImEXEvent("email_send_from_modal");
|
||||||
|
|
||||||
//const attachments = [];
|
//const attachments = [];
|
||||||
@@ -77,10 +73,15 @@ export function EmailOverlayContainer({
|
|||||||
// attachments.push(t);
|
// attachments.push(t);
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
const { from, ...values } = allValues;
|
||||||
setSending(true);
|
setSending(true);
|
||||||
try {
|
try {
|
||||||
await axios.post("/sendemail", {
|
await axios.post("/sendemail", {
|
||||||
...defaultEmailFrom,
|
...defaultEmailFrom,
|
||||||
|
ReplyTo: {
|
||||||
|
Email: from,
|
||||||
|
Name: currentUser.displayName,
|
||||||
|
},
|
||||||
...values,
|
...values,
|
||||||
html: rawHtml,
|
html: rawHtml,
|
||||||
attachments: [
|
attachments: [
|
||||||
@@ -138,6 +139,7 @@ export function EmailOverlayContainer({
|
|||||||
}
|
}
|
||||||
|
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
|
from: currentUser.validemail ? currentUser.email : bodyshop.email,
|
||||||
...emailConfig.messageOptions,
|
...emailConfig.messageOptions,
|
||||||
cc:
|
cc:
|
||||||
emailConfig.messageOptions.cc &&
|
emailConfig.messageOptions.cc &&
|
||||||
|
|||||||
@@ -507,6 +507,18 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={["md_from_emails"]}
|
||||||
|
label={t("bodyshop.fields.md_from_emails")}
|
||||||
|
// rules={[
|
||||||
|
// {
|
||||||
|
// //message: t("general.validation.required"),
|
||||||
|
// type: "array",
|
||||||
|
// },
|
||||||
|
// ]}
|
||||||
|
>
|
||||||
|
<Select mode="tags" />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={["md_email_cc", "parts_order"]}
|
name={["md_email_cc", "parts_order"]}
|
||||||
label={t("bodyshop.fields.md_email_cc", { template: "parts_order" })}
|
label={t("bodyshop.fields.md_email_cc", { template: "parts_order" })}
|
||||||
|
|||||||
@@ -70,6 +70,12 @@ export default function ShopInfoSchedulingComponent({ form }) {
|
|||||||
>
|
>
|
||||||
<Select mode="tags" />
|
<Select mode="tags" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={["ss_configuration", "dailyhrslimit"]}
|
||||||
|
label={t("bodyshop.fields.ss_configuration.dailyhrslimit")}
|
||||||
|
>
|
||||||
|
<InputNumber min={0} />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<Divider orientation="left">{t("bodyshop.labels.workingdays")}</Divider>
|
<Divider orientation="left">{t("bodyshop.labels.workingdays")}</Divider>
|
||||||
<Space wrap size="large">
|
<Space wrap size="large">
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ export const QUERY_BODYSHOP = gql`
|
|||||||
md_filehandlers
|
md_filehandlers
|
||||||
md_email_cc
|
md_email_cc
|
||||||
timezone
|
timezone
|
||||||
|
ss_configuration
|
||||||
|
md_from_emails
|
||||||
employees {
|
employees {
|
||||||
user_email
|
user_email
|
||||||
id
|
id
|
||||||
@@ -199,6 +201,8 @@ export const UPDATE_SHOP = gql`
|
|||||||
md_filehandlers
|
md_filehandlers
|
||||||
md_email_cc
|
md_email_cc
|
||||||
timezone
|
timezone
|
||||||
|
ss_configuration
|
||||||
|
md_from_emails
|
||||||
employees {
|
employees {
|
||||||
id
|
id
|
||||||
first_name
|
first_name
|
||||||
@@ -266,7 +270,6 @@ export const QUERY_DELIVER_CHECKLIST = gql`
|
|||||||
ro_number
|
ro_number
|
||||||
actual_completion
|
actual_completion
|
||||||
actual_delivery
|
actual_delivery
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -285,6 +285,7 @@
|
|||||||
"md_classes": "Classes",
|
"md_classes": "Classes",
|
||||||
"md_ded_notes": "Deductible Notes",
|
"md_ded_notes": "Deductible Notes",
|
||||||
"md_email_cc": "Auto Email CC: $t(printcenter.subjects.jobs.{{template}})",
|
"md_email_cc": "Auto Email CC: $t(printcenter.subjects.jobs.{{template}})",
|
||||||
|
"md_from_emails": "Additional From Emails",
|
||||||
"md_hour_split": {
|
"md_hour_split": {
|
||||||
"paint": "Paint Hour Split",
|
"paint": "Paint Hour Split",
|
||||||
"prep": "Prep Hour Split"
|
"prep": "Prep Hour Split"
|
||||||
@@ -455,6 +456,9 @@
|
|||||||
"label": "Label",
|
"label": "Label",
|
||||||
"templates": "Templates"
|
"templates": "Templates"
|
||||||
},
|
},
|
||||||
|
"ss_configuration": {
|
||||||
|
"dailyhrslimit": "Daily Incoming Hours Limit"
|
||||||
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
"gte": "Greater Than/Equal to (hrs)",
|
"gte": "Greater Than/Equal to (hrs)",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
@@ -827,6 +831,7 @@
|
|||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": "CC",
|
"cc": "CC",
|
||||||
|
"from": "From",
|
||||||
"subject": "Subject",
|
"subject": "Subject",
|
||||||
"to": "To"
|
"to": "To"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -285,6 +285,7 @@
|
|||||||
"md_classes": "",
|
"md_classes": "",
|
||||||
"md_ded_notes": "",
|
"md_ded_notes": "",
|
||||||
"md_email_cc": "",
|
"md_email_cc": "",
|
||||||
|
"md_from_emails": "",
|
||||||
"md_hour_split": {
|
"md_hour_split": {
|
||||||
"paint": "",
|
"paint": "",
|
||||||
"prep": ""
|
"prep": ""
|
||||||
@@ -455,6 +456,9 @@
|
|||||||
"label": "",
|
"label": "",
|
||||||
"templates": ""
|
"templates": ""
|
||||||
},
|
},
|
||||||
|
"ss_configuration": {
|
||||||
|
"dailyhrslimit": ""
|
||||||
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
"gte": "",
|
"gte": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
@@ -827,6 +831,7 @@
|
|||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": "",
|
"cc": "",
|
||||||
|
"from": "",
|
||||||
"subject": "",
|
"subject": "",
|
||||||
"to": ""
|
"to": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -285,6 +285,7 @@
|
|||||||
"md_classes": "",
|
"md_classes": "",
|
||||||
"md_ded_notes": "",
|
"md_ded_notes": "",
|
||||||
"md_email_cc": "",
|
"md_email_cc": "",
|
||||||
|
"md_from_emails": "",
|
||||||
"md_hour_split": {
|
"md_hour_split": {
|
||||||
"paint": "",
|
"paint": "",
|
||||||
"prep": ""
|
"prep": ""
|
||||||
@@ -455,6 +456,9 @@
|
|||||||
"label": "",
|
"label": "",
|
||||||
"templates": ""
|
"templates": ""
|
||||||
},
|
},
|
||||||
|
"ss_configuration": {
|
||||||
|
"dailyhrslimit": ""
|
||||||
|
},
|
||||||
"ssbuckets": {
|
"ssbuckets": {
|
||||||
"gte": "",
|
"gte": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
@@ -827,6 +831,7 @@
|
|||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"cc": "",
|
"cc": "",
|
||||||
|
"from": "",
|
||||||
"subject": "",
|
"subject": "",
|
||||||
"to": ""
|
"to": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,13 +24,34 @@ export default async function RenderTemplate(
|
|||||||
let { contextData, useShopSpecificTemplate } = await fetchContextData(
|
let { contextData, useShopSpecificTemplate } = await fetchContextData(
|
||||||
templateObject
|
templateObject
|
||||||
);
|
);
|
||||||
|
const { ignoreCustomMargins } = Templates[templateObject.name];
|
||||||
|
|
||||||
let reportRequest = {
|
let reportRequest = {
|
||||||
template: {
|
template: {
|
||||||
name: useShopSpecificTemplate
|
name: useShopSpecificTemplate
|
||||||
? `/${bodyshop.imexshopid}/${templateObject.name}`
|
? `/${bodyshop.imexshopid}/${templateObject.name}`
|
||||||
: `/${templateObject.name}`,
|
: `/${templateObject.name}`,
|
||||||
...(renderAsHtml ? {} : { recipe: "chrome-pdf" }),
|
...(renderAsHtml
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
recipe: "chrome-pdf",
|
||||||
|
...(!ignoreCustomMargins && {
|
||||||
|
chrome: {
|
||||||
|
marginTop:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.headerMargin &&
|
||||||
|
bodyshop.logo_img_path.headerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.headerMargin
|
||||||
|
: "36px",
|
||||||
|
marginBottom:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.footerMargin &&
|
||||||
|
bodyshop.logo_img_path.footerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.footerMargin
|
||||||
|
: "36px",
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
...(renderAsExcel ? { recipe: "html-to-xlsx" } : {}),
|
...(renderAsExcel ? { recipe: "html-to-xlsx" } : {}),
|
||||||
},
|
},
|
||||||
data: {
|
data: {
|
||||||
@@ -121,7 +142,25 @@ export async function RenderTemplates(
|
|||||||
name: rootTemplate.useShopSpecificTemplate
|
name: rootTemplate.useShopSpecificTemplate
|
||||||
? `/${bodyshop.imexshopid}/${rootTemplate.templateObject.name}`
|
? `/${bodyshop.imexshopid}/${rootTemplate.templateObject.name}`
|
||||||
: `/${rootTemplate.templateObject.name}`,
|
: `/${rootTemplate.templateObject.name}`,
|
||||||
...(renderAsHtml ? {} : { recipe: "chrome-pdf" }),
|
...(renderAsHtml
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
recipe: "chrome-pdf",
|
||||||
|
chrome: {
|
||||||
|
marginTop:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.headerMargin &&
|
||||||
|
bodyshop.logo_img_path.headerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.headerMargin
|
||||||
|
: "36px",
|
||||||
|
marginBottom:
|
||||||
|
bodyshop.logo_img_path &&
|
||||||
|
bodyshop.logo_img_path.footerMargin &&
|
||||||
|
bodyshop.logo_img_path.footerMargin > 36
|
||||||
|
? bodyshop.logo_img_path.footerMargin
|
||||||
|
: "36px",
|
||||||
|
},
|
||||||
|
}),
|
||||||
pdfOperations: templateAndData.map((template) => {
|
pdfOperations: templateAndData.map((template) => {
|
||||||
return {
|
return {
|
||||||
template: {
|
template: {
|
||||||
@@ -151,7 +190,7 @@ export async function RenderTemplates(
|
|||||||
};
|
};
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const render = await jsreport.renderAsync(reportRequest);
|
const render = await jsreport.renderAsync({ reportRequest });
|
||||||
if (!renderAsHtml) {
|
if (!renderAsHtml) {
|
||||||
render.download("Speed Print");
|
render.download("Speed Print");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -371,6 +371,7 @@ export const TemplateList = (type, context) => {
|
|||||||
subject: i18n.t("printcenter.jobs.parts_label_single"),
|
subject: i18n.t("printcenter.jobs.parts_label_single"),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
group: "ro",
|
group: "ro",
|
||||||
|
ignoreCustomMargins: true,
|
||||||
},
|
},
|
||||||
envelope_return_address: {
|
envelope_return_address: {
|
||||||
title: i18n.t("printcenter.jobs.envelope_return_address"),
|
title: i18n.t("printcenter.jobs.envelope_return_address"),
|
||||||
@@ -379,6 +380,7 @@ export const TemplateList = (type, context) => {
|
|||||||
key: "envelope_return_address",
|
key: "envelope_return_address",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
group: "ro",
|
group: "ro",
|
||||||
|
ignoreCustomMargins: true,
|
||||||
},
|
},
|
||||||
sgi_certificate_of_repairs: {
|
sgi_certificate_of_repairs: {
|
||||||
title: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
title: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
||||||
|
|||||||
@@ -834,6 +834,7 @@
|
|||||||
- md_email_cc
|
- md_email_cc
|
||||||
- md_estimators
|
- md_estimators
|
||||||
- md_filehandlers
|
- md_filehandlers
|
||||||
|
- md_from_emails
|
||||||
- md_hour_split
|
- md_hour_split
|
||||||
- md_ins_cos
|
- md_ins_cos
|
||||||
- md_jobline_presets
|
- md_jobline_presets
|
||||||
@@ -860,6 +861,7 @@
|
|||||||
- shopname
|
- shopname
|
||||||
- shoprates
|
- shoprates
|
||||||
- speedprint
|
- speedprint
|
||||||
|
- ss_configuration
|
||||||
- ssbuckets
|
- ssbuckets
|
||||||
- state
|
- state
|
||||||
- state_tax_id
|
- state_tax_id
|
||||||
@@ -915,6 +917,7 @@
|
|||||||
- md_email_cc
|
- md_email_cc
|
||||||
- md_estimators
|
- md_estimators
|
||||||
- md_filehandlers
|
- md_filehandlers
|
||||||
|
- md_from_emails
|
||||||
- md_hour_split
|
- md_hour_split
|
||||||
- md_ins_cos
|
- md_ins_cos
|
||||||
- md_jobline_presets
|
- md_jobline_presets
|
||||||
@@ -938,6 +941,7 @@
|
|||||||
- shopname
|
- shopname
|
||||||
- shoprates
|
- shoprates
|
||||||
- speedprint
|
- speedprint
|
||||||
|
- ss_configuration
|
||||||
- ssbuckets
|
- ssbuckets
|
||||||
- state
|
- state
|
||||||
- state_tax_id
|
- state_tax_id
|
||||||
|
|||||||
@@ -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 "ss_configuration" jsonb
|
||||||
|
-- null default jsonb_build_object();
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."bodyshops" add column "ss_configuration" jsonb
|
||||||
|
null default jsonb_build_object();
|
||||||
@@ -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 "md_from_emails" jsonb
|
||||||
|
-- null default jsonb_build_array();
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."bodyshops" add column "md_from_emails" jsonb
|
||||||
|
null default jsonb_build_array();
|
||||||
@@ -576,6 +576,7 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
SalesTaxTotal: Dinero(job.job_totals.totals.local_tax)
|
SalesTaxTotal: Dinero(job.job_totals.totals.local_tax)
|
||||||
.add(Dinero(job.job_totals.totals.state_tax))
|
.add(Dinero(job.job_totals.totals.state_tax))
|
||||||
.add(Dinero(job.job_totals.totals.federal_tax))
|
.add(Dinero(job.job_totals.totals.federal_tax))
|
||||||
|
.add(Dinero(job.job_totals.additional.pvrt))
|
||||||
.toFormat(AHDineroFormat),
|
.toFormat(AHDineroFormat),
|
||||||
SalesTaxTotalCost: 0,
|
SalesTaxTotalCost: 0,
|
||||||
GrossTotal: Dinero(job.job_totals.totals.total_repairs).toFormat(
|
GrossTotal: Dinero(job.job_totals.totals.total_repairs).toFormat(
|
||||||
|
|||||||
@@ -464,6 +464,7 @@ exports.QUERY_UPCOMING_APPOINTMENTS = `query QUERY_UPCOMING_APPOINTMENTS($now: t
|
|||||||
jobs_by_pk(id: $jobId) {
|
jobs_by_pk(id: $jobId) {
|
||||||
bodyshop {
|
bodyshop {
|
||||||
ssbuckets
|
ssbuckets
|
||||||
|
ss_configuration
|
||||||
target_touchtime
|
target_touchtime
|
||||||
workingdays
|
workingdays
|
||||||
timezone
|
timezone
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const Dinero = require("dinero.js");
|
|||||||
const moment = require("moment-timezone");
|
const moment = require("moment-timezone");
|
||||||
const logger = require("../utils/logger");
|
const logger = require("../utils/logger");
|
||||||
const _ = require("lodash");
|
const _ = require("lodash");
|
||||||
|
const { filter } = require("lodash");
|
||||||
require("dotenv").config({
|
require("dotenv").config({
|
||||||
path: path.resolve(
|
path: path.resolve(
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
@@ -32,7 +33,8 @@ 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, timezone } = result.jobs_by_pk.bodyshop;
|
const { ssbuckets, workingdays, timezone, ss_configuration } =
|
||||||
|
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(
|
||||||
@@ -63,29 +65,68 @@ exports.job = async (req, res) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const filteredArrJobs = arrJobs.filter(
|
// const filteredArrJobs = arrJobs.filter(
|
||||||
(j) => JobBucket.id === CheckJobBucket(ssbuckets, j)
|
// (j) => JobBucket.id === CheckJobBucket(ssbuckets, j)
|
||||||
);
|
// );
|
||||||
|
const filteredArrJobs = [];
|
||||||
|
|
||||||
|
// filteredArrJobs.forEach((item) => {
|
||||||
|
// const itemDate = moment(item.scheduled_in)
|
||||||
|
// .tz(timezone)
|
||||||
|
// .format("yyyy-MM-DD");
|
||||||
|
// if (!!load[itemDate]) {
|
||||||
|
// load[itemDate].hoursIn =
|
||||||
|
// (load[itemDate].hoursIn || 0) +
|
||||||
|
// item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
// item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
|
// load[itemDate].jobsIn.push(item);
|
||||||
|
// } else {
|
||||||
|
// load[itemDate] = {
|
||||||
|
// jobsIn: [item],
|
||||||
|
// jobsOut: [],
|
||||||
|
// hoursIn:
|
||||||
|
// item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
// item.larhrs.aggregate.sum.mod_lb_hrs,
|
||||||
|
// };
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
arrJobs.forEach((item) => {
|
||||||
|
let isSameBucket = false;
|
||||||
|
if (JobBucket.id === CheckJobBucket(ssbuckets, item)) {
|
||||||
|
filteredArrJobs.push(item);
|
||||||
|
isSameBucket = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let jobHours =
|
||||||
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
|
|
||||||
filteredArrJobs.forEach((item) => {
|
|
||||||
const itemDate = moment(item.scheduled_in)
|
const itemDate = moment(item.scheduled_in)
|
||||||
.tz(timezone)
|
.tz(timezone)
|
||||||
.format("yyyy-MM-DD");
|
.format("yyyy-MM-DD");
|
||||||
if (!!load[itemDate]) {
|
if (isSameBucket) {
|
||||||
load[itemDate].hoursIn =
|
if (!!load[itemDate]) {
|
||||||
(load[itemDate].hoursIn || 0) +
|
load[itemDate].hoursIn = (load[itemDate].hoursIn || 0) + jobHours;
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
load[itemDate].jobsIn.push(item);
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
} else {
|
||||||
load[itemDate].jobsIn.push(item);
|
load[itemDate] = {
|
||||||
} else {
|
jobsIn: [item],
|
||||||
|
jobsOut: [],
|
||||||
|
hoursIn: jobHours,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!load[itemDate]) {
|
||||||
load[itemDate] = {
|
load[itemDate] = {
|
||||||
jobsIn: [item],
|
jobsIn: [],
|
||||||
jobsOut: [],
|
jobsOut: [],
|
||||||
hoursIn:
|
hoursIn: 0,
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
hoursInTotal: 0,
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
load[itemDate].hoursInTotal =
|
||||||
|
(load[itemDate].hoursInTotal || 0) + jobHours;
|
||||||
});
|
});
|
||||||
|
|
||||||
//Get the completing jobs.
|
//Get the completing jobs.
|
||||||
@@ -214,11 +255,25 @@ exports.job = async (req, res) => {
|
|||||||
(workingdays[dayOfWeekMapper(moment(loadKey).day())] || false) &&
|
(workingdays[dayOfWeekMapper(moment(loadKey).day())] || false) &&
|
||||||
!load[loadKey].blocked;
|
!load[loadKey].blocked;
|
||||||
|
|
||||||
|
let isUnderDailyTotalLimit = true;
|
||||||
|
|
||||||
|
if (
|
||||||
|
ss_configuration &&
|
||||||
|
ss_configuration.dailyhrslimit &&
|
||||||
|
ss_configuration.dailyhrslimit > 0 &&
|
||||||
|
load[loadKey] &&
|
||||||
|
load[loadKey].hoursInTotal &&
|
||||||
|
load[loadKey].hoursInTotal > ss_configuration.dailyhrslimit
|
||||||
|
) {
|
||||||
|
isUnderDailyTotalLimit = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
load[loadKey].expectedLoad &&
|
load[loadKey].expectedLoad &&
|
||||||
load[loadKey].expectedLoad[JobBucket.id] &&
|
load[loadKey].expectedLoad[JobBucket.id] &&
|
||||||
JobBucket.target > load[loadKey].expectedLoad[JobBucket.id].count &&
|
JobBucket.target > load[loadKey].expectedLoad[JobBucket.id].count &&
|
||||||
isShopOpen
|
isShopOpen &&
|
||||||
|
isUnderDailyTotalLimit
|
||||||
)
|
)
|
||||||
possibleDates.push(new Date(loadKey).toISOString().substr(0, 10));
|
possibleDates.push(new Date(loadKey).toISOString().substr(0, 10));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user