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 8bbda03e1..34acb7994 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 @@ -9,10 +9,12 @@ import { createStructuredSelector } from "reselect"; import { auth, logImEXEvent } from "../../firebase/firebase.utils"; import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries"; import { UPDATE_JOB } from "../../graphql/jobs.queries"; +import { insertAuditTrail } from "../../redux/application/application.actions"; import { selectBodyshop, selectCurrentUser, } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; import client from "../../utils/GraphQLClient"; const mapStateToProps = createStructuredSelector({ @@ -20,6 +22,11 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, }); +const mapDispatchToProps = (dispatch) => ({ + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), +}); + function updateJobCache(items) { client.cache.modify({ id: "ROOT_QUERY", @@ -40,6 +47,7 @@ export function JobsCloseExportButton({ disabled, setSelectedJobs, refetch, + insertAuditTrail, }) { const history = useHistory(); const { t } = useTranslation(); @@ -181,6 +189,10 @@ export function JobsCloseExportButton({ key: "jobsuccessexport", message: t("jobs.successes.exported"), }); + insertAuditTrail({ + jobid: jobId, + operation: AuditTrailMapping.jobexported(), + }); updateJobCache( jobUpdateResponse.data.update_jobs.returning.map((job) => job.id) ); @@ -192,12 +204,20 @@ export function JobsCloseExportButton({ }); } } - if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) { + if ( + bodyshop.accountingconfig && + bodyshop.accountingconfig.qbo && + successfulTransactions.length > 0 + ) { notification.open({ type: "success", key: "jobsuccessexport", message: t("jobs.successes.exported"), }); + insertAuditTrail({ + jobid: jobId, + operation: AuditTrailMapping.jobexported(), + }); updateJobCache([ ...new Set( successfulTransactions.map( @@ -227,4 +247,7 @@ export function JobsCloseExportButton({ ); } -export default connect(mapStateToProps, null)(JobsCloseExportButton); +export default connect( + mapStateToProps, + mapDispatchToProps +)(JobsCloseExportButton); 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 3204d7311..2bb338d97 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 @@ -9,10 +9,12 @@ import { createStructuredSelector } from "reselect"; import { auth, logImEXEvent } from "../../firebase/firebase.utils"; import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries"; import { UPDATE_JOBS } from "../../graphql/jobs.queries"; +import { insertAuditTrail } from "../../redux/application/application.actions"; import { selectBodyshop, selectCurrentUser, } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; import client from "../../utils/GraphQLClient"; const mapStateToProps = createStructuredSelector({ @@ -20,6 +22,11 @@ const mapStateToProps = createStructuredSelector({ currentUser: selectCurrentUser, }); +const mapDispatchToProps = (dispatch) => ({ + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), +}); + function updateJobCache(items) { client.cache.modify({ id: "ROOT_QUERY", @@ -41,6 +48,7 @@ export function JobsExportAllButton({ loadingCallback, completedCallback, refetch, + insertAuditTrail, }) { const { t } = useTranslation(); const [updateJob] = useMutation(UPDATE_JOBS); @@ -177,6 +185,12 @@ export function JobsExportAllButton({ key: "jobsuccessexport", message: t("jobs.successes.exported"), }); + jobUpdateResponse.data.update_jobs.returning.forEach((job) => { + insertAuditTrail({ + jobid: job.id, + operation: AuditTrailMapping.jobexported(), + }); + }); updateJobCache( jobUpdateResponse.data.update_jobs.returning.map( (job) => job.id @@ -190,13 +204,17 @@ export function JobsExportAllButton({ }); } } - if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && successfulTransactions.length > 0) { + if ( + bodyshop.accountingconfig && + bodyshop.accountingconfig.qbo && + successfulTransactions.length > 0 + ) { notification.open({ type: "success", key: "jobsuccessexport", message: t("jobs.successes.exported"), }); - updateJobCache([ + const successfulTransactionsSet = [ ...new Set( successfulTransactions.map( (st) => @@ -207,7 +225,14 @@ export function JobsExportAllButton({ ] ) ), - ]); + ]; + if (successfulTransactionsSet.length > 0) { + insertAuditTrail({ + jobid: successfulTransactionsSet[0], + operation: AuditTrailMapping.jobexported(), + }); + } + updateJobCache(successfulTransactionsSet); } } }) @@ -225,4 +250,7 @@ export function JobsExportAllButton({ ); } -export default connect(mapStateToProps, null)(JobsExportAllButton); +export default connect( + mapStateToProps, + mapDispatchToProps +)(JobsExportAllButton); diff --git a/client/src/pages/dms/dms.container.jsx b/client/src/pages/dms/dms.container.jsx index 77c670e60..9ed0133a9 100644 --- a/client/src/pages/dms/dms.container.jsx +++ b/client/src/pages/dms/dms.container.jsx @@ -26,10 +26,12 @@ import { OwnerNameDisplayFunction } from "../../components/owner-name-display/ow import { auth } from "../../firebase/firebase.utils"; import { QUERY_JOB_EXPORT_DMS } from "../../graphql/jobs.queries"; import { + insertAuditTrail, setBreadcrumbs, setSelectedHeader, } from "../../redux/application/application.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -38,6 +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 })), }); export default connect(mapStateToProps, mapDispatchToProps)(DmsContainer); @@ -46,7 +50,7 @@ export const socket = SocketIO( process.env.NODE_ENV === "production" ? process.env.REACT_APP_AXIOS_BASE_API_URL : window.location.origin, - // "http://localhost:4000", // for dev testing, + // "http://localhost:4000", // for dev testing, { path: "/ws", withCredentials: true, @@ -57,7 +61,12 @@ export const socket = SocketIO( } ); -export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) { +export function DmsContainer({ + bodyshop, + setBreadcrumbs, + setSelectedHeader, + insertAuditTrail, +}) { const { t } = useTranslation(); const [logLevel, setLogLevel] = useState("DEBUG"); const history = useHistory(); @@ -115,6 +124,10 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) { notification.success({ message: t("jobs.successes.exported"), }); + insertAuditTrail({ + jobid: payload, + operation: AuditTrailMapping.jobexported(), + }); history.push("/manage/accounting/receivables"); }); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index c7259897e..9edefeaeb 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -115,6 +115,7 @@ "jobassignmentremoved": "Employee assignment removed for {{operation}}", "jobchecklist": "Checklist type \"{{type}}\" completed. In production set to {{inproduction}}. Status set to {{status}}.", "jobconverted": "Job converted and assigned number {{ro_number}}.", + "jobexported": "Job has been exported.", "jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.", "jobimported": "Job imported.", "jobinproductionchange": "Job production status set to {{inproduction}}", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index ed7cc4efa..2a1e1be9b 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -115,6 +115,7 @@ "jobassignmentremoved": "", "jobchecklist": "", "jobconverted": "", + "jobexported": "", "jobfieldchanged": "", "jobimported": "", "jobinproductionchange": "", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 638b7d0d6..d2cacffeb 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -115,6 +115,7 @@ "jobassignmentremoved": "", "jobchecklist": "", "jobconverted": "", + "jobexported": "", "jobfieldchanged": "", "jobimported": "", "jobinproductionchange": "", diff --git a/client/src/utils/AuditTrailMappings.js b/client/src/utils/AuditTrailMappings.js index 757bdd43c..4ad405f0a 100644 --- a/client/src/utils/AuditTrailMappings.js +++ b/client/src/utils/AuditTrailMappings.js @@ -35,6 +35,7 @@ const AuditTrailMapping = { i18n.t("audit_trail.messages.jobchecklist", { type, inproduction, status }), jobconverted: (ro_number) => i18n.t("audit_trail.messages.jobconverted", { ro_number }), + jobexported: () => i18n.t("audit_trail.messages.jobexported"), jobfieldchange: (field, value) => i18n.t("audit_trail.messages.jobfieldchanged", { field, value }), jobimported: () => i18n.t("audit_trail.messages.jobimported"),