From ae8a924cd6e46d326e1bdda649dd34855a8ffab4 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Wed, 28 Jul 2021 16:31:32 -0700 Subject: [PATCH 1/3] IO-1273 Resolve dashboard error 2 --- .../projected-monthly-sales.component.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/client/src/components/dashboard-components/pojected-monthly-sales/projected-monthly-sales.component.jsx b/client/src/components/dashboard-components/pojected-monthly-sales/projected-monthly-sales.component.jsx index 3bc1dcc76..abe4b9485 100644 --- a/client/src/components/dashboard-components/pojected-monthly-sales/projected-monthly-sales.component.jsx +++ b/client/src/components/dashboard-components/pojected-monthly-sales/projected-monthly-sales.component.jsx @@ -15,7 +15,11 @@ export default function DashboardProjectedMonthlySales({ data, ...cardProps }) { data.projected_monthly_sales.reduce( (acc, val) => acc.add( - Dinero(val.job_totals.totals && val.job_totals.totals.subtotal) + Dinero( + val.job_totals && + val.job_totals.totals && + val.job_totals.totals.subtotal + ) ), Dinero() ); From d306041bcf5f1d9567ea5cd8e4ec8118dc024af2 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Thu, 29 Jul 2021 13:18:28 -0700 Subject: [PATCH 2/3] IO-992 Audit trail bugfixes. --- bodyshop_translations.babel | 21 ++++++++++++ .../production-board-kanban.component.jsx | 25 ++++++++++++-- ...n-list-columns.empassignment.component.jsx | 34 +++++++++++++++---- ...oduction-list-columns.status.component.jsx | 23 +++++++++++-- .../jobs-detail.page.component.jsx | 4 ++- client/src/translations/en_us/common.json | 1 + client/src/translations/es/common.json | 1 + client/src/translations/fr/common.json | 1 + 8 files changed, 98 insertions(+), 12 deletions(-) diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index de7f4c2b7..194b68d3a 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -20730,6 +20730,27 @@ + + special_coverage_policy + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + specialcoveragepolicy false 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 2d71c2889..2c3c4f6d0 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 @@ -14,12 +14,25 @@ import IndefiniteLoading from "../indefinite-loading/indefinite-loading.componen import { logImEXEvent } from "../../firebase/firebase.utils"; import ProductionBoardFilters from "../production-board-filters/production-board-filters.component"; import { selectTechnician } from "../../redux/tech/tech.selectors"; +import { insertAuditTrail } from "../../redux/application/application.actions"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; + const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, technician: selectTechnician, }); -export function ProductionBoardKanbanComponent({ data, bodyshop, technician }) { +const mapDispatchToProps = (dispatch) => ({ + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), +}); + +export function ProductionBoardKanbanComponent({ + data, + bodyshop, + technician, + insertAuditTrail, +}) { const [boardLanes, setBoardLanes] = useState({ columns: [{ id: "Loading...", title: "Loading...", cards: [] }], }); @@ -104,6 +117,11 @@ export function ProductionBoardKanbanComponent({ data, bodyshop, technician }) { newChildCardNewParent ), }); + insertAuditTrail({ + jobid: card.id, + operation: AuditTrailMapping.jobstatuschange(destination.toColumnId), + }); + if (update.errors) { notification["error"]({ message: t("production.errors.boardupdate", { @@ -130,4 +148,7 @@ export function ProductionBoardKanbanComponent({ data, bodyshop, technician }) { ); } -export default connect(mapStateToProps, null)(ProductionBoardKanbanComponent); +export default connect( + mapStateToProps, + mapDispatchToProps +)(ProductionBoardKanbanComponent); 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 0b99973bc..07d2f8b3f 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 @@ -16,24 +16,32 @@ 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 { selectBodyshop } from "../../redux/user/user.selectors"; +import AuditTrailMapping from "../../utils/AuditTrailMappings"; const iconStyle = { marginLeft: ".3rem" }; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, }); const mapDispatchToProps = (dispatch) => ({ - //setUserLanguage: language => dispatch(setUserLanguage(language)) + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), }); -export function ProductionListEmpAssignment({ bodyshop, record, type }) { +export function ProductionListEmpAssignment({ + insertAuditTrail, + bodyshop, + record, + type, +}) { const { t } = useTranslation(); const [updateJob] = useMutation(UPDATE_JOB); const [loading, setLoading] = useState(false); const handleAdd = async (assignment) => { setLoading(true); - const { operation, employeeid } = assignment; + const { operation, employeeid, name } = assignment; logImEXEvent("job_assign_employee", { operation }); let empAssignment = determineFieldName(operation); @@ -44,6 +52,11 @@ export function ProductionListEmpAssignment({ bodyshop, record, type }) { awaitRefetchQueries: true, }); + insertAuditTrail({ + jobid: record.id, + operation: AuditTrailMapping.jobassignmentchange(empAssignment, name), + }); + if (!!result.errors) { notification["error"]({ message: t("jobs.errors.assigning", { @@ -64,6 +77,11 @@ export function ProductionListEmpAssignment({ bodyshop, record, type }) { awaitRefetchQueries: true, }); + insertAuditTrail({ + jobid: record.id, + operation: AuditTrailMapping.jobassignmentremoved(empAssignment), + }); + if (!!result.errors) { notification["error"]({ message: t("jobs.errors.assigning", { @@ -80,8 +98,8 @@ export function ProductionListEmpAssignment({ bodyshop, record, type }) { }); const [visibility, setVisibility] = useState(false); - const onChange = (e) => { - setAssignment({ ...assignment, employeeid: e }); + const onChange = (e, option) => { + setAssignment({ ...assignment, employeeid: e, name: option.name }); }; const popContent = ( @@ -99,7 +117,11 @@ export function ProductionListEmpAssignment({ bodyshop, record, type }) { } > {bodyshop.employees.map((emp) => ( - + {`${emp.first_name} ${emp.last_name}`} ))} 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 7349f6b63..e29ffdbeb 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 @@ -6,12 +6,21 @@ 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 AuditTrailMapping from "../../utils/AuditTrailMappings"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, }); - -export function ProductionListColumnStatus({ record, bodyshop }) { +const mapDispatchToProps = (dispatch) => ({ + insertAuditTrail: ({ jobid, operation }) => + dispatch(insertAuditTrail({ jobid, operation })), +}); +export function ProductionListColumnStatus({ + record, + bodyshop, + insertAuditTrail, +}) { const [updateJob] = useMutation(UPDATE_JOB); const [loading, setLoading] = useState(false); @@ -28,6 +37,11 @@ export function ProductionListColumnStatus({ record, bodyshop }) { }, }, }); + insertAuditTrail({ + jobid: record.id, + operation: AuditTrailMapping.jobstatuschange(key), + }); + setLoading(false); }; @@ -52,4 +66,7 @@ export function ProductionListColumnStatus({ record, bodyshop }) { ); } -export default connect(mapStateToProps, null)(ProductionListColumnStatus); +export default connect( + mapStateToProps, + mapDispatchToProps +)(ProductionListColumnStatus); 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 6c752f480..75baa16bf 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -162,7 +162,9 @@ export function JobsDetailPage({ jobid: job.id, operation: AuditTrailMapping.jobfieldchange( key, - changedAuditFields[key] + changedAuditFields[key] instanceof moment + ? moment(changedAuditFields[key]).format("MM/DD/YYYY hh:mm a") + : changedAuditFields[key] ), }); }); diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index ed6416c20..f3dfec0d0 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1247,6 +1247,7 @@ "servicecar": "Service Car", "servicing_dealer": "Servicing Dealer", "servicing_dealer_contact": "Servicing Dealer Contact", + "special_coverage_policy": "Special Coverage Policy", "specialcoveragepolicy": "Special Coverage Policy", "state_tax_rate": "Provincial/State Tax Rate", "status": "Job Status", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 2514ae112..78f6490d3 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1247,6 +1247,7 @@ "servicecar": "Auto de servicio", "servicing_dealer": "Distribuidor de servicio", "servicing_dealer_contact": "Servicio Contacto con el concesionario", + "special_coverage_policy": "Política de cobertura especial", "specialcoveragepolicy": "Política de cobertura especial", "state_tax_rate": "", "status": "Estado del trabajo", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 5fcd1efca..c0838ead4 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1247,6 +1247,7 @@ "servicecar": "Voiture de service", "servicing_dealer": "Concessionnaire", "servicing_dealer_contact": "Contacter le concessionnaire", + "special_coverage_policy": "Politique de couverture spéciale", "specialcoveragepolicy": "Politique de couverture spéciale", "state_tax_rate": "", "status": "Statut de l'emploi", From 74a62a46d3792b11947c59876b60694cc1d609b5 Mon Sep 17 00:00:00 2001 From: Patrick Fic <> Date: Thu, 29 Jul 2021 13:24:14 -0700 Subject: [PATCH 3/3] IO-1280 Sorting on Available jobs. --- .../jobs-available-table.component.jsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/components/jobs-available-table/jobs-available-table.component.jsx b/client/src/components/jobs-available-table/jobs-available-table.component.jsx index d5b341d00..508eddc6f 100644 --- a/client/src/components/jobs-available-table/jobs-available-table.component.jsx +++ b/client/src/components/jobs-available-table/jobs-available-table.component.jsx @@ -57,7 +57,7 @@ export function JobsAvailableComponent({ title: t("jobs.fields.cieca_id"), dataIndex: "cieca_id", key: "cieca_id", - sorter: (a, b) => alphaSort(a, b), + sorter: (a, b) => alphaSort(a.cieca_id, b.cieca_id), sortOrder: state.sortedInfo.columnKey === "cieca_id" && state.sortedInfo.order, }, @@ -68,9 +68,10 @@ export function JobsAvailableComponent({ //width: "8%", // onFilter: (value, record) => record.ro_number.includes(value), // filteredValue: state.filteredInfo.text || null, - sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number), + sorter: (a, b) => + alphaSort(a.job && a.job.ro_number, b.job && b.job.ro_number), sortOrder: - state.sortedInfo.columnKey === "cieca_id" && state.sortedInfo.order, + state.sortedInfo.columnKey === "job_id" && state.sortedInfo.order, render: (text, record) => record.job ? ( @@ -87,7 +88,7 @@ export function JobsAvailableComponent({ dataIndex: "ownr_name", key: "ownr_name", ellipsis: true, - sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln), + sorter: (a, b) => alphaSort(a.ownr_name, b.ownr_name), sortOrder: state.sortedInfo.columnKey === "ownr_name" && state.sortedInfo.order, },