Merge release & add time ticket calculations.

This commit is contained in:
Patrick Fic
2021-09-13 14:47:09 -07:00
13 changed files with 7789 additions and 7604 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project be_version="2.7.1" version="1.2">
<babeledit_project version="1.2" be_version="2.7.1">
<!--
BabelEdit project file
@@ -3683,6 +3683,69 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>itc_federal</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>itc_local</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>itc_state</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>mappingname</name>
<definition_loaded>false</definition_loaded>
@@ -5819,27 +5882,6 @@
<folder_node>
<name>responsibilitycenters</name>
<children>
<concept_node>
<name>LA4</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>ap</name>
<definition_loaded>false</definition_loaded>
@@ -5987,6 +6029,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>la4</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>lab</name>
<definition_loaded>false</definition_loaded>
@@ -17284,6 +17347,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>getmakes</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>post</name>
<definition_loaded>false</definition_loaded>

View File

@@ -120,7 +120,9 @@ export function DmsAllocationsSummary({ socket, bodyshop, jobId, title }) {
{totals.totalSale.toFormat()}
</Table.Summary.Cell>
<Table.Summary.Cell>
{totals.totalCost.toFormat()}
{
// totals.totalCost.toFormat()
}
</Table.Summary.Cell>
<Table.Summary.Cell></Table.Summary.Cell>
<Table.Summary.Cell></Table.Summary.Cell>

View File

@@ -13,6 +13,7 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
@@ -22,9 +23,10 @@ import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
});
export function JobsDetailRates({ jobRO, form, job }) {
export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
const { t } = useTranslation();
return (
<div>
@@ -77,7 +79,7 @@ export function JobsDetailRates({ jobRO, form, job }) {
label={t("jobs.fields.adjustment_bottom_line")}
name="adjustment_bottom_line"
>
<CurrencyInput disabled={jobRO} />
<CurrencyInput disabled={jobRO || bodyshop.cdk_dealerid} />
</Form.Item>
<Space align="end">
<Form.Item label={t("jobs.fields.ca_bc_pvrt")} name="ca_bc_pvrt">

View File

@@ -121,6 +121,27 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.dms.itc_federal")}
valuePropName="checked"
name={["cdk_configuration", "itc_federal"]}
>
<Switch />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.dms.itc_state")}
valuePropName="checked"
name={["cdk_configuration", "itc_state"]}
>
<Switch />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.dms.itc_local")}
valuePropName="checked"
name={["cdk_configuration", "itc_local"]}
>
<Switch />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("bodyshop.labels.dms.cdk.payers")}>
<Form.List name={["cdk_configuration", "payers"]}>
@@ -471,20 +492,26 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
{fields.map((field, index) => (
<Form.Item key={field.key}>
<div>
<Form.Item
label={t("bodyshop.fields.dms.mappingname")}
key={`${index}name`}
name={[field.name, "name"]}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
<LayoutFormRow>
<Form.Item
label={t("bodyshop.fields.dms.mappingname")}
key={`${index}name`}
name={[field.name, "name"]}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Input />
</Form.Item>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
</LayoutFormRow>
<LayoutFormRow
header={t("bodyshop.labels.defaultcostsmapping")}
>
@@ -1627,12 +1654,6 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
</Select>
</Form.Item>
</LayoutFormRow>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
</div>
</Form.Item>
))}
@@ -2717,7 +2738,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
</Form.Item>
{bodyshop.cdk_dealerid && (
<Form.Item
label={t("bodyshop.fields.responsibilitycenter_dms_acctnumber")}
label={t("bodyshop.fields.dms.dms_acctnumber")}
rules={[
{
required: true,
@@ -2815,7 +2836,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
</Form.Item>
{bodyshop.cdk_dealerid && (
<Form.Item
label={t("bodyshop.fields.responsibilitycenter_dms_acctnumber")}
label={t("bodyshop.fields.dms.dms_acctnumber")}
rules={[
{
required: true,
@@ -2911,21 +2932,9 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.responsibilitycenter_rate")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={["md_responsibility_centers", "taxes", "local", "rate"]}
>
<InputNumber precision={2} />
</Form.Item>
{bodyshop.cdk_dealerid && (
<Form.Item
label={t("bodyshop.fields.responsibilitycenter_dms_acctnumber")}
label={t("bodyshop.fields.dms.dms_acctnumber")}
rules={[
{
required: true,
@@ -2942,6 +2951,18 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
<Input />
</Form.Item>
)}
<Form.Item
label={t("bodyshop.fields.responsibilitycenter_rate")}
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
name={["md_responsibility_centers", "taxes", "local", "rate"]}
>
<InputNumber precision={2} />
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={<div>AR</div>}>
{/* <Form.Item

View File

@@ -108,6 +108,8 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
});
history.push("/manage/accounting/receivables");
});
if (socket.disconnected) socket.connect();
return () => {
socket.removeAllListeners();
socket.disconnect();

View File

@@ -218,7 +218,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
},
]}
>
<InputNumber disabled={jobRO} />
<InputNumber precision={0} disabled={jobRO} />
</Form.Item>
)}
{bodyshop.cdk_dealerid && (
@@ -244,7 +244,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
}),
]}
>
<InputNumber disabled={jobRO} />
<InputNumber precision={0} disabled={jobRO} />
</Form.Item>
)}
</LayoutFormRow>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -79,40 +79,78 @@ exports.default = async function (socket, jobid) {
bill_val.billlines.map((line_val) => {
if (!bill_acc[line_val.cost_center])
bill_acc[line_val.cost_center] = Dinero();
const lineDinero = Dinero({
let lineDinero = Dinero({
amount: Math.round((line_val.actual_cost || 0) * 100),
})
.multiply(line_val.quantity)
.multiply(bill_val.is_credit_memo ? -1 : 1);
bill_acc[line_val.cost_center] =
bill_acc[line_val.cost_center].add(lineDinero);
//Add appropriate tax amounts.
const {
applicable_taxes: { local, state, federal },
} = line_val;
if (local) {
taxAllocations.local.cost = taxAllocations.local.cost.add(
if (bodyshop.cdk_configuration.itc_local)
taxAllocations.local.cost = taxAllocations.local.cost.add(
lineDinero.percentage(bill_val.local_tax_rate || 0)
);
lineDinero = lineDinero.add(
lineDinero.percentage(bill_val.local_tax_rate || 0)
);
}
if (state) {
taxAllocations.state.cost = taxAllocations.state.cost.add(
if (bodyshop.cdk_configuration.itc_state)
taxAllocations.state.cost = taxAllocations.state.cost.add(
lineDinero.percentage(bill_val.state_tax_rate || 0)
);
lineDinero = lineDinero.add(
lineDinero.percentage(bill_val.state_tax_rate || 0)
);
}
if (federal) {
taxAllocations.federal.cost = taxAllocations.federal.cost.add(
//If it's an ITC, add it as a negative cost, otherwise add it to the item cost.
if (bodyshop.cdk_configuration.itc_federal)
taxAllocations.federal.cost = taxAllocations.federal.cost.add(
lineDinero.percentage(bill_val.federal_tax_rate || 0)
);
lineDinero = lineDinero.add(
lineDinero.percentage(bill_val.federal_tax_rate || 0)
);
// bill_acc[line_val.cost_center] = bill_acc[line_val.cost_center].add(
// lineDinero.percentage(bill_val.federal_tax_rate || 0)
// );
}
bill_acc[line_val.cost_center] =
bill_acc[line_val.cost_center].add(lineDinero);
return null;
});
return bill_acc;
}, {});
job.timetickets.forEach((ticket) => {
//Get the total amount of the ticket.
let TicketTotal = Dinero({
amount: Math.round(
ticket.rate *
(ticket.employee && ticket.employee.flat_rate
? ticket.productivehrs || 0
: ticket.actualhrs || 0) *
100
),
});
//Add it to the right cost center.
if (!costCenterHash[ticket.cost_center])
costCenterHash[ticket.cost_center] = Dinero();
costCenterHash[ticket.cost_center] =
costCenterHash[ticket.cost_center].add(TicketTotal);
});
const jobAllocations = _.union(
Object.keys(profitCenterHash),
Object.keys(costCenterHash)

View File

@@ -976,7 +976,7 @@ async function GenerateTransWips(socket) {
const allocations = await CalcualteAllocations(socket, socket.JobData.id);
const wips = [];
allocations.forEach((alloc) => {
//Add the sale item
//Add the sale item from each allocation.
if (alloc.sale.getAmount() > 0 && !alloc.tax) {
const item = {
acct: alloc.profitCenter.dms_acctnumber,
@@ -993,6 +993,7 @@ async function GenerateTransWips(socket) {
wips.push(item);
}
//Add the cost Item.
if (alloc.cost.getAmount() > 0 && !alloc.tax) {
const item = {
acct: alloc.costCenter.dms_acctnumber,
@@ -1025,33 +1026,38 @@ async function GenerateTransWips(socket) {
}
if (alloc.tax) {
const item = {
acct: alloc.costCenter.dms_acctnumber,
cntl: socket.JobData.ro_number,
cntl2: null,
credtMemoNo: null,
postAmt: alloc.cost.getAmount(),
postDesc: null,
prod: null,
statCnt: 1,
transID: socket.DMSTransHeader.transID,
trgtCoID: socket.JobData.bodyshop.cdk_configuration.srcco,
};
// if (alloc.cost.getAmount() > 0) {
// const item = {
// acct: alloc.costCenter.dms_acctnumber,
// cntl: socket.JobData.ro_number,
// cntl2: null,
// credtMemoNo: null,
// postAmt: alloc.cost.getAmount(),
// postDesc: null,
// prod: null,
// statCnt: 1,
// transID: socket.DMSTransHeader.transID,
// trgtCoID: socket.JobData.bodyshop.cdk_configuration.srcco,
// };
wips.push(item);
const item2 = {
acct: alloc.profitCenter.dms_acctnumber,
cntl: socket.JobData.ro_number,
cntl2: null,
credtMemoNo: null,
postAmt: alloc.sale.multiply(-1).getAmount(),
postDesc: null,
prod: null,
statCnt: 1,
transID: socket.DMSTransHeader.transID,
trgtCoID: socket.JobData.bodyshop.cdk_configuration.srcco,
};
wips.push(item2);
// wips.push(item);
// }
if (alloc.sale.getAmount() > 0) {
const item2 = {
acct: alloc.profitCenter.dms_acctnumber,
cntl: socket.JobData.ro_number,
cntl2: null,
credtMemoNo: null,
postAmt: alloc.sale.multiply(-1).getAmount(),
postDesc: null,
prod: null,
statCnt: 1,
transID: socket.DMSTransHeader.transID,
trgtCoID: socket.JobData.bodyshop.cdk_configuration.srcco,
};
wips.push(item2);
}
}
});
@@ -1076,7 +1082,11 @@ async function GenerateTransWips(socket) {
console.log(
"WIPS TOTAL",
wips.reduce((acc, val) => acc + val.postAmt, 0)
wips.reduce((acc, val) => {
console.log(val);
console.log(acc + val.postAmt);
return acc + val.postAmt;
}, 0)
);
return wips;

View File

@@ -954,106 +954,116 @@ affected_rows
`;
exports.GET_CDK_ALLOCATIONS = `
query QUERY_JOB_CLOSE_DETAILS($id: uuid!) {
jobs_by_pk(id: $id) {
bodyshop{
id
md_responsibility_centers
}
ro_number
invoice_allocation
ins_co_id
exports.GET_CDK_ALLOCATIONS = `query QUERY_JOB_CLOSE_DETAILS($id: uuid!) {
jobs_by_pk(id: $id) {
bodyshop {
id
ded_amt
ded_status
depreciation_taxes
other_amount_payable
towing_payable
storage_payable
adjustment_bottom_line
federal_tax_rate
state_tax_rate
local_tax_rate
tax_tow_rt
tax_str_rt
tax_paint_mat_rt
tax_sub_rt
tax_lbr_rt
tax_levies_rt
parts_tax_rates
job_totals
rate_la1
rate_la2
rate_la3
rate_la4
rate_laa
rate_lab
rate_lad
rate_lae
rate_laf
rate_lag
rate_lam
rate_lar
rate_las
rate_lau
rate_ma2s
rate_ma2t
rate_ma3s
rate_mabl
rate_macs
rate_mahw
rate_mapa
rate_mash
rate_matd
status
date_exported
date_invoiced
voided
scheduled_completion
actual_completion
scheduled_delivery
actual_delivery
scheduled_in
actual_in
bills {
id
federal_tax_rate
local_tax_rate
state_tax_rate
is_credit_memo
billlines {
actual_cost
cost_center
id
quantity
applicable_taxes
}
}
joblines(where: { removed: { _eq: false } }) {
id
removed
tax_part
line_desc
prt_dsmk_p
prt_dsmk_m
part_type
oem_partno
db_price
act_price
part_qty
mod_lbr_ty
db_hrs
mod_lb_hrs
lbr_op
lbr_amt
op_code_desc
profitcenter_labor
profitcenter_part
prt_dsmk_p
md_responsibility_centers
cdk_configuration
}
ro_number
invoice_allocation
ins_co_id
id
ded_amt
ded_status
depreciation_taxes
other_amount_payable
towing_payable
storage_payable
adjustment_bottom_line
federal_tax_rate
state_tax_rate
local_tax_rate
tax_tow_rt
tax_str_rt
tax_paint_mat_rt
tax_sub_rt
tax_lbr_rt
tax_levies_rt
parts_tax_rates
job_totals
rate_la1
rate_la2
rate_la3
rate_la4
rate_laa
rate_lab
rate_lad
rate_lae
rate_laf
rate_lag
rate_lam
rate_lar
rate_las
rate_lau
rate_ma2s
rate_ma2t
rate_ma3s
rate_mabl
rate_macs
rate_mahw
rate_mapa
rate_mash
rate_matd
status
date_exported
date_invoiced
voided
scheduled_completion
actual_completion
scheduled_delivery
actual_delivery
scheduled_in
actual_in
timetickets {
id
actualhrs
cost_center
productivehrs
rate
employee {
flat_rate
}
}
bills(where: {isinhouse: {_eq: false}}) {
id
federal_tax_rate
local_tax_rate
state_tax_rate
is_credit_memo
billlines {
actual_cost
cost_center
id
quantity
applicable_taxes
}
}
joblines(where: {removed: {_eq: false}}) {
id
removed
tax_part
line_desc
prt_dsmk_p
prt_dsmk_m
part_type
oem_partno
db_price
act_price
part_qty
mod_lbr_ty
db_hrs
mod_lb_hrs
lbr_op
lbr_amt
op_code_desc
profitcenter_labor
profitcenter_part
prt_dsmk_p
}
}
}
`;
exports.GET_QBO_AUTH = `query GET_QBO_AUTH($email: String!) {

View File

@@ -50,7 +50,11 @@ io.on("connection", (socket) => {
socket.on("set-log-level", (level) => {
socket.log_level = level;
createLogEvent(socket, "DEBUG", `Updated log level to ${level}`);
socket.emit("log-event", {
timestamp: new Date(),
level: "INFO",
message: `Updated log level to ${level}`,
});
});
socket.on("cdk-export-job", (jobid) => {