Added bulk assignment. Added partial parts order line remarks capability.

This commit is contained in:
Patrick Fic
2020-02-20 10:38:07 -08:00
parent eec5a806e9
commit c90cccb6be
12 changed files with 245 additions and 47 deletions

View File

@@ -5979,6 +5979,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>lineremarks</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>
</children>
</folder_node>
<folder_node>
@@ -6005,6 +6026,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>inthisorder</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>print</name>
<definition_loaded>false</definition_loaded>

View File

@@ -24,7 +24,6 @@ export default function AllocationsAssignmentContainer({
notification["success"]({
message: t("employees.successes.save")
});
//TODO Better way to reset the field decorators?
visibilityState[1](false);
if (refetch) refetch();
});

View File

@@ -0,0 +1,66 @@
import { Button, Popover, Select } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
});
export default connect(
mapStateToProps,
null
)(function AllocationsBulkAssignmentComponent({
bodyshop,
handleAssignment,
assignment,
setAssignment,
visibilityState
}) {
const { t } = useTranslation();
const onChange = e => {
console.log("e", e);
setAssignment({ ...assignment, employeeid: e });
};
const [visibility, setVisibility] = visibilityState;
const popContent = (
<div>
<Select
showSearch
style={{ width: 200 }}
placeholder='Select a person'
optionFilterProp='children'
onChange={onChange}
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}>
{bodyshop.employees.map(emp => (
<Select.Option value={emp.id} key={emp.id}>
{`${emp.first_name} ${emp.last_name}`}
</Select.Option>
))}
</Select>
<Button
type='primary'
disabled={!assignment.employeeid}
onClick={handleAssignment}>
Assign
</Button>
<Button onClick={() => setVisibility(false)}>Close</Button>
</div>
);
return (
<Popover content={popContent} visible={visibility}>
<Button onClick={() => setVisibility(true)}>
{t("allocations.actions.assign")}
</Button>
</Popover>
);
});

View File

@@ -0,0 +1,46 @@
import React, { useState } from "react";
import AllocationsBulkAssignment from "./allocations-bulk-assignment.component";
import { useMutation } from "react-apollo";
import { INSERT_ALLOCATION } from "../../graphql/allocations.queries";
import { useTranslation } from "react-i18next";
import { notification } from "antd";
export default function AllocationsBulkAssignmentContainer({
jobLines,
refetch
}) {
const visibilityState = useState(false);
const { t } = useTranslation();
const [assignment, setAssignment] = useState({
employeeid: null
});
const [insertAllocation] = useMutation(INSERT_ALLOCATION);
const handleAssignment = () => {
const allocs = jobLines.reduce((acc, value) => {
acc.push({
joblineid: value.id,
hours: parseFloat(value.mod_lb_hrs) || 0,
employeeid: assignment.employeeid
});
return acc;
}, []);
insertAllocation({ variables: { alloc: allocs } }).then(r => {
notification["success"]({
message: t("employees.successes.save")
});
visibilityState[1](false);
if (refetch) refetch();
});
};
return (
<AllocationsBulkAssignment
handleAssignment={handleAssignment}
assignment={assignment}
setAssignment={setAssignment}
visibilityState={visibilityState}
/>
);
}

View File

