WIP Financial
This commit is contained in:
@@ -15,16 +15,16 @@ import InvoiceEnterModalComponent from "./invoice-enter-modal.component";
|
|||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
invoiceEnterModal: selectInvoiceEnterModal,
|
invoiceEnterModal: selectInvoiceEnterModal,
|
||||||
bodyshop: selectBodyshop
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
toggleModalVisible: () => dispatch(toggleModalVisible("invoiceEnter"))
|
toggleModalVisible: () => dispatch(toggleModalVisible("invoiceEnter")),
|
||||||
});
|
});
|
||||||
|
|
||||||
function InvoiceEnterModalContainer({
|
function InvoiceEnterModalContainer({
|
||||||
invoiceEnterModal,
|
invoiceEnterModal,
|
||||||
toggleModalVisible,
|
toggleModalVisible,
|
||||||
bodyshop
|
bodyshop,
|
||||||
}) {
|
}) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -35,45 +35,45 @@ function InvoiceEnterModalContainer({
|
|||||||
const { data: RoAutoCompleteData } = useQuery(ACTIVE_JOBS_FOR_AUTOCOMPLETE, {
|
const { data: RoAutoCompleteData } = useQuery(ACTIVE_JOBS_FOR_AUTOCOMPLETE, {
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
variables: { statuses: bodyshop.md_ro_statuses.open_statuses || ["Open"] },
|
variables: { statuses: bodyshop.md_ro_statuses.open_statuses || ["Open"] },
|
||||||
skip: !invoiceEnterModal.visible
|
skip: !invoiceEnterModal.visible,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { data: VendorAutoCompleteData } = useQuery(
|
const { data: VendorAutoCompleteData } = useQuery(
|
||||||
SEARCH_VENDOR_AUTOCOMPLETE,
|
SEARCH_VENDOR_AUTOCOMPLETE,
|
||||||
{
|
{
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
skip: !invoiceEnterModal.visible
|
skip: !invoiceEnterModal.visible,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const [loadLines, { data: lineData }] = useLazyQuery(
|
const [loadLines, { data: lineData }] = useLazyQuery(
|
||||||
GET_JOB_LINES_TO_ENTER_INVOICE,
|
GET_JOB_LINES_TO_ENTER_INVOICE,
|
||||||
{
|
{
|
||||||
fetchPolicy: "network-only"
|
fetchPolicy: "network-only",
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleFinish = values => {
|
const handleFinish = (values) => {
|
||||||
insertInvoice({
|
insertInvoice({
|
||||||
variables: {
|
variables: {
|
||||||
invoice: [
|
invoice: [
|
||||||
Object.assign({}, values, {
|
Object.assign({}, values, {
|
||||||
invoicelines: { data: values.invoicelines }
|
invoicelines: { data: values.invoicelines },
|
||||||
})
|
}),
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
.then(r => {
|
.then((r) => {
|
||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("invoices.successes.created")
|
message: t("invoices.successes.created"),
|
||||||
});
|
});
|
||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("invoices.errors.creating", {
|
message: t("invoices.errors.creating", {
|
||||||
message: JSON.stringify(error)
|
message: JSON.stringify(error),
|
||||||
})
|
}),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -82,6 +82,8 @@ function InvoiceEnterModalContainer({
|
|||||||
toggleModalVisible();
|
toggleModalVisible();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
console.log("invoiceEnterModal", invoiceEnterModal);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={
|
title={
|
||||||
@@ -96,7 +98,17 @@ function InvoiceEnterModalContainer({
|
|||||||
onCancel={handleCancel}
|
onCancel={handleCancel}
|
||||||
destroyOnClose
|
destroyOnClose
|
||||||
>
|
>
|
||||||
<Form onFinish={handleFinish} autoComplete={"off"} form={form}>
|
<Form
|
||||||
|
onFinish={handleFinish}
|
||||||
|
autoComplete={"off"}
|
||||||
|
form={form}
|
||||||
|
initialValues={{
|
||||||
|
jobid:
|
||||||
|
(invoiceEnterModal.context.job &&
|
||||||
|
invoiceEnterModal.context.job.id) ||
|
||||||
|
null,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<InvoiceEnterModalComponent
|
<InvoiceEnterModalComponent
|
||||||
form={form}
|
form={form}
|
||||||
roAutoCompleteOptions={RoAutoCompleteData && RoAutoCompleteData.jobs}
|
roAutoCompleteOptions={RoAutoCompleteData && RoAutoCompleteData.jobs}
|
||||||
|
|||||||
@@ -18,31 +18,47 @@ function CalculateTaxesTotals(job, otherTotals) {
|
|||||||
job.towing_payable +
|
job.towing_payable +
|
||||||
job.storage_payable; //Levies should be included??
|
job.storage_payable; //Levies should be included??
|
||||||
|
|
||||||
console.log("job.parts_tax_rates", job.parts_tax_rates);
|
|
||||||
|
|
||||||
const statePartsTax = job.joblines.reduce((acc, val) => {
|
const statePartsTax = job.joblines.reduce((acc, val) => {
|
||||||
if (!!!val.part_type) return acc;
|
console.log("val", val);
|
||||||
|
if (!!!val.tax_part) return acc;
|
||||||
if (!!job.parts_tax_rates[val.part_type]) {
|
if (!!job.parts_tax_rates[val.part_type]) {
|
||||||
return (
|
return (
|
||||||
acc +
|
acc +
|
||||||
(val.act_price * job.parts_tax_rates[val.part_type].prt_tax_rt || 0)
|
val.act_price *
|
||||||
|
val.part_qty *
|
||||||
|
(job.parts_tax_rates[val.part_type].prt_tax_rt || 0)
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
|
console.log("otherTotals", otherTotals);
|
||||||
|
|
||||||
|
console.log("job", job);
|
||||||
|
console.log("parts pst", statePartsTax);
|
||||||
|
console.log(
|
||||||
|
"pst on labor",
|
||||||
|
otherTotals.rates.rates_subtotal * (job.tax_lbr_rt || 0)
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"pst on mat",
|
||||||
|
(otherTotals.rates.paint_mat.total + otherTotals.rates.shop_mat.total) *
|
||||||
|
(job.tax_paint_mat_rt || 0)
|
||||||
|
);
|
||||||
|
|
||||||
let ret = {
|
let ret = {
|
||||||
subtotal: subtotal,
|
subtotal: subtotal,
|
||||||
federal_tax: subtotal * job.federal_tax_rate || 0,
|
federal_tax: subtotal * (job.federal_tax_rate || 0),
|
||||||
statePartsTax,
|
statePartsTax,
|
||||||
state_tax:
|
state_tax:
|
||||||
statePartsTax +
|
statePartsTax +
|
||||||
(otherTotals.rates.rates_subtotal * job.tax_lbr_rate || 0) +
|
otherTotals.rates.rates_subtotal * (job.tax_lbr_rt || 0) +
|
||||||
(job.towing_payable || 0 * job.tax_tow_rt || 0) +
|
((job.towing_payable || 0) * job.tax_tow_rt || 0) +
|
||||||
(job.storage_payable || 0 * job.tax_str_rt || 0) +
|
((job.storage_payable || 0) * job.tax_str_rt || 0) +
|
||||||
(otherTotals.rates.paint_mat.subtotal * job.tax_paint_mat_rt || 0),
|
(otherTotals.rates.paint_mat.total + otherTotals.rates.shop_mat.total) *
|
||||||
local_tax: subtotal * job.local_tax_rate || 0,
|
(job.tax_paint_mat_rt || 0),
|
||||||
|
local_tax: subtotal * (job.local_tax_rate || 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
ret.total_repairs =
|
ret.total_repairs =
|
||||||
@@ -175,7 +191,11 @@ function CalculateRatesTotals(ratesList, shoprates) {
|
|||||||
for (const property in ret) {
|
for (const property in ret) {
|
||||||
ret[property].total = ret[property].hours * ret[property].rate;
|
ret[property].total = ret[property].hours * ret[property].rate;
|
||||||
subtotal = subtotal + ret[property].hours * ret[property].rate;
|
subtotal = subtotal + ret[property].hours * ret[property].rate;
|
||||||
if (property !== "paint_mat" && property !== "shop_mat")
|
if (
|
||||||
|
property !== "paint_mat" &&
|
||||||
|
property !== "shop_mat" &&
|
||||||
|
property !== "rate_atp"
|
||||||
|
)
|
||||||
rates_subtotal =
|
rates_subtotal =
|
||||||
rates_subtotal + ret[property].hours * ret[property].rate;
|
rates_subtotal + ret[property].hours * ret[property].rate;
|
||||||
}
|
}
|
||||||
@@ -201,7 +221,7 @@ function CalculatePartsTotals(jobLines) {
|
|||||||
...acc,
|
...acc,
|
||||||
parts: {
|
parts: {
|
||||||
...acc.parts,
|
...acc.parts,
|
||||||
subtotal: acc.parts.subtotal + value.act_price,
|
subtotal: acc.parts.subtotal + value.act_price * value.part_qty,
|
||||||
//TODO Add Adjustments in
|
//TODO Add Adjustments in
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -237,7 +257,7 @@ function CalculatePartsTotals(jobLines) {
|
|||||||
function CalculateCustPayable(job) {
|
function CalculateCustPayable(job) {
|
||||||
return {
|
return {
|
||||||
deductible: job.ded_amt || 0,
|
deductible: job.ded_amt || 0,
|
||||||
federal_tax: job.federal_tax_payable || 0,
|
federal_tax: job.federal_tax_payable || 0, //TODO Should this be renamed to make it more clear this is customer GST?
|
||||||
other_customer_amount: job.other_amount_payable || 0,
|
other_customer_amount: job.other_amount_payable || 0,
|
||||||
dep_taxes: job.depreciation_taxes || 0,
|
dep_taxes: job.depreciation_taxes || 0,
|
||||||
total:
|
total:
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import AlertComponent from "../alert/alert.component";
|
|||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setInvoiceEnterContext: context =>
|
setInvoiceEnterContext: (context) =>
|
||||||
dispatch(setModalContext({ context: context, modal: "invoiceEnter" }))
|
dispatch(setModalContext({ context: context, modal: "invoiceEnter" })),
|
||||||
});
|
});
|
||||||
export default connect(
|
export default connect(
|
||||||
mapStateToProps,
|
mapStateToProps,
|
||||||
@@ -19,17 +19,17 @@ export default connect(
|
|||||||
)(function JobsDetailPliComponent({
|
)(function JobsDetailPliComponent({
|
||||||
setInvoiceEnterContext,
|
setInvoiceEnterContext,
|
||||||
job,
|
job,
|
||||||
invoicesQuery
|
invoicesQuery,
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setInvoiceEnterContext({
|
setInvoiceEnterContext({
|
||||||
actions: { refetch: null },
|
actions: { refetch: invoicesQuery.refetch || null },
|
||||||
context: {
|
context: {
|
||||||
job
|
job,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -434,10 +434,15 @@ export const QUERY_JOB_FINANCIALS = gql`
|
|||||||
rate_mash
|
rate_mash
|
||||||
rate_matd
|
rate_matd
|
||||||
joblines {
|
joblines {
|
||||||
|
id
|
||||||
|
tax_part
|
||||||
|
prt_dsmk_p
|
||||||
|
prt_dsmk_m
|
||||||
mod_lbr_ty
|
mod_lbr_ty
|
||||||
act_price
|
act_price
|
||||||
mod_lb_hrs
|
mod_lb_hrs
|
||||||
part_type
|
part_type
|
||||||
|
part_qty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user