IO-1967 Convert dollar amount to labor.

This commit is contained in:
Patrick Fic
2022-06-29 15:05:03 -07:00
parent 037ff4c2a1
commit 39dbf40a49
12 changed files with 365 additions and 14 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
@@ -17826,6 +17826,27 @@
<folder_node>
<name>actions</name>
<children>
<concept_node>
<name>converttolabor</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>new</name>
<definition_loaded>false</definition_loaded>
@@ -19006,6 +19027,27 @@
<folder_node>
<name>labels</name>
<children>
<concept_node>
<name>adjustmenttobeadded</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>billref</name>
<definition_loaded>false</definition_loaded>
@@ -19027,6 +19069,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>convertedtolabor</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>edit</name>
<definition_loaded>false</definition_loaded>

View File

@@ -44,6 +44,7 @@ import JobCreateIOU from "../job-create-iou/job-create-iou.component";
import JobLinesExpander from "./job-lines-expander.component";
import { selectBodyshop } from "../../redux/user/user.selectors";
import moment from "moment";
import JobLineConvertToLabor from "../job-line-convert-to-labor/job-line-convert-to-labor.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -295,9 +296,9 @@ export function JobLinesComponent({
dataIndex: "actions",
key: "actions",
render: (text, record) => (
<div>
{(record.manual_line || jobIsPrivate) && (
<Space>
{(record.manual_line || jobIsPrivate) && (
<>
<Button
disabled={jobRO}
onClick={() => {
@@ -334,9 +335,10 @@ export function JobLinesComponent({
>
<DeleteFilled />
</Button>
</Space>
</>
)}
</div>
<JobLineConvertToLabor jobline={record} job={job} />
</Space>
),
},
];

View File

@@ -0,0 +1,244 @@
import { ClockCircleOutlined } from "@ant-design/icons";
import { useApolloClient, useMutation } from "@apollo/client";
import {
Button,
Card,
Form,
InputNumber,
notification,
Popover,
Select,
Space,
Tooltip,
} from "antd";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { logImEXEvent } from "../../firebase/firebase.utils";
import {
QUERY_JOB_LBR_ADJUSTMENTS,
UPDATE_JOB,
} from "../../graphql/jobs.queries";
import {
INSERT_SCOREBOARD_ENTRY,
UPDATE_SCOREBOARD_ENTRY,
} from "../../graphql/scoreboard.queries";
import FormDatePicker from "../form-date-picker/form-date-picker.component";
import LaborTypeFormItemComponent from "../form-items-formatted/labor-type-form-item.component";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { insertAuditTrail } from "../../redux/application/application.actions";
import _ from "lodash";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
});
const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) =>
dispatch(insertAuditTrail({ jobid, operation })),
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobLineConvertToLabor);
export function JobLineConvertToLabor({ jobline, job, ...otherBtnProps }) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [form] = Form.useForm();
const [visibility, setVisibility] = useState(false);
const client = useApolloClient();
const handleFinish = async (values) => {
const { mod_lbr_ty } = values;
logImEXEvent("job_convert_dollar_to_labor");
setLoading(true);
const existingAdjustments = await client.query({
query: QUERY_JOB_LBR_ADJUSTMENTS,
variables: {
id: job.id,
},
});
const newAdjustments = _.cloneDeep(
existingAdjustments.data.jobs_by_pk.lbr_adjustments
);
newAdjustments[mod_lbr_ty] =
(newAdjustments[mod_lbr_ty] || 0) +
calculateAdjustment({ mod_lbr_ty, job, jobline });
const jobUpdate = client.mutate({
mutation: UPDATE_JOB,
variables: {
jobId: job.id,
job: { lbr_adjustments: newAdjustments },
},
});
const lineUpdate = client.mutate({
mutation: UPDATE_JOB_LINE,
variables: {
lineId: jobline.id,
line: { convertedtolbr: true },
},
});
if (!!jobUpdate.errors) {
notification["error"]({
message: t("jobs.errors.saving", {
message: JSON.stringify(jobUpdate.errors),
}),
});
return;
}
if (!!lineUpdate.errors) {
notification["error"]({
message: t("joblines.errors.saving", {
message: JSON.stringify(lineUpdate.errors),
}),
});
return;
}
insertAuditTrail({
jobid: values.jobid,
operation: AuditTrailMapping.jobmodifylbradj(),
});
setLoading(false);
setVisibility(false);
};
const overlay = (
<Card>
<Form form={form} layout="vertical" onFinish={handleFinish}>
<Form.Item
label={t("joblines.fields.mod_lbr_ty")}
name="mod_lbr_ty"
rules={[
{
required: true,
//message: t("general.validation.required"),
},
]}
>
<Select allowClear optionFilterProp="children" showSearch>
<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 shouldUpdate>
{() => {
const { mod_lbr_ty } = form.getFieldsValue();
return t("joblines.labels.adjustmenttobeadded", {
adjustment: calculateAdjustment({
mod_lbr_ty,
job,
jobline,
}).toFixed(1),
});
}}
</Form.Item>
<Space wrap>
<Button
type="primary"
disabled={jobline.convertedtolbr}
htmlType="submit"
>
{t("general.actions.save")}
</Button>
<Button onClick={() => setVisibility(false)}>
{t("general.actions.cancel")}
</Button>
</Space>
</Form>
</Card>
);
const handleClick = (e) => {
setLoading(true);
form.setFieldsValue({
// date: new moment(),
// bodyhrs: Math.round(v.bodyhrs * 10) / 10,
// painthrs: Math.round(v.painthrs * 10) / 10,
});
setVisibility(true);
setLoading(false);
};
return (
<Popover
disabled={jobline.convertedtolbr}
content={overlay}
visible={visibility}
placement="bottom"
>
<Tooltip title={t("joblines.actions.converttolabor")}>
<Button
disabled={jobline.convertedtolbr}
loading={loading}
onClick={handleClick}
{...otherBtnProps}
>
<ClockCircleOutlined />
</Button>
</Tooltip>
</Popover>
);
}
function calculateAdjustment({ mod_lbr_ty, job, jobline }) {
if (!mod_lbr_ty) return 0;
const rate = job[`rate_${mod_lbr_ty.toLowerCase()}`];
if (rate === 0 || rate === null || rate === undefined) return 0;
const adj = jobline.act_price / job[`rate_${mod_lbr_ty.toLowerCase()}`];
return adj;
}