@@ -20,7 +20,7 @@
.messages ul li {
display: inline-block;
clear: both;
float: left;
//float: left;
margin: 5px 15px 5px 15px;
width: calc(100% - 25px);
font-size: 0.9em;

View File

@@ -6,7 +6,7 @@ import { alphaSort } from "../../utils/sorters";
//import EditableCell from "./job-lines-cell.component";
import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
export default function JobLinesComponent({
loading,
refetch,
@@ -166,11 +166,13 @@ export default function JobLinesComponent({
return (
<div>
<PartsOrderModalContainer
partsOrderModalVisible={partsOrderModalVisible}
linesToOrder={selectedLines}
jobId={jobId}
/>
{partsOrderModalVisible[0] ? (
<PartsOrderModalContainer
partsOrderModalVisible={partsOrderModalVisible}
linesToOrder={selectedLines}
jobId={jobId}
/>
) : null}
<Table
title={() => {
@@ -188,13 +190,17 @@ export default function JobLinesComponent({
onClick={() => setPartsModalVisible(true)}>
{t("parts.actions.order")}
</Button>
<AllocationsBulkAssignmentContainer
jobLines={selectedLines}
refetch={refetch}
/>
</div>
);
}}
{...formItemLayout}
loading={loading}
size='small'
pagination={{ position: "bottom", defaultPageSize: 50 }}
pagination={{ position: "top", defaultPageSize: 25 }}
rowSelection={{
// selectedRowKeys: selectedLines,
onSelect: (record, selected, selectedRows, nativeEvent) =>

View File

@@ -54,12 +54,13 @@ export default withRouter(function JobsAvailableSupplementContainer({
//create upsert job
let supp = estData.data.available_jobs_by_pk.est_data;
delete supp.joblines;
//TODO How to update the estimate lines.
delete supp.owner;
delete supp.vehicle;
if (!importOptions.overrideHeaders) {
delete supp["ins_ea"];
//Strip out the header options
//TODO Remove all required fields.
}
updateJob({
@@ -101,12 +102,11 @@ export default withRouter(function JobsAvailableSupplementContainer({
setSelectedJob(null);
};
if (error) return <AlertComponent type="error" message={error.message} />;
if (error) return <AlertComponent type='error' message={error.message} />;
return (
<LoadingSpinner
loading={insertLoading}
message={t("jobs.labels.creating_new_job")}
>
message={t("jobs.labels.creating_new_job")}>
<JobsAvailableSupplementComponent
loading={loading}
data={data}

View File

@@ -1,13 +1,15 @@
import { AutoComplete, DatePicker, Icon, Input, List, Radio } from "antd";
import React, { useState } from "react";
import { AutoComplete, Icon, DatePicker, Radio } from "antd";
import { useTranslation } from "react-i18next";
export default function PartsOrderModalComponent({
vendorList,
state,
sendTypeState
sendTypeState,
orderLinesState
}) {
const [partsOrder, setPartsOrder] = state;
const [sendType, setSendType] = sendTypeState;
const orderLines = orderLinesState[0];
const [vendorComplete, setVendorComplete] = useState(vendorList);
const { t } = useTranslation();
@@ -22,8 +24,6 @@ export default function PartsOrderModalComponent({
};
const handleSelect = (value, option) => {
console.log("value", value);
console.log("option", option);
setPartsOrder({ ...partsOrder, vendorid: option.key });
};
@@ -52,6 +52,33 @@ export default function PartsOrderModalComponent({
}}
/>
{t("parts_orders.labels.inthisorder")}
<List
itemLayout='horizontal'
dataSource={orderLines}
renderItem={item => (
<List.Item
actions={[
<Input placeholder={t("parts_orders.fields.lineremarks")} />
//TODO Editable table/adding line remarks to the order.
]}>
{
// <List.Item.Meta
// avatar={
// <Avatar src='https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png' />
// }
// title={<a href='https://ant.design'>{item.name.last}</a>}
// description='Ant Design, a design language for background applications, is refined by Ant UED Team'
// />
}
<div>{`${item.line_desc}${
item.oem_partno ? " | " + item.oem_partno : ""
}`}</div>
</List.Item>
)}
/>
<Radio.Group
defaultValue={sendType}
onChange={e => setSendType(e.target.value)}>

View File

@@ -1,18 +1,18 @@
import { Modal, notification } from "antd";
import React, { useState } from "react";
import { useQuery, useMutation } from "react-apollo";
import { useMutation, useQuery } from "react-apollo";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries";
import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries";
import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries";
import {
selectCurrentUser,
selectBodyshop
selectBodyshop,
selectCurrentUser
} from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
import PartsOrderModalComponent from "./parts-order-modal.component";
import { useTranslation } from "react-i18next";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
@@ -28,23 +28,40 @@ export default connect(
currentUser,
bodyshop
}) {
const [modalVisible, setModalVisible] = partsOrderModalVisible;
const { loading, error, data } = useQuery(QUERY_ALL_VENDORS_FOR_ORDER, {
fetchPolicy: "network-only",
skip: !modalVisible
});
const { t } = useTranslation();
const [insertPartOrder] = useMutation(INSERT_NEW_PARTS_ORDERS);
const sendTypeState = useState("e");
const [modalVisible, setModalVisible] = partsOrderModalVisible;
//set order lines to be a version of the incoming lines.
const orderLinesState = useState(
linesToOrder.reduce((acc, value) => {
acc.push({
line_desc: value.line_desc,
oem_partno: value.oem_partno,
db_price: value.db_price,
act_price: value.act_price,
line_remarks: "Alalala",
joblineid: value.joblineid,
status: bodyshop.md_order_statuses.default_ordered || "Ordered*"
});
return acc;
}, [])
);
const orderLines = orderLinesState[0];
const sendTypeState = useState("e");
const partsOrderState = useState({
vendorid: null,
jobid: jobId,
user_email: currentUser.email
});
console.log("sendTypeState[0]", sendTypeState[0]);
const partsOrder = partsOrderState[0];
const { loading, error, data } = useQuery(QUERY_ALL_VENDORS_FOR_ORDER, {
fetchPolicy: "network-only",
skip: !modalVisible
});
const [insertPartOrder] = useMutation(INSERT_NEW_PARTS_ORDERS);
const handleOk = () => {
insertPartOrder({
variables: {
@@ -53,19 +70,7 @@ export default connect(
...partsOrder,
status: bodyshop.md_order_statuses.default_ordered || "Ordered*",
parts_order_lines: {
data: linesToOrder.reduce((acc, value) => {
acc.push({
line_desc: value.line_desc,
oem_partno: value.oem_partno,
db_price: value.db_price,
act_price: value.act_price,
line_remarks: "Alalala",
joblineid: value.joblineid,
status:
bodyshop.md_order_statuses.default_ordered || "Ordered*"
});
return acc;
}, [])
data: orderLines
}
}
]
@@ -96,6 +101,7 @@ export default connect(
vendorList={(data && data.vendors) || []}
state={partsOrderState}
sendTypeState={sendTypeState}
orderLinesState={orderLinesState}
/>
</LoadingSpinner>
</Modal>

View File

@@ -385,10 +385,12 @@
"creating": "Error encountered when creating parts order. "
},
"fields": {
"deliver_by": "Deliver By"
"deliver_by": "Deliver By",
"lineremarks": "Line Remarks"
},
"labels": {
"email": "Send by Email",
"inthisorder": "Parts in this Order",
"print": "Show Printed Form"
},
"successes": {

View File

@@ -385,10 +385,12 @@
"creating": "Se encontró un error al crear el pedido de piezas."
},
"fields": {
"deliver_by": "Entregado por"
"deliver_by": "Entregado por",
"lineremarks": "Comentarios de línea"
},
"labels": {
"email": "Enviar por correo electrónico",
"inthisorder": "Partes en este pedido",
"print": "Mostrar formulario impreso"
},
"successes": {

View File

@@ -385,10 +385,12 @@
"creating": "Erreur rencontrée lors de la création de la commande de pièces."
},
"fields": {
"deliver_by": "Livrer par"
"deliver_by": "Livrer par",
"lineremarks": "Remarques sur la ligne"
},
"labels": {
"email": "Envoyé par email",
"inthisorder": "Pièces dans cette commande",
"print": "Afficher le formulaire imprimé"
},
"successes": {