Merged in release/2022-10-21 (pull request #599)

Release/2022 10 21
This commit is contained in:
Patrick Fic
2022-10-18 17:46:18 +00:00
10 changed files with 176 additions and 48 deletions

View File

@@ -37395,6 +37395,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>parts_invoice_label_single</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>parts_label_multiple</name> <name>parts_label_multiple</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -43081,6 +43102,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>shiftalreadyclockedon</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> </children>
</folder_node> </folder_node>
<folder_node> <folder_node>

View File

@@ -229,23 +229,26 @@ function BillEnterModalContainer({
}); });
} }
} }
//If it's not a credit memo, update the statuses.
await Promise.all( if (!values.is_credit_memo) {
remainingValues.billlines await Promise.all(
.filter((il) => il.joblineid !== "noline") remainingValues.billlines
.map((li) => { .filter((il) => il.joblineid !== "noline")
return updateJobLines({ .map((li) => {
variables: { return updateJobLines({
lineId: li.joblineid, variables: {
line: { lineId: li.joblineid,
location: li.location || location, line: {
status: location: li.location || location,
bodyshop.md_order_statuses.default_received || "Received*", status:
bodyshop.md_order_statuses.default_received || "Received*",
},
}, },
}, });
}); })
}) );
); }
///////////////////////// /////////////////////////
if (upload && upload.length > 0) { if (upload && upload.length > 0) {

View File

@@ -1,11 +1,12 @@
import { useQuery } from "@apollo/client"; import { useQuery } from "@apollo/client";
import { Row, Col, Timeline, Typography, Space, Divider, Skeleton } from "antd"; import { Col, Divider, Row, Skeleton, Space, Timeline, Typography } from "antd";
import React from "react"; import React from "react";
import { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import AlertComponent from "../alert/alert.component";
import { DateFormatter } from "../../utils/DateFormatter";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateFormatter } from "../../utils/DateFormatter";
import AlertComponent from "../alert/alert.component";
export default function JobLinesExpander({ jobline, jobid }) { export default function JobLinesExpander({ jobline, jobid }) {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -48,7 +49,46 @@ export default function JobLinesExpander({ jobline, jobid }) {
)} )}
</Timeline> </Timeline>
</Col> </Col>
<Col md={24} lg={12}></Col> <Col md={24} lg={12}>
<Typography.Title level={4}>{t("bills.labels.bills")}</Typography.Title>
<Timeline>
{data.billlines.length > 0 ? (
data.billlines.map((line) => (
<Timeline.Item key={line.id}>
<Row wrap>
<Col span={4}>
<Link
to={`/manage/jobs/${jobid}?tab=partssublet&billid=${line.bill.id}`}
>
{line.bill.invoice_number}
</Link>
</Col>
<Col span={4}>
<span>
{`${t("billlines.fields.actual_price")}: `}
<CurrencyFormatter>{line.actual_price}</CurrencyFormatter>
</span>
</Col>
<Col span={4}>
<span>
{`${t("billlines.fields.actual_cost")}: `}
<CurrencyFormatter>{line.actual_cost}</CurrencyFormatter>
</span>
</Col>
<Col span={4}>
<DateFormatter>{line.bill.date}</DateFormatter>
</Col>
<Col span={4}> {line.bill.vendor.name}</Col>
</Row>
</Timeline.Item>
))
) : (
<Timeline.Item>
{t("parts_orders.labels.notyetordered")}
</Timeline.Item>
)}
</Timeline>
</Col>
</Row> </Row>
); );
} }

View File