View File

@@ -1,4 +1,4 @@
import { Form, Select } from "antd";
import { Form, Select, Space, Tooltip } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
@@ -8,6 +8,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import LaborTypeFormItem from "../form-items-formatted/labor-type-form-item.component";
import PartTypeFormItem from "../form-items-formatted/part-type-form-item.component";
import ReadOnlyFormItem from "../form-items-formatted/read-only-form-item.component";
import { WarningOutlined } from "@ant-design/icons";
import "./jobs-close-lines.styles.scss";
const mapStateToProps = createStructuredSelector({
@@ -62,6 +63,7 @@ export function JobsCloseLines({ bodyshop, job, jobRO }) {
</Form.Item>
</td>
<td>
<Space>
<Form.Item
span={2}
// label={t("joblines.fields.act_price")}
@@ -70,6 +72,14 @@ export function JobsCloseLines({ bodyshop, job, jobRO }) {
>
<ReadOnlyFormItem type="currency" />
</Form.Item>
<Form.Item
noStyle
key={`${index}convertedtolbr`}
name={[field.name, "convertedtolbr"]}
>
<HasBeenConvertedTolabor />
</Form.Item>
</Space>
</td>
<td>
<Form.Item
@@ -192,3 +202,14 @@ export function JobsCloseLines({ bodyshop, job, jobRO }) {
);
}
export default connect(mapStateToProps, mapDispatchToProps)(JobsCloseLines);
const HasBeenConvertedTolabor = ({ value }) => {
const { t } = useTranslation();
console.log(value);
if (!value) return null;
return (
<Tooltip title={t("joblines.labels.convertedtolabor")}>
<WarningOutlined style={{ color: "tomato" }} />
</Tooltip>
);
};

View File

@@ -177,6 +177,7 @@ export const UPDATE_JOB_LINE = gql`
location
status
removed
convertedtolbr
}
}
}

View File

@@ -702,6 +702,7 @@ export const GET_JOB_BY_PK = gql`
prt_dsmk_p
prt_dsmk_m
ioucreated
convertedtolbr
billlines(limit: 1, order_by: { bill: { date: desc } }) {
id
quantity
@@ -1905,6 +1906,7 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
profitcenter_labor
profitcenter_part
prt_dsmk_p
convertedtolbr
}
}
}

View File

@@ -1114,6 +1114,7 @@
},
"joblines": {
"actions": {
"converttolabor": "Convert amount to Labor.",
"new": "New Line"
},
"errors": {
@@ -1179,7 +1180,9 @@
"unq_seq": "Seq #"
},
"labels": {
"adjustmenttobeadded": "Adjustment to be added: {{adjustment}}",
"billref": "Latest Bill",
"convertedtolabor": "This line has been converted to labor. Ensure you adjust the profit center for the amount accordingly.",
"edit": "Edit Line",
"ioucreated": "IOU",
"new": "New Line",

View File

@@ -1114,6 +1114,7 @@
},
"joblines": {
"actions": {
"converttolabor": "",
"new": ""
},
"errors": {
@@ -1179,7 +1180,9 @@
"unq_seq": "Seq #"
},
"labels": {
"adjustmenttobeadded": "",
"billref": "",
"convertedtolabor": "",
"edit": "Línea de edición",
"ioucreated": "",
"new": "Nueva línea",

View File

@@ -1114,6 +1114,7 @@
},
"joblines": {
"actions": {
"converttolabor": "",
"new": ""
},
"errors": {
@@ -1179,7 +1180,9 @@
"unq_seq": "Seq #"
},
"labels": {
"adjustmenttobeadded": "",
"billref": "",
"convertedtolabor": "",
"edit": "Ligne d'édition",
"ioucreated": "",
"new": "Nouvelle ligne",

View File

@@ -2384,6 +2384,7 @@
- bett_tax
- bett_type
- cert_part
- convertedtolbr
- created_at
- db_hrs
- db_price
@@ -2447,6 +2448,7 @@
- bett_tax
- bett_type
- cert_part
- convertedtolbr
- created_at
- db_hrs
- db_price
@@ -2521,6 +2523,7 @@
- bett_tax
- bett_type
- cert_part
- convertedtolbr
- created_at
- db_hrs
- db_price

View File

@@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."joblines" add column "convertedtolbr" boolean
-- not null default 'false';

View File

@@ -0,0 +1,2 @@
alter table "public"."joblines" add column "convertedtolbr" boolean
not null default 'false';