From 1ff5ed414168c55a28c8fc2e3625a5edb4483055 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 20 Dec 2023 11:36:42 -0800 Subject: [PATCH 1/2] IO-1366 Audit Logging for Production Alert --- .../jobs-detail-header-actions.component.jsx | 8 +++++ ...roduction-list-columns.alert.component.jsx | 30 +++++++++++++++++-- client/src/translations/en_us/common.json | 1 + client/src/translations/es/common.json | 1 + client/src/translations/fr/common.json | 1 + client/src/utils/AuditTrailMappings.js | 1 + 6 files changed, 39 insertions(+), 3 deletions(-) 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 ae3ba9a7b..bf0b049fb 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 @@ -108,6 +108,14 @@ export function JobsDetailHeaderActions({ }, }, }); + insertAuditTrail({ + jobid: job.id, + operation: AuditTrailMapping.alertToggle( + !!job.production_vars && !!job.production_vars.alert + ? !job.production_vars.alert + : true + ), + }); }; const handleSuspend = (e) => { 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 8823afb46..8bad135ca 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 @@ -1,12 +1,23 @@ import { ExclamationCircleFilled } from "@ant-design/icons"; +import { useMutation } from "@apollo/client"; import { Dropdown, Menu } from "antd"; import React from "react"; import { useTranslation } from "react-i18next"; -import { useMutation } from "@apollo/client"; -import { UPDATE_JOB } from "../../graphql/jobs.queries"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.utils"; +import { UPDATE_JOB } from "../../graphql/jobs.queries"; +import { insertAuditTrail } from "../../redux/application/application.actions"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; -export default function ProductionListColumnAlert({ record }) { +const mapStateToProps = createStructuredSelector({}); + +const mapDispatchToProps = (dispatch) => ({ + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), +}); + +export function ProductionListColumnAlert({ record, insertAuditTrail }) { const { t } = useTranslation(); const [updateAlert] = useMutation(UPDATE_JOB); @@ -27,6 +38,14 @@ export default function ProductionListColumnAlert({ record }) { }, }, }, + }); + insertAuditTrail({ + jobid: record.id, + operation: AuditTrailMapping.alertToggle( + !!record.production_vars && !!record.production_vars.alert + ? !record.production_vars.alert + : true + ), }).then(() => { if (record.refetch) record.refetch(); }); @@ -58,3 +77,8 @@ export default function ProductionListColumnAlert({ record }) { ); } + +export default connect( + mapStateToProps, + mapDispatchToProps +)(ProductionListColumnAlert); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index bbac4cc7b..d8a8da68a 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -103,6 +103,7 @@ "admin_jobmarkforreexport": "ADMIN: Job marked for re-export.", "admin_jobuninvoice": "ADMIN: Job has been uninvoiced.", "admin_jobunvoid": "ADMIN: Job has been unvoided.", + "alerttoggle": "Alert Toggle set to {{status}}", "appointmentcancel": "Appointment canceled. Lost Reason: {{lost_sale_reason}}.", "appointmentinsert": "Appointment created. Appointment Date: {{start}}.", "billposted": "Bill with invoice number {{invoice_number}} posted.", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 33cf621da..4049e024b 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -103,6 +103,7 @@ "admin_jobmarkforreexport": "", "admin_jobuninvoice": "", "admin_jobunvoid": "", + "alerttoggle": "", "appointmentcancel": "", "appointmentinsert": "", "billposted": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 3b5251fa7..2f55093e1 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -103,6 +103,7 @@ "admin_jobmarkforreexport": "", "admin_jobuninvoice": "", "admin_jobunvoid": "", + "alerttoggle": "", "appointmentcancel": "", "appointmentinsert": "", "billposted": "", diff --git a/client/src/utils/AuditTrailMappings.js b/client/src/utils/AuditTrailMappings.js index afa0de1e5..edfebdab1 100644 --- a/client/src/utils/AuditTrailMappings.js +++ b/client/src/utils/AuditTrailMappings.js @@ -1,6 +1,7 @@ import i18n from "i18next"; const AuditTrailMapping = { + alertToggle: (status) => i18n.t("audit_trail.messages.alerttoggle", { status }), appointmentcancel: (lost_sale_reason) => i18n.t("audit_trail.messages.appointmentcancel", { lost_sale_reason }), appointmentinsert: (start) => From 482b03c2d19ef46fe8dbd9c50b4b39a7f9d9b329 Mon Sep 17 00:00:00 2001 From: Allan Carr Date: Wed, 20 Dec 2023 11:52:04 -0800 Subject: [PATCH 2/2] IO-1366 Invoice Job Audit Trail --- .../pages/jobs-close/jobs-close.component.jsx | 16 ++++++++++++++-- client/src/translations/en_us/common.json | 1 + client/src/translations/es/common.json | 1 + client/src/translations/fr/common.json | 1 + client/src/utils/AuditTrailMappings.js | 2 ++ 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/client/src/pages/jobs-close/jobs-close.component.jsx b/client/src/pages/jobs-close/jobs-close.component.jsx index 91c8c7385..b6feb3ff5 100644 --- a/client/src/pages/jobs-close/jobs-close.component.jsx +++ b/client/src/pages/jobs-close/jobs-close.component.jsx @@ -36,14 +36,22 @@ import JobsCloseLines from "../../components/jobs-close-lines/jobs-close-lines.c import LayoutFormRow from "../../components/layout-form-row/layout-form-row.component"; import { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.queries"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; +import { insertAuditTrail } from "../../redux/application/application.actions"; import { selectJobReadOnly } from "../../redux/application/application.selectors"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; + const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, jobRO: selectJobReadOnly, }); -export function JobsCloseComponent({ job, bodyshop, jobRO }) { +const mapDispatchToProps = (dispatch) => ({ + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), +}); + +export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, }) { const { t } = useTranslation(); const [form] = Form.useForm(); const client = useApolloClient(); @@ -110,6 +118,10 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) { notification["success"]({ message: t("jobs.successes.closed"), }); + insertAuditTrail({ + jobid: job.id, + operation: AuditTrailMapping.jobinvoiced(), + }); // history.push(`/manage/jobs/${job.id}`); } else { setLoading(false); @@ -527,4 +539,4 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) { ); } -export default connect(mapStateToProps, null)(JobsCloseComponent); +export default connect(mapStateToProps, mapDispatchToProps)(JobsCloseComponent); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index d8a8da68a..cf55cfeb2 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -112,6 +112,7 @@ "jobassignmentchange": "Employee {{name}} assigned to {{operation}}", "jobassignmentremoved": "Employee assignment removed for {{operation}}", "jobchecklist": "Checklist type \"{{type}}\" completed. In production set to {{inproduction}}. Status set to {{status}}.", + "jobinvoiced": "Job has been invoiced.", "jobconverted": "Job converted and assigned number {{ro_number}}.", "jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.", "jobimported": "Job imported.", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 4049e024b..fd3bebe6f 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -112,6 +112,7 @@ "jobassignmentchange": "", "jobassignmentremoved": "", "jobchecklist": "", + "jobinvoiced": "", "jobconverted": "", "jobfieldchanged": "", "jobimported": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 2f55093e1..dab607ebc 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -112,6 +112,7 @@ "jobassignmentchange": "", "jobassignmentremoved": "", "jobchecklist": "", + "jobinvoiced": "", "jobconverted": "", "jobfieldchanged": "", "jobimported": "", diff --git a/client/src/utils/AuditTrailMappings.js b/client/src/utils/AuditTrailMappings.js index edfebdab1..d7098fa2d 100644 --- a/client/src/utils/AuditTrailMappings.js +++ b/client/src/utils/AuditTrailMappings.js @@ -12,6 +12,8 @@ const AuditTrailMapping = { "ADMIN: " + i18n.t("audit_trail.messages.jobstatuschange", { status }), jobsupplement: () => i18n.t("audit_trail.messages.jobsupplement"), jobimported: () => i18n.t("audit_trail.messages.jobimported"), + jobinvoiced: () => + i18n.t("audit_trail.messages.jobinvoiced"), jobconverted: (ro_number) => i18n.t("audit_trail.messages.jobconverted", { ro_number }), jobfieldchange: (field, value) =>