Compare commits

...

6 Commits

Author SHA1 Message Date
Allan Carr
521a7084b7 IO-3262 Correction for v_year in Project Mexico
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2025-12-05 09:48:32 -08:00
Allan Carr
a3c71fdfc0 IO-3262 Add email address to Usage Report
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2025-12-03 10:28:20 -08:00
Allan Carr
90edf94fee IO-3262 Tech Console Job Clock Out
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2025-12-01 12:50:11 -08:00
Dave Richer
123066f1cd Merged in release/2025-11-21 (pull request #2671)
Release/2025 11 21 into Master-AIO - IO-3435 IO-3445 IO-3440 IO-3446
2025-11-21 19:19:15 +00:00
Allan Carr
a153cca3c0 Merged in feature/IO-3440-Payment-By-Date-Excel (pull request #2669)
IO-3440 Payment By Date - Excel
2025-11-21 00:26:54 +00:00
Allan Carr
35c7c32c8e IO-3440 Payment By Date - Excel
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2025-11-20 16:29:05 -08:00
6 changed files with 122 additions and 131 deletions

View File

@@ -16,7 +16,7 @@ const mapDispatchToProps = () => ({
export function TechHeader({ technician }) { export function TechHeader({ technician }) {
const { t } = useTranslation(); const { t } = useTranslation();
return ( return (
<Header style={{ textAlign: "center" }}> <Header style={{ textAlign: "center", height: "auto", overflow: "visible" }}>
<Typography.Title style={{ color: "#fff" }}> <Typography.Title style={{ color: "#fff" }}>
{technician {technician
? t("tech.labels.loggedin", { ? t("tech.labels.loggedin", {

View File

@@ -1,5 +1,5 @@
import { useMutation, useQuery } from "@apollo/client"; import { useMutation, useQuery } from "@apollo/client";
import { Button, Card, Col, Form, InputNumber, Popover, Row, Select } from "antd"; import { Button, Card, Form, InputNumber, Popover, Select, Space } from "antd";
import axios from "axios"; import axios from "axios";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -124,8 +124,7 @@ export function TechClockOffButton({
cost_center: isShiftTicket ? "timetickets.labels.shift" : technician ? technician.cost_center : null cost_center: isShiftTicket ? "timetickets.labels.shift" : technician ? technician.cost_center : null
}} }}
> >
<Row gutter={[16, 16]}> <Space direction="vertical">
<Col span={!isShiftTicket ? 8 : 24}>
{!isShiftTicket ? ( {!isShiftTicket ? (
<div> <div>
<Form.Item <Form.Item
@@ -155,7 +154,6 @@ export function TechClockOffButton({
} }
if (!value || getFieldValue("cost_center") === null || !lineTicketData) if (!value || getFieldValue("cost_center") === null || !lineTicketData)
return Promise.resolve(); return Promise.resolve();
//Check the cost center, //Check the cost center,
const totals = CalculateAllocationsTotals( const totals = CalculateAllocationsTotals(
bodyshop, bodyshop,
@@ -163,16 +161,13 @@ export function TechClockOffButton({
lineTicketData.timetickets, lineTicketData.timetickets,
lineTicketData.jobs_by_pk.lbr_adjustments lineTicketData.jobs_by_pk.lbr_adjustments
); );
const fieldTypeToCheck = const fieldTypeToCheck =
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? "mod_lbr_ty" : "cost_center"; bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? "mod_lbr_ty" : "cost_center";
const costCenterDiff = const costCenterDiff =
Math.round( Math.round(
totals.find((total) => total[fieldTypeToCheck] === getFieldValue("cost_center")) totals.find((total) => total[fieldTypeToCheck] === getFieldValue("cost_center"))
?.difference * 10 ?.difference * 10
) / 10; ) / 10;
if (value > costCenterDiff) if (value > costCenterDiff)
return Promise.reject(t("timetickets.validation.hoursenteredmorethanavailable")); return Promise.reject(t("timetickets.validation.hoursenteredmorethanavailable"));
else { else {
@@ -213,7 +208,6 @@ export function TechClockOffButton({
)} )}
</Select> </Select>
</Form.Item> </Form.Item>
{isShiftTicket ? ( {isShiftTicket ? (
<div></div> <div></div>
) : ( ) : (
@@ -239,24 +233,21 @@ export function TechClockOffButton({
{t("general.actions.save")} {t("general.actions.save")}
</Button> </Button>
<TechJobClockoutDelete completedCallback={completedCallback} timeTicketId={timeTicketId} /> <TechJobClockoutDelete completedCallback={completedCallback} timeTicketId={timeTicketId} />
</Col>
{!isShiftTicket && ( {!isShiftTicket && (
<Col span={16}> <LaborAllocationContainer jobid={jobId || null} loading={queryLoading} lineTicketData={lineTicketData} />
<LaborAllocationContainer
jobid={jobId || null}
loading={queryLoading}
lineTicketData={lineTicketData}
/>
</Col>
)} )}
</Row> </Space>
</Form> </Form>
</div> </div>
</Card> </Card>
); );
return ( return (
<Popover content={overlay} trigger="click"> <Popover
content={<div style={{ maxHeight: "75vh", overflowY: "auto" }}>{overlay}</div>}
trigger="click"
getPopupContainer={() => document.querySelector('#time-ticket-modal')}
>
<Button loading={loading} {...otherBtnProps}> <Button loading={loading} {...otherBtnProps}>
{t("timetickets.actions.clockout")} {t("timetickets.actions.clockout")}
</Button> </Button>

View File

@@ -1221,7 +1221,7 @@ export const TemplateList = (type, context) => {
payments_by_date_excel: { payments_by_date_excel: {
title: i18n.t("reportcenter.templates.payments_by_date_excel"), title: i18n.t("reportcenter.templates.payments_by_date_excel"),
subject: i18n.t("reportcenter.templates.payments_by_date_excel"), subject: i18n.t("reportcenter.templates.payments_by_date_excel"),
key: "payments_by_date", key: "payments_by_date_excel",
reporttype: "excel", reporttype: "excel",
disabled: false, disabled: false,
rangeFilter: { rangeFilter: {

View File

@@ -234,11 +234,10 @@ const CreateRepairOrderTag = (job, errorCallback) => {
const ret = { const ret = {
ro_number: crypto.createHash("md5").update(job.id, "utf8").digest("hex"), ro_number: crypto.createHash("md5").update(job.id, "utf8").digest("hex"),
v_vin: job.v_vin || "", v_vin: job.v_vin || "",
v_year: job.v_model_yr v_year: (() => {
? parseInt(job.v_model_yr.match(/\d/g)) const y = parseInt(job.v_model_yr);
? parseInt(job.v_model_yr.match(/\d/g).join(""), 10) return isNaN(y) ? null : y < 100 ? y + (y >= (new Date().getFullYear() + 1) % 100 ? 1900 : 2000) : y;
: "" })(),
: "",
v_make: job.v_makedesc || "", v_make: job.v_makedesc || "",
v_model: job.v_model || "", v_model: job.v_model || "",

View File

@@ -286,11 +286,10 @@ const CreateRepairOrderTag = (job, errorCallback) => {
const ret = { const ret = {
ro_number: crypto.createHash("md5").update(job.ro_number, "utf8").digest("hex"), ro_number: crypto.createHash("md5").update(job.ro_number, "utf8").digest("hex"),
v_vin: job.v_vin || "", v_vin: job.v_vin || "",
v_year: job.v_model_yr v_year: (() => {
? parseInt(job.v_model_yr.match(/\d/g)) const y = parseInt(job.v_model_yr);
? parseInt(job.v_model_yr.match(/\d/g).join(""), 10) return isNaN(y) ? null : y < 100 ? y + (y >= (new Date().getFullYear() + 1) % 100 ? 1900 : 2000) : y;
: "" })(),
: "",
v_make: job.v_make_desc || "", v_make: job.v_make_desc || "",
v_model: job.v_model_desc || "", v_model: job.v_model_desc || "",

View File

@@ -55,7 +55,9 @@ exports.default = async (req, res) => {
"patrick.fic@convenient-brands.com", "patrick.fic@convenient-brands.com",
"bradley.rhoades@convenient-brands.com", "bradley.rhoades@convenient-brands.com",
"jrome@rometech.com", "jrome@rometech.com",
"ivana@imexsystems.ca" "ivana@imexsystems.ca",
"support@imexsystems.ca",
"sarah@rometech.com"
], ],
subject: `RO Usage Report - ${moment().format("MM/DD/YYYY")}`, subject: `RO Usage Report - ${moment().format("MM/DD/YYYY")}`,
text: ` text: `