Merge branch 'release/2023-08-11' into feature/IO-2278-parts-dispatching
This commit is contained in:
@@ -4318,6 +4318,48 @@
|
|||||||
<folder_node>
|
<folder_node>
|
||||||
<name>dms</name>
|
<name>dms</name>
|
||||||
<children>
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>apcontrol</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>appostingaccount</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>cashierid</name>
|
<name>cashierid</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -14025,6 +14067,48 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>scheduledintoday</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>scheduledouttoday</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>
|
||||||
@@ -23886,6 +23970,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>dms_unsold</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>dms_wip_acctnumber</name>
|
<name>dms_wip_acctnumber</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -43605,6 +43710,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>jobs_scheduled_completion</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>lag_time</name>
|
<name>lag_time</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -148,6 +148,10 @@
|
|||||||
background: #e7f3ff !important;
|
background: #e7f3ff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-table-tbody > tr.ant-table-row-selected > td {
|
||||||
|
background: #e6f7ff !important;
|
||||||
|
}
|
||||||
|
|
||||||
.job-line-manual {
|
.job-line-manual {
|
||||||
color: tomato;
|
color: tomato;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { useApolloClient, useMutation } from "@apollo/client";
|
import { useApolloClient, useMutation } from "@apollo/client";
|
||||||
import { Button, Checkbox, Form, Modal, notification, Space } from "antd";
|
import { Button, Checkbox, Form, Modal, Space, notification } from "antd";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React, { useEffect, useState, useMemo } 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";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { INSERT_NEW_BILL } from "../../graphql/bills.queries";
|
import { INSERT_NEW_BILL } from "../../graphql/bills.queries";
|
||||||
|
import { UPDATE_INVENTORY_LINES } from "../../graphql/inventory.queries";
|
||||||
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
|
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
|
||||||
import {
|
import {
|
||||||
QUERY_JOB_LBR_ADJUSTMENTS,
|
QUERY_JOB_LBR_ADJUSTMENTS,
|
||||||
UPDATE_JOB,
|
UPDATE_JOB,
|
||||||
} from "../../graphql/jobs.queries";
|
} from "../../graphql/jobs.queries";
|
||||||
import { MUTATION_MARK_RETURN_RECEIVED } from "../../graphql/parts-orders.queries";
|
import { MUTATION_MARK_RETURN_RECEIVED } from "../../graphql/parts-orders.queries";
|
||||||
import { UPDATE_INVENTORY_LINES } from "../../graphql/inventory.queries";
|
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
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";
|
||||||
@@ -20,15 +20,15 @@ import {
|
|||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser,
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
import confirmDialog from "../../utils/asyncConfirm";
|
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import BillFormContainer from "../bill-form/bill-form.container";
|
|
||||||
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
|
||||||
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
|
||||||
import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
|
|
||||||
import useLocalStorage from "../../utils/useLocalStorage";
|
|
||||||
import { GenerateDocument } from "../../utils/RenderTemplate";
|
import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
|
import confirmDialog from "../../utils/asyncConfirm";
|
||||||
|
import useLocalStorage from "../../utils/useLocalStorage";
|
||||||
|
import BillFormContainer from "../bill-form/bill-form.container";
|
||||||
|
import { CalculateBillTotal } from "../bill-form/bill-form.totals.utility";
|
||||||
|
import { handleUpload as handleLocalUpload } from "../documents-local-upload/documents-local-upload.utility";
|
||||||
|
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
billEnterModal: selectBillEnterModal,
|
billEnterModal: selectBillEnterModal,
|
||||||
@@ -126,6 +126,17 @@ function BillEnterModalContainer({
|
|||||||
deductedfromlbr: deductedfromlbr,
|
deductedfromlbr: deductedfromlbr,
|
||||||
lbr_adjustment,
|
lbr_adjustment,
|
||||||
joblineid: i.joblineid === "noline" ? null : i.joblineid,
|
joblineid: i.joblineid === "noline" ? null : i.joblineid,
|
||||||
|
applicable_taxes: {
|
||||||
|
federal:
|
||||||
|
(i.applicable_taxes && i.applicable_taxes.federal) ||
|
||||||
|
false,
|
||||||
|
state:
|
||||||
|
(i.applicable_taxes && i.applicable_taxes.state) ||
|
||||||
|
false,
|
||||||
|
local:
|
||||||
|
(i.applicable_taxes && i.applicable_taxes.local) ||
|
||||||
|
false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Icon, { UploadOutlined } from "@ant-design/icons";
|
import Icon, { UploadOutlined } from "@ant-design/icons";
|
||||||
import { useApolloClient } from "@apollo/client";
|
import { useApolloClient } from "@apollo/client";
|
||||||
import { MdOpenInNew } from "react-icons/md";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import {
|
import {
|
||||||
Alert,
|
Alert,
|
||||||
Divider,
|
Divider,
|
||||||
@@ -12,14 +12,17 @@ import {
|
|||||||
Switch,
|
Switch,
|
||||||
Upload,
|
Upload,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
|
import moment from "moment";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { MdOpenInNew } from "react-icons/md";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries";
|
import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import AlertComponent from "../alert/alert.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component";
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||||
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
@@ -28,8 +31,6 @@ import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|||||||
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
||||||
import BillFormLines from "./bill-form.lines.component";
|
import BillFormLines from "./bill-form.lines.component";
|
||||||
import { CalculateBillTotal } from "./bill-form.totals.utility";
|
import { CalculateBillTotal } from "./bill-form.totals.utility";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
|
||||||
import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -58,6 +59,11 @@ export function BillFormComponent({
|
|||||||
{},
|
{},
|
||||||
bodyshop.imexshopid
|
bodyshop.imexshopid
|
||||||
);
|
);
|
||||||
|
const { ClosingPeriod } = useTreatments(
|
||||||
|
["ClosingPeriod"],
|
||||||
|
{},
|
||||||
|
bodyshop.imexshopid
|
||||||
|
);
|
||||||
|
|
||||||
const handleVendorSelect = (props, opt) => {
|
const handleVendorSelect = (props, opt) => {
|
||||||
setDiscount(opt.discount);
|
setDiscount(opt.discount);
|
||||||
@@ -259,6 +265,37 @@ export function BillFormComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(rule, value) {
|
||||||
|
if (
|
||||||
|
ClosingPeriod.treatment === "on" &&
|
||||||
|
bodyshop.accountingconfig.ClosingPeriod
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
moment(value)
|
||||||
|
.startOf("day")
|
||||||
|
.isSameOrAfter(
|
||||||
|
moment(
|
||||||
|
bodyshop.accountingconfig.ClosingPeriod[0]
|
||||||
|
).startOf("day")
|
||||||
|
) &&
|
||||||
|
moment(value)
|
||||||
|
.startOf("day")
|
||||||
|
.isSameOrBefore(
|
||||||
|
moment(
|
||||||
|
bodyshop.accountingconfig.ClosingPeriod[1]
|
||||||
|
).endOf("day")
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return Promise.resolve();
|
||||||
|
} else {
|
||||||
|
return Promise.reject(t("bills.validation.closingperiod"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<FormDatePicker disabled={disabled} />
|
<FormDatePicker disabled={disabled} />
|
||||||
|
|||||||
@@ -1,13 +1,18 @@
|
|||||||
import { Badge, List, Tag } from "antd";
|
import { Badge, List, Tag } from "antd";
|
||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
import {
|
||||||
|
AutoSizer,
|
||||||
|
CellMeasurer,
|
||||||
|
CellMeasurerCache,
|
||||||
|
List as VirtualizedList,
|
||||||
|
} from "react-virtualized";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setSelectedConversation } from "../../redux/messaging/messaging.actions";
|
import { setSelectedConversation } from "../../redux/messaging/messaging.actions";
|
||||||
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
|
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
|
||||||
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
import { TimeAgoFormatter } from "../../utils/DateFormatter";
|
||||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
import { List as VirtualizedList, AutoSizer } from "react-virtualized";
|
|
||||||
|
|
||||||
import "./chat-conversation-list.styles.scss";
|
import "./chat-conversation-list.styles.scss";
|
||||||
|
|
||||||
@@ -24,57 +29,66 @@ function ChatConversationListComponent({
|
|||||||
conversationList,
|
conversationList,
|
||||||
selectedConversation,
|
selectedConversation,
|
||||||
setSelectedConversation,
|
setSelectedConversation,
|
||||||
subscribeToMoreConversations,
|
|
||||||
loadMoreConversations,
|
loadMoreConversations,
|
||||||
}) {
|
}) {
|
||||||
useEffect(
|
const cache = new CellMeasurerCache({
|
||||||
() => subscribeToMoreConversations(),
|
fixedWidth: true,
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
defaultHeight: 60,
|
||||||
[]
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const rowRenderer = ({ index, key, style }) => {
|
const rowRenderer = ({ index, key, style, parent }) => {
|
||||||
const item = conversationList[index];
|
const item = conversationList[index];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<List.Item
|
<CellMeasurer
|
||||||
key={key}
|
key={key}
|
||||||
onClick={() => setSelectedConversation(item.id)}
|
cache={cache}
|
||||||
className={`chat-list-item ${
|
parent={parent}
|
||||||
item.id === selectedConversation
|
columnIndex={0}
|
||||||
? "chat-list-selected-conversation"
|
rowIndex={index}
|
||||||
: null
|
|
||||||
}`}
|
|
||||||
style={style}
|
|
||||||
>
|
>
|
||||||
<div sryle={{ display: "inline-block" }}>
|
<List.Item
|
||||||
{item.label && <div className="chat-name">{item.label}</div>}
|
onClick={() => setSelectedConversation(item.id)}
|
||||||
{item.job_conversations.length > 0 ? (
|
className={`chat-list-item ${
|
||||||
<div className="chat-name">
|
item.id === selectedConversation
|
||||||
{item.job_conversations.map((j, idx) => (
|
? "chat-list-selected-conversation"
|
||||||
<div key={idx}>
|
: null
|
||||||
<OwnerNameDisplay ownerObject={j.job} />
|
}`}
|
||||||
</div>
|
style={style}
|
||||||
))}
|
>
|
||||||
</div>
|
<div
|
||||||
) : (
|
style={{
|
||||||
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
display: "inline-block",
|
||||||
)}
|
}}
|
||||||
</div>
|
>
|
||||||
<div sryle={{ display: "inline-block" }}>
|
{item.label && <div className="chat-name">{item.label}</div>}
|
||||||
<div>
|
{item.job_conversations.length > 0 ? (
|
||||||
{item.job_conversations.length > 0
|
<div className="chat-name">
|
||||||
? item.job_conversations.map((j, idx) => (
|
{item.job_conversations.map((j, idx) => (
|
||||||
<Tag key={idx} className="ro-number-tag">
|
<div key={idx}>
|
||||||
{j.job.ro_number}
|
<OwnerNameDisplay ownerObject={j.job} />
|
||||||
</Tag>
|
</div>
|
||||||
))
|
))}
|
||||||
: null}
|
</div>
|
||||||
|
) : (
|
||||||
|
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
|
<div style={{ display: "inline-block" }}>
|
||||||
</div>
|
<div>
|
||||||
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
{item.job_conversations.length > 0
|
||||||
</List.Item>
|
? item.job_conversations.map((j, idx) => (
|
||||||
|
<Tag key={idx} className="ro-number-tag">
|
||||||
|
{j.job.ro_number}
|
||||||
|
</Tag>
|
||||||
|
))
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
|
||||||
|
</div>
|
||||||
|
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
||||||
|
</List.Item>
|
||||||
|
</CellMeasurer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,7 +100,7 @@ function ChatConversationListComponent({
|
|||||||
height={height}
|
height={height}
|
||||||
width={width}
|
width={width}
|
||||||
rowCount={conversationList.length}
|
rowCount={conversationList.length}
|
||||||
rowHeight={60}
|
rowHeight={cache.rowHeight}
|
||||||
rowRenderer={rowRenderer}
|
rowRenderer={rowRenderer}
|
||||||
onScroll={({ scrollTop, scrollHeight, clientHeight }) => {
|
onScroll={({ scrollTop, scrollHeight, clientHeight }) => {
|
||||||
if (scrollTop + clientHeight === scrollHeight) {
|
if (scrollTop + clientHeight === scrollHeight) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
ShrinkOutlined,
|
ShrinkOutlined,
|
||||||
SyncOutlined,
|
SyncOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { useLazyQuery, useSubscription } from "@apollo/client";
|
import { useLazyQuery, useQuery } from "@apollo/client";
|
||||||
import { Badge, Card, Col, Row, Space, Tag, Tooltip, Typography } from "antd";
|
import { Badge, Card, Col, Row, Space, Tag, Tooltip, Typography } from "antd";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -12,8 +12,7 @@ import { connect } from "react-redux";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import {
|
import {
|
||||||
CONVERSATION_LIST_QUERY,
|
CONVERSATION_LIST_QUERY,
|
||||||
CONVERSATION_LIST_SUBSCRIPTION,
|
UNREAD_CONVERSATION_COUNT,
|
||||||
UNREAD_CONVERSATION_COUNT_SUBSCRIPTION,
|
|
||||||
} from "../../graphql/conversations.queries";
|
} from "../../graphql/conversations.queries";
|
||||||
import { toggleChatVisible } from "../../redux/messaging/messaging.actions";
|
import { toggleChatVisible } from "../../redux/messaging/messaging.actions";
|
||||||
import {
|
import {
|
||||||
@@ -42,19 +41,20 @@ export function ChatPopupComponent({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [pollInterval, setpollInterval] = useState(0);
|
const [pollInterval, setpollInterval] = useState(0);
|
||||||
|
|
||||||
const { data: unreadData } = useSubscription(
|
const { data: unreadData } = useQuery(UNREAD_CONVERSATION_COUNT, {
|
||||||
UNREAD_CONVERSATION_COUNT_SUBSCRIPTION
|
|
||||||
);
|
|
||||||
|
|
||||||
const [
|
|
||||||
getConversations,
|
|
||||||
{ loading, data, called, refetch, fetchMore, subscribeToMore },
|
|
||||||
] = useLazyQuery(CONVERSATION_LIST_QUERY, {
|
|
||||||
fetchPolicy: "network-only",
|
fetchPolicy: "network-only",
|
||||||
nextFetchPolicy: "network-only",
|
nextFetchPolicy: "network-only",
|
||||||
skip: !chatVisible,
|
...(pollInterval > 0 ? { pollInterval } : {}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [getConversations, { loading, data, refetch, fetchMore }] =
|
||||||
|
useLazyQuery(CONVERSATION_LIST_QUERY, {
|
||||||
|
fetchPolicy: "network-only",
|
||||||
|
nextFetchPolicy: "network-only",
|
||||||
|
skip: !chatVisible,
|
||||||
|
...(pollInterval > 0 ? { pollInterval } : {}),
|
||||||
|
});
|
||||||
|
|
||||||
const fcmToken = sessionStorage.getItem("fcmtoken");
|
const fcmToken = sessionStorage.getItem("fcmtoken");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -66,13 +66,13 @@ export function ChatPopupComponent({
|
|||||||
}, [fcmToken]);
|
}, [fcmToken]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (called && chatVisible)
|
if (chatVisible)
|
||||||
getConversations({
|
getConversations({
|
||||||
variables: {
|
variables: {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}, [chatVisible, called, getConversations]);
|
}, [chatVisible, getConversations]);
|
||||||
|
|
||||||
const loadMoreConversations = useCallback(() => {
|
const loadMoreConversations = useCallback(() => {
|
||||||
if (data)
|
if (data)
|
||||||
@@ -119,43 +119,6 @@ export function ChatPopupComponent({
|
|||||||
<ChatConversationListComponent
|
<ChatConversationListComponent
|
||||||
conversationList={data ? data.conversations : []}
|
conversationList={data ? data.conversations : []}
|
||||||
loadMoreConversations={loadMoreConversations}
|
loadMoreConversations={loadMoreConversations}
|
||||||
subscribeToMoreConversations={() =>
|
|
||||||
subscribeToMore({
|
|
||||||
document: CONVERSATION_LIST_SUBSCRIPTION,
|
|
||||||
variables: { offset: 0 },
|
|
||||||
updateQuery: (prev, { subscriptionData }) => {
|
|
||||||
if (
|
|
||||||
!subscriptionData.data ||
|
|
||||||
subscriptionData.data.conversations.length === 0
|
|
||||||
)
|
|
||||||
return prev;
|
|
||||||
|
|
||||||
let conversations = [...prev.conversations];
|
|
||||||
const newConversations =
|
|
||||||
subscriptionData.data.conversations;
|
|
||||||
|
|
||||||
for (const conversation of newConversations) {
|
|
||||||
const index = conversations.findIndex(
|
|
||||||
(prevConversation) =>
|
|
||||||
prevConversation.id === conversation.id
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index !== -1) {
|
|
||||||
conversations.splice(index, 1);
|
|
||||||
conversations.unshift(conversation);
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
conversations.unshift(conversation);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.assign({}, prev, {
|
|
||||||
conversations: conversations,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
|
|||||||
@@ -59,6 +59,14 @@ export default function ContractsCarsComponent({
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "model" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "model" && state.sortedInfo.order,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("courtesycars.fields.color"),
|
||||||
|
dataIndex: "color",
|
||||||
|
key: "color",
|
||||||
|
sorter: (a, b) => alphaSort(a.color, b.color),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "color" && state.sortedInfo.order,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("courtesycars.fields.plate"),
|
title: t("courtesycars.fields.plate"),
|
||||||
dataIndex: "plate",
|
dataIndex: "plate",
|
||||||
@@ -93,6 +101,9 @@ export default function ContractsCarsComponent({
|
|||||||
(cc.model || "")
|
(cc.model || "")
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(state.search.toLowerCase()) ||
|
.includes(state.search.toLowerCase()) ||
|
||||||
|
(cc.color || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(state.search.toLowerCase()) ||
|
||||||
(cc.plate || "").toLowerCase().includes(state.search.toLowerCase())
|
(cc.plate || "").toLowerCase().includes(state.search.toLowerCase())
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,235 @@
|
|||||||
|
import {
|
||||||
|
BranchesOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
PauseCircleOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
import { Card, Space, Table, Tooltip } from "antd";
|
||||||
|
import moment from "moment";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import ChatOpenButton from "../../chat-open-button/chat-open-button.component";
|
||||||
|
import OwnerNameDisplay from "../../owner-name-display/owner-name-display.component";
|
||||||
|
import DashboardRefreshRequired from "../refresh-required.component";
|
||||||
|
|
||||||
|
export default function DashboardScheduledInToday({ data, ...cardProps }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [state, setState] = useState({
|
||||||
|
sortedInfo: {},
|
||||||
|
});
|
||||||
|
if (!data) return null;
|
||||||
|
if (!data.scheduled_in_today)
|
||||||
|
return <DashboardRefreshRequired {...cardProps} />;
|
||||||
|
|
||||||
|
const appt = []; // Flatten Data
|
||||||
|
data.scheduled_in_today.forEach((item) => {
|
||||||
|
var i = {
|
||||||
|
canceled: item.canceled,
|
||||||
|
id: item.id,
|
||||||
|
alt_transport: item.job.alt_transport,
|
||||||
|
clm_no: item.job.clm_no,
|
||||||
|
jobid: item.job.jobid,
|
||||||
|
ins_co_nm: item.job.ins_co_nm,
|
||||||
|
iouparent: item.job.iouparent,
|
||||||
|
ownerid: item.job.ownerid,
|
||||||
|
ownr_co_nm: item.job.ownr_co_nm,
|
||||||
|
ownr_ea: item.job.ownr_ea,
|
||||||
|
ownr_fn: item.job.ownr_fn,
|
||||||
|
ownr_ln: item.job.ownr_ln,
|
||||||
|
ownr_ph1: item.job.ownr_ph1,
|
||||||
|
ownr_ph2: item.job.ownr_ph2,
|
||||||
|
production_vars: item.job.production_vars,
|
||||||
|
ro_number: item.job.ro_number,
|
||||||
|
suspended: item.job.suspended,
|
||||||
|
v_make_desc: item.job.v_make_desc,
|
||||||
|
v_model_desc: item.job.v_model_desc,
|
||||||
|
v_model_yr: item.job.v_model_yr,
|
||||||
|
v_vin: item.job.v_vin,
|
||||||
|
vehicleid: item.job.vehicleid,
|
||||||
|
note: item.note,
|
||||||
|
start: moment(item.start).format("hh:mm a"),
|
||||||
|
title: item.title,
|
||||||
|
};
|
||||||
|
appt.push(i);
|
||||||
|
});
|
||||||
|
appt.sort ( function (a, b) { return new Date(a.start) - new Date(b.start); });
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ro_number"),
|
||||||
|
dataIndex: "ro_number",
|
||||||
|
key: "ro_number",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Link
|
||||||
|
to={"/manage/jobs/" + record.jobid}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<Space>
|
||||||
|
{record.ro_number || t("general.labels.na")}
|
||||||
|
{record.production_vars && record.production_vars.alert ? (
|
||||||
|
<ExclamationCircleFilled className="production-alert" />
|
||||||
|
) : null}
|
||||||
|
{record.suspended && (
|
||||||
|
<PauseCircleOutlined style={{ color: "orangered" }} />
|
||||||
|
)}
|
||||||
|
{record.iouparent && (
|
||||||
|
<Tooltip title={t("jobs.labels.iou")}>
|
||||||
|
<BranchesOutlined style={{ color: "orangered" }} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.owner"),
|
||||||
|
dataIndex: "owner",
|
||||||
|
key: "owner",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => {
|
||||||
|
return record.ownerid ? (
|
||||||
|
<Link
|
||||||
|
to={"/manage/owners/" + record.ownerid}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ownr_ph1"),
|
||||||
|
dataIndex: "ownr_ph1",
|
||||||
|
key: "ownr_ph1",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => (
|
||||||
|
<ChatOpenButton phone={record.ownr_ph1} jobid={record.jobid} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ownr_ph2"),
|
||||||
|
dataIndex: "ownr_ph2",
|
||||||
|
key: "ownr_ph2",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => (
|
||||||
|
<ChatOpenButton phone={record.ownr_ph2} jobid={record.jobid} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ownr_ea"),
|
||||||
|
dataIndex: "ownr_ea",
|
||||||
|
key: "ownr_ea",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => (
|
||||||
|
<ChatOpenButton phone={record.ownr_ea} jobid={record.jobid} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.vehicle"),
|
||||||
|
dataIndex: "vehicle",
|
||||||
|
key: "vehicle",
|
||||||
|
ellipsis: true,
|
||||||
|
render: (text, record) => {
|
||||||
|
return record.vehicleid ? (
|
||||||
|
<Link
|
||||||
|
to={"/manage/vehicles/" + record.vehicleid}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
|
||||||
|
record.v_model_desc || ""
|
||||||
|
}`}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span>{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
|
||||||
|
record.v_model_desc || ""
|
||||||
|
}`}</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ins_co_nm"),
|
||||||
|
dataIndex: "ins_co_nm",
|
||||||
|
key: "ins_co_nm",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("appointments.fields.time"),
|
||||||
|
dataIndex: "start",
|
||||||
|
key: "start",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("appointments.fields.alt_transport"),
|
||||||
|
dataIndex: "alt_transport",
|
||||||
|
key: "alt_transport",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleTableChange = (sorter) => {
|
||||||
|
setState({ ...state, sortedInfo: sorter });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card title={t("dashboard.titles.scheduledintoday", {date: moment().startOf("day").format("MM/DD/YYYY")})} {...cardProps}>
|
||||||
|
<div style={{ height: "100%" }}>
|
||||||
|
<Table
|
||||||
|
onChange={handleTableChange}
|
||||||
|
pagination={{ position: "top", defaultPageSize: 50 }}
|
||||||
|
columns={columns}
|
||||||
|
scroll={{ x: true, y: "calc(100% - 2em)" }}
|
||||||
|
rowKey="id"
|
||||||
|
style={{ height: "85%" }}
|
||||||
|
dataSource={appt}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DashboardScheduledInTodayGql = `
|
||||||
|
scheduled_in_today: appointments(where: {start: {_gte: "${moment()
|
||||||
|
.startOf("day")
|
||||||
|
.toISOString()}", _lte: "${moment()
|
||||||
|
.endOf("day")
|
||||||
|
.toISOString()}"}, canceled: {_eq: false}, block: {_neq: true}}) {
|
||||||
|
canceled
|
||||||
|
id
|
||||||
|
job {
|
||||||
|
alt_transport
|
||||||
|
clm_no
|
||||||
|
jobid: id
|
||||||
|
ins_co_nm
|
||||||
|
iouparent
|
||||||
|
ownerid
|
||||||
|
ownr_co_nm
|
||||||
|
ownr_ea
|
||||||
|
ownr_fn
|
||||||
|
ownr_ln
|
||||||
|
ownr_ph1
|
||||||
|
ownr_ph2
|
||||||
|
production_vars
|
||||||
|
ro_number
|
||||||
|
suspended
|
||||||
|
v_make_desc
|
||||||
|
v_model_desc
|
||||||
|
v_model_yr
|
||||||
|
v_vin
|
||||||
|
vehicleid
|
||||||
|
}
|
||||||
|
note
|
||||||
|
start
|
||||||
|
title
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -0,0 +1,210 @@
|
|||||||
|
import {
|
||||||
|
BranchesOutlined,
|
||||||
|
ExclamationCircleFilled,
|
||||||
|
PauseCircleOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
import { Card, Space, Table, Tooltip } from "antd";
|
||||||
|
import moment from "moment";
|
||||||
|
import React, { useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import ChatOpenButton from "../../chat-open-button/chat-open-button.component";
|
||||||
|
import OwnerNameDisplay from "../../owner-name-display/owner-name-display.component";
|
||||||
|
import DashboardRefreshRequired from "../refresh-required.component";
|
||||||
|
|
||||||
|
export default function DashboardScheduledOutToday({ data, ...cardProps }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [state, setState] = useState({
|
||||||
|
sortedInfo: {},
|
||||||
|
});
|
||||||
|
if (!data) return null;
|
||||||
|
if (!data.scheduled_out_today)
|
||||||
|
return <DashboardRefreshRequired {...cardProps} />;
|
||||||
|
|
||||||
|
data.scheduled_out_today.forEach((item) => {
|
||||||
|
item.scheduled_completion= moment(item.scheduled_completion).format("hh:mm a")
|
||||||
|
});
|
||||||
|
data.scheduled_out_today.sort(function (a, b) {
|
||||||
|
return new Date(a.scheduled_completion) - new Date(b.scheduled_completion);
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ro_number"),
|
||||||
|
dataIndex: "ro_number",
|
||||||
|
key: "ro_number",
|
||||||
|
render: (text, record) => (
|
||||||
|
<Link
|
||||||
|
to={"/manage/jobs/" + record.jobid}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<Space>
|
||||||
|
{record.ro_number || t("general.labels.na")}
|
||||||
|
{record.production_vars && record.production_vars.alert ? (
|
||||||
|
<ExclamationCircleFilled className="production-alert" />
|
||||||
|
) : null}
|
||||||
|
{record.suspended && (
|
||||||
|
<PauseCircleOutlined style={{ color: "orangered" }} />
|
||||||
|
)}
|
||||||
|
{record.iouparent && (
|
||||||
|
<Tooltip title={t("jobs.labels.iou")}>
|
||||||
|
<BranchesOutlined style={{ color: "orangered" }} />
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
</Link>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.owner"),
|
||||||
|
dataIndex: "owner",
|
||||||
|
key: "owner",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => {
|
||||||
|
return record.ownerid ? (
|
||||||
|
<Link
|
||||||
|
to={"/manage/owners/" + record.ownerid}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span>
|
||||||
|
<OwnerNameDisplay ownerObject={record} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ownr_ph1"),
|
||||||
|
dataIndex: "ownr_ph1",
|
||||||
|
key: "ownr_ph1",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => (
|
||||||
|
<ChatOpenButton phone={record.ownr_ph1} jobid={record.jobid} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ownr_ph2"),
|
||||||
|
dataIndex: "ownr_ph2",
|
||||||
|
key: "ownr_ph2",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => (
|
||||||
|
<ChatOpenButton phone={record.ownr_ph2} jobid={record.jobid} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ownr_ea"),
|
||||||
|
dataIndex: "ownr_ea",
|
||||||
|
key: "ownr_ea",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
render: (text, record) => (
|
||||||
|
<ChatOpenButton phone={record.ownr_ea} jobid={record.jobid} />
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.vehicle"),
|
||||||
|
dataIndex: "vehicle",
|
||||||
|
key: "vehicle",
|
||||||
|
ellipsis: true,
|
||||||
|
render: (text, record) => {
|
||||||
|
return record.vehicleid ? (
|
||||||
|
<Link
|
||||||
|
to={"/manage/vehicles/" + record.vehicleid}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
|
||||||
|
record.v_model_desc || ""
|
||||||
|
}`}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span>{`${record.v_model_yr || ""} ${record.v_make_desc || ""} ${
|
||||||
|
record.v_model_desc || ""
|
||||||
|
}`}</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.ins_co_nm"),
|
||||||
|
dataIndex: "ins_co_nm",
|
||||||
|
key: "ins_co_nm",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.scheduled_completion"),
|
||||||
|
dataIndex: "scheduled_completion",
|
||||||
|
key: "scheduled_completion",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: t("appointments.fields.alt_transport"),
|
||||||
|
dataIndex: "alt_transport",
|
||||||
|
key: "alt_transport",
|
||||||
|
ellipsis: true,
|
||||||
|
responsive: ["md"],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleTableChange = (sorter) => {
|
||||||
|
setState({ ...state, sortedInfo: sorter });
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
title={t("dashboard.titles.scheduledouttoday", {
|
||||||
|
date: moment().startOf("day").format("MM/DD/YYYY"),
|
||||||
|
})}
|
||||||
|
{...cardProps}
|
||||||
|
>
|
||||||
|
<div style={{ height: "100%" }}>
|
||||||
|
<Table
|
||||||
|
onChange={handleTableChange}
|
||||||
|
pagination={{ position: "top", defaultPageSize: 50 }}
|
||||||
|
columns={columns}
|
||||||
|
scroll={{ x: true, y: "calc(100% - 2em)" }}
|
||||||
|
rowKey="id"
|
||||||
|
style={{ height: "85%" }}
|
||||||
|
dataSource={data.scheduled_out_today}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const DashboardScheduledOutTodayGql = `
|
||||||
|
scheduled_out_today: jobs(where: {
|
||||||
|
date_invoiced: {_is_null: true},
|
||||||
|
ro_number: {_is_null: false},
|
||||||
|
voided: {_eq: false},
|
||||||
|
scheduled_completion: {_gte: "${moment().startOf("day").toISOString()}",
|
||||||
|
_lte: "${moment().endOf("day").toISOString()}"}}) {
|
||||||
|
alt_transport
|
||||||
|
clm_no
|
||||||
|
jobid: id
|
||||||
|
ins_co_nm
|
||||||
|
iouparent
|
||||||
|
ownerid
|
||||||
|
ownr_co_nm
|
||||||
|
ownr_ea
|
||||||
|
ownr_fn
|
||||||
|
ownr_ln
|
||||||
|
ownr_ph1
|
||||||
|
ownr_ph2
|
||||||
|
production_vars
|
||||||
|
ro_number
|
||||||
|
scheduled_completion
|
||||||
|
suspended
|
||||||
|
v_make_desc
|
||||||
|
v_model_desc
|
||||||
|
v_model_yr
|
||||||
|
v_vin
|
||||||
|
vehicleid
|
||||||
|
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import Icon, { SyncOutlined } from "@ant-design/icons";
|
import Icon, { SyncOutlined } from "@ant-design/icons";
|
||||||
import { gql, useMutation, useQuery } from "@apollo/client";
|
import { gql, useMutation, useQuery } from "@apollo/client";
|
||||||
import { Button, Dropdown, Menu, notification, PageHeader, Space } from "antd";
|
import { Button, Dropdown, Menu, PageHeader, Space, notification } from "antd";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
@@ -37,6 +37,12 @@ import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
|||||||
//Combination of the following:
|
//Combination of the following:
|
||||||
// /node_modules/react-grid-layout/css/styles.css
|
// /node_modules/react-grid-layout/css/styles.css
|
||||||
// /node_modules/react-resizable/css/styles.css
|
// /node_modules/react-resizable/css/styles.css
|
||||||
|
import DashboardScheduledInToday, {
|
||||||
|
DashboardScheduledInTodayGql,
|
||||||
|
} from "../dashboard-components/scheduled-in-today/scheduled-in-today.component";
|
||||||
|
import DashboardScheduledOutToday, {
|
||||||
|
DashboardScheduledOutTodayGql,
|
||||||
|
} from "../dashboard-components/scheduled-out-today/scheduled-out-today.component";
|
||||||
import "./dashboard-grid.styles.scss";
|
import "./dashboard-grid.styles.scss";
|
||||||
import { GenerateDashboardData } from "./dashboard-grid.utils";
|
import { GenerateDashboardData } from "./dashboard-grid.utils";
|
||||||
|
|
||||||
@@ -268,6 +274,28 @@ const componentList = {
|
|||||||
w: 2,
|
w: 2,
|
||||||
h: 2,
|
h: 2,
|
||||||
},
|
},
|
||||||
|
ScheduleInToday: {
|
||||||
|
label: i18next.t("dashboard.titles.scheduledintoday", {
|
||||||
|
date: moment().startOf("day").format("MM/DD/YYYY"),
|
||||||
|
}),
|
||||||
|
component: DashboardScheduledInToday,
|
||||||
|
gqlFragment: DashboardScheduledInTodayGql,
|
||||||
|
minW: 10,
|
||||||
|
minH: 2,
|
||||||
|
w: 10,
|
||||||
|
h: 2,
|
||||||
|
},
|
||||||
|
ScheduleOutToday: {
|
||||||
|
label: i18next.t("dashboard.titles.scheduledouttoday", {
|
||||||
|
date: moment().startOf("day").format("MM/DD/YYYY"),
|
||||||
|
}),
|
||||||
|
component: DashboardScheduledOutToday,
|
||||||
|
gqlFragment: DashboardScheduledOutTodayGql,
|
||||||
|
minW: 10,
|
||||||
|
minH: 2,
|
||||||
|
w: 10,
|
||||||
|
h: 2,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const createDashboardQuery = (state) => {
|
const createDashboardQuery = (state) => {
|
||||||
@@ -283,8 +311,12 @@ const createDashboardQuery = (state) => {
|
|||||||
monthly_sales: jobs(where: {_and: [
|
monthly_sales: jobs(where: {_and: [
|
||||||
{ voided: {_eq: false}},
|
{ voided: {_eq: false}},
|
||||||
{date_invoiced: {_gte: "${moment()
|
{date_invoiced: {_gte: "${moment()
|
||||||
.startOf("month").startOf('day').toISOString()}"}}, {date_invoiced: {_lte: "${moment()
|
.startOf("month")
|
||||||
.endOf("month").endOf('day').toISOString()}"}}]}) {
|
.startOf("day")
|
||||||
|
.toISOString()}"}}, {date_invoiced: {_lte: "${moment()
|
||||||
|
.endOf("month")
|
||||||
|
.endOf("day")
|
||||||
|
.toISOString()}"}}]}) {
|
||||||
id
|
id
|
||||||
ro_number
|
ro_number
|
||||||
date_invoiced
|
date_invoiced
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ export function DmsAllocationsSummaryAp({ socket, bodyshop, billids, title }) {
|
|||||||
key: "status",
|
key: "status",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.ro_number"),
|
title: t("bills.fields.invoice_number"),
|
||||||
dataIndex: ["Posting", "Reference"],
|
dataIndex: ["Posting", "Reference"],
|
||||||
key: "reference",
|
key: "reference",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
Select,
|
Select,
|
||||||
Space,
|
Space,
|
||||||
Statistic,
|
Statistic,
|
||||||
|
Switch,
|
||||||
Typography,
|
Typography,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import Dinero from "dinero.js";
|
import Dinero from "dinero.js";
|
||||||
@@ -183,6 +184,13 @@ export function DmsPostForm({ bodyshop, socket, job, logsRef }) {
|
|||||||
<Space>
|
<Space>
|
||||||
<DmsCdkMakes form={form} socket={socket} job={job} />
|
<DmsCdkMakes form={form} socket={socket} job={job} />
|
||||||
<DmsCdkMakesRefetch />
|
<DmsCdkMakesRefetch />
|
||||||
|
<Form.Item
|
||||||
|
name="dms_unsold"
|
||||||
|
label={t("jobs.fields.dms.dms_unsold")}
|
||||||
|
initialValue={false}
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -311,7 +311,9 @@ function Header({
|
|||||||
icon={<SettingOutlined />}
|
icon={<SettingOutlined />}
|
||||||
>
|
>
|
||||||
<Menu.Item key="shop" icon={<Icon component={GiSettingsKnobs} />}>
|
<Menu.Item key="shop" icon={<Icon component={GiSettingsKnobs} />}>
|
||||||
<Link to="/manage/shop">{t("menus.header.shop_config")}</Link>
|
<Link to="/manage/shop?tab=info">
|
||||||
|
{t("menus.header.shop_config")}
|
||||||
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
<Menu.Item key="dashboard" icon={<DashboardFilled />}>
|
<Menu.Item key="dashboard" icon={<DashboardFilled />}>
|
||||||
<Link to="/manage/dashboard">{t("menus.header.dashboard")}</Link>
|
<Link to="/manage/dashboard">{t("menus.header.dashboard")}</Link>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
|
||||||
import { useMutation } from "@apollo/client";
|
import { useMutation } from "@apollo/client";
|
||||||
import { Button, Form, notification } from "antd";
|
import { Button, Form, notification } from "antd";
|
||||||
|
import moment from "moment";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
|
||||||
import moment from "moment";
|
|
||||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||||
|
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
||||||
|
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||||
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
@@ -38,8 +38,8 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const result = await updateJob({
|
const result = await updateJob({
|
||||||
variables: { jobId: job.id, job: values },
|
variables: { jobId: job.id, job: values },
|
||||||
refetchQueries: ['GET_JOB_BY_PK'],
|
refetchQueries: ["GET_JOB_BY_PK"],
|
||||||
awaitRefetchQueries:true
|
awaitRefetchQueries: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const changedAuditFields = form.getFieldsValue(
|
const changedAuditFields = form.getFieldsValue(
|
||||||
@@ -126,7 +126,10 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
|
|||||||
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
|
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
|
||||||
<DateTimePicker />
|
<DateTimePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.date_repairstarted")} name="date_repairstarted">
|
<Form.Item
|
||||||
|
label={t("jobs.fields.date_repairstarted")}
|
||||||
|
name="date_repairstarted"
|
||||||
|
>
|
||||||
<DateTimePicker />
|
<DateTimePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
@@ -173,6 +176,9 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
|
|||||||
>
|
>
|
||||||
<DateTimePicker />
|
<DateTimePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item label={t("jobs.fields.date_void")} name="date_void">
|
||||||
|
<DateTimePicker />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
import { useMutation } from "@apollo/client";
|
import { gql, useMutation } from "@apollo/client";
|
||||||
import { Button, notification } from "antd";
|
import { Button, notification } from "antd";
|
||||||
import { gql } from "@apollo/client";
|
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
|
import moment from "moment";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.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 moment from "moment";
|
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
|
||||||
import { INSERT_EXPORT_LOG } from "../../graphql/accounting.queries";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
@@ -150,6 +149,10 @@ export function JobAdminMarkReexport({
|
|||||||
|
|
||||||
if (!result.errors) {
|
if (!result.errors) {
|
||||||
notification["success"]({ message: t("jobs.successes.save") });
|
notification["success"]({ message: t("jobs.successes.save") });
|
||||||
|
insertAuditTrail({
|
||||||
|
jobid: job.id,
|
||||||
|
operation: AuditTrailMapping.admin_jobuninvoice(),
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
message: t("jobs.errors.saving", {
|
message: t("jobs.errors.saving", {
|
||||||
|
|||||||
@@ -33,8 +33,9 @@ export function JobsAdminUnvoid({
|
|||||||
mutation UNVOID_JOB($jobId: uuid!) {
|
mutation UNVOID_JOB($jobId: uuid!) {
|
||||||
update_jobs_by_pk(pk_columns: {id: $jobId}, _set: {voided: false, status: "${
|
update_jobs_by_pk(pk_columns: {id: $jobId}, _set: {voided: false, status: "${
|
||||||
bodyshop.md_ro_statuses.default_imported
|
bodyshop.md_ro_statuses.default_imported
|
||||||
}"}) {
|
}", date_void: null}) {
|
||||||
id
|
id
|
||||||
|
date_void
|
||||||
voided
|
voided
|
||||||
status
|
status
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -141,6 +141,10 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
|||||||
<Form.Item label={t("jobs.fields.date_exported")} name="date_exported">
|
<Form.Item label={t("jobs.fields.date_exported")} name="date_exported">
|
||||||
<DateTimePicker disabled={true || jobRO} />
|
<DateTimePicker disabled={true || jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item label={t("jobs.fields.date_void")} name="date_void">
|
||||||
|
<DateTimePicker disabled={true || jobRO} />
|
||||||
|
</Form.Item>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import {
|
|||||||
Dropdown,
|
Dropdown,
|
||||||
Form,
|
Form,
|
||||||
Menu,
|
Menu,
|
||||||
notification,
|
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
Popover,
|
Popover,
|
||||||
Select,
|
Select,
|
||||||
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -24,12 +24,12 @@ import {
|
|||||||
selectBodyshop,
|
selectBodyshop,
|
||||||
selectCurrentUser,
|
selectCurrentUser,
|
||||||
} from "../../redux/user/user.selectors";
|
} from "../../redux/user/user.selectors";
|
||||||
|
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
|
||||||
import JobsDetailHeaderActionsAddevent from "./jobs-detail-header-actions.addevent";
|
import JobsDetailHeaderActionsAddevent from "./jobs-detail-header-actions.addevent";
|
||||||
import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
|
import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
|
||||||
import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component";
|
import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component";
|
||||||
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
|
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
|
||||||
import JobsDetailHeaderActionsExportcustdataComponent from "./jobs-detail-header-actions.exportcustdata.component";
|
import JobsDetailHeaderActionsExportcustdataComponent from "./jobs-detail-header-actions.exportcustdata.component";
|
||||||
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -480,6 +480,7 @@ export function JobsDetailHeaderActions({
|
|||||||
scheduled_in: null,
|
scheduled_in: null,
|
||||||
scheduled_completion: null,
|
scheduled_completion: null,
|
||||||
inproduction: false,
|
inproduction: false,
|
||||||
|
date_void: new Date(),
|
||||||
},
|
},
|
||||||
note: [
|
note: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ export function ScoreboardChart({ sbEntriesByDate, bodyshop }) {
|
|||||||
bodyhrs: dayAcc.bodyhrs + dayVal.bodyhrs,
|
bodyhrs: dayAcc.bodyhrs + dayVal.bodyhrs,
|
||||||
painthrs: dayAcc.painthrs + dayVal.painthrs,
|
painthrs: dayAcc.painthrs + dayVal.painthrs,
|
||||||
sales:
|
sales:
|
||||||
dayAcc.painthrs +
|
dayAcc.sales + dayVal.job.job_totals.totals.subtotal.amount / 100,
|
||||||
dayVal.job.job_totals.totals.subtotal.amount / 100 +
|
|
||||||
2500,
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
{ bodyhrs: 0, painthrs: 0, sales: 0 }
|
{ bodyhrs: 0, painthrs: 0, sales: 0 }
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ export function ShopInfoComponent({ bodyshop, form, saveLoading }) {
|
|||||||
<Tabs
|
<Tabs
|
||||||
defaultActiveKey={search.subtab}
|
defaultActiveKey={search.subtab}
|
||||||
onChange={(key) =>
|
onChange={(key) =>
|
||||||
history.push({ search: `?tab=${search.tab}&subtab=${key}` })
|
history.push({
|
||||||
|
search: `?tab=${search.tab}&subtab=${key}`,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Tabs.TabPane key="general" tab={t("bodyshop.labels.shopinfo")}>
|
<Tabs.TabPane key="general" tab={t("bodyshop.labels.shopinfo")}>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import { useMutation, useQuery } from "@apollo/client";
|
||||||
import ShopInfoComponent from "./shop-info.component";
|
|
||||||
import { Form, notification } from "antd";
|
import { Form, notification } from "antd";
|
||||||
import { useQuery, useMutation } from "@apollo/client";
|
import moment from "moment";
|
||||||
import { QUERY_BODYSHOP, UPDATE_SHOP } from "../../graphql/bodyshop.queries";
|
import React, { useEffect, useState } from "react";
|
||||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
|
||||||
import AlertComponent from "../alert/alert.component";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { QUERY_BODYSHOP, UPDATE_SHOP } from "../../graphql/bodyshop.queries";
|
||||||
|
import AlertComponent from "../alert/alert.component";
|
||||||
import FormsFieldChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
import FormsFieldChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||||
import moment from "moment";
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
|
import ShopInfoComponent from "./shop-info.component";
|
||||||
export default function ShopInfoContainer() {
|
export default function ShopInfoContainer() {
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -52,13 +52,28 @@ export default function ShopInfoContainer() {
|
|||||||
onFinish={handleFinish}
|
onFinish={handleFinish}
|
||||||
initialValues={
|
initialValues={
|
||||||
data
|
data
|
||||||
? {
|
? data.bodyshops[0].accountingconfig.ClosingPeriod
|
||||||
...data.bodyshops[0],
|
? {
|
||||||
schedule_start_time: moment(
|
...data.bodyshops[0],
|
||||||
data.bodyshops[0].schedule_start_time
|
accountingconfig: {
|
||||||
),
|
...data.bodyshops[0].accountingconfig,
|
||||||
schedule_end_time: moment(data.bodyshops[0].schedule_end_time),
|
ClosingPeriod: [
|
||||||
}
|
moment(data.bodyshops[0].accountingconfig.ClosingPeriod[0]),
|
||||||
|
moment(data.bodyshops[0].accountingconfig.ClosingPeriod[1]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
schedule_start_time: moment(
|
||||||
|
data.bodyshops[0].schedule_start_time
|
||||||
|
),
|
||||||
|
schedule_end_time: moment(data.bodyshops[0].schedule_end_time),
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
...data.bodyshops[0],
|
||||||
|
schedule_start_time: moment(
|
||||||
|
data.bodyshops[0].schedule_start_time
|
||||||
|
),
|
||||||
|
schedule_end_time: moment(data.bodyshops[0].schedule_end_time),
|
||||||
|
}
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { DeleteFilled } from "@ant-design/icons";
|
import { DeleteFilled } from "@ant-design/icons";
|
||||||
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
|
DatePicker,
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
@@ -9,8 +11,13 @@ import {
|
|||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
|
import momentTZ from "moment-timezone";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import DatePickerRanges from "../../utils/DatePickerRanges";
|
||||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
import FormItemEmail from "../form-items-formatted/email-form-item.component";
|
import FormItemEmail from "../form-items-formatted/email-form-item.component";
|
||||||
import PhoneFormItem, {
|
import PhoneFormItem, {
|
||||||
@@ -18,12 +25,22 @@ import PhoneFormItem, {
|
|||||||
} from "../form-items-formatted/phone-form-item.component";
|
} from "../form-items-formatted/phone-form-item.component";
|
||||||
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.component";
|
||||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||||
|
|
||||||
import momentTZ from "moment-timezone";
|
|
||||||
const timeZonesList = momentTZ.tz.names();
|
const timeZonesList = momentTZ.tz.names();
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoGeneral);
|
||||||
|
|
||||||
export default function ShopInfoGeneral({ form }) {
|
export function ShopInfoGeneral({ form, bodyshop }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { ClosingPeriod } = useTreatments(
|
||||||
|
["ClosingPeriod"],
|
||||||
|
{},
|
||||||
|
bodyshop && bodyshop.imexshopid
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -392,6 +409,20 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Select mode="tags" />
|
<Select mode="tags" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{ClosingPeriod.treatment === "on" && (
|
||||||
|
<>
|
||||||
|
<Form.Item
|
||||||
|
allowClear
|
||||||
|
name={["accountingconfig", "ClosingPeriod"]}
|
||||||
|
label={t("bodyshop.fields.closingperiod")} //{t("reportcenter.labels.dates")}
|
||||||
|
>
|
||||||
|
<DatePicker.RangePicker
|
||||||
|
format="MM/DD/YYYY"
|
||||||
|
ranges={DatePickerRanges}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow
|
<LayoutFormRow
|
||||||
header={t("bodyshop.labels.scoreboardsetup")}
|
header={t("bodyshop.labels.scoreboardsetup")}
|
||||||
@@ -602,6 +633,20 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Select mode="tags" />
|
<Select mode="tags" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name={["md_email_cc", "parts_return_slip"]}
|
||||||
|
label={t("bodyshop.fields.md_email_cc", {
|
||||||
|
template: "parts_return_slip",
|
||||||
|
})}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
type: "array",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Select mode="tags" />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name={["tt_allow_post_to_invoiced"]}
|
name={["tt_allow_post_to_invoiced"]}
|
||||||
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
|
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
|
||||||
|
|||||||
@@ -162,6 +162,32 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
|||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
)}
|
)}
|
||||||
|
{bodyshop.pbs_serialnumber && (
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.dms.appostingaccount")}
|
||||||
|
name={["pbs_configuration", "appostingaccount"]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{ value: "wip", label: "WIP" },
|
||||||
|
{ value: "cogs", label: "COGS" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
{bodyshop.pbs_serialnumber && (
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.dms.apcontrol")}
|
||||||
|
name={["pbs_configuration", "apcontrol"]}
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{ value: "ro", label: "RO Number" },
|
||||||
|
{ value: "vendordmsid", label: "Vendor DMS ID" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow header={t("bodyshop.labels.dms.cdk.payers")}>
|
<LayoutFormRow header={t("bodyshop.labels.dms.cdk.payers")}>
|
||||||
<Form.List name={["cdk_configuration", "payers"]}>
|
<Form.List name={["cdk_configuration", "payers"]}>
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import {
|
|||||||
Col,
|
Col,
|
||||||
Form,
|
Form,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
notification,
|
|
||||||
Popover,
|
Popover,
|
||||||
Row,
|
Row,
|
||||||
Select,
|
Select,
|
||||||
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
@@ -16,13 +16,14 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { GET_LINE_TICKET_BY_PK } from "../../graphql/jobs-lines.queries";
|
||||||
|
import { UPDATE_JOB_STATUS } from "../../graphql/jobs.queries";
|
||||||
import { UPDATE_TIME_TICKET } from "../../graphql/timetickets.queries";
|
import { UPDATE_TIME_TICKET } from "../../graphql/timetickets.queries";
|
||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
|
||||||
import TechJobClockoutDelete from "../tech-job-clock-out-delete/tech-job-clock-out-delete.component";
|
import TechJobClockoutDelete from "../tech-job-clock-out-delete/tech-job-clock-out-delete.component";
|
||||||
import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component";
|
import { LaborAllocationContainer } from "../time-ticket-modal/time-ticket-modal.component";
|
||||||
import { GET_LINE_TICKET_BY_PK } from "../../graphql/jobs-lines.queries";
|
|
||||||
import { CalculateAllocationsTotals } from "../labor-allocations-table/labor-allocations-table.utility";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -40,6 +41,7 @@ export function TechClockOffButton({
|
|||||||
}) {
|
}) {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [updateTimeticket] = useMutation(UPDATE_TIME_TICKET);
|
const [updateTimeticket] = useMutation(UPDATE_TIME_TICKET);
|
||||||
|
const [updateJobStatus] = useMutation(UPDATE_JOB_STATUS);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
const { queryLoading, data: lineTicketData } = useQuery(
|
const { queryLoading, data: lineTicketData } = useQuery(
|
||||||
GET_LINE_TICKET_BY_PK,
|
GET_LINE_TICKET_BY_PK,
|
||||||
@@ -59,7 +61,8 @@ export function TechClockOffButton({
|
|||||||
|
|
||||||
const handleFinish = async (values) => {
|
const handleFinish = async (values) => {
|
||||||
logImEXEvent("tech_clock_out_job");
|
logImEXEvent("tech_clock_out_job");
|
||||||
|
const status = values.status;
|
||||||
|
delete values.status;
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const result = await updateTimeticket({
|
const result = await updateTimeticket({
|
||||||
variables: {
|
variables: {
|
||||||
@@ -98,6 +101,26 @@ export function TechClockOffButton({
|
|||||||
message: t("timetickets.successes.clockedout"),
|
message: t("timetickets.successes.clockedout"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!isShiftTicket) {
|
||||||
|
const job_update_result = await updateJobStatus({
|
||||||
|
variables: {
|
||||||
|
jobId: jobId,
|
||||||
|
status: status,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!!job_update_result.errors) {
|
||||||
|
notification["error"]({
|
||||||
|
message: t("jobs.errors.updating", {
|
||||||
|
message: JSON.stringify(result.errors),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
notification["success"]({
|
||||||
|
message: t("jobs.successes.updated"),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
if (completedCallback) completedCallback();
|
if (completedCallback) completedCallback();
|
||||||
};
|
};
|
||||||
@@ -195,7 +218,6 @@ export function TechClockOffButton({
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="cost_center"
|
name="cost_center"
|
||||||
label={t("timetickets.fields.cost_center")}
|
label={t("timetickets.fields.cost_center")}
|
||||||
@@ -228,6 +250,29 @@ export function TechClockOffButton({
|
|||||||
</Select>
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
{isShiftTicket ? (
|
||||||
|
<div></div>
|
||||||
|
) : (
|
||||||
|
<Form.Item
|
||||||
|
name="status"
|
||||||
|
label={t("jobs.fields.status")}
|
||||||
|
initialValue={
|
||||||
|
lineTicketData && lineTicketData.jobs_by_pk.status
|
||||||
|
}
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
//message: t("general.validation.required"),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Select>
|
||||||
|
{bodyshop.md_ro_statuses.production_statuses.map((item) => (
|
||||||
|
<Select.Option key={item}></Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
<Button type="primary" htmlType="submit" loading={loading}>
|
<Button type="primary" htmlType="submit" loading={loading}>
|
||||||
{t("general.actions.save")}
|
{t("general.actions.save")}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
import { Alert, Button, Col, Row, Space } from "antd";
|
||||||
|
import i18n from "i18next";
|
||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectUpdateAvailable } from "../../redux/application/application.selectors";
|
||||||
|
import { AlertOutlined } from "@ant-design/icons";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { setUpdateAvailable } from "../../redux/application/application.actions";
|
||||||
|
import { store } from "../../redux/store";
|
||||||
|
import * as serviceWorkerRegistration from "../../serviceWorkerRegistration";
|
||||||
|
|
||||||
|
let globalRegistration;
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
updateAvailable: selectUpdateAvailable,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(UpdateAlert);
|
||||||
|
|
||||||
|
export function UpdateAlert({ updateAvailable }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
if (!updateAvailable) return null;
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
message={t("general.messages.newversiontitle")}
|
||||||
|
showIcon
|
||||||
|
icon={<AlertOutlined />}
|
||||||
|
description={
|
||||||
|
<Row gutter={[16, 16]}>
|
||||||
|
<Col sm={24} md={16} lg={18}>
|
||||||
|
{t("general.messages.newversionmessage")}
|
||||||
|
</Col>
|
||||||
|
<Col sm={24} md={8} lg={6}>
|
||||||
|
<Space wrap>
|
||||||
|
<Button
|
||||||
|
onClick={async () => {
|
||||||
|
window.open("https://imex-online.noticeable.news/", "_blank");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n.t("general.actions.viewreleasenotes")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={async () => {
|
||||||
|
if (globalRegistration && globalRegistration.waiting) {
|
||||||
|
await globalRegistration.unregister();
|
||||||
|
// Makes Workbox call skipWaiting()
|
||||||
|
globalRegistration.waiting.postMessage({
|
||||||
|
type: "SKIP_WAITING",
|
||||||
|
});
|
||||||
|
// Once the service worker is unregistered, we can reload the page to let
|
||||||
|
// the browser download a fresh copy of our app (invalidating the cache)
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{i18n.t("general.actions.refresh")}
|
||||||
|
</Button>
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
}
|
||||||
|
closable={false}
|
||||||
|
type="warning"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onServiceWorkerUpdate = (registration) => {
|
||||||
|
console.log("onServiceWorkerUpdate", registration);
|
||||||
|
globalRegistration = registration;
|
||||||
|
store.dispatch(setUpdateAvailable(true));
|
||||||
|
};
|
||||||
|
|
||||||
|
serviceWorkerRegistration.register({ onUpdate: onServiceWorkerUpdate });
|
||||||
@@ -1,37 +1,5 @@
|
|||||||
import { gql } from "@apollo/client";
|
import { gql } from "@apollo/client";
|
||||||
|
|
||||||
export const CONVERSATION_LIST_SUBSCRIPTION = gql`
|
|
||||||
subscription CONVERSATION_LIST_SUBSCRIPTION($offset: Int!) {
|
|
||||||
conversations(
|
|
||||||
order_by: { updated_at: desc }
|
|
||||||
limit: 1
|
|
||||||
offset: $offset
|
|
||||||
where: { archived: { _eq: false } }
|
|
||||||
) {
|
|
||||||
phone_num
|
|
||||||
id
|
|
||||||
updated_at
|
|
||||||
unreadcnt
|
|
||||||
messages_aggregate(
|
|
||||||
where: { read: { _eq: false }, isoutbound: { _eq: false } }
|
|
||||||
) {
|
|
||||||
aggregate {
|
|
||||||
count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
job_conversations {
|
|
||||||
job {
|
|
||||||
id
|
|
||||||
ro_number
|
|
||||||
ownr_fn
|
|
||||||
ownr_ln
|
|
||||||
ownr_co_nm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const UNREAD_CONVERSATION_COUNT = gql`
|
export const UNREAD_CONVERSATION_COUNT = gql`
|
||||||
query UNREAD_CONVERSATION_COUNT {
|
query UNREAD_CONVERSATION_COUNT {
|
||||||
messages_aggregate(
|
messages_aggregate(
|
||||||
@@ -44,18 +12,6 @@ export const UNREAD_CONVERSATION_COUNT = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const UNREAD_CONVERSATION_COUNT_SUBSCRIPTION = gql`
|
|
||||||
subscription UNREAD_CONVERSATION_COUNT_SUBSCRIPTION {
|
|
||||||
messages_aggregate(
|
|
||||||
where: { read: { _eq: false }, isoutbound: { _eq: false } }
|
|
||||||
) {
|
|
||||||
aggregate {
|
|
||||||
count
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const CONVERSATION_LIST_QUERY = gql`
|
export const CONVERSATION_LIST_QUERY = gql`
|
||||||
query CONVERSATION_LIST_QUERY($offset: Int!) {
|
query CONVERSATION_LIST_QUERY($offset: Int!) {
|
||||||
conversations(
|
conversations(
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export const GET_LINE_TICKET_BY_PK = gql`
|
|||||||
id
|
id
|
||||||
lbr_adjustments
|
lbr_adjustments
|
||||||
converted
|
converted
|
||||||
|
status
|
||||||
}
|
}
|
||||||
joblines(where: { jobid: { _eq: $id }, removed: { _eq: false } }) {
|
joblines(where: { jobid: { _eq: $id }, removed: { _eq: false } }) {
|
||||||
id
|
id
|
||||||
|
|||||||
@@ -682,6 +682,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
date_rentalresp
|
date_rentalresp
|
||||||
date_exported
|
date_exported
|
||||||
date_repairstarted
|
date_repairstarted
|
||||||
|
date_void
|
||||||
status
|
status
|
||||||
owner_owing
|
owner_owing
|
||||||
tax_registration_number
|
tax_registration_number
|
||||||
@@ -1086,6 +1087,7 @@ export const UPDATE_JOB = gql`
|
|||||||
scheduled_completion
|
scheduled_completion
|
||||||
actual_in
|
actual_in
|
||||||
date_repairstarted
|
date_repairstarted
|
||||||
|
date_void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1133,6 +1135,7 @@ export const VOID_JOB = gql`
|
|||||||
update_jobs_by_pk(_set: $job, pk_columns: { id: $jobId }) {
|
update_jobs_by_pk(_set: $job, pk_columns: { id: $jobId }) {
|
||||||
id
|
id
|
||||||
date_exported
|
date_exported
|
||||||
|
date_void
|
||||||
status
|
status
|
||||||
alt_transport
|
alt_transport
|
||||||
ro_number
|
ro_number
|
||||||
@@ -1227,10 +1230,10 @@ export const ACTIVE_JOBS_FOR_AUTOCOMPLETE = gql`
|
|||||||
query ACTIVE_JOBS_FOR_AUTOCOMPLETE($statuses: [String!]!) {
|
query ACTIVE_JOBS_FOR_AUTOCOMPLETE($statuses: [String!]!) {
|
||||||
jobs(where: { status: { _in: $statuses } }) {
|
jobs(where: { status: { _in: $statuses } }) {
|
||||||
id
|
id
|
||||||
|
ownr_co_nm
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
ro_number
|
ro_number
|
||||||
|
|
||||||
vehicleid
|
vehicleid
|
||||||
v_make_desc
|
v_make_desc
|
||||||
v_model_desc
|
v_model_desc
|
||||||
@@ -1258,6 +1261,7 @@ export const SEARCH_JOBS_FOR_AUTOCOMPLETE = gql`
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
|
ownr_co_nm
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
ro_number
|
ro_number
|
||||||
@@ -1274,6 +1278,7 @@ export const SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE = gql`
|
|||||||
query SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE($id: uuid!) {
|
query SEARCH_JOBS_BY_ID_FOR_AUTOCOMPLETE($id: uuid!) {
|
||||||
jobs_by_pk(id: $id) {
|
jobs_by_pk(id: $id) {
|
||||||
id
|
id
|
||||||
|
ownr_co_nm
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
ro_number
|
ro_number
|
||||||
@@ -1292,6 +1297,7 @@ export const SEARCH_FOR_JOBS = gql`
|
|||||||
search_jobs(args: { search: $search }, limit: 25) {
|
search_jobs(args: { search: $search }, limit: 25) {
|
||||||
id
|
id
|
||||||
ro_number
|
ro_number
|
||||||
|
ownr_co_nm
|
||||||
ownr_fn
|
ownr_fn
|
||||||
ownr_ln
|
ownr_ln
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import queryString from "query-string";
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { useHistory, useLocation, Link } from "react-router-dom";
|
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import SocketIO from "socket.io-client";
|
import SocketIO from "socket.io-client";
|
||||||
import AlertComponent from "../../components/alert/alert.component";
|
import AlertComponent from "../../components/alert/alert.component";
|
||||||
@@ -22,6 +22,7 @@ import DmsCustomerSelector from "../../components/dms-customer-selector/dms-cust
|
|||||||
import DmsLogEvents from "../../components/dms-log-events/dms-log-events.component";
|
import DmsLogEvents from "../../components/dms-log-events/dms-log-events.component";
|
||||||
import DmsPostForm from "../../components/dms-post-form/dms-post-form.component";
|
import DmsPostForm from "../../components/dms-post-form/dms-post-form.component";
|
||||||
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||||
|
import { OwnerNameDisplayFunction } from "../../components/owner-name-display/owner-name-display.component";
|
||||||
import { auth } from "../../firebase/firebase.utils";
|
import { auth } from "../../firebase/firebase.utils";
|
||||||
import { QUERY_JOB_EXPORT_DMS } from "../../graphql/jobs.queries";
|
import { QUERY_JOB_EXPORT_DMS } from "../../graphql/jobs.queries";
|
||||||
import {
|
import {
|
||||||
@@ -29,7 +30,6 @@ import {
|
|||||||
setSelectedHeader,
|
setSelectedHeader,
|
||||||
} from "../../redux/application/application.actions";
|
} from "../../redux/application/application.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import { OwnerNameDisplayFunction } from "../../components/owner-name-display/owner-name-display.component";
|
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -46,6 +46,7 @@ export const socket = SocketIO(
|
|||||||
process.env.NODE_ENV === "production"
|
process.env.NODE_ENV === "production"
|
||||||
? process.env.REACT_APP_AXIOS_BASE_API_URL
|
? process.env.REACT_APP_AXIOS_BASE_API_URL
|
||||||
: window.location.origin,
|
: window.location.origin,
|
||||||
|
// "http://localhost:4000", // for dev testing,
|
||||||
{
|
{
|
||||||
path: "/ws",
|
path: "/ws",
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import {
|
|||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
InputNumber,
|
InputNumber,
|
||||||
notification,
|
|
||||||
PageHeader,
|
PageHeader,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
Row,
|
Row,
|
||||||
@@ -17,12 +16,14 @@ import {
|
|||||||
Statistic,
|
Statistic,
|
||||||
Switch,
|
Switch,
|
||||||
Typography,
|
Typography,
|
||||||
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
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";
|
||||||
//import { useHistory } from "react-router-dom";
|
//import { useHistory } from "react-router-dom";
|
||||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
|
import Dinero from "dinero.js";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
@@ -37,7 +38,6 @@ import { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.qu
|
|||||||
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
import { UPDATE_JOB } from "../../graphql/jobs.queries";
|
||||||
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 Dinero from "dinero.js";
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
@@ -55,6 +55,11 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
{},
|
{},
|
||||||
bodyshop && bodyshop.imexshopid
|
bodyshop && bodyshop.imexshopid
|
||||||
);
|
);
|
||||||
|
const { ClosingPeriod } = useTreatments(
|
||||||
|
["ClosingPeriod"],
|
||||||
|
{},
|
||||||
|
bodyshop && bodyshop.imexshopid
|
||||||
|
);
|
||||||
|
|
||||||
const handleFinish = async ({ removefromproduction, ...values }) => {
|
const handleFinish = async ({ removefromproduction, ...values }) => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -254,12 +259,40 @@ export function JobsCloseComponent({ job, bodyshop, jobRO }) {
|
|||||||
if (!value || moment(value).isSameOrAfter(moment(), "day")) {
|
if (!value || moment(value).isSameOrAfter(moment(), "day")) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error(t("jobs.labels.dms.invoicedatefuture"))
|
new Error(t("jobs.labels.dms.invoicedatefuture"))
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(_, value) {
|
||||||
|
if (
|
||||||
|
ClosingPeriod.treatment === "on" &&
|
||||||
|
bodyshop.accountingconfig.ClosingPeriod
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
moment(value).isSameOrAfter(
|
||||||
|
moment(
|
||||||
|
bodyshop.accountingconfig.ClosingPeriod[0]
|
||||||
|
).startOf("day")
|
||||||
|
) &&
|
||||||
|
moment(value).isSameOrBefore(
|
||||||
|
moment(
|
||||||
|
bodyshop.accountingconfig.ClosingPeriod[1]
|
||||||
|
).endOf("day")
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return Promise.resolve();
|
||||||
|
} else {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(t("jobs.labels.closingperiod"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<DateTimePicker
|
<DateTimePicker
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
import * as Sentry from "@sentry/react";
|
import * as Sentry from "@sentry/react";
|
||||||
|
|
||||||
import "./manage.page.styles.scss";
|
import "./manage.page.styles.scss";
|
||||||
|
import UpdateAlert from "../../components/update-alert/update-alert.component";
|
||||||
|
|
||||||
const ManageRootPage = lazy(() =>
|
const ManageRootPage = lazy(() =>
|
||||||
import("../manage-root/manage-root.page.container")
|
import("../manage-root/manage-root.page.container")
|
||||||
@@ -394,6 +395,7 @@ export function Manage({ match, conflict, bodyshop }) {
|
|||||||
<>
|
<>
|
||||||
<ChatAffixContainer />
|
<ChatAffixContainer />
|
||||||
<Layout className="layout-container">
|
<Layout className="layout-container">
|
||||||
|
<UpdateAlert />
|
||||||
<HeaderContainer />
|
<HeaderContainer />
|
||||||
|
|
||||||
<Content className="content-container">
|
<Content className="content-container">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import AlertComponent from "../../components/alert/alert.component";
|
|||||||
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
|
||||||
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
|
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
|
||||||
import { setBodyshop } from "../../redux/user/user.actions";
|
import { setBodyshop } from "../../redux/user/user.actions";
|
||||||
import "../../utils/RegisterSw";
|
//import "../../utils/RegisterSw";
|
||||||
import ManagePage from "./manage.page.component";
|
import ManagePage from "./manage.page.component";
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|||||||
@@ -40,6 +40,10 @@ export function ShopPage({ bodyshop, setSelectedHeader, setBreadcrumbs }) {
|
|||||||
]);
|
]);
|
||||||
}, [t, setSelectedHeader, setBreadcrumbs, bodyshop.shopname]);
|
}, [t, setSelectedHeader, setBreadcrumbs, bodyshop.shopname]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!search.tab) history.push({ search: "?tab=info" });
|
||||||
|
}, [history, search]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RbacWrapper action="shop:config">
|
<RbacWrapper action="shop:config">
|
||||||
<Tabs
|
<Tabs
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import TechSider from "../../components/tech-sider/tech-sider.component";
|
|||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
import FeatureWrapper from "../../components/feature-wrapper/feature-wrapper.component";
|
import FeatureWrapper from "../../components/feature-wrapper/feature-wrapper.component";
|
||||||
import "./tech.page.styles.scss";
|
import "./tech.page.styles.scss";
|
||||||
|
import UpdateAlert from "../../components/update-alert/update-alert.component";
|
||||||
const TimeTicketModalContainer = lazy(() =>
|
const TimeTicketModalContainer = lazy(() =>
|
||||||
import("../../components/time-ticket-modal/time-ticket-modal.container")
|
import("../../components/time-ticket-modal/time-ticket-modal.container")
|
||||||
);
|
);
|
||||||
@@ -59,7 +60,9 @@ export function TechPage({ technician, match }) {
|
|||||||
<TechSider />
|
<TechSider />
|
||||||
<Layout>
|
<Layout>
|
||||||
{technician ? null : <Redirect to={`${match.path}/login`} />}
|
{technician ? null : <Redirect to={`${match.path}/login`} />}
|
||||||
|
<UpdateAlert />
|
||||||
<TechHeader />
|
<TechHeader />
|
||||||
|
|
||||||
<Content className="tech-content-container">
|
<Content className="tech-content-container">
|
||||||
<ErrorBoundary>
|
<ErrorBoundary>
|
||||||
<Suspense
|
<Suspense
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import LoadingSpinner from "../../components/loading-spinner/loading-spinner.com
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import "../../utils/RegisterSw";
|
//import "../../utils/RegisterSw";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
|
|||||||
@@ -62,3 +62,8 @@ export const setProblemJobs = (problemJobs) => ({
|
|||||||
type: ApplicationActionTypes.SET_PROBLEM_JOBS,
|
type: ApplicationActionTypes.SET_PROBLEM_JOBS,
|
||||||
payload: problemJobs,
|
payload: problemJobs,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const setUpdateAvailable = (isUpdateAvailable) => ({
|
||||||
|
type: ApplicationActionTypes.SET_UPDATE_AVAILABLE,
|
||||||
|
payload: isUpdateAvailable,
|
||||||
|
});
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import ApplicationActionTypes from "./application.types";
|
|||||||
const INITIAL_STATE = {
|
const INITIAL_STATE = {
|
||||||
loading: false,
|
loading: false,
|
||||||
online: true,
|
online: true,
|
||||||
|
updateAvailable: false,
|
||||||
breadcrumbs: [],
|
breadcrumbs: [],
|
||||||
recentItems: [],
|
recentItems: [],
|
||||||
selectedHeader: "home",
|
selectedHeader: "home",
|
||||||
@@ -18,6 +19,11 @@ const INITIAL_STATE = {
|
|||||||
|
|
||||||
const applicationReducer = (state = INITIAL_STATE, action) => {
|
const applicationReducer = (state = INITIAL_STATE, action) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case ApplicationActionTypes.SET_UPDATE_AVAILABLE:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
updateAvailable: action.payload,
|
||||||
|
};
|
||||||
case ApplicationActionTypes.SET_SELECTED_HEADER:
|
case ApplicationActionTypes.SET_SELECTED_HEADER:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -48,3 +48,7 @@ export const selectProblemJobs = createSelector(
|
|||||||
[selectApplication],
|
[selectApplication],
|
||||||
(application) => application.problemJobs
|
(application) => application.problemJobs
|
||||||
);
|
);
|
||||||
|
export const selectUpdateAvailable = createSelector(
|
||||||
|
[selectApplication],
|
||||||
|
(application) => application.updateAvailable
|
||||||
|
);
|
||||||
|
|||||||
@@ -12,5 +12,6 @@ const ApplicationActionTypes = {
|
|||||||
SET_ONLINE_STATUS: "SET_ONLINE_STATUS",
|
SET_ONLINE_STATUS: "SET_ONLINE_STATUS",
|
||||||
INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL",
|
INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL",
|
||||||
SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS",
|
SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS",
|
||||||
|
SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE"
|
||||||
};
|
};
|
||||||
export default ApplicationActionTypes;
|
export default ApplicationActionTypes;
|
||||||
|
|||||||
@@ -101,6 +101,7 @@
|
|||||||
"messages": {
|
"messages": {
|
||||||
"admin_jobmarkexported": "ADMIN: Job marked as exported.",
|
"admin_jobmarkexported": "ADMIN: Job marked as exported.",
|
||||||
"admin_jobmarkforreexport": "ADMIN: Job marked for re-export.",
|
"admin_jobmarkforreexport": "ADMIN: Job marked for re-export.",
|
||||||
|
"admin_jobuninvoice": "ADMIN: Job has been uninvoiced.",
|
||||||
"admin_jobunvoid": "ADMIN: Job has been unvoided.",
|
"admin_jobunvoid": "ADMIN: Job has been unvoided.",
|
||||||
"billposted": "Bill with invoice number {{invoice_number}} posted.",
|
"billposted": "Bill with invoice number {{invoice_number}} posted.",
|
||||||
"billupdated": "Bill with invoice number {{invoice_number}} updated.",
|
"billupdated": "Bill with invoice number {{invoice_number}} updated.",
|
||||||
@@ -222,6 +223,7 @@
|
|||||||
"reexport": "Bill marked for re-export."
|
"reexport": "Bill marked for re-export."
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"closingperiod": "This Bill Date is outside of the Closing Period.",
|
||||||
"inventoryquantity": "Quantity must be greater than or equal to what has been added to inventory ({{number}}).",
|
"inventoryquantity": "Quantity must be greater than or equal to what has been added to inventory ({{number}}).",
|
||||||
"manualinhouse": "Manual posting to the in house vendor is restricted. ",
|
"manualinhouse": "Manual posting to the in house vendor is restricted. ",
|
||||||
"unique_invoice_number": "This invoice number has already been entered for this vendor."
|
"unique_invoice_number": "This invoice number has already been entered for this vendor."
|
||||||
@@ -261,6 +263,7 @@
|
|||||||
"bill_local_tax_rate": "Bill - Provincial/State Tax Rate %",
|
"bill_local_tax_rate": "Bill - Provincial/State Tax Rate %",
|
||||||
"bill_state_tax_rate": "Bill - Provincial/State Tax Rate %",
|
"bill_state_tax_rate": "Bill - Provincial/State Tax Rate %",
|
||||||
"city": "City",
|
"city": "City",
|
||||||
|
"closingperiod": "Closing Period",
|
||||||
"country": "Country",
|
"country": "Country",
|
||||||
"dailybodytarget": "Scoreboard - Daily Body Target",
|
"dailybodytarget": "Scoreboard - Daily Body Target",
|
||||||
"dailypainttarget": "Scoreboard - Daily Paint Target",
|
"dailypainttarget": "Scoreboard - Daily Paint Target",
|
||||||
@@ -269,6 +272,8 @@
|
|||||||
"templates": "Delivery Templates"
|
"templates": "Delivery Templates"
|
||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
|
"apcontrol": "AP Control Number",
|
||||||
|
"appostingaccount": "AP Posting Account",
|
||||||
"cashierid": "Cashier ID",
|
"cashierid": "Cashier ID",
|
||||||
"default_journal": "Default Journal",
|
"default_journal": "Default Journal",
|
||||||
"disablebillwip": "Disable bill WIP for A/P Posting",
|
"disablebillwip": "Disable bill WIP for A/P Posting",
|
||||||
@@ -858,7 +863,9 @@
|
|||||||
"prodhrssummary": "Production Hours Summary",
|
"prodhrssummary": "Production Hours Summary",
|
||||||
"productiondollars": "Total dollars in Production",
|
"productiondollars": "Total dollars in Production",
|
||||||
"productionhours": "Total hours in Production",
|
"productionhours": "Total hours in Production",
|
||||||
"projectedmonthlysales": "Projected Monthly Sales"
|
"projectedmonthlysales": "Projected Monthly Sales",
|
||||||
|
"scheduledintoday": "Sheduled In Today: {{date}}",
|
||||||
|
"scheduledouttoday": "Sheduled Out Today: {{date}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
@@ -1118,7 +1125,7 @@
|
|||||||
},
|
},
|
||||||
"messages": {
|
"messages": {
|
||||||
"exception": "$t(titles.app) has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.",
|
"exception": "$t(titles.app) has encountered an error. Please try again. If the problem persists, please submit a support ticket or contact us.",
|
||||||
"newversionmessage": "Click refresh below to update to the latest available version of ImEX Online. Please make sure all other tabs and windows are closed.",
|
"newversionmessage": "Click refresh to update to the latest available version of ImEX Online. Please make sure all other tabs and windows are closed.",
|
||||||
"newversiontitle": "New version of ImEX Online Available",
|
"newversiontitle": "New version of ImEX Online Available",
|
||||||
"noacctfilepath": "There is no accounting file path set. You will not be able to export any items.",
|
"noacctfilepath": "There is no accounting file path set. You will not be able to export any items.",
|
||||||
"nofeatureaccess": "You do not have access to this feature of ImEX Online. Please contact support to request a license for this feature.",
|
"nofeatureaccess": "You do not have access to this feature of ImEX Online. Please contact support to request a license for this feature.",
|
||||||
@@ -1436,6 +1443,7 @@
|
|||||||
"date_repairstarted": "Repairs Started",
|
"date_repairstarted": "Repairs Started",
|
||||||
"date_scheduled": "Scheduled",
|
"date_scheduled": "Scheduled",
|
||||||
"date_towin": "Towed In",
|
"date_towin": "Towed In",
|
||||||
|
"date_void": "Void",
|
||||||
"ded_amt": "Deductible",
|
"ded_amt": "Deductible",
|
||||||
"ded_note": "Deductible Note",
|
"ded_note": "Deductible Note",
|
||||||
"ded_status": "Deductible Status",
|
"ded_status": "Deductible Status",
|
||||||
@@ -1451,6 +1459,7 @@
|
|||||||
"cost_dms_acctnumber": "Cost DMS Acct #",
|
"cost_dms_acctnumber": "Cost DMS Acct #",
|
||||||
"dms_make": "DMS Make",
|
"dms_make": "DMS Make",
|
||||||
"dms_model": "DMS Model",
|
"dms_model": "DMS Model",
|
||||||
|
"dms_unsold": "New, Unsold Vehicle",
|
||||||
"dms_wip_acctnumber": "Cost WIP DMS Acct #",
|
"dms_wip_acctnumber": "Cost WIP DMS Acct #",
|
||||||
"id": "DMS ID",
|
"id": "DMS ID",
|
||||||
"inservicedate": "In Service Date",
|
"inservicedate": "In Service Date",
|
||||||
@@ -1682,6 +1691,7 @@
|
|||||||
"checklists": "Checklists",
|
"checklists": "Checklists",
|
||||||
"closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.",
|
"closeconfirm": "Are you sure you want to close this job? This cannot be easily undone.",
|
||||||
"closejob": "Close Job {{ro_number}}",
|
"closejob": "Close Job {{ro_number}}",
|
||||||
|
"closingperiod": "This Invoice Date is outside of the Closing Period.",
|
||||||
"contracts": "CC Contracts",
|
"contracts": "CC Contracts",
|
||||||
"convertedtolabor": "Lines Converted to Labor",
|
"convertedtolabor": "Lines Converted to Labor",
|
||||||
"cost": "Cost",
|
"cost": "Cost",
|
||||||
@@ -2423,6 +2433,7 @@
|
|||||||
"jobs": {
|
"jobs": {
|
||||||
"individual_job_note": "Job Note RO: {{ro_number}}",
|
"individual_job_note": "Job Note RO: {{ro_number}}",
|
||||||
"parts_order": "Parts Order PO: {{ro_number}} - {{name}}",
|
"parts_order": "Parts Order PO: {{ro_number}} - {{name}}",
|
||||||
|
"parts_return_slip":"Parts Return PO: {{ro_number}} - {{name}}",
|
||||||
"sublet_order": "Sublet Order PO: {{ro_number}} - {{name}}"
|
"sublet_order": "Sublet Order PO: {{ro_number}} - {{name}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2590,6 +2601,7 @@
|
|||||||
"jobs_completed_not_invoiced": "Jobs Completed not Invoiced",
|
"jobs_completed_not_invoiced": "Jobs Completed not Invoiced",
|
||||||
"jobs_invoiced_not_exported": "Jobs Invoiced not Exported",
|
"jobs_invoiced_not_exported": "Jobs Invoiced not Exported",
|
||||||
"jobs_reconcile": "Parts/Sublet/Labor Reconciliation",
|
"jobs_reconcile": "Parts/Sublet/Labor Reconciliation",
|
||||||
|
"jobs_scheduled_completion": "Jobs Scheduled Completion",
|
||||||
"lag_time": "Lag Time",
|
"lag_time": "Lag Time",
|
||||||
"open_orders": "Open Orders by Date",
|
"open_orders": "Open Orders by Date",
|
||||||
"open_orders_csr": "Open Orders by CSR",
|
"open_orders_csr": "Open Orders by CSR",
|
||||||
@@ -2638,6 +2650,7 @@
|
|||||||
"timetickets_summary": "Time Tickets Summary",
|
"timetickets_summary": "Time Tickets Summary",
|
||||||
"unclaimed_hrs": "Unclaimed Hours",
|
"unclaimed_hrs": "Unclaimed Hours",
|
||||||
"void_ros": "Void ROs",
|
"void_ros": "Void ROs",
|
||||||
|
"work_in_progress_jobs": "Work in Progress - Jobs",
|
||||||
"work_in_progress_labour": "Work in Progress - Labor",
|
"work_in_progress_labour": "Work in Progress - Labor",
|
||||||
"work_in_progress_payables": "Work in Progress - Payables"
|
"work_in_progress_payables": "Work in Progress - Payables"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,7 @@
|
|||||||
"messages": {
|
"messages": {
|
||||||
"admin_jobmarkexported": "",
|
"admin_jobmarkexported": "",
|
||||||
"admin_jobmarkforreexport": "",
|
"admin_jobmarkforreexport": "",
|
||||||
|
"admin_jobuninvoice": "",
|
||||||
"admin_jobunvoid": "",
|
"admin_jobunvoid": "",
|
||||||
"billposted": "",
|
"billposted": "",
|
||||||
"billupdated": "",
|
"billupdated": "",
|
||||||
@@ -222,6 +223,7 @@
|
|||||||
"reexport": ""
|
"reexport": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"closingperiod": "",
|
||||||
"inventoryquantity": "",
|
"inventoryquantity": "",
|
||||||
"manualinhouse": "",
|
"manualinhouse": "",
|
||||||
"unique_invoice_number": ""
|
"unique_invoice_number": ""
|
||||||
@@ -261,6 +263,7 @@
|
|||||||
"bill_local_tax_rate": "",
|
"bill_local_tax_rate": "",
|
||||||
"bill_state_tax_rate": "",
|
"bill_state_tax_rate": "",
|
||||||
"city": "",
|
"city": "",
|
||||||
|
"closingperiod": "",
|
||||||
"country": "",
|
"country": "",
|
||||||
"dailybodytarget": "",
|
"dailybodytarget": "",
|
||||||
"dailypainttarget": "",
|
"dailypainttarget": "",
|
||||||
@@ -269,6 +272,8 @@
|
|||||||
"templates": ""
|
"templates": ""
|
||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
|
"apcontrol": "",
|
||||||
|
"appostingaccount": "",
|
||||||
"cashierid": "",
|
"cashierid": "",
|
||||||
"default_journal": "",
|
"default_journal": "",
|
||||||
"disablebillwip": "",
|
"disablebillwip": "",
|
||||||
@@ -858,7 +863,9 @@
|
|||||||
"prodhrssummary": "",
|
"prodhrssummary": "",
|
||||||
"productiondollars": "",
|
"productiondollars": "",
|
||||||
"productionhours": "",
|
"productionhours": "",
|
||||||
"projectedmonthlysales": ""
|
"projectedmonthlysales": "",
|
||||||
|
"scheduledintoday": "",
|
||||||
|
"scheduledouttoday": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
@@ -1436,6 +1443,7 @@
|
|||||||
"date_repairstarted": "",
|
"date_repairstarted": "",
|
||||||
"date_scheduled": "Programado",
|
"date_scheduled": "Programado",
|
||||||
"date_towin": "",
|
"date_towin": "",
|
||||||
|
"date_void": "",
|
||||||
"ded_amt": "Deducible",
|
"ded_amt": "Deducible",
|
||||||
"ded_note": "",
|
"ded_note": "",
|
||||||
"ded_status": "Estado deducible",
|
"ded_status": "Estado deducible",
|
||||||
@@ -1451,6 +1459,7 @@
|
|||||||
"cost_dms_acctnumber": "",
|
"cost_dms_acctnumber": "",
|
||||||
"dms_make": "",
|
"dms_make": "",
|
||||||
"dms_model": "",
|
"dms_model": "",
|
||||||
|
"dms_unsold": "",
|
||||||
"dms_wip_acctnumber": "",
|
"dms_wip_acctnumber": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"inservicedate": "",
|
"inservicedate": "",
|
||||||
@@ -1682,6 +1691,7 @@
|
|||||||
"checklists": "",
|
"checklists": "",
|
||||||
"closeconfirm": "",
|
"closeconfirm": "",
|
||||||
"closejob": "",
|
"closejob": "",
|
||||||
|
"closingperiod": "",
|
||||||
"contracts": "",
|
"contracts": "",
|
||||||
"convertedtolabor": "",
|
"convertedtolabor": "",
|
||||||
"cost": "",
|
"cost": "",
|
||||||
@@ -2423,6 +2433,7 @@
|
|||||||
"jobs": {
|
"jobs": {
|
||||||
"individual_job_note": "",
|
"individual_job_note": "",
|
||||||
"parts_order": "",
|
"parts_order": "",
|
||||||
|
"parts_return_slip": "",
|
||||||
"sublet_order": ""
|
"sublet_order": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2590,6 +2601,7 @@
|
|||||||
"jobs_completed_not_invoiced": "",
|
"jobs_completed_not_invoiced": "",
|
||||||
"jobs_invoiced_not_exported": "",
|
"jobs_invoiced_not_exported": "",
|
||||||
"jobs_reconcile": "",
|
"jobs_reconcile": "",
|
||||||
|
"jobs_scheduled_completion": "",
|
||||||
"lag_time": "",
|
"lag_time": "",
|
||||||
"open_orders": "",
|
"open_orders": "",
|
||||||
"open_orders_csr": "",
|
"open_orders_csr": "",
|
||||||
@@ -2638,6 +2650,7 @@
|
|||||||
"timetickets_summary": "",
|
"timetickets_summary": "",
|
||||||
"unclaimed_hrs": "",
|
"unclaimed_hrs": "",
|
||||||
"void_ros": "",
|
"void_ros": "",
|
||||||
|
"work_in_progress_jobs": "",
|
||||||
"work_in_progress_labour": "",
|
"work_in_progress_labour": "",
|
||||||
"work_in_progress_payables": ""
|
"work_in_progress_payables": ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,6 +101,7 @@
|
|||||||
"messages": {
|
"messages": {
|
||||||
"admin_jobmarkexported": "",
|
"admin_jobmarkexported": "",
|
||||||
"admin_jobmarkforreexport": "",
|
"admin_jobmarkforreexport": "",
|
||||||
|
"admin_jobuninvoice": "",
|
||||||
"admin_jobunvoid": "",
|
"admin_jobunvoid": "",
|
||||||
"billposted": "",
|
"billposted": "",
|
||||||
"billupdated": "",
|
"billupdated": "",
|
||||||
@@ -222,6 +223,7 @@
|
|||||||
"reexport": ""
|
"reexport": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"closingperiod": "",
|
||||||
"inventoryquantity": "",
|
"inventoryquantity": "",
|
||||||
"manualinhouse": "",
|
"manualinhouse": "",
|
||||||
"unique_invoice_number": ""
|
"unique_invoice_number": ""
|
||||||
@@ -261,6 +263,7 @@
|
|||||||
"bill_local_tax_rate": "",
|
"bill_local_tax_rate": "",
|
||||||
"bill_state_tax_rate": "",
|
"bill_state_tax_rate": "",
|
||||||
"city": "",
|
"city": "",
|
||||||
|
"closingperiod": "",
|
||||||
"country": "",
|
"country": "",
|
||||||
"dailybodytarget": "",
|
"dailybodytarget": "",
|
||||||
"dailypainttarget": "",
|
"dailypainttarget": "",
|
||||||
@@ -269,6 +272,8 @@
|
|||||||
"templates": ""
|
"templates": ""
|
||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
|
"apcontrol": "",
|
||||||
|
"appostingaccount": "",
|
||||||
"cashierid": "",
|
"cashierid": "",
|
||||||
"default_journal": "",
|
"default_journal": "",
|
||||||
"disablebillwip": "",
|
"disablebillwip": "",
|
||||||
@@ -858,7 +863,9 @@
|
|||||||
"prodhrssummary": "",
|
"prodhrssummary": "",
|
||||||
"productiondollars": "",
|
"productiondollars": "",
|
||||||
"productionhours": "",
|
"productionhours": "",
|
||||||
"projectedmonthlysales": ""
|
"projectedmonthlysales": "",
|
||||||
|
"scheduledintoday": "",
|
||||||
|
"scheduledouttoday": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dms": {
|
"dms": {
|
||||||
@@ -1436,6 +1443,7 @@
|
|||||||
"date_repairstarted": "",
|
"date_repairstarted": "",
|
||||||
"date_scheduled": "Prévu",
|
"date_scheduled": "Prévu",
|
||||||
"date_towin": "",
|
"date_towin": "",
|
||||||
|
"date_void": "",
|
||||||
"ded_amt": "Déductible",
|
"ded_amt": "Déductible",
|
||||||
"ded_note": "",
|
"ded_note": "",
|
||||||
"ded_status": "Statut de franchise",
|
"ded_status": "Statut de franchise",
|
||||||
@@ -1451,6 +1459,7 @@
|
|||||||
"cost_dms_acctnumber": "",
|
"cost_dms_acctnumber": "",
|
||||||
"dms_make": "",
|
"dms_make": "",
|
||||||
"dms_model": "",
|
"dms_model": "",
|
||||||
|
"dms_unsold": "",
|
||||||
"dms_wip_acctnumber": "",
|
"dms_wip_acctnumber": "",
|
||||||
"id": "",
|
"id": "",
|
||||||
"inservicedate": "",
|
"inservicedate": "",
|
||||||
@@ -1682,6 +1691,7 @@
|
|||||||
"checklists": "",
|
"checklists": "",
|
||||||
"closeconfirm": "",
|
"closeconfirm": "",
|
||||||
"closejob": "",
|
"closejob": "",
|
||||||
|
"closingperiod": "",
|
||||||
"contracts": "",
|
"contracts": "",
|
||||||
"convertedtolabor": "",
|
"convertedtolabor": "",
|
||||||
"cost": "",
|
"cost": "",
|
||||||
@@ -2423,6 +2433,7 @@
|
|||||||
"jobs": {
|
"jobs": {
|
||||||
"individual_job_note": "",
|
"individual_job_note": "",
|
||||||
"parts_order": "",
|
"parts_order": "",
|
||||||
|
"parts_return_slip": "",
|
||||||
"sublet_order": ""
|
"sublet_order": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2590,6 +2601,7 @@
|
|||||||
"jobs_completed_not_invoiced": "",
|
"jobs_completed_not_invoiced": "",
|
||||||
"jobs_invoiced_not_exported": "",
|
"jobs_invoiced_not_exported": "",
|
||||||
"jobs_reconcile": "",
|
"jobs_reconcile": "",
|
||||||
|
"jobs_scheduled_completion": "",
|
||||||
"lag_time": "",
|
"lag_time": "",
|
||||||
"open_orders": "",
|
"open_orders": "",
|
||||||
"open_orders_csr": "",
|
"open_orders_csr": "",
|
||||||
@@ -2638,6 +2650,7 @@
|
|||||||
"timetickets_summary": "",
|
"timetickets_summary": "",
|
||||||
"unclaimed_hrs": "",
|
"unclaimed_hrs": "",
|
||||||
"void_ros": "",
|
"void_ros": "",
|
||||||
|
"work_in_progress_jobs": "",
|
||||||
"work_in_progress_labour": "",
|
"work_in_progress_labour": "",
|
||||||
"work_in_progress_payables": ""
|
"work_in_progress_payables": ""
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ const AuditTrailMapping = {
|
|||||||
jobnoteupdated: () => i18n.t("audit_trail.messages.jobnoteupdated"),
|
jobnoteupdated: () => i18n.t("audit_trail.messages.jobnoteupdated"),
|
||||||
jobnotedeleted: () => i18n.t("audit_trail.messages.jobnotedeleted"),
|
jobnotedeleted: () => i18n.t("audit_trail.messages.jobnotedeleted"),
|
||||||
admin_jobunvoid: () => i18n.t("audit_trail.messages.admin_jobunvoid"),
|
admin_jobunvoid: () => i18n.t("audit_trail.messages.admin_jobunvoid"),
|
||||||
|
admin_jobuninvoice: () => i18n.t("audit_trail.messages.admin_jobuninvoice"),
|
||||||
admin_jobmarkforreexport: () =>
|
admin_jobmarkforreexport: () =>
|
||||||
i18n.t("audit_trail.messages.admin_jobmarkforreexport"),
|
i18n.t("audit_trail.messages.admin_jobmarkforreexport"),
|
||||||
admin_jobmarkexported: () =>
|
admin_jobmarkexported: () =>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { Button, notification, Space } from "antd";
|
|||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import * as serviceWorkerRegistration from "../serviceWorkerRegistration";
|
import * as serviceWorkerRegistration from "../serviceWorkerRegistration";
|
||||||
|
import { store } from "../redux/store";
|
||||||
|
|
||||||
const onServiceWorkerUpdate = (registration) => {
|
const onServiceWorkerUpdate = (registration) => {
|
||||||
console.log("onServiceWorkerUpdate", registration);
|
console.log("onServiceWorkerUpdate", registration);
|
||||||
@@ -33,6 +34,9 @@ const onServiceWorkerUpdate = (registration) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
store.dispatch()
|
||||||
|
|
||||||
notification.open({
|
notification.open({
|
||||||
icon: <AlertOutlined />,
|
icon: <AlertOutlined />,
|
||||||
message: i18n.t("general.messages.newversiontitle"),
|
message: i18n.t("general.messages.newversiontitle"),
|
||||||
|
|||||||
@@ -615,7 +615,14 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
parts_return_slip: {
|
parts_return_slip: {
|
||||||
title: i18n.t("printcenter.jobs.parts_return_slip"),
|
title: i18n.t("printcenter.jobs.parts_return_slip"),
|
||||||
subject: i18n.t("printcenter.jobs.parts_return_slip"),
|
subject: i18n.t("printcenter.subjects.jobs.parts_return_slip", {
|
||||||
|
ro_number: context && context.job && context.job.ro_number,
|
||||||
|
name: (
|
||||||
|
(context && context.job && context.job.ownr_ln) ||
|
||||||
|
(context && context.job && context.job.ownr_co_nm) ||
|
||||||
|
""
|
||||||
|
).trim(),
|
||||||
|
}),
|
||||||
description: "",
|
description: "",
|
||||||
key: "parts_return_slip",
|
key: "parts_return_slip",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@@ -1246,7 +1253,7 @@ export const TemplateList = (type, context) => {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
rangeFilter: {
|
rangeFilter: {
|
||||||
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_void"),
|
||||||
},
|
},
|
||||||
group: "sales",
|
group: "sales",
|
||||||
},
|
},
|
||||||
@@ -1549,6 +1556,19 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
group: "payroll",
|
group: "payroll",
|
||||||
},
|
},
|
||||||
|
work_in_progress_jobs_excel: {
|
||||||
|
title: i18n.t("reportcenter.templates.work_in_progress_jobs"),
|
||||||
|
subject: i18n.t("reportcenter.templates.work_in_progress_jobs"),
|
||||||
|
key: "work_in_progress_jobs_excel",
|
||||||
|
//idtype: "vendor",
|
||||||
|
reporttype: "excel",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
|
},
|
||||||
|
group: "jobs",
|
||||||
|
},
|
||||||
work_in_progress_labour: {
|
work_in_progress_labour: {
|
||||||
title: i18n.t("reportcenter.templates.work_in_progress_labour"),
|
title: i18n.t("reportcenter.templates.work_in_progress_labour"),
|
||||||
description: "",
|
description: "",
|
||||||
@@ -1906,6 +1926,18 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
group: "sales",
|
group: "sales",
|
||||||
},
|
},
|
||||||
|
jobs_scheduled_completion: {
|
||||||
|
title: i18n.t("reportcenter.templates.jobs_scheduled_completion"),
|
||||||
|
subject: i18n.t("reportcenter.templates.jobs_scheduled_completion"),
|
||||||
|
key: "jobs_scheduled_completion",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.scheduled_completion"),
|
||||||
|
},
|
||||||
|
group: "jobs",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
...(!type || type === "courtesycarcontract"
|
...(!type || type === "courtesycarcontract"
|
||||||
|
|||||||
@@ -2092,6 +2092,13 @@
|
|||||||
table:
|
table:
|
||||||
name: employee_team_members
|
name: employee_team_members
|
||||||
schema: public
|
schema: public
|
||||||
|
- name: joblines
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on:
|
||||||
|
column: assigned_team
|
||||||
|
table:
|
||||||
|
name: joblines
|
||||||
|
schema: public
|
||||||
insert_permissions:
|
insert_permissions:
|
||||||
- role: user
|
- role: user
|
||||||
permission:
|
permission:
|
||||||
@@ -2665,6 +2672,9 @@
|
|||||||
name: joblines
|
name: joblines
|
||||||
schema: public
|
schema: public
|
||||||
object_relationships:
|
object_relationships:
|
||||||
|
- name: employee_team
|
||||||
|
using:
|
||||||
|
foreign_key_constraint_on: assigned_team
|
||||||
- name: job
|
- name: job
|
||||||
using:
|
using:
|
||||||
foreign_key_constraint_on: jobid
|
foreign_key_constraint_on: jobid
|
||||||
@@ -2726,6 +2736,7 @@
|
|||||||
- alt_part_i
|
- alt_part_i
|
||||||
- alt_partm
|
- alt_partm
|
||||||
- alt_partno
|
- alt_partno
|
||||||
|
- assigned_team
|
||||||
- bett_amt
|
- bett_amt
|
||||||
- bett_pctg
|
- bett_pctg
|
||||||
- bett_tax
|
- bett_tax
|
||||||
@@ -2734,6 +2745,7 @@
|
|||||||
- convertedtolbr
|
- convertedtolbr
|
||||||
- convertedtolbr_data
|
- convertedtolbr_data
|
||||||
- created_at
|
- created_at
|
||||||
|
- critical
|
||||||
- db_hrs
|
- db_hrs
|
||||||
- db_price
|
- db_price
|
||||||
- db_ref
|
- db_ref
|
||||||
@@ -2793,6 +2805,7 @@
|
|||||||
- alt_part_i
|
- alt_part_i
|
||||||
- alt_partm
|
- alt_partm
|
||||||
- alt_partno
|
- alt_partno
|
||||||
|
- assigned_team
|
||||||
- bett_amt
|
- bett_amt
|
||||||
- bett_pctg
|
- bett_pctg
|
||||||
- bett_tax
|
- bett_tax
|
||||||
@@ -2872,6 +2885,7 @@
|
|||||||
- alt_part_i
|
- alt_part_i
|
||||||
- alt_partm
|
- alt_partm
|
||||||
- alt_partno
|
- alt_partno
|
||||||
|
- assigned_team
|
||||||
- bett_amt
|
- bett_amt
|
||||||
- bett_pctg
|
- bett_pctg
|
||||||
- bett_tax
|
- bett_tax
|
||||||
@@ -3286,6 +3300,7 @@
|
|||||||
- clm_total
|
- clm_total
|
||||||
- clm_zip
|
- clm_zip
|
||||||
- comment
|
- comment
|
||||||
|
- completed_tasks
|
||||||
- converted
|
- converted
|
||||||
- created_at
|
- created_at
|
||||||
- cust_pr
|
- cust_pr
|
||||||
@@ -3480,6 +3495,7 @@
|
|||||||
- v_model_yr
|
- v_model_yr
|
||||||
- v_vin
|
- v_vin
|
||||||
- vehicleid
|
- vehicleid
|
||||||
|
- date_void
|
||||||
- voided
|
- voided
|
||||||
select_permissions:
|
select_permissions:
|
||||||
- role: user
|
- role: user
|
||||||
@@ -3550,6 +3566,7 @@
|
|||||||
- clm_total
|
- clm_total
|
||||||
- clm_zip
|
- clm_zip
|
||||||
- comment
|
- comment
|
||||||
|
- completed_tasks
|
||||||
- converted
|
- converted
|
||||||
- created_at
|
- created_at
|
||||||
- cust_pr
|
- cust_pr
|
||||||
@@ -3745,6 +3762,7 @@
|
|||||||
- v_model_yr
|
- v_model_yr
|
||||||
- v_vin
|
- v_vin
|
||||||
- vehicleid
|
- vehicleid
|
||||||
|
- date_void
|
||||||
- voided
|
- voided
|
||||||
filter:
|
filter:
|
||||||
bodyshop:
|
bodyshop:
|
||||||
@@ -3825,6 +3843,7 @@
|
|||||||
- clm_total
|
- clm_total
|
||||||
- clm_zip
|
- clm_zip
|
||||||
- comment
|
- comment
|
||||||
|
- completed_tasks
|
||||||
- converted
|
- converted
|
||||||
- created_at
|
- created_at
|
||||||
- cust_pr
|
- cust_pr
|
||||||
@@ -4020,6 +4039,7 @@
|
|||||||
- v_model_yr
|
- v_model_yr
|
||||||
- v_vin
|
- v_vin
|
||||||
- vehicleid
|
- vehicleid
|
||||||
|
- date_void
|
||||||
- voided
|
- voided
|
||||||
filter:
|
filter:
|
||||||
bodyshop:
|
bodyshop:
|
||||||
@@ -4629,6 +4649,7 @@
|
|||||||
_eq: X-Hasura-User-Id
|
_eq: X-Hasura-User-Id
|
||||||
- active:
|
- active:
|
||||||
_eq: true
|
_eq: true
|
||||||
|
allow_aggregations: true
|
||||||
update_permissions:
|
update_permissions:
|
||||||
- role: user
|
- role: user
|
||||||
permission:
|
permission:
|
||||||
@@ -4662,6 +4683,74 @@
|
|||||||
- name: parts_dispatch
|
- name: parts_dispatch
|
||||||
using:
|
using:
|
||||||
foreign_key_constraint_on: partsdispatchid
|
foreign_key_constraint_on: partsdispatchid
|
||||||
|
insert_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
parts_dispatch:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- id
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- partsdispatchid
|
||||||
|
- joblineid
|
||||||
|
- quantity
|
||||||
|
- accepted_at
|
||||||
|
select_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- quantity
|
||||||
|
- accepted_at
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- id
|
||||||
|
- joblineid
|
||||||
|
- partsdispatchid
|
||||||
|
filter:
|
||||||
|
parts_dispatch:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
allow_aggregations: true
|
||||||
|
update_permissions:
|
||||||
|
- role: user
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- id
|
||||||
|
- created_at
|
||||||
|
- updated_at
|
||||||
|
- partsdispatchid
|
||||||
|
- joblineid
|
||||||
|
- quantity
|
||||||
|
- accepted_at
|
||||||
|
filter:
|
||||||
|
parts_dispatch:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
check: null
|
||||||
- table:
|
- table:
|
||||||
name: parts_order_lines
|
name: parts_order_lines
|
||||||
schema: public
|
schema: public
|
||||||
@@ -5475,6 +5564,7 @@
|
|||||||
- memo
|
- memo
|
||||||
- productivehrs
|
- productivehrs
|
||||||
- rate
|
- rate
|
||||||
|
- task_name
|
||||||
- ttapprovalqueueid
|
- ttapprovalqueueid
|
||||||
- updated_at
|
- updated_at
|
||||||
select_permissions:
|
select_permissions:
|
||||||
@@ -5498,6 +5588,7 @@
|
|||||||
- memo
|
- memo
|
||||||
- productivehrs
|
- productivehrs
|
||||||
- rate
|
- rate
|
||||||
|
- task_name
|
||||||
- ttapprovalqueueid
|
- ttapprovalqueueid
|
||||||
- updated_at
|
- updated_at
|
||||||
filter:
|
filter:
|
||||||
@@ -5530,6 +5621,7 @@
|
|||||||
- memo
|
- memo
|
||||||
- productivehrs
|
- productivehrs
|
||||||
- rate
|
- rate
|
||||||
|
- task_name
|
||||||
- ttapprovalqueueid
|
- ttapprovalqueueid
|
||||||
- updated_at
|
- updated_at
|
||||||
filter:
|
filter:
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."parts_dispatch_lines" alter column "accepted_at" set not null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."parts_dispatch_lines" alter column "accepted_at" drop not null;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
alter table "public"."job_conversations" drop constraint "job_conversations_conversationid_fkey",
|
||||||
|
add constraint "job_conversations_conversationid_fkey"
|
||||||
|
foreign key ("conversationid")
|
||||||
|
references "public"."conversations"
|
||||||
|
("id") on update restrict on delete restrict;
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
alter table "public"."job_conversations" drop constraint "job_conversations_conversationid_fkey",
|
||||||
|
add constraint "job_conversations_conversationid_fkey"
|
||||||
|
foreign key ("conversationid")
|
||||||
|
references "public"."conversations"
|
||||||
|
("id") on update cascade on delete 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"."joblines" add column "assigned_team" uuid
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."joblines" add column "assigned_team" uuid
|
||||||
|
null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."joblines" drop constraint "joblines_assigned_team_fkey";
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
alter table "public"."joblines"
|
||||||
|
add constraint "joblines_assigned_team_fkey"
|
||||||
|
foreign key ("assigned_team")
|
||||||
|
references "public"."employee_teams"
|
||||||
|
("id") on update restrict on delete restrict;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."jobs" add column "completed_tasks" jsonb
|
||||||
|
-- null default jsonb_build_array();
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."jobs" add column "completed_tasks" jsonb
|
||||||
|
null default jsonb_build_array();
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."jobs" add column "void_date" Timestamp
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."jobs" add column "void_date" Timestamp
|
||||||
|
null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "public"."jobs" ALTER COLUMN "void_date" TYPE timestamp without time zone;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE "public"."jobs" ALTER COLUMN "void_date" TYPE timestamptz;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."jobs" rename column "date_void" to "void_date";
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
alter table "public"."jobs" rename column "void_date" to "date_void";
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
-- Could not auto-generate a down migration.
|
||||||
|
-- Please write an appropriate down migration for the SQL below:
|
||||||
|
-- alter table "public"."timetickets" add column "task_name" text
|
||||||
|
-- null;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
alter table "public"."timetickets" add column "task_name" text
|
||||||
|
null;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "public"."parts_dispatch_employeeid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "parts_dispatch_employeeid" on
|
||||||
|
"public"."parts_dispatch" using btree ("employeeid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "public"."parts_dispatch_dispatchid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "parts_dispatch_dispatchid" on
|
||||||
|
"public"."parts_dispatch_lines" using btree ("partsdispatchid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "public"."parts_dispatch_line_accepted_at";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "parts_dispatch_line_accepted_at" on
|
||||||
|
"public"."parts_dispatch_lines" using btree ("accepted_at");
|
||||||
@@ -123,8 +123,14 @@ async function PbsCalculateAllocationsAp(socket, billids) {
|
|||||||
|
|
||||||
if (!billHash[cc.name]) {
|
if (!billHash[cc.name]) {
|
||||||
billHash[cc.name] = {
|
billHash[cc.name] = {
|
||||||
Account: cc.dms_acctnumber,
|
Account:
|
||||||
ControlNumber: bill.vendor.dmsid,
|
bodyshop.pbs_configuration.appostingaccount === "wip"
|
||||||
|
? cc.dms_wip_acctnumber
|
||||||
|
: cc.dms_acctnumber,
|
||||||
|
ControlNumber:
|
||||||
|
bodyshop.pbs_configuration.apcontrol === "ro"
|
||||||
|
? bill.job.ro_number
|
||||||
|
: bill.vendor.dmsid,
|
||||||
Amount: Dinero(),
|
Amount: Dinero(),
|
||||||
// Comment: "String",
|
// Comment: "String",
|
||||||
AdditionalInfo: bill.vendor.name,
|
AdditionalInfo: bill.vendor.name,
|
||||||
|
|||||||
@@ -133,7 +133,13 @@ const generateBillLine = (billLine, responsibilityCenters, jobClass) => {
|
|||||||
const findTaxCode = (billLine, taxcode) => {
|
const findTaxCode = (billLine, taxcode) => {
|
||||||
const {
|
const {
|
||||||
applicable_taxes: { local, state, federal },
|
applicable_taxes: { local, state, federal },
|
||||||
} = billLine;
|
} =
|
||||||
|
billLine.applicable_taxes === null
|
||||||
|
? {
|
||||||
|
...billLine,
|
||||||
|
applicable_taxes: { local: false, state: false, federal: false },
|
||||||
|
}
|
||||||
|
: billLine;
|
||||||
const t = taxcode.filter(
|
const t = taxcode.filter(
|
||||||
(t) =>
|
(t) =>
|
||||||
!!t.local === !!local &&
|
!!t.local === !!local &&
|
||||||
|
|||||||
@@ -262,10 +262,10 @@ const generateInvoiceQbxml = (
|
|||||||
RefNumber: jobs_by_pk.ro_number,
|
RefNumber: jobs_by_pk.ro_number,
|
||||||
BillAddress: {
|
BillAddress: {
|
||||||
Addr1: jobs_by_pk.ownr_co_nm
|
Addr1: jobs_by_pk.ownr_co_nm
|
||||||
? jobs_by_pk.ownr_co_nm.substring(0, 30)
|
? jobs_by_pk.ownr_co_nm.substring(0, 30).trim()
|
||||||
: `${`${jobs_by_pk.ownr_ln || ""} ${
|
: `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
|
||||||
jobs_by_pk.ownr_fn || ""
|
.substring(0, 30)
|
||||||
}`.substring(0, 30)}`,
|
.trim()}`,
|
||||||
Addr2: jobs_by_pk.ownr_addr1,
|
Addr2: jobs_by_pk.ownr_addr1,
|
||||||
Addr3: jobs_by_pk.ownr_addr2,
|
Addr3: jobs_by_pk.ownr_addr2,
|
||||||
City: jobs_by_pk.ownr_city,
|
City: jobs_by_pk.ownr_city,
|
||||||
@@ -274,10 +274,10 @@ const generateInvoiceQbxml = (
|
|||||||
},
|
},
|
||||||
ShipAddress: {
|
ShipAddress: {
|
||||||
Addr1: jobs_by_pk.ownr_co_nm
|
Addr1: jobs_by_pk.ownr_co_nm
|
||||||
? jobs_by_pk.ownr_co_nm.substring(0, 30)
|
? jobs_by_pk.ownr_co_nm.substring(0, 30).trim()
|
||||||
: `${`${jobs_by_pk.ownr_ln || ""} ${
|
: `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
|
||||||
jobs_by_pk.ownr_fn || ""
|
.substring(0, 30)
|
||||||
}`.substring(0, 30)}`,
|
.trim()}`,
|
||||||
Addr2: jobs_by_pk.ownr_addr1,
|
Addr2: jobs_by_pk.ownr_addr1,
|
||||||
Addr3: jobs_by_pk.ownr_addr2,
|
Addr3: jobs_by_pk.ownr_addr2,
|
||||||
City: jobs_by_pk.ownr_city,
|
City: jobs_by_pk.ownr_city,
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ exports.generateOwnerTier = (jobs_by_pk, isThreeTier, twotierpref) => {
|
|||||||
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
|
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
|
||||||
jobs_by_pk.owner.accountingid || ""
|
jobs_by_pk.owner.accountingid || ""
|
||||||
}`
|
}`
|
||||||
: `${`${jobs_by_pk.ownr_ln || ""} ${
|
: `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
|
||||||
jobs_by_pk.ownr_fn || ""
|
.substring(0, 30)
|
||||||
}`.substring(0, 30)} #${jobs_by_pk.owner.accountingid || ""}`
|
.trim()} #${jobs_by_pk.owner.accountingid || ""}`
|
||||||
)
|
)
|
||||||
.trim()
|
.trim()
|
||||||
.replace(":", " ");
|
.replace(":", " ");
|
||||||
@@ -39,9 +39,9 @@ exports.generateOwnerTier = (jobs_by_pk, isThreeTier, twotierpref) => {
|
|||||||
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
|
? `${jobs_by_pk.ownr_co_nm.substring(0, 30)} #${
|
||||||
jobs_by_pk.owner.accountingid || ""
|
jobs_by_pk.owner.accountingid || ""
|
||||||
}`
|
}`
|
||||||
: `${`${jobs_by_pk.ownr_ln || ""} ${
|
: `${`${jobs_by_pk.ownr_ln || ""} ${jobs_by_pk.ownr_fn || ""}`
|
||||||
jobs_by_pk.ownr_fn || ""
|
.substring(0, 30)
|
||||||
}`.substring(0, 30)} #${jobs_by_pk.owner.accountingid || ""}`
|
.trim()} #${jobs_by_pk.owner.accountingid || ""}`
|
||||||
)
|
)
|
||||||
.trim()
|
.trim()
|
||||||
.replace(":", " ");
|
.replace(":", " ");
|
||||||
|
|||||||
@@ -717,18 +717,24 @@ async function InsertDmsVehicle(socket) {
|
|||||||
dealer: {
|
dealer: {
|
||||||
dealerNumber: socket.JobData.bodyshop.cdk_dealerid,
|
dealerNumber: socket.JobData.bodyshop.cdk_dealerid,
|
||||||
...(socket.txEnvelope.inservicedate && {
|
...(socket.txEnvelope.inservicedate && {
|
||||||
inServiceDate: moment(socket.txEnvelope.inservicedate)
|
inServiceDate:
|
||||||
//.tz(socket.JobData.bodyshop.timezone)
|
socket.txEnvelope.dms_unsold === true
|
||||||
.startOf("day")
|
? ""
|
||||||
.toISOString(),
|
: moment(socket.txEnvelope.inservicedate)
|
||||||
|
//.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.startOf("day")
|
||||||
|
.toISOString(),
|
||||||
}),
|
}),
|
||||||
vehicleId: socket.DMSVid.vehiclesVehId,
|
vehicleId: socket.DMSVid.vehiclesVehId,
|
||||||
},
|
},
|
||||||
manufacturer: {},
|
manufacturer: {},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
deliveryDate: moment()
|
deliveryDate:
|
||||||
// .tz(socket.JobData.bodyshop.timezone)
|
socket.txEnvelope.dms_unsold === true
|
||||||
.format("YYYYMMDD"),
|
? ""
|
||||||
|
: moment()
|
||||||
|
// .tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.format("YYYYMMDD"),
|
||||||
licensePlateNo:
|
licensePlateNo:
|
||||||
socket.JobData.plate_no === null
|
socket.JobData.plate_no === null
|
||||||
? null
|
? null
|
||||||
@@ -860,19 +866,25 @@ async function UpdateDmsVehicle(socket) {
|
|||||||
...socket.DMSVeh.dealer,
|
...socket.DMSVeh.dealer,
|
||||||
...((socket.txEnvelope.inservicedate ||
|
...((socket.txEnvelope.inservicedate ||
|
||||||
socket.DMSVeh.dealer.inServiceDate) && {
|
socket.DMSVeh.dealer.inServiceDate) && {
|
||||||
inServiceDate: moment(
|
inServiceDate:
|
||||||
socket.DMSVeh.dealer.inServiceDate ||
|
socket.txEnvelope.dms_unsold === true
|
||||||
socket.txEnvelope.inservicedate
|
? ""
|
||||||
)
|
: moment(
|
||||||
// .tz(socket.JobData.bodyshop.timezone)
|
socket.DMSVeh.dealer.inServiceDate ||
|
||||||
.toISOString(),
|
socket.txEnvelope.inservicedate
|
||||||
|
)
|
||||||
|
// .tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
...socket.DMSVeh.vehicle,
|
...socket.DMSVeh.vehicle,
|
||||||
deliveryDate: moment(socket.DMSVeh.vehicle.deliveryDate)
|
deliveryDate:
|
||||||
//.tz(socket.JobData.bodyshop.timezone)
|
socket.txEnvelope.dms_unsold === true
|
||||||
.toISOString(),
|
? ""
|
||||||
|
: moment(socket.DMSVeh.vehicle.deliveryDate)
|
||||||
|
//.tz(socket.JobData.bodyshop.timezone)
|
||||||
|
.toISOString(),
|
||||||
},
|
},
|
||||||
owners: ids,
|
owners: ids,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1697,6 +1697,7 @@ query GET_PBS_AP_ALLOCATIONS($billids: [uuid!]) {
|
|||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
timezone
|
timezone
|
||||||
pbs_serialnumber
|
pbs_serialnumber
|
||||||
|
pbs_configuration
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
bills(where: {id: {_in: $billids}, exported:{_eq: false}}) {
|
bills(where: {id: {_in: $billids}, exported:{_eq: false}}) {
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ async function OpenSearchUpdateHandler(req, res) {
|
|||||||
"v_model_yr",
|
"v_model_yr",
|
||||||
"v_make_desc",
|
"v_make_desc",
|
||||||
"v_model_desc",
|
"v_model_desc",
|
||||||
|
"v_vin",
|
||||||
]);
|
]);
|
||||||
document.bodyshopid = req.body.event.data.new.shopid;
|
document.bodyshopid = req.body.event.data.new.shopid;
|
||||||
break;
|
break;
|
||||||
@@ -139,7 +140,7 @@ async function OpenSearchUpdateHandler(req, res) {
|
|||||||
"exported_at",
|
"exported_at",
|
||||||
"invoice_number",
|
"invoice_number",
|
||||||
"is_credit_memo",
|
"is_credit_memo",
|
||||||
"total"
|
"total",
|
||||||
]),
|
]),
|
||||||
...bill.bills_by_pk,
|
...bill.bills_by_pk,
|
||||||
bodyshopid: bill.bills_by_pk.job.shopid,
|
bodyshopid: bill.bills_by_pk.job.shopid,
|
||||||
@@ -244,17 +245,54 @@ async function OpensearchSearchHandler(req, res) {
|
|||||||
bool: {
|
bool: {
|
||||||
must: [
|
must: [
|
||||||
{
|
{
|
||||||
multi_match: {
|
match: {
|
||||||
query: search,
|
bodyshopid: assocs.associations[0].shopid,
|
||||||
type: "phrase_prefix",
|
|
||||||
//fields: ["*"],
|
|
||||||
// fuzziness: "5",
|
|
||||||
//prefix_length: 2,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
match: {
|
bool: {
|
||||||
bodyshopid: assocs.associations[0].shopid,
|
should: [
|
||||||
|
{
|
||||||
|
multi_match: {
|
||||||
|
query: search,
|
||||||
|
type: "cross_fields",
|
||||||
|
fields: ["*ownr_fn", "*ownr_ln"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
multi_match: {
|
||||||
|
query: search,
|
||||||
|
type: "most_fields",
|
||||||
|
fields: [
|
||||||
|
"*v_model_yr",
|
||||||
|
"*v_make_desc^2",
|
||||||
|
"*v_model_desc^3",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
query_string: {
|
||||||
|
query: `*${search}*`,
|
||||||
|
|
||||||
|
fields: [
|
||||||
|
"*ro_number^20",
|
||||||
|
"*clm_no^14",
|
||||||
|
"*v_vin^12",
|
||||||
|
"*plate_no^12",
|
||||||
|
"*ownr_ln^10",
|
||||||
|
"transactionid^10",
|
||||||
|
"paymentnum^10",
|
||||||
|
"invoice_number^10",
|
||||||
|
"*ownr_fn^8",
|
||||||
|
"*ownr_co_nm^8",
|
||||||
|
"*ownr_ph1^8",
|
||||||
|
"*ownr_ph2^8",
|
||||||
|
"*",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
minimum_should_match: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user