diff --git a/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx b/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx
index ca94a70b3..6fb7692a4 100644
--- a/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx
+++ b/client/src/components/bill-enter-modal/bill-enter-modal.container.jsx
@@ -229,23 +229,26 @@ function BillEnterModalContainer({
});
}
}
+ //If it's not a credit memo, update the statuses.
- await Promise.all(
- remainingValues.billlines
- .filter((il) => il.joblineid !== "noline")
- .map((li) => {
- return updateJobLines({
- variables: {
- lineId: li.joblineid,
- line: {
- location: li.location || location,
- status:
- bodyshop.md_order_statuses.default_received || "Received*",
+ if (!values.is_credit_memo) {
+ await Promise.all(
+ remainingValues.billlines
+ .filter((il) => il.joblineid !== "noline")
+ .map((li) => {
+ return updateJobLines({
+ variables: {
+ lineId: li.joblineid,
+ line: {
+ location: li.location || location,
+ status:
+ bodyshop.md_order_statuses.default_received || "Received*",
+ },
},
- },
- });
- })
- );
+ });
+ })
+ );
+ }
/////////////////////////
if (upload && upload.length > 0) {
diff --git a/client/src/components/job-detail-lines/job-lines-expander.component.jsx b/client/src/components/job-detail-lines/job-lines-expander.component.jsx
index b875a61b1..06e00c729 100644
--- a/client/src/components/job-detail-lines/job-lines-expander.component.jsx
+++ b/client/src/components/job-detail-lines/job-lines-expander.component.jsx
@@ -1,11 +1,12 @@
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 { GET_JOB_LINE_ORDERS } from "../../graphql/jobs.queries";
import { useTranslation } from "react-i18next";
-import AlertComponent from "../alert/alert.component";
-import { DateFormatter } from "../../utils/DateFormatter";
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 }) {
const { t } = useTranslation();
@@ -48,7 +49,46 @@ export default function JobLinesExpander({ jobline, jobid }) {
)}
-
+
+ {t("bills.labels.bills")}
+
+ {data.billlines.length > 0 ? (
+ data.billlines.map((line) => (
+
+
+
+
+ {line.bill.invoice_number}
+
+
+
+
+ {`${t("billlines.fields.actual_price")}: `}
+ {line.actual_price}
+
+
+
+
+ {`${t("billlines.fields.actual_cost")}: `}
+ {line.actual_cost}
+
+
+
+ {line.bill.date}
+
+ {line.bill.vendor.name}
+
+
+ ))
+ ) : (
+
+ {t("parts_orders.labels.notyetordered")}
+
+ )}
+
+
);
}
diff --git a/client/src/components/time-ticket-shift-form/time-ticket-shift-form.container.jsx b/client/src/components/time-ticket-shift-form/time-ticket-shift-form.container.jsx
index c2180ee8a..3234039f9 100644
--- a/client/src/components/time-ticket-shift-form/time-ticket-shift-form.container.jsx
+++ b/client/src/components/time-ticket-shift-form/time-ticket-shift-form.container.jsx
@@ -27,6 +27,7 @@ export function TimeTicektShiftContainer({
technician,
currentUser,
isTechConsole,
+ checkIfAlreadyClocked,
}) {
const [form] = Form.useForm();
const [insertTimeTicket] = useMutation(INSERT_NEW_TIME_TICKET);
@@ -43,36 +44,47 @@ export function TimeTicektShiftContainer({
const handleFinish = async (values) => {
setLoading(true);
- const theTime = moment((await axios.post("/utils/time")).data);
- 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"],
- });
+ const alreadyClocked = await checkIfAlreadyClocked();
- if (!!result.errors) {
+ if (alreadyClocked) {
+ //Show the error.
notification["error"]({
- message: t("timetickets.errors.clockingin", {
- message: JSON.stringify(result.errors),
- }),
+ message: t("timetickets.errors.shiftalreadyclockedon"),
});
} else {
- notification["success"]({
- message: t("timetickets.successes.clockedin"),
+ const theTime = moment((await axios.post("/utils/time")).data);
+
+ 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);
};
diff --git a/client/src/components/time-ticket-shift/time-ticket-shift.container.jsx b/client/src/components/time-ticket-shift/time-ticket-shift.container.jsx
index a91dd4004..9f0fec612 100644
--- a/client/src/components/time-ticket-shift/time-ticket-shift.container.jsx
+++ b/client/src/components/time-ticket-shift/time-ticket-shift.container.jsx
@@ -64,6 +64,12 @@ export function TimeTicketShiftContainer({
);
+ const checkIfAlreadyClocked = async () => {
+ const { data } = await refetch();
+
+ return data.timetickets.length > 0;
+ };
+
return (
{data.timetickets.length > 0 ? (
@@ -72,7 +78,10 @@ export function TimeTicketShiftContainer({
refetch={refetch}
/>
) : (
-
+
)}
);
diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js
index 7d0bcb8f0..4bf702cee 100644
--- a/client/src/graphql/jobs.queries.js
+++ b/client/src/graphql/jobs.queries.js
@@ -2120,6 +2120,22 @@ export const DELETE_RELATED_RO = gql`
`;
export const GET_JOB_LINE_ORDERS = gql`
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 } }) {
id
act_price
diff --git a/client/src/pages/jobs-close/jobs-close.component.jsx b/client/src/pages/jobs-close/jobs-close.component.jsx
index f7e6d3795..f7fcbfe1a 100644
--- a/client/src/pages/jobs-close/jobs-close.component.jsx
+++ b/client/src/pages/jobs-close/jobs-close.component.jsx
@@ -354,7 +354,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
totalAllocated
)
: Dinero();
- return discrep.getAmount() > 0
+ return discrep.getAmount() >= 0
? Promise.resolve()
: Promise.reject(
new Error(
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index 12e52e1a5..f4c464986 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -2215,6 +2215,7 @@
"mpi_eglass_auth": "MPI - eGlass Auth",
"mpi_final_acct_sheet": "MPI - Final Accounting Sheet",
"paint_grid": "Paint Grid",
+ "parts_invoice_label_single": "Parts Label Single",
"parts_label_multiple": "Parts Label - Multi",
"parts_label_single": "Parts Label - Single",
"parts_list": "Parts List",
@@ -2557,7 +2558,8 @@
"creating": "Error creating time ticket. {{message}}",
"deleting": "Error deleting time ticket. {{message}}",
"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": {
"actualhrs": "Actual Hours",
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index 6bba2a817..1ab9f658c 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -2215,6 +2215,7 @@
"mpi_eglass_auth": "",
"mpi_final_acct_sheet": "",
"paint_grid": "",
+ "parts_invoice_label_single": "",
"parts_label_multiple": "",
"parts_label_single": "",
"parts_list": "",
@@ -2557,7 +2558,8 @@
"creating": "",
"deleting": "",
"noemployeeforuser": "",
- "noemployeeforuser_sub": ""
+ "noemployeeforuser_sub": "",
+ "shiftalreadyclockedon": ""
},
"fields": {
"actualhrs": "",
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index 1c446e2a3..ffe4f8505 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -2215,6 +2215,7 @@
"mpi_eglass_auth": "",
"mpi_final_acct_sheet": "",
"paint_grid": "",
+ "parts_invoice_label_single": "",
"parts_label_multiple": "",
"parts_label_single": "",
"parts_list": "",
@@ -2557,7 +2558,8 @@
"creating": "",
"deleting": "",
"noemployeeforuser": "",
- "noemployeeforuser_sub": ""
+ "noemployeeforuser_sub": "",
+ "shiftalreadyclockedon": ""
},
"fields": {
"actualhrs": "",