Added allocation adding + basic pull
This commit is contained in:
@@ -18,6 +18,63 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>translation</name>
|
<name>translation</name>
|
||||||
<children>
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>allocations</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>actions</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>assign</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>
|
||||||
|
<name>fields</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>employee</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>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>appointments</name>
|
<name>appointments</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -1456,6 +1513,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>mod_lb_hrs</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>oem_partno</name>
|
<name>oem_partno</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
import { Select, Button, Popover, InputNumber } 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 AllocationsAssignmentComponent({
|
||||||
|
bodyshop,
|
||||||
|
handleAssignment,
|
||||||
|
assignment,
|
||||||
|
setAssignment,
|
||||||
|
visibilityState,
|
||||||
|
maxHours
|
||||||
|
}) {
|
||||||
|
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>
|
||||||
|
<InputNumber
|
||||||
|
defaultValue={assignment.hours}
|
||||||
|
placeholder={t("joblines.fields.mod_lb_hrs")}
|
||||||
|
max={parseFloat(maxHours)}
|
||||||
|
min={0}
|
||||||
|
onChange={e => setAssignment({ ...assignment, hours: e })}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<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>
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
import React, { useState } from "react";
|
||||||
|
import AllocationsAssignmentComponent from "./allocations-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 AllocationsAssignmentContainer({ jobLineId, hours }) {
|
||||||
|
const visibilityState = useState(false);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [assignment, setAssignment] = useState({
|
||||||
|
joblineid: jobLineId,
|
||||||
|
hours: parseFloat(hours),
|
||||||
|
employeeid: null
|
||||||
|
});
|
||||||
|
const [insertAllocation] = useMutation(INSERT_ALLOCATION);
|
||||||
|
|
||||||
|
const handleAssignment = () => {
|
||||||
|
insertAllocation({ variables: { alloc: { ...assignment } } }).then(r => {
|
||||||
|
notification["success"]({
|
||||||
|
message: t("employees.successes.save")
|
||||||
|
});
|
||||||
|
//TODO: Better way to reset the field decorators?
|
||||||
|
visibilityState[1](false);
|
||||||
|
//refetch().then(r => form.resetFields());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AllocationsAssignmentComponent
|
||||||
|
handleAssignment={handleAssignment}
|
||||||
|
maxHours={hours}
|
||||||
|
assignment={assignment}
|
||||||
|
setAssignment={setAssignment}
|
||||||
|
visibilityState={visibilityState}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
//import EditableCell from "./job-lines-cell.component";
|
//import EditableCell from "./job-lines-cell.component";
|
||||||
|
import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
|
||||||
|
|
||||||
export default function JobLinesComponent({
|
export default function JobLinesComponent({
|
||||||
jobLines,
|
jobLines,
|
||||||
@@ -97,6 +98,38 @@ export default function JobLinesComponent({
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<CurrencyFormatter>{record.act_price}</CurrencyFormatter>
|
<CurrencyFormatter>{record.act_price}</CurrencyFormatter>
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("joblines.fields.mod_lb_hrs"),
|
||||||
|
dataIndex: "mod_lb_hrs",
|
||||||
|
key: "mod_lb_hrs",
|
||||||
|
sorter: (a, b) => a.mod_lb_hrs - b.mod_lb_hrs,
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "mod_lb_hrs" && state.sortedInfo.order
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("allocations.fields.employee"),
|
||||||
|
dataIndex: "employee",
|
||||||
|
key: "employee",
|
||||||
|
sorter: (a, b) => a.act_price - b.act_price, //TODO Fix employee sorting.
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "employee" && state.sortedInfo.order,
|
||||||
|
render: (text, record) => (
|
||||||
|
<span>
|
||||||
|
{record.allocations && record.allocations.length > 0
|
||||||
|
? record.allocations.map(item => (
|
||||||
|
<div
|
||||||
|
key={item.id}
|
||||||
|
>{`${item.employee.first_name} ${item.employee.last_name} (${item.hours})`}</div>
|
||||||
|
))
|
||||||
|
: null}
|
||||||
|
<AllocationsAssignmentContainer
|
||||||
|
key={record.id}
|
||||||
|
jobLineId={record.id}
|
||||||
|
hours={record.mod_lb_hrs}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
11
client/src/graphql/allocations.queries.js
Normal file
11
client/src/graphql/allocations.queries.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { gql } from "apollo-boost";
|
||||||
|
|
||||||
|
export const INSERT_ALLOCATION = gql`
|
||||||
|
mutation INSERT_ALLOCATION($alloc: [allocations_insert_input!]!) {
|
||||||
|
insert_allocations(objects: $alloc) {
|
||||||
|
returning {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -20,6 +20,13 @@ export const QUERY_BODYSHOP = gql`
|
|||||||
updated_at
|
updated_at
|
||||||
zip_post
|
zip_post
|
||||||
region_config
|
region_config
|
||||||
|
employees {
|
||||||
|
id
|
||||||
|
first_name
|
||||||
|
last_name
|
||||||
|
employee_number
|
||||||
|
cost_center
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -18,6 +18,15 @@ export const GET_JOB_LINES_BY_PK = gql`
|
|||||||
lbr_op
|
lbr_op
|
||||||
lbr_amt
|
lbr_amt
|
||||||
op_code_desc
|
op_code_desc
|
||||||
|
allocations {
|
||||||
|
id
|
||||||
|
hours
|
||||||
|
employee {
|
||||||
|
id
|
||||||
|
first_name
|
||||||
|
last_name
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
{
|
{
|
||||||
"translation": {
|
"translation": {
|
||||||
|
"allocations": {
|
||||||
|
"actions": {
|
||||||
|
"assign": "Assign"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"employee": "Allocated To"
|
||||||
|
}
|
||||||
|
},
|
||||||
"appointments": {
|
"appointments": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
@@ -116,6 +124,7 @@
|
|||||||
"act_price": "Actual Price",
|
"act_price": "Actual Price",
|
||||||
"db_price": "Database Price",
|
"db_price": "Database Price",
|
||||||
"line_desc": "Line Description",
|
"line_desc": "Line Description",
|
||||||
|
"mod_lb_hrs": "Labor Hours",
|
||||||
"oem_partno": "OEM Part #",
|
"oem_partno": "OEM Part #",
|
||||||
"part_type": "Part Type",
|
"part_type": "Part Type",
|
||||||
"unq_seq": "Seq #"
|
"unq_seq": "Seq #"
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
{
|
{
|
||||||
"translation": {
|
"translation": {
|
||||||
|
"allocations": {
|
||||||
|
"actions": {
|
||||||
|
"assign": "Asignar"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"employee": "Asignado a"
|
||||||
|
}
|
||||||
|
},
|
||||||
"appointments": {
|
"appointments": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"cancel": "Cancelar",
|
"cancel": "Cancelar",
|
||||||
@@ -116,6 +124,7 @@
|
|||||||
"act_price": "Precio actual",
|
"act_price": "Precio actual",
|
||||||
"db_price": "Precio de base de datos",
|
"db_price": "Precio de base de datos",
|
||||||
"line_desc": "Descripción de línea",
|
"line_desc": "Descripción de línea",
|
||||||
|
"mod_lb_hrs": "Horas laborales",
|
||||||
"oem_partno": "OEM parte #",
|
"oem_partno": "OEM parte #",
|
||||||
"part_type": "Tipo de parte",
|
"part_type": "Tipo de parte",
|
||||||
"unq_seq": "Seq #"
|
"unq_seq": "Seq #"
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
{
|
{
|
||||||
"translation": {
|
"translation": {
|
||||||
|
"allocations": {
|
||||||
|
"actions": {
|
||||||
|
"assign": "Attribuer"
|
||||||
|
},
|
||||||
|
"fields": {
|
||||||
|
"employee": "Alloué à"
|
||||||
|
}
|
||||||
|
},
|
||||||
"appointments": {
|
"appointments": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"cancel": "annuler",
|
"cancel": "annuler",
|
||||||
@@ -116,6 +124,7 @@
|
|||||||
"act_price": "Prix actuel",
|
"act_price": "Prix actuel",
|
||||||
"db_price": "Prix de la base de données",
|
"db_price": "Prix de la base de données",
|
||||||
"line_desc": "Description de la ligne",
|
"line_desc": "Description de la ligne",
|
||||||
|
"mod_lb_hrs": "Heures de travail",
|
||||||
"oem_partno": "Pièce OEM #",
|
"oem_partno": "Pièce OEM #",
|
||||||
"part_type": "Type de pièce",
|
"part_type": "Type de pièce",
|
||||||
"unq_seq": "Seq #"
|
"unq_seq": "Seq #"
|
||||||
|
|||||||
Reference in New Issue
Block a user