From fa7d90d2a9d1f571d60483d2edce1c3d04a39ecf Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Tue, 5 Mar 2024 15:28:22 -0800 Subject: [PATCH] IO-2651 Audit Log Extension Signed-off-by: Allan Carr --- .../bill-delete-button.component.jsx | 5 +-- .../bill-detail-edit-component.jsx | 5 +-- .../bill-detail-edit-return.component.jsx | 4 +-- .../bill-enter-modal.container.jsx | 6 ++-- .../card-payment-modal.component..jsx | 5 +-- .../schedule-event.container.jsx | 1 + .../job-checklist-form.component.jsx | 5 +-- .../job-employee-assignments.container.jsx | 6 ++-- .../job-line-convert-to-labor.component.jsx | 5 +-- .../jobs-admin-change.status.component.jsx | 5 +-- .../jobs-admin-dates.component.jsx | 5 +-- .../jobs-admin-mark-reexport.component.jsx | 7 +++-- .../jobs-admin-remove-ar.component.jsx | 5 +-- .../jobs-admin-unvoid.component.jsx | 5 +-- .../jobs-available-table.container.jsx | 6 ++-- .../jobs-change-status.component.jsx | 5 +-- .../jobs-close-export-button.component.jsx | 6 ++-- .../jobs-convert-button.component.jsx | 5 +-- ...il-header-actions.addtoproduction.util.jsx | 1 + .../jobs-detail-header-actions.component.jsx | 8 +++-- .../jobs-export-all-button.component.jsx | 6 ++-- .../jobs-notes/jobs-notes.container.jsx | 5 +-- ...-allocations-adjustment-edit.component.jsx | 5 +-- .../note-upsert-modal.container.jsx | 7 +++-- .../parts-order-modal.container.jsx | 17 +++++----- .../production-board-kanban.component.jsx | 5 +-- ...roduction-list-columns.alert.component.jsx | 5 +-- ...n-list-columns.empassignment.component.jsx | 8 +++-- ...roduction-list-columns.status.category.jsx | 4 +-- ...oduction-list-columns.status.component.jsx | 7 +++-- .../schedule-job-modal.container.jsx | 5 +-- client/src/graphql/audit_trail.queries.js | 1 + client/src/pages/dms/dms.container.jsx | 5 +-- .../pages/jobs-close/jobs-close.component.jsx | 7 +++-- .../jobs-detail.page.component.jsx | 31 ++++++++++++------- .../redux/application/application.actions.js | 4 +-- .../redux/application/application.sagas.js | 3 +- hasura/metadata/tables.yaml | 20 ++++++------ .../down.sql | 4 +++ .../up.sql | 2 ++ 40 files changed, 157 insertions(+), 94 deletions(-) create mode 100644 hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/down.sql create mode 100644 hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/up.sql 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-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/production-board-kanban/production-board-kanban.component.jsx b/client/src/components/production-board-kanban/production-board-kanban.component.jsx index 9421de918..0895e8c7f 100644 --- a/client/src/components/production-board-kanban/production-board-kanban.component.jsx +++ b/client/src/components/production-board-kanban/production-board-kanban.component.jsx @@ -29,8 +29,8 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function ProductionBoardKanbanComponent({ @@ -133,6 +133,7 @@ export function ProductionBoardKanbanComponent({ insertAuditTrail({ jobid: card.id, operation: AuditTrailMapping.jobstatuschange(destination.toColumnId), + type: "jobstatuschange", }); if (update.errors) { diff --git a/client/src/components/production-list-columns/production-list-columns.alert.component.jsx b/client/src/components/production-list-columns/production-list-columns.alert.component.jsx index 8bad135ca..f362eab5b 100644 --- a/client/src/components/production-list-columns/production-list-columns.alert.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.alert.component.jsx @@ -13,8 +13,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 function ProductionListColumnAlert({ record, insertAuditTrail }) { @@ -46,6 +46,7 @@ export function ProductionListColumnAlert({ record, insertAuditTrail }) { ? !record.production_vars.alert : true ), + type: "alertToggle", }).then(() => { if (record.refetch) record.refetch(); }); diff --git a/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx b/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx index e2ed28896..f3603c666 100644 --- a/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.empassignment.component.jsx @@ -3,12 +3,12 @@ import { useMutation } from "@apollo/client"; import { Button, Col, - notification, Popover, Row, Select, Space, Spin, + notification, } from "antd"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; @@ -25,8 +25,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 function ProductionListEmpAssignment({ @@ -55,6 +55,7 @@ export function ProductionListEmpAssignment({ insertAuditTrail({ jobid: record.id, operation: AuditTrailMapping.jobassignmentchange(empAssignment, name), + type: "jobassignmentchange", }); if (!!result.errors) { @@ -80,6 +81,7 @@ export function ProductionListEmpAssignment({ insertAuditTrail({ jobid: record.id, operation: AuditTrailMapping.jobassignmentremoved(empAssignment), + type: "jobassignmentremoved", }); if (!!result.errors) { diff --git a/client/src/components/production-list-columns/production-list-columns.status.category.jsx b/client/src/components/production-list-columns/production-list-columns.status.category.jsx index 115b69a3f..d49f1f348 100644 --- a/client/src/components/production-list-columns/production-list-columns.status.category.jsx +++ b/client/src/components/production-list-columns/production-list-columns.status.category.jsx @@ -12,8 +12,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 function ProductionListColumnCategory({ record, bodyshop }) { const [updateJob] = useMutation(UPDATE_JOB); diff --git a/client/src/components/production-list-columns/production-list-columns.status.component.jsx b/client/src/components/production-list-columns/production-list-columns.status.component.jsx index e29ffdbeb..b122bd3ae 100644 --- a/client/src/components/production-list-columns/production-list-columns.status.component.jsx +++ b/client/src/components/production-list-columns/production-list-columns.status.component.jsx @@ -5,16 +5,16 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; -import { selectBodyshop } from "../../redux/user/user.selectors"; import { insertAuditTrail } from "../../redux/application/application.actions"; +import { selectBodyshop } from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings"; 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 function ProductionListColumnStatus({ record, @@ -40,6 +40,7 @@ export function ProductionListColumnStatus({ insertAuditTrail({ jobid: record.id, operation: AuditTrailMapping.jobstatuschange(key), + type: "jobstatuschange", }); setLoading(false); diff --git a/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx b/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx index 19d6d4a37..c5a781fc0 100644 --- a/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx +++ b/client/src/components/schedule-job-modal/schedule-job-modal.container.jsx @@ -34,8 +34,8 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ toggleModalVisible: () => dispatch(toggleModalVisible("schedule")), setEmailOptions: (e) => dispatch(setEmailOptions(e)), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function ScheduleJobModalContainer({ @@ -146,6 +146,7 @@ export function ScheduleJobModalContainer({ operation: AuditTrailMapping.appointmentinsert( DateTimeFormat(values.start) ), + type: "appointmentinsert", }); } diff --git a/client/src/graphql/audit_trail.queries.js b/client/src/graphql/audit_trail.queries.js index 793cc0001..29891412c 100644 --- a/client/src/graphql/audit_trail.queries.js +++ b/client/src/graphql/audit_trail.queries.js @@ -40,6 +40,7 @@ export const INSERT_AUDIT_TRAIL = gql` bodyshopid created operation + type useremail } } diff --git a/client/src/pages/dms/dms.container.jsx b/client/src/pages/dms/dms.container.jsx index 9ed0133a9..32d48b55c 100644 --- a/client/src/pages/dms/dms.container.jsx +++ b/client/src/pages/dms/dms.container.jsx @@ -40,8 +40,8 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), setSelectedHeader: (key) => dispatch(setSelectedHeader(key)), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export default connect(mapStateToProps, mapDispatchToProps)(DmsContainer); @@ -127,6 +127,7 @@ export function DmsContainer({ insertAuditTrail({ jobid: payload, operation: AuditTrailMapping.jobexported(), + type: "jobexported", }); history.push("/manage/accounting/receivables"); }); diff --git a/client/src/pages/jobs-close/jobs-close.component.jsx b/client/src/pages/jobs-close/jobs-close.component.jsx index b6feb3ff5..b95d72a7d 100644 --- a/client/src/pages/jobs-close/jobs-close.component.jsx +++ b/client/src/pages/jobs-close/jobs-close.component.jsx @@ -47,11 +47,11 @@ const mapStateToProps = createStructuredSelector({ }); const mapDispatchToProps = (dispatch) => ({ - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); -export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, }) { +export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail }) { const { t } = useTranslation(); const [form] = Form.useForm(); const client = useApolloClient(); @@ -121,6 +121,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, }) insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.jobinvoiced(), + type: "jobinvoiced", }); // history.push(`/manage/jobs/${job.id}`); } else { diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index 89a912242..ec383d6a7 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -29,6 +29,7 @@ import { createStructuredSelector } from "reselect"; import FormFieldsChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component"; import JobAuditTrail from "../../components/job-audit-trail/job-audit-trail.component"; import JobsLinesContainer from "../../components/job-detail-lines/job-lines.container"; +import JobLifecycleComponent from "../../components/job-lifecycle/job-lifecycle.component"; import JobLineUpsertModalContainer from "../../components/job-lines-upsert-modal/job-lines-upsert-modal.container"; import JobReconciliationModal from "../../components/job-reconciliation-modal/job-reconciliation.modal.container"; import JobSyncButton from "../../components/job-sync-button/job-sync-button.component"; @@ -54,7 +55,6 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings"; import UndefinedToNull from "../../utils/undefinedtonull"; import { DateTimeFormat } from "./../../utils/DateFormatter"; -import JobLifecycleComponent from "../../components/job-lifecycle/job-lifecycle.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -63,8 +63,8 @@ const mapStateToProps = createStructuredSelector({ const mapDispatchToProps = (dispatch) => ({ setPrintCenterContext: (context) => dispatch(setModalContext({ context: context, modal: "printCenter" })), - insertAuditTrail: ({ jobid, operation }) => - dispatch(insertAuditTrail({ jobid, operation })), + insertAuditTrail: ({ jobid, operation, type }) => + dispatch(insertAuditTrail({ jobid, operation, type })), }); export function JobsDetailPage({ bodyshop, @@ -177,6 +177,7 @@ export function JobsDetailPage({ ? DateTimeFormat(changedAuditFields[key]) : changedAuditFields[key] ), + type: "jobfieldchange", }); }); @@ -334,15 +335,23 @@ export function JobsDetailPage({ > - {t('menus.jobsdetail.lifecycle')}} - key="lifecycle" - > - - + + + {t("menus.jobsdetail.lifecycle")} + + } + key="lifecycle" + > + + - diff --git a/client/src/redux/application/application.actions.js b/client/src/redux/application/application.actions.js index 88e23ad66..40b97e168 100644 --- a/client/src/redux/application/application.actions.js +++ b/client/src/redux/application/application.actions.js @@ -54,9 +54,9 @@ export const setOnline = (isOnline) => ({ payload: isOnline, }); -export const insertAuditTrail = ({ jobid, billid, operation }) => ({ +export const insertAuditTrail = ({ jobid, billid, operation, type }) => ({ type: ApplicationActionTypes.INSERT_AUDIT_TRAIL, - payload: { jobid, billid, operation }, + payload: { jobid, billid, operation, type }, }); export const setProblemJobs = (problemJobs) => ({ type: ApplicationActionTypes.SET_PROBLEM_JOBS, diff --git a/client/src/redux/application/application.sagas.js b/client/src/redux/application/application.sagas.js index fed628415..dc907da74 100644 --- a/client/src/redux/application/application.sagas.js +++ b/client/src/redux/application/application.sagas.js @@ -266,7 +266,7 @@ export function* onInsertAuditTrail() { } export function* insertAuditTrailSaga({ - payload: { jobid, billid, operation }, + payload: { jobid, billid, operation, type }, }) { const state = yield select(); const bodyshop = state.user.bodyshop; @@ -278,6 +278,7 @@ export function* insertAuditTrailSaga({ jobid, billid, operation, + type, useremail: currentUser.email, }, }; diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index 17ccc52a9..587fa8ac3 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -259,28 +259,30 @@ - active: _eq: true columns: - - id + - billid + - bodyshopid - created - - operation + - id + - jobid - new_val - old_val + - operation + - type - useremail - - bodyshopid - - jobid - - billid select_permissions: - role: user permission: columns: + - billid + - bodyshopid + - created - id + - jobid - new_val - old_val - operation + - type - useremail - - created - - billid - - bodyshopid - - jobid filter: bodyshop: associations: diff --git a/hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/down.sql b/hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/down.sql new file mode 100644 index 000000000..cc828330e --- /dev/null +++ b/hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/down.sql @@ -0,0 +1,4 @@ +-- Could not auto-generate a down migration. +-- Please write an appropriate down migration for the SQL below: +-- alter table "public"."audit_trail" add column "type" text +-- null; diff --git a/hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/up.sql b/hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/up.sql new file mode 100644 index 000000000..6653b7b7f --- /dev/null +++ b/hasura/migrations/1709671738458_alter_table_public_audit_trail_add_column_type/up.sql @@ -0,0 +1,2 @@ +alter table "public"."audit_trail" add column "type" text + null;