Added page for job closing BOD-131

This commit is contained in:
Patrick Fic
2020-05-15 16:43:27 -07:00
parent 58b4985319
commit 51ea04bf2c
15 changed files with 833 additions and 444 deletions

View File

@@ -1085,6 +1085,48 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>responsibilitycenter_accountname</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>responsibilitycenter_accountnumber</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>
<folder_node> <folder_node>
<name>responsibilitycenters</name> <name>responsibilitycenters</name>
<children> <children>
@@ -13662,6 +13704,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>jobs-close</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> <concept_node>
<name>jobs-detail</name> <name>jobs-detail</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -14105,6 +14168,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>jobs-close</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> <concept_node>
<name>jobs-create</name> <name>jobs-create</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>

View File

@@ -147,7 +147,7 @@ export default function InvoiceEnterModalLinesComponent({
> >
<Select style={{ width: "150px" }}> <Select style={{ width: "150px" }}>
{responsibilityCenters.costs.map((item) => ( {responsibilityCenters.costs.map((item) => (
<Select.Option key={item}>{item}</Select.Option> <Select.Option key={item.name}>{item.name}</Select.Option>
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>

View File

@@ -0,0 +1,35 @@
import React from "react";
export default function JobCloseLabMatAllocation({
labmatAllocations,
setLabmatAllocations,
}) {
console.log(
"JobCloseLabMatAllocation -> labmatAllocations",
labmatAllocations
);
return (
<div>
<table>
<thead>
<tr>
<th>Rate</th>
<th>Available</th>
</tr>
</thead>
<tbody>
{Object.keys(labmatAllocations).map((alloc) => (
<tr>
<td>{alloc}</td>
<td>
{
//labmatAllocations[alloc].total.toFormat()
}
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}

View File

@@ -64,10 +64,10 @@ export default function JobsList({
render: (text, record) => { render: (text, record) => {
return record.owner ? ( return record.owner ? (
<Link to={"/manage/owners/" + record.owner.id}> <Link to={"/manage/owners/" + record.owner.id}>
{`${record.ownr_fn} ${record.ownr_ln}`} {`${record.ownr_fn || ""} ${record.ownr_ln || ""}`}
</Link> </Link>
) : ( ) : (
<span>{`${record.ownr_fn} ${record.ownr_ln}`}</span> <span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""}`}</span>
); );
}, },
}, },

View File

@@ -32,37 +32,41 @@ export default withRouter(function JobsList({
title: t("jobs.fields.ro_number"), title: t("jobs.fields.ro_number"),
dataIndex: "ro_number", dataIndex: "ro_number",
key: "ro_number", key: "ro_number",
width: "8%", sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
sorter: (a, b) =>
alphaSort(
a.ro_number ? a.ro_number : a.est_number,
b.ro_number ? b.ro_number : b.est_number
),
sortOrder: sortOrder:
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order, state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
render: (text, record) => ( render: (text, record) => (
<Link to={"/manage/jobs/" + record.id}> <Link to={"/manage/jobs/" + record.id}>{record.ro_number}</Link>
{record.ro_number ? record.ro_number : record.est_number}
</Link>
), ),
}, },
{
title: t("jobs.fields.est_number"),
dataIndex: "est_number",
key: "est_number",
sorter: (a, b) => a.est_number - b.est_number,
sortOrder:
state.sortedInfo.columnKey === "est_number" && state.sortedInfo.order,
render: (text, record) => (
<Link to={"/manage/jobs/" + record.id}>{record.est_number}</Link>
),
},
{ {
title: t("jobs.fields.owner"), title: t("jobs.fields.owner"),
dataIndex: "owner", dataIndex: "owner",
key: "owner", key: "owner",
ellipsis: true,
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
width: "25%",
sortOrder: sortOrder:
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
render: (text, record) => { render: (text, record) => {
return record.owner ? ( return record.owner ? (
<Link to={"/manage/owners/" + record.owner.id}> <Link to={"/manage/owners/" + record.owner.id}>
{`${record.ownr_fn} ${record.ownr_ln}`} {`${record.ownr_fn || ""} ${record.ownr_ln || ""}`}
</Link> </Link>
) : ( ) : (
<span>{`${record.ownr_fn} ${record.ownr_ln}`}</span> <span>{`${record.ownr_fn || ""} ${record.ownr_ln || ""}`}</span>
); );
}, },
}, },
@@ -70,7 +74,6 @@ export default withRouter(function JobsList({
title: t("jobs.fields.ownr_ph1"), title: t("jobs.fields.ownr_ph1"),
dataIndex: "ownr_ph1", dataIndex: "ownr_ph1",
key: "ownr_ph1", key: "ownr_ph1",
width: "12%",
ellipsis: true, ellipsis: true,
render: (text, record) => { render: (text, record) => {
return record.ownr_ph1 ? ( return record.ownr_ph1 ? (
@@ -85,8 +88,6 @@ export default withRouter(function JobsList({
title: t("jobs.fields.status"), title: t("jobs.fields.status"),
dataIndex: "status", dataIndex: "status",
key: "status", key: "status",
width: "10%",
ellipsis: true,
sorter: (a, b) => alphaSort(a.status, b.status), sorter: (a, b) => alphaSort(a.status, b.status),
sortOrder: sortOrder:
state.sortedInfo.columnKey === "status" && state.sortedInfo.order, state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
@@ -99,7 +100,6 @@ export default withRouter(function JobsList({
title: t("jobs.fields.vehicle"), title: t("jobs.fields.vehicle"),
dataIndex: "vehicle", dataIndex: "vehicle",
key: "vehicle", key: "vehicle",
width: "15%",
ellipsis: true, ellipsis: true,
render: (text, record) => { render: (text, record) => {
return record.vehicleid ? ( return record.vehicleid ? (
@@ -119,8 +119,6 @@ export default withRouter(function JobsList({
title: t("vehicles.fields.plate_no"), title: t("vehicles.fields.plate_no"),
dataIndex: "plate_no", dataIndex: "plate_no",
key: "plate_no", key: "plate_no",
width: "8%",
ellipsis: true,
sorter: (a, b) => alphaSort(a.plate_no, b.plate_no), sorter: (a, b) => alphaSort(a.plate_no, b.plate_no),
sortOrder: sortOrder:
state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order, state.sortedInfo.columnKey === "plate_no" && state.sortedInfo.order,
@@ -132,7 +130,6 @@ export default withRouter(function JobsList({
title: t("jobs.fields.clm_no"), title: t("jobs.fields.clm_no"),
dataIndex: "clm_no", dataIndex: "clm_no",
key: "clm_no", key: "clm_no",
width: "12%",
ellipsis: true, ellipsis: true,
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no), sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
sortOrder: sortOrder:
@@ -149,7 +146,6 @@ export default withRouter(function JobsList({
title: t("jobs.fields.clm_total"), title: t("jobs.fields.clm_total"),
dataIndex: "clm_total", dataIndex: "clm_total",
key: "clm_total", key: "clm_total",
width: "10%",
sorter: (a, b) => a.clm_total - b.clm_total, sorter: (a, b) => a.clm_total - b.clm_total,
sortOrder: sortOrder:
state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order, state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order,
@@ -165,7 +161,6 @@ export default withRouter(function JobsList({
title: t("jobs.fields.owner_owing"), title: t("jobs.fields.owner_owing"),
dataIndex: "owner_owing", dataIndex: "owner_owing",
key: "owner_owing", key: "owner_owing",
width: "8%",
render: (text, record) => ( render: (text, record) => (
<CurrencyFormatter>{record.owner_owing}</CurrencyFormatter> <CurrencyFormatter>{record.owner_owing}</CurrencyFormatter>
), ),
@@ -210,10 +205,10 @@ export default withRouter(function JobsList({
</div> </div>
); );
}} }}
size="small" size='small'
pagination={{ position: "top" }} pagination={{ position: "top" }}
columns={columns.map((item) => ({ ...item }))} columns={columns.map((item) => ({ ...item }))}
rowKey="id" rowKey='id'
dataSource={jobs} dataSource={jobs}
rowSelection={{ rowSelection={{
onSelect: (record) => { onSelect: (record) => {

View File

@@ -15,433 +15,468 @@ export default function ShopInfoResponsibilityCenterComponent({ form }) {
const [options, setOptions] = useState( const [options, setOptions] = useState(
[ [
...(form.getFieldValue(["md_responsibility_centers", "costs"]) || []), ...(form
...(form.getFieldValue(["md_responsibility_centers", "profits"]) || []) .getFieldValue(["md_responsibility_centers", "costs"])
.map((i) => i.name) || []),
...(form
.getFieldValue(["md_responsibility_centers", "profits"])
.map((i) => i.name) || []),
] || [] ] || []
); );
const handleBlur = () => { const handleBlur = () => {
setOptions([ setOptions([
...(form.getFieldValue(["md_responsibility_centers", "costs"]) || []), ...(form
...(form.getFieldValue(["md_responsibility_centers", "profits"]) || []) .getFieldValue(["md_responsibility_centers", "costs"])
.map((i) => i.name) || []),
...(form
.getFieldValue(["md_responsibility_centers", "profits"])
.map((i) => i.name) || []),
]); ]);
}; };
return ( return (
<div> <div>
<strong>{t("bodyshop.labels.responsibilitycenters.title")}</strong> <strong>{t("bodyshop.labels.responsibilitycenters.title")}</strong>=
<Row> <div>
<Col span={8}> <strong>{t("bodyshop.labels.responsibilitycenters.costs")}</strong>
<strong>{t("bodyshop.labels.responsibilitycenters.costs")}</strong> <Form.List name={["md_responsibility_centers", "costs"]}>
<Form.List name={["md_responsibility_centers", "costs"]}> {(fields, { add, remove }) => {
{(fields, { add, remove }) => { return (
return ( <div>
<div> {fields.map((field, index) => (
{fields.map((field, index) => ( <Form.Item key={field.key} style={{ padding: 0, margin: 2 }}>
<Form.Item <div style={{ display: "flex" }}>
key={field.key} <Form.Item
style={{ padding: 0, margin: 2 }} style={{ padding: 0, margin: 2 }}
> label={t("bodyshop.fields.responsibilitycenter")}
<div style={{ display: "flex" }}> key={`${index}name`}
<Form.Item name={[field.name, "name"]}
style={{ padding: 0, margin: 2 }} rules={[
label={t("bodyshop.fields.responsibilitycenter")} {
key={`${index}`} required: true,
name={[field.name]} message: t("general.validation.required"),
rules={[ },
{ ]}>
required: true, <Input onBlur={handleBlur} />
message: t("general.validation.required") </Form.Item>
} <Form.Item
]} style={{ padding: 0, margin: 2 }}
> label={t(
<Input onBlur={handleBlur} /> "bodyshop.fields.responsibilitycenter_accountname"
</Form.Item> )}
<DeleteFilled key={`${index}accountname`}
onClick={() => { name={[field.name, "accountname"]}
remove(field.name); rules={[
}} {
/> required: true,
</div> message: t("general.validation.required"),
</Form.Item> },
))} ]}>
<Form.Item> <Input onBlur={handleBlur} />
<Button </Form.Item>
type="dashed" <Form.Item
onClick={() => { style={{ padding: 0, margin: 2 }}
add(); label={t(
}} "bodyshop.fields.responsibilitycenter_accountnumber"
style={{ width: "100%" }} )}
> key={`${index}accountnumber`}
{t("bodyshop.actions.newstatus")} name={[field.name, "accountnumber"]}
</Button> rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input onBlur={handleBlur} />
</Form.Item>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
</div>
</Form.Item> </Form.Item>
</div> ))}
); <Form.Item>
}} <Button
</Form.List> type='dashed'
</Col> onClick={() => {
add();
<Col span={8}> }}
<strong>{t("bodyshop.labels.responsibilitycenters.profits")}</strong> style={{ width: "100%" }}>
<Form.List name={["md_responsibility_centers", "profits"]}> {t("bodyshop.actions.newstatus")}
{(fields, { add, remove }) => { </Button>
return ( </Form.Item>
<div> </div>
{fields.map((field, index) => ( );
<Form.Item }}
key={field.key} </Form.List>
style={{ padding: 0, margin: 2 }} </div>
> <div>
<div style={{ display: "flex" }}> <strong>{t("bodyshop.labels.responsibilitycenters.profits")}</strong>
<Form.Item <Form.List name={["md_responsibility_centers", "profits"]}>
style={{ padding: 0, margin: 2 }} {(fields, { add, remove }) => {
label={t("bodyshop.fields.responsibilitycenter")} return (
key={`${index}`} <div>
name={[field.name]} {fields.map((field, index) => (
rules={[ <Form.Item key={field.key} style={{ padding: 0, margin: 2 }}>
{ <div style={{ display: "flex" }}>
required: true, <Form.Item
message: t("general.validation.required") style={{ padding: 0, margin: 2 }}
} label={t("bodyshop.fields.responsibilitycenter")}
]} key={`${index}name`}
> name={[field.name, "name"]}
<Input onBlur={handleBlur} /> rules={[
</Form.Item> {
<DeleteFilled required: true,
onClick={() => { message: t("general.validation.required"),
remove(field.name); },
}} ]}>
/> <Input onBlur={handleBlur} />
</div> </Form.Item>
</Form.Item> <Form.Item
))} style={{ padding: 0, margin: 2 }}
<Form.Item> label={t(
<Button "bodyshop.fields.responsibilitycenter_accountname"
type="dashed" )}
onClick={() => { key={`${index}accountname`}
add(); name={[field.name, "accountname"]}
}} rules={[
style={{ width: "100%" }} {
> required: true,
{t("bodyshop.actions.newstatus")} message: t("general.validation.required"),
</Button> },
]}>
<Input onBlur={handleBlur} />
</Form.Item>
<Form.Item
style={{ padding: 0, margin: 2 }}
label={t(
"bodyshop.fields.responsibilitycenter_accountnumber"
)}
key={`${index}accountnumber`}
name={[field.name, "accountnumber"]}
rules={[
{
required: true,
message: t("general.validation.required"),
},
]}>
<Input onBlur={handleBlur} />
</Form.Item>
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
</div>
</Form.Item> </Form.Item>
</div>
);
}}
</Form.List>
</Col>
<Col span={8}>
<SelectorDiv>
<Form.Item
label={t("bodyshop.fields.responsibilitycenters.atp")}
rules={[
{
required: true,
message: t("general.validation.required")
}
]}
name={["md_responsibility_centers", "defaults", "ATP"]}
>
<Select>
{options.map((item, idx) => (
<Select.Option key={idx}>{item}</Select.Option>
))} ))}
</Select> <Form.Item>
</Form.Item> <Button
<Form.Item type='dashed'
label={t("bodyshop.fields.responsibilitycenters.lab")} onClick={() => {
rules={[ add();
{ }}
required: true, style={{ width: "100%" }}>
message: t("general.validation.required") {t("bodyshop.actions.newstatus")}
} </Button>
]} </Form.Item>
name={["md_responsibility_centers", "defaults", "LAB"]} </div>
> );
<Select> }}
{options.map((item, idx) => ( </Form.List>
<Select.Option key={idx}>{item}</Select.Option> </div>
))} <div>
</Select> <SelectorDiv>
</Form.Item> <Form.Item
<Form.Item label={t("bodyshop.fields.responsibilitycenters.atp")}
label={t("bodyshop.fields.responsibilitycenters.lad")} rules={[
rules={[ {
{ required: true,
required: true, message: t("general.validation.required"),
message: t("general.validation.required") },
} ]}
]} name={["md_responsibility_centers", "defaults", "ATP"]}>
name={["md_responsibility_centers", "defaults", "LAD"]} <Select>
> {options.map((item, idx) => (
<Select> <Select.Option key={idx}>{item}</Select.Option>
{options.map((item, idx) => ( ))}
<Select.Option key={idx}>{item}</Select.Option> </Select>
))} </Form.Item>
</Select> <Form.Item
</Form.Item> label={t("bodyshop.fields.responsibilitycenters.lab")}
<Form.Item rules={[
label={t("bodyshop.fields.responsibilitycenters.lae")} {
rules={[ required: true,
{ message: t("general.validation.required"),
required: true, },
message: t("general.validation.required") ]}
} name={["md_responsibility_centers", "defaults", "LAB"]}>
]} <Select>
name={["md_responsibility_centers", "defaults", "LAE"]} {options.map((item, idx) => (
> <Select.Option key={idx}>{item}</Select.Option>
<Select> ))}
{options.map((item, idx) => ( </Select>
<Select.Option key={idx}>{item}</Select.Option> </Form.Item>
))} <Form.Item
</Select> label={t("bodyshop.fields.responsibilitycenters.lad")}
</Form.Item> rules={[
<Form.Item {
label={t("bodyshop.fields.responsibilitycenters.laf")} required: true,
rules={[ message: t("general.validation.required"),
{ },
required: true, ]}
message: t("general.validation.required") name={["md_responsibility_centers", "defaults", "LAD"]}>
} <Select>
]} {options.map((item, idx) => (
name={["md_responsibility_centers", "defaults", "LAF"]} <Select.Option key={idx}>{item}</Select.Option>
> ))}
<Select> </Select>
{options.map((item, idx) => ( </Form.Item>
<Select.Option key={idx}>{item}</Select.Option> <Form.Item
))} label={t("bodyshop.fields.responsibilitycenters.lae")}
</Select> rules={[
</Form.Item> {
<Form.Item required: true,
label={t("bodyshop.fields.responsibilitycenters.lag")} message: t("general.validation.required"),
rules={[ },
{ ]}
required: true, name={["md_responsibility_centers", "defaults", "LAE"]}>
message: t("general.validation.required") <Select>
} {options.map((item, idx) => (
]} <Select.Option key={idx}>{item}</Select.Option>
name={["md_responsibility_centers", "defaults", "LAG"]} ))}
> </Select>
<Select> </Form.Item>
{options.map((item, idx) => ( <Form.Item
<Select.Option key={idx}>{item}</Select.Option> label={t("bodyshop.fields.responsibilitycenters.laf")}
))} rules={[
</Select> {
</Form.Item> required: true,
<Form.Item message: t("general.validation.required"),
label={t("bodyshop.fields.responsibilitycenters.lam")} },
rules={[ ]}
{ name={["md_responsibility_centers", "defaults", "LAF"]}>
required: true, <Select>
message: t("general.validation.required") {options.map((item, idx) => (
} <Select.Option key={idx}>{item}</Select.Option>
]} ))}
name={["md_responsibility_centers", "defaults", "LAM"]} </Select>
> </Form.Item>
<Select> <Form.Item
{options.map((item, idx) => ( label={t("bodyshop.fields.responsibilitycenters.lag")}
<Select.Option key={idx}>{item}</Select.Option> rules={[
))} {
</Select> required: true,
</Form.Item> message: t("general.validation.required"),
<Form.Item },
label={t("bodyshop.fields.responsibilitycenters.lar")} ]}
rules={[ name={["md_responsibility_centers", "defaults", "LAG"]}>
{ <Select>
required: true, {options.map((item, idx) => (
message: t("general.validation.required") <Select.Option key={idx}>{item}</Select.Option>
} ))}
]} </Select>
name={["md_responsibility_centers", "defaults", "LAR"]} </Form.Item>
> <Form.Item
<Select> label={t("bodyshop.fields.responsibilitycenters.lam")}
{options.map((item, idx) => ( rules={[
<Select.Option key={idx}>{item}</Select.Option> {
))} required: true,
</Select> message: t("general.validation.required"),
</Form.Item> },
<Form.Item ]}
label={t("bodyshop.fields.responsibilitycenters.las")} name={["md_responsibility_centers", "defaults", "LAM"]}>
rules={[ <Select>
{ {options.map((item, idx) => (
required: true, <Select.Option key={idx}>{item}</Select.Option>
message: t("general.validation.required") ))}
} </Select>
]} </Form.Item>
name={["md_responsibility_centers", "defaults", "LAS"]} <Form.Item
> label={t("bodyshop.fields.responsibilitycenters.lar")}
<Select> rules={[
{options.map((item, idx) => ( {
<Select.Option key={idx}>{item}</Select.Option> required: true,
))} message: t("general.validation.required"),
</Select> },
</Form.Item> ]}
<Form.Item name={["md_responsibility_centers", "defaults", "LAR"]}>
label={t("bodyshop.fields.responsibilitycenters.lau")} <Select>
rules={[ {options.map((item, idx) => (
{ <Select.Option key={idx}>{item}</Select.Option>
required: true, ))}
message: t("general.validation.required") </Select>
} </Form.Item>
]} <Form.Item
name={["md_responsibility_centers", "defaults", "LAU"]} label={t("bodyshop.fields.responsibilitycenters.las")}
> rules={[
<Select> {
{options.map((item, idx) => ( required: true,
<Select.Option key={idx}>{item}</Select.Option> message: t("general.validation.required"),
))} },
</Select> ]}
</Form.Item> name={["md_responsibility_centers", "defaults", "LAS"]}>
<Form.Item <Select>
label={t("bodyshop.fields.responsibilitycenters.paa")} {options.map((item, idx) => (
rules={[ <Select.Option key={idx}>{item}</Select.Option>
{ ))}
required: true, </Select>
message: t("general.validation.required") </Form.Item>
} <Form.Item
]} label={t("bodyshop.fields.responsibilitycenters.lau")}
name={["md_responsibility_centers", "defaults", "PAA"]} rules={[
> {
<Select> required: true,
{options.map((item, idx) => ( message: t("general.validation.required"),
<Select.Option key={idx}>{item}</Select.Option> },
))} ]}
</Select> name={["md_responsibility_centers", "defaults", "LAU"]}>
</Form.Item> <Select>
<Form.Item {options.map((item, idx) => (
label={t("bodyshop.fields.responsibilitycenters.pac")} <Select.Option key={idx}>{item}</Select.Option>
rules={[ ))}
{ </Select>
required: true, </Form.Item>
message: t("general.validation.required") <Form.Item
} label={t("bodyshop.fields.responsibilitycenters.paa")}
]} rules={[
name={["md_responsibility_centers", "defaults", "PAC"]} {
> required: true,
<Select> message: t("general.validation.required"),
{options.map((item, idx) => ( },
<Select.Option key={idx}>{item}</Select.Option> ]}
))} name={["md_responsibility_centers", "defaults", "PAA"]}>
</Select> <Select>
</Form.Item> {options.map((item, idx) => (
<Form.Item <Select.Option key={idx}>{item}</Select.Option>
label={t("bodyshop.fields.responsibilitycenters.pal")} ))}
rules={[ </Select>
{ </Form.Item>
required: true, <Form.Item
message: t("general.validation.required") label={t("bodyshop.fields.responsibilitycenters.pac")}
} rules={[
]} {
name={["md_responsibility_centers", "defaults", "PAL"]} required: true,
> message: t("general.validation.required"),
<Select> },
{options.map((item, idx) => ( ]}
<Select.Option key={idx}>{item}</Select.Option> name={["md_responsibility_centers", "defaults", "PAC"]}>
))} <Select>
</Select> {options.map((item, idx) => (
</Form.Item> <Select.Option key={idx}>{item}</Select.Option>
<Form.Item ))}
label={t("bodyshop.fields.responsibilitycenters.pam")} </Select>
rules={[ </Form.Item>
{ <Form.Item
required: true, label={t("bodyshop.fields.responsibilitycenters.pal")}
message: t("general.validation.required") rules={[
} {
]} required: true,
name={["md_responsibility_centers", "defaults", "PAM"]} message: t("general.validation.required"),
> },
<Select> ]}
{options.map((item, idx) => ( name={["md_responsibility_centers", "defaults", "PAL"]}>
<Select.Option key={idx}>{item}</Select.Option> <Select>
))} {options.map((item, idx) => (
</Select> <Select.Option key={idx}>{item}</Select.Option>
</Form.Item> ))}
<Form.Item </Select>
label={t("bodyshop.fields.responsibilitycenters.pan")} </Form.Item>
rules={[ <Form.Item
{ label={t("bodyshop.fields.responsibilitycenters.pam")}
required: true, rules={[
message: t("general.validation.required") {
} required: true,
]} message: t("general.validation.required"),
name={["md_responsibility_centers", "defaults", "PAN"]} },
> ]}
<Select> name={["md_responsibility_centers", "defaults", "PAM"]}>
{options.map((item, idx) => ( <Select>
<Select.Option key={idx}>{item}</Select.Option> {options.map((item, idx) => (
))} <Select.Option key={idx}>{item}</Select.Option>
</Select> ))}
</Form.Item> </Select>
<Form.Item </Form.Item>
label={t("bodyshop.fields.responsibilitycenters.pao")} <Form.Item
rules={[ label={t("bodyshop.fields.responsibilitycenters.pan")}
{ rules={[
required: true, {
message: t("general.validation.required") required: true,
} message: t("general.validation.required"),
]} },
name={["md_responsibility_centers", "defaults", "PAO"]} ]}
> name={["md_responsibility_centers", "defaults", "PAN"]}>
<Select> <Select>
{options.map((item, idx) => ( {options.map((item, idx) => (
<Select.Option key={idx}>{item}</Select.Option> <Select.Option key={idx}>{item}</Select.Option>
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label={t("bodyshop.fields.responsibilitycenters.pap")} label={t("bodyshop.fields.responsibilitycenters.pao")}
rules={[ rules={[
{ {
required: true, required: true,
message: t("general.validation.required") message: t("general.validation.required"),
} },
]} ]}
name={["md_responsibility_centers", "defaults", "PAP"]} name={["md_responsibility_centers", "defaults", "PAO"]}>
> <Select>
<Select> {options.map((item, idx) => (
{options.map((item, idx) => ( <Select.Option key={idx}>{item}</Select.Option>
<Select.Option key={idx}>{item}</Select.Option> ))}
))} </Select>
</Select> </Form.Item>
</Form.Item> <Form.Item
<Form.Item label={t("bodyshop.fields.responsibilitycenters.pap")}
label={t("bodyshop.fields.responsibilitycenters.par")} rules={[
rules={[ {
{ required: true,
required: true, message: t("general.validation.required"),
message: t("general.validation.required") },
} ]}
]} name={["md_responsibility_centers", "defaults", "PAP"]}>
name={["md_responsibility_centers", "defaults", "PAR"]} <Select>
> {options.map((item, idx) => (
<Select> <Select.Option key={idx}>{item}</Select.Option>
{options.map((item, idx) => ( ))}
<Select.Option key={idx}>{item}</Select.Option> </Select>
))} </Form.Item>
</Select> <Form.Item
</Form.Item> label={t("bodyshop.fields.responsibilitycenters.par")}
<Form.Item rules={[
label={t("bodyshop.fields.responsibilitycenters.tow")} {
rules={[ required: true,
{ message: t("general.validation.required"),
required: true, },
message: t("general.validation.required") ]}
} name={["md_responsibility_centers", "defaults", "PAR"]}>
]} <Select>
name={["md_responsibility_centers", "defaults", "TOW"]} {options.map((item, idx) => (
> <Select.Option key={idx}>{item}</Select.Option>
<Select> ))}
{options.map((item, idx) => ( </Select>
<Select.Option key={idx}>{item}</Select.Option> </Form.Item>
))} <Form.Item
</Select> label={t("bodyshop.fields.responsibilitycenters.tow")}
</Form.Item> rules={[
</SelectorDiv> {
</Col> required: true,
</Row> message: t("general.validation.required"),
},
]}
name={["md_responsibility_centers", "defaults", "TOW"]}>
<Select>
{options.map((item, idx) => (
<Select.Option key={idx}>{item}</Select.Option>
))}
</Select>
</Form.Item>
</SelectorDiv>
</div>
</div> </div>
); );
} }

View File

@@ -107,7 +107,7 @@ export default function TimeTicketModalComponent({
}} }}
> >
{responsibilityCenters.costs.map((item) => ( {responsibilityCenters.costs.map((item) => (
<Select.Option key={item}>{item}</Select.Option> <Select.Option key={item.name}>{item.name}</Select.Option>
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>

View File

@@ -151,7 +151,7 @@ export default function VendorsFormComponent({
> >
<Select style={{ width: "150px" }}> <Select style={{ width: "150px" }}>
{responsibilityCenters.costs.map(item => ( {responsibilityCenters.costs.map(item => (
<Select.Option key={item}>{item}</Select.Option> <Select.Option key={item.name}>{item.name}</Select.Option>
))} ))}
</Select> </Select>
</Form.Item> </Form.Item>

View File

@@ -750,3 +750,141 @@ export const QUERY_ALL_JOBS_PAGINATED = gql`
} }
} }
`; `;
export const QUERY_JOB_CLOSE_DETAILS = gql`
query QUERY_JOB_CLOSE_DETAILS($id: uuid!) {
jobs_by_pk(id: $id) {
po_number
special_coverage_policy
scheduled_delivery
converted
est_number
ro_number
clm_total
inproduction
plate_no
v_vin
v_model_yr
v_model_desc
v_make_desc
v_color
ins_co_id
policy_no
loss_date
clm_no
area_of_damage
ins_co_nm
ins_addr1
ins_city
ins_ct_ln
ins_ct_fn
ins_ea
ins_ph1
est_co_nm
est_ct_fn
est_ct_ln
pay_date
est_ph1
est_ea
regie_number
scheduled_completion
id
ded_amt
ded_status
depreciation_taxes
federal_tax_payable
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
ownr_fn
ownr_ln
ownr_ea
ownr_addr1
ownr_addr2
ownr_city
ownr_st
ownr_zip
ownr_ctry
ownr_ph1
owner {
id
ownr_fn
ownr_ln
ownr_ea
ownr_addr1
ownr_addr2
ownr_city
ownr_st
ownr_zip
ownr_ctry
ownr_ph1
}
labor_rate_desc
rate_atp
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
actual_completion
scheduled_delivery
actual_delivery
date_invoiced
date_closed
date_exported
status
owner_owing
joblines {
id
unq_seq
line_ind
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
}
cieca_ttl
}
}
`;

View File

@@ -0,0 +1,31 @@
import React, { useCallback, useState } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { CalculateJob } from "../../components/job-totals-table/job-totals.utility";
import JobsCloseLaborMaterialAllocation from "../../components/jobs-close-labmat-allocation/jobs-close-labmat-allocation.component";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
});
export function JobsCloseComponent({ job, bodyshop }) {
const CalcJobMemoized = useCallback(
() => CalculateJob(job, bodyshop.shoprates),
[job, bodyshop.shoprates]
);
const jobTotals = CalcJobMemoized();
const [labmatAllocations, setLabmatAllocations] = useState(jobTotals.rates);
return (
<div>
<JobsCloseLaborMaterialAllocation
labmatAllocations={labmatAllocations}
setLabmatAllocations={setLabmatAllocations}
/>
</div>
);
}
export default connect(mapStateToProps, null)(JobsCloseComponent);

View File

@@ -0,0 +1,53 @@
import { useQuery } from "@apollo/react-hooks";
import React, { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { useParams } from "react-router-dom";
import AlertComponent from "../../components/alert/alert.component";
import { QUERY_JOB_CLOSE_DETAILS } from "../../graphql/jobs.queries";
import { setBreadcrumbs } from "../../redux/application/application.actions";
import JobsCloseComponent from "./jobs-close.component";
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
const mapDispatchToProps = (dispatch) => ({
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
});
export function JobsCloseContainer({ setBreadcrumbs }) {
const { jobId } = useParams();
const { loading, error, data } = useQuery(QUERY_JOB_CLOSE_DETAILS, {
variables: { id: jobId },
});
const { t } = useTranslation();
useEffect(() => {
document.title = t("titles.jobs-close", {
number: data ? data.jobs_by_pk.ro_number : null,
});
setBreadcrumbs([
{
link: `/manage/jobs/${jobId}/`,
label: t("titles.bc.jobs"),
},
{
link: `/manage/jobs/${jobId}/`,
label: t("titles.bc.jobs-detail", {
number: data ? data.jobs_by_pk.ro_number : null,
}),
},
{
link: `/manage/jobs/${jobId}/close`,
label: t("titles.bc.jobs-close"),
},
]);
}, [setBreadcrumbs, t, jobId, data]);
if (loading) return <LoadingSpinner />;
if (error) return <AlertComponent message={error.message} type='error' />;
return (
<div>
<JobsCloseComponent job={data ? data.jobs_by_pk : {}} />
</div>
);
}
export default connect(null, mapDispatchToProps)(JobsCloseContainer);

View File

@@ -87,6 +87,7 @@ const JobIntake = lazy(() =>
import("../jobs-intake/jobs-intake.page.container") import("../jobs-intake/jobs-intake.page.container")
); );
const AllJobs = lazy(() => import("../jobs-all/jobs-all.container")); const AllJobs = lazy(() => import("../jobs-all/jobs-all.container"));
const JobsClose = lazy(() => import("../jobs-close/jobs-close.container"));
const { Header, Content, Footer } = Layout; const { Header, Content, Footer } = Layout;
@@ -125,7 +126,12 @@ export default function Manage({ match }) {
exact exact
path={`${match.path}/jobs/:jobId/intake`} path={`${match.path}/jobs/:jobId/intake`}
component={JobIntake} component={JobIntake}
/>{" "} />
<Route
exact
path={`${match.path}/jobs/:jobId/close`}
component={JobsClose}
/>
<Route <Route
exact exact
path={`${match.path}/jobs/all`} path={`${match.path}/jobs/all`}

View File

@@ -86,6 +86,8 @@
"invoice_state_tax_rate": "Invoices - State Tax Rate %", "invoice_state_tax_rate": "Invoices - State Tax Rate %",
"logo_img_path": "Shop Logo", "logo_img_path": "Shop Logo",
"responsibilitycenter": "Responsibility Center", "responsibilitycenter": "Responsibility Center",
"responsibilitycenter_accountname": "Account Name",
"responsibilitycenter_accountnumber": "Account Number",
"responsibilitycenters": { "responsibilitycenters": {
"atp": "ATP", "atp": "ATP",
"lab": "Labor", "lab": "Labor",
@@ -884,6 +886,7 @@
"jobs": "Jobs", "jobs": "Jobs",
"jobs-active": "Active Jobs", "jobs-active": "Active Jobs",
"jobs-all": "All Jobs", "jobs-all": "All Jobs",
"jobs-close": "Close Job",
"jobs-detail": "Job {{number}}", "jobs-detail": "Job {{number}}",
"jobs-intake": "Intake", "jobs-intake": "Intake",
"jobs-new": "Create a New Job", "jobs-new": "Create a New Job",
@@ -906,6 +909,7 @@
"invoices-list": "Invoices | $t(titles.app)", "invoices-list": "Invoices | $t(titles.app)",
"jobs": "Active Jobs | $t(titles.app)", "jobs": "Active Jobs | $t(titles.app)",
"jobs-all": "All Jobs | $t(titles.app)", "jobs-all": "All Jobs | $t(titles.app)",
"jobs-close": "Close Job {{number}} | $t(titles.app)",
"jobs-create": "Create a New Job | $t(titles.app)", "jobs-create": "Create a New Job | $t(titles.app)",
"jobs-intake": "Intake | $t(titles.app)", "jobs-intake": "Intake | $t(titles.app)",
"jobsavailable": "Available Jobs | $t(titles.app)", "jobsavailable": "Available Jobs | $t(titles.app)",

View File

@@ -86,6 +86,8 @@
"invoice_state_tax_rate": "", "invoice_state_tax_rate": "",
"logo_img_path": "", "logo_img_path": "",
"responsibilitycenter": "", "responsibilitycenter": "",
"responsibilitycenter_accountname": "",
"responsibilitycenter_accountnumber": "",
"responsibilitycenters": { "responsibilitycenters": {
"atp": "", "atp": "",
"lab": "", "lab": "",
@@ -884,6 +886,7 @@
"jobs": "", "jobs": "",
"jobs-active": "", "jobs-active": "",
"jobs-all": "", "jobs-all": "",
"jobs-close": "",
"jobs-detail": "", "jobs-detail": "",
"jobs-intake": "", "jobs-intake": "",
"jobs-new": "", "jobs-new": "",
@@ -906,6 +909,7 @@
"invoices-list": "", "invoices-list": "",
"jobs": "Todos los trabajos | $t(titles.app)", "jobs": "Todos los trabajos | $t(titles.app)",
"jobs-all": "", "jobs-all": "",
"jobs-close": "",
"jobs-create": "", "jobs-create": "",
"jobs-intake": "", "jobs-intake": "",
"jobsavailable": "Empleos disponibles | $t(titles.app)", "jobsavailable": "Empleos disponibles | $t(titles.app)",

View File

@@ -86,6 +86,8 @@
"invoice_state_tax_rate": "", "invoice_state_tax_rate": "",
"logo_img_path": "", "logo_img_path": "",
"responsibilitycenter": "", "responsibilitycenter": "",
"responsibilitycenter_accountname": "",
"responsibilitycenter_accountnumber": "",
"responsibilitycenters": { "responsibilitycenters": {
"atp": "", "atp": "",
"lab": "", "lab": "",
@@ -884,6 +886,7 @@
"jobs": "", "jobs": "",
"jobs-active": "", "jobs-active": "",
"jobs-all": "", "jobs-all": "",
"jobs-close": "",
"jobs-detail": "", "jobs-detail": "",
"jobs-intake": "", "jobs-intake": "",
"jobs-new": "", "jobs-new": "",
@@ -906,6 +909,7 @@
"invoices-list": "", "invoices-list": "",
"jobs": "Tous les emplois | $t(titles.app)", "jobs": "Tous les emplois | $t(titles.app)",
"jobs-all": "", "jobs-all": "",
"jobs-close": "",
"jobs-create": "", "jobs-create": "",
"jobs-intake": "", "jobs-intake": "",
"jobsavailable": "Emplois disponibles | $t(titles.app)", "jobsavailable": "Emplois disponibles | $t(titles.app)",