Merged in feature/2021-07-30 (pull request #150)
feature/2021-07-30 Approved-by: Patrick Fic
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
<babeledit_project version="1.2" be_version="2.7.1">
|
<babeledit_project be_version="2.7.1" version="1.2">
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
BabelEdit project file
|
BabelEdit project file
|
||||||
@@ -500,6 +500,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>note</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>time</name>
|
<name>time</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -1117,6 +1138,258 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>messages</name>
|
<name>messages</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>billposted</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>billupdated</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobassignmentchange</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobassignmentremoved</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobchecklist</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobconverted</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobfieldchanged</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobimported</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobinproductionchange</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobmodifylbradj</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobspartsorder</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobspartsreturn</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>jobstatuschange</name>
|
<name>jobstatuschange</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -1138,6 +1411,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobsupplement</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
@@ -13570,6 +13864,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>newpassword</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>no</name>
|
<name>no</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -37182,6 +37497,27 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>actions</name>
|
<name>actions</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>changepassword</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>signout</name>
|
<name>signout</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -37367,6 +37703,32 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>successess</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>passwordchanged</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import BillReeportButtonComponent from "../bill-reexport-button/bill-reexport-bu
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
@@ -33,6 +35,8 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setPartsOrderContext: (context) =>
|
setPartsOrderContext: (context) =>
|
||||||
dispatch(setModalContext({ context: context, modal: "partsOrder" })),
|
dispatch(setModalContext({ context: context, modal: "partsOrder" })),
|
||||||
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(
|
||||||
@@ -40,7 +44,10 @@ export default connect(
|
|||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(BillDetailEditcontainer);
|
)(BillDetailEditcontainer);
|
||||||
|
|
||||||
export function BillDetailEditcontainer({ setPartsOrderContext }) {
|
export function BillDetailEditcontainer({
|
||||||
|
setPartsOrderContext,
|
||||||
|
insertAuditTrail,
|
||||||
|
}) {
|
||||||
const search = queryString.parse(useLocation().search);
|
const search = queryString.parse(useLocation().search);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -134,6 +141,12 @@ export function BillDetailEditcontainer({ setPartsOrderContext }) {
|
|||||||
});
|
});
|
||||||
await Promise.all(updates);
|
await Promise.all(updates);
|
||||||
|
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: bill.jobid,
|
||||||
|
billid: search.billid,
|
||||||
|
operation: AuditTrailMapping.billupdated(bill.invoice_number),
|
||||||
|
});
|
||||||
|
|
||||||
await refetch();
|
await refetch();
|
||||||
form.setFieldsValue(transformData(data));
|
form.setFieldsValue(transformData(data));
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ import {
|
|||||||
QUERY_JOB_LBR_ADJUSTMENTS,
|
QUERY_JOB_LBR_ADJUSTMENTS,
|
||||||
UPDATE_JOB,
|
UPDATE_JOB,
|
||||||
} from "../../graphql/jobs.queries";
|
} from "../../graphql/jobs.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
||||||
import { selectBillEnterModal } from "../../redux/modals/modals.selectors";
|
import { selectBillEnterModal } from "../../redux/modals/modals.selectors";
|
||||||
import {
|
import {
|
||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser,
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import BillFormContainer from "../bill-form/bill-form.container";
|
import BillFormContainer from "../bill-form/bill-form.container";
|
||||||
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||||
|
|
||||||
@@ -27,6 +29,8 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
toggleModalVisible: () => dispatch(toggleModalVisible("billEnter")),
|
toggleModalVisible: () => dispatch(toggleModalVisible("billEnter")),
|
||||||
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
});
|
});
|
||||||
|
|
||||||
function BillEnterModalContainer({
|
function BillEnterModalContainer({
|
||||||
@@ -34,6 +38,7 @@ function BillEnterModalContainer({
|
|||||||
toggleModalVisible,
|
toggleModalVisible,
|
||||||
bodyshop,
|
bodyshop,
|
||||||
currentUser,
|
currentUser,
|
||||||
|
insertAuditTrail,
|
||||||
}) {
|
}) {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -83,7 +88,7 @@ function BillEnterModalContainer({
|
|||||||
},
|
},
|
||||||
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID"],
|
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID"],
|
||||||
});
|
});
|
||||||
console.log("adjustmentsToInsert", adjustmentsToInsert);
|
|
||||||
const adjKeys = Object.keys(adjustmentsToInsert);
|
const adjKeys = Object.keys(adjustmentsToInsert);
|
||||||
if (adjKeys.length > 0) {
|
if (adjKeys.length > 0) {
|
||||||
//Query the adjustments, merge, and update them.
|
//Query the adjustments, merge, and update them.
|
||||||
@@ -116,7 +121,12 @@ function BillEnterModalContainer({
|
|||||||
message: JSON.stringify(jobUpdate.errors),
|
message: JSON.stringify(jobUpdate.errors),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: values.jobid,
|
||||||
|
operation: AuditTrailMapping.jobmodifylbradj(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!!r1.errors) {
|
if (!!r1.errors) {
|
||||||
@@ -172,6 +182,12 @@ function BillEnterModalContainer({
|
|||||||
});
|
});
|
||||||
if (billEnterModal.actions.refetch) billEnterModal.actions.refetch();
|
if (billEnterModal.actions.refetch) billEnterModal.actions.refetch();
|
||||||
|
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: values.jobid,
|
||||||
|
billid: billId,
|
||||||
|
operation: AuditTrailMapping.billposted(remainingValues.invoice_number),
|
||||||
|
});
|
||||||
|
|
||||||
if (enterAgain) {
|
if (enterAgain) {
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
form.setFieldsValue({ billlines: [] });
|
form.setFieldsValue({ billlines: [] });
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { DateFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
import { alphaSort, dateSort } from "../../utils/sorters";
|
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||||
@@ -14,6 +15,7 @@ import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
|||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//jobRO: selectJobReadOnly,
|
//jobRO: selectJobReadOnly,
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@@ -26,6 +28,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function BillsListTableComponent({
|
export function BillsListTableComponent({
|
||||||
|
bodyshop,
|
||||||
job,
|
job,
|
||||||
billsQuery,
|
billsQuery,
|
||||||
handleOnRowClick,
|
handleOnRowClick,
|
||||||
@@ -52,7 +55,9 @@ export function BillsListTableComponent({
|
|||||||
)}
|
)}
|
||||||
<BillDeleteButton bill={record} />
|
<BillDeleteButton bill={record} />
|
||||||
<Button
|
<Button
|
||||||
disabled={record.is_credit_memo}
|
disabled={
|
||||||
|
record.is_credit_memo || record.vendorid === bodyshop.inhousevendorid
|
||||||
|
}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
setPartsOrderContext({
|
setPartsOrderContext({
|
||||||
actions: {},
|
actions: {},
|
||||||
|
|||||||
@@ -34,7 +34,9 @@ export default function DashboardMonthlyRevenueGraph({ data, ...cardProps }) {
|
|||||||
let dailySales;
|
let dailySales;
|
||||||
if (!!jobsByDate[val]) {
|
if (!!jobsByDate[val]) {
|
||||||
dailySales = jobsByDate[val].reduce((dayAcc, dayVal) => {
|
dailySales = jobsByDate[val].reduce((dayAcc, dayVal) => {
|
||||||
return dayAcc.add(Dinero(dayVal.job_totals.totals.subtotal));
|
return dayAcc.add(
|
||||||
|
Dinero((dayVal.job_totals && dayVal.job_totals.totals.subtotal) || 0)
|
||||||
|
);
|
||||||
}, Dinero());
|
}, Dinero());
|
||||||
} else {
|
} else {
|
||||||
dailySales = Dinero();
|
dailySales = Dinero();
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ export default function DashboardProjectedMonthlySales({ data, ...cardProps }) {
|
|||||||
const dollars =
|
const dollars =
|
||||||
data.projected_monthly_sales &&
|
data.projected_monthly_sales &&
|
||||||
data.projected_monthly_sales.reduce(
|
data.projected_monthly_sales.reduce(
|
||||||
(acc, val) => acc.add(Dinero(val.job_totals.totals.subtotal)),
|
(acc, val) =>
|
||||||
|
acc.add(
|
||||||
|
Dinero(val.job_totals.totals && val.job_totals.totals.subtotal)
|
||||||
|
),
|
||||||
Dinero()
|
Dinero()
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ export default function DashboardTotalProductionDollars({
|
|||||||
const dollars =
|
const dollars =
|
||||||
data.production_jobs &&
|
data.production_jobs &&
|
||||||
data.production_jobs.reduce(
|
data.production_jobs.reduce(
|
||||||
(acc, val) => acc.add(Dinero(val.job_totals.totals.subtotal)),
|
(acc, val) =>
|
||||||
|
acc.add(Dinero(val.job_totals && val.job_totals.totals.subtotal)),
|
||||||
Dinero()
|
Dinero()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Button, Popover, Space } from "antd";
|
import { Button, Divider, Popover, Space } from "antd";
|
||||||
|
import { AlertFilled } from "@ant-design/icons";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -12,6 +13,7 @@ import DataLabel from "../data-label/data-label.component";
|
|||||||
import ScheduleAtChange from "./job-at-change.component";
|
import ScheduleAtChange from "./job-at-change.component";
|
||||||
import ScheduleEventColor from "./schedule-event.color.component";
|
import ScheduleEventColor from "./schedule-event.color.component";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
|
import ScheduleEventNote from "./schedule-event.note.component";
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setScheduleContext: (context) =>
|
setScheduleContext: (context) =>
|
||||||
@@ -38,7 +40,7 @@ export function ScheduleEventComponent({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const popoverContent = (
|
const popoverContent = (
|
||||||
<div>
|
<div style={{ maxWidth: "40vw" }}>
|
||||||
{!event.isintake ? (
|
{!event.isintake ? (
|
||||||
<strong>{event.title}</strong>
|
<strong>{event.title}</strong>
|
||||||
) : (
|
) : (
|
||||||
@@ -83,9 +85,10 @@ export function ScheduleEventComponent({
|
|||||||
{(event.job && event.job.alt_transport) || ""}
|
{(event.job && event.job.alt_transport) || ""}
|
||||||
<ScheduleAtChange job={event && event.job} />
|
<ScheduleAtChange job={event && event.job} />
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
|
<ScheduleEventNote event={event} />
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
<Divider />
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
{event.job ? (
|
{event.job ? (
|
||||||
<Link to={`/manage/jobs/${event.job && event.job.id}`}>
|
<Link to={`/manage/jobs/${event.job && event.job.id}`}>
|
||||||
@@ -161,6 +164,7 @@ export function ScheduleEventComponent({
|
|||||||
const RegularEvent = event.isintake ? (
|
const RegularEvent = event.isintake ? (
|
||||||
<div style={{ display: "flex", flexWrap: "wrap" }}>
|
<div style={{ display: "flex", flexWrap: "wrap" }}>
|
||||||
<Space>
|
<Space>
|
||||||
|
{event.note && <AlertFilled className="production-alert" />}
|
||||||
<strong>{`${event.job.ro_number || t("general.labels.na")}`}</strong>
|
<strong>{`${event.job.ro_number || t("general.labels.na")}`}</strong>
|
||||||
<span>{`${(event.job && event.job.ownr_fn) || ""} ${
|
<span>{`${(event.job && event.job.ownr_fn) || ""} ${
|
||||||
(event.job && event.job.ownr_ln) || ""
|
(event.job && event.job.ownr_ln) || ""
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import { EditFilled, SaveFilled } from "@ant-design/icons";
|
||||||
|
import { useMutation } from "@apollo/client";
|
||||||
|
import { Button, Input, notification, Space } from "antd";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import DataLabel from "../data-label/data-label.component";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
|
||||||
|
export function ScheduleEventNote({ event }) {
|
||||||
|
const [editing, setEditing] = useState(false);
|
||||||
|
const [note, setNote] = useState(event.note || "");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [updateAppointment] = useMutation(UPDATE_APPOINTMENT);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const toggleEdit = async () => {
|
||||||
|
if (editing) {
|
||||||
|
//Await the update
|
||||||
|
setLoading(true);
|
||||||
|
const result = await updateAppointment({
|
||||||
|
variables: {
|
||||||
|
appid: event.id,
|
||||||
|
app: { note },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!!!result.errors) {
|
||||||
|
// notification["success"]({ message: t("appointments.successes.saved") });
|
||||||
|
} else {
|
||||||
|
notification["error"]({
|
||||||
|
message: t("jobs.errors.saving", {
|
||||||
|
error: JSON.stringify(result.errors),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setEditing(false);
|
||||||
|
} else {
|
||||||
|
setEditing(true);
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DataLabel label={t("appointments.fields.note")}>
|
||||||
|
<Space flex>
|
||||||
|
{!editing ? (
|
||||||
|
event.note || ""
|
||||||
|
) : (
|
||||||
|
<Input.TextArea
|
||||||
|
rows={3}
|
||||||
|
value={note}
|
||||||
|
onChange={(e) => setNote(e.target.value)}
|
||||||
|
style={{ maxWidth: "8vw" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<Button onClick={toggleEdit} loading={loading}>
|
||||||
|
{editing ? <SaveFilled /> : <EditFilled />}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</DataLabel>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ScheduleEventNote);
|
||||||
@@ -16,16 +16,20 @@ import {
|
|||||||
import ConfigFormComponents from "../../../config-form-components/config-form-components.component";
|
import ConfigFormComponents from "../../../config-form-components/config-form-components.component";
|
||||||
import DateTimePicker from "../../../form-date-time-picker/form-date-time-picker.component";
|
import DateTimePicker from "../../../form-date-time-picker/form-date-time-picker.component";
|
||||||
import moment from "moment-business-days";
|
import moment from "moment-business-days";
|
||||||
|
import { insertAuditTrail } from "../../../../redux/application/application.actions";
|
||||||
|
import AuditTrailMapping from "../../../../utils/AuditTrailMappings";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function JobChecklistForm({
|
export function JobChecklistForm({
|
||||||
|
insertAuditTrail,
|
||||||
formItems,
|
formItems,
|
||||||
bodyshop,
|
bodyshop,
|
||||||
currentUser,
|
currentUser,
|
||||||
@@ -59,6 +63,12 @@ export function JobChecklistForm({
|
|||||||
production_vars: {
|
production_vars: {
|
||||||
...job.production_vars,
|
...job.production_vars,
|
||||||
...values.production_vars,
|
...values.production_vars,
|
||||||
|
note:
|
||||||
|
values.production_vars &&
|
||||||
|
values.production_vars.note &&
|
||||||
|
values.production_vars.note !== ""
|
||||||
|
? job.production_vars && values.production_vars.note
|
||||||
|
: job.production_vars && job.production_vars.note,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
...(type === "intake" && {
|
...(type === "intake" && {
|
||||||
@@ -109,6 +119,17 @@ export function JobChecklistForm({
|
|||||||
if (!!!result.errors) {
|
if (!!!result.errors) {
|
||||||
notification["success"]({ message: t("checklist.successes.completed") });
|
notification["success"]({ message: t("checklist.successes.completed") });
|
||||||
history.push(`/manage/jobs/${jobId}`);
|
history.push(`/manage/jobs/${jobId}`);
|
||||||
|
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: jobId,
|
||||||
|
operation: AuditTrailMapping.jobchecklist(
|
||||||
|
type,
|
||||||
|
(type === "deliver" && values.removeFromProduction && false) ||
|
||||||
|
(type === "intake" && values.addToProduction),
|
||||||
|
(type === "intake" && bodyshop.md_ro_statuses.default_arrived) ||
|
||||||
|
(type === "deliver" && bodyshop.md_ro_statuses.default_delivered)
|
||||||
|
),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("checklist.errors.complete", {
|
message: t("checklist.errors.complete", {
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ export function JobEmployeeAssignments({
|
|||||||
});
|
});
|
||||||
const [visibility, setVisibility] = useState(false);
|
const [visibility, setVisibility] = useState(false);
|
||||||
|
|
||||||
const onChange = (e) => {
|
const onChange = (value, option) => {
|
||||||
setAssignment({ ...assignment, employeeid: e });
|
setAssignment({ ...assignment, employeeid: value, name: option.name });
|
||||||
};
|
};
|
||||||
|
|
||||||
const popContent = (
|
const popContent = (
|
||||||
@@ -56,7 +56,11 @@ export function JobEmployeeAssignments({
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{bodyshop.employees.map((emp) => (
|
{bodyshop.employees.map((emp) => (
|
||||||
<Select.Option value={emp.id} key={emp.id}>
|
<Select.Option
|
||||||
|
value={emp.id}
|
||||||
|
key={emp.id}
|
||||||
|
name={`${emp.first_name} ${emp.last_name}`}
|
||||||
|
>
|
||||||
{`${emp.first_name} ${emp.last_name}`}
|
{`${emp.first_name} ${emp.last_name}`}
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -6,14 +6,34 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
|||||||
import { UPDATE_JOB_ASSIGNMENTS } from "../../graphql/jobs.queries";
|
import { UPDATE_JOB_ASSIGNMENTS } from "../../graphql/jobs.queries";
|
||||||
import JobEmployeeAssignmentsComponent from "./job-employee-assignments.component";
|
import JobEmployeeAssignmentsComponent from "./job-employee-assignments.component";
|
||||||
|
|
||||||
export default function JobEmployeeAssignmentsContainer({ job, refetch }) {
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
//currentUser: selectCurrentUser
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
|
});
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(JobEmployeeAssignmentsContainer);
|
||||||
|
|
||||||
|
export function JobEmployeeAssignmentsContainer({
|
||||||
|
job,
|
||||||
|
refetch,
|
||||||
|
insertAuditTrail,
|
||||||
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [updateJob] = useMutation(UPDATE_JOB_ASSIGNMENTS);
|
const [updateJob] = useMutation(UPDATE_JOB_ASSIGNMENTS);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
const handleAdd = async (assignment) => {
|
const handleAdd = async (assignment) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const { operation, employeeid } = assignment;
|
const { operation, employeeid, name } = assignment;
|
||||||
logImEXEvent("job_assign_employee", { operation });
|
logImEXEvent("job_assign_employee", { operation });
|
||||||
|
|
||||||
let empAssignment = determineFieldName(operation);
|
let empAssignment = determineFieldName(operation);
|
||||||
@@ -23,6 +43,11 @@ export default function JobEmployeeAssignmentsContainer({ job, refetch }) {
|
|||||||
});
|
});
|
||||||
if (refetch) refetch();
|
if (refetch) refetch();
|
||||||
|
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: job.id,
|
||||||
|
operation: AuditTrailMapping.jobassignmentchange(operation, name),
|
||||||
|
});
|
||||||
|
|
||||||
if (!!result.errors) {
|
if (!!result.errors) {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("jobs.errors.assigning", {
|
message: t("jobs.errors.assigning", {
|
||||||
@@ -48,6 +73,10 @@ export default function JobEmployeeAssignmentsContainer({ job, refetch }) {
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: job.id,
|
||||||
|
operation: AuditTrailMapping.jobassignmentremoved(operation),
|
||||||
|
});
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export function JobsAvailableComponent({
|
|||||||
//width: "8%",
|
//width: "8%",
|
||||||
// onFilter: (value, record) => record.ro_number.includes(value),
|
// onFilter: (value, record) => record.ro_number.includes(value),
|
||||||
// filteredValue: state.filteredInfo.text || null,
|
// filteredValue: state.filteredInfo.text || null,
|
||||||
sorter: (a, b) => alphaSort(a, b),
|
sorter: (a, b) => alphaSort(a.job.ro_number, b.job.ro_number),
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "cieca_id" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "cieca_id" && state.sortedInfo.order,
|
||||||
render: (text, record) =>
|
render: (text, record) =>
|
||||||
|
|||||||
@@ -25,10 +25,12 @@ import {
|
|||||||
import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
|
import { INSERT_NEW_NOTE } from "../../graphql/notes.queries";
|
||||||
import { SEARCH_VEHICLE_BY_VIN } from "../../graphql/vehicles.queries";
|
import { SEARCH_VEHICLE_BY_VIN } from "../../graphql/vehicles.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import {
|
import {
|
||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser,
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import JobsAvailableScan from "../jobs-available-scan/jobs-available-scan.component";
|
import JobsAvailableScan from "../jobs-available-scan/jobs-available-scan.component";
|
||||||
import JobsFindModalContainer from "../jobs-find-modal/jobs-find-modal.container";
|
import JobsFindModalContainer from "../jobs-find-modal/jobs-find-modal.container";
|
||||||
@@ -42,8 +44,15 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
});
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
|
});
|
||||||
|
export function JobsAvailableContainer({
|
||||||
|
bodyshop,
|
||||||
|
currentUser,
|
||||||
|
insertAuditTrail,
|
||||||
|
}) {
|
||||||
const { loading, error, data, refetch } = useQuery(QUERY_AVAILABLE_JOBS, {
|
const { loading, error, data, refetch } = useQuery(QUERY_AVAILABLE_JOBS, {
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
});
|
});
|
||||||
@@ -157,6 +166,11 @@ export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
|||||||
});
|
});
|
||||||
//Job has been inserted. Clean up the available jobs record.
|
//Job has been inserted. Clean up the available jobs record.
|
||||||
|
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: r.data.insert_jobs.returning[0].id,
|
||||||
|
operation: AuditTrailMapping.jobimported(),
|
||||||
|
});
|
||||||
|
|
||||||
deleteJob({
|
deleteJob({
|
||||||
variables: { id: estData.data.available_jobs_by_pk.id },
|
variables: { id: estData.data.available_jobs_by_pk.id },
|
||||||
}).then((r) => {
|
}).then((r) => {
|
||||||
@@ -283,6 +297,10 @@ export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: selectedJob,
|
||||||
|
operation: AuditTrailMapping.jobsupplement(),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -368,4 +386,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
|||||||
</LoadingSpinner>
|
</LoadingSpinner>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default connect(mapStateToProps, null)(JobsAvailableContainer);
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(JobsAvailableContainer);
|
||||||
|
|||||||
@@ -13,8 +13,10 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { CONVERT_JOB_TO_RO } from "../../graphql/jobs.queries";
|
import { CONVERT_JOB_TO_RO } from "../../graphql/jobs.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
@@ -22,10 +24,17 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function JobsConvertButton({ bodyshop, job, refetch, jobRO }) {
|
export function JobsConvertButton({
|
||||||
|
bodyshop,
|
||||||
|
job,
|
||||||
|
refetch,
|
||||||
|
jobRO,
|
||||||
|
insertAuditTrail,
|
||||||
|
}) {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [mutationConvertJob] = useMutation(CONVERT_JOB_TO_RO);
|
const [mutationConvertJob] = useMutation(CONVERT_JOB_TO_RO);
|
||||||
@@ -43,6 +52,14 @@ export function JobsConvertButton({ bodyshop, job, refetch, jobRO }) {
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("jobs.successes.converted"),
|
message: t("jobs.successes.converted"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: job.id,
|
||||||
|
operation: AuditTrailMapping.jobconverted(
|
||||||
|
res.data.update_jobs.returning[0].ro_number
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
import { notification } from "antd";
|
import { notification } from "antd";
|
||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
import { store } from "../../redux/store";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
|
||||||
export default function AddToProduction(
|
export default function AddToProduction(
|
||||||
apolloClient,
|
apolloClient,
|
||||||
@@ -21,6 +24,13 @@ export default function AddToProduction(
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: i18n.t("jobs.successes.save"),
|
message: i18n.t("jobs.successes.save"),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
store.dispatch(
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: jobId,
|
||||||
|
operation: AuditTrailMapping.jobinproductionchange(!remove),
|
||||||
|
})
|
||||||
|
);
|
||||||
if (completionCallback) completionCallback();
|
if (completionCallback) completionCallback();
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
|||||||
import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries";
|
import { UPDATE_JOB_LINE_STATUS } from "../../graphql/jobs-lines.queries";
|
||||||
import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries";
|
import { INSERT_NEW_PARTS_ORDERS } from "../../graphql/parts-orders.queries";
|
||||||
import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries";
|
import { QUERY_ALL_VENDORS_FOR_ORDER } from "../../graphql/vendors.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import { setEmailOptions } from "../../redux/email/email.actions";
|
import { setEmailOptions } from "../../redux/email/email.actions";
|
||||||
import {
|
import {
|
||||||
setModalContext,
|
setModalContext,
|
||||||
@@ -19,6 +20,7 @@ import {
|
|||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser,
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
@@ -36,6 +38,8 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
toggleModalVisible: () => dispatch(toggleModalVisible("partsOrder")),
|
toggleModalVisible: () => dispatch(toggleModalVisible("partsOrder")),
|
||||||
setBillEnterContext: (context) =>
|
setBillEnterContext: (context) =>
|
||||||
dispatch(setModalContext({ context: context, modal: "billEnter" })),
|
dispatch(setModalContext({ context: context, modal: "billEnter" })),
|
||||||
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function PartsOrderModalContainer({
|
export function PartsOrderModalContainer({
|
||||||
@@ -45,6 +49,7 @@ export function PartsOrderModalContainer({
|
|||||||
bodyshop,
|
bodyshop,
|
||||||
setEmailOptions,
|
setEmailOptions,
|
||||||
setBillEnterContext,
|
setBillEnterContext,
|
||||||
|
insertAuditTrail,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@@ -109,6 +114,18 @@ export function PartsOrderModalContainer({
|
|||||||
: bodyshop.md_order_statuses.default_ordered || "Ordered*",
|
: bodyshop.md_order_statuses.default_ordered || "Ordered*",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: jobId,
|
||||||
|
operation: isReturn
|
||||||
|
? AuditTrailMapping.jobspartsreturn(
|
||||||
|
insertResult.data.insert_parts_orders.returning[0].order_number
|
||||||
|
)
|
||||||
|
: AuditTrailMapping.jobspartsorder(
|
||||||
|
insertResult.data.insert_parts_orders.returning[0].order_number
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
if (!!jobLinesResult.errors) {
|
if (!!jobLinesResult.errors) {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("parts_orders.errors.creating"),
|
message: t("parts_orders.errors.creating"),
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import { Button, Form, Input } from "antd";
|
import { Button, Form, Input, notification } from "antd";
|
||||||
|
import { LockOutlined } from "@ant-design/icons";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { updateUserDetails } from "../../redux/user/user.actions";
|
import { updateUserDetails } from "../../redux/user/user.actions";
|
||||||
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
import { selectCurrentUser } from "../../redux/user/user.selectors";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import {
|
||||||
|
logImEXEvent,
|
||||||
|
updateCurrentPassword,
|
||||||
|
} from "../../firebase/firebase.utils";
|
||||||
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
@@ -28,33 +33,96 @@ export default connect(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleChangePassword = async ({ password }) => {
|
||||||
|
logImEXEvent("password_update");
|
||||||
|
try {
|
||||||
|
await updateCurrentPassword(password);
|
||||||
|
notification.success({
|
||||||
|
message: t("user.successess.passwordchanged"),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
notification.error({
|
||||||
|
message: error.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Form
|
<Form
|
||||||
onFinish={handleFinish}
|
onFinish={handleFinish}
|
||||||
autoComplete={"no"}
|
autoComplete={"no"}
|
||||||
initialValues={currentUser}
|
initialValues={currentUser}
|
||||||
|
layout="vertical"
|
||||||
>
|
>
|
||||||
<Form.Item
|
<LayoutFormRow>
|
||||||
label={t("user.fields.displayname")}
|
<Form.Item
|
||||||
rules={[
|
label={t("user.fields.displayname")}
|
||||||
{
|
rules={[
|
||||||
required: true,
|
{
|
||||||
//message: t("general.validation.required"),
|
required: true,
|
||||||
},
|
//message: t("general.validation.required"),
|
||||||
]}
|
},
|
||||||
name="displayName"
|
]}
|
||||||
>
|
name="displayName"
|
||||||
<Input />
|
>
|
||||||
</Form.Item>
|
<Input />
|
||||||
<Form.Item label={t("user.fields.photourl")} name="photoURL">
|
</Form.Item>
|
||||||
<Input />
|
<Form.Item label={t("user.fields.photourl")} name="photoURL">
|
||||||
</Form.Item>
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
|
</LayoutFormRow>
|
||||||
|
|
||||||
<Button type="primary" key="submit" htmlType="submit">
|
<Button type="primary" key="submit" htmlType="submit">
|
||||||
{t("user.actions.updateprofile")}
|
{t("user.actions.updateprofile")}
|
||||||
</Button>
|
</Button>
|
||||||
</Form>
|
</Form>
|
||||||
|
<Form
|
||||||
|
onFinish={handleChangePassword}
|
||||||
|
autoComplete={"no"}
|
||||||
|
initialValues={currentUser}
|
||||||
|
layout="vertical"
|
||||||
|
>
|
||||||
|
<LayoutFormRow>
|
||||||
|
<Form.Item label={t("general.labels.newpassword")} name="password">
|
||||||
|
<Input
|
||||||
|
prefix={<LockOutlined />}
|
||||||
|
type="password"
|
||||||
|
placeholder={t("general.labels.password")}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("general.labels.confirmpassword")}
|
||||||
|
name="password-confirm"
|
||||||
|
dependencies={["password"]}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(rule, value) {
|
||||||
|
if (!value || getFieldValue("password") === value) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(
|
||||||
|
t("general.labels.passwordsdonotmatch")
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
prefix={<LockOutlined />}
|
||||||
|
type="password"
|
||||||
|
placeholder={t("general.labels.password")}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</LayoutFormRow>
|
||||||
|
<Button type="primary" key="submit" htmlType="submit">
|
||||||
|
{t("user.actions.changepassword")}
|
||||||
|
</Button>
|
||||||
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,4 +1,14 @@
|
|||||||
import { Button, Card, Col, Form, Row, Select, Switch } from "antd";
|
import {
|
||||||
|
Button,
|
||||||
|
Col,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Row,
|
||||||
|
Select,
|
||||||
|
Space,
|
||||||
|
Switch,
|
||||||
|
Typography,
|
||||||
|
} from "antd";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
@@ -91,31 +101,34 @@ export function ScheduleJobModalComponent({
|
|||||||
<DateTimePicker onlyFuture />
|
<DateTimePicker onlyFuture />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<Card title={t("appointments.labels.smartscheduling")}>
|
|
||||||
|
<Typography.Title level={4}>
|
||||||
|
{t("appointments.labels.smartscheduling")}
|
||||||
|
</Typography.Title>
|
||||||
|
|
||||||
|
{
|
||||||
|
// smartOptions.length > 0 && (
|
||||||
|
// <div>{t("appointments.labels.suggesteddates")}</div>
|
||||||
|
// )
|
||||||
|
}
|
||||||
|
<Space wrap>
|
||||||
<Button onClick={handleSmartScheduling} loading={loading}>
|
<Button onClick={handleSmartScheduling} loading={loading}>
|
||||||
{t("appointments.actions.calculate")}
|
{t("appointments.actions.calculate")}
|
||||||
</Button>
|
</Button>
|
||||||
{smartOptions.length > 0 && (
|
{smartOptions.map((d, idx) => (
|
||||||
<div>{t("appointments.labels.suggesteddates")}</div>
|
<Button
|
||||||
)}
|
className="imex-flex-row__margin"
|
||||||
<div
|
key={idx}
|
||||||
className="imex-flex-row imex-flex-row__flex-space-around"
|
onClick={() => {
|
||||||
style={{ flexWrap: "wrap" }}
|
form.setFieldsValue({ start: new moment(d).add(8, "hours") });
|
||||||
>
|
handleDateBlur();
|
||||||
{smartOptions.map((d, idx) => (
|
}}
|
||||||
<Button
|
>
|
||||||
className="imex-flex-row__margin"
|
<DateFormatter>{d}</DateFormatter>
|
||||||
key={idx}
|
</Button>
|
||||||
onClick={() => {
|
))}
|
||||||
form.setFieldsValue({ start: new moment(d).add(8, "hours") });
|
</Space>
|
||||||
handleDateBlur();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<DateFormatter>{d}</DateFormatter>
|
|
||||||
</Button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
<LayoutFormRow grow>
|
<LayoutFormRow grow>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="notifyCustomer"
|
name="notifyCustomer"
|
||||||
@@ -124,12 +137,9 @@ export function ScheduleJobModalComponent({
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item shouldUpdate>
|
|
||||||
{() => (
|
<Form.Item name="email" label={t("jobs.fields.ownr_ea")}>
|
||||||
<Form.Item name="email" label={t("jobs.fields.ownr_ea")}>
|
<EmailInput disabled={!form.getFieldValue("notifyCustomer")} />
|
||||||
<EmailInput disabled={!form.getFieldValue("notifyCustomer")} />
|
|
||||||
</Form.Item>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow grow>
|
<LayoutFormRow grow>
|
||||||
@@ -158,6 +168,9 @@ export function ScheduleJobModalComponent({
|
|||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item name={"note"} label={t("appointments.fields.note")}>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
{t("appointments.labels.history")}
|
{t("appointments.labels.history")}
|
||||||
<ScheduleExistingAppointmentsList
|
<ScheduleExistingAppointmentsList
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ export function ScheduleJobModalContainer({
|
|||||||
start: moment(values.start),
|
start: moment(values.start),
|
||||||
end: moment(values.start).add(bodyshop.appt_length || 60, "minutes"),
|
end: moment(values.start).add(bodyshop.appt_length || 60, "minutes"),
|
||||||
color: values.color,
|
color: values.color,
|
||||||
|
note:values.note
|
||||||
},
|
},
|
||||||
jobId: jobId,
|
jobId: jobId,
|
||||||
altTransport: values.alt_transport,
|
altTransport: values.alt_transport,
|
||||||
|
|||||||
@@ -35,6 +35,24 @@ export const updateCurrentUser = (userDetails) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const updateCurrentPassword = async (password) => {
|
||||||
|
const currentUser = await getCurrentUser();
|
||||||
|
|
||||||
|
return currentUser.updatePassword(password);
|
||||||
|
|
||||||
|
// return new Promise((resolve, reject) => {
|
||||||
|
// const unsubscribe = auth.onAuthStateChanged(
|
||||||
|
// (userAuth) => {
|
||||||
|
// userAuth.updatePassword(password).then((r) => {
|
||||||
|
// unsubscribe();
|
||||||
|
// resolve(userAuth);
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// (error) => reject(error)
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
};
|
||||||
|
|
||||||
let messaging;
|
let messaging;
|
||||||
try {
|
try {
|
||||||
messaging = firebase.messaging();
|
messaging = firebase.messaging();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export const QUERY_ALL_ACTIVE_APPOINTMENTS = gql`
|
|||||||
isintake
|
isintake
|
||||||
block
|
block
|
||||||
color
|
color
|
||||||
|
note
|
||||||
job {
|
job {
|
||||||
alt_transport
|
alt_transport
|
||||||
ro_number
|
ro_number
|
||||||
@@ -69,6 +70,7 @@ export const INSERT_APPOINTMENT_BLOCK = gql`
|
|||||||
title
|
title
|
||||||
isintake
|
isintake
|
||||||
block
|
block
|
||||||
|
note
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,6 +92,7 @@ export const INSERT_APPOINTMENT = gql`
|
|||||||
isintake
|
isintake
|
||||||
block
|
block
|
||||||
color
|
color
|
||||||
|
note
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_jobs(
|
update_jobs(
|
||||||
@@ -116,6 +119,7 @@ export const QUERY_APPOINTMENT_BY_DATE = gql`
|
|||||||
isintake
|
isintake
|
||||||
block
|
block
|
||||||
color
|
color
|
||||||
|
note
|
||||||
job {
|
job {
|
||||||
alt_transport
|
alt_transport
|
||||||
ro_number
|
ro_number
|
||||||
@@ -168,6 +172,7 @@ export const UPDATE_APPOINTMENT = gql`
|
|||||||
isintake
|
isintake
|
||||||
block
|
block
|
||||||
color
|
color
|
||||||
|
note
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -198,6 +203,7 @@ export const QUERY_APPOINTMENTS_BY_JOBID = gql`
|
|||||||
canceled
|
canceled
|
||||||
created_at
|
created_at
|
||||||
block
|
block
|
||||||
|
note
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ export const INSERT_NEW_PARTS_ORDERS = gql`
|
|||||||
insert_parts_orders(objects: $po) {
|
insert_parts_orders(objects: $po) {
|
||||||
returning {
|
returning {
|
||||||
id
|
id
|
||||||
|
order_number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import Icon, {
|
|||||||
FileImageFilled,
|
FileImageFilled,
|
||||||
PrinterFilled,
|
PrinterFilled,
|
||||||
ToolFilled,
|
ToolFilled,
|
||||||
|
HistoryOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
@@ -46,6 +47,8 @@ import { selectJobReadOnly } from "../../redux/application/application.selectors
|
|||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import JobAuditTrail from "../../components/job-audit-trail/job-audit-trail.component";
|
import JobAuditTrail from "../../components/job-audit-trail/job-audit-trail.component";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -54,6 +57,8 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
setPrintCenterContext: (context) =>
|
setPrintCenterContext: (context) =>
|
||||||
dispatch(setModalContext({ context: context, modal: "printCenter" })),
|
dispatch(setModalContext({ context: context, modal: "printCenter" })),
|
||||||
|
insertAuditTrail: ({ jobid, operation }) =>
|
||||||
|
dispatch(insertAuditTrail({ jobid, operation })),
|
||||||
});
|
});
|
||||||
export function JobsDetailPage({
|
export function JobsDetailPage({
|
||||||
setPrintCenterContext,
|
setPrintCenterContext,
|
||||||
@@ -61,6 +66,7 @@ export function JobsDetailPage({
|
|||||||
job,
|
job,
|
||||||
mutationUpdateJob,
|
mutationUpdateJob,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
insertAuditTrail,
|
||||||
refetch,
|
refetch,
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -82,6 +88,7 @@ export function JobsDetailPage({
|
|||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (values) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
const result = await mutationUpdateJob({
|
const result = await mutationUpdateJob({
|
||||||
variables: {
|
variables: {
|
||||||
jobId: job.id,
|
jobId: job.id,
|
||||||
@@ -106,6 +113,60 @@ export function JobsDetailPage({
|
|||||||
notification["success"]({
|
notification["success"]({
|
||||||
message: t("jobs.successes.savetitle"),
|
message: t("jobs.successes.savetitle"),
|
||||||
});
|
});
|
||||||
|
const changedAuditFields = form.getFieldsValue(
|
||||||
|
[
|
||||||
|
"scheduled_in",
|
||||||
|
"actual_in",
|
||||||
|
"scheduled_completion",
|
||||||
|
"actual_completion",
|
||||||
|
"scheduled_delivery",
|
||||||
|
"actual_delivery",
|
||||||
|
"date_invoiced",
|
||||||
|
"ins_co_nm",
|
||||||
|
"ded_amt",
|
||||||
|
"ded_status",
|
||||||
|
"date_exported",
|
||||||
|
"special_coverage_policy",
|
||||||
|
"ca_gst_registrant",
|
||||||
|
"ca_bc_pvrt",
|
||||||
|
"scheduled_in",
|
||||||
|
"rate_la1",
|
||||||
|
"rate_la2",
|
||||||
|
"rate_la3",
|
||||||
|
"rate_la4",
|
||||||
|
"rate_laa",
|
||||||
|
"rate_lab",
|
||||||
|
"rate_lad",
|
||||||
|
"rate_lae",
|
||||||
|
"rate_laf",
|
||||||
|
"rate_lag",
|
||||||
|
"rate_lam",
|
||||||
|
"rate_lar",
|
||||||
|
"rate_las",
|
||||||
|
"rate_lau",
|
||||||
|
"rate_ma2s",
|
||||||
|
"rate_ma2t",
|
||||||
|
"rate_ma3s",
|
||||||
|
"rate_mabl",
|
||||||
|
"rate_macs",
|
||||||
|
"rate_mapa",
|
||||||
|
"rate_mahw",
|
||||||
|
"rate_mash",
|
||||||
|
"rate_matd",
|
||||||
|
],
|
||||||
|
(meta) => meta && meta.touched
|
||||||
|
);
|
||||||
|
|
||||||
|
Object.keys(changedAuditFields).forEach((key) => {
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: job.id,
|
||||||
|
operation: AuditTrailMapping.jobfieldchange(
|
||||||
|
key,
|
||||||
|
changedAuditFields[key]
|
||||||
|
),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
await refetch();
|
await refetch();
|
||||||
form.setFieldsValue(transormJobToForm(job));
|
form.setFieldsValue(transormJobToForm(job));
|
||||||
form.resetFields();
|
form.resetFields();
|
||||||
@@ -283,7 +344,7 @@ export function JobsDetailPage({
|
|||||||
<Tabs.TabPane
|
<Tabs.TabPane
|
||||||
tab={
|
tab={
|
||||||
<span>
|
<span>
|
||||||
<Icon component={FaRegStickyNote} />
|
<HistoryOutlined />
|
||||||
{t("jobs.labels.audit")}
|
{t("jobs.labels.audit")}
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,8 +100,12 @@ export function* onUpdateUserDetails() {
|
|||||||
}
|
}
|
||||||
export function* updateUserDetails(userDetails) {
|
export function* updateUserDetails(userDetails) {
|
||||||
try {
|
try {
|
||||||
yield updateCurrentUser(userDetails.payload);
|
const updatedDetails = yield updateCurrentUser(userDetails.payload);
|
||||||
yield put(updateUserDetailsSuccess(userDetails.payload));
|
console.log(
|
||||||
|
"🚀 ~ file: user.sagas.js ~ line 104 ~ updatedDetails",
|
||||||
|
updatedDetails
|
||||||
|
);
|
||||||
|
yield put(updateUserDetailsSuccess(updatedDetails));
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
message: i18next.t("profile.successes.updated"),
|
message: i18next.t("profile.successes.updated"),
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"fields": {
|
"fields": {
|
||||||
"alt_transport": "Alt. Trans.",
|
"alt_transport": "Alt. Trans.",
|
||||||
"color": "Appointment Color",
|
"color": "Appointment Color",
|
||||||
|
"note": "Appt. Note",
|
||||||
"time": "Appointment Time",
|
"time": "Appointment Time",
|
||||||
"title": "Title"
|
"title": "Title"
|
||||||
},
|
},
|
||||||
@@ -84,7 +85,20 @@
|
|||||||
},
|
},
|
||||||
"audit_trail": {
|
"audit_trail": {
|
||||||
"messages": {
|
"messages": {
|
||||||
"jobstatuschange": "Job status changed to {{status}}."
|
"billposted": "Bill with invoice number {{invoice_number}} posted.",
|
||||||
|
"billupdated": "Bill with invoice number {{invoice_number}} updated.",
|
||||||
|
"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}}.",
|
||||||
|
"jobconverted": "Job converted and assigned number {{ro_number}}.",
|
||||||
|
"jobfieldchanged": "Job field $t(jobs.fields.{{field}}) changed to {{value}}.",
|
||||||
|
"jobimported": "Job imported.",
|
||||||
|
"jobinproductionchange": "Job production status set to {{inproduction}}",
|
||||||
|
"jobmodifylbradj": "Labor adjustments modified.",
|
||||||
|
"jobspartsorder": "Parts order {{order_number}} added to job.",
|
||||||
|
"jobspartsreturn": "Parts return {{order_number}} added to job.",
|
||||||
|
"jobstatuschange": "Job status changed to {{status}}.",
|
||||||
|
"jobsupplement": "Job supplement imported."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"billlines": {
|
"billlines": {
|
||||||
@@ -862,6 +876,7 @@
|
|||||||
"message": "Message",
|
"message": "Message",
|
||||||
"monday": "Monday",
|
"monday": "Monday",
|
||||||
"na": "N/A",
|
"na": "N/A",
|
||||||
|
"newpassword": "New Password",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
"nointernet": "It looks like you're not connected to the internet.",
|
"nointernet": "It looks like you're not connected to the internet.",
|
||||||
"nointernet_sub": "Please check your connection and try again. ",
|
"nointernet_sub": "Please check your connection and try again. ",
|
||||||
@@ -2226,6 +2241,7 @@
|
|||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"changepassword": "Change Password",
|
||||||
"signout": "Sign Out",
|
"signout": "Sign Out",
|
||||||
"updateprofile": "Update Profile"
|
"updateprofile": "Update Profile"
|
||||||
},
|
},
|
||||||
@@ -2240,6 +2256,9 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"actions": "Actions"
|
"actions": "Actions"
|
||||||
|
},
|
||||||
|
"successess": {
|
||||||
|
"passwordchanged": "Password changed successfully. "
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"fields": {
|
"fields": {
|
||||||
"alt_transport": "",
|
"alt_transport": "",
|
||||||
"color": "",
|
"color": "",
|
||||||
|
"note": "",
|
||||||
"time": "",
|
"time": "",
|
||||||
"title": "Título"
|
"title": "Título"
|
||||||
},
|
},
|
||||||
@@ -84,7 +85,20 @@
|
|||||||
},
|
},
|
||||||
"audit_trail": {
|
"audit_trail": {
|
||||||
"messages": {
|
"messages": {
|
||||||
"jobstatuschange": ""
|
"billposted": "",
|
||||||
|
"billupdated": "",
|
||||||
|
"jobassignmentchange": "",
|
||||||
|
"jobassignmentremoved": "",
|
||||||
|
"jobchecklist": "",
|
||||||
|
"jobconverted": "",
|
||||||
|
"jobfieldchanged": "",
|
||||||
|
"jobimported": "",
|
||||||
|
"jobinproductionchange": "",
|
||||||
|
"jobmodifylbradj": "",
|
||||||
|
"jobspartsorder": "",
|
||||||
|
"jobspartsreturn": "",
|
||||||
|
"jobstatuschange": "",
|
||||||
|
"jobsupplement": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"billlines": {
|
"billlines": {
|
||||||
@@ -862,6 +876,7 @@
|
|||||||
"message": "",
|
"message": "",
|
||||||
"monday": "",
|
"monday": "",
|
||||||
"na": "N / A",
|
"na": "N / A",
|
||||||
|
"newpassword": "",
|
||||||
"no": "",
|
"no": "",
|
||||||
"nointernet": "",
|
"nointernet": "",
|
||||||
"nointernet_sub": "",
|
"nointernet_sub": "",
|
||||||
@@ -2226,6 +2241,7 @@
|
|||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"changepassword": "",
|
||||||
"signout": "desconectar",
|
"signout": "desconectar",
|
||||||
"updateprofile": "Actualización del perfil"
|
"updateprofile": "Actualización del perfil"
|
||||||
},
|
},
|
||||||
@@ -2240,6 +2256,9 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"actions": ""
|
"actions": ""
|
||||||
|
},
|
||||||
|
"successess": {
|
||||||
|
"passwordchanged": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"fields": {
|
"fields": {
|
||||||
"alt_transport": "",
|
"alt_transport": "",
|
||||||
"color": "",
|
"color": "",
|
||||||
|
"note": "",
|
||||||
"time": "",
|
"time": "",
|
||||||
"title": "Titre"
|
"title": "Titre"
|
||||||
},
|
},
|
||||||
@@ -84,7 +85,20 @@
|
|||||||
},
|
},
|
||||||
"audit_trail": {
|
"audit_trail": {
|
||||||
"messages": {
|
"messages": {
|
||||||
"jobstatuschange": ""
|
"billposted": "",
|
||||||
|
"billupdated": "",
|
||||||
|
"jobassignmentchange": "",
|
||||||
|
"jobassignmentremoved": "",
|
||||||
|
"jobchecklist": "",
|
||||||
|
"jobconverted": "",
|
||||||
|
"jobfieldchanged": "",
|
||||||
|
"jobimported": "",
|
||||||
|
"jobinproductionchange": "",
|
||||||
|
"jobmodifylbradj": "",
|
||||||
|
"jobspartsorder": "",
|
||||||
|
"jobspartsreturn": "",
|
||||||
|
"jobstatuschange": "",
|
||||||
|
"jobsupplement": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"billlines": {
|
"billlines": {
|
||||||
@@ -862,6 +876,7 @@
|
|||||||
"message": "",
|
"message": "",
|
||||||
"monday": "",
|
"monday": "",
|
||||||
"na": "N / A",
|
"na": "N / A",
|
||||||
|
"newpassword": "",
|
||||||
"no": "",
|
"no": "",
|
||||||
"nointernet": "",
|
"nointernet": "",
|
||||||
"nointernet_sub": "",
|
"nointernet_sub": "",
|
||||||
@@ -2226,6 +2241,7 @@
|
|||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"changepassword": "",
|
||||||
"signout": "Déconnexion",
|
"signout": "Déconnexion",
|
||||||
"updateprofile": "Mettre à jour le profil"
|
"updateprofile": "Mettre à jour le profil"
|
||||||
},
|
},
|
||||||
@@ -2240,6 +2256,9 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"actions": ""
|
"actions": ""
|
||||||
|
},
|
||||||
|
"successess": {
|
||||||
|
"passwordchanged": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vehicles": {
|
"vehicles": {
|
||||||
|
|||||||
@@ -3,6 +3,29 @@ import i18n from "i18next";
|
|||||||
const AuditTrailMapping = {
|
const AuditTrailMapping = {
|
||||||
jobstatuschange: (status) =>
|
jobstatuschange: (status) =>
|
||||||
i18n.t("audit_trail.messages.jobstatuschange", { status }),
|
i18n.t("audit_trail.messages.jobstatuschange", { status }),
|
||||||
|
jobsupplement: () => i18n.t("audit_trail.messages.jobsupplement"),
|
||||||
|
jobimported: () => i18n.t("audit_trail.messages.jobimported"),
|
||||||
|
jobconverted: (ro_number) =>
|
||||||
|
i18n.t("audit_trail.messages.jobconverted", { ro_number }),
|
||||||
|
jobfieldchange: (field, value) =>
|
||||||
|
i18n.t("audit_trail.messages.jobfieldchanged", { field, value }),
|
||||||
|
jobspartsorder: (order_number) =>
|
||||||
|
i18n.t("audit_trail.messages.jobspartsorder", { order_number }),
|
||||||
|
jobspartsreturn: (order_number) =>
|
||||||
|
i18n.t("audit_trail.messages.jobspartsreturn", { order_number }),
|
||||||
|
jobmodifylbradj: () => i18n.t("audit_trail.messages.jobmodifylbradj", {}),
|
||||||
|
billposted: (invoice_number) =>
|
||||||
|
i18n.t("audit_trail.messages.billposted", { invoice_number }),
|
||||||
|
billupdated: (invoice_number) =>
|
||||||
|
i18n.t("audit_trail.messages.billupdated", { invoice_number }),
|
||||||
|
jobassignmentchange: (operation, name) =>
|
||||||
|
i18n.t("audit_trail.messages.jobassignmentchange", { operation, name }),
|
||||||
|
jobassignmentremoved: (operation) =>
|
||||||
|
i18n.t("audit_trail.messages.jobassignmentremoved", { operation }),
|
||||||
|
jobinproductionchange: (inproduction) =>
|
||||||
|
i18n.t("audit_trail.messages.jobinproductionchange", { inproduction }),
|
||||||
|
jobchecklist: (type, inproduction, status) =>
|
||||||
|
i18n.t("audit_trail.messages.jobchecklist", { type, inproduction, status }),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AuditTrailMapping;
|
export default AuditTrailMapping;
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."appointments" DROP COLUMN "note";
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."appointments" ADD COLUMN "note" text NULL;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: drop_insert_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- arrived
|
||||||
|
- block
|
||||||
|
- bodyshopid
|
||||||
|
- canceled
|
||||||
|
- color
|
||||||
|
- created_at
|
||||||
|
- end
|
||||||
|
- id
|
||||||
|
- isintake
|
||||||
|
- jobid
|
||||||
|
- start
|
||||||
|
- title
|
||||||
|
- updated_at
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: create_insert_permission
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: drop_insert_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- arrived
|
||||||
|
- block
|
||||||
|
- bodyshopid
|
||||||
|
- canceled
|
||||||
|
- color
|
||||||
|
- created_at
|
||||||
|
- end
|
||||||
|
- id
|
||||||
|
- isintake
|
||||||
|
- jobid
|
||||||
|
- note
|
||||||
|
- start
|
||||||
|
- title
|
||||||
|
- updated_at
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: create_insert_permission
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: true
|
||||||
|
columns:
|
||||||
|
- arrived
|
||||||
|
- block
|
||||||
|
- bodyshopid
|
||||||
|
- canceled
|
||||||
|
- color
|
||||||
|
- created_at
|
||||||
|
- end
|
||||||
|
- id
|
||||||
|
- isintake
|
||||||
|
- jobid
|
||||||
|
- start
|
||||||
|
- title
|
||||||
|
- updated_at
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: true
|
||||||
|
columns:
|
||||||
|
- arrived
|
||||||
|
- block
|
||||||
|
- bodyshopid
|
||||||
|
- canceled
|
||||||
|
- color
|
||||||
|
- created_at
|
||||||
|
- end
|
||||||
|
- id
|
||||||
|
- isintake
|
||||||
|
- jobid
|
||||||
|
- note
|
||||||
|
- start
|
||||||
|
- title
|
||||||
|
- updated_at
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: drop_update_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- arrived
|
||||||
|
- block
|
||||||
|
- bodyshopid
|
||||||
|
- canceled
|
||||||
|
- color
|
||||||
|
- created_at
|
||||||
|
- end
|
||||||
|
- id
|
||||||
|
- isintake
|
||||||
|
- jobid
|
||||||
|
- start
|
||||||
|
- title
|
||||||
|
- updated_at
|
||||||
|
filter:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: create_update_permission
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: drop_update_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- arrived
|
||||||
|
- block
|
||||||
|
- bodyshopid
|
||||||
|
- canceled
|
||||||
|
- color
|
||||||
|
- created_at
|
||||||
|
- end
|
||||||
|
- id
|
||||||
|
- isintake
|
||||||
|
- jobid
|
||||||
|
- note
|
||||||
|
- start
|
||||||
|
- title
|
||||||
|
- updated_at
|
||||||
|
filter:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: appointments
|
||||||
|
schema: public
|
||||||
|
type: create_update_permission
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."audit_trail" ALTER COLUMN "created" TYPE timestamp
|
||||||
|
without time zone;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."audit_trail" ALTER COLUMN "created" TYPE timestamptz;
|
||||||
|
type: run_sql
|
||||||
@@ -115,6 +115,7 @@ tables:
|
|||||||
- id
|
- id
|
||||||
- isintake
|
- isintake
|
||||||
- jobid
|
- jobid
|
||||||
|
- note
|
||||||
- start
|
- start
|
||||||
- title
|
- title
|
||||||
- updated_at
|
- updated_at
|
||||||
@@ -132,6 +133,7 @@ tables:
|
|||||||
- id
|
- id
|
||||||
- isintake
|
- isintake
|
||||||
- jobid
|
- jobid
|
||||||
|
- note
|
||||||
- start
|
- start
|
||||||
- title
|
- title
|
||||||
- updated_at
|
- updated_at
|
||||||
@@ -159,6 +161,7 @@ tables:
|
|||||||
- id
|
- id
|
||||||
- isintake
|
- isintake
|
||||||
- jobid
|
- jobid
|
||||||
|
- note
|
||||||
- start
|
- start
|
||||||
- title
|
- title
|
||||||
- updated_at
|
- updated_at
|
||||||
|
|||||||
4781
package-lock.json
generated
4781
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user