Compare commits
11 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10fceb7ddf | ||
|
|
6c1a0cff8d | ||
|
|
ba683a2e8a | ||
|
|
5209c12b89 | ||
|
|
bf7aa17f65 | ||
|
|
cd6e0dcde3 | ||
|
|
a2822f5592 | ||
|
|
ca129fa4a0 | ||
|
|
de92b2d47e | ||
|
|
5d7384aa8b | ||
|
|
bf18e687da |
@@ -1,10 +1,9 @@
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import Icon, {
|
||||
BankFilled,
|
||||
BarChartOutlined,
|
||||
CarFilled,
|
||||
ClockCircleFilled,
|
||||
CheckCircleOutlined,
|
||||
ClockCircleFilled,
|
||||
DashboardFilled,
|
||||
DollarCircleFilled,
|
||||
ExportOutlined,
|
||||
@@ -26,6 +25,7 @@ import Icon, {
|
||||
UnorderedListOutlined,
|
||||
UserOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import { Layout, Menu } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -252,7 +252,11 @@ function Header({
|
||||
onClick={() => {
|
||||
setTimeTicketContext({
|
||||
actions: {},
|
||||
context: {},
|
||||
context: {
|
||||
created_by: currentUser.displayName
|
||||
? currentUser.email.concat(" | ", currentUser.displayName)
|
||||
: currentUser.email,
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import { alphaSort, statusSort } from "../../utils/sorters";
|
||||
import OwnerDetailUpdateJobsComponent from "../owner-detail-update-jobs/owner-detail-update-jobs.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -15,6 +16,15 @@ const mapStateToProps = createStructuredSelector({
|
||||
function OwnerDetailJobsComponent({ bodyshop, owner }) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedJobs, setSelectedJobs] = useState([]);
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {},
|
||||
filteredInfo: { text: "" },
|
||||
});
|
||||
|
||||
const handleTableChange = (pagination, filters, sorter) => {
|
||||
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: t("jobs.fields.ro_number"),
|
||||
@@ -26,6 +36,9 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
|
||||
{record.ro_number || t("general.labels.na")}
|
||||
</Link>
|
||||
),
|
||||
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.vehicle"),
|
||||
@@ -46,11 +59,17 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
|
||||
title: t("jobs.fields.clm_no"),
|
||||
dataIndex: "clm_no",
|
||||
key: "clm_no",
|
||||
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.status"),
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
sorter: (a, b) => statusSort(a.status, b.status, bodyshop.md_ro_statuses.statuses),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||
},
|
||||
|
||||
{
|
||||
@@ -60,6 +79,9 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
|
||||
render: (text, record) => (
|
||||
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
|
||||
),
|
||||
sorter: (a, b) => a.clm_total - b.clm_total,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -80,6 +102,7 @@ function OwnerDetailJobsComponent({ bodyshop, owner }) {
|
||||
scroll={{ x: true }}
|
||||
rowKey="id"
|
||||
dataSource={owner.jobs}
|
||||
onChange={handleTableChange}
|
||||
rowSelection={{
|
||||
onSelect: (record, selected, selectedRows) => {
|
||||
setSelectedJobs(selectedRows ? selectedRows.map((i) => i.id) : []);
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import { Button, Card, Form, notification, Space } from "antd";
|
||||
import axios from "axios";
|
||||
import moment from "moment";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
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 { 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";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
technician: selectTechnician,
|
||||
bodyshop: selectBodyshop,
|
||||
currentUser: selectCurrentUser,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setTimeTicketContext: (context) =>
|
||||
@@ -25,6 +29,7 @@ export function TechClockInContainer({
|
||||
setTimeTicketContext,
|
||||
technician,
|
||||
bodyshop,
|
||||
currentUser,
|
||||
}) {
|
||||
console.log(
|
||||
"🚀 ~ file: tech-job-clock-in-form.container.jsx:29 ~ technician:",
|
||||
@@ -66,6 +71,12 @@ export function TechClockInContainer({
|
||||
values.cost_center
|
||||
);
|
||||
}),
|
||||
created_by: currentUser.email.concat(
|
||||
" | ",
|
||||
technician.employee_number
|
||||
.concat(" ", technician.first_name, " ", technician.last_name)
|
||||
.trim()
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -100,6 +111,17 @@ export function TechClockInContainer({
|
||||
employeeid: technician.id,
|
||||
flat_rate: emps.flat_rate,
|
||||
},
|
||||
created_by: currentUser.email.concat(
|
||||
" | ",
|
||||
technician.employee_number
|
||||
.concat(
|
||||
" ",
|
||||
technician.first_name,
|
||||
" ",
|
||||
technician.last_name
|
||||
)
|
||||
.trim()
|
||||
),
|
||||
},
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -9,9 +9,10 @@ import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
selectAuthLevel,
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import { onlyUnique } from "../../utils/arrayHelper";
|
||||
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
|
||||
import { onlyUnique } from "../../utils/arrayHelper";
|
||||
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||
import RbacWrapper, {
|
||||
HasRbacAccess,
|
||||
@@ -20,6 +21,7 @@ import TimeTicketEnterButton from "../time-ticket-enter-button/time-ticket-enter
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
authLevel: selectAuthLevel,
|
||||
currentUser: selectCurrentUser,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
@@ -29,6 +31,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(TimeTicketList);
|
||||
export function TimeTicketList({
|
||||
bodyshop,
|
||||
authLevel,
|
||||
currentUser,
|
||||
disabled,
|
||||
loading,
|
||||
timetickets,
|
||||
@@ -193,7 +196,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: t("general.labels.actions"),
|
||||
dataIndex: "actions",
|
||||
@@ -254,7 +265,12 @@ export function TimeTicketList({
|
||||
(techConsole ? null : (
|
||||
<TimeTicketEnterButton
|
||||
actions={{ refetch }}
|
||||
context={{ jobId: jobId }}
|
||||
context={{
|
||||
jobId: jobId,
|
||||
created_by: currentUser.displayName
|
||||
? currentUser.email.concat(" | ", currentUser.displayName)
|
||||
: currentUser.email,
|
||||
}}
|
||||
disabled={disabled}
|
||||
>
|
||||
{t("timetickets.actions.enter")}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
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 React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
@@ -77,6 +77,7 @@ export function TimeTicketModalContainer({
|
||||
)[0].rate
|
||||
: null,
|
||||
bodyshopid: bodyshop.id,
|
||||
created_by: timeTicketModal.context.created_by,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -65,6 +65,21 @@ export function TimeTicektShiftContainer({
|
||||
clockon: theTime,
|
||||
date: theTime,
|
||||
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,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -6,8 +6,9 @@ import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
|
||||
import { alphaSort, statusSort } from "../../utils/sorters";
|
||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
import VehicleDetailUpdateJobsComponent from "../vehicle-detail-update-jobs/vehicle-detail-update-jobs.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -16,6 +17,14 @@ const mapStateToProps = createStructuredSelector({
|
||||
export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
|
||||
const { t } = useTranslation();
|
||||
const [selectedJobs, setSelectedJobs] = useState([]);
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {},
|
||||
filteredInfo: { text: "" },
|
||||
});
|
||||
|
||||
const handleTableChange = (pagination, filters, sorter) => {
|
||||
setState({ ...state, filteredInfo: filters, sortedInfo: sorter });
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
@@ -28,6 +37,9 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
|
||||
{record.ro_number || t("general.labels.na")}
|
||||
</Link>
|
||||
),
|
||||
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "ro_number" && state.sortedInfo.order,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.owner"),
|
||||
@@ -43,11 +55,17 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
|
||||
title: t("jobs.fields.clm_no"),
|
||||
dataIndex: "clm_no",
|
||||
key: "clm_no",
|
||||
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "clm_no" && state.sortedInfo.order,
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.status"),
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
sorter: (a, b) => statusSort(a.status, b.status, bodyshop.md_ro_statuses.statuses),
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||
},
|
||||
|
||||
{
|
||||
@@ -57,6 +75,9 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
|
||||
render: (text, record) => (
|
||||
<CurrencyFormatter>{record.clm_total}</CurrencyFormatter>
|
||||
),
|
||||
sorter: (a, b) => a.clm_total - b.clm_total,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "clm_total" && state.sortedInfo.order,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -76,6 +97,7 @@ export function VehicleDetailJobsComponent({ vehicle, bodyshop }) {
|
||||
rowKey="id"
|
||||
scroll={{ x: true }}
|
||||
dataSource={vehicle.jobs}
|
||||
onChange={handleTableChange}
|
||||
rowSelection={{
|
||||
onSelect: (record, selected, selectedRows) => {
|
||||
setSelectedJobs(selectedRows ? selectedRows.map((i) => i.id) : []);
|
||||
|
||||
@@ -57,6 +57,7 @@ export const GET_LINE_TICKET_BY_PK = gql`
|
||||
actualhrs
|
||||
ciecacode
|
||||
cost_center
|
||||
created_by
|
||||
date
|
||||
id
|
||||
jobid
|
||||
|
||||
@@ -69,7 +69,7 @@ export const QUERY_OWNER_BY_ID = gql`
|
||||
preferred_contact
|
||||
note
|
||||
tax_number
|
||||
jobs {
|
||||
jobs(order_by: { date_open: desc }) {
|
||||
id
|
||||
ro_number
|
||||
clm_no
|
||||
|
||||
@@ -37,6 +37,7 @@ export const QUERY_TIME_TICKETS_IN_RANGE = gql`
|
||||
clockon
|
||||
cost_center
|
||||
created_at
|
||||
created_by
|
||||
date
|
||||
id
|
||||
rate
|
||||
@@ -80,6 +81,7 @@ export const QUERY_TIME_TICKETS_TECHNICIAN_IN_RANGE = gql`
|
||||
clockon
|
||||
cost_center
|
||||
created_at
|
||||
created_by
|
||||
date
|
||||
id
|
||||
rate
|
||||
@@ -112,6 +114,7 @@ export const QUERY_TIME_TICKETS_TECHNICIAN_IN_RANGE = gql`
|
||||
clockon
|
||||
cost_center
|
||||
created_at
|
||||
created_by
|
||||
date
|
||||
id
|
||||
rate
|
||||
@@ -151,6 +154,7 @@ export const QUERY_TIME_TICKETS_IN_RANGE_SB = gql`
|
||||
clockon
|
||||
cost_center
|
||||
created_at
|
||||
created_by
|
||||
date
|
||||
id
|
||||
rate
|
||||
@@ -181,6 +185,7 @@ export const QUERY_TIME_TICKETS_IN_RANGE_SB = gql`
|
||||
clockon
|
||||
cost_center
|
||||
created_at
|
||||
created_by
|
||||
date
|
||||
id
|
||||
rate
|
||||
@@ -210,6 +215,7 @@ export const INSERT_NEW_TIME_TICKET = gql`
|
||||
insert_timetickets(objects: $timeTicketInput) {
|
||||
returning {
|
||||
id
|
||||
created_by
|
||||
clockon
|
||||
clockoff
|
||||
employeeid
|
||||
|
||||
@@ -28,11 +28,10 @@ export const QUERY_VEHICLE_BY_ID = gql`
|
||||
updated_at
|
||||
trim_color
|
||||
notes
|
||||
jobs {
|
||||
jobs(order_by: { date_open: desc }) {
|
||||
id
|
||||
ro_number
|
||||
ownr_fn
|
||||
|
||||
ownr_ln
|
||||
owner {
|
||||
id
|
||||
|
||||
@@ -2730,6 +2730,7 @@
|
||||
"clockon": "Clocked In",
|
||||
"committed": "",
|
||||
"cost_center": "Cost Center",
|
||||
"created_by": "Created By",
|
||||
"date": "Ticket Date",
|
||||
"efficiency": "Efficiency",
|
||||
"employee": "Employee",
|
||||
|
||||
@@ -2730,6 +2730,7 @@
|
||||
"clockon": "",
|
||||
"committed": "",
|
||||
"cost_center": "",
|
||||
"created_by": "",
|
||||
"date": "",
|
||||
"efficiency": "",
|
||||
"employee": "",
|
||||
|
||||
@@ -2730,6 +2730,7 @@
|
||||
"clockon": "",
|
||||
"committed": "",
|
||||
"cost_center": "",
|
||||
"created_by": "",
|
||||
"date": "",
|
||||
"efficiency": "",
|
||||
"employee": "",
|
||||
|
||||
@@ -1040,7 +1040,7 @@ export const TemplateList = (type, context) => {
|
||||
disabled: false,
|
||||
rangeFilter: {
|
||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||
field: i18n.t("jobs.fields.date_open"),
|
||||
field: i18n.t("jobs.fields.date_invoiced"),
|
||||
},
|
||||
group: "jobs",
|
||||
},
|
||||
|
||||
@@ -4649,6 +4649,7 @@
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
allow_aggregations: true
|
||||
update_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -4726,6 +4727,7 @@
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
allow_aggregations: true
|
||||
update_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -5554,6 +5556,7 @@
|
||||
- committed_at
|
||||
- cost_center
|
||||
- created_at
|
||||
- created_by
|
||||
- date
|
||||
- employeeid
|
||||
- flat_rate
|
||||
@@ -5578,6 +5581,7 @@
|
||||
- committed_at
|
||||
- cost_center
|
||||
- created_at
|
||||
- created_by
|
||||
- date
|
||||
- employeeid
|
||||
- flat_rate
|
||||
@@ -5611,6 +5615,7 @@
|
||||
- committed_at
|
||||
- cost_center
|
||||
- created_at
|
||||
- created_by
|
||||
- date
|
||||
- employeeid
|
||||
- flat_rate
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
DROP INDEX IF EXISTS "public"."parts_dispatch_employeeid";
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE INDEX "parts_dispatch_employeeid" on
|
||||
"public"."parts_dispatch" using btree ("employeeid");
|
||||
@@ -0,0 +1 @@
|
||||
DROP INDEX IF EXISTS "public"."parts_dispatch_dispatchid";
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE INDEX "parts_dispatch_dispatchid" on
|
||||
"public"."parts_dispatch_lines" using btree ("partsdispatchid");
|
||||
@@ -0,0 +1 @@
|
||||
DROP INDEX IF EXISTS "public"."parts_dispatch_line_accepted_at";
|
||||
@@ -0,0 +1,2 @@
|
||||
CREATE INDEX "parts_dispatch_line_accepted_at" on
|
||||
"public"."parts_dispatch_lines" using btree ("accepted_at");
|
||||
@@ -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;
|
||||
@@ -0,0 +1,2 @@
|
||||
alter table "public"."timetickets" add column "created_by" text
|
||||
null;
|
||||
Reference in New Issue
Block a user