Merged in release/2023-02-03 (pull request #663)
release/2023-02-03 Approved-by: Patrick Fic
This commit is contained in:
@@ -40880,6 +40880,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>gsr_by_atp</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>gsr_by_category</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>gsr_by_csr</name>
|
<name>gsr_by_csr</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -22,10 +22,6 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function ScheduleCalendarHeaderGraph({ bodyshop, loadData }) {
|
export function ScheduleCalendarHeaderGraph({ bodyshop, loadData }) {
|
||||||
console.log(
|
|
||||||
"🚀 ~ file: schedule-calendar-header-graph.component.js:23 ~ ScheduleCalendarHeaderGraph ~ loadData",
|
|
||||||
loadData
|
|
||||||
);
|
|
||||||
const { ssbuckets } = bodyshop;
|
const { ssbuckets } = bodyshop;
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const data = useMemo(() => {
|
const data = useMemo(() => {
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ export function ScheduleCalendarHeaderComponent({
|
|||||||
<div onClick={(e) => e.stopPropagation()}>
|
<div onClick={(e) => e.stopPropagation()}>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{loadData && loadData.jobsOut ? (
|
{loadData && loadData.allJobsOut ? (
|
||||||
loadData.jobsOut.map((j) => (
|
loadData.allJobsOut.map((j) => (
|
||||||
<tr key={j.id}>
|
<tr key={j.id}>
|
||||||
<td>
|
<td>
|
||||||
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
||||||
@@ -102,11 +102,12 @@ export function ScheduleCalendarHeaderComponent({
|
|||||||
<div onClick={(e) => e.stopPropagation()}>
|
<div onClick={(e) => e.stopPropagation()}>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
{loadData && loadData.jobsIn ? (
|
{loadData && loadData.allJobsIn ? (
|
||||||
loadData.jobsIn.map((j) => (
|
loadData.allJobsIn.map((j) => (
|
||||||
<tr key={j.id}>
|
<tr key={j.id}>
|
||||||
<td>
|
<td>
|
||||||
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
<Link to={`/manage/jobs/${j.id}`}>{j.ro_number}</Link>
|
||||||
|
{j.status}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<OwnerNameDisplay ownerObject={j} />
|
<OwnerNameDisplay ownerObject={j} />
|
||||||
@@ -142,7 +143,7 @@ export function ScheduleCalendarHeaderComponent({
|
|||||||
title={t("appointments.labels.arrivingjobs")}
|
title={t("appointments.labels.arrivingjobs")}
|
||||||
>
|
>
|
||||||
<Icon component={MdFileDownload} style={{ color: "green" }} />
|
<Icon component={MdFileDownload} style={{ color: "green" }} />
|
||||||
{(loadData.hoursIn || 0) && loadData.hoursIn.toFixed(2)}
|
{(loadData.allHoursIn || 0) && loadData.allHoursIn.toFixed(2)}
|
||||||
</Popover>
|
</Popover>
|
||||||
<Popover
|
<Popover
|
||||||
placement={"bottom"}
|
placement={"bottom"}
|
||||||
@@ -151,7 +152,7 @@ export function ScheduleCalendarHeaderComponent({
|
|||||||
title={t("appointments.labels.completingjobs")}
|
title={t("appointments.labels.completingjobs")}
|
||||||
>
|
>
|
||||||
<Icon component={MdFileUpload} style={{ color: "red" }} />
|
<Icon component={MdFileUpload} style={{ color: "red" }} />
|
||||||
{(loadData.hoursOut || 0) && loadData.hoursOut.toFixed(2)}
|
{(loadData.allHoursOut || 0) && loadData.allHoursOut.toFixed(2)}
|
||||||
</Popover>
|
</Popover>
|
||||||
<ScheduleCalendarHeaderGraph loadData={loadData} />
|
<ScheduleCalendarHeaderGraph loadData={loadData} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -294,6 +294,12 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
|
|||||||
where: { inproduction: { _eq: true }, suspended: { _eq: false } }
|
where: { inproduction: { _eq: true }, suspended: { _eq: false } }
|
||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
|
actual_in
|
||||||
|
scheduled_in
|
||||||
|
actual_completion
|
||||||
|
scheduled_completion
|
||||||
|
inproduction
|
||||||
|
ro_number
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
||||||
) {
|
) {
|
||||||
@@ -327,12 +333,15 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
|
status
|
||||||
ro_number
|
ro_number
|
||||||
scheduled_completion
|
scheduled_completion
|
||||||
actual_completion
|
actual_completion
|
||||||
|
scheduled_in
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
ownr_co_nm
|
ownr_co_nm
|
||||||
|
inproduction
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
||||||
) {
|
) {
|
||||||
@@ -360,11 +369,16 @@ export const QUERY_SCHEDULE_LOAD_DATA = gql`
|
|||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
scheduled_in
|
scheduled_in
|
||||||
|
actual_in
|
||||||
|
scheduled_completion
|
||||||
ro_number
|
ro_number
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
ownr_co_nm
|
ownr_co_nm
|
||||||
alt_transport
|
alt_transport
|
||||||
|
actual_completion
|
||||||
|
inproduction
|
||||||
|
status
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
productionTotal: {},
|
productionTotal: {},
|
||||||
productionHours: 0,
|
productionHours: 0,
|
||||||
};
|
};
|
||||||
|
let problemJobs = [];
|
||||||
//Set the current load.
|
//Set the current load.
|
||||||
buckets.forEach((bucket) => {
|
buckets.forEach((bucket) => {
|
||||||
load.productionTotal[bucket.id] = { count: 0, label: bucket.label };
|
load.productionTotal[bucket.id] = { count: 0, label: bucket.label };
|
||||||
@@ -45,6 +45,32 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
|
|
||||||
prodJobs.forEach((item) => {
|
prodJobs.forEach((item) => {
|
||||||
//Add all of the jobs currently in production to the buckets so that we have a starting point.
|
//Add all of the jobs currently in production to the buckets so that we have a starting point.
|
||||||
|
if (
|
||||||
|
!item.actual_completion &&
|
||||||
|
moment(item.scheduled_completion).isBefore(moment().startOf("day"))
|
||||||
|
) {
|
||||||
|
problemJobs.push({
|
||||||
|
...item,
|
||||||
|
code: "Job was scheduled to go, but it has not been completed. Update the scheduled completion date to correct projections",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
item.actual_completion &&
|
||||||
|
moment(item.actual_completion).isBefore(moment().startOf("day"))
|
||||||
|
) {
|
||||||
|
problemJobs.push({
|
||||||
|
...item,
|
||||||
|
code: "Job is already marked as completed, but it is still in production. This job should be removed from production",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!(item.actual_completion || item.scheduled_completion)) {
|
||||||
|
problemJobs.push({
|
||||||
|
...item,
|
||||||
|
code: "Job does not have a scheduled or actual completion date. Update the scheduled or actual completion dates to correct projections",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const bucketId = CheckJobBucket(buckets, item);
|
const bucketId = CheckJobBucket(buckets, item);
|
||||||
load.productionHours =
|
load.productionHours =
|
||||||
load.productionHours +
|
load.productionHours +
|
||||||
@@ -59,77 +85,119 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
arrJobs.forEach((item) => {
|
arrJobs.forEach((item) => {
|
||||||
if (!item.scheduled_in)
|
if (!item.scheduled_in) {
|
||||||
console.log("JOB HAS NO SCHEDULED IN DATE.", item);
|
console.log("JOB HAS NO SCHEDULED IN DATE.", item);
|
||||||
const itemDate = moment(item.scheduled_in).format("yyyy-MM-DD");
|
problemJobs.push({
|
||||||
|
...item,
|
||||||
|
code: "Job has no scheduled in date",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
item.actual_completion &&
|
||||||
|
moment(item.actual_completion).isAfter(moment())
|
||||||
|
) {
|
||||||
|
problemJobs.push({
|
||||||
|
...item,
|
||||||
|
code: "Job has an actual completion date set in the future",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (item.actual_completion && item.inproduction) {
|
||||||
|
problemJobs.push({
|
||||||
|
...item,
|
||||||
|
code: "Job has an actual completion date but it is still marked in production",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemDate = moment(item.actual_in || item.scheduled_in).format(
|
||||||
|
"yyyy-MM-DD"
|
||||||
|
);
|
||||||
|
|
||||||
|
const AddJobForSchedulingCalc =
|
||||||
|
!item.inproduction &&
|
||||||
|
!moment(item.actual_completion || item.scheduled_completion).isSame(
|
||||||
|
moment(item.actual_in || item.scheduled_in),
|
||||||
|
"day"
|
||||||
|
);
|
||||||
|
|
||||||
if (!!load[itemDate]) {
|
if (!!load[itemDate]) {
|
||||||
load[itemDate].hoursIn =
|
load[itemDate].allHoursIn =
|
||||||
(load[itemDate].hoursIn || 0) +
|
(load[itemDate].allHoursIn || 0) +
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
load[itemDate].jobsIn.push(item);
|
|
||||||
|
//If the job hasn't already arrived, add it to the jobs in list.
|
||||||
|
// Make sure it also hasn't already been completed, or isn't an in and out job.
|
||||||
|
//This prevents the duplicate counting.
|
||||||
|
load[itemDate].allJobsIn.push(item);
|
||||||
|
if (AddJobForSchedulingCalc) {
|
||||||
|
load[itemDate].jobsIn.push(item);
|
||||||
|
load[itemDate].hoursIn =
|
||||||
|
(load[itemDate].hoursIn || 0) +
|
||||||
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
load[itemDate] = {
|
load[itemDate] = {
|
||||||
jobsIn: [item],
|
allJobsIn: [item],
|
||||||
|
jobsIn: AddJobForSchedulingCalc ? [item] : [], //Same as above, only add it if it isn't already in production.
|
||||||
jobsOut: [],
|
jobsOut: [],
|
||||||
hoursIn:
|
allJobsOut: [],
|
||||||
|
allHoursIn:
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs,
|
item.larhrs.aggregate.sum.mod_lb_hrs,
|
||||||
|
hoursIn: AddJobForSchedulingCalc
|
||||||
|
? item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
item.larhrs.aggregate.sum.mod_lb_hrs
|
||||||
|
: 0,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let problemJobs = [];
|
|
||||||
compJobs.forEach((item) => {
|
compJobs.forEach((item) => {
|
||||||
if (!(item.actual_completion || item.scheduled_completion))
|
if (!(item.actual_completion || item.scheduled_completion))
|
||||||
console.log("JOB HAS NO COMPLETION DATE.", item);
|
console.warn("JOB HAS NO COMPLETION DATE.", item);
|
||||||
|
|
||||||
const inProdJobs = prodJobs.find((p) => p.id === item.id);
|
const inProdJobs = prodJobs.find((p) => p.id === item.id);
|
||||||
const inArrJobs = arrJobs.find((p) => p.id === item.id);
|
const inArrJobs = arrJobs.find((p) => p.id === item.id);
|
||||||
|
|
||||||
if (!(inProdJobs || inArrJobs)) {
|
const AddJobForSchedulingCalc =
|
||||||
//Job isn't found in production or coming in.
|
item.inproduction &&
|
||||||
//is it going today or scheduled to go today?
|
!moment(item.actual_completion || item.scheduled_completion).isSame(
|
||||||
if (
|
moment(item.scheduled_in),
|
||||||
moment(item.actual_completion || item.scheduled_completion).isSame(
|
"day"
|
||||||
moment(),
|
) &&
|
||||||
"day"
|
(inProdJobs || inArrJobs);
|
||||||
)
|
|
||||||
) {
|
|
||||||
console.log("Job is going today anyways, ignore it.", item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
moment(item.actual_completion || item.scheduled_completion).isBefore(
|
|
||||||
moment(),
|
|
||||||
"day"
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
console.log("Job should have already gone. Ignoring it.", item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
problemJobs.push({
|
|
||||||
...item,
|
|
||||||
code: "Job is scheduled for completion, but it is not marked in production nor is it an arriving job in this period. Check the scheduled in and completion dates",
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemDate = moment(
|
const itemDate = moment(
|
||||||
item.actual_completion || item.scheduled_completion
|
item.actual_completion || item.scheduled_completion
|
||||||
).format("yyyy-MM-DD");
|
).format("yyyy-MM-DD");
|
||||||
|
//Skip it, it's already completed.
|
||||||
|
|
||||||
if (!!load[itemDate]) {
|
if (!!load[itemDate]) {
|
||||||
load[itemDate].hoursOut =
|
load[itemDate].allHoursOut =
|
||||||
(load[itemDate].hoursOut || 0) +
|
(load[itemDate].allHoursOut || 0) +
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
load[itemDate].jobsOut.push(item);
|
//Add only the jobs that are still in production to get rid of.
|
||||||
|
//If it's not in production, we'd subtract unnecessarily.
|
||||||
|
load[itemDate].allJobsOut.push(item);
|
||||||
|
|
||||||
|
if (AddJobForSchedulingCalc) {
|
||||||
|
load[itemDate].jobsOut.push(item);
|
||||||
|
load[itemDate].hoursOut =
|
||||||
|
(load[itemDate].hoursOut || 0) +
|
||||||
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
load[itemDate] = {
|
load[itemDate] = {
|
||||||
jobsOut: [item],
|
allJobsOut: [item],
|
||||||
hoursOut:
|
jobsOut: AddJobForSchedulingCalc ? [item] : [], //Same as above.
|
||||||
|
hoursOut: AddJobForSchedulingCalc
|
||||||
|
? item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
item.larhrs.aggregate.sum.mod_lb_hrs
|
||||||
|
: 0,
|
||||||
|
allHoursOut:
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs,
|
item.larhrs.aggregate.sum.mod_lb_hrs,
|
||||||
};
|
};
|
||||||
@@ -137,6 +205,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Propagate the expected load to each day.
|
//Propagate the expected load to each day.
|
||||||
|
|
||||||
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).add(day, "days").format("yyyy-MM-DD");
|
||||||
@@ -146,6 +215,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
if (!!!load[current]) {
|
if (!!!load[current]) {
|
||||||
load[current] = {};
|
load[current] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (day === 0) {
|
if (day === 0) {
|
||||||
//Starting on day 1. The load is current.
|
//Starting on day 1. The load is current.
|
||||||
load[current].expectedLoad = CalculateLoad(
|
load[current].expectedLoad = CalculateLoad(
|
||||||
|
|||||||
@@ -49,7 +49,7 @@
|
|||||||
"blocked": "Blocked",
|
"blocked": "Blocked",
|
||||||
"cancelledappointment": "Canceled appointment for: ",
|
"cancelledappointment": "Canceled appointment for: ",
|
||||||
"completingjobs": "Completing Jobs",
|
"completingjobs": "Completing Jobs",
|
||||||
"dataconsistency": "{{ro_number}} has a data consistency issue. It has been excluded for scheduling purposes. CODE: {{code}}.",
|
"dataconsistency": "{{ro_number}} has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.",
|
||||||
"expectedjobs": "Expected Jobs in Production: ",
|
"expectedjobs": "Expected Jobs in Production: ",
|
||||||
"expectedprodhrs": "Expected Production Hours:",
|
"expectedprodhrs": "Expected Production Hours:",
|
||||||
"history": "History",
|
"history": "History",
|
||||||
@@ -2425,6 +2425,8 @@
|
|||||||
"export_payables": "Export Log - Payables",
|
"export_payables": "Export Log - Payables",
|
||||||
"export_payments": "Export Log - Payments",
|
"export_payments": "Export Log - Payments",
|
||||||
"export_receivables": "Export Log - Receivables",
|
"export_receivables": "Export Log - Receivables",
|
||||||
|
"gsr_by_atp": "Gross Sales by ATP",
|
||||||
|
"gsr_by_category": "Gross Sales by Category",
|
||||||
"gsr_by_csr": "Gross Sales by CSR",
|
"gsr_by_csr": "Gross Sales by CSR",
|
||||||
"gsr_by_delivery_date": "Gross Sales by Delivery Date",
|
"gsr_by_delivery_date": "Gross Sales by Delivery Date",
|
||||||
"gsr_by_estimator": "Gross Sales by Estimator",
|
"gsr_by_estimator": "Gross Sales by Estimator",
|
||||||
|
|||||||
@@ -2425,6 +2425,8 @@
|
|||||||
"export_payables": "",
|
"export_payables": "",
|
||||||
"export_payments": "",
|
"export_payments": "",
|
||||||
"export_receivables": "",
|
"export_receivables": "",
|
||||||
|
"gsr_by_atp": "",
|
||||||
|
"gsr_by_category": "",
|
||||||
"gsr_by_csr": "",
|
"gsr_by_csr": "",
|
||||||
"gsr_by_delivery_date": "",
|
"gsr_by_delivery_date": "",
|
||||||
"gsr_by_estimator": "",
|
"gsr_by_estimator": "",
|
||||||
|
|||||||
@@ -2425,6 +2425,8 @@
|
|||||||
"export_payables": "",
|
"export_payables": "",
|
||||||
"export_payments": "",
|
"export_payments": "",
|
||||||
"export_receivables": "",
|
"export_receivables": "",
|
||||||
|
"gsr_by_atp": "",
|
||||||
|
"gsr_by_category": "",
|
||||||
"gsr_by_csr": "",
|
"gsr_by_csr": "",
|
||||||
"gsr_by_delivery_date": "",
|
"gsr_by_delivery_date": "",
|
||||||
"gsr_by_estimator": "",
|
"gsr_by_estimator": "",
|
||||||
|
|||||||
@@ -1343,6 +1343,32 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
group: "sales",
|
group: "sales",
|
||||||
},
|
},
|
||||||
|
gsr_by_category: {
|
||||||
|
title: i18n.t("reportcenter.templates.gsr_by_category"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.gsr_by_category"),
|
||||||
|
key: "gsr_by_category",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
|
},
|
||||||
|
group: "sales",
|
||||||
|
},
|
||||||
|
gsr_by_atp: {
|
||||||
|
title: i18n.t("reportcenter.templates.gsr_by_atp"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.gsr_by_atp"),
|
||||||
|
key: "gsr_by_atp",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
|
},
|
||||||
|
group: "sales",
|
||||||
|
},
|
||||||
gsr_labor_only: {
|
gsr_labor_only: {
|
||||||
title: i18n.t("reportcenter.templates.gsr_labor_only"),
|
title: i18n.t("reportcenter.templates.gsr_labor_only"),
|
||||||
description: "",
|
description: "",
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ let transporter = nodemailer.createTransport({
|
|||||||
});
|
});
|
||||||
|
|
||||||
exports.sendServerEmail = async function ({ subject, text }) {
|
exports.sendServerEmail = async function ({ subject, text }) {
|
||||||
|
if (process.env.NODE_ENV === undefined) return;
|
||||||
try {
|
try {
|
||||||
transporter.sendMail(
|
transporter.sendMail(
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user