Merged in release/2021-10-01 (pull request #227)
release/2021-10-01 Approved-by: Patrick Fic
@@ -8229,6 +8229,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>qbo</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>rbac</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -32575,6 +32596,27 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>csi_invitation_action</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>diagnostic_authorization</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
@@ -33205,6 +33247,48 @@
|
||||
</translation>
|
||||
</translations>
|
||||
</concept_node>
|
||||
<concept_node>
|
||||
<name>sgi_certificate_of_repairs</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>sgi_windshield_auth</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>stolen_recovery_checklist</name>
|
||||
<definition_loaded>false</definition_loaded>
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
"private": true,
|
||||
"proxy": "http://localhost:5000",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.4.13",
|
||||
"@apollo/client": "^3.4.14",
|
||||
"@craco/craco": "^6.3.0",
|
||||
"@fingerprintjs/fingerprintjs": "^3.3.0",
|
||||
"@lourenci/react-kanban": "^2.1.0",
|
||||
"@openreplay/tracker": "^3.3.1",
|
||||
"@openreplay/tracker-assist": "^3.1.1",
|
||||
"@openreplay/tracker": "^3.4.0",
|
||||
"@openreplay/tracker-assist": "^3.4.0",
|
||||
"@openreplay/tracker-graphql": "^3.0.0",
|
||||
"@openreplay/tracker-redux": "^3.0.0",
|
||||
"@sentry/react": "^6.13.0",
|
||||
"@sentry/tracing": "^6.13.0",
|
||||
"@stripe/react-stripe-js": "^1.4.0",
|
||||
"@stripe/stripe-js": "^1.17.1",
|
||||
"@sentry/react": "^6.13.2",
|
||||
"@sentry/tracing": "^6.13.2",
|
||||
"@stripe/react-stripe-js": "^1.5.0",
|
||||
"@stripe/stripe-js": "^1.18.0",
|
||||
"@tanem/react-nprogress": "^3.0.79",
|
||||
"antd": "^4.16.13",
|
||||
"apollo-link-logger": "^2.0.0",
|
||||
@@ -26,15 +26,15 @@
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^9.0.2",
|
||||
"graphql": "^15.5.3",
|
||||
"i18next": "^21.0.0",
|
||||
"firebase": "^9.1.0",
|
||||
"graphql": "^15.6.0",
|
||||
"i18next": "^21.1.1",
|
||||
"i18next-browser-languagedetector": "^6.1.2",
|
||||
"jsoneditor": "^9.5.4",
|
||||
"jsoneditor": "^9.5.6",
|
||||
"jsreport-browser-client-dist": "^1.3.0",
|
||||
"libphonenumber-js": "^1.9.34",
|
||||
"logrocket": "^2.0.0",
|
||||
"markerjs2": "^2.11.2",
|
||||
"markerjs2": "^2.12.0",
|
||||
"moment-business-days": "^1.2.0",
|
||||
"phone": "^3.1.8",
|
||||
"preval.macro": "^5.0.0",
|
||||
@@ -59,13 +59,13 @@
|
||||
"react-scripts": "^4.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"recharts": "^2.1.3",
|
||||
"recharts": "^2.1.4",
|
||||
"redux": "^4.1.1",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.1.3",
|
||||
"redux-state-sync": "^3.1.2",
|
||||
"reselect": "^4.0.0",
|
||||
"sass": "^1.41.1",
|
||||
"sass": "^1.42.1",
|
||||
"socket.io-client": "^4.2.0",
|
||||
"styled-components": "^5.3.1",
|
||||
"subscriptions-transport-ws": "^0.9.18",
|
||||
|
||||
24
client/src/assets/C2QB_composite_English.svg
Normal file
|
After Width: | Height: | Size: 51 KiB |
24
client/src/assets/C2QB_transparent_English.svg
Normal file
|
After Width: | Height: | Size: 51 KiB |
4
client/src/assets/qbo/C2QB_green_btn_med_default.svg
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
5
client/src/assets/qbo/C2QB_green_btn_med_hover.svg
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
4
client/src/assets/qbo/C2QB_green_btn_short_default.svg
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
5
client/src/assets/qbo/C2QB_green_btn_short_hover.svg
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
4
client/src/assets/qbo/C2QB_green_btn_tall_default.svg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
5
client/src/assets/qbo/C2QB_green_btn_tall_hover.svg
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
5
client/src/assets/qbo/C2QB_transparent_btn_med_hover.svg
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
@@ -11,6 +11,7 @@ import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-butto
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
@@ -206,6 +207,9 @@ export function AccountingReceivablesTableComponent({
|
||||
completedCallback={setSelectedJobs}
|
||||
/>
|
||||
)}
|
||||
{bodyshop.accountingconfig && bodyshop.accountingconfig.qbo && (
|
||||
<QboAuthorizeComponent />
|
||||
)}
|
||||
<Input.Search
|
||||
value={state.search}
|
||||
onChange={handleSearch}
|
||||
|
||||
@@ -34,6 +34,7 @@ export function JobsCloseExportButton({
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleQbxml = async () => {
|
||||
//Check if it's a CDK setup.
|
||||
if (bodyshop.cdk_dealerid) {
|
||||
history.push(`/manage/dms?jobId=${jobId}`);
|
||||
return;
|
||||
@@ -41,48 +42,58 @@ export function JobsCloseExportButton({
|
||||
logImEXEvent("jobs_close_export");
|
||||
|
||||
setLoading(true);
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: [jobId] },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log("handle -> XML", QbXmlResponse);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if it's a QBO Setup.
|
||||
let PartnerResponse;
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/qb/",
|
||||
QbXmlResponse.data,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error connecting to quickbooks or partner.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting-partner"),
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/receivables`, {
|
||||
withCredentials: true,
|
||||
jobIds: [jobId],
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
} else {
|
||||
//Default is QBD
|
||||
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: [jobId] },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
console.log("handle -> XML", QbXmlResponse);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/qb/",
|
||||
QbXmlResponse.data,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error connecting to quickbooks or partner.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting-partner"),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log("PartnerResponse", PartnerResponse);
|
||||
|
||||
@@ -104,7 +104,7 @@ export function JobsDetailHeaderCsi({
|
||||
replyTo: bodyshop.email,
|
||||
},
|
||||
template: {
|
||||
name: TemplateList("job").csi_invitation.key,
|
||||
name: TemplateList("job_special").csi_invitation_action.key,
|
||||
variables: {
|
||||
id: result.data.insert_csi.returning[0].id,
|
||||
},
|
||||
|
||||
@@ -34,53 +34,61 @@ export function JobsExportAllButton({
|
||||
const [loading, setLoading] = useState(false);
|
||||
const handleQbxml = async () => {
|
||||
logImEXEvent("jobs_export_all");
|
||||
|
||||
setLoading(true);
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: jobIds },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let PartnerResponse;
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/qb/",
|
||||
QbXmlResponse.data,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error connecting to quickbooks or partner.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting-partner"),
|
||||
setLoading(true);
|
||||
if (bodyshop.accountingconfig && bodyshop.accountingconfig.qbo) {
|
||||
PartnerResponse = await axios.post(`/qbo/receivables`, {
|
||||
withCredentials: true,
|
||||
jobIds: jobIds,
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
let QbXmlResponse;
|
||||
try {
|
||||
QbXmlResponse = await axios.post(
|
||||
"/accounting/qbxml/receivables",
|
||||
{ jobIds: jobIds },
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error getting QBXML from Server.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting", {
|
||||
error: "Unable to retrieve QBXML. " + JSON.stringify(error.message),
|
||||
}),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
PartnerResponse = await axios.post(
|
||||
"http://localhost:1337/qb/",
|
||||
// "http://609feaeae986.ngrok.io/qb/",
|
||||
QbXmlResponse.data,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.log("Error connecting to quickbooks or partner.", error);
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.exporting-partner"),
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
console.log("PartnerResponse", PartnerResponse);
|
||||
const groupedData = _.groupBy(PartnerResponse.data, "id");
|
||||
const groupedData = _.groupBy(
|
||||
PartnerResponse.data,
|
||||
bodyshop.accountingconfig.qbo ? "jobid" : "id"
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
Object.keys(groupedData).map(async (key) => {
|
||||
@@ -157,6 +165,7 @@ export function JobsExportAllButton({
|
||||
|
||||
if (!!completedCallback) completedCallback([]);
|
||||
if (!!loadingCallback) loadingCallback(false);
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,28 +1,35 @@
|
||||
import { Card, Col, Input, Row, Space, Typography } from "antd";
|
||||
import _ from "lodash";
|
||||
import React, { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectPrintCenter } from "../../redux/modals/modals.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
import Jobd3RdPartyModal from "../job-3rd-party-modal/job-3rd-party-modal.component";
|
||||
import PrintCenterItem from "../print-center-item/print-center-item.component";
|
||||
import PrintCenterSpeedPrint from "../print-center-speed-print/print-center-speed-print.component";
|
||||
import { useTranslation } from "react-i18next";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
printCenterModal: selectPrintCenter,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({});
|
||||
|
||||
export function PrintCenterJobsComponent({ printCenterModal }) {
|
||||
export function PrintCenterJobsComponent({ printCenterModal, bodyshop }) {
|
||||
const [search, setSearch] = useState("");
|
||||
const { id: jobId } = printCenterModal.context;
|
||||
const tempList = TemplateList("job", {});
|
||||
const { t } = useTranslation();
|
||||
const JobsReportsList = Object.keys(tempList).map((key) => {
|
||||
return tempList[key];
|
||||
});
|
||||
const JobsReportsList = Object.keys(tempList)
|
||||
.map((key) => {
|
||||
return tempList[key];
|
||||
})
|
||||
.filter(
|
||||
(temp) =>
|
||||
!temp.regions || (temp.regions && temp.regions[bodyshop.region_config])
|
||||
);
|
||||
|
||||
const filteredJobsReportsList =
|
||||
search !== ""
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { Button, Space } from "antd";
|
||||
import { Space, Tag } from "antd";
|
||||
import Axios from "axios";
|
||||
import React, { useEffect } from "react";
|
||||
//import QboImg from "./qbo_signin.png";
|
||||
import queryString from "query-string";
|
||||
import { useLocation } from "react-router-dom";
|
||||
import React, { useEffect } from "react";
|
||||
import { useCookies } from "react-cookie";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import QboSignIn from "../../assets/qbo/C2QB_green_btn_med_default.svg";
|
||||
|
||||
export default function QboAuthorizeComponent() {
|
||||
const location = useLocation();
|
||||
|
||||
const [, setCookie] = useCookies(["access_token", "refresh_token"]);
|
||||
const history = useHistory();
|
||||
const [cookies, setCookie] = useCookies(["access_token", "refresh_token"]);
|
||||
|
||||
const handleQbSignIn = async () => {
|
||||
const result = await Axios.post("/qbo/authorize");
|
||||
console.log("pushing to history", result.data);
|
||||
window.location.href = result.data;
|
||||
};
|
||||
const qs = queryString.parse(location.search);
|
||||
@@ -35,42 +34,24 @@ export default function QboAuthorizeComponent() {
|
||||
path: "/",
|
||||
expires,
|
||||
});
|
||||
|
||||
history.push({ pathname: `/manage/accounting/receivables` });
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [qs, location, setCookie]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Space wrap>
|
||||
<Button onClick={handleQbSignIn}>
|
||||
{/* <img
|
||||
src={QboImg}
|
||||
alt="Sign in with Intuit"
|
||||
onClick={handleQbSignIn}
|
||||
/> */}
|
||||
auth
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const response = await Axios.get(`/qbo/refresh`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
console.log(response);
|
||||
}}
|
||||
>
|
||||
Refresh Token
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
const response = await Axios.post(`/qbo/receivables`, {
|
||||
withCredentials: true,
|
||||
});
|
||||
console.log(response);
|
||||
}}
|
||||
>
|
||||
REC
|
||||
</Button>
|
||||
</Space>
|
||||
<Space>
|
||||
<img
|
||||
onClick={handleQbSignIn}
|
||||
alt="Sign In to QuickBooks Online"
|
||||
src={QboSignIn}
|
||||
style={{ cursor: "pointer" }}
|
||||
/>
|
||||
{!cookies.qbo_realmId && (
|
||||
<Tag color="red">No QuickBooks company has been connected.</Tag>
|
||||
)}
|
||||
{error && JSON.parse(decodeURIComponent(error)).error_description}
|
||||
</div>
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -121,6 +121,13 @@ export default function ShopInfoGeneral({ form }) {
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("bodyshop.labels.accountingsetup")}>
|
||||
<Form.Item
|
||||
label={t("bodyshop.labels.qbo")}
|
||||
valuePropName="checked"
|
||||
name={["accountingconfig", "qbo"]}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bodyshop.labels.accountingtiers")}
|
||||
rules={[
|
||||
|
||||
@@ -77,6 +77,7 @@ export const QUERY_PARTS_QUEUE = gql`
|
||||
) {
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ownr_ph1
|
||||
ownr_ea
|
||||
plate_no
|
||||
@@ -98,6 +99,7 @@ export const QUERY_PARTS_QUEUE = gql`
|
||||
status
|
||||
updated_at
|
||||
vehicleid
|
||||
ownerid
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -110,6 +112,7 @@ export const SUBSCRIPTION_JOBS_IN_PRODUCTION = gql`
|
||||
ro_number
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
v_model_yr
|
||||
v_model_desc
|
||||
clm_no
|
||||
@@ -540,6 +543,7 @@ export const GET_JOB_BY_PK = gql`
|
||||
db_ref
|
||||
manual_line
|
||||
prt_dsmk_p
|
||||
prt_dsmk_m
|
||||
billlines(limit: 1, order_by: { bill: { date: desc } }) {
|
||||
id
|
||||
quantity
|
||||
@@ -1636,6 +1640,7 @@ export const QUERY_ALL_JOBS_PAGINATED_STATUS_FILTERED = gql`
|
||||
) {
|
||||
ownr_fn
|
||||
ownr_ln
|
||||
ownr_co_nm
|
||||
ownerid
|
||||
ownr_ph1
|
||||
ownr_ea
|
||||
|
||||
@@ -116,8 +116,8 @@ export function PartsQueuePageComponent({ bodyshop }) {
|
||||
// sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
||||
// sortOrder: sortcolumn === "owner" && sortorder,
|
||||
render: (text, record) => {
|
||||
return record.owner ? (
|
||||
<Link to={"/manage/owners/" + record.owner.id}>
|
||||
return record.ownerid ? (
|
||||
<Link to={"/manage/owners/" + record.ownerid}>
|
||||
{`${record.ownr_fn || ""} ${record.ownr_ln || ""} ${
|
||||
record.ownr_co_nm || ""
|
||||
}`}
|
||||
|
||||
@@ -509,6 +509,7 @@
|
||||
"orderstatuses": "Order Statuses",
|
||||
"partslocations": "Parts Locations",
|
||||
"printlater": "Print Later",
|
||||
"qbo": "Use QuickBooks Online?",
|
||||
"rbac": "Role Based Access Control",
|
||||
"responsibilitycenters": {
|
||||
"costs": "Cost Centers",
|
||||
@@ -1952,6 +1953,7 @@
|
||||
"coversheet_landscape": "Coversheet (Landscape)",
|
||||
"coversheet_portrait": "Coversheet Portrait",
|
||||
"csi_invitation": "CSI Invitation",
|
||||
"csi_invitation_action": "CSI Invite",
|
||||
"diagnostic_authorization": "Diagnostic Authorization",
|
||||
"estimate": "Estimate Only",
|
||||
"estimate_detail": "Estimate Details",
|
||||
@@ -1982,6 +1984,8 @@
|
||||
"qc_sheet": "Quality Control Sheet",
|
||||
"ro_totals": "RO Totals",
|
||||
"ro_with_description": "RO Summary with Descriptions",
|
||||
"sgi_certificate_of_repairs": "SGI - Certificate of Repairs",
|
||||
"sgi_windshield_auth": "SGI - Windshield Authorization",
|
||||
"stolen_recovery_checklist": "Stolen Recovery Checklist",
|
||||
"supplement_request": "Supplement Request",
|
||||
"thank_you_ro": "Thank You Letter",
|
||||
|
||||
@@ -509,6 +509,7 @@
|
||||
"orderstatuses": "",
|
||||
"partslocations": "",
|
||||
"printlater": "",
|
||||
"qbo": "",
|
||||
"rbac": "",
|
||||
"responsibilitycenters": {
|
||||
"costs": "",
|
||||
@@ -1952,6 +1953,7 @@
|
||||
"coversheet_landscape": "",
|
||||
"coversheet_portrait": "",
|
||||
"csi_invitation": "",
|
||||
"csi_invitation_action": "",
|
||||
"diagnostic_authorization": "",
|
||||
"estimate": "",
|
||||
"estimate_detail": "",
|
||||
@@ -1982,6 +1984,8 @@
|
||||
"qc_sheet": "",
|
||||
"ro_totals": "",
|
||||
"ro_with_description": "",
|
||||
"sgi_certificate_of_repairs": "",
|
||||
"sgi_windshield_auth": "",
|
||||
"stolen_recovery_checklist": "",
|
||||
"supplement_request": "",
|
||||
"thank_you_ro": "",
|
||||
|
||||
@@ -509,6 +509,7 @@
|
||||
"orderstatuses": "",
|
||||
"partslocations": "",
|
||||
"printlater": "",
|
||||
"qbo": "",
|
||||
"rbac": "",
|
||||
"responsibilitycenters": {
|
||||
"costs": "",
|
||||
@@ -1952,6 +1953,7 @@
|
||||
"coversheet_landscape": "",
|
||||
"coversheet_portrait": "",
|
||||
"csi_invitation": "",
|
||||
"csi_invitation_action": "",
|
||||
"diagnostic_authorization": "",
|
||||
"estimate": "",
|
||||
"estimate_detail": "",
|
||||
@@ -1982,6 +1984,8 @@
|
||||
"qc_sheet": "",
|
||||
"ro_totals": "",
|
||||
"ro_with_description": "",
|
||||
"sgi_certificate_of_repairs": "",
|
||||
"sgi_windshield_auth": "",
|
||||
"stolen_recovery_checklist": "",
|
||||
"supplement_request": "",
|
||||
"thank_you_ro": "",
|
||||
|
||||
@@ -352,6 +352,28 @@ export const TemplateList = (type, context) => {
|
||||
disabled: false,
|
||||
group: "ro",
|
||||
},
|
||||
sgi_certificate_of_repairs: {
|
||||
title: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
||||
description: "Thank You Letter by RO",
|
||||
key: "sgi_certificate_of_repairs",
|
||||
subject: i18n.t("printcenter.jobs.sgi_certificate_of_repairs"),
|
||||
disabled: false,
|
||||
group: "ro",
|
||||
regions: {
|
||||
CA_SK: true,
|
||||
},
|
||||
},
|
||||
sgi_windshield_auth: {
|
||||
title: i18n.t("printcenter.jobs.sgi_windshield_auth"),
|
||||
description: "Thank You Letter by RO",
|
||||
key: "sgi_windshield_auth",
|
||||
subject: i18n.t("printcenter.jobs.sgi_windshield_auth"),
|
||||
disabled: false,
|
||||
group: "pre",
|
||||
regions: {
|
||||
CA_SK: true,
|
||||
},
|
||||
},
|
||||
// parts_label_multi: {
|
||||
// title: i18n.t("printcenter.jobs.parts_label_multi"),
|
||||
// description: "Thank You Letter by RO",
|
||||
@@ -370,6 +392,13 @@ export const TemplateList = (type, context) => {
|
||||
key: "special_thirdpartypayer",
|
||||
disabled: false,
|
||||
},
|
||||
csi_invitation_action: {
|
||||
title: i18n.t("printcenter.jobs.csi_invitation_action"),
|
||||
description: "CSI invite",
|
||||
key: "csi_invitation_action",
|
||||
subject: i18n.t("printcenter.jobs.csi_invitation_action"),
|
||||
disabled: false,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
...(!type || type === "appointment"
|
||||
|
||||
848
client/yarn.lock
@@ -1,2 +1,7 @@
|
||||
version: 2
|
||||
endpoint: https://bodyshop-dev-db.herokuapp.com
|
||||
admin_secret: Dev-BodyShopApp!
|
||||
metadata_directory: metadata
|
||||
actions:
|
||||
kind: synchronous
|
||||
handler_webhook_baseurl: http://localhost:3000
|
||||
|
||||
0
hasura/metadata/actions.graphql
Normal file
6
hasura/metadata/actions.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
actions: []
|
||||
custom_types:
|
||||
enums: []
|
||||
input_objects: []
|
||||
objects: []
|
||||
scalars: []
|
||||
1
hasura/metadata/allow_list.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
hasura/metadata/cron_triggers.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
27
hasura/metadata/functions.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
- function:
|
||||
schema: public
|
||||
name: search_bills
|
||||
- function:
|
||||
schema: public
|
||||
name: search_cccontracts
|
||||
- function:
|
||||
schema: public
|
||||
name: search_dms_vehicles
|
||||
- function:
|
||||
schema: public
|
||||
name: search_exportlog
|
||||
- function:
|
||||
schema: public
|
||||
name: search_jobs
|
||||
- function:
|
||||
schema: public
|
||||
name: search_owners
|
||||
- function:
|
||||
schema: public
|
||||
name: search_payments
|
||||
- function:
|
||||
schema: public
|
||||
name: search_phonebook
|
||||
- function:
|
||||
schema: public
|
||||
name: search_vehicles
|
||||
1
hasura/metadata/query_collections.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
1
hasura/metadata/remote_schemas.yaml
Normal file
@@ -0,0 +1 @@
|
||||
[]
|
||||
4775
hasura/metadata/tables.yaml
Normal file
1
hasura/metadata/version.yaml
Normal file
@@ -0,0 +1 @@
|
||||
version: 2
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "website";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "website" text NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."documents" DROP COLUMN "takenat";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."documents" ADD COLUMN "takenat" timestamptz NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD CONSTRAINT "bodyshops_autohouseid_key" UNIQUE ("autohouseid");
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP CONSTRAINT "bodyshops_autohouseid_key";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "jc_hourly_rates";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "jc_hourly_rates" jsonb NULL DEFAULT jsonb_build_object();
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."vehicles" ALTER COLUMN "v_vin" SET NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."vehicles" ALTER COLUMN "v_vin" DROP NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE ONLY "public"."joblines" ALTER COLUMN "prt_dsmk_p" DROP DEFAULT;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE ONLY "public"."joblines" ALTER COLUMN "prt_dsmk_p" SET DEFAULT 0;
|
||||
3
hasura/migrations/1622571551101_run_sql_migration/up.sql
Executable file
@@ -0,0 +1,3 @@
|
||||
|
||||
update joblines
|
||||
set prt_dsmk_p = 0 where joblines.prt_dsmk_p is null;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."conversations" DROP COLUMN "archived";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."conversations" ADD COLUMN "archived" boolean NOT NULL DEFAULT false;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."parts_orders" DROP COLUMN "orderedby";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."parts_orders" ADD COLUMN "orderedby" text NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
alter table "public"."parts_orders" drop constraint "parts_orders_orderedby_fkey";
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."parts_orders"
|
||||
add constraint "parts_orders_orderedby_fkey"
|
||||
foreign key ("orderedby")
|
||||
references "public"."users"
|
||||
("email") on update set null on delete set null;
|
||||
8
hasura/migrations/1622650359491_set_fk_public_exportlog_billid/down.sql
Executable file
@@ -0,0 +1,8 @@
|
||||
|
||||
alter table "public"."exportlog" drop constraint "exportlog_billid_fkey",
|
||||
add constraint "exportlog_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id")
|
||||
on update restrict
|
||||
on delete restrict;
|
||||
6
hasura/migrations/1622650359491_set_fk_public_exportlog_billid/up.sql
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."exportlog" drop constraint "exportlog_billid_fkey",
|
||||
add constraint "exportlog_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id") on update cascade on delete cascade;
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
ALTER TABLE ONLY "public"."users" ALTER COLUMN "dashboardlayout" SET DEFAULT jsonb_build_array();
|
||||
ALTER TABLE "public"."users" ALTER COLUMN "dashboardlayout" SET NOT NULL;
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
ALTER TABLE "public"."users" ALTER COLUMN "dashboardlayout" DROP DEFAULT;
|
||||
ALTER TABLE "public"."users" ALTER COLUMN "dashboardlayout" DROP NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "md_jobline_presets";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "md_jobline_presets" jsonb NULL DEFAULT jsonb_build_array();
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "cdk_dealerid";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "cdk_dealerid" text NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "features";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "features" jsonb NULL DEFAULT jsonb_build_object();
|
||||
30
hasura/migrations/1625768789569_run_sql_migration/up.sql
Executable file
@@ -0,0 +1,30 @@
|
||||
|
||||
CREATE OR REPLACE FUNCTION public.search_payments(search text)
|
||||
RETURNS SETOF payments
|
||||
LANGUAGE plpgsql
|
||||
STABLE
|
||||
AS $function$
|
||||
|
||||
BEGIN
|
||||
if search = '' then
|
||||
return query select * from payments ;
|
||||
else
|
||||
return query SELECT
|
||||
p.*
|
||||
FROM
|
||||
payments p, jobs j
|
||||
WHERE
|
||||
p.jobid = j.id AND
|
||||
(
|
||||
search <% p.paymentnum OR
|
||||
search <% j.ownr_fn OR
|
||||
search <% j.ownr_ln OR
|
||||
search <% j.ownr_co_nm OR
|
||||
search <% j.ro_number OR
|
||||
search <% (p.payer) OR
|
||||
search <% (p.transactionid) OR
|
||||
search <% (p.memo));
|
||||
end if;
|
||||
|
||||
END
|
||||
$function$;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
alter table "public"."vehicles" add constraint "vehicles_v_vin_shopid_key" unique ("v_vin", "shopid");
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
alter table "public"."vehicles" drop constraint "vehicles_v_vin_shopid_key";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "attach_pdf_to_email";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "attach_pdf_to_email" boolean NOT NULL DEFAULT False;
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" ADD COLUMN "schemaname" text;
|
||||
ALTER TABLE "public"."audit_trail" ALTER COLUMN "schemaname" DROP NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" DROP COLUMN "schemaname" CASCADE;
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" ADD COLUMN "tabname" text;
|
||||
ALTER TABLE "public"."audit_trail" ALTER COLUMN "tabname" DROP NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" DROP COLUMN "tabname" CASCADE;
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" ADD COLUMN "recordid" uuid;
|
||||
ALTER TABLE "public"."audit_trail" ALTER COLUMN "recordid" DROP NOT NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" DROP COLUMN "recordid" CASCADE;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" DROP COLUMN "jobid";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" ADD COLUMN "jobid" uuid NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" DROP COLUMN "billid";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" ADD COLUMN "billid" uuid NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_billid_fkey";
|
||||
6
hasura/migrations/1626970720625_set_fk_public_audit_trail_billid/up.sql
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."audit_trail"
|
||||
add constraint "audit_trail_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id") on update cascade on delete cascade;
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_billid_fkey",
|
||||
add constraint "audit_trail_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id")
|
||||
on update cascade
|
||||
on delete cascade;
|
||||
6
hasura/migrations/1626970735347_set_fk_public_audit_trail_billid/up.sql
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_billid_fkey",
|
||||
add constraint "audit_trail_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id") on update cascade on delete set null;
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_billid_fkey",
|
||||
add constraint "audit_trail_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id")
|
||||
on update cascade
|
||||
on delete set null;
|
||||
6
hasura/migrations/1626970788128_set_fk_public_audit_trail_billid/up.sql
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_billid_fkey",
|
||||
add constraint "audit_trail_billid_fkey"
|
||||
foreign key ("billid")
|
||||
references "public"."bills"
|
||||
("id") on update cascade on delete set null;
|
||||
2
hasura/migrations/1626970818772_set_fk_public_audit_trail_jobid/down.sql
Executable file
@@ -0,0 +1,2 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_jobid_fkey";
|
||||
6
hasura/migrations/1626970818772_set_fk_public_audit_trail_jobid/up.sql
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."audit_trail"
|
||||
add constraint "audit_trail_jobid_fkey"
|
||||
foreign key ("jobid")
|
||||
references "public"."jobs"
|
||||
("id") on update cascade on delete set null;
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_useremail_fkey",
|
||||
add constraint "audit_trail_useremail_fkey"
|
||||
foreign key ("useremail")
|
||||
references "public"."users"
|
||||
("email")
|
||||
on update restrict
|
||||
on delete restrict;
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
alter table "public"."audit_trail" drop constraint "audit_trail_useremail_fkey",
|
||||
add constraint "audit_trail_useremail_fkey"
|
||||
foreign key ("useremail")
|
||||
references "public"."users"
|
||||
("email") on update cascade on delete set null;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."appointments" DROP COLUMN "note";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."appointments" ADD COLUMN "note" text NULL;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" ALTER COLUMN "created" TYPE timestamp without time zone;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."audit_trail" ALTER COLUMN "created" TYPE timestamptz;
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" DROP COLUMN "tt_allow_post_to_invoiced";
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
ALTER TABLE "public"."bodyshops" ADD COLUMN "tt_allow_post_to_invoiced" boolean NOT NULL DEFAULT false;
|
||||