Merged in release/2022-03-04 (pull request #406)
release/2022-03-04 Approved-by: Patrick Fic
This commit is contained in:
@@ -9,7 +9,7 @@ import { DateFormatter } from "../../utils/DateFormatter";
|
|||||||
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
|
import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel-select.component";
|
||||||
import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component";
|
import CourtesyCarStatus from "../courtesy-car-status-select/courtesy-car-status-select.component";
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||||
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
//import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<FormFieldsChanged form={form} />
|
{/* <FormFieldsChanged form={form} /> */}
|
||||||
<LayoutFormRow header={t("courtesycars.labels.vehicle")}>
|
<LayoutFormRow header={t("courtesycars.labels.vehicle")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("courtesycars.fields.make")}
|
label={t("courtesycars.fields.make")}
|
||||||
|
|||||||
@@ -55,15 +55,17 @@ export function JobEmployeeAssignments({
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{bodyshop.employees.map((emp) => (
|
{bodyshop.employees
|
||||||
<Select.Option
|
.filter((emp) => emp.active)
|
||||||
value={emp.id}
|
.map((emp) => (
|
||||||
key={emp.id}
|
<Select.Option
|
||||||
name={`${emp.first_name} ${emp.last_name}`}
|
value={emp.id}
|
||||||
>
|
key={emp.id}
|
||||||
{`${emp.first_name} ${emp.last_name}`}
|
name={`${emp.first_name} ${emp.last_name}`}
|
||||||
</Select.Option>
|
>
|
||||||
))}
|
{`${emp.first_name} ${emp.last_name}`}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ export default function JobLinesBillRefernece({ jobline }) {
|
|||||||
{subletRequired && <WarningFilled />}
|
{subletRequired && <WarningFilled />}
|
||||||
{`${(billLine.actual_price * billLine.quantity).toFixed(2)} (${
|
{`${(billLine.actual_price * billLine.quantity).toFixed(2)} (${
|
||||||
billLine.bill.vendor.name
|
billLine.bill.vendor.name
|
||||||
})`}
|
} #${billLine.bill.invoice_number})`}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,15 +116,17 @@ export function ProductionListEmpAssignment({
|
|||||||
0
|
0
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{bodyshop.employees.map((emp) => (
|
{bodyshop.employees
|
||||||
<Select.Option
|
.filter((emp) => emp.active)
|
||||||
value={emp.id}
|
.map((emp) => (
|
||||||
key={emp.id}
|
<Select.Option
|
||||||
name={`${emp.first_name} ${emp.last_name}`}
|
value={emp.id}
|
||||||
>
|
key={emp.id}
|
||||||
{`${emp.first_name} ${emp.last_name}`}
|
name={`${emp.first_name} ${emp.last_name}`}
|
||||||
</Select.Option>
|
>
|
||||||
))}
|
{`${emp.first_name} ${emp.last_name}`}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Col>
|
</Col>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
|
|||||||
@@ -696,6 +696,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
joblineid
|
joblineid
|
||||||
bill {
|
bill {
|
||||||
id
|
id
|
||||||
|
invoice_number
|
||||||
vendor {
|
vendor {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
|
|||||||
@@ -181,12 +181,13 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
|||||||
TxnDate: moment(bill.date)
|
TxnDate: moment(bill.date)
|
||||||
//.tz(bill.job.bodyshop.timezone)
|
//.tz(bill.job.bodyshop.timezone)
|
||||||
.format("YYYY-MM-DD"),
|
.format("YYYY-MM-DD"),
|
||||||
...(bill.vendor.due_date && {
|
...(!bill.is_credit_memo &&
|
||||||
DueDate: moment(bill.date)
|
bill.vendor.due_date && {
|
||||||
//.tz(bill.job.bodyshop.timezone)
|
DueDate: moment(bill.date)
|
||||||
.add(bill.vendor.due_date, "days")
|
//.tz(bill.job.bodyshop.timezone)
|
||||||
.format("YYYY-MM-DD"),
|
.add(bill.vendor.due_date, "days")
|
||||||
}),
|
.format("YYYY-MM-DD"),
|
||||||
|
}),
|
||||||
DocNumber: bill.invoice_number,
|
DocNumber: bill.invoice_number,
|
||||||
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
||||||
|
|
||||||
|
|||||||
@@ -75,12 +75,13 @@ const generateBill = (bill) => {
|
|||||||
TxnDate: moment(bill.date)
|
TxnDate: moment(bill.date)
|
||||||
//.tz(bill.job.bodyshop.timezone)
|
//.tz(bill.job.bodyshop.timezone)
|
||||||
.format("YYYY-MM-DD"),
|
.format("YYYY-MM-DD"),
|
||||||
...(bill.vendor.due_date && {
|
...(!bill.is_credit_memo &&
|
||||||
DueDate: moment(bill.date)
|
bill.vendor.due_date && {
|
||||||
// .tz(bill.job.bodyshop.timezone)
|
DueDate: moment(bill.date)
|
||||||
.add(bill.vendor.due_date, "days")
|
// .tz(bill.job.bodyshop.timezone)
|
||||||
.format("YYYY-MM-DD"),
|
.add(bill.vendor.due_date, "days")
|
||||||
}),
|
.format("YYYY-MM-DD"),
|
||||||
|
}),
|
||||||
RefNumber: bill.invoice_number,
|
RefNumber: bill.invoice_number,
|
||||||
Memo: `RO ${bill.job.ro_number || ""}`,
|
Memo: `RO ${bill.job.ro_number || ""}`,
|
||||||
ExpenseLineAdd: bill.billlines.map((il) =>
|
ExpenseLineAdd: bill.billlines.map((il) =>
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
Street: job.ownr_addr1 || "",
|
Street: job.ownr_addr1 || "",
|
||||||
City: job.ownr_city || "",
|
City: job.ownr_city || "",
|
||||||
State: job.ownr_st || "",
|
State: job.ownr_st || "",
|
||||||
Zip: job.ownr_zip || "",
|
Zip: (job.ownr_zip && job.ownr_zip.substring(0, 3)) || "",
|
||||||
Phone1: job.ownr_ph1 || "",
|
Phone1: job.ownr_ph1 || "",
|
||||||
Phone2: null,
|
Phone2: null,
|
||||||
Phone2Extension: null,
|
Phone2Extension: null,
|
||||||
@@ -488,8 +488,8 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
PartsReconditionedCost:
|
PartsReconditionedCost:
|
||||||
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
|
repairCosts.PartsReconditionedCost.toFormat(AHDineroFormat),
|
||||||
PartsRecycled: Dinero(
|
PartsRecycled: Dinero(
|
||||||
job.job_totals.parts.parts.list.PAR &&
|
job.job_totals.parts.parts.list.PAL &&
|
||||||
job.job_totals.parts.parts.list.PAR.total
|
job.job_totals.parts.parts.list.PAL.total
|
||||||
).toFormat(AHDineroFormat),
|
).toFormat(AHDineroFormat),
|
||||||
PartsRecycledCost:
|
PartsRecycledCost:
|
||||||
repairCosts.PartsRecycledCost.toFormat(AHDineroFormat),
|
repairCosts.PartsRecycledCost.toFormat(AHDineroFormat),
|
||||||
@@ -555,7 +555,9 @@ const CreateRepairOrderTag = (job, errorCallback) => {
|
|||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
),
|
),
|
||||||
BMTotalCost: repairCosts.BMTotalCost.toFormat(AHDineroFormat),
|
BMTotalCost: repairCosts.BMTotalCost.toFormat(AHDineroFormat),
|
||||||
MiscTotal: 0,
|
MiscTotal: Dinero(job.job_totals.additional.additionalCosts).toFormat(
|
||||||
|
AHDineroFormat
|
||||||
|
),
|
||||||
MiscTotalCost: 0,
|
MiscTotalCost: 0,
|
||||||
TowingTotal: Dinero(job.job_totals.additional.towing).toFormat(
|
TowingTotal: Dinero(job.job_totals.additional.towing).toFormat(
|
||||||
AHDineroFormat
|
AHDineroFormat
|
||||||
@@ -673,7 +675,7 @@ const CreateCosts = (job) => {
|
|||||||
});
|
});
|
||||||
return bill_acc;
|
return bill_acc;
|
||||||
}, {});
|
}, {});
|
||||||
const materialsHours = { mapaHrs: 0, mashHrs: 0 };
|
|
||||||
//If the hourly rates for job costing are set, add them in.
|
//If the hourly rates for job costing are set, add them in.
|
||||||
if (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mapa) {
|
if (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mapa) {
|
||||||
if (
|
if (
|
||||||
@@ -694,9 +696,32 @@ const CreateCosts = (job) => {
|
|||||||
(job.bodyshop.jc_hourly_rates &&
|
(job.bodyshop.jc_hourly_rates &&
|
||||||
job.bodyshop.jc_hourly_rates.mapa * 100) ||
|
job.bodyshop.jc_hourly_rates.mapa * 100) ||
|
||||||
0,
|
0,
|
||||||
}).multiply(materialsHours.mapaHrs)
|
}).multiply(job.job_totals.rates.mapa.hours)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (job.bodyshop.jc_hourly_rates && job.bodyshop.jc_hourly_rates.mash) {
|
||||||
|
if (
|
||||||
|
!billTotalsByCostCenters[
|
||||||
|
job.bodyshop.md_responsibility_centers.defaults.costs.MASH
|
||||||
|
]
|
||||||
|
)
|
||||||
|
billTotalsByCostCenters[
|
||||||
|
job.bodyshop.md_responsibility_centers.defaults.costs.MASH
|
||||||
|
] = Dinero();
|
||||||
|
billTotalsByCostCenters[
|
||||||
|
job.bodyshop.md_responsibility_centers.defaults.costs.MASH
|
||||||
|
] = billTotalsByCostCenters[
|
||||||
|
job.bodyshop.md_responsibility_centers.defaults.costs.MASH
|
||||||
|
].add(
|
||||||
|
Dinero({
|
||||||
|
amount:
|
||||||
|
(job.bodyshop.jc_hourly_rates &&
|
||||||
|
job.bodyshop.jc_hourly_rates.mash * 100) ||
|
||||||
|
0,
|
||||||
|
}).multiply(job.job_totals.rates.mash.hours)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const ticketTotalsByCostCenter = job.timetickets.reduce(
|
const ticketTotalsByCostCenter = job.timetickets.reduce(
|
||||||
(ticket_acc, ticket_val) => {
|
(ticket_acc, ticket_val) => {
|
||||||
//At the invoice level.
|
//At the invoice level.
|
||||||
|
|||||||
@@ -111,10 +111,9 @@ exports.job = async (req, res) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
moment(item.actual_completion || item.scheduled_completion).tz(timezone).isBefore(
|
moment(item.actual_completion || item.scheduled_completion)
|
||||||
moment().tz(timezone),
|
.tz(timezone)
|
||||||
"day"
|
.isBefore(moment().tz(timezone), "day")
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
console.log("Job should have already gone. Ignoring it.", item);
|
console.log("Job should have already gone. Ignoring it.", item);
|
||||||
return;
|
return;
|
||||||
@@ -128,7 +127,9 @@ 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
|
||||||
).tz(timezone).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) +
|
||||||
@@ -153,14 +154,20 @@ exports.job = async (req, res) => {
|
|||||||
const end = moment.max([
|
const end = moment.max([
|
||||||
...filteredArrJobs.map((a) => moment(a.scheduled_in).tz(timezone)),
|
...filteredArrJobs.map((a) => moment(a.scheduled_in).tz(timezone)),
|
||||||
...filteredCompJobs
|
...filteredCompJobs
|
||||||
.map((p) => moment(p.actual_completion || p.scheduled_completion).tz(timezone))
|
.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().tz(timezone).add(15, "days"),
|
moment().tz(timezone).add(15, "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).tz(timezone).add(day, "days").format("yyyy-MM-DD");
|
const current = moment(today)
|
||||||
const prev = moment(today).tz(timezone)
|
.tz(timezone)
|
||||||
|
.add(day, "days")
|
||||||
|
.format("yyyy-MM-DD");
|
||||||
|
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]) {
|
||||||
@@ -204,7 +211,7 @@ exports.job = async (req, res) => {
|
|||||||
|
|
||||||
loadKeys.forEach((loadKey) => {
|
loadKeys.forEach((loadKey) => {
|
||||||
const isShopOpen =
|
const isShopOpen =
|
||||||
(workingdays[dayOfWeekMapper(moment(loadKey).tz(timezone).day())] || false) &&
|
(workingdays[dayOfWeekMapper(moment(loadKey).day())] || false) &&
|
||||||
!load[loadKey].blocked;
|
!load[loadKey].blocked;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
|||||||
Reference in New Issue
Block a user