@@ -27,6 +27,7 @@ export function TimeTicektShiftContainer({
technician, technician,
currentUser, currentUser,
isTechConsole, isTechConsole,
checkIfAlreadyClocked,
}) { }) {
const [form] = Form.useForm(); const [form] = Form.useForm();
const [insertTimeTicket] = useMutation(INSERT_NEW_TIME_TICKET); const [insertTimeTicket] = useMutation(INSERT_NEW_TIME_TICKET);
@@ -43,36 +44,47 @@ export function TimeTicektShiftContainer({
const handleFinish = async (values) => { const handleFinish = async (values) => {
setLoading(true); setLoading(true);
const theTime = moment((await axios.post("/utils/time")).data);
const result = await insertTimeTicket({ const alreadyClocked = await checkIfAlreadyClocked();
variables: {
timeTicketInput: [
{
bodyshopid: bodyshop.id,
employeeid: isTechConsole ? technician.id : employeeId,
cost_center: "timetickets.labels.shift",
clockon: theTime,
date: theTime,
memo: values.memo,
},
],
},
awaitRefetchQueries: true,
refetchQueries: ["QUERY_ACTIVE_SHIFT_TIME_TICKETS"],
});
if (!!result.errors) { if (alreadyClocked) {
//Show the error.
notification["error"]({ notification["error"]({
message: t("timetickets.errors.clockingin", { message: t("timetickets.errors.shiftalreadyclockedon"),
message: JSON.stringify(result.errors),
}),
}); });
} else { } else {
notification["success"]({ const theTime = moment((await axios.post("/utils/time")).data);
message: t("timetickets.successes.clockedin"),
const result = await insertTimeTicket({
variables: {
timeTicketInput: [
{
bodyshopid: bodyshop.id,
employeeid: isTechConsole ? technician.id : employeeId,
cost_center: "timetickets.labels.shift",
clockon: theTime,
date: theTime,
memo: values.memo,
},
],
},
awaitRefetchQueries: true,
refetchQueries: ["QUERY_ACTIVE_SHIFT_TIME_TICKETS"],
}); });
if (!!result.errors) {
notification["error"]({
message: t("timetickets.errors.clockingin", {
message: JSON.stringify(result.errors),
}),
});
} else {
notification["success"]({
message: t("timetickets.successes.clockedin"),
});
}
} }
setLoading(false); setLoading(false);
}; };

View File

@@ -64,6 +64,12 @@ export function TimeTicketShiftContainer({
</div> </div>
); );
const checkIfAlreadyClocked = async () => {
const { data } = await refetch();
return data.timetickets.length > 0;
};
return ( return (
<div> <div>
{data.timetickets.length > 0 ? ( {data.timetickets.length > 0 ? (
@@ -72,7 +78,10 @@ export function TimeTicketShiftContainer({
refetch={refetch} refetch={refetch}
/> />
) : ( ) : (
<TimeTicketShiftFormContainer isTechConsole={isTechConsole} /> <TimeTicketShiftFormContainer
isTechConsole={isTechConsole}
checkIfAlreadyClocked={checkIfAlreadyClocked}
/>
)} )}
</div> </div>
); );

View File

@@ -2120,6 +2120,22 @@ export const DELETE_RELATED_RO = gql`
`; `;
export const GET_JOB_LINE_ORDERS = gql` export const GET_JOB_LINE_ORDERS = gql`
query GET_JOB_LINE_ORDERS($joblineid: uuid!) { query GET_JOB_LINE_ORDERS($joblineid: uuid!) {
billlines(where: { joblineid: { _eq: $joblineid } }) {
actual_cost
actual_price
billid
quantity
bill {
id
invoice_number
date
vendorid
vendor {
id
name
}
}
}
parts_order_lines(where: { job_line_id: { _eq: $joblineid } }) { parts_order_lines(where: { job_line_id: { _eq: $joblineid } }) {
id id
act_price act_price

View File

@@ -354,7 +354,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
totalAllocated totalAllocated
) )
: Dinero(); : Dinero();
return discrep.getAmount() > 0 return discrep.getAmount() >= 0
? Promise.resolve() ? Promise.resolve()
: Promise.reject( : Promise.reject(
new Error( new Error(

View File

@@ -2215,6 +2215,7 @@
"mpi_eglass_auth": "MPI - eGlass Auth", "mpi_eglass_auth": "MPI - eGlass Auth",
"mpi_final_acct_sheet": "MPI - Final Accounting Sheet", "mpi_final_acct_sheet": "MPI - Final Accounting Sheet",
"paint_grid": "Paint Grid", "paint_grid": "Paint Grid",
"parts_invoice_label_single": "Parts Label Single",
"parts_label_multiple": "Parts Label - Multi", "parts_label_multiple": "Parts Label - Multi",
"parts_label_single": "Parts Label - Single", "parts_label_single": "Parts Label - Single",
"parts_list": "Parts List", "parts_list": "Parts List",
@@ -2557,7 +2558,8 @@
"creating": "Error creating time ticket. {{message}}", "creating": "Error creating time ticket. {{message}}",
"deleting": "Error deleting time ticket. {{message}}", "deleting": "Error deleting time ticket. {{message}}",
"noemployeeforuser": "Unable to use Shift Clock", "noemployeeforuser": "Unable to use Shift Clock",
"noemployeeforuser_sub": "An employee record has not been created for this user. Please create one before using the shift clock. " "noemployeeforuser_sub": "An employee record has not been created for this user. Please create one before using the shift clock. ",
"shiftalreadyclockedon": "You are already clocked onto a shift. Unable to create shift entry."
}, },
"fields": { "fields": {
"actualhrs": "Actual Hours", "actualhrs": "Actual Hours",

View File

@@ -2215,6 +2215,7 @@
"mpi_eglass_auth": "", "mpi_eglass_auth": "",
"mpi_final_acct_sheet": "", "mpi_final_acct_sheet": "",
"paint_grid": "", "paint_grid": "",
"parts_invoice_label_single": "",
"parts_label_multiple": "", "parts_label_multiple": "",
"parts_label_single": "", "parts_label_single": "",
"parts_list": "", "parts_list": "",
@@ -2557,7 +2558,8 @@
"creating": "", "creating": "",
"deleting": "", "deleting": "",
"noemployeeforuser": "", "noemployeeforuser": "",
"noemployeeforuser_sub": "" "noemployeeforuser_sub": "",
"shiftalreadyclockedon": ""
}, },
"fields": { "fields": {
"actualhrs": "", "actualhrs": "",

View File

@@ -2215,6 +2215,7 @@
"mpi_eglass_auth": "", "mpi_eglass_auth": "",
"mpi_final_acct_sheet": "", "mpi_final_acct_sheet": "",
"paint_grid": "", "paint_grid": "",
"parts_invoice_label_single": "",
"parts_label_multiple": "", "parts_label_multiple": "",
"parts_label_single": "", "parts_label_single": "",
"parts_list": "", "parts_list": "",
@@ -2557,7 +2558,8 @@
"creating": "", "creating": "",
"deleting": "", "deleting": "",
"noemployeeforuser": "", "noemployeeforuser": "",
"noemployeeforuser_sub": "" "noemployeeforuser_sub": "",
"shiftalreadyclockedon": ""
}, },
"fields": { "fields": {
"actualhrs": "", "actualhrs": "",