feature/IO-999-Part-Tax-rate-Label
This commit is contained in:
@@ -6369,6 +6369,27 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>md_parts_scan</name>
|
<name>md_parts_scan</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>caseInsensitive</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>expression</name>
|
<name>expression</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -6390,6 +6411,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>field</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>flags</name>
|
<name>flags</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -6411,6 +6453,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>operation</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>value</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>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
@@ -11987,6 +12071,158 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>operations</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>contains</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>ends_with</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>equals</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>greater_than</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>less_than</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>not_equals</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>starts_with</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>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>successes</name>
|
<name>successes</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -23131,6 +23367,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>alt_partno</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>amount</name>
|
<name>amount</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -23236,6 +23493,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>include_in_part_cnt</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>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>lbr_types</name>
|
<name>lbr_types</name>
|
||||||
<children>
|
<children>
|
||||||
|
|||||||
@@ -85,6 +85,17 @@ export function AccountingPayablesTableComponent({ bodyshop, loading, payments,
|
|||||||
sortOrder: state.sortedInfo.columnKey === "amount" && state.sortedInfo.order,
|
sortOrder: state.sortedInfo.columnKey === "amount" && state.sortedInfo.order,
|
||||||
render: (text, record) => <CurrencyFormatter>{record.amount}</CurrencyFormatter>
|
render: (text, record) => <CurrencyFormatter>{record.amount}</CurrencyFormatter>
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("payments.fields.type"),
|
||||||
|
dataIndex: "type",
|
||||||
|
key: "type",
|
||||||
|
sorter: (a, b) => a.type.localeCompare(b.type),
|
||||||
|
sortOrder: state.sortedInfo.columnKey === "type" && state.sortedInfo.order,
|
||||||
|
filters: bodyshop.md_payment_types.map((s) => {
|
||||||
|
return { text: s, value: [s] };
|
||||||
|
}),
|
||||||
|
onFilter: (value, record) => value.includes(record.type)
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("payments.fields.memo"),
|
title: t("payments.fields.memo"),
|
||||||
dataIndex: "memo",
|
dataIndex: "memo",
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import { AlertFilled } from "@ant-design/icons";
|
import { AlertFilled } from "@ant-design/icons";
|
||||||
|
import { useMutation } from "@apollo/client";
|
||||||
import { Button, Divider, Dropdown, Form, Input, notification, Popover, Select, Space } from "antd";
|
import { Button, Divider, Dropdown, Form, Input, notification, Popover, Select, Space } from "antd";
|
||||||
import parsePhoneNumber from "libphonenumber-js";
|
import parsePhoneNumber from "libphonenumber-js";
|
||||||
import dayjs from "../../utils/day";
|
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React, { useContext, useState } from "react";
|
import React, { useContext, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Link, useLocation, useNavigate } from "react-router-dom";
|
import { Link, useLocation, useNavigate } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
|
||||||
|
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
|
||||||
import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions";
|
import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions";
|
||||||
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 CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
|
import dayjs from "../../utils/day";
|
||||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
||||||
import DataLabel from "../data-label/data-label.component";
|
import DataLabel from "../data-label/data-label.component";
|
||||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
||||||
import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.component";
|
import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.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 ScheduleEventNote from "./schedule-event.note.component";
|
import ScheduleEventNote from "./schedule-event.note.component";
|
||||||
import { useMutation } from "@apollo/client";
|
|
||||||
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
|
|
||||||
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
|
||||||
import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop
|
bodyshop: selectBodyshop
|
||||||
@@ -127,6 +127,7 @@ export function ScheduleEventComponent({
|
|||||||
<DataLabel label={t("jobs.fields.ownr_ph2")}>
|
<DataLabel label={t("jobs.fields.ownr_ph2")}>
|
||||||
<ChatOpenButton phone={event.job && event.job.ownr_ph2} jobid={event.job.id} />
|
<ChatOpenButton phone={event.job && event.job.ownr_ph2} jobid={event.job.id} />
|
||||||
</DataLabel>
|
</DataLabel>
|
||||||
|
<DataLabel hideIfNull label={t("jobs.fields.loss_of_use")}>{(event.job && event.job.loss_of_use) || ""}</DataLabel>
|
||||||
<DataLabel label={t("jobs.fields.alt_transport")}>
|
<DataLabel label={t("jobs.fields.alt_transport")}>
|
||||||
{(event.job && event.job.alt_transport) || ""}
|
{(event.job && event.job.alt_transport) || ""}
|
||||||
<ScheduleAtChange job={event && event.job} />
|
<ScheduleAtChange job={event && event.job} />
|
||||||
|
|||||||
@@ -192,6 +192,23 @@ export function JobLinesUpsertModalComponent({ bodyshop, open, jobLine, handleCa
|
|||||||
<Form.Item label={t("joblines.fields.tax_part")} name="tax_part" valuePropName="checked" initialValue={true}>
|
<Form.Item label={t("joblines.fields.tax_part")} name="tax_part" valuePropName="checked" initialValue={true}>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item dependencies={[["act_price"]]} noStyle>
|
||||||
|
{() => {
|
||||||
|
if (form.getFieldValue("act_price") === 0) {
|
||||||
|
return (
|
||||||
|
<Form.Item
|
||||||
|
label={t("joblines.fields.include_in_part_cnt")}
|
||||||
|
name="include_in_part_cnt"
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ export function JobsCloseExportButton({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!!!jobUpdateResponse.errors) {
|
if (!jobUpdateResponse.errors) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "jobsuccessexport",
|
key: "jobsuccessexport",
|
||||||
@@ -222,7 +222,7 @@ export function JobsCloseExportButton({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
|
<Button onClick={handleQbxml} loading={loading} disabled={disabled} type="primary">
|
||||||
{t("jobs.actions.export")}
|
{t("jobs.actions.export")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ import { auth, logImEXEvent } from "../../firebase/firebase.utils";
|
|||||||
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
|
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
|
||||||
import { UPDATE_JOBS } from "../../graphql/jobs.queries";
|
import { UPDATE_JOBS } from "../../graphql/jobs.queries";
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
|
||||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import client from "../../utils/GraphQLClient";
|
import client from "../../utils/GraphQLClient";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
@@ -165,7 +165,7 @@ export function JobsExportAllButton({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!!!jobUpdateResponse.errors) {
|
if (!jobUpdateResponse.errors) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "jobsuccessexport",
|
key: "jobsuccessexport",
|
||||||
@@ -213,13 +213,13 @@ export function JobsExportAllButton({
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!!completedCallback) completedCallback([]);
|
if (completedCallback) completedCallback([]);
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled || jobIds?.length > 10}>
|
<Button onClick={handleQbxml} loading={loading} disabled={disabled || jobIds?.length > 10} type="primary">
|
||||||
{t("jobs.actions.exportselected")}
|
{t("jobs.actions.exportselected")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { EditFilled } from "@ant-design/icons";
|
import { EditFilled } from "@ant-design/icons";
|
||||||
import { Alert, Card, Col, Row, Space, Table, Typography } from "antd";
|
import { Alert, Card, Col, Row, Space, Table, Typography } from "antd";
|
||||||
import _ from "lodash";
|
|
||||||
import React, { useEffect, useMemo, useState } from "react";
|
import React, { useEffect, useMemo, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -9,11 +8,11 @@ import { selectTechnician } from "../../redux/tech/tech.selectors";
|
|||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
|
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
||||||
import LaborAllocationsAdjustmentEdit from "../labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component";
|
import LaborAllocationsAdjustmentEdit from "../labor-allocations-adjustment-edit/labor-allocations-adjustment-edit.component";
|
||||||
|
import UpsellComponent, { upsellEnum } from "../upsell/upsell.component";
|
||||||
import "./labor-allocations-table.styles.scss";
|
import "./labor-allocations-table.styles.scss";
|
||||||
import { CalculateAllocationsTotals } from "./labor-allocations-table.utility";
|
import { CalculateAllocationsTotals } from "./labor-allocations-table.utility";
|
||||||
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
|
||||||
import UpsellComponent, { upsellEnum } from "../upsell/upsell.component";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
technician: selectTechnician
|
technician: selectTechnician
|
||||||
@@ -65,6 +64,7 @@ export function LaborAllocationsTable({
|
|||||||
key: "total",
|
key: "total",
|
||||||
sorter: (a, b) => a.total - b.total,
|
sorter: (a, b) => a.total - b.total,
|
||||||
sortOrder: state.sortedInfo.columnKey === "total" && state.sortedInfo.order,
|
sortOrder: state.sortedInfo.columnKey === "total" && state.sortedInfo.order,
|
||||||
|
align: "right",
|
||||||
render: (text, record) => record.total.toFixed(1)
|
render: (text, record) => record.total.toFixed(1)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -73,6 +73,7 @@ export function LaborAllocationsTable({
|
|||||||
key: "hrs_claimed",
|
key: "hrs_claimed",
|
||||||
sorter: (a, b) => a.claimed - b.claimed,
|
sorter: (a, b) => a.claimed - b.claimed,
|
||||||
sortOrder: state.sortedInfo.columnKey === "claimed" && state.sortedInfo.order,
|
sortOrder: state.sortedInfo.columnKey === "claimed" && state.sortedInfo.order,
|
||||||
|
align: "right",
|
||||||
render: (text, record) => record.claimed && record.claimed.toFixed(1)
|
render: (text, record) => record.claimed && record.claimed.toFixed(1)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -81,6 +82,7 @@ export function LaborAllocationsTable({
|
|||||||
key: "adjustments",
|
key: "adjustments",
|
||||||
sorter: (a, b) => a.adjustments - b.adjustments,
|
sorter: (a, b) => a.adjustments - b.adjustments,
|
||||||
sortOrder: state.sortedInfo.columnKey === "adjustments" && state.sortedInfo.order,
|
sortOrder: state.sortedInfo.columnKey === "adjustments" && state.sortedInfo.order,
|
||||||
|
align: "right",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
{record.adjustments.toFixed(1)}
|
{record.adjustments.toFixed(1)}
|
||||||
@@ -100,17 +102,17 @@ export function LaborAllocationsTable({
|
|||||||
{
|
{
|
||||||
title: t("jobs.labels.difference"),
|
title: t("jobs.labels.difference"),
|
||||||
dataIndex: "difference",
|
dataIndex: "difference",
|
||||||
|
|
||||||
key: "difference",
|
key: "difference",
|
||||||
sorter: (a, b) => a.difference - b.difference,
|
sorter: (a, b) => a.difference - b.difference,
|
||||||
sortOrder: state.sortedInfo.columnKey === "difference" && state.sortedInfo.order,
|
sortOrder: state.sortedInfo.columnKey === "difference" && state.sortedInfo.order,
|
||||||
|
align: "right",
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<strong
|
<strong
|
||||||
style={{
|
style={{
|
||||||
color: record.difference >= 0 ? "green" : "red"
|
color: record.difference.toFixed(1) >= 0 ? "green" : "red"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{_.round(record.difference, 1)}
|
{(Math.abs(record.difference) < 0.05 ? 0 : record.difference).toFixed(1)}
|
||||||
</strong>
|
</strong>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -129,7 +131,6 @@ export function LaborAllocationsTable({
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => `${record.op_code_desc || ""}${record.alt_partm ? ` ${record.alt_partm}` : ""}`
|
render: (text, record) => `${record.op_code_desc || ""}${record.alt_partm ? ` ${record.alt_partm}` : ""}`
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("joblines.fields.act_price"),
|
title: t("joblines.fields.act_price"),
|
||||||
dataIndex: "act_price",
|
dataIndex: "act_price",
|
||||||
@@ -187,7 +188,7 @@ export function LaborAllocationsTable({
|
|||||||
{ hrs_total: 0, hrs_claimed: 0, adjustments: 0, difference: 0 }
|
{ hrs_total: 0, hrs_claimed: 0, adjustments: 0, difference: 0 }
|
||||||
);
|
);
|
||||||
|
|
||||||
if (summary.difference !== 0 && typeof warningCallback === "function") {
|
if (Math.abs(summary.difference.toFixed(1)) !== 0 && typeof warningCallback === "function") {
|
||||||
warningCallback({ key: "labor", warning: t("jobs.labels.outstandinghours") });
|
warningCallback({ key: "labor", warning: t("jobs.labels.outstandinghours") });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,19 +218,21 @@ export function LaborAllocationsTable({
|
|||||||
summary={() => (
|
summary={() => (
|
||||||
<Table.Summary.Row>
|
<Table.Summary.Row>
|
||||||
<Table.Summary.Cell>
|
<Table.Summary.Cell>
|
||||||
<Typography.Title level={4}>{t("general.labels.totals")}</Typography.Title>
|
<Typography.Title level={4} style={{ margin: 0, lineHeight: 1 }}>
|
||||||
|
{t("general.labels.totals")}
|
||||||
|
</Typography.Title>
|
||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
<Table.Summary.Cell>{summary.hrs_total.toFixed(1)}</Table.Summary.Cell>
|
<Table.Summary.Cell align="right">{summary.hrs_total.toFixed(1)}</Table.Summary.Cell>
|
||||||
<Table.Summary.Cell>{summary.hrs_claimed.toFixed(1)}</Table.Summary.Cell>
|
<Table.Summary.Cell align="right">{summary.hrs_claimed.toFixed(1)}</Table.Summary.Cell>
|
||||||
<Table.Summary.Cell>{summary.adjustments.toFixed(1)}</Table.Summary.Cell>
|
<Table.Summary.Cell align="right">{summary.adjustments.toFixed(1)}</Table.Summary.Cell>
|
||||||
<Table.Summary.Cell>
|
<Table.Summary.Cell align="right">
|
||||||
<Typography.Text
|
<Typography.Text
|
||||||
style={{
|
style={{
|
||||||
fontWeight: "bold",
|
fontWeight: "bold",
|
||||||
color: summary.difference >= 0 ? "green" : "red"
|
color: summary.difference.toFixed(1) >= 0 ? "green" : "red"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{summary.difference.toFixed(1)}
|
{(Math.abs(summary.difference) < 0.05 ? 0 : summary.difference).toFixed(1)}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
</Table.Summary.Cell>
|
</Table.Summary.Cell>
|
||||||
</Table.Summary.Row>
|
</Table.Summary.Row>
|
||||||
@@ -261,11 +264,10 @@ export function LaborAllocationsTable({
|
|||||||
</Card>
|
</Card>
|
||||||
</Col>
|
</Col>
|
||||||
)}
|
)}
|
||||||
{showWarning && summary.difference !== 0 && (
|
{showWarning && Math.abs(summary.difference.toFixed(1)) !== 0 && (
|
||||||
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstandinghours")} />
|
<Alert style={{ margin: "8px 0px" }} type="warning" message={t("jobs.labels.outstandinghours")} />
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(mapStateToProps, null)(LaborAllocationsTable);
|
export default connect(mapStateToProps, null)(LaborAllocationsTable);
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function PayableExportAll({
|
|||||||
let PartnerResponse;
|
let PartnerResponse;
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (!!loadingCallback) loadingCallback(true);
|
if (loadingCallback) loadingCallback(true);
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||||
PartnerResponse = await axios.post(`/qbo/payables`, {
|
PartnerResponse = await axios.post(`/qbo/payables`, {
|
||||||
bills: billids,
|
bills: billids,
|
||||||
@@ -85,7 +85,7 @@ export function PayableExportAll({
|
|||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("bills.errors.exporting-partner")
|
message: t("bills.errors.exporting-partner")
|
||||||
});
|
});
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -152,7 +152,7 @@ export function PayableExportAll({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!!!billUpdateResponse.errors) {
|
if (!billUpdateResponse.errors) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "billsuccessexport",
|
key: "billsuccessexport",
|
||||||
@@ -187,8 +187,8 @@ export function PayableExportAll({
|
|||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(proms);
|
await Promise.all(proms);
|
||||||
if (!!completedCallback) completedCallback([]);
|
if (completedCallback) completedCallback([]);
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ export function PayableExportAll({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled || billids?.length > 10}>
|
<Button onClick={handleQbxml} loading={loading} disabled={disabled || billids?.length > 10} type="primary">
|
||||||
{t("jobs.actions.exportselected")}
|
{t("jobs.actions.exportselected")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export function PayableExportButton({
|
|||||||
logImEXEvent("accounting_export_payable");
|
logImEXEvent("accounting_export_payable");
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (!!loadingCallback) loadingCallback(true);
|
if (loadingCallback) loadingCallback(true);
|
||||||
|
|
||||||
//Check if it's a QBO Setup.
|
//Check if it's a QBO Setup.
|
||||||
let PartnerResponse;
|
let PartnerResponse;
|
||||||
@@ -88,7 +88,7 @@ export function PayableExportButton({
|
|||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("bills.errors.exporting-partner")
|
message: t("bills.errors.exporting-partner")
|
||||||
});
|
});
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -149,7 +149,7 @@ export function PayableExportButton({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!!!billUpdateResponse.errors) {
|
if (!billUpdateResponse.errors) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "billsuccessexport",
|
key: "billsuccessexport",
|
||||||
@@ -186,7 +186,7 @@ export function PayableExportButton({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -198,7 +198,7 @@ export function PayableExportButton({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
|
<Button onClick={handleQbxml} loading={loading} disabled={disabled} type="primary">
|
||||||
{t("jobs.actions.export")}
|
{t("jobs.actions.export")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function PaymentExportButton({
|
|||||||
} else {
|
} else {
|
||||||
//Default is QBD
|
//Default is QBD
|
||||||
|
|
||||||
if (!!loadingCallback) loadingCallback(true);
|
if (loadingCallback) loadingCallback(true);
|
||||||
|
|
||||||
let QbXmlResponse;
|
let QbXmlResponse;
|
||||||
try {
|
try {
|
||||||
@@ -88,7 +88,7 @@ export function PaymentExportButton({
|
|||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("payments.errors.exporting-partner")
|
message: t("payments.errors.exporting-partner")
|
||||||
});
|
});
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ export function PaymentExportButton({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!!!paymentUpdateResponse.errors) {
|
if (!paymentUpdateResponse.errors) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "paymentsuccessexport",
|
key: "paymentsuccessexport",
|
||||||
@@ -184,12 +184,12 @@ export function PaymentExportButton({
|
|||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled}>
|
<Button onClick={handleQbxml} loading={loading} disabled={disabled} type="primary">
|
||||||
{t("jobs.actions.export")}
|
{t("jobs.actions.export")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function PaymentsExportAllButton({
|
|||||||
|
|
||||||
const handleQbxml = async () => {
|
const handleQbxml = async () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (!!loadingCallback) loadingCallback(true);
|
if (loadingCallback) loadingCallback(true);
|
||||||
let PartnerResponse;
|
let PartnerResponse;
|
||||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||||
PartnerResponse = await axios.post(`/qbo/payments`, {
|
PartnerResponse = await axios.post(`/qbo/payments`, {
|
||||||
@@ -76,7 +76,7 @@ export function PaymentsExportAllButton({
|
|||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("payments.errors.exporting-partner")
|
message: t("payments.errors.exporting-partner")
|
||||||
});
|
});
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ export function PaymentsExportAllButton({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!!!paymentUpdateResponse.errors) {
|
if (!paymentUpdateResponse.errors) {
|
||||||
notification.open({
|
notification.open({
|
||||||
type: "success",
|
type: "success",
|
||||||
key: "paymentsuccessexport",
|
key: "paymentsuccessexport",
|
||||||
@@ -174,13 +174,13 @@ export function PaymentsExportAllButton({
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
await Promise.all(proms);
|
await Promise.all(proms);
|
||||||
if (!!completedCallback) completedCallback([]);
|
if (completedCallback) completedCallback([]);
|
||||||
if (!!loadingCallback) loadingCallback(false);
|
if (loadingCallback) loadingCallback(false);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button onClick={handleQbxml} loading={loading} disabled={disabled || paymentIds?.length > 10}>
|
<Button onClick={handleQbxml} loading={loading} disabled={disabled || paymentIds?.length > 10} type="primary">
|
||||||
{t("jobs.actions.exportselected")}
|
{t("jobs.actions.exportselected")}
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -555,7 +555,7 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={["md_email_cc", "parts_order"]}
|
name={["md_email_cc", "parts_order"]}
|
||||||
label={t("bodyshop.fields.md_email_cc", { template: "parts_order" })}
|
label={t("bodyshop.fields.md_email_cc", { template: "parts_orders" })}
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
@@ -567,9 +567,7 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={["md_email_cc", "parts_return_slip"]}
|
name={["md_email_cc", "parts_return_slip"]}
|
||||||
label={t("bodyshop.fields.md_email_cc", {
|
label={t("bodyshop.fields.md_email_cc", { template: "parts_returns" })}
|
||||||
template: "parts_return_slip"
|
|
||||||
})}
|
|
||||||
rules={[
|
rules={[
|
||||||
{
|
{
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
@@ -1261,7 +1259,7 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
|||||||
key={`${index}prt_dsmk_p`}
|
key={`${index}prt_dsmk_p`}
|
||||||
name={[field.name, "prt_dsmk_p"]}
|
name={[field.name, "prt_dsmk_p"]}
|
||||||
>
|
>
|
||||||
<InputNumber precision={0} min={0} max={100} />
|
<InputNumber precision={0} min={-100} max={100} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("joblines.fields.ah_detail_line")}
|
label={t("joblines.fields.ah_detail_line")}
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export const QUERY_PAYMENTS_FOR_EXPORT = gql`
|
|||||||
transactionid
|
transactionid
|
||||||
paymentnum
|
paymentnum
|
||||||
date
|
date
|
||||||
|
type
|
||||||
exportlogs {
|
exportlogs {
|
||||||
id
|
id
|
||||||
successful
|
successful
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export const QUERY_ALL_ACTIVE_APPOINTMENTS = gql`
|
|||||||
est_ct_fn
|
est_ct_fn
|
||||||
est_ct_ln
|
est_ct_ln
|
||||||
comment
|
comment
|
||||||
|
loss_of_use
|
||||||
labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) {
|
labhrs: joblines_aggregate(where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } }) {
|
||||||
aggregate {
|
aggregate {
|
||||||
sum {
|
sum {
|
||||||
|
|||||||
@@ -238,6 +238,7 @@ export const UPDATE_JOB_LINE = gql`
|
|||||||
convertedtolbr
|
convertedtolbr
|
||||||
convertedtolbr_data
|
convertedtolbr_data
|
||||||
assigned_team
|
assigned_team
|
||||||
|
include_in_part_cnt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -581,6 +581,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
status
|
status
|
||||||
tax_part
|
tax_part
|
||||||
unq_seq
|
unq_seq
|
||||||
|
include_in_part_cnt
|
||||||
}
|
}
|
||||||
kmin
|
kmin
|
||||||
kmout
|
kmout
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1444,7 +1444,8 @@ export const TemplateList = (type, context) => {
|
|||||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
field: i18n.t("jobs.fields.date_exported")
|
field: i18n.t("jobs.fields.date_exported")
|
||||||
},
|
},
|
||||||
group: "sales"
|
group: "sales",
|
||||||
|
featureNameRestricted: "export"
|
||||||
},
|
},
|
||||||
gsr_by_estimator: {
|
gsr_by_estimator: {
|
||||||
title: i18n.t("reportcenter.templates.gsr_by_estimator"),
|
title: i18n.t("reportcenter.templates.gsr_by_estimator"),
|
||||||
@@ -1865,7 +1866,8 @@ export const TemplateList = (type, context) => {
|
|||||||
object: i18n.t("reportcenter.labels.objects.jobs"),
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
field: i18n.t("jobs.fields.date_open")
|
field: i18n.t("jobs.fields.date_open")
|
||||||
},
|
},
|
||||||
group: "jobs"
|
group: "jobs",
|
||||||
|
featureNameRestricted: "bills"
|
||||||
},
|
},
|
||||||
psr_by_make: {
|
psr_by_make: {
|
||||||
title: i18n.t("reportcenter.templates.psr_by_make"),
|
title: i18n.t("reportcenter.templates.psr_by_make"),
|
||||||
@@ -1901,7 +1903,8 @@ export const TemplateList = (type, context) => {
|
|||||||
object: i18n.t("reportcenter.labels.objects.parts_orders"),
|
object: i18n.t("reportcenter.labels.objects.parts_orders"),
|
||||||
field: i18n.t("parts_orders.fields.order_date")
|
field: i18n.t("parts_orders.fields.order_date")
|
||||||
},
|
},
|
||||||
group: "jobs"
|
group: "jobs",
|
||||||
|
featureNameRestricted: "bills"
|
||||||
},
|
},
|
||||||
returns_grouped_by_vendor_detailed: {
|
returns_grouped_by_vendor_detailed: {
|
||||||
title: i18n.t("reportcenter.templates.returns_grouped_by_vendor_detailed"),
|
title: i18n.t("reportcenter.templates.returns_grouped_by_vendor_detailed"),
|
||||||
@@ -1913,7 +1916,8 @@ export const TemplateList = (type, context) => {
|
|||||||
object: i18n.t("reportcenter.labels.objects.parts_orders"),
|
object: i18n.t("reportcenter.labels.objects.parts_orders"),
|
||||||
field: i18n.t("parts_orders.fields.order_date")
|
field: i18n.t("parts_orders.fields.order_date")
|
||||||
},
|
},
|
||||||
group: "jobs"
|
group: "jobs",
|
||||||
|
featureNameRestricted: "bills"
|
||||||
},
|
},
|
||||||
scheduled_parts_list: {
|
scheduled_parts_list: {
|
||||||
title: i18n.t("reportcenter.templates.scheduled_parts_list"),
|
title: i18n.t("reportcenter.templates.scheduled_parts_list"),
|
||||||
@@ -2225,7 +2229,19 @@ export const TemplateList = (type, context) => {
|
|||||||
field: i18n.t("jobs.fields.date_open")
|
field: i18n.t("jobs.fields.date_open")
|
||||||
},
|
},
|
||||||
group: "jobs"
|
group: "jobs"
|
||||||
}
|
},
|
||||||
|
purchases_by_date_excel: {
|
||||||
|
title: i18n.t("reportcenter.templates.purchases_by_date_excel"),
|
||||||
|
subject: i18n.t("reportcenter.templates.purchases_by_date_excel"),
|
||||||
|
key: "purchases_by_date_excel",
|
||||||
|
reporttype: "excel",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.bills"),
|
||||||
|
field: i18n.t("bills.fields.date")
|
||||||
|
},
|
||||||
|
group: "purchases"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
...(!type || type === "courtesycarcontract"
|
...(!type || type === "courtesycarcontract"
|
||||||
|
|||||||
@@ -207,6 +207,7 @@
|
|||||||
- default_prod_list_view
|
- default_prod_list_view
|
||||||
- id
|
- id
|
||||||
- kanban_settings
|
- kanban_settings
|
||||||
|
- notification_settings
|
||||||
- qbo_realmId
|
- qbo_realmId
|
||||||
- shopid
|
- shopid
|
||||||
- useremail
|
- useremail
|
||||||
@@ -222,6 +223,7 @@
|
|||||||
- authlevel
|
- authlevel
|
||||||
- default_prod_list_view
|
- default_prod_list_view
|
||||||
- kanban_settings
|
- kanban_settings
|
||||||
|
- notification_settings
|
||||||
- qbo_realmId
|
- qbo_realmId
|
||||||
filter:
|
filter:
|
||||||
user:
|
user:
|
||||||
@@ -681,6 +683,31 @@
|
|||||||
- exported:
|
- exported:
|
||||||
_eq: false
|
_eq: false
|
||||||
event_triggers:
|
event_triggers:
|
||||||
|
- name: notifications_bills
|
||||||
|
definition:
|
||||||
|
enable_manual: false
|
||||||
|
insert:
|
||||||
|
columns: '*'
|
||||||
|
retry_conf:
|
||||||
|
interval_sec: 10
|
||||||
|
num_retries: 0
|
||||||
|
timeout_sec: 60
|
||||||
|
webhook_from_env: HASURA_API_URL
|
||||||
|
headers:
|
||||||
|
- name: event-secret
|
||||||
|
value_from_env: EVENT_SECRET
|
||||||
|
request_transform:
|
||||||
|
body:
|
||||||
|
action: transform
|
||||||
|
template: |-
|
||||||
|
{
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
method: POST
|
||||||
|
query_params: {}
|
||||||
|
template_engine: Kriti
|
||||||
|
url: '{{$base_url}}/notifications/events/handleBillsChange'
|
||||||
|
version: 2
|
||||||
- name: os_bills
|
- name: os_bills
|
||||||
definition:
|
definition:
|
||||||
delete:
|
delete:
|
||||||
@@ -2805,6 +2832,80 @@
|
|||||||
_eq: X-Hasura-User-Id
|
_eq: X-Hasura-User-Id
|
||||||
- active:
|
- active:
|
||||||
_eq: true
|
_eq: true
|
||||||
|
- table:
|
||||||
|
name: job_watchers
|
||||||
|
schema: public
|
||||||
|
object_relationships:
|
||||||
|
- name: job
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: jobid
|
||||||
|
- name: user
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: user_email
|
||||||
|
insert_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
user:
|
||||||
|
_and:
|
||||||
|
- associations:
|
||||||
|
active:
|
||||||
|
_eq: true
|
||||||
|
- authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
columns:
|
||||||
|
- user_email
|
||||||
|
- created_at
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
comment: ""
|
||||||
|
select_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- user_email
|
||||||
|
- created_at
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
filter:
|
||||||
|
user:
|
||||||
|
_and:
|
||||||
|
- associations:
|
||||||
|
active:
|
||||||
|
_eq: true
|
||||||
|
- authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
comment: ""
|
||||||
|
update_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- user_email
|
||||||
|
- created_at
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
filter:
|
||||||
|
user:
|
||||||
|
_and:
|
||||||
|
- associations:
|
||||||
|
active:
|
||||||
|
_eq: true
|
||||||
|
- authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
check: null
|
||||||
|
comment: ""
|
||||||
|
delete_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
filter:
|
||||||
|
user:
|
||||||
|
_and:
|
||||||
|
- associations:
|
||||||
|
active:
|
||||||
|
_eq: true
|
||||||
|
- authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
comment: ""
|
||||||
- table:
|
- table:
|
||||||
name: joblines
|
name: joblines
|
||||||
schema: public
|
schema: public
|
||||||
@@ -2896,6 +2997,7 @@
|
|||||||
- est_seq
|
- est_seq
|
||||||
- glass_flag
|
- glass_flag
|
||||||
- id
|
- id
|
||||||
|
- include_in_part_cnt
|
||||||
- ioucreated
|
- ioucreated
|
||||||
- jobid
|
- jobid
|
||||||
- lbr_amt
|
- lbr_amt
|
||||||
@@ -2965,6 +3067,7 @@
|
|||||||
- est_seq
|
- est_seq
|
||||||
- glass_flag
|
- glass_flag
|
||||||
- id
|
- id
|
||||||
|
- include_in_part_cnt
|
||||||
- ioucreated
|
- ioucreated
|
||||||
- jobid
|
- jobid
|
||||||
- lbr_amt
|
- lbr_amt
|
||||||
@@ -3045,6 +3148,7 @@
|
|||||||
- est_seq
|
- est_seq
|
||||||
- glass_flag
|
- glass_flag
|
||||||
- id
|
- id
|
||||||
|
- include_in_part_cnt
|
||||||
- ioucreated
|
- ioucreated
|
||||||
- jobid
|
- jobid
|
||||||
- lbr_amt
|
- lbr_amt
|
||||||
@@ -4326,6 +4430,58 @@
|
|||||||
template_engine: Kriti
|
template_engine: Kriti
|
||||||
url: '{{$base_url}}/record-handler/arms'
|
url: '{{$base_url}}/record-handler/arms'
|
||||||
version: 2
|
version: 2
|
||||||
|
- name: notifications_jobs
|
||||||
|
definition:
|
||||||
|
enable_manual: false
|
||||||
|
insert:
|
||||||
|
columns: '*'
|
||||||
|
update:
|
||||||
|
columns:
|
||||||
|
- queued_for_parts
|
||||||
|
- employee_prep
|
||||||
|
- clm_total
|
||||||
|
- towin
|
||||||
|
- employee_body
|
||||||
|
- converted
|
||||||
|
- scheduled_in
|
||||||
|
- scheduled_completion
|
||||||
|
- scheduled_delivery
|
||||||
|
- actual_delivery
|
||||||
|
- actual_completion
|
||||||
|
- alt_transport
|
||||||
|
- date_exported
|
||||||
|
- status
|
||||||
|
- employee_csr
|
||||||
|
- actual_in
|
||||||
|
- deliverchecklist
|
||||||
|
- comment
|
||||||
|
- job_totals
|
||||||
|
- employee_refinish
|
||||||
|
- inproduction
|
||||||
|
- production_vars
|
||||||
|
- intakechecklist
|
||||||
|
- cieca_ttl
|
||||||
|
- date_invoiced
|
||||||
|
retry_conf:
|
||||||
|
interval_sec: 10
|
||||||
|
num_retries: 0
|
||||||
|
timeout_sec: 60
|
||||||
|
webhook_from_env: HASURA_API_URL
|
||||||
|
headers:
|
||||||
|
- name: event-secret
|
||||||
|
value_from_env: EVENT_SECRET
|
||||||
|
request_transform:
|
||||||
|
body:
|
||||||
|
action: transform
|
||||||
|
template: |-
|
||||||
|
{
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
method: POST
|
||||||
|
query_params: {}
|
||||||
|
template_engine: Kriti
|
||||||
|
url: '{{$base_url}}/notifications/events/handleJobsChange'
|
||||||
|
version: 2
|
||||||
- name: os_jobs
|
- name: os_jobs
|
||||||
definition:
|
definition:
|
||||||
delete:
|
delete:
|
||||||
@@ -4669,6 +4825,57 @@
|
|||||||
_eq: X-Hasura-User-Id
|
_eq: X-Hasura-User-Id
|
||||||
- active:
|
- active:
|
||||||
_eq: true
|
_eq: true
|
||||||
|
- table:
|
||||||
|
name: notifications
|
||||||
|
schema: public
|
||||||
|
object_relationships:
|
||||||
|
- name: association
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: associationid
|
||||||
|
- name: job
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: jobid
|
||||||
|
select_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- associationid
|
||||||
|
- created_at
|
||||||
|
- fcm_data
|
||||||
|
- fcm_message
|
||||||
|
- fcm_title
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
- meta
|
||||||
|
- read
|
||||||
|
- ui_translation_meta
|
||||||
|
- ui_translation_string
|
||||||
|
- updated_at
|
||||||
|
filter:
|
||||||
|
association:
|
||||||
|
_and:
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
comment: ""
|
||||||
|
update_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- meta
|
||||||
|
- read
|
||||||
|
filter:
|
||||||
|
association:
|
||||||
|
_and:
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
check: null
|
||||||
|
comment: ""
|
||||||
- table:
|
- table:
|
||||||
name: owners
|
name: owners
|
||||||
schema: public
|
schema: public
|
||||||
@@ -4909,6 +5116,32 @@
|
|||||||
- active:
|
- active:
|
||||||
_eq: true
|
_eq: true
|
||||||
check: null
|
check: null
|
||||||
|
event_triggers:
|
||||||
|
- name: notifications_parts_dispatch
|
||||||
|
definition:
|
||||||
|
enable_manual: false
|
||||||
|
insert:
|
||||||
|
columns: '*'
|
||||||
|
retry_conf:
|
||||||
|
interval_sec: 10
|
||||||
|
num_retries: 0
|
||||||
|
timeout_sec: 60
|
||||||
|
webhook_from_env: HASURA_API_URL
|
||||||
|
headers:
|
||||||
|
- name: event-secret
|
||||||
|
value_from_env: EVENT_SECRET
|
||||||
|
request_transform:
|
||||||
|
body:
|
||||||
|
action: transform
|
||||||
|
template: |-
|
||||||
|
{
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
method: POST
|
||||||
|
query_params: {}
|
||||||
|
template_engine: Kriti
|
||||||
|
url: '{{$base_url}}/notifications/events/handlePartsDispatchChange'
|
||||||
|
version: 2
|
||||||
- table:
|
- table:
|
||||||
name: parts_dispatch_lines
|
name: parts_dispatch_lines
|
||||||
schema: public
|
schema: public
|
||||||
@@ -5879,6 +6112,36 @@
|
|||||||
_eq: true
|
_eq: true
|
||||||
check: null
|
check: null
|
||||||
event_triggers:
|
event_triggers:
|
||||||
|
- name: notifications_tasks
|
||||||
|
definition:
|
||||||
|
enable_manual: false
|
||||||
|
insert:
|
||||||
|
columns: '*'
|
||||||
|
update:
|
||||||
|
columns:
|
||||||
|
- assigned_to
|
||||||
|
- completed
|
||||||
|
- description
|
||||||
|
retry_conf:
|
||||||
|
interval_sec: 10
|
||||||
|
num_retries: 0
|
||||||
|
timeout_sec: 60
|
||||||
|
webhook_from_env: HASURA_API_URL
|
||||||
|
headers:
|
||||||
|
- name: event-secret
|
||||||
|
value_from_env: EVENT_SECRET
|
||||||
|
request_transform:
|
||||||
|
body:
|
||||||
|
action: transform
|
||||||
|
template: |-
|
||||||
|
{
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
method: POST
|
||||||
|
query_params: {}
|
||||||
|
template_engine: Kriti
|
||||||
|
url: '{{$base_url}}/notifications/events/handleTasksChange'
|
||||||
|
version: 2
|
||||||
- name: tasks_assigned_changed
|
- name: tasks_assigned_changed
|
||||||
definition:
|
definition:
|
||||||
enable_manual: false
|
enable_manual: false
|
||||||
@@ -6035,6 +6298,32 @@
|
|||||||
_eq: X-Hasura-User-Id
|
_eq: X-Hasura-User-Id
|
||||||
- active:
|
- active:
|
||||||
_eq: true
|
_eq: true
|
||||||
|
event_triggers:
|
||||||
|
- name: notifications_time_tickets
|
||||||
|
definition:
|
||||||
|
enable_manual: false
|
||||||
|
insert:
|
||||||
|
columns: '*'
|
||||||
|
retry_conf:
|
||||||
|
interval_sec: 10
|
||||||
|
num_retries: 0
|
||||||
|
timeout_sec: 60
|
||||||
|
webhook_from_env: HASURA_API_URL
|
||||||
|
headers:
|
||||||
|
- name: event-secret
|
||||||
|
value_from_env: EVENT_SECRET
|
||||||
|
request_transform:
|
||||||
|
body:
|
||||||
|
action: transform
|
||||||
|
template: |-
|
||||||
|
{
|
||||||
|
"success": true
|
||||||
|
}
|
||||||
|
method: POST
|
||||||
|
query_params: {}
|
||||||
|
template_engine: Kriti
|
||||||
|
url: '{{$base_url}}/notifications/events/handleTimeTicketsChange'
|
||||||
|
version: 2
|
||||||
- table:
|
- table:
|
||||||
name: transitions
|
name: transitions
|
||||||
schema: public
|
schema: public
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."associations" add column "notification_settings" jsonb
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."associations" add column "notification_settings" jsonb
|
||||||
|
null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP TABLE "public"."notifications";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE TABLE "public"."notifications" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "job_id" uuid NOT NULL, "association_id" uuid NOT NULL, "ui_translation_string" text NOT NULL, "ui_translation_meta" jsonb, "fcm_title" text NOT NULL, "fcm_message" text NOT NULL, "fcm_data" jsonb, "read" timestamptz, "meta" jsonb, "scenario" Integer NOT NULL, PRIMARY KEY ("id") , FOREIGN KEY ("job_id") REFERENCES "public"."jobs"("id") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("association_id") REFERENCES "public"."associations"("id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"));COMMENT ON TABLE "public"."notifications" IS E'Real Time Notifications System';
|
||||||
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
comment on column "public"."notifications"."scenario" is E'Real Time Notifications System';
|
||||||
|
alter table "public"."notifications" alter column "scenario" drop not null;
|
||||||
|
alter table "public"."notifications" add column "scenario" int4;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."notifications" drop column "scenario" cascade;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."notifications" add column "scenario" text
|
||||||
|
-- not null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."notifications" add column "scenario" text
|
||||||
|
not null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP TABLE "public"."job_watchers";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE TABLE "public"."job_watchers" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "job_id" uuid NOT NULL, "user_email" text NOT NULL, "created_at" timestamptz NOT NULL DEFAULT now(), PRIMARY KEY ("id") , FOREIGN KEY ("user_email") REFERENCES "public"."users"("email") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("job_id") REFERENCES "public"."jobs"("id") ON UPDATE restrict ON DELETE restrict, UNIQUE ("id"));COMMENT ON TABLE "public"."job_watchers" IS E'Job Watchers';
|
||||||
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
comment on column "public"."notifications"."scenario" is E'Real Time Notifications System';
|
||||||
|
alter table "public"."notifications" alter column "scenario" drop not null;
|
||||||
|
alter table "public"."notifications" add column "scenario" text;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."notifications" drop column "scenario" cascade;
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- update associations set notification_settings = '{}';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
update associations set notification_settings = '{}';
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."associations" alter column "notification_settings" drop not null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."associations" alter column "notification_settings" set not null;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- update notifications set meta = '{}';
|
||||||
|
-- update notifications set fcm_data = '{}';
|
||||||
|
-- update notifications set ui_translation_meta = '{}';
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
update notifications set meta = '{}';
|
||||||
|
update notifications set fcm_data = '{}';
|
||||||
|
update notifications set ui_translation_meta = '{}';
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."notifications" alter column "meta" drop not null;
|
||||||
|
ALTER TABLE "public"."notifications" ALTER COLUMN "meta" drop default;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."notifications" alter column "meta" set default jsonb_build_object();
|
||||||
|
alter table "public"."notifications" alter column "meta" set not null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."notifications" alter column "fcm_data" drop not null;
|
||||||
|
ALTER TABLE "public"."notifications" ALTER COLUMN "fcm_data" drop default;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."notifications" alter column "fcm_data" set default jsonb_build_object();
|
||||||
|
alter table "public"."notifications" alter column "fcm_data" set not null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."notifications" alter column "ui_translation_meta" drop not null;
|
||||||
|
ALTER TABLE "public"."notifications" ALTER COLUMN "ui_translation_meta" drop default;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."notifications" alter column "ui_translation_meta" set default jsonb_build_object();
|
||||||
|
alter table "public"."notifications" alter column "ui_translation_meta" set not null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."notifications" rename column "jobid" to "job_id";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."notifications" rename column "job_id" to "jobid";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."notifications" rename column "associationid" to "association_id";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."notifications" rename column "association_id" to "associationid";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."job_watchers" rename column "jobid" to "job_id";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."job_watchers" rename column "job_id" to "jobid";
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."joblines" add column "include_in_part_cnt" boolean
|
||||||
|
-- not null default 'false';
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."joblines" add column "include_in_part_cnt" boolean
|
||||||
|
not null default 'false';
|
||||||
10
hasura/migrations/1736890690896_run_sql_migration/down.sql
Normal file
10
hasura/migrations/1736890690896_run_sql_migration/down.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- CREATE OR REPLACE VIEW "public"."joblines_status" AS
|
||||||
|
-- SELECT j.jobid,
|
||||||
|
-- j.status,
|
||||||
|
-- count(1) AS count,
|
||||||
|
-- j.part_type
|
||||||
|
-- FROM joblines j
|
||||||
|
-- WHERE ((j.part_type IS NOT NULL) AND (j.part_type <> 'PAE'::text) AND (j.part_type <> 'PAS'::text) AND (j.part_type <> 'PASL'::text) AND ((j.part_qty)::numeric <> (0)::numeric) AND ((j.act_price <> (0)::numeric) OR (j.include_in_part_cnt is TRUE))AND (j.removed IS FALSE))
|
||||||
|
-- GROUP BY j.jobid, j.status, j.part_type;
|
||||||
8
hasura/migrations/1736890690896_run_sql_migration/up.sql
Normal file
8
hasura/migrations/1736890690896_run_sql_migration/up.sql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
CREATE OR REPLACE VIEW "public"."joblines_status" AS
|
||||||
|
SELECT j.jobid,
|
||||||
|
j.status,
|
||||||
|
count(1) AS count,
|
||||||
|
j.part_type
|
||||||
|
FROM joblines j
|
||||||
|
WHERE ((j.part_type IS NOT NULL) AND (j.part_type <> 'PAE'::text) AND (j.part_type <> 'PAS'::text) AND (j.part_type <> 'PASL'::text) AND ((j.part_qty)::numeric <> (0)::numeric) AND ((j.act_price <> (0)::numeric) OR (j.include_in_part_cnt is TRUE))AND (j.removed IS FALSE))
|
||||||
|
GROUP BY j.jobid, j.status, j.part_type;
|
||||||
10
hasura/migrations/1736890701752_run_sql_migration/down.sql
Normal file
10
hasura/migrations/1736890701752_run_sql_migration/down.sql
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- CREATE OR REPLACE VIEW "public"."joblines_status" AS
|
||||||
|
-- SELECT j.jobid,
|
||||||
|
-- j.status,
|
||||||
|
-- count(1) AS count,
|
||||||
|
-- j.part_type
|
||||||
|
-- FROM joblines j
|
||||||
|
-- WHERE ((j.part_type IS NOT NULL) AND (j.part_type <> 'PAE'::text) AND (j.part_type <> 'PAS'::text) AND (j.part_type <> 'PASL'::text) AND ((j.part_qty)::numeric <> (0)::numeric) AND ((j.act_price <> (0)::numeric) OR (j.include_in_part_cnt is TRUE))AND (j.removed IS FALSE))
|
||||||
|
-- GROUP BY j.jobid, j.status, j.part_type;
|
||||||
8
hasura/migrations/1736890701752_run_sql_migration/up.sql
Normal file
8
hasura/migrations/1736890701752_run_sql_migration/up.sql
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
CREATE OR REPLACE VIEW "public"."joblines_status" AS
|
||||||
|
SELECT j.jobid,
|
||||||
|
j.status,
|
||||||
|
count(1) AS count,
|
||||||
|
j.part_type
|
||||||
|
FROM joblines j
|
||||||
|
WHERE ((j.part_type IS NOT NULL) AND (j.part_type <> 'PAE'::text) AND (j.part_type <> 'PAS'::text) AND (j.part_type <> 'PASL'::text) AND ((j.part_qty)::numeric <> (0)::numeric) AND ((j.act_price <> (0)::numeric) OR (j.include_in_part_cnt is TRUE))AND (j.removed IS FALSE))
|
||||||
|
GROUP BY j.jobid, j.status, j.part_type;
|
||||||
@@ -34,7 +34,7 @@ exports.default = async (req, res) => {
|
|||||||
|
|
||||||
//Query the usage data.
|
//Query the usage data.
|
||||||
const queryResults = await client.request(queries.STATUS_UPDATE, {
|
const queryResults = await client.request(queries.STATUS_UPDATE, {
|
||||||
today: moment().startOf("day").subtract(3, "days"),
|
today: moment().startOf("day").subtract(7, "days"),
|
||||||
period: moment().subtract(90, "days").startOf("day")
|
period: moment().subtract(90, "days").startOf("day")
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ Usage Report for ${moment().format("MM/DD/YYYY")} for Rome Online Customers.
|
|||||||
Notes:
|
Notes:
|
||||||
- Days Since Creation: The number of days since the shop was created. Only shops created in the last 90 days are included.
|
- Days Since Creation: The number of days since the shop was created. Only shops created in the last 90 days are included.
|
||||||
- Updated values should be higher than created values.
|
- Updated values should be higher than created values.
|
||||||
- Counts are inclusive of the last 3 days of data.
|
- Counts are inclusive of the last 7 days of data.
|
||||||
`,
|
`,
|
||||||
attachments: [{ filename: `RO Usage Report ${moment().format("MM/DD/YYYY")}.csv`, content: csv }]
|
attachments: [{ filename: `RO Usage Report ${moment().format("MM/DD/YYYY")}.csv`, content: csv }]
|
||||||
})
|
})
|
||||||
|
|||||||
5
server/notifications/eventHandlers/handeJobsChange.js
Normal file
5
server/notifications/eventHandlers/handeJobsChange.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const handleJobsChange = (req, res) => {
|
||||||
|
return res.status(200).json({ message: "Jobs change handled." });
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = handleJobsChange;
|
||||||
5
server/notifications/eventHandlers/handleBillsChange.js
Normal file
5
server/notifications/eventHandlers/handleBillsChange.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const handleBillsChange = (req, res) => {
|
||||||
|
return res.status(200).json({ message: "Bills change handled." });
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = handleBillsChange;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
const handlePartsDispatchChange = (req, res) => {
|
||||||
|
return res.status(200).json({ message: "Parts Dispatch change handled." });
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = handlePartsDispatchChange;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
const handlePartsOrderChange = (req, res) => {
|
||||||
|
return res.status(200).json({ message: "Parts Order change handled." });
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = handlePartsOrderChange;
|
||||||
5
server/notifications/eventHandlers/handleTasksChange.js
Normal file
5
server/notifications/eventHandlers/handleTasksChange.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
const handleTasksChange = (req, res) => {
|
||||||
|
return res.status(200).json({ message: "Tasks change handled." });
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = handleTasksChange;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
const handleTimeTicketsChange = (req, res) => {
|
||||||
|
return res.status(200).json({ message: "Time Tickets change handled." });
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = handleTimeTicketsChange;
|
||||||
@@ -1,12 +1,28 @@
|
|||||||
const express = require("express");
|
const express = require("express");
|
||||||
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
const validateFirebaseIdTokenMiddleware = require("../middleware/validateFirebaseIdTokenMiddleware");
|
||||||
const { subscribe, unsubscribe, sendNotification } = require("../firebase/firebase-handler");
|
const { subscribe, unsubscribe, sendNotification } = require("../firebase/firebase-handler");
|
||||||
|
const eventAuthorizationMiddleware = require("../middleware/eventAuthorizationMIddleware");
|
||||||
|
|
||||||
|
const handlePartsOrderChange = require("../notifications/eventHandlers/handlePartsOrderChange");
|
||||||
|
const handlePartsDispatchChange = require("../notifications/eventHandlers/handlePartsDispatchChange");
|
||||||
|
const handleTasksChange = require("../notifications/eventHandlers/handleTasksChange");
|
||||||
|
const handleTimeTicketsChange = require("../notifications/eventHandlers/handleTimeTicketsChange");
|
||||||
|
const handleJobsChange = require("../notifications/eventHandlers/handeJobsChange");
|
||||||
|
const handleBillsChange = require("../notifications/eventHandlers/handleBillsChange");
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
|
|
||||||
router.use(validateFirebaseIdTokenMiddleware);
|
// These are FCM handlers
|
||||||
|
router.post("/subscribe", validateFirebaseIdTokenMiddleware, subscribe);
|
||||||
|
router.post("/unsubscribe", validateFirebaseIdTokenMiddleware, unsubscribe);
|
||||||
|
router.post("/sendtestnotification", validateFirebaseIdTokenMiddleware, sendNotification);
|
||||||
|
|
||||||
router.post("/subscribe", subscribe);
|
// Hasura Entry points for creating notifications
|
||||||
router.post("/unsubscribe", unsubscribe);
|
router.post("/events/handleJobsChange", eventAuthorizationMiddleware, handleJobsChange);
|
||||||
router.post("/sendtestnotification", sendNotification);
|
router.post("/events/handleBillsChange", eventAuthorizationMiddleware, handleBillsChange);
|
||||||
|
router.post("/events/handlePartsOrderChange", eventAuthorizationMiddleware, handlePartsOrderChange);
|
||||||
|
router.post("/events/handlePartsDispatchChange", eventAuthorizationMiddleware, handlePartsDispatchChange);
|
||||||
|
router.post("/events/handleTasksChange", eventAuthorizationMiddleware, handleTasksChange);
|
||||||
|
router.post("/events/handleTimeTicketsChange", eventAuthorizationMiddleware, handleTimeTicketsChange);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user