Merged in feature/america (pull request #933)

Feature/america
This commit is contained in:
Patrick Fic
2023-08-14 22:39:18 +00:00
27 changed files with 258 additions and 70 deletions

View File

@@ -46441,6 +46441,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>payall</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>shiftalreadyclockedon</name> <name>shiftalreadyclockedon</name>
<definition_loaded>false</definition_loaded> <definition_loaded>false</definition_loaded>
@@ -47401,6 +47422,27 @@
</translation> </translation>
</translations> </translations>
</concept_node> </concept_node>
<concept_node>
<name>payall</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

@@ -1,10 +1,9 @@
import { useTreatments } from "@splitsoftware/splitio-react";
import Icon, { import Icon, {
BankFilled, BankFilled,
BarChartOutlined, BarChartOutlined,
CarFilled, CarFilled,
ClockCircleFilled,
CheckCircleOutlined, CheckCircleOutlined,
ClockCircleFilled,
DashboardFilled, DashboardFilled,
DollarCircleFilled, DollarCircleFilled,
ExportOutlined, ExportOutlined,
@@ -26,6 +25,7 @@ import Icon, {
UnorderedListOutlined, UnorderedListOutlined,
UserOutlined, UserOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { useTreatments } from "@splitsoftware/splitio-react";
import { Layout, Menu } from "antd"; import { Layout, Menu } from "antd";
import React from "react"; import React from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -275,7 +275,11 @@ function Header({
onClick={() => { onClick={() => {
setTimeTicketContext({ setTimeTicketContext({
actions: {}, actions: {},
context: {}, context: {
created_by: currentUser.displayName
? currentUser.email.concat(" | ", currentUser.displayName)
: currentUser.email,
},
}); });
}} }}
> >

View File

@@ -1,5 +1,14 @@
import { Button, Card, Col, Row, Space, Table, Typography } from "antd"; import {
import { SyncOutlined } from '@ant-design/icons' Button,
Card,
Col,
Row,
Space,
Table,
Typography,
notification,
} from "antd";
import { SyncOutlined } from "@ant-design/icons";
import axios from "axios"; import axios from "axios";
import _ from "lodash"; import _ from "lodash";
import React, { useEffect, useMemo, useState } from "react"; import React, { useEffect, useMemo, useState } from "react";
@@ -225,10 +234,34 @@ export function PayrollLaborAllocationsTable({
<Space> <Space>
<Button <Button
onClick={async () => { onClick={async () => {
await axios.post("/payroll/payall", { const response = await axios.post("/payroll/payall", {
jobid: jobId, jobid: jobId,
}); });
if (refetch) refetch();
if (response.status === 200) {
if (response.data.success) {
notification.open({
type: "success",
message: t("timetickets.successes.payall"),
});
} else {
notification.open({
type: "error",
message: t("timetickets.errors.payall", {
error: response.data.error,
}),
});
}
if (refetch) refetch();
} else {
notification.open({
type: "error",
message: t("timetickets.errors.payall", {
error: JSON.stringify(""),
}),
});
}
}} }}
> >
{t("timetickets.actions.payall")} {t("timetickets.actions.payall")}
@@ -242,7 +275,7 @@ export function PayrollLaborAllocationsTable({
refetch(); refetch();
}} }}
> >
<SyncOutlined/> <SyncOutlined />
</Button> </Button>
</Space> </Space>
} }

View File

@@ -36,6 +36,7 @@ import FormDatePicker from "../form-date-picker/form-date-picker.component";
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component"; import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import ShopEmployeeAddVacation from "./shop-employees-add-vacation.component"; import ShopEmployeeAddVacation from "./shop-employees-add-vacation.component";
import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -56,7 +57,11 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
fetchPolicy: "network-only", fetchPolicy: "network-only",
nextFetchPolicy: "network-only", nextFetchPolicy: "network-only",
}); });
const { Enhanced_Payroll } = useTreatments(
["Enhanced_Payroll"],
{},
bodyshop.imexshopid
);
const client = useApolloClient(); const client = useApolloClient();
useEffect(() => { useEffect(() => {
if (data && data.employees_by_pk) form.setFieldsValue(data.employees_by_pk); if (data && data.employees_by_pk) form.setFieldsValue(data.employees_by_pk);
@@ -362,7 +367,7 @@ export function ShopEmployeesFormComponent({ bodyshop }) {
{t("timetickets.labels.shift")} {t("timetickets.labels.shift")}
</Select.Option> </Select.Option>
{bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber {bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === "on"
? CiecaSelect(false, true) ? CiecaSelect(false, true)
: bodyshop.md_responsibility_centers.costs.map( : bodyshop.md_responsibility_centers.costs.map(
(c) => ( (c) => (

View File

@@ -143,14 +143,6 @@ export function ShopInfoTaskPresets({ bodyshop, form }) {
{t("joblines.fields.lbr_types.LAM")} {t("joblines.fields.lbr_types.LAM")}
</Checkbox> </Checkbox>
</Col> </Col>
<Col span={4}>
<Checkbox
value="LAM"
style={{ lineHeight: "32px" }}
>
{t("joblines.fields.lbr_types.LAM")}
</Checkbox>
</Col>
<Col span={4}> <Col span={4}>
<Checkbox <Checkbox
value="LAR" value="LAR"

View File

@@ -8,6 +8,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import JobSearchSelect from "../job-search-select/job-search-select.component"; import JobSearchSelect from "../job-search-select/job-search-select.component";
import JobsDetailLaborContainer from "../jobs-detail-labor/jobs-detail-labor.container"; import JobsDetailLaborContainer from "../jobs-detail-labor/jobs-detail-labor.container";
import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -16,6 +17,11 @@ const mapStateToProps = createStructuredSelector({
export function TechClockInComponent({ form, bodyshop, technician }) { export function TechClockInComponent({ form, bodyshop, technician }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { Enhanced_Payroll } = useTreatments(
["Enhanced_Payroll"],
{},
bodyshop.imexshopid
);
const emps = bodyshop.employees.filter((e) => e.id === technician.id)[0]; const emps = bodyshop.employees.filter((e) => e.id === technician.id)[0];
return ( return (
<div> <div>
@@ -53,7 +59,7 @@ export function TechClockInComponent({ form, bodyshop, technician }) {
<Select.Option key={item.cost_center} value={item.cost_center}> <Select.Option key={item.cost_center} value={item.cost_center}>
{item.cost_center === "timetickets.labels.shift" {item.cost_center === "timetickets.labels.shift"
? t(item.cost_center) ? t(item.cost_center)
: bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber : bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === "on"
? t( ? t(
`joblines.fields.lbr_types.${item.cost_center.toUpperCase()}` `joblines.fields.lbr_types.${item.cost_center.toUpperCase()}`
) )

View File

@@ -1,21 +1,26 @@
import { useMutation } from "@apollo/client"; import { useMutation } from "@apollo/client";
import { Button, Card, Form, notification, Space } from "antd"; import { Button, Card, Form, notification, Space } from "antd";
import axios from "axios"; import axios from "axios";
import moment from "moment";
import React, { useState } from "react"; import React, { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { createStructuredSelector } from "reselect"; import { createStructuredSelector } from "reselect";
import { INSERT_NEW_TIME_TICKET } from "../../graphql/timetickets.queries"; import { INSERT_NEW_TIME_TICKET } from "../../graphql/timetickets.queries";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import TechClockInComponent from "./tech-job-clock-in-form.component";
import TechJobPrintTickets from "../tech-job-print-tickets/tech-job-print-tickets.component";
import moment from "moment";
import { setModalContext } from "../../redux/modals/modals.actions"; import { setModalContext } from "../../redux/modals/modals.actions";
import { selectTechnician } from "../../redux/tech/tech.selectors";
import {
selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors";
import TechJobPrintTickets from "../tech-job-print-tickets/tech-job-print-tickets.component";
import TechClockInComponent from "./tech-job-clock-in-form.component";
import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
technician: selectTechnician, technician: selectTechnician,
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
currentUser: selectCurrentUser,
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setTimeTicketContext: (context) => setTimeTicketContext: (context) =>
@@ -25,10 +30,12 @@ export function TechClockInContainer({
setTimeTicketContext, setTimeTicketContext,
technician, technician,
bodyshop, bodyshop,
currentUser,
}) { }) {
console.log( const { Enhanced_Payroll } = useTreatments(
"🚀 ~ file: tech-job-clock-in-form.container.jsx:29 ~ technician:", ["Enhanced_Payroll"],
technician {},
bodyshop.imexshopid
); );
const [form] = Form.useForm(); const [form] = Form.useForm();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
@@ -56,7 +63,7 @@ export function TechClockInContainer({
jobid: values.jobid, jobid: values.jobid,
cost_center: values.cost_center, cost_center: values.cost_center,
ciecacode: ciecacode:
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === 'on'
? values.cost_center ? values.cost_center
: Object.keys( : Object.keys(
bodyshop.md_responsibility_centers.defaults.costs bodyshop.md_responsibility_centers.defaults.costs
@@ -66,6 +73,12 @@ export function TechClockInContainer({
values.cost_center values.cost_center
); );
}), }),
created_by: currentUser.email.concat(
" | ",
technician.employee_number
.concat(" ", technician.first_name, " ", technician.last_name)
.trim()
),
}, },
], ],
}, },
@@ -100,6 +113,17 @@ export function TechClockInContainer({
employeeid: technician.id, employeeid: technician.id,
flat_rate: emps.flat_rate, flat_rate: emps.flat_rate,
}, },
created_by: currentUser.email.concat(
" | ",
technician.employee_number
.concat(
" ",
technician.first_name,
" ",
technician.last_name
)
.trim()
),
}, },
}); });
}} }}

View File

@@ -24,6 +24,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility"; import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
import TechJobClockoutDelete from "../tech-job-clock-out-delete/tech-job-clock-out-delete.component"; import TechJobClockoutDelete from "../tech-job-clock-out-delete/tech-job-clock-out-delete.component";
import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component"; import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component";
import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -43,6 +44,12 @@ export function TechClockOffButton({
const [updateTimeticket] = useMutation(UPDATE_TIME_TICKET); const [updateTimeticket] = useMutation(UPDATE_TIME_TICKET);
const [updateJobStatus] = useMutation(UPDATE_JOB_STATUS); const [updateJobStatus] = useMutation(UPDATE_JOB_STATUS);
const [form] = Form.useForm(); const [form] = Form.useForm();
const { Enhanced_Payroll } = useTreatments(
["Enhanced_Payroll"],
{},
bodyshop.imexshopid
);
const { queryLoading, data: lineTicketData } = useQuery( const { queryLoading, data: lineTicketData } = useQuery(
GET_LINE_TICKET_BY_PK, GET_LINE_TICKET_BY_PK,
{ {
@@ -76,7 +83,9 @@ export function TechClockOffButton({
?.rate, ?.rate,
flat_rate: emps && emps.flat_rate, flat_rate: emps && emps.flat_rate,
ciecacode: ciecacode:
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber bodyshop.cdk_dealerid ||
bodyshop.pbs_serialnumber ||
Enhanced_Payroll.treatment === "on"
? values.cost_center ? values.cost_center
: Object.keys( : Object.keys(
bodyshop.md_responsibility_centers.defaults.costs bodyshop.md_responsibility_centers.defaults.costs

View File

@@ -1,6 +1,7 @@
import Icon, { import Icon, {
SearchOutlined, SearchOutlined,
ScheduleOutlined, ScheduleOutlined,
UserAddOutlined,
CarOutlined, CarOutlined,
} from "@ant-design/icons"; } from "@ant-design/icons";
import { Layout, Menu } from "antd"; import { Layout, Menu } from "antd";
@@ -72,19 +73,28 @@ export function TechSider({
<Link to={`/tech/joblookup`}>{t("menus.tech.joblookup")}</Link> <Link to={`/tech/joblookup`}>{t("menus.tech.joblookup")}</Link>
</Menu.Item> </Menu.Item>
{Enhanced_Payroll.treatment === "on" ? ( {Enhanced_Payroll.treatment === "on" ? (
<Menu.Item <>
key="3" <Menu.Item
disabled={!!!technician} key="TechAssignedProdJobs"
icon={<Icon component={FaBusinessTime} />} disabled={!!!technician}
onClick={() => { icon={<UserAddOutlined />}
setTimeTicketTaskContext({ >
actions: {}, <Link to={`/tech/assigned`}> {t("menus.tech.assignedjobs")}</Link>
context: { jobid: null }, </Menu.Item>
}); <Menu.Item
}} key="3"
> disabled={!!!technician}
{t("menus.tech.claimtask")} icon={<Icon component={FaBusinessTime} />}
</Menu.Item> onClick={() => {
setTimeTicketTaskContext({
actions: {},
context: { jobid: null },
});
}}
>
{t("menus.tech.claimtask")}
</Menu.Item>
</>
) : ( ) : (
<Menu.Item <Menu.Item
key="3" key="3"
@@ -120,13 +130,7 @@ export function TechSider({
> >
<Link to={`/tech/board`}> {t("menus.tech.productionboard")}</Link> <Link to={`/tech/board`}> {t("menus.tech.productionboard")}</Link>
</Menu.Item> </Menu.Item>
<Menu.Item
key="TechAssignedProdJobs"
disabled={!!!technician}
icon={<Icon component={BsKanban} />}
>
<Link to={`/tech/assigned`}> {t("menus.tech.assignedjobs")}</Link>
</Menu.Item>
<Menu.Item <Menu.Item
key="7" key="7"
disabled={!!!technician} disabled={!!!technician}

View File

@@ -10,6 +10,7 @@ import { setModalContext } from "../../redux/modals/modals.actions";
import { import {
selectAuthLevel, selectAuthLevel,
selectBodyshop, selectBodyshop,
selectCurrentUser,
} from "../../redux/user/user.selectors"; } from "../../redux/user/user.selectors";
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter"; import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
import { onlyUnique } from "../../utils/arrayHelper"; import { onlyUnique } from "../../utils/arrayHelper";
@@ -23,6 +24,7 @@ import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
authLevel: selectAuthLevel, authLevel: selectAuthLevel,
currentUser: selectCurrentUser,
}); });
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
setTimeTicketTaskContext: (context) => setTimeTicketTaskContext: (context) =>
@@ -34,6 +36,7 @@ export function TimeTicketList({
bodyshop, bodyshop,
setTimeTicketTaskContext, setTimeTicketTaskContext,
authLevel, authLevel,
currentUser,
disabled, disabled,
loading, loading,
timetickets, timetickets,
@@ -238,7 +241,15 @@ export function TimeTicketList({
}, },
}, },
]), ]),
{
title: t("timetickets.fields.created_by"),
dataIndex: "created_by",
key: "created_by",
sorter: (a, b) => alphaSort(a.created_by, b.created_by),
sortOrder:
state.sortedInfo.columnKey === "created_by" && state.sortedInfo.order,
render: (text, record) => record.created_by,
},
// { // {
// title: "Pay", // title: "Pay",
// dataIndex: "pay", // dataIndex: "pay",
@@ -326,7 +337,12 @@ export function TimeTicketList({
(techConsole ? null : ( (techConsole ? null : (
<TimeTicketEnterButton <TimeTicketEnterButton
actions={{ refetch }} actions={{ refetch }}
context={{ jobId: jobId }} context={{
jobId: jobId,
created_by: currentUser.displayName
? currentUser.email.concat(" | ", currentUser.displayName)
: currentUser.email,
}}
disabled={disabled} disabled={disabled}
> >
{t("timetickets.actions.enter")} {t("timetickets.actions.enter")}

View File

@@ -20,6 +20,7 @@ import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component"; import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component";
import TimeTicketList from "../time-ticket-list/time-ticket-list.component"; import TimeTicketList from "../time-ticket-list/time-ticket-list.component";
import TimeTicketCalculatorComponent from "../time-ticket-calculator/time-ticket-calculator.component"; import TimeTicketCalculatorComponent from "../time-ticket-calculator/time-ticket-calculator.component";
import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop, bodyshop: selectBodyshop,
@@ -41,6 +42,11 @@ export function TimeTicketModalComponent({
employeeSelectDisabled, employeeSelectDisabled,
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();
const { Enhanced_Payroll } = useTreatments(
["Enhanced_Payroll"],
{},
bodyshop.imexshopid
);
const [loadLineTicketData, { called, loading, data: lineTicketData }] = const [loadLineTicketData, { called, loading, data: lineTicketData }] =
useLazyQuery(GET_LINE_TICKET_BY_PK, { useLazyQuery(GET_LINE_TICKET_BY_PK, {
fetchPolicy: "network-only", fetchPolicy: "network-only",
@@ -58,7 +64,7 @@ export function TimeTicketModalComponent({
<Select.Option key={item.cost_center} value={item.cost_center}> <Select.Option key={item.cost_center} value={item.cost_center}>
{item.cost_center === "timetickets.labels.shift" {item.cost_center === "timetickets.labels.shift"
? t(item.cost_center) ? t(item.cost_center)
: bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber : bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatment === 'on'
? t( ? t(
`joblines.fields.lbr_types.${item.cost_center.toUpperCase()}` `joblines.fields.lbr_types.${item.cost_center.toUpperCase()}`
) )

View File

@@ -1,5 +1,5 @@
import { useMutation, useQuery } from "@apollo/client"; import { useMutation, useQuery } from "@apollo/client";
import { Button, Form, Modal, notification, PageHeader, Space } from "antd"; import { Button, Form, Modal, PageHeader, Space, notification } from "antd";
import moment from "moment"; import moment from "moment";
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -15,6 +15,7 @@ import { selectTimeTicket } from "../../redux/modals/modals.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors";
import TimeTicketModalComponent from "./time-ticket-modal.component"; import TimeTicketModalComponent from "./time-ticket-modal.component";
import TimeTicketsCommitToggleComponent from "../time-tickets-commit-toggle/time-tickets-commit-toggle.component"; import TimeTicketsCommitToggleComponent from "../time-tickets-commit-toggle/time-tickets-commit-toggle.component";
import { useTreatments } from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({ const mapStateToProps = createStructuredSelector({
timeTicketModal: selectTimeTicket, timeTicketModal: selectTimeTicket,
@@ -35,7 +36,11 @@ export function TimeTicketModalContainer({
const [enterAgain, setEnterAgain] = useState(false); const [enterAgain, setEnterAgain] = useState(false);
const [insertTicket] = useMutation(INSERT_NEW_TIME_TICKET); const [insertTicket] = useMutation(INSERT_NEW_TIME_TICKET);
const [updateTicket] = useMutation(UPDATE_TIME_TICKET); const [updateTicket] = useMutation(UPDATE_TIME_TICKET);
const { Enhanced_Payroll } = useTreatments(
["Enhanced_Payroll"],
{},
bodyshop.imexshopid
);
const { data: EmployeeAutoCompleteData } = useQuery(QUERY_ACTIVE_EMPLOYEES, { const { data: EmployeeAutoCompleteData } = useQuery(QUERY_ACTIVE_EMPLOYEES, {
skip: !timeTicketModal.visible, skip: !timeTicketModal.visible,
fetchPolicy: "network-only", fetchPolicy: "network-only",
@@ -78,6 +83,7 @@ export function TimeTicketModalContainer({
)[0].rate )[0].rate
: null, : null,
bodyshopid: bodyshop.id, bodyshopid: bodyshop.id,
created_by: timeTicketModal.context.created_by,
}, },
], ],
}, },
@@ -147,7 +153,7 @@ export function TimeTicketModalContainer({
if (!!changedFields.cost_center && !!EmployeeAutoCompleteData) { if (!!changedFields.cost_center && !!EmployeeAutoCompleteData) {
form.setFieldsValue({ form.setFieldsValue({
ciecacode: ciecacode:
bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber || Enhanced_Payroll.treatments === 'on'
? changedFields.cost_center ? changedFields.cost_center
: Object.keys( : Object.keys(
bodyshop.md_responsibility_centers.defaults.costs bodyshop.md_responsibility_centers.defaults.costs

View File

@@ -65,6 +65,21 @@ export function TimeTicektShiftContainer({
clockon: theTime, clockon: theTime,
date: theTime, date: theTime,
memo: values.memo, memo: values.memo,
created_by: isTechConsole
? currentUser.email.concat(
" | ",
technician.employee_number
.concat(
" ",
technician.first_name,
" ",
technician.last_name
)
.trim()
)
: currentUser.displayName
? currentUser.email.concat(" | ", currentUser.displayName)
: currentUser.email,
}, },
], ],
}, },

View File

@@ -74,7 +74,7 @@ export function TimeTicketTaskModalComponent({
<Form.Item dependencies={["task"]}> <Form.Item dependencies={["task"]}>
{() => { {() => {
const { task } = form.getFieldsValue(); const { task } = form.getFieldsValue();
const theTaskPreset = bodyshop.md_tasks_presets.presets.find( const theTaskPreset = bodyshop.md_tasks_presets?.presets?.find(
(tp) => tp.name === task (tp) => tp.name === task
); );

View File

@@ -57,6 +57,7 @@ export const GET_LINE_TICKET_BY_PK = gql`
actualhrs actualhrs
ciecacode ciecacode
cost_center cost_center
created_by
date date
id id
jobid jobid

View File

@@ -39,6 +39,7 @@ export const QUERY_TIME_TICKETS_IN_RANGE = gql`
clockon clockon
cost_center cost_center
created_at created_at
created_by
date date
id id
rate rate
@@ -85,6 +86,7 @@ export const QUERY_TIME_TICKETS_TECHNICIAN_IN_RANGE = gql`
clockon clockon
cost_center cost_center
created_at created_at
created_by
date date
id id
rate rate
@@ -119,6 +121,7 @@ export const QUERY_TIME_TICKETS_TECHNICIAN_IN_RANGE = gql`
clockon clockon
cost_center cost_center
created_at created_at
created_by
date date
id id
rate rate
@@ -160,6 +163,7 @@ export const QUERY_TIME_TICKETS_IN_RANGE_SB = gql`
clockon clockon
cost_center cost_center
created_at created_at
created_by
date date
id id
rate rate
@@ -194,6 +198,7 @@ export const QUERY_TIME_TICKETS_IN_RANGE_SB = gql`
clockon clockon
cost_center cost_center
created_at created_at
created_by
date date
id id
rate rate
@@ -223,6 +228,7 @@ export const INSERT_NEW_TIME_TICKET = gql`
insert_timetickets(objects: $timeTicketInput) { insert_timetickets(objects: $timeTicketInput) {
returning { returning {
id id
created_by
clockon clockon
clockoff clockoff
employeeid employeeid

View File

@@ -178,7 +178,7 @@ export function TechAssignedProdJobs({
}, },
}, },
{ {
title: t("jobs.labels.actions"), title: t("general.labels.actions"),
dataIndex: "actions", dataIndex: "actions",
key: "actions", key: "actions",
render: (text, record) => ( render: (text, record) => (

View File

@@ -2755,6 +2755,7 @@
"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. ",
"payall": "Error flagging hours. {{error}}",
"shiftalreadyclockedon": "You are already clocked onto a shift. Unable to create shift entry." "shiftalreadyclockedon": "You are already clocked onto a shift. Unable to create shift entry."
}, },
"fields": { "fields": {
@@ -2765,6 +2766,7 @@
"clockon": "Clocked In", "clockon": "Clocked In",
"committed": "Committed", "committed": "Committed",
"cost_center": "Cost Center", "cost_center": "Cost Center",
"created_by": "Created By",
"date": "Ticket Date", "date": "Ticket Date",
"efficiency": "Efficiency", "efficiency": "Efficiency",
"employee": "Employee", "employee": "Employee",
@@ -2805,7 +2807,8 @@
"clockedout": "Clocked out successfully.", "clockedout": "Clocked out successfully.",
"committed": "Time Tickets Committed Successfully", "committed": "Time Tickets Committed Successfully",
"created": "Time ticket entered successfully.", "created": "Time ticket entered successfully.",
"deleted": "Time ticket deleted successfully." "deleted": "Time ticket deleted successfully.",
"payall": "All hours paid out successfully."
}, },
"validation": { "validation": {
"clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.", "clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.",

View File

@@ -2755,6 +2755,7 @@
"deleting": "", "deleting": "",
"noemployeeforuser": "", "noemployeeforuser": "",
"noemployeeforuser_sub": "", "noemployeeforuser_sub": "",
"payall": "",
"shiftalreadyclockedon": "" "shiftalreadyclockedon": ""
}, },
"fields": { "fields": {
@@ -2765,6 +2766,7 @@
"clockon": "", "clockon": "",
"committed": "", "committed": "",
"cost_center": "", "cost_center": "",
"created_by": "",
"date": "", "date": "",
"efficiency": "", "efficiency": "",
"employee": "", "employee": "",
@@ -2805,7 +2807,8 @@
"clockedout": "", "clockedout": "",
"committed": "", "committed": "",
"created": "", "created": "",
"deleted": "" "deleted": "",
"payall": ""
}, },
"validation": { "validation": {
"clockoffmustbeafterclockon": "", "clockoffmustbeafterclockon": "",

View File

@@ -2755,6 +2755,7 @@
"deleting": "", "deleting": "",
"noemployeeforuser": "", "noemployeeforuser": "",
"noemployeeforuser_sub": "", "noemployeeforuser_sub": "",
"payall": "",
"shiftalreadyclockedon": "" "shiftalreadyclockedon": ""
}, },
"fields": { "fields": {
@@ -2765,6 +2766,7 @@
"clockon": "", "clockon": "",
"committed": "", "committed": "",
"cost_center": "", "cost_center": "",
"created_by": "",
"date": "", "date": "",
"efficiency": "", "efficiency": "",
"employee": "", "employee": "",
@@ -2805,7 +2807,8 @@
"clockedout": "", "clockedout": "",
"committed": "", "committed": "",
"created": "", "created": "",
"deleted": "" "deleted": "",
"payall": ""
}, },
"validation": { "validation": {
"clockoffmustbeafterclockon": "", "clockoffmustbeafterclockon": "",

View File

@@ -1049,7 +1049,7 @@ export const TemplateList = (type, context) => {
disabled: false, disabled: false,
rangeFilter: { rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"), object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_open"), field: i18n.t("jobs.fields.date_invoiced"),
}, },
group: "jobs", group: "jobs",
}, },

View File

@@ -5556,6 +5556,7 @@
- committed_at - committed_at
- cost_center - cost_center
- created_at - created_at
- created_by
- date - date
- employeeid - employeeid
- flat_rate - flat_rate
@@ -5580,6 +5581,7 @@
- committed_at - committed_at
- cost_center - cost_center
- created_at - created_at
- created_by
- date - date
- employeeid - employeeid
- flat_rate - flat_rate
@@ -5613,6 +5615,7 @@
- committed_at - committed_at
- cost_center - cost_center
- created_at - created_at
- created_by
- date - date
- employeeid - employeeid
- flat_rate - flat_rate

View File

@@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."timetickets" add column "created_by" text
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."timetickets" add column "created_by" text
null;

View File

@@ -656,6 +656,7 @@ exports.QUERY_EMPLOYEE_PIN = `query QUERY_EMPLOYEE_PIN($shopId: uuid!, $employee
employee_number employee_number
id id
pin pin
active
} }
}`; }`;

View File

@@ -32,7 +32,7 @@ exports.payall = async function (req, res) {
const { employeeHash, assignmentHash } = CalculateExpectedHoursForJob(job); const { employeeHash, assignmentHash } = CalculateExpectedHoursForJob(job);
const ticketHash = CalculateTicketsHoursForJob(job); const ticketHash = CalculateTicketsHoursForJob(job);
if (assignmentHash.unassigned > 0) { if (assignmentHash.unassigned > 0) {
res.json({ success: false, error: "Unassigned hours." }); res.json({ success: false, error: "Not all hours have been assigned." });
return; return;
} }
@@ -65,7 +65,7 @@ exports.payall = async function (req, res) {
cost_center: cost_center:
job.bodyshop.md_responsibility_centers.defaults.costs[key], job.bodyshop.md_responsibility_centers.defaults.costs[key],
flat_rate: true, flat_rate: true,
memo: `*SYS-PAY* Add unflagged hours. (${req.user.email})`, memo: `Add unflagged hours. (${req.user.email})`,
}); });
}); });
} else { } else {
@@ -83,7 +83,7 @@ exports.payall = async function (req, res) {
job.bodyshop.md_responsibility_centers.defaults.costs[ job.bodyshop.md_responsibility_centers.defaults.costs[
path.mod_lbr_ty path.mod_lbr_ty
], ],
memo: `*SYS-PAY* Add unflagged hours. (${req.user.email})`, memo: `Add unflagged hours. (${req.user.email})`,
}); });
} }
} else if (diff.op === "update") { } else if (diff.op === "update") {
@@ -102,7 +102,7 @@ exports.payall = async function (req, res) {
job.bodyshop.md_responsibility_centers.defaults.costs[ job.bodyshop.md_responsibility_centers.defaults.costs[
path.mod_lbr_ty path.mod_lbr_ty
], ],
memo: `*SYS-PAY* Adjust flagged hours per assignment. (${req.user.email})`, memo: `Adjust flagged hours per assignment. (${req.user.email})`,
}); });
} else { } else {
//Has to be a delete //Has to be a delete
@@ -124,7 +124,7 @@ exports.payall = async function (req, res) {
cost_center: cost_center:
job.bodyshop.md_responsibility_centers.defaults.costs[key], job.bodyshop.md_responsibility_centers.defaults.costs[key],
flat_rate: true, flat_rate: true,
memo: `*SYS-PAY* Remove flagged hours per assignment. (${req.user.email})`, memo: `Remove flagged hours per assignment. (${req.user.email})`,
}); });
}); });
} else { } else {
@@ -142,7 +142,7 @@ exports.payall = async function (req, res) {
path.mod_lbr_ty path.mod_lbr_ty
], ],
flat_rate: true, flat_rate: true,
memo: `*SYS-PAY* Remove flagged hours per assignment. (${req.user.email})`, memo: `Remove flagged hours per assignment. (${req.user.email})`,
}); });
} }
} }
@@ -163,10 +163,10 @@ exports.payall = async function (req, res) {
jobid, jobid,
{ {
jobid: jobid, jobid: jobid,
error, error: JSON.stringify(error),
} }
); );
res.status(503).send(); res.status(400).json({ error: error.message });
} }
}; };

View File

@@ -23,7 +23,7 @@ exports.techLogin = async (req, res) => {
let technician; let technician;
if (result.employees && result.employees[0]) { if (result.employees && result.employees[0]) {
const dbRecord = result.employees[0]; const dbRecord = result.employees[0];
if (dbRecord.pin === pin) { if (dbRecord.pin === pin && dbRecord.active === true) {
valid = true; valid = true;
delete dbRecord.pin; delete dbRecord.pin;
technician = dbRecord; technician = dbRecord;