WIP Bill Line deduction from Labor IO-571

This commit is contained in:
Patrick Fic
2021-01-08 17:24:40 -08:00
parent baef1eaaf9
commit 12f14e5425
23 changed files with 638 additions and 93 deletions

View File

@@ -5,15 +5,15 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { INSERT_NEW_BILL } from "../../graphql/bills.queries";
import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectBillEnterModal } from "../../redux/modals/modals.selectors";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import { handleUpload } from "../documents-upload/documents-upload.utility";
import BillFormContainer from "../bill-form/bill-form.container";
import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries";
import { handleUpload } from "../documents-upload/documents-upload.utility";
const mapStateToProps = createStructuredSelector({
billEnterModal: selectBillEnterModal,
@@ -37,81 +37,98 @@ function BillEnterModalContainer({
const [updateJobLines] = useMutation(UPDATE_JOB_LINE_STATUS);
const [loading, setLoading] = useState(false);
const handleFinish = (values) => {
const handleFinish = async (values) => {
console.log(
"🚀 ~ file: bill-enter-modal.container.jsx ~ line 41 ~ handleFinish ~ values",
values
);
setLoading(true);
const { upload, location, ...remainingValues } = values;
insertBill({
const adjustmentsToInsert = [];
const r1 = await insertBill({
variables: {
bill: [
Object.assign({}, remainingValues, {
{
...remainingValues,
billlines: {
data:
remainingValues.billlines &&
remainingValues.billlines.map((i) => {
const { deductfromlabor, lbr_adjustment, ...restI } = i;
if (deductfromlabor) {
adjustmentsToInsert.push({
...lbr_adjustment,
act_price: i.act_price,
});
}
return {
...i,
...restI,
joblineid: i.joblineid === "noline" ? null : i.joblineid,
};
}),
},
}),
},
],
},
})
.then((r) => {
const billId = r.data.insert_bills.returning[0].id;
});
updateJobLines({
variables: {
ids: remainingValues.billlines
.filter((il) => il.joblineid !== "noline")
.map((li) => li.joblineid),
status: bodyshop.md_order_statuses.default_received || "Received*",
location: location,
},
}).then((joblineresult) => {
/////////////////////////
if (upload && upload.length > 0) {
//insert Each of the documents?
upload.forEach((u) => {
handleUpload(
{ file: u.originFileObj },
{
bodyshop: bodyshop,
uploaded_by: currentUser.email,
jobId: values.jobid,
billId: billId,
tagsArray: null,
callback: null,
}
);
});
}
///////////////////////////
setLoading(false);
notification["success"]({
message: t("bills.successes.created"),
});
if (billEnterModal.actions.refetch) billEnterModal.actions.refetch();
if (enterAgain) {
form.resetFields();
form.setFieldsValue({ billlines: [] });
} else {
toggleModalVisible();
}
setEnterAgain(false);
});
})
.catch((error) => {
setLoading(false);
setEnterAgain(false);
notification["error"]({
message: t("bills.errors.creating", {
message: JSON.stringify(error),
}),
});
if (!!r1.errors) {
setLoading(false);
setEnterAgain(false);
notification["error"]({
message: t("bills.errors.creating", {
message: JSON.stringify(r1.errors),
}),
});
}
const billId = r1.data.insert_bills.returning[0].id;
await updateJobLines({
variables: {
ids: remainingValues.billlines
.filter((il) => il.joblineid !== "noline")
.map((li) => li.joblineid),
status: bodyshop.md_order_statuses.default_received || "Received*",
location: location,
},
});
console.log("adjustmentsToInsert", adjustmentsToInsert);
/////////////////////////
if (upload && upload.length > 0) {
//insert Each of the documents?
upload.forEach((u) => {
handleUpload(
{ file: u.originFileObj },
{
bodyshop: bodyshop,
uploaded_by: currentUser.email,
jobId: values.jobid,
billId: billId,
tagsArray: null,
callback: null,
}
);
});
}
///////////////////////////
setLoading(false);
notification["success"]({
message: t("bills.successes.created"),
});
if (billEnterModal.actions.refetch) billEnterModal.actions.refetch();
if (enterAgain) {
form.resetFields();
form.setFieldsValue({ billlines: [] });
} else {
toggleModalVisible();
}
setEnterAgain(false);
};
const handleCancel = () => {

View File

@@ -66,6 +66,14 @@ export function BillFormComponent({
return (
<div>
<Form.Item
// label={t("bills.fields.isinhouse")}
style={{ display: "none" }}
name="isinhouse"
valuePropName="checked"
>
<Switch />
</Form.Item>
<LayoutFormRow grow>
<Form.Item
name="jobid"
@@ -106,7 +114,6 @@ export function BillFormComponent({
/>
</Form.Item>
</LayoutFormRow>
<LayoutFormRow>
<Form.Item
label={t("bills.fields.invoice_number")}
@@ -145,14 +152,7 @@ export function BillFormComponent({
>
<Input disabled={disabled || disableInvNumber} />
</Form.Item>
<Form.Item
// label={t("bills.fields.isinhouse")}
style={{ display: "none" }}
name="isinhouse"
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
label={t("bills.fields.date")}
name="date"
@@ -222,7 +222,6 @@ export function BillFormComponent({
responsibilityCenters={responsibilityCenters}
disabled={disabled}
/>
<Form.Item
name="upload"
label="Upload"
@@ -239,7 +238,6 @@ export function BillFormComponent({
<Button>Click to upload</Button>
</Upload>
</Form.Item>
<Form.Item shouldUpdate>
{() => {
const values = form.getFieldsValue([

View File

@@ -10,11 +10,24 @@ import {
} from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import BillLineSearchSelect from "../bill-line-search-select/bill-line-search-select.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
export default function BillEnterModalLinesComponent({
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function BillEnterModalLinesComponent({
bodyshop,
disabled,
lineData,
discount,
@@ -22,7 +35,7 @@ export default function BillEnterModalLinesComponent({
responsibilityCenters,
}) {
const { t } = useTranslation();
const { setFieldsValue, getFieldsValue } = form;
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
return (
<Form.List name="billlines">
@@ -212,6 +225,110 @@ export default function BillEnterModalLinesComponent({
>
<Switch disabled={disabled} />
</Form.Item>
<Form.Item
label={t("billlines.labels.deductfromlabor")}
key={`${index}deductfromlabor`}
valuePropName="checked"
name={[field.name, "deductfromlabor"]}
>
<Switch disabled={disabled} />
</Form.Item>
<Form.Item
shouldUpdate={(prev, cur) =>
prev.billlines[index].deductfromlabor !==
cur.billlines[index].deductfromlabor
}
>
{() => {
if (
getFieldValue([
"billlines",
field.name,
"deductfromlabor",
])
)
return (
<div>
<Form.Item
label={t("joblines.fields.mod_lbr_ty")}
key={`${index}modlbrty`}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
name={[
field.name,
"lbr_adjustment",
"mod_lbr_ty",
]}
>
<Select allowClear>
<Select.Option value="LAA">
{t("joblines.fields.lbr_types.LAA")}
</Select.Option>
<Select.Option value="LAB">
{t("joblines.fields.lbr_types.LAB")}
</Select.Option>
<Select.Option value="LAD">
{t("joblines.fields.lbr_types.LAD")}
</Select.Option>
<Select.Option value="LAE">
{t("joblines.fields.lbr_types.LAE")}
</Select.Option>
<Select.Option value="LAF">
{t("joblines.fields.lbr_types.LAF")}
</Select.Option>
<Select.Option value="LAG">
{t("joblines.fields.lbr_types.LAG")}
</Select.Option>
<Select.Option value="LAM">
{t("joblines.fields.lbr_types.LAM")}
</Select.Option>
<Select.Option value="LAR">
{t("joblines.fields.lbr_types.LAR")}
</Select.Option>
<Select.Option value="LAS">
{t("joblines.fields.lbr_types.LAS")}
</Select.Option>
<Select.Option value="LAU">
{t("joblines.fields.lbr_types.LAU")}
</Select.Option>
<Select.Option value="LA1">
{t("joblines.fields.lbr_types.LA1")}
</Select.Option>
<Select.Option value="LA2">
{t("joblines.fields.lbr_types.LA2")}
</Select.Option>
<Select.Option value="LA3">
{t("joblines.fields.lbr_types.LA3")}
</Select.Option>
<Select.Option value="LA4">
{t("joblines.fields.lbr_types.LA4")}
</Select.Option>
</Select>
</Form.Item>
<Form.Item
label={t("jobs.labels.adjustmentrate")}
name={[field.name, "lbr_adjustment", "rate"]}
initialValue={
bodyshop.default_adjustment_rate
}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<InputNumber precision={2} />
</Form.Item>
</div>
);
return <span />;
}}
</Form.Item>
</LayoutFormRow>
<FormListMoveArrows
move={move}
@@ -246,3 +363,8 @@ export default function BillEnterModalLinesComponent({
</Form.List>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(BillEnterModalLinesComponent);

View File

@@ -20,12 +20,16 @@ export default forwardRef(FormItemPhone);
export const PhoneItemFormatterValidation = (getFieldValue, name) => ({
async validator(rule, value) {
const p = phone(getFieldValue(name), "us");
const p2 = phone(getFieldValue(name), "ca");
if (p.length > 0 || p2.length > 0) {
if (!getFieldValue(name)) {
return Promise.resolve();
} else {
return Promise.reject(i18n.t("general.validation.invalidphone"));
const p = phone(getFieldValue(name), "us");
const p2 = phone(getFieldValue(name), "ca");
if (p.length > 0 || p2.length > 0) {
return Promise.resolve();
} else {
return Promise.reject(i18n.t("general.validation.invalidphone"));
}
}
// PhoneInput({

View File

@@ -15,7 +15,7 @@ import { UPDATE_JOB } from "../../graphql/jobs.queries";
export default function LaborAllocationsAdjustmentEdit({
jobId,
mod_lbr_ty,
adjustments = [],
adjustments,
children,
}) {
const [loading, setLoading] = useState(false);
@@ -30,10 +30,10 @@ export default function LaborAllocationsAdjustmentEdit({
variables: {
jobId: jobId,
job: {
lbr_adjustments: [
{ mod_lbr_ty: values.mod_lbr_ty, hours: values.hours },
...adjustments.filter((a) => a.mod_lbr_ty !== values.mod_lbr_ty),
],
lbr_adjustments: {
...adjustments,
[values.mod_lbr_ty]: values.hours,
},
},
},
});
@@ -61,8 +61,7 @@ export default function LaborAllocationsAdjustmentEdit({
onFinish={handleFinish}
initialValues={{
mod_lbr_ty: mod_lbr_ty,
hours: adjustments.filter((i) => i.mod_lbr_ty === mod_lbr_ty)[0]
?.hours,
hours: adjustments[mod_lbr_ty],
}}
>
<Form.Item

View File

@@ -8,9 +8,7 @@ export const CalculateAllocationsTotals = (
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
const ticketCodes = timetickets.map((item) => item.cieca_code);
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
const adjustmentCodes = adjustments.map((item) => item.mod_lbr_ty);
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
const allCodes = [...jobCodes, ...ticketCodes, ...adjustmentCodes].filter(
const allCodes = [...jobCodes, ...ticketCodes].filter(
(value, index, self) => self.indexOf(value) === index && !!value
);
@@ -21,11 +19,7 @@ export const CalculateAllocationsTotals = (
total: joblines.reduce((acc2, val2) => {
return val2.mod_lbr_ty === value ? acc2 + val2.mod_lb_hrs : acc2;
}, 0),
adjustments: adjustments.reduce((acc3, val3) => {
console.log("acc3", acc3);
console.log("val3", val3);
return val3.mod_lbr_ty === value ? acc3 + val3.hours : acc3;
}, 0),
adjustments: adjustments[value] || 0,
claimed: timetickets.reduce((acc3, val3) => {
return val3.ciecacode === value ? acc3 + val3.productivehrs : acc3;
}, 0),

View File

@@ -285,6 +285,18 @@ export default function ShopInfoComponent({ form, saveLoading }) {
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.default_adjustment_rate")}
name={"default_adjustment_rate"}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}
>
<InputNumber min={0} precision={2} />
</Form.Item>
<Form.Item shouldUpdate>
{() => {
return (