diff --git a/_reference/reportFiltersAndSorters.md b/_reference/reportFiltersAndSorters.md index 2aea3f11a..0b5b16aaf 100644 --- a/_reference/reportFiltersAndSorters.md +++ b/_reference/reportFiltersAndSorters.md @@ -59,7 +59,7 @@ Filters can make use of reflection to pre-fill select boxes, the following is an "type": "internal", "name": "special.job_statuses" } - }, + } ``` in this example, a reflector with the type 'internal' (all types at the moment require this, and it is used for future functionality), with a name of `special.job_statuses` @@ -74,9 +74,13 @@ The following cases are available - `special.employees` - This will reflect the employees `bodyshop.employees` - `special.first_names` - This will reflect the first names `bodyshop.employees` - `special.last_names` - This will reflect the last names `bodyshop.employees` -- `special.referral_sources` - This will reflect the referral sources `bodyshop.md_referral_sources +- `special.referral_sources` - This will reflect the referral sources `bodyshop.md_referral_sources` - `special.class`- This will reflect the class `bodyshop.md_classes` -- +- `special.lost_sale_reasons` - This will reflect the lost sale reasons `bodyshop.md_lost_sale_reasons` +- `special.alt_transports` - This will reflect the alternative transports `bodyshop.appt_alt_transport` +- `special.payment_types` - This will reflect the payment types `bodyshop.md_payment_types` +- `special.payment_payers` - This is a special case with a key value set of [Customer, Insurance] + ### Path without brackets, multi level `"name": "jobs.joblines.mod_lb_hrs",` @@ -156,6 +160,7 @@ query gendoc_hours_sold_detail_open($starttz: timestamptz!, $endtz: timestamptz! - Do not add the ability to filter things that are already filtered as part of the original query, this would be redundant and could cause issues. - Do not add the ability to filter on things like FK constraints, must like the above example. +- *INHERITANCE CAVEAT* If you have a filters file on a parent report that has a child that you do not want the filters inherited from, you must place a blank filters file (valid json so {}) on the child report level. This will than fetch the child filters, which are empty and move along, versus inheriting the parent filters. ## Sorters diff --git a/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx b/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx index 260589c2f..1110ddc37 100644 --- a/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx +++ b/client/src/components/accounting-payables-table/accounting-payables-table.component.jsx @@ -1,21 +1,21 @@ -import { Input, Table, Checkbox, Card, Space } from "antd"; +import { Card, Checkbox, Input, Space, Table } from "antd"; +import queryString from "query-string"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; -import { Link } from "react-router-dom"; -import CurrencyFormatter from "../../utils/CurrencyFormatter"; -import { alphaSort, dateSort } from "../../utils/sorters"; -import PayableExportButton from "../payable-export-button/payable-export-button.component"; -import PayableExportAll from "../payable-export-all-button/payable-export-all-button.component"; -import { DateFormatter } from "../../utils/DateFormatter"; -import queryString from "query-string"; -import { logImEXEvent } from "../../firebase/firebase.utils"; -import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; import { connect } from "react-redux"; +import { Link } from "react-router-dom"; import { createStructuredSelector } from "reselect"; +import { logImEXEvent } from "../../firebase/firebase.utils"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import CurrencyFormatter from "../../utils/CurrencyFormatter"; +import { DateFormatter } from "../../utils/DateFormatter"; +import { pageLimit } from "../../utils/config"; +import { alphaSort, dateSort } from "../../utils/sorters"; import ExportLogsCountDisplay from "../export-logs-count-display/export-logs-count-display.component"; +import PayableExportAll from "../payable-export-all-button/payable-export-all-button.component"; +import PayableExportButton from "../payable-export-button/payable-export-button.component"; import BillMarkSelectedExported from "../payable-mark-selected-exported/payable-mark-selected-exported.component"; -import {pageLimit} from "../../utils/config"; +import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -138,7 +138,6 @@ export function AccountingPayablesTableComponent({ title: t("exportlogs.labels.attempts"), dataIndex: "attempts", key: "attempts", - render: (text, record) => ( ), @@ -147,8 +146,6 @@ export function AccountingPayablesTableComponent({ title: t("general.labels.actions"), dataIndex: "actions", key: "actions", - sorter: (a, b) => a.clm_total - b.clm_total, - render: (text, record) => ( alphaSort(a.job.ownr_ln, b.job.ownr_ln), + sorter: (a, b) => + alphaSort( + OwnerNameDisplayFunction(a.job), + OwnerNameDisplayFunction(b.job) + ), sortOrder: state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, render: (text, record) => { @@ -94,6 +100,9 @@ export function AccountingPayablesTableComponent({ title: t("payments.fields.amount"), dataIndex: "amount", key: "amount", + sorter: (a, b) => a.amount - b.amount, + sortOrder: + state.sortedInfo.columnKey === "amount" && state.sortedInfo.order, render: (text, record) => ( {record.amount} ), @@ -112,18 +121,21 @@ export function AccountingPayablesTableComponent({ title: t("payments.fields.created_at"), dataIndex: "created_at", key: "created_at", + sorter: (a, b) => dateSort(a.created_at, b.created_at), + sortOrder: + state.sortedInfo.columnKey === "created_at" && state.sortedInfo.order, render: (text, record) => ( {record.created_at} ), }, - { - title: t("payments.fields.exportedat"), - dataIndex: "exportedat", - key: "exportedat", - render: (text, record) => ( - {record.exportedat} - ), - }, + // { + // title: t("payments.fields.exportedat"), + // dataIndex: "exportedat", + // key: "exportedat", + // render: (text, record) => ( + // {record.exportedat} + // ), + // }, { title: t("exportlogs.labels.attempts"), dataIndex: "attempts", @@ -137,8 +149,6 @@ export function AccountingPayablesTableComponent({ title: t("general.labels.actions"), dataIndex: "actions", key: "actions", - sorter: (a, b) => a.clm_total - b.clm_total, - render: (text, record) => ( a.status - b.status, + sorter: (a, b) => statusSort(a, b, bodyshop.md_ro_statuses.statuses), sortOrder: state.sortedInfo.columnKey === "status" && state.sortedInfo.order, }, @@ -83,7 +85,8 @@ export function AccountingReceivablesTableComponent({ title: t("jobs.fields.owner"), dataIndex: "owner", key: "owner", - sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), + sorter: (a, b) => + alphaSort(OwnerNameDisplayFunction(a), OwnerNameDisplayFunction(b)), sortOrder: state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, render: (text, record) => { @@ -103,6 +106,15 @@ export function AccountingReceivablesTableComponent({ dataIndex: "vehicle", key: "vehicle", ellipsis: true, + sorter: (a, b) => + alphaSort( + `${a.v_model_yr || ""} ${a.v_make_desc || ""} ${ + a.v_model_desc || "" + }`, + `${b.v_model_yr || ""} ${b.v_make_desc || ""} ${b.v_model_desc || ""}` + ), + sortOrder: + state.sortedInfo.columnKey === "vehicle" && state.sortedInfo.order, render: (text, record) => { return record.vehicleid ? ( diff --git a/client/src/components/bill-delete-button/bill-delete-button.component.jsx b/client/src/components/bill-delete-button/bill-delete-button.component.jsx index ca3f3822d..0e30cabad 100644 --- a/client/src/components/bill-delete-button/bill-delete-button.component.jsx +++ b/client/src/components/bill-delete-button/bill-delete-button.component.jsx @@ -12,8 +12,8 @@ import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component"; const mapStateToProps = createStructuredSelector({}); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect(mapStateToProps, mapDispatchToProps)(BillDeleteButton); @@ -51,6 +51,7 @@ export function BillDeleteButton({ bill, jobid, callback, insertAuditTrail }) { insertAuditTrail({ jobid: jobid, operation: AuditTrailMapping.billdeleted(bill.invoice_number), + type: "billdeleted", }); if (callback && typeof callback === "function") callback(bill.id); diff --git a/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx b/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx index 12ca80301..93d115254 100644 --- a/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx +++ b/client/src/components/bill-detail-edit/bill-detail-edit-component.jsx @@ -33,8 +33,8 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ setPartsOrderContext: (context) => dispatch(setModalContext({ context: context, modal: "partsOrder" })), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect( @@ -150,6 +150,7 @@ export function BillDetailEditcontainer({ jobid: bill.jobid, billid: search.billid, operation: AuditTrailMapping.billupdated(bill.invoice_number), + type: "billupdated", }); await refetch(); diff --git a/client/src/components/bill-detail-edit/bill-detail-edit-return.component.jsx b/client/src/components/bill-detail-edit/bill-detail-edit-return.component.jsx index 81571f8b0..3935fc5f2 100644 --- a/client/src/components/bill-detail-edit/bill-detail-edit-return.component.jsx +++ b/client/src/components/bill-detail-edit/bill-detail-edit-return.component.jsx @@ -16,8 +16,8 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ setPartsOrderContext: (context) => dispatch(setModalContext({ context: context, modal: "partsOrder" })), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect( 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 c106a8c4c..b75d51d14 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 @@ -37,8 +37,8 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ toggleModalVisible: () => dispatch(toggleModalVisible("billEnter")), - insertAuditTrail: ({ jobid, billid, operation }) => - dispatch(insertAuditTrail({ jobid, billid, operation })), + insertAuditTrail: ({ jobid, billid, operation, type }) => + dispatch(insertAuditTrail({ jobid, billid, operation, type })), }); const Templates = TemplateList("job_special"); @@ -171,6 +171,7 @@ function BillEnterModalContainer({ mod_lbr_ty: key, hours: adjustmentsToInsert[key].toFixed(1), }), + type: "jobmodifylbradj", }); }); @@ -320,6 +321,7 @@ function BillEnterModalContainer({ operation: AuditTrailMapping.billposted( r1.data.insert_bills.returning[0].invoice_number ), + type: "billposted", }); if (enterAgain) { diff --git a/client/src/components/card-payment-modal/card-payment-modal.component..jsx b/client/src/components/card-payment-modal/card-payment-modal.component..jsx index 071e2a758..a1e0b2461 100644 --- a/client/src/components/card-payment-modal/card-payment-modal.component..jsx +++ b/client/src/components/card-payment-modal/card-payment-modal.component..jsx @@ -37,8 +37,8 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), toggleModalVisible: () => dispatch(toggleModalVisible("cardPayment")), }); @@ -102,6 +102,7 @@ const CardPaymentModalComponent = ({ insertAuditTrail({ jobid: payment.jobid, operation: AuditTrailMapping.failedpayment(), + type: "failedpayment", }) ); }); diff --git a/client/src/components/job-at-change/schedule-event.container.jsx b/client/src/components/job-at-change/schedule-event.container.jsx index 60abf9c61..f51d4379a 100644 --- a/client/src/components/job-at-change/schedule-event.container.jsx +++ b/client/src/components/job-at-change/schedule-event.container.jsx @@ -53,6 +53,7 @@ export default function ScheduleEventContainer({ bodyshop, event, refetch }) { insertAuditTrail({ jobid: event.job.id, operation: AuditTrailMapping.appointmentcancel(lost_sale_reason), + type: "appointmentcancel", }) ); } diff --git a/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx b/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx index a809100a6..eae9b707b 100644 --- a/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx +++ b/client/src/components/job-checklist/components/job-checklist-form/job-checklist-form.component.jsx @@ -28,8 +28,8 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function JobChecklistForm({ @@ -183,6 +183,7 @@ export function JobChecklistForm({ (type === "intake" && bodyshop.md_ro_statuses.default_arrived) || (type === "deliver" && bodyshop.md_ro_statuses.default_delivered) ), + type: "jobchecklist", }); } else { notification["error"]({ diff --git a/client/src/components/job-employee-assignments/job-employee-assignments.container.jsx b/client/src/components/job-employee-assignments/job-employee-assignments.container.jsx index 71e56c53c..a5feb3fa7 100644 --- a/client/src/components/job-employee-assignments/job-employee-assignments.container.jsx +++ b/client/src/components/job-employee-assignments/job-employee-assignments.container.jsx @@ -14,8 +14,8 @@ const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect( mapStateToProps, @@ -46,6 +46,7 @@ export function JobEmployeeAssignmentsContainer({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.jobassignmentchange(operation, name), + type: "jobassignmentchange", }); if (!!result.errors) { @@ -76,6 +77,7 @@ export function JobEmployeeAssignmentsContainer({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.jobassignmentremoved(operation), + type: "jobassignmentremoved", }); setLoading(false); }; diff --git a/client/src/components/job-line-convert-to-labor/job-line-convert-to-labor.component.jsx b/client/src/components/job-line-convert-to-labor/job-line-convert-to-labor.component.jsx index dea8e5dcc..80ecffdc2 100644 --- a/client/src/components/job-line-convert-to-labor/job-line-convert-to-labor.component.jsx +++ b/client/src/components/job-line-convert-to-labor/job-line-convert-to-labor.component.jsx @@ -28,8 +28,8 @@ const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect( mapStateToProps, @@ -113,6 +113,7 @@ export function JobLineConvertToLabor({ hours: calculateAdjustment({ mod_lbr_ty, job, jobline }).toFixed(1), mod_lbr_ty, }), + type: "jobmodifylbradj", }); setLoading(false); setVisibility(false); diff --git a/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx b/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx index 54a020d37..995da5ba0 100644 --- a/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx +++ b/client/src/components/jobs-admin-change-status/jobs-admin-change.status.component.jsx @@ -14,8 +14,8 @@ const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminStatus); @@ -32,6 +32,7 @@ export function JobsAdminStatus({ insertAuditTrail, bodyshop, job }) { insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.admin_jobstatuschange(status), + type: "admin_jobstatuschange", }); // refetch(); }) diff --git a/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx b/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx index 5ac31da74..4e038dcb8 100644 --- a/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx +++ b/client/src/components/jobs-admin-dates/jobs-admin-dates.component.jsx @@ -20,8 +20,8 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect( @@ -57,6 +57,7 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) { ? DateTimeFormat(changedAuditFields[key]) : changedAuditFields[key] ), + type: "admin_jobfieldchange", }); }); diff --git a/client/src/components/jobs-admin-mark-reexport/jobs-admin-mark-reexport.component.jsx b/client/src/components/jobs-admin-mark-reexport/jobs-admin-mark-reexport.component.jsx index 98f5c65d5..f59c6f7d6 100644 --- a/client/src/components/jobs-admin-mark-reexport/jobs-admin-mark-reexport.component.jsx +++ b/client/src/components/jobs-admin-mark-reexport/jobs-admin-mark-reexport.component.jsx @@ -23,8 +23,8 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect( mapStateToProps, @@ -59,6 +59,7 @@ export function JobAdminMarkReexport({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.admin_jobmarkforreexport(), + type: "admin_jobmarkforreexport", }); } else { notification["error"]({ @@ -99,6 +100,7 @@ export function JobAdminMarkReexport({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.admin_jobmarkexported(), + type: "admin_jobmarkexported", }); } else { notification["error"]({ @@ -124,6 +126,7 @@ export function JobAdminMarkReexport({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.admin_jobuninvoice(), + type: "admin_jobuninvoice", }); } else { notification["error"]({ diff --git a/client/src/components/jobs-admin-remove-ar/jobs-admin-remove-ar.component.jsx b/client/src/components/jobs-admin-remove-ar/jobs-admin-remove-ar.component.jsx index f1bda15ce..86aa54c01 100644 --- a/client/src/components/jobs-admin-remove-ar/jobs-admin-remove-ar.component.jsx +++ b/client/src/components/jobs-admin-remove-ar/jobs-admin-remove-ar.component.jsx @@ -10,8 +10,8 @@ import AuditTrailMapping from "../../utils/AuditTrailMappings"; const mapStateToProps = createStructuredSelector({}); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminRemoveAR); @@ -34,6 +34,7 @@ export function JobsAdminRemoveAR({ insertAuditTrail, job }) { insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.admin_job_remove_from_ar(value), + type: "admin_job_remove_from_ar", }); setSwitchValue(value); } else { diff --git a/client/src/components/jobs-admin-unvoid/jobs-admin-unvoid.component.jsx b/client/src/components/jobs-admin-unvoid/jobs-admin-unvoid.component.jsx index 2094178c4..2b79a406a 100644 --- a/client/src/components/jobs-admin-unvoid/jobs-admin-unvoid.component.jsx +++ b/client/src/components/jobs-admin-unvoid/jobs-admin-unvoid.component.jsx @@ -17,8 +17,8 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect(mapStateToProps, mapDispatchToProps)(JobsAdminUnvoid); @@ -49,6 +49,7 @@ export function JobsAdminUnvoid({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.admin_jobunvoid(), + type: "admin_jobunvoid", }); } else { notification["error"]({ diff --git a/client/src/components/jobs-available-table/jobs-available-table.container.jsx b/client/src/components/jobs-available-table/jobs-available-table.container.jsx index bbad59845..20efbe600 100644 --- a/client/src/components/jobs-available-table/jobs-available-table.container.jsx +++ b/client/src/components/jobs-available-table/jobs-available-table.container.jsx @@ -47,8 +47,8 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function JobsAvailableContainer({ bodyshop, @@ -190,6 +190,7 @@ export function JobsAvailableContainer({ insertAuditTrail({ jobid: r.data.insert_jobs.returning[0].id, operation: AuditTrailMapping.jobimported(), + type: "jobimported", }); deleteJob({ @@ -350,6 +351,7 @@ export function JobsAvailableContainer({ insertAuditTrail({ jobid: selectedJob, operation: AuditTrailMapping.jobsupplement(), + type: "jobsupplement", }); } }; diff --git a/client/src/components/jobs-change-status/jobs-change-status.component.jsx b/client/src/components/jobs-change-status/jobs-change-status.component.jsx index aa5f61fc2..12eb9d8ea 100644 --- a/client/src/components/jobs-change-status/jobs-change-status.component.jsx +++ b/client/src/components/jobs-change-status/jobs-change-status.component.jsx @@ -16,8 +16,8 @@ const mapStateToProps = createStructuredSelector({ jobRO: selectJobReadOnly, }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function JobsChangeStatus({ job, bodyshop, jobRO, insertAuditTrail }) { @@ -35,6 +35,7 @@ export function JobsChangeStatus({ job, bodyshop, jobRO, insertAuditTrail }) { insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.jobstatuschange(status), + type: "jobstatuschange", }); // refetch(); }) diff --git a/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx b/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx index 34acb7994..df598b409 100644 --- a/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx +++ b/client/src/components/jobs-close-export-button/jobs-close-export-button.component.jsx @@ -23,8 +23,8 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); function updateJobCache(items) { @@ -192,6 +192,7 @@ export function JobsCloseExportButton({ insertAuditTrail({ jobid: jobId, operation: AuditTrailMapping.jobexported(), + type: "jobexported", }); updateJobCache( jobUpdateResponse.data.update_jobs.returning.map((job) => job.id) @@ -217,6 +218,7 @@ export function JobsCloseExportButton({ insertAuditTrail({ jobid: jobId, operation: AuditTrailMapping.jobexported(), + type: "jobexported", }); updateJobCache([ ...new Set( diff --git a/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx b/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx index 543ad36ca..e72f26720 100644 --- a/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx +++ b/client/src/components/jobs-convert-button/jobs-convert-button.component.jsx @@ -25,8 +25,8 @@ const mapStateToProps = createStructuredSelector({ jobRO: selectJobReadOnly, }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function JobsConvertButton({ @@ -78,6 +78,7 @@ export function JobsConvertButton({ operation: AuditTrailMapping.jobconverted( res.data.update_jobs.returning[0].ro_number ), + type: "jobconverted", }); setVisible(false); diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.addtoproduction.util.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.addtoproduction.util.jsx index 90c8ebd8b..2aa592763 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.addtoproduction.util.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.addtoproduction.util.jsx @@ -29,6 +29,7 @@ export default function AddToProduction( insertAuditTrail({ jobid: jobId, operation: AuditTrailMapping.jobinproductionchange(!remove), + type: "jobinproductionchange", }) ); if (completionCallback) completionCallback(); diff --git a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx index bc76f668e..76a093822 100644 --- a/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx +++ b/client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx @@ -52,8 +52,8 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(setModalContext({ context: context, modal: "timeTicket" })), setCardPaymentContext: (context) => dispatch(setModalContext({ context: context, modal: "cardPayment" })), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function JobsDetailHeaderActions({ @@ -115,6 +115,7 @@ export function JobsDetailHeaderActions({ ? !job.production_vars.alert : true ), + type: "alertToggle", }); }; @@ -134,6 +135,7 @@ export function JobsDetailHeaderActions({ operation: AuditTrailMapping.jobsuspend( !!job.suspended ? !job.suspended : true ), + type: "jobsuspend", }); }; @@ -190,6 +192,7 @@ export function JobsDetailHeaderActions({ jobid: job.id, operation: AuditTrailMapping.appointmentcancel(lost_sale_reason), + type: "appointmentcancel", }); return; } @@ -549,6 +552,7 @@ export function JobsDetailHeaderActions({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.jobvoid(), + type: "jobvoid", }); //go back to jobs list. history.push(`/manage/`); diff --git a/client/src/components/jobs-export-all-button/jobs-export-all-button.component.jsx b/client/src/components/jobs-export-all-button/jobs-export-all-button.component.jsx index 2bb338d97..25a08fb88 100644 --- a/client/src/components/jobs-export-all-button/jobs-export-all-button.component.jsx +++ b/client/src/components/jobs-export-all-button/jobs-export-all-button.component.jsx @@ -23,8 +23,8 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); function updateJobCache(items) { @@ -189,6 +189,7 @@ export function JobsExportAllButton({ insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.jobexported(), + type: "jobexported", }); }); updateJobCache( @@ -230,6 +231,7 @@ export function JobsExportAllButton({ insertAuditTrail({ jobid: successfulTransactionsSet[0], operation: AuditTrailMapping.jobexported(), + type: "jobexported", }); } updateJobCache(successfulTransactionsSet); diff --git a/client/src/components/jobs-list/jobs-list.component.jsx b/client/src/components/jobs-list/jobs-list.component.jsx index 68b3f3425..94024bccc 100644 --- a/client/src/components/jobs-list/jobs-list.component.jsx +++ b/client/src/components/jobs-list/jobs-list.component.jsx @@ -21,6 +21,7 @@ import useLocalStorage from "../../utils/useLocalStorage"; import AlertComponent from "../alert/alert.component"; import ChatOpenButton from "../chat-open-button/chat-open-button.component"; import OwnerNameDisplay from "../owner-name-display/owner-name-display.component"; +import { OwnerNameDisplayFunction } from "./../owner-name-display/owner-name-display.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -145,7 +146,8 @@ export function JobsList({ bodyshop }) { key: "owner", ellipsis: true, responsive: ["md"], - sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), + sorter: (a, b) => + alphaSort(OwnerNameDisplayFunction(a), OwnerNameDisplayFunction(b)), sortOrder: state.sortedInfo.columnKey === "owner" && state.sortedInfo.order, render: (text, record) => { @@ -188,7 +190,8 @@ export function JobsList({ bodyshop }) { dataIndex: "status", key: "status", ellipsis: true, - sorter: (a, b) => alphaSort(a.status, b.status), + sorter: (a, b) => + statusSort(a.status, b.status, bodyshop.md_ro_statuses.active_statuses), sortOrder: state.sortedInfo.columnKey === "status" && state.sortedInfo.order, filteredValue: filter?.status || null, @@ -219,6 +222,15 @@ export function JobsList({ bodyshop }) { dataIndex: "vehicle", key: "vehicle", ellipsis: true, + sorter: (a, b) => + alphaSort( + `${a.v_model_yr || ""} ${a.v_make_desc || ""} ${ + a.v_model_desc || "" + }`, + `${b.v_model_yr || ""} ${b.v_make_desc || ""} ${b.v_model_desc || ""}` + ), + sortOrder: + state.sortedInfo.columnKey === "vehicle" && state.sortedInfo.order, render: (text, record) => { return record.vehicleid ? ( alphaSort(a.ins_co_nm, b.ins_co_nm), + sortOrder: + state.sortedInfo.columnKey === "ins_co_nm" && state.sortedInfo.order, filteredValue: filter?.ins_co_nm || null, filters: (jobs && @@ -302,6 +317,13 @@ export function JobsList({ bodyshop }) { key: "estimator", ellipsis: true, responsive: ["xl"], + sorter: (a, b) => + alphaSort( + `${a.est_ct_fn || ""} ${a.est_ct_ln || ""}`.trim(), + `${b.est_ct_fn || ""} ${b.est_ct_ln || ""}`.trim() + ), + sortOrder: + state.sortedInfo.columnKey === "estimator" && state.sortedInfo.order, filterSearch: true, filteredValue: filter?.estimator || null, filters: diff --git a/client/src/components/jobs-notes/jobs-notes.container.jsx b/client/src/components/jobs-notes/jobs-notes.container.jsx index f62a219cb..897435c4b 100644 --- a/client/src/components/jobs-notes/jobs-notes.container.jsx +++ b/client/src/components/jobs-notes/jobs-notes.container.jsx @@ -19,8 +19,8 @@ const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect(mapStateToProps, mapDispatchToProps)(JobNotesContainer); @@ -49,6 +49,7 @@ export function JobNotesContainer({ jobId, insertAuditTrail }) { insertAuditTrail({ jobid: jobId, operation: AuditTrailMapping.jobnotedeleted(), + type: "jobnotedeleted", }); }); setDeleteLoading(false); diff --git a/client/src/components/labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component.jsx b/client/src/components/labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component.jsx index 5d5a56d2c..5978c8019 100644 --- a/client/src/components/labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component.jsx +++ b/client/src/components/labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component.jsx @@ -20,8 +20,8 @@ const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect( mapStateToProps, @@ -76,6 +76,7 @@ export function LaborAllocationsAdjustmentEdit({ values.hours - ((adjustments && adjustments[mod_lbr_ty]) || 0).toFixed(1), }), + type: "jobmodifylbradj", }); } setLoading(false); diff --git a/client/src/components/note-upsert-modal/note-upsert-modal.container.jsx b/client/src/components/note-upsert-modal/note-upsert-modal.container.jsx index f925b7100..2b9e27439 100644 --- a/client/src/components/note-upsert-modal/note-upsert-modal.container.jsx +++ b/client/src/components/note-upsert-modal/note-upsert-modal.container.jsx @@ -19,8 +19,8 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ toggleModalVisible: () => dispatch(toggleModalVisible("noteUpsert")), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function NoteUpsertModalContainer({ @@ -70,6 +70,7 @@ export function NoteUpsertModalContainer({ insertAuditTrail({ jobid: context.jobId, operation: AuditTrailMapping.jobnoteupdated(), + type: "jobnoteupdated", }); }); if (refetch) refetch(); @@ -102,6 +103,7 @@ export function NoteUpsertModalContainer({ insertAuditTrail({ jobid: newJobId, operation: AuditTrailMapping.jobnoteadded(), + type: "jobnoteadded", }); }); } @@ -115,6 +117,7 @@ export function NoteUpsertModalContainer({ insertAuditTrail({ jobid: context.jobId, operation: AuditTrailMapping.jobnoteadded(), + type: "jobnoteadded", }); } }; diff --git a/client/src/components/parts-order-modal/parts-order-modal.container.jsx b/client/src/components/parts-order-modal/parts-order-modal.container.jsx index 0f30012a3..b7edad316 100644 --- a/client/src/components/parts-order-modal/parts-order-modal.container.jsx +++ b/client/src/components/parts-order-modal/parts-order-modal.container.jsx @@ -1,12 +1,16 @@ -import { useMutation, useQuery, useApolloClient } from "@apollo/client"; +import { useApolloClient, useMutation, useQuery } from "@apollo/client"; +import { useTreatments } from "@splitsoftware/splitio-react"; import { Form, Modal, notification } from "antd"; +import axios from "axios"; +import _ from "lodash"; import moment from "moment"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; -import { logImEXEvent, auth } from "../../firebase/firebase.utils"; +import { auth, logImEXEvent } from "../../firebase/firebase.utils"; import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries"; +import { UPDATE_JOB } from "../../graphql/jobs.queries"; import { INSERT_NEW_PARTS_ORDERS, QUERY_PARTS_ORDER_OEC, @@ -29,10 +33,6 @@ import { TemplateList } from "../../utils/TemplateConstants"; import AlertComponent from "../alert/alert.component"; import LoadingSpinner from "../loading-spinner/loading-spinner.component"; import PartsOrderModalComponent from "./parts-order-modal.component"; -import axios from "axios"; -import { useTreatments } from "@splitsoftware/splitio-react"; -import _ from "lodash"; -import { UPDATE_JOB } from "../../graphql/jobs.queries"; const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, @@ -45,8 +45,8 @@ const mapDispatchToProps = (dispatch) => ({ toggleModalVisible: () => dispatch(toggleModalVisible("partsOrder")), setBillEnterContext: (context) => dispatch(setModalContext({ context: context, modal: "billEnter" })), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function PartsOrderModalContainer({ @@ -142,6 +142,7 @@ export function PartsOrderModalContainer({ : AuditTrailMapping.jobspartsorder( insertResult.data.insert_parts_orders.returning[0].order_number ), + type: isReturn ? "jobspartsreturn" : "jobspartsorder", }); const jobLinesResult = await updateJobLines({ diff --git a/client/src/components/phonebook-form/phonebook-form.component.jsx b/client/src/components/phonebook-form/phonebook-form.component.jsx index e40096ce9..4795c14ad 100644 --- a/client/src/components/phonebook-form/phonebook-form.component.jsx +++ b/client/src/components/phonebook-form/phonebook-form.component.jsx @@ -1,6 +1,12 @@ import { Button, Form, Input, PageHeader, Space } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { + selectAuthLevel, + selectBodyshop, +} from "../../redux/user/user.selectors"; import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component"; import FormItemEmail from "../form-items-formatted/email-form-item.component"; import PhoneFormItem, { @@ -8,12 +14,6 @@ import PhoneFormItem, { } from "../form-items-formatted/phone-form-item.component"; import LayoutFormRow from "../layout-form-row/layout-form-row.component"; import { HasRbacAccess } from "../rbac-wrapper/rbac-wrapper.component"; -import { connect } from "react-redux"; -import { createStructuredSelector } from "reselect"; -import { - selectAuthLevel, - selectBodyshop, -} from "../../redux/user/user.selectors"; const mapStateToProps = createStructuredSelector({ authLevel: selectAuthLevel, bodyshop: selectBodyshop, @@ -46,13 +46,19 @@ export function PhonebookFormComponent({ return (
+ {() => + `${form.getFieldValue("firstname") || ""} ${ + form.getFieldValue("lastname") || "" + }${ + form.getFieldValue("company") + ? ` - ${form.getFieldValue("company")}` + : "" + }` + } + + } extra={