diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel
index 23707d6e7..f453df8c6 100644
--- a/bodyshop_translations.babel
+++ b/bodyshop_translations.babel
@@ -8864,6 +8864,27 @@
+
+ tt_enforce_hours_for_tech_console
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
use_fippa
false
@@ -17310,6 +17331,27 @@
+
+ total
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
totals
false
@@ -33806,6 +33848,27 @@
errors
+
+ deleting
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
noaccess
false
@@ -34367,6 +34430,27 @@
+
+ deleteconfirm
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
existing_owners
false
@@ -34477,6 +34561,27 @@
successes
+
+ delete
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
save
false
@@ -44980,6 +45085,27 @@
+
+ hoursenteredmorethanavailable
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
@@ -47292,6 +47418,27 @@
errors
+
+ deleting
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
noaccess
false
@@ -47916,6 +48063,27 @@
labels
+
+ deleteconfirm
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
fromvehicle
false
@@ -48005,6 +48173,27 @@
successes
+
+ delete
+ false
+
+
+
+
+
+ en-US
+ false
+
+
+ es-MX
+ false
+
+
+ fr-CA
+ false
+
+
+
save
false
diff --git a/client/src/components/labor-allocations-table/labor-allocations-table.utility.js b/client/src/components/labor-allocations-table/labor-allocations-table.utility.js
index 2ce5b4a0b..d236de913 100644
--- a/client/src/components/labor-allocations-table/labor-allocations-table.utility.js
+++ b/client/src/components/labor-allocations-table/labor-allocations-table.utility.js
@@ -6,10 +6,6 @@ export const CalculateAllocationsTotals = (
timetickets,
adjustments = []
) => {
- console.log(
- "🚀 ~ file: labor-allocations-table.utility.js ~ line 9 ~ adjustments",
- adjustments
- );
const responsibilitycenters = bodyshop.md_responsibility_centers;
const jobCodes = joblines.map((item) => item.mod_lbr_ty);
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
diff --git a/client/src/components/shop-info/shop-info.general.component.jsx b/client/src/components/shop-info/shop-info.general.component.jsx
index 3e9b1ed2c..32ac5aa5d 100644
--- a/client/src/components/shop-info/shop-info.general.component.jsx
+++ b/client/src/components/shop-info/shop-info.general.component.jsx
@@ -589,6 +589,13 @@ export default function ShopInfoGeneral({ form }) {
>
+
+
+
e.id === (technician && technician.id)
@@ -129,6 +141,51 @@ export function TechClockOffButton({
required: true,
//message: t("general.validation.required"),
},
+ ({ getFieldValue }) => ({
+ validator(rule, value) {
+ console.log(
+ bodyshop.tt_enforce_hours_for_tech_console
+ );
+ if (!bodyshop.tt_enforce_hours_for_tech_console) {
+ return Promise.resolve();
+ }
+ if (
+ !value ||
+ getFieldValue("cost_center") === null ||
+ !lineTicketData
+ )
+ return Promise.resolve();
+
+ //Check the cost center,
+ const totals = CalculateAllocationsTotals(
+ bodyshop,
+ lineTicketData.joblines,
+ lineTicketData.timetickets,
+ lineTicketData.jobs_by_pk.lbr_adjustments
+ );
+
+ const fieldTypeToCheck =
+ bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber
+ ? "mod_lbr_ty"
+ : "cost_center";
+
+ const costCenterDiff = totals.find(
+ (total) =>
+ total[fieldTypeToCheck] ===
+ getFieldValue("cost_center")
+ )?.difference;
+
+ if (value > costCenterDiff)
+ return Promise.reject(
+ t(
+ "timetickets.validation.hoursenteredmorethanavailable"
+ )
+ );
+ else {
+ return Promise.resolve();
+ }
+ },
+ }),
]}
>
@@ -178,7 +235,11 @@ export function TechClockOffButton({
{!isShiftTicket && (
-
+
)}
diff --git a/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx b/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx
index 6f61fccf0..c0cf7b024 100644
--- a/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx
+++ b/client/src/components/time-ticket-modal/time-ticket-modal.component.jsx
@@ -1,4 +1,4 @@
-import { useQuery } from "@apollo/client";
+import { useLazyQuery } from "@apollo/client";
import { Form, Input, InputNumber, Select, Switch } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
@@ -14,6 +14,7 @@ import FormDatePicker from "../form-date-picker/form-date-picker.component";
import FormDateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
import JobSearchSelect from "../job-search-select/job-search-select.component";
import LaborAllocationsTable from "../labor-allocations-table/labor-allocations-table.component";
+import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component";
@@ -38,7 +39,11 @@ export function TimeTicketModalComponent({
employeeSelectDisabled,
}) {
const { t } = useTranslation();
-
+ const [loadLineTicketData, { called, loading, data: lineTicketData }] =
+ useLazyQuery(GET_LINE_TICKET_BY_PK, {
+ fetchPolicy: "network-only",
+ nextFetchPolicy: "network-only",
+ });
const CostCenterSelect = ({ emps, value, ...props }) => {
return (
- {() => (
-
- )}
+ {() => {
+ const jobid = form.getFieldValue("jobid");
+ if (
+ (!called && jobid) ||
+ (jobid && lineTicketData?.jobs_by_pk?.id !== jobid && !loading)
+ ) {
+ loadLineTicketData({ variables: { id: jobid } });
+ }
+ return (
+
+ );
+ }}
);
}
-export function LaborAllocationContainer({ jobid }) {
- const { loading, data: lineTicketData } = useQuery(GET_LINE_TICKET_BY_PK, {
- variables: { id: jobid },
- skip: !jobid,
- fetchPolicy: "network-only",
- nextFetchPolicy: "network-only",
- });
+export function LaborAllocationContainer({ jobid, loading, lineTicketData }) {
if (loading) return ;
if (!lineTicketData) return null;
return (
diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js
index 956bf9dd4..c934c9514 100644
--- a/client/src/graphql/bodyshop.queries.js
+++ b/client/src/graphql/bodyshop.queries.js
@@ -116,6 +116,7 @@ export const QUERY_BODYSHOP = gql`
md_lost_sale_reasons
md_parts_scan
enforce_conversion_category
+ tt_enforce_hours_for_tech_console
employees {
user_email
id
@@ -230,6 +231,7 @@ export const UPDATE_SHOP = gql`
md_lost_sale_reasons
md_parts_scan
enforce_conversion_category
+ tt_enforce_hours_for_tech_console
employees {
id
first_name
diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json
index a8299c658..f01d1a186 100644
--- a/client/src/translations/en_us/common.json
+++ b/client/src/translations/en_us/common.json
@@ -541,6 +541,7 @@
"target_touchtime": "Target Touch Time",
"timezone": "Timezone",
"tt_allow_post_to_invoiced": "Allow Time Tickets to be posted to Invoiced & Exported Jobs",
+ "tt_enforce_hours_for_tech_console": "Restrict Claimable hours from Tech Console",
"use_fippa": "Use FIPPA for Names on Generated Documents?",
"uselocalmediaserver": "Use Local Media Server?",
"website": "Website",
@@ -1063,8 +1064,8 @@
"sunday": "Sunday",
"text": "Text",
"thursday": "Thursday",
- "totals": "Totals",
"total": "Total",
+ "totals": "Totals",
"tuesday": "Tuesday",
"unknown": "Unknown",
"username": "Username",
@@ -2662,7 +2663,8 @@
},
"validation": {
"clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.",
- "clockoffwithoutclockon": "Clock off time cannot be set without a clock in time."
+ "clockoffwithoutclockon": "Clock off time cannot be set without a clock in time.",
+ "hoursenteredmorethanavailable": "The number of hours entered is more than what is available for this cost center."
}
},
"titles": {
diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json
index 7f0385f80..552b080a2 100644
--- a/client/src/translations/es/common.json
+++ b/client/src/translations/es/common.json
@@ -541,6 +541,7 @@
"target_touchtime": "",
"timezone": "",
"tt_allow_post_to_invoiced": "",
+ "tt_enforce_hours_for_tech_console": "",
"use_fippa": "",
"uselocalmediaserver": "",
"website": "",
@@ -1063,6 +1064,7 @@
"sunday": "",
"text": "",
"thursday": "",
+ "total": "",
"totals": "",
"tuesday": "",
"unknown": "Desconocido",
@@ -2661,7 +2663,8 @@
},
"validation": {
"clockoffmustbeafterclockon": "",
- "clockoffwithoutclockon": ""
+ "clockoffwithoutclockon": "",
+ "hoursenteredmorethanavailable": ""
}
},
"titles": {
diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json
index 172a44d34..40d15a480 100644
--- a/client/src/translations/fr/common.json
+++ b/client/src/translations/fr/common.json
@@ -541,6 +541,7 @@
"target_touchtime": "",
"timezone": "",
"tt_allow_post_to_invoiced": "",
+ "tt_enforce_hours_for_tech_console": "",
"use_fippa": "",
"uselocalmediaserver": "",
"website": "",
@@ -1063,6 +1064,7 @@
"sunday": "",
"text": "",
"thursday": "",
+ "total": "",
"totals": "",
"tuesday": "",
"unknown": "Inconnu",
@@ -2661,7 +2663,8 @@
},
"validation": {
"clockoffmustbeafterclockon": "",
- "clockoffwithoutclockon": ""
+ "clockoffwithoutclockon": "",
+ "hoursenteredmorethanavailable": ""
}
},
"titles": {
diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml
index 0055e4b7a..a456a9a0f 100644
--- a/hasura/metadata/tables.yaml
+++ b/hasura/metadata/tables.yaml
@@ -935,6 +935,7 @@
- textid
- timezone
- tt_allow_post_to_invoiced
+ - tt_enforce_hours_for_tech_console
- updated_at
- use_fippa
- uselocalmediaserver
@@ -1023,6 +1024,7 @@
- target_touchtime
- timezone
- tt_allow_post_to_invoiced
+ - tt_enforce_hours_for_tech_console
- updated_at
- use_fippa
- uselocalmediaserver
@@ -2391,30 +2393,32 @@
- active:
_eq: true
columns:
- - id
- - created_at
- - updated_at
- - jobid
- billid
+ - bodyshopid
+ - created_at
+ - id
+ - jobid
+ - message
+ - metadata
- paymentid
- successful
- - message
- - bodyshopid
+ - updated_at
- useremail
select_permissions:
- role: user
permission:
columns:
- - successful
- - message
- - useremail
- - created_at
- - updated_at
- billid
- bodyshopid
+ - created_at
- id
- jobid
+ - message
+ - metadata
- paymentid
+ - successful
+ - updated_at
+ - useremail
filter:
bodyshop:
associations:
diff --git a/hasura/migrations/1681331289298_alter_table_public_bodyshops_add_column_tt_enforce_hours_for_tech_console/down.sql b/hasura/migrations/1681331289298_alter_table_public_bodyshops_add_column_tt_enforce_hours_for_tech_console/down.sql
new file mode 100644
index 000000000..53e7608da
--- /dev/null
+++ b/hasura/migrations/1681331289298_alter_table_public_bodyshops_add_column_tt_enforce_hours_for_tech_console/down.sql
@@ -0,0 +1,4 @@
+-- Could not auto-generate a down migration.
+-- Please write an appropriate down migration for the SQL below:
+-- alter table "public"."bodyshops" add column "tt_enforce_hours_for_tech_console" boolean
+-- not null default 'false';
diff --git a/hasura/migrations/1681331289298_alter_table_public_bodyshops_add_column_tt_enforce_hours_for_tech_console/up.sql b/hasura/migrations/1681331289298_alter_table_public_bodyshops_add_column_tt_enforce_hours_for_tech_console/up.sql
new file mode 100644
index 000000000..86e0f5973
--- /dev/null
+++ b/hasura/migrations/1681331289298_alter_table_public_bodyshops_add_column_tt_enforce_hours_for_tech_console/up.sql
@@ -0,0 +1,2 @@
+alter table "public"."bodyshops" add column "tt_enforce_hours_for_tech_console" boolean
+ not null default 'false';