Improved totals calculations
This commit is contained in:
@@ -1,47 +1,43 @@
|
|||||||
import { Button, notification } from "antd";
|
import { Button, notification } from "antd";
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
export default function JobCalculateTotals({ job, disabled, refetch }) {
|
||||||
import Dinero from "dinero.js";
|
|
||||||
export default function JobCalculateTotals({ job, disabled }) {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [updateJob] = useMutation(UPDATE_JOB);
|
|
||||||
|
|
||||||
const handleCalculate = async () => {
|
const handleCalculate = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const newTotals = (
|
|
||||||
await Axios.post("/job/totals", {
|
|
||||||
job: job,
|
|
||||||
})
|
|
||||||
).data;
|
|
||||||
|
|
||||||
const result = await updateJob({
|
await Axios.post("/job/totalsssu", {
|
||||||
refetchQueries: ["GET_JOB_BY_PK"],
|
id: job.id,
|
||||||
awaitRefetchQueries: true,
|
|
||||||
variables: {
|
|
||||||
jobId: job.id,
|
|
||||||
job: {
|
|
||||||
job_totals: newTotals,
|
|
||||||
clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
|
||||||
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat(
|
|
||||||
"0.00"
|
|
||||||
),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
if (!!!result.errors) {
|
|
||||||
notification["success"]({ message: t("jobs.successes.updated") });
|
if (refetch) refetch();
|
||||||
} else {
|
// const result = await updateJob({
|
||||||
notification["error"]({
|
// refetchQueries: ["GET_JOB_BY_PK"],
|
||||||
message: t("jobs.errors.updating", {
|
// awaitRefetchQueries: true,
|
||||||
error: JSON.stringify(result.errors),
|
// variables: {
|
||||||
}),
|
// jobId: job.id,
|
||||||
});
|
// job: {
|
||||||
}
|
// job_totals: newTotals,
|
||||||
|
// clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
||||||
|
// owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat(
|
||||||
|
// "0.00"
|
||||||
|
// ),
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
// if (!!!result.errors) {
|
||||||
|
// notification["success"]({ message: t("jobs.successes.updated") });
|
||||||
|
// } else {
|
||||||
|
// notification["error"]({
|
||||||
|
// message: t("jobs.errors.updating", {
|
||||||
|
// error: JSON.stringify(result.errors),
|
||||||
|
// }),
|
||||||
|
// });
|
||||||
|
// }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("jobs.errors.updating", {
|
message: t("jobs.errors.updating", {
|
||||||
|
|||||||
@@ -3,12 +3,11 @@ import {
|
|||||||
useApolloClient,
|
useApolloClient,
|
||||||
useLazyQuery,
|
useLazyQuery,
|
||||||
useMutation,
|
useMutation,
|
||||||
useQuery
|
useQuery,
|
||||||
} from "@apollo/client";
|
} from "@apollo/client";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import { Col, notification, Row } from "antd";
|
import { Col, notification, Row } from "antd";
|
||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import Dinero from "dinero.js";
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
@@ -20,7 +19,7 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
|||||||
import {
|
import {
|
||||||
DELETE_AVAILABLE_JOB,
|
DELETE_AVAILABLE_JOB,
|
||||||
QUERY_AVAILABLE_JOBS,
|
QUERY_AVAILABLE_JOBS,
|
||||||
QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK
|
QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK,
|
||||||
} from "../../graphql/available-jobs.queries";
|
} from "../../graphql/available-jobs.queries";
|
||||||
import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
|
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
|
||||||
@@ -28,7 +27,7 @@ import { SEARCH_VEHICLE_BY_VIN } from "../../graphql/vehicles.queries";
|
|||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import {
|
import {
|
||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
import confirmDialog from "../../utils/asyncConfirm";
|
import confirmDialog from "../../utils/asyncConfirm";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
@@ -114,14 +113,14 @@ export function JobsAvailableContainer({
|
|||||||
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
//IO-539 Check for Parts Rate on PAL for SGI use case.
|
||||||
await CheckTaxRates(estData.est_data, bodyshop);
|
await CheckTaxRates(estData.est_data, bodyshop);
|
||||||
// }
|
// }
|
||||||
const newTotals = (
|
// const newTotals = (
|
||||||
await Axios.post("/job/totals", {
|
// await Axios.post("/job/totals", {
|
||||||
job: {
|
// job: {
|
||||||
...estData.est_data,
|
// ...estData.est_data,
|
||||||
joblines: estData.est_data.joblines.data,
|
// joblines: estData.est_data.joblines.data,
|
||||||
},
|
// },
|
||||||
})
|
// })
|
||||||
).data;
|
// ).data;
|
||||||
|
|
||||||
let existingVehicles;
|
let existingVehicles;
|
||||||
if (estData.est_data.v_vin) {
|
if (estData.est_data.v_vin) {
|
||||||
@@ -136,9 +135,9 @@ export function JobsAvailableContainer({
|
|||||||
|
|
||||||
const newJob = {
|
const newJob = {
|
||||||
...estData.est_data,
|
...estData.est_data,
|
||||||
clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
// clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
|
||||||
owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
|
// owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
|
||||||
job_totals: newTotals,
|
// job_totals: newTotals,
|
||||||
date_open: moment(),
|
date_open: moment(),
|
||||||
notes: {
|
notes: {
|
||||||
data: {
|
data: {
|
||||||
@@ -167,6 +166,10 @@ export function JobsAvailableContainer({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
|
Axios.post("/job/totalsssu", {
|
||||||
|
id: r.data.insert_jobs.returning[0].id,
|
||||||
|
});
|
||||||
|
|
||||||
if (CriticalPartsScanning.treatment === "on") {
|
if (CriticalPartsScanning.treatment === "on") {
|
||||||
CriticalPartsScan(r.data.insert_jobs.returning[0].id);
|
CriticalPartsScan(r.data.insert_jobs.returning[0].id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ require("dotenv").config({
|
|||||||
|
|
||||||
async function RunTheTest() {
|
async function RunTheTest() {
|
||||||
const bodyshopids = ["6c63a820-542c-497e-8c82-0cc38fb2bbca"];
|
const bodyshopids = ["6c63a820-542c-497e-8c82-0cc38fb2bbca"];
|
||||||
const bearerToken = `Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6ImFlYjMxMjdiMjRjZTg2MDJjODEyNDUxZThmZTczZDU4MjkyMDg4N2MiLCJ0eXAiOiJKV1QifQ.eyJodHRwczovL2hhc3VyYS5pby9qd3QvY2xhaW1zIjp7IngtaGFzdXJhLWRlZmF1bHQtcm9sZSI6InVzZXIiLCJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbInVzZXIiXSwieC1oYXN1cmEtdXNlci1pZCI6InQ2WW0xTkRsQ0RPUFpyM0Y5Ymd1V0g0TGhTWDIifSwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL3JvbWUtcHJvZC0xIiwiYXVkIjoicm9tZS1wcm9kLTEiLCJhdXRoX3RpbWUiOjE2NzY0ODIxOTYsInVzZXJfaWQiOiJ0NlltMU5EbENET1BacjNGOWJndVdINExoU1gyIiwic3ViIjoidDZZbTFORGxDRE9QWnIzRjliZ3VXSDRMaFNYMiIsImlhdCI6MTY3NjU4NzYxNSwiZXhwIjoxNjc2NTkxMjE1LCJlbWFpbCI6InBhdHJpY2tAcm9tZS5kZXYiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiZW1haWwiOlsicGF0cmlja0Byb21lLmRldiJdfSwic2lnbl9pbl9wcm92aWRlciI6InBhc3N3b3JkIn19.53cLDjRthvAWUOKjSmdMII78MxD1s-mkEbG9z9KVxLB18NsKS-iZMAfIZcYb-LXZGscH8O-jR0OSyMgXitc-mv6xYV6bAGcO7gUgxwMKqnbh9-pK_uyGQ5LQ-yxMG2F397ObJu3fyB1RZ1e8LRYkIpV9LwAm4XiHQdGAfYyFDA2fSOS-9x9k6im07hAYsEeIx2hNr-8vVaEpkCENF2JFpJ9qjtfp6pRnbwQY2VA8nsJly1oOz56GLhb5f1m2Ta22eVqAye9of5EXmNSTsvDkAv7Xs3NNuNbHu8fM76tAuKPniurMNV5VwJZX7RhsjFelmoUFFTVOj6JVL-Sw-vs65A`;
|
const bearerToken = `Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Ijk3OWVkMTU1OTdhYjM1Zjc4MjljZTc0NDMwN2I3OTNiN2ViZWIyZjAiLCJ0eXAiOiJKV1QifQ.eyJodHRwczovL2hhc3VyYS5pby9qd3QvY2xhaW1zIjp7IngtaGFzdXJhLWRlZmF1bHQtcm9sZSI6InVzZXIiLCJ4LWhhc3VyYS1hbGxvd2VkLXJvbGVzIjpbInVzZXIiXSwieC1oYXN1cmEtdXNlci1pZCI6InQ2WW0xTkRsQ0RPUFpyM0Y5Ymd1V0g0TGhTWDIifSwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL3JvbWUtcHJvZC0xIiwiYXVkIjoicm9tZS1wcm9kLTEiLCJhdXRoX3RpbWUiOjE2NzkzNDc4NzAsInVzZXJfaWQiOiJ0NlltMU5EbENET1BacjNGOWJndVdINExoU1gyIiwic3ViIjoidDZZbTFORGxDRE9QWnIzRjliZ3VXSDRMaFNYMiIsImlhdCI6MTY3OTk1NDk3MiwiZXhwIjoxNjc5OTU4NTcyLCJlbWFpbCI6InBhdHJpY2tAcm9tZS5kZXYiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiZW1haWwiOlsicGF0cmlja0Byb21lLmRldiJdfSwic2lnbl9pbl9wcm92aWRlciI6InBhc3N3b3JkIn19.Dnq_xo5tffFf-LK0qD_iieUa_UYe4cJqOxcuJnRGH0aqirMMeQLRR4B_Z3pOsD3T20ML3qZMQNUKx-Ivz1mfyK_aA7_4GKtHRKOpIrAyssw_l5aXuCAEmC8iLQHDGvKi7Vp8LsTMPKqjJSjtaW2zuFqcIGrqncWkBMYSnCKjCFsKjryp35hQiIynAN1W0ajgjmFZHCy7hG1h4wFtLKNXEAGxWA0tE7m7ZZBZk3W7J3nMbYiMuGZfw0y2yYeILQGw3UW6sb9B2Jx2bAR3x-GWhPzQHNZEPolE-andm900cFgdph1z7eBE5P2udc2rp8JsAPdUdovt8ZImhCUeE5wD6g`;
|
||||||
const { jobs } = await client.request(
|
const { jobs } = await client.request(
|
||||||
gql`
|
gql`
|
||||||
query GET_JOBS($bodyshopids: [uuid!]!) {
|
query GET_JOBS($bodyshopids: [uuid!]!) {
|
||||||
@@ -77,7 +77,7 @@ async function RunTheTest() {
|
|||||||
|
|
||||||
const calcTotal = newjob.job_totals.totals.total_repairs.amount;
|
const calcTotal = newjob.job_totals.totals.total_repairs.amount;
|
||||||
const ttlTotal = newjob.cieca_ttl.data.g_ttl_amt * 100;
|
const ttlTotal = newjob.cieca_ttl.data.g_ttl_amt * 100;
|
||||||
result.difference = Math.abs(calcTotal - ttlTotal) / 100;
|
result.difference = (calcTotal - ttlTotal) / 100;
|
||||||
|
|
||||||
if (Math.abs(calcTotal - ttlTotal) > 5) {
|
if (Math.abs(calcTotal - ttlTotal) > 5) {
|
||||||
//Diff is greater than 5 cents. Fail it.
|
//Diff is greater than 5 cents. Fail it.
|
||||||
|
|||||||
@@ -908,6 +908,7 @@ exports.UPDATE_JOB = `
|
|||||||
|
|
||||||
exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) {
|
exports.GET_JOB_BY_PK = `query GET_JOB_BY_PK($id: uuid!) {
|
||||||
jobs_by_pk(id: $id) {
|
jobs_by_pk(id: $id) {
|
||||||
|
cieca_stl
|
||||||
updated_at
|
updated_at
|
||||||
alt_transport
|
alt_transport
|
||||||
intakechecklist
|
intakechecklist
|
||||||
@@ -1073,6 +1074,8 @@ vehicle{
|
|||||||
manual_line
|
manual_line
|
||||||
prt_dsmk_p
|
prt_dsmk_p
|
||||||
prt_dsmk_m
|
prt_dsmk_m
|
||||||
|
misc_amt
|
||||||
|
misc_tax
|
||||||
parts_order_lines {
|
parts_order_lines {
|
||||||
id
|
id
|
||||||
parts_order {
|
parts_order {
|
||||||
|
|||||||
@@ -58,15 +58,15 @@ async function TotalsServerSide(req, res) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
let ret = {
|
let ret = {
|
||||||
|
rates: await CalculateRatesTotals({ job, client }),
|
||||||
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates),
|
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates),
|
||||||
rates: CalculateRatesTotals(job),
|
|
||||||
additional: CalculateAdditional(job),
|
additional: CalculateAdditional(job),
|
||||||
};
|
};
|
||||||
ret.totals = CalculateTaxesTotals(job, ret);
|
ret.totals = CalculateTaxesTotals(job, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.log("job-totals-ssu-error", "ERROR", req.user.email, job.id, {
|
logger.log("job-totals-ssu-error", "ERROR", req.user?.email, job.id, {
|
||||||
jobid: job.id,
|
jobid: job.id,
|
||||||
error,
|
error,
|
||||||
});
|
});
|
||||||
@@ -92,8 +92,8 @@ async function Totals(req, res) {
|
|||||||
await AutoAddAtsIfRequired({ job, client });
|
await AutoAddAtsIfRequired({ job, client });
|
||||||
try {
|
try {
|
||||||
let ret = {
|
let ret = {
|
||||||
|
rates: await CalculateRatesTotals({ job, client }),
|
||||||
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates),
|
parts: CalculatePartsTotals(job.joblines, job.parts_tax_rates),
|
||||||
rates: CalculateRatesTotals(job),
|
|
||||||
additional: CalculateAdditional(job),
|
additional: CalculateAdditional(job),
|
||||||
};
|
};
|
||||||
ret.totals = CalculateTaxesTotals(job, ret);
|
ret.totals = CalculateTaxesTotals(job, ret);
|
||||||
@@ -183,72 +183,72 @@ async function AutoAddAtsIfRequired({ job, client }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function CalculateRatesTotals(ratesList) {
|
async function CalculateRatesTotals({ job, client }) {
|
||||||
const jobLines = ratesList.joblines.filter((jl) => !jl.removed);
|
const jobLines = job.joblines.filter((jl) => !jl.removed);
|
||||||
|
|
||||||
let ret = {
|
let ret = {
|
||||||
la1: {
|
la1: {
|
||||||
hours: 0,
|
hours: 0,
|
||||||
rate: ratesList.rate_la1 || 0,
|
rate: job.rate_la1 || 0,
|
||||||
},
|
},
|
||||||
la2: {
|
la2: {
|
||||||
hours: 0,
|
hours: 0,
|
||||||
rate: ratesList.rate_la2 || 0,
|
rate: job.rate_la2 || 0,
|
||||||
},
|
},
|
||||||
la3: {
|
la3: {
|
||||||
rate: ratesList.rate_la3 || 0,
|
rate: job.rate_la3 || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
la4: {
|
la4: {
|
||||||
rate: ratesList.rate_la4 || 0,
|
rate: job.rate_la4 || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
laa: {
|
laa: {
|
||||||
rate: ratesList.rate_laa || 0,
|
rate: job.rate_laa || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
lab: {
|
lab: {
|
||||||
rate: ratesList.rate_lab || 0,
|
rate: job.rate_lab || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
lad: {
|
lad: {
|
||||||
rate: ratesList.rate_lad || 0,
|
rate: job.rate_lad || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
lae: {
|
lae: {
|
||||||
rate: ratesList.rate_lae || 0,
|
rate: job.rate_lae || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
laf: {
|
laf: {
|
||||||
rate: ratesList.rate_laf || 0,
|
rate: job.rate_laf || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
lag: {
|
lag: {
|
||||||
rate: ratesList.rate_lag || 0,
|
rate: job.rate_lag || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
lam: {
|
lam: {
|
||||||
rate: ratesList.rate_lam || 0,
|
rate: job.rate_lam || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
lar: {
|
lar: {
|
||||||
rate: ratesList.rate_lar || 0,
|
rate: job.rate_lar || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
las: {
|
las: {
|
||||||
rate: ratesList.rate_las || 0,
|
rate: job.rate_las || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
lau: {
|
lau: {
|
||||||
rate: ratesList.rate_lau || 0,
|
rate: job.rate_lau || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
mapa: {
|
mapa: {
|
||||||
rate: ratesList.rate_mapa || 0,
|
rate: job.rate_mapa || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
mash: {
|
mash: {
|
||||||
rate: ratesList.rate_mash || 0,
|
rate: job.rate_mash || 0,
|
||||||
hours: 0,
|
hours: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -258,8 +258,9 @@ function CalculateRatesTotals(ratesList) {
|
|||||||
//Otherwise, calculate them and add them to the default MAPA and MASH centers.
|
//Otherwise, calculate them and add them to the default MAPA and MASH centers.
|
||||||
let hasMapaLine = false;
|
let hasMapaLine = false;
|
||||||
let hasMashLine = false;
|
let hasMashLine = false;
|
||||||
let mapaOpCodes = ParseCalopCode(ratesList.materials["mapa"]?.cal_opcode);
|
let hasMahwLine = false;
|
||||||
let mashOpCodes = ParseCalopCode(ratesList.materials["mash"]?.cal_opcode);
|
let mapaOpCodes = ParseCalopCode(job.materials["mapa"]?.cal_opcode);
|
||||||
|
let mashOpCodes = ParseCalopCode(job.materials["mash"]?.cal_opcode);
|
||||||
|
|
||||||
jobLines.forEach((item) => {
|
jobLines.forEach((item) => {
|
||||||
//IO-1317 Use the lines on the estimate if they exist instead.
|
//IO-1317 Use the lines on the estimate if they exist instead.
|
||||||
@@ -276,6 +277,9 @@ function CalculateRatesTotals(ratesList) {
|
|||||||
amount: Math.round((item.act_price || 0) * 100),
|
amount: Math.round((item.act_price || 0) * 100),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (item.line_desc.toLowerCase().includes("hazardous waste")) {
|
||||||
|
hasMahwLine = item;
|
||||||
|
}
|
||||||
|
|
||||||
if (item.mod_lbr_ty) {
|
if (item.mod_lbr_ty) {
|
||||||
//Check to see if it has 0 hours and a price instead.
|
//Check to see if it has 0 hours and a price instead.
|
||||||
@@ -333,16 +337,16 @@ function CalculateRatesTotals(ratesList) {
|
|||||||
}
|
}
|
||||||
let threshold;
|
let threshold;
|
||||||
//Check if there is a max for this type.
|
//Check if there is a max for this type.
|
||||||
if (ratesList.materials && ratesList.materials[property]) {
|
if (job.materials && job.materials[property]) {
|
||||||
//
|
//
|
||||||
|
|
||||||
if (
|
if (
|
||||||
ratesList.materials[property].cal_maxdlr !== undefined &&
|
job.materials[property].cal_maxdlr !== undefined &&
|
||||||
ratesList.materials[property].cal_maxdlr >= 0
|
job.materials[property].cal_maxdlr >= 0
|
||||||
) {
|
) {
|
||||||
//It has an upper threshhold.
|
//It has an upper threshhold.
|
||||||
threshold = Dinero({
|
threshold = Dinero({
|
||||||
amount: Math.round(ratesList.materials[property].cal_maxdlr * 100),
|
amount: Math.round(job.materials[property].cal_maxdlr * 100),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,6 +368,37 @@ function CalculateRatesTotals(ratesList) {
|
|||||||
rates_subtotal = rates_subtotal.add(ret[property].total);
|
rates_subtotal = rates_subtotal.add(ret[property].total);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const stlMahw = job.cieca_stl.data.find((c) => c.ttl_typecd === "MAHW");
|
||||||
|
|
||||||
|
if (
|
||||||
|
stlMahw &&
|
||||||
|
stlMahw.ttl_amt !== 0 &&
|
||||||
|
(!hasMahwLine || hasMahwLine.act_price !== stlMahw.ttl_amt)
|
||||||
|
) {
|
||||||
|
//Add a hazardous waste material line in case there isn't one on the estimate.
|
||||||
|
const newMahwLine = {
|
||||||
|
line_desc: "Hazardous Waste Removal*",
|
||||||
|
part_type: "PAS",
|
||||||
|
oem_partno: null,
|
||||||
|
db_price: 0,
|
||||||
|
act_price: stlMahw.ttl_amt,
|
||||||
|
part_qty: 1,
|
||||||
|
//mod_lbr_ty: "LAB",
|
||||||
|
db_hrs: 0,
|
||||||
|
mod_lb_hrs: 0,
|
||||||
|
lbr_op: "OP11",
|
||||||
|
lbr_amt: 0,
|
||||||
|
op_code_desc: "REMOVE / REPLACE",
|
||||||
|
tax_part: true,
|
||||||
|
db_ref: null,
|
||||||
|
manual_line: true,
|
||||||
|
jobid: job.id,
|
||||||
|
};
|
||||||
|
job.joblines.push(newMahwLine);
|
||||||
|
await client.request(queries.INSERT_NEW_JOB_LINE, {
|
||||||
|
lineInput: [newMahwLine],
|
||||||
|
});
|
||||||
|
}
|
||||||
ret.subtotal = subtotal;
|
ret.subtotal = subtotal;
|
||||||
ret.rates_subtotal = rates_subtotal;
|
ret.rates_subtotal = rates_subtotal;
|
||||||
|
|
||||||
@@ -374,6 +409,54 @@ function CalculateRatesTotals(ratesList) {
|
|||||||
|
|
||||||
function CalculatePartsTotals(jobLines, parts_tax_rates) {
|
function CalculatePartsTotals(jobLines, parts_tax_rates) {
|
||||||
const jl = jobLines.filter((jl) => !jl.removed);
|
const jl = jobLines.filter((jl) => !jl.removed);
|
||||||
|
// jl.forEach((line) => {
|
||||||
|
// //Some profile based estimates don't automatically add the discount to the line, some do.
|
||||||
|
// //Clean up the ones that don't to add it in.
|
||||||
|
|
||||||
|
// //Apply a discount to the line if there is a profile discount, but it isn't added to the line itself.
|
||||||
|
// const partTax = parts_tax_rates[line.part_type];
|
||||||
|
// if (
|
||||||
|
// line.act_price > 0 &&
|
||||||
|
// partTax &&
|
||||||
|
// partTax.prt_discp &&
|
||||||
|
// partTax.prt_discp > 0
|
||||||
|
// ) {
|
||||||
|
// //apply a discount
|
||||||
|
// const discount = Dinero({
|
||||||
|
// amount: Math.round(line.act_price * 100),
|
||||||
|
// }).percentage(
|
||||||
|
// Math.abs(partTax.prt_discp) > 1
|
||||||
|
// ? partTax.prt_discp
|
||||||
|
// : partTax.prt_discp * 100
|
||||||
|
// );
|
||||||
|
// line.prt_dsmk_m = discount.toFormat("0.0");
|
||||||
|
// line.prt_dsmk_p = partTax.prt_discp;
|
||||||
|
// line.act_price = Dinero({
|
||||||
|
// amount: Math.round(line.act_price * 100),
|
||||||
|
// })
|
||||||
|
// .subtract(discount)
|
||||||
|
// .toFormat("0.0");
|
||||||
|
// } else if (
|
||||||
|
// line.act_price > 0 &&
|
||||||
|
// partTax &&
|
||||||
|
// partTax.prt_mkupp &&
|
||||||
|
// partTax.prt_mkupp > 0
|
||||||
|
// ) {
|
||||||
|
// //apply a mark up
|
||||||
|
// const markup = Dinero({
|
||||||
|
// amount: Math.round(line.act_price * 100),
|
||||||
|
// }).percentage(
|
||||||
|
// Math.abs(partTax.prt_mkupp) > 1
|
||||||
|
// ? partTax.prt_mkupp
|
||||||
|
// : partTax.prt_mkupp * 100
|
||||||
|
// );
|
||||||
|
// line.prt_dsmk_m = markup.toFormat("0.0");
|
||||||
|
// line.prt_dsmk_p = partTax.prt_mkupp;
|
||||||
|
// line.act_price = Dinero({ amount: Math.round(line.act_price * 100) })
|
||||||
|
// .add(markup)
|
||||||
|
// .toFormat("0.0");
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
const ret = jl.reduce(
|
const ret = jl.reduce(
|
||||||
(acc, value) => {
|
(acc, value) => {
|
||||||
@@ -715,7 +798,7 @@ function CalculateTaxesTotals(job, otherTotals) {
|
|||||||
}
|
}
|
||||||
console.log(statePartsTax.toFormat(), val.line_desc);
|
console.log(statePartsTax.toFormat(), val.line_desc);
|
||||||
});
|
});
|
||||||
console.log("State Parts Tax", statePartsTax.toFormat());
|
|
||||||
let ret = {
|
let ret = {
|
||||||
subtotal: subtotal,
|
subtotal: subtotal,
|
||||||
federal_tax: subtotal
|
federal_tax: subtotal
|
||||||
@@ -742,21 +825,21 @@ function CalculateTaxesTotals(job, otherTotals) {
|
|||||||
otherTotals.additional.storage.percentage((job.tax_str_rt || 0) * 100)
|
otherTotals.additional.storage.percentage((job.tax_str_rt || 0) * 100)
|
||||||
)
|
)
|
||||||
.add(additionalItemsTax)
|
.add(additionalItemsTax)
|
||||||
.add(
|
.add(
|
||||||
otherTotals.rates.mapa.hasMapaLine === false //If parts and materials were not added as lines, we must calculate the taxes on them.
|
otherTotals.rates.mapa.hasMapaLine === false //If parts and materials were not added as lines, we must calculate the taxes on them.
|
||||||
? otherTotals.rates.mapa.total.percentage(
|
? otherTotals.rates.mapa.total.percentage(
|
||||||
(job.tax_paint_mat_rt || 0) * 100
|
(job.tax_paint_mat_rt || 0) * 100
|
||||||
)
|
)
|
||||||
: Dinero()
|
: Dinero()
|
||||||
)
|
)
|
||||||
.add(
|
.add(
|
||||||
otherTotals.rates.mash.hasMashLine === false //If parts and materials were not added as lines, we must calculate the taxes on them.
|
otherTotals.rates.mash.hasMashLine === false //If parts and materials were not added as lines, we must calculate the taxes on them.
|
||||||
? otherTotals.rates.mash.total.percentage(
|
? otherTotals.rates.mash.total.percentage(
|
||||||
(job.tax_paint_mat_rt || 0) * 100
|
(job.tax_paint_mat_rt || 0) * 100
|
||||||
)
|
)
|
||||||
: Dinero()
|
: Dinero()
|
||||||
),
|
),
|
||||||
|
|
||||||
local_tax: subtotal.percentage((job.local_tax_rate || 0) * 100),
|
local_tax: subtotal.percentage((job.local_tax_rate || 0) * 100),
|
||||||
};
|
};
|
||||||
ret.total_repairs = ret.subtotal
|
ret.total_repairs = ret.subtotal
|
||||||
@@ -803,6 +886,17 @@ function DiscountNotAlreadyCounted(jobline, joblines) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Check it against the database price too? If it's an OE part.
|
||||||
|
console.log(jobline.db_price - jobline.act_price);
|
||||||
|
if (
|
||||||
|
Math.abs(jobline.db_price - jobline.act_price) -
|
||||||
|
Math.abs(jobline.prt_dsmk_m) <
|
||||||
|
0.01
|
||||||
|
) {
|
||||||
|
console.log(jobline.line_desc, "Already had the discount counted.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
//If it's not a discount line, then it definitely hasn't been counted yet.
|
//If it's not a discount line, then it definitely hasn't been counted yet.
|
||||||
jobline.db_ref !== "900510" &&
|
jobline.db_ref !== "900510" &&
|
||||||
|
|||||||
Reference in New Issue
Block a user