Compare commits
97 Commits
developmen
...
feature/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb5a146dee | ||
|
|
a8b555b773 | ||
|
|
aa60424eae | ||
|
|
95ba0e1f8a | ||
|
|
786d76bb73 | ||
|
|
8427ea208b | ||
|
|
b897795c27 | ||
|
|
9dfff36edf | ||
|
|
9d4f98d3ee | ||
|
|
8770e95ee3 | ||
|
|
9ff9baa78c | ||
|
|
28326f2628 | ||
|
|
7c35a2e790 | ||
|
|
488d1be1cc | ||
|
|
11d3e3c7ad | ||
|
|
a61b4a47cf | ||
|
|
0108135fe9 | ||
|
|
372b7e8e30 | ||
|
|
74b3ceec63 | ||
|
|
144fe06e60 | ||
|
|
bef01385b2 | ||
|
|
fa3ccf0fea | ||
|
|
d2bb7121cb | ||
|
|
2dbcd203ce | ||
|
|
1eb65dbc43 | ||
|
|
b066e08511 | ||
|
|
214d07f2ef | ||
|
|
16746dd2a0 | ||
|
|
bcec0cd902 | ||
|
|
6faf69a875 | ||
|
|
6f229a859b | ||
|
|
092904377f | ||
|
|
7277688de4 | ||
|
|
9e5ff432d7 | ||
|
|
5817daa4b3 | ||
|
|
51292f50dc | ||
|
|
b5e9e75751 | ||
|
|
f778b964fd | ||
|
|
06c14d2742 | ||
|
|
7441288cf5 | ||
|
|
7524cdf0b1 | ||
|
|
46dff9f52c | ||
|
|
afb0c85e9f | ||
|
|
af6bb18db2 | ||
|
|
c28d4c15a0 | ||
|
|
0c167a1833 | ||
|
|
f7938df5e4 | ||
|
|
5717677339 | ||
|
|
cffe9cd4f6 | ||
|
|
5da8c77b3a | ||
|
|
3cc652d113 | ||
|
|
7d82fb8f04 | ||
|
|
f1cbc9f775 | ||
|
|
58c6ba2f87 | ||
|
|
0fbd4b495b | ||
|
|
343274e1e2 | ||
|
|
bc729c0f8c | ||
|
|
09ce5ac892 | ||
|
|
2536b0b986 | ||
|
|
c8506387f6 | ||
|
|
79f2c7dd3d | ||
|
|
d91a83a137 | ||
|
|
0b21b8d976 | ||
|
|
842cb54867 | ||
|
|
a5628188d8 | ||
|
|
1b0e37be45 | ||
|
|
48ecfe0d98 | ||
|
|
b5b4a3a4f9 | ||
|
|
585d585cd3 | ||
|
|
42356c4e99 | ||
|
|
cd9aeba9f7 | ||
|
|
8a7a5f35c1 | ||
|
|
b24c5e7cf1 | ||
|
|
e8b7e2f0b9 | ||
|
|
b75e14e4f5 | ||
|
|
3e59c60477 | ||
|
|
e89b4fe2a4 | ||
|
|
73b0542b62 | ||
|
|
c9812c36c0 | ||
|
|
d62a2c0aaf | ||
|
|
ee15f063ce | ||
|
|
5f0a683ec1 | ||
|
|
6ae9de7df3 | ||
|
|
19aa41ab5b | ||
|
|
0494b3a9a6 | ||
|
|
01d9dc9033 | ||
|
|
47b8d8d8b2 | ||
|
|
6e3453cd90 | ||
|
|
4e10451bea | ||
|
|
81d5c8f449 | ||
|
|
79fa71fc84 | ||
|
|
f6378daa89 | ||
|
|
f2a4eb1b65 | ||
|
|
2d19c35177 | ||
|
|
9787f7e377 | ||
|
|
3abac3e7ac | ||
|
|
fddf75b40b |
@@ -22,7 +22,7 @@ hooks.js:
|
|||||||
module.exports = [
|
module.exports = [
|
||||||
{
|
{
|
||||||
path: "/pull",
|
path: "/pull",
|
||||||
command: "git pull && npm i",
|
command: "git pull && yarn && pm2 restart 0",
|
||||||
cwd: "/home/ubuntu/io/",
|
cwd: "/home/ubuntu/io/",
|
||||||
method: "post",
|
method: "post",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ import JobsShow from "../jobs/jobs.show";
|
|||||||
const httpLink = new HttpLink({
|
const httpLink = new HttpLink({
|
||||||
uri: process.env.REACT_APP_GRAPHQL_ENDPOINT,
|
uri: process.env.REACT_APP_GRAPHQL_ENDPOINT,
|
||||||
headers: {
|
headers: {
|
||||||
"x-hasura-admin-secret": `Dev-BodyShopAppBySnaptSoftware!`,
|
"x-hasura-admin-secret": `Dev-BodyShopApp!`,
|
||||||
// 'Authorization': `Bearer xxxx`,
|
// 'Authorization': `Bearer xxxx`,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -67,7 +67,7 @@ const client = new ApolloClient({
|
|||||||
// uri: process.env.REACT_APP_GRAPHQL_ENDPOINT,
|
// uri: process.env.REACT_APP_GRAPHQL_ENDPOINT,
|
||||||
// cache: new InMemoryCache(),
|
// cache: new InMemoryCache(),
|
||||||
// headers: {
|
// headers: {
|
||||||
// "x-hasura-admin-secret": `Dev-BodyShopAppBySnaptSoftware!`,
|
// "x-hasura-admin-secret": `Dev-BodyShopApp!`,
|
||||||
// // 'Authorization': `Bearer xxxx`,
|
// // 'Authorization': `Bearer xxxx`,
|
||||||
// },
|
// },
|
||||||
// });
|
// });
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@
|
|||||||
"dinero.js": "^1.8.1",
|
"dinero.js": "^1.8.1",
|
||||||
"dotenv": "^9.0.2",
|
"dotenv": "^9.0.2",
|
||||||
"env-cmd": "^10.1.0",
|
"env-cmd": "^10.1.0",
|
||||||
|
"exifr": "^7.0.0",
|
||||||
"firebase": "^8.6.0",
|
"firebase": "^8.6.0",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"i18next": "^20.2.2",
|
"i18next": "^20.2.2",
|
||||||
@@ -28,6 +29,7 @@
|
|||||||
"jsreport-browser-client-dist": "^1.3.0",
|
"jsreport-browser-client-dist": "^1.3.0",
|
||||||
"libphonenumber-js": "^1.9.17",
|
"libphonenumber-js": "^1.9.17",
|
||||||
"logrocket": "^1.2.0",
|
"logrocket": "^1.2.0",
|
||||||
|
"markerjs2": "^2.8.1",
|
||||||
"moment-business-days": "^1.2.0",
|
"moment-business-days": "^1.2.0",
|
||||||
"phone": "^2.4.21",
|
"phone": "^2.4.21",
|
||||||
"preval.macro": "^5.0.0",
|
"preval.macro": "^5.0.0",
|
||||||
|
|||||||
@@ -9,12 +9,50 @@
|
|||||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||||
<link rel="apple-touch-icon" href="logo192.png" />
|
<link rel="apple-touch-icon" href="logo192.png" />
|
||||||
|
|
||||||
<!-- <script
|
<script>
|
||||||
data-jsd-embedded
|
!(function () {
|
||||||
data-key="51adb36e-ee16-46b1-a4c6-4b6d5fcd8530"
|
"use strict";
|
||||||
data-base-url="https://jsd-widget.atlassian.com"
|
var e = [
|
||||||
src="https://jsd-widget.atlassian.com/assets/embed.js"
|
"debug",
|
||||||
></script> -->
|
"destroy",
|
||||||
|
"do",
|
||||||
|
"help",
|
||||||
|
"identify",
|
||||||
|
"is",
|
||||||
|
"off",
|
||||||
|
"on",
|
||||||
|
"ready",
|
||||||
|
"render",
|
||||||
|
"reset",
|
||||||
|
"safe",
|
||||||
|
"set",
|
||||||
|
];
|
||||||
|
if (window.noticeable)
|
||||||
|
console.warn("Noticeable SDK code snippet loaded more than once");
|
||||||
|
else {
|
||||||
|
var n = (window.noticeable = window.noticeable || []);
|
||||||
|
function t(e) {
|
||||||
|
return function () {
|
||||||
|
var t = Array.prototype.slice.call(arguments);
|
||||||
|
return t.unshift(e), n.push(t), n;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
!(function () {
|
||||||
|
for (var o = 0; o < e.length; o++) {
|
||||||
|
var r = e[o];
|
||||||
|
n[r] = t(r);
|
||||||
|
}
|
||||||
|
})(),
|
||||||
|
(function () {
|
||||||
|
var e = document.createElement("script");
|
||||||
|
(e.async = !0), (e.src = "https://sdk.noticeable.io/l.js");
|
||||||
|
var n = document.head;
|
||||||
|
n.insertBefore(e, n.firstChild);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is installed on a
|
manifest.json provides metadata used when your web app is installed on a
|
||||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||||
|
|||||||
@@ -3,17 +3,42 @@ import { ConfigProvider } from "antd";
|
|||||||
import enLocale from "antd/es/locale/en_US";
|
import enLocale from "antd/es/locale/en_US";
|
||||||
import LogRocket from "logrocket";
|
import LogRocket from "logrocket";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import React from "react";
|
import React, { useEffect } from "react";
|
||||||
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
||||||
import client from "../utils/GraphQLClient";
|
import client from "../utils/GraphQLClient";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import JiraSupportComponent from "../components/jira-support-widget/jira-support-widget.component";
|
||||||
moment.locale("en-US");
|
moment.locale("en-US");
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "production") LogRocket.init("gvfvfw/bodyshopapp");
|
if (process.env.NODE_ENV === "production") LogRocket.init("gvfvfw/bodyshopapp");
|
||||||
|
|
||||||
export default function AppContainer() {
|
export default function AppContainer() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Include the Crisp code here, without the <script></script> tags
|
||||||
|
window.$crisp = [];
|
||||||
|
window.CRISP_WEBSITE_ID = "36724f62-2eb0-4b29-9cdd-9905fb99913e";
|
||||||
|
var d = document;
|
||||||
|
var s = d.createElement("script");
|
||||||
|
s.src = "https://client.crisp.chat/l.js";
|
||||||
|
s.async = 1;
|
||||||
|
d.getElementsByTagName("head")[0].appendChild(s);
|
||||||
|
|
||||||
|
//Release Notes
|
||||||
|
|
||||||
|
// var rs = d.createElement("script");
|
||||||
|
// rs.src = "https://sdk.noticeable.io/s.js";
|
||||||
|
// //rs.async = 1;
|
||||||
|
// d.getElementsByTagName("head")[0].appendChild(rs);
|
||||||
|
// // window.noticeable.render("widget", "IABVNO4scRKY11XBQkNr");
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
d.getElementsByTagName("head")[0].removeChild(s);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ApolloProvider client={client}>
|
<ApolloProvider client={client}>
|
||||||
<ConfigProvider
|
<ConfigProvider
|
||||||
@@ -29,6 +54,7 @@ export default function AppContainer() {
|
|||||||
>
|
>
|
||||||
<GlobalLoadingBar />
|
<GlobalLoadingBar />
|
||||||
<App />
|
<App />
|
||||||
|
<JiraSupportComponent />
|
||||||
</ConfigProvider>
|
</ConfigProvider>
|
||||||
</ApolloProvider>
|
</ApolloProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,13 +1,17 @@
|
|||||||
|
import { Button, Result } from "antd";
|
||||||
import React, { lazy, Suspense, useEffect } from "react";
|
import React, { lazy, Suspense, useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import DocumentEditorContainer from "../components/document-editor/document-editor.container";
|
||||||
import ErrorBoundary from "../components/error-boundary/error-boundary.component";
|
import ErrorBoundary from "../components/error-boundary/error-boundary.component";
|
||||||
//Component Imports
|
//Component Imports
|
||||||
import LoadingSpinner from "../components/loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../components/loading-spinner/loading-spinner.component";
|
||||||
import AboutPage from "../pages/about/about.page";
|
import AboutPage from "../pages/about/about.page";
|
||||||
import TechPageContainer from "../pages/tech/tech.page.container";
|
import TechPageContainer from "../pages/tech/tech.page.container";
|
||||||
|
import { setOnline } from "../redux/application/application.actions";
|
||||||
|
import { selectOnline } from "../redux/application/application.selectors";
|
||||||
import { checkUserSession } from "../redux/user/user.actions";
|
import { checkUserSession } from "../redux/user/user.actions";
|
||||||
import { selectCurrentUser } from "../redux/user/user.selectors";
|
import { selectCurrentUser } from "../redux/user/user.selectors";
|
||||||
import PrivateRoute from "../utils/private-route";
|
import PrivateRoute from "../utils/private-route";
|
||||||
@@ -27,25 +31,59 @@ const MobilePaymentContainer = lazy(() =>
|
|||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
|
online: selectOnline,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
checkUserSession: () => dispatch(checkUserSession()),
|
checkUserSession: () => dispatch(checkUserSession()),
|
||||||
|
setOnline: (isOnline) => dispatch(setOnline(isOnline)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export function App({ checkUserSession, currentUser }) {
|
export function App({ checkUserSession, currentUser, online, setOnline }) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!navigator.onLine) {
|
||||||
|
setOnline(false);
|
||||||
|
}
|
||||||
|
|
||||||
checkUserSession();
|
checkUserSession();
|
||||||
}, [checkUserSession]);
|
}, [checkUserSession, setOnline]);
|
||||||
|
|
||||||
//const b = Grid.useBreakpoint();
|
//const b = Grid.useBreakpoint();
|
||||||
// console.log("Breakpoints:", b);
|
// console.log("Breakpoints:", b);
|
||||||
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
window.addEventListener("offline", function (e) {
|
||||||
|
console.log("Internet connection lost.");
|
||||||
|
setOnline(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener("online", function (e) {
|
||||||
|
setOnline(true);
|
||||||
|
});
|
||||||
|
|
||||||
if (currentUser.authorized === null) {
|
if (currentUser.authorized === null) {
|
||||||
return <LoadingSpinner message={t("general.labels.loggingin")} />;
|
return <LoadingSpinner message={t("general.labels.loggingin")} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!online)
|
||||||
|
return (
|
||||||
|
<Result
|
||||||
|
status="warning"
|
||||||
|
title={t("general.labels.nointernet")}
|
||||||
|
subTitle={t("general.labels.nointernet_sub")}
|
||||||
|
extra={
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
window.location.reload();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("general.actions.refresh")}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Suspense fallback={<LoadingSpinner message="ImEX Online" />}>
|
<Suspense fallback={<LoadingSpinner message="ImEX Online" />}>
|
||||||
@@ -85,6 +123,13 @@ export function App({ checkUserSession, currentUser }) {
|
|||||||
component={TechPageContainer}
|
component={TechPageContainer}
|
||||||
/>
|
/>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
|
<ErrorBoundary>
|
||||||
|
<PrivateRoute
|
||||||
|
isAuthorized={currentUser.authorized}
|
||||||
|
path="/edit"
|
||||||
|
component={DocumentEditorContainer}
|
||||||
|
/>
|
||||||
|
</ErrorBoundary>
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</Switch>
|
</Switch>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -118,3 +118,9 @@
|
|||||||
.production-list-min-height {
|
.production-list-min-height {
|
||||||
min-height: 19px;
|
min-height: 19px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#noticeable-widget {
|
||||||
|
iframe {
|
||||||
|
z-index: 2 !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import { Link } from "react-router-dom";
|
|||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter, DateTimeFormatter } from "../../utils/DateFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||||
import PaymentExportButton from "../payment-export-button/payment-export-button.component";
|
import PaymentExportButton from "../payment-export-button/payment-export-button.component";
|
||||||
import { PaymentsExportAllButton } from "../payments-export-all-button/payments-export-all-button.component";
|
import PaymentsExportAllButton from "../payments-export-all-button/payments-export-all-button.component";
|
||||||
|
|
||||||
export default function AccountingPayablesTableComponent({
|
export default function AccountingPayablesTableComponent({
|
||||||
loading,
|
loading,
|
||||||
@@ -41,19 +41,12 @@ export default function AccountingPayablesTableComponent({
|
|||||||
title: t("payments.fields.date"),
|
title: t("payments.fields.date"),
|
||||||
dataIndex: "date",
|
dataIndex: "date",
|
||||||
key: "date",
|
key: "date",
|
||||||
sorter: (a, b) => alphaSort(a.date, b.date),
|
sorter: (a, b) => dateSort(a.date, b.date),
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "date" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "date" && state.sortedInfo.order,
|
||||||
render: (text, record) => <DateFormatter>{record.date}</DateFormatter>,
|
render: (text, record) => <DateFormatter>{record.date}</DateFormatter>,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: t("payments.fields.date"),
|
|
||||||
dataIndex: "date",
|
|
||||||
key: "date",
|
|
||||||
sorter: (a, b) => alphaSort(a.date, b.date),
|
|
||||||
sortOrder:
|
|
||||||
state.sortedInfo.columnKey === "date" && state.sortedInfo.order,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.owner"),
|
title: t("jobs.fields.owner"),
|
||||||
dataIndex: "owner",
|
dataIndex: "owner",
|
||||||
@@ -61,7 +54,7 @@ export default function AccountingPayablesTableComponent({
|
|||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: (a, b) => alphaSort(a.job.ownr_ln, b.job.ownr_ln),
|
sorter: (a, b) => alphaSort(a.job.ownr_ln, b.job.ownr_ln),
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "ownr_ln" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "owner" && state.sortedInfo.order,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.job.owner ? (
|
return record.job.owner ? (
|
||||||
<Link to={"/manage/owners/" + record.job.owner.id}>
|
<Link to={"/manage/owners/" + record.job.owner.id}>
|
||||||
|
|||||||
@@ -106,6 +106,18 @@ export function BillFormComponent({
|
|||||||
required: true,
|
required: true,
|
||||||
//message: t("general.validation.required"),
|
//message: t("general.validation.required"),
|
||||||
},
|
},
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(rule, value) {
|
||||||
|
if (
|
||||||
|
value &&
|
||||||
|
!getFieldValue(["isinhouse"]) &&
|
||||||
|
value === bodyshop.inhousevendorid
|
||||||
|
) {
|
||||||
|
return Promise.reject(t("bills.validation.manualinhouse"));
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
}),
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<VendorSearchSelect
|
<VendorSearchSelect
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Space } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||||
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
|
||||||
@@ -5,20 +6,16 @@ import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
|
|||||||
|
|
||||||
export default function ChatConversationTitle({ conversation }) {
|
export default function ChatConversationTitle({ conversation }) {
|
||||||
return (
|
return (
|
||||||
<div>
|
<Space flex>
|
||||||
<div className="imex-flex-row">
|
<PhoneNumberFormatter>
|
||||||
<ChatConversationTitleTags
|
{conversation && conversation.phone_num}
|
||||||
jobConversations={
|
</PhoneNumberFormatter>
|
||||||
(conversation && conversation.job_conversations) || []
|
<ChatConversationTitleTags
|
||||||
}
|
jobConversations={
|
||||||
/>
|
(conversation && conversation.job_conversations) || []
|
||||||
<ChatTagRoContainer conversation={conversation || []} />
|
}
|
||||||
</div>
|
/>
|
||||||
<div className="imex-flex-row">
|
<ChatTagRoContainer conversation={conversation || []} />
|
||||||
<PhoneNumberFormatter>
|
</Space>
|
||||||
{conversation && conversation.phone_num}
|
|
||||||
</PhoneNumberFormatter>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CloseCircleOutlined, LoadingOutlined } from "@ant-design/icons";
|
import { CloseCircleOutlined, LoadingOutlined } from "@ant-design/icons";
|
||||||
import { Select, Empty } from "antd";
|
import { Select, Empty, Space } from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
@@ -13,27 +13,27 @@ export default function ChatTagRoComponent({
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<Space flex>
|
||||||
<Select
|
<div style={{ width: "15rem" }}>
|
||||||
showSearch
|
<Select
|
||||||
autoFocus
|
showSearch
|
||||||
style={{
|
autoFocus
|
||||||
width: 300,
|
dropdownMatchSelectWidth
|
||||||
}}
|
placeholder={t("general.labels.search")}
|
||||||
placeholder={t("general.labels.search")}
|
filterOption={false}
|
||||||
filterOption={false}
|
onSearch={handleSearch}
|
||||||
onSearch={handleSearch}
|
onSelect={handleInsertTag}
|
||||||
onSelect={handleInsertTag}
|
notFoundContent={loading ? <LoadingOutlined /> : <Empty />}
|
||||||
notFoundContent={loading ? <LoadingOutlined /> : <Empty />}
|
>
|
||||||
>
|
{roOptions.map((item, idx) => (
|
||||||
{roOptions.map((item, idx) => (
|
<Select.Option key={item.id || idx}>
|
||||||
<Select.Option key={item.id || idx}>
|
{` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${
|
||||||
{` ${item.ro_number || ""} | ${item.ownr_fn || ""} ${
|
item.ownr_ln || ""
|
||||||
item.ownr_ln || ""
|
} ${item.ownr_co_nm || ""}`}
|
||||||
} ${item.ownr_co_nm || ""}`}
|
</Select.Option>
|
||||||
</Select.Option>
|
))}
|
||||||
))}
|
</Select>
|
||||||
</Select>
|
</div>
|
||||||
{loading ? <LoadingOutlined /> : null}
|
{loading ? <LoadingOutlined /> : null}
|
||||||
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
@@ -41,6 +41,6 @@ export default function ChatTagRoComponent({
|
|||||||
) : (
|
) : (
|
||||||
<CloseCircleOutlined onClick={() => setVisible(false)} />
|
<CloseCircleOutlined onClick={() => setVisible(false)} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</Space>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
//import "tui-image-editor/dist/tui-image-editor.css";
|
||||||
|
import { Result } from "antd";
|
||||||
|
import * as markerjs2 from "markerjs2";
|
||||||
|
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import {
|
||||||
|
selectBodyshop,
|
||||||
|
selectCurrentUser,
|
||||||
|
} from "../../redux/user/user.selectors";
|
||||||
|
import { handleUpload } from "../documents-upload/documents-upload.utility";
|
||||||
|
import { GenerateSrcUrl } from "../jobs-documents-gallery/job-documents.utility";
|
||||||
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
currentUser: selectCurrentUser,
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
|
||||||
|
export function DocumentEditorComponent({ currentUser, bodyshop, document }) {
|
||||||
|
const imgRef = useRef(null);
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [uploaded, setuploaded] = useState(false);
|
||||||
|
const markerArea = useRef(null);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
const triggerUpload = useCallback(
|
||||||
|
async (dataUrl) => {
|
||||||
|
setLoading(true);
|
||||||
|
handleUpload(
|
||||||
|
{
|
||||||
|
filename: `${document.key.split("/").pop()}-${Date.now()}.jpg`,
|
||||||
|
file: await b64toBlob(dataUrl),
|
||||||
|
onSuccess: () => {
|
||||||
|
setLoading(false);
|
||||||
|
setuploaded(true);
|
||||||
|
},
|
||||||
|
onError: () => setLoading(false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bodyshop: bodyshop,
|
||||||
|
uploaded_by: currentUser.email,
|
||||||
|
jobId: document.jobid,
|
||||||
|
//billId: billId,
|
||||||
|
tagsArray: ["edited"],
|
||||||
|
//callback: callbackAfterUpload,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[bodyshop, currentUser, document]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (imgRef.current !== null) {
|
||||||
|
// create a marker.js MarkerArea
|
||||||
|
markerArea.current = new markerjs2.MarkerArea(imgRef.current);
|
||||||
|
console.log(`markerArea.current`, markerArea.current);
|
||||||
|
// attach an event handler to assign annotated image back to our image element
|
||||||
|
markerArea.current.addCloseEventListener((closeEvent) => {
|
||||||
|
console.log("Close Event", closeEvent);
|
||||||
|
});
|
||||||
|
|
||||||
|
markerArea.current.addRenderEventListener((dataUrl) => {
|
||||||
|
imgRef.current.src = dataUrl;
|
||||||
|
markerArea.current.close();
|
||||||
|
triggerUpload(dataUrl);
|
||||||
|
});
|
||||||
|
// launch marker.js
|
||||||
|
|
||||||
|
markerArea.current.renderAtNaturalSize = true;
|
||||||
|
markerArea.current.renderImageType = "image/jpeg";
|
||||||
|
markerArea.current.renderImageQuality = 1;
|
||||||
|
//markerArea.current.settings.displayMode = "inline";
|
||||||
|
markerArea.current.show();
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [triggerUpload]);
|
||||||
|
|
||||||
|
async function b64toBlob(url) {
|
||||||
|
const res = await fetch(url);
|
||||||
|
return await res.blob();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{!loading && !uploaded && (
|
||||||
|
<img
|
||||||
|
ref={imgRef}
|
||||||
|
src={GenerateSrcUrl(document)}
|
||||||
|
alt="sample"
|
||||||
|
crossOrigin="anonymous"
|
||||||
|
style={{ maxWidth: "90vw", maxHeight: "90vh" }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{loading && <LoadingSpinner message={t("documents.labels.uploading")} />}
|
||||||
|
{uploaded && (
|
||||||
|
<Result
|
||||||
|
status="success"
|
||||||
|
title={t("documents.successes.edituploaded")}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(DocumentEditorComponent);
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import { useQuery } from "@apollo/client";
|
||||||
|
import { Result } from "antd";
|
||||||
|
import queryString from "query-string";
|
||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { useLocation } from "react-router";
|
||||||
|
import { QUERY_BODYSHOP } from "../../graphql/bodyshop.queries";
|
||||||
|
import { GET_DOCUMENT_BY_PK } from "../../graphql/documents.queries";
|
||||||
|
import { setBodyshop } from "../../redux/user/user.actions";
|
||||||
|
import AlertComponent from "../alert/alert.component";
|
||||||
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
|
import DocumentEditor from "./document-editor.component";
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
setBodyshop: (bs) => dispatch(setBodyshop(bs)),
|
||||||
|
});
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(DocumentEditorContainer);
|
||||||
|
|
||||||
|
export function DocumentEditorContainer({ setBodyshop }) {
|
||||||
|
//Get the image details for the image to be saved.
|
||||||
|
//Get the document id from the search string.
|
||||||
|
const { documentId } = queryString.parse(useLocation().search);
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
loading: loadingShop,
|
||||||
|
error: errorShop,
|
||||||
|
data: dataShop,
|
||||||
|
} = useQuery(QUERY_BODYSHOP, {
|
||||||
|
fetchPolicy: "network-only",
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (dataShop) setBodyshop(dataShop.bodyshops[0]);
|
||||||
|
}, [dataShop, setBodyshop]);
|
||||||
|
|
||||||
|
const { loading, error, data } = useQuery(GET_DOCUMENT_BY_PK, {
|
||||||
|
variables: { documentId },
|
||||||
|
skip: !documentId,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (loading || loadingShop) return <LoadingSpinner />;
|
||||||
|
if (error || errorShop)
|
||||||
|
return (
|
||||||
|
<AlertComponent
|
||||||
|
message={error.message || errorShop.message}
|
||||||
|
type="error"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!data || !data.documents_by_pk)
|
||||||
|
return <Result status="404" title={t("general.errors.notfound")} />;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<DocumentEditor document={data ? data.documents_by_pk : null} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,6 +5,8 @@ import { logImEXEvent } from "../../firebase/firebase.utils";
|
|||||||
import { INSERT_NEW_DOCUMENT } from "../../graphql/documents.queries";
|
import { INSERT_NEW_DOCUMENT } from "../../graphql/documents.queries";
|
||||||
import { axiosAuthInterceptorId } from "../../utils/CleanAxios";
|
import { axiosAuthInterceptorId } from "../../utils/CleanAxios";
|
||||||
import client from "../../utils/GraphQLClient";
|
import client from "../../utils/GraphQLClient";
|
||||||
|
import exifr from "exifr";
|
||||||
|
|
||||||
//Context: currentUserEmail, bodyshop, jobid, invoiceid
|
//Context: currentUserEmail, bodyshop, jobid, invoiceid
|
||||||
|
|
||||||
//Required to prevent headers from getting set and rejected from Cloudinary.
|
//Required to prevent headers from getting set and rejected from Cloudinary.
|
||||||
@@ -19,8 +21,13 @@ export const handleUpload = (ev, context) => {
|
|||||||
const { onError, onSuccess, onProgress } = ev;
|
const { onError, onSuccess, onProgress } = ev;
|
||||||
const { bodyshop, jobId } = context;
|
const { bodyshop, jobId } = context;
|
||||||
|
|
||||||
let key = `${bodyshop.id}/${jobId}/${ev.file.name.replace(/\.[^/.]+$/, "")}`;
|
const fileName = ev.file.name || ev.filename;
|
||||||
let extension = ev.file.name.split(".").pop();
|
|
||||||
|
let key = `${bodyshop.id}/${jobId}/${fileName.replace(
|
||||||
|
/\.[^/.]+$/,
|
||||||
|
""
|
||||||
|
)}-${new Date().getTime()}`;
|
||||||
|
let extension = fileName.split(".").pop();
|
||||||
uploadToCloudinary(
|
uploadToCloudinary(
|
||||||
key,
|
key,
|
||||||
extension,
|
extension,
|
||||||
@@ -85,6 +92,7 @@ export const uploadToCloudinary = async (
|
|||||||
if (!!onProgress) onProgress({ percent: (e.loaded / e.total) * 100 });
|
if (!!onProgress) onProgress({ percent: (e.loaded / e.total) * 100 });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append("file", file);
|
formData.append("file", file);
|
||||||
|
|
||||||
@@ -122,6 +130,12 @@ export const uploadToCloudinary = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
//Insert the document with the matching key.
|
//Insert the document with the matching key.
|
||||||
|
let takenat;
|
||||||
|
if (fileType.includes("image")) {
|
||||||
|
const exif = await exifr.parse(file);
|
||||||
|
|
||||||
|
takenat = exif && exif.DateTimeOriginal;
|
||||||
|
}
|
||||||
const documentInsert = await client.mutate({
|
const documentInsert = await client.mutate({
|
||||||
mutation: INSERT_NEW_DOCUMENT,
|
mutation: INSERT_NEW_DOCUMENT,
|
||||||
variables: {
|
variables: {
|
||||||
@@ -132,9 +146,10 @@ export const uploadToCloudinary = async (
|
|||||||
uploaded_by: uploaded_by,
|
uploaded_by: uploaded_by,
|
||||||
key: key,
|
key: key,
|
||||||
type: fileType,
|
type: fileType,
|
||||||
extension: extension,
|
extension: cloudinaryUploadResponse.data.format || extension,
|
||||||
bodyshopid: bodyshop.id,
|
bodyshopid: bodyshop.id,
|
||||||
size: cloudinaryUploadResponse.data.bytes || file.size,
|
size: cloudinaryUploadResponse.data.bytes || file.size,
|
||||||
|
takenat,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -166,6 +181,7 @@ export const uploadToCloudinary = async (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Also needs to be updated in media JS and mobile app.
|
||||||
export function DetermineFileType(filetype) {
|
export function DetermineFileType(filetype) {
|
||||||
if (!filetype) return "auto";
|
if (!filetype) return "auto";
|
||||||
else if (filetype.startsWith("image")) return "image";
|
else if (filetype.startsWith("image")) return "image";
|
||||||
|
|||||||
@@ -57,6 +57,23 @@ ${this.state.error.stack}
|
|||||||
if (this.state.hasErrored === true) {
|
if (this.state.hasErrored === true) {
|
||||||
logImEXEvent("error_boundary_rendered", { error, info });
|
logImEXEvent("error_boundary_rendered", { error, info });
|
||||||
|
|
||||||
|
window.$crisp.push([
|
||||||
|
"set",
|
||||||
|
"session:event",
|
||||||
|
[
|
||||||
|
[
|
||||||
|
[
|
||||||
|
"error_boundary",
|
||||||
|
{
|
||||||
|
error: this.state.error.message,
|
||||||
|
stack: this.state.error.stack,
|
||||||
|
},
|
||||||
|
"red",
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Result
|
<Result
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import Icon, {
|
|||||||
LineChartOutlined,
|
LineChartOutlined,
|
||||||
PaperClipOutlined,
|
PaperClipOutlined,
|
||||||
PhoneOutlined,
|
PhoneOutlined,
|
||||||
|
QuestionCircleFilled,
|
||||||
ScheduleOutlined,
|
ScheduleOutlined,
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
TeamOutlined,
|
TeamOutlined,
|
||||||
@@ -255,6 +256,13 @@ function Header({
|
|||||||
{t("menus.header.temporarydocs")}
|
{t("menus.header.temporarydocs")}
|
||||||
</Link>
|
</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
<Menu.Item
|
||||||
|
key="help"
|
||||||
|
onClick={() => {
|
||||||
|
window.open("https://help.imex.online/", "_blank");
|
||||||
|
}}
|
||||||
|
icon={<Icon component={QuestionCircleFilled} />}
|
||||||
|
/>
|
||||||
<Menu.SubMenu title={t("menus.header.shop")} icon={<SettingOutlined />}>
|
<Menu.SubMenu title={t("menus.header.shop")} 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">{t("menus.header.shop_config")}</Link>
|
||||||
|
|||||||
@@ -1,28 +1,28 @@
|
|||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default function JiraSupportComponent() {
|
export default function JiraSupportComponent() {
|
||||||
useScript();
|
//useScript();
|
||||||
|
|
||||||
return <div></div>;
|
return <div></div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const useScript = () => {
|
// const useScript = () => {
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
const script = document.createElement("script");
|
// const script = document.createElement("script");
|
||||||
script.src = "https://jsd-widget.atlassian.com/assets/embed.js";
|
// script.src = "https://jsd-widget.atlassian.com/assets/embed.js";
|
||||||
script.setAttribute("data-jsd-embedded", true);
|
// script.setAttribute("data-jsd-embedded", true);
|
||||||
script.setAttribute("data-key", "d69bb65c-1dd3-483f-b109-66a970d03f44");
|
// script.setAttribute("data-key", "d69bb65c-1dd3-483f-b109-66a970d03f44");
|
||||||
script.setAttribute("data-base-url", "https://jsd-widget.atlassian.com");
|
// script.setAttribute("data-base-url", "https://jsd-widget.atlassian.com");
|
||||||
//script.async = true;
|
// //script.async = true;
|
||||||
script.onload = () => {
|
// script.onload = () => {
|
||||||
var DOMContentLoaded_event = document.createEvent("Event");
|
// var DOMContentLoaded_event = document.createEvent("Event");
|
||||||
DOMContentLoaded_event.initEvent("DOMContentLoaded", true, true);
|
// DOMContentLoaded_event.initEvent("DOMContentLoaded", true, true);
|
||||||
window.document.dispatchEvent(DOMContentLoaded_event);
|
// window.document.dispatchEvent(DOMContentLoaded_event);
|
||||||
};
|
// };
|
||||||
document.head.appendChild(script);
|
// document.head.appendChild(script);
|
||||||
|
|
||||||
return () => {
|
// return () => {
|
||||||
document.head.removeChild(script);
|
// document.head.removeChild(script);
|
||||||
};
|
// };
|
||||||
}, []);
|
// }, []);
|
||||||
};
|
// };
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from "../../../../redux/user/user.selectors";
|
} from "../../../../redux/user/user.selectors";
|
||||||
import ConfigFormComponents from "../../../config-form-components/config-form-components.component";
|
import ConfigFormComponents from "../../../config-form-components/config-form-components.component";
|
||||||
import DateTimePicker from "../../../form-date-time-picker/form-date-time-picker.component";
|
import DateTimePicker from "../../../form-date-time-picker/form-date-time-picker.component";
|
||||||
|
import moment from "moment-business-days";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
@@ -133,7 +134,14 @@ export function JobChecklistForm({
|
|||||||
initialValues={{
|
initialValues={{
|
||||||
...(type === "intake" && {
|
...(type === "intake" && {
|
||||||
addToProduction: true,
|
addToProduction: true,
|
||||||
scheduled_completion: job && job.scheduled_completion,
|
scheduled_completion:
|
||||||
|
(job && job.scheduled_completion) ||
|
||||||
|
moment().businessAdd(
|
||||||
|
(job.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
job.larhrs.aggregate.sum.mod_lb_hrs) /
|
||||||
|
bodyshop.target_touchtime,
|
||||||
|
"days"
|
||||||
|
),
|
||||||
scheduled_delivery: job && job.scheduled_delivery,
|
scheduled_delivery: job && job.scheduled_delivery,
|
||||||
}),
|
}),
|
||||||
...(type === "deliver" && {
|
...(type === "deliver" && {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export default function JobDetailCardsNotesComponent({ loading, data }) {
|
|||||||
bordered
|
bordered
|
||||||
dataSource={data.notes}
|
dataSource={data.notes}
|
||||||
renderItem={(item) => (
|
renderItem={(item) => (
|
||||||
<List.Item>
|
<List.Item style={{ whiteSpace: "pre-line" }}>
|
||||||
{item.critical ? (
|
{item.critical ? (
|
||||||
<EyeInvisibleFilled style={{ margin: 4, color: "red" }} />
|
<EyeInvisibleFilled style={{ margin: 4, color: "red" }} />
|
||||||
) : null}
|
) : null}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import { createStructuredSelector } from "reselect";
|
|||||||
import { DELETE_JOB_LINE_BY_PK } from "../../graphql/jobs-lines.queries";
|
import { DELETE_JOB_LINE_BY_PK } from "../../graphql/jobs-lines.queries";
|
||||||
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
import { selectJobReadOnly } from "../../redux/application/application.selectors";
|
||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
import { onlyUnique } from "../../utils/arrayHelper";
|
import { onlyUnique } from "../../utils/arrayHelper";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort } from "../../utils/sorters";
|
||||||
@@ -37,6 +38,7 @@ import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.con
|
|||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
|
technician: selectTechnician,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
@@ -48,6 +50,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||||||
|
|
||||||
export function JobLinesComponent({
|
export function JobLinesComponent({
|
||||||
jobRO,
|
jobRO,
|
||||||
|
technician,
|
||||||
setPartsOrderContext,
|
setPartsOrderContext,
|
||||||
loading,
|
loading,
|
||||||
refetch,
|
refetch,
|
||||||
@@ -155,7 +158,16 @@ export function JobLinesComponent({
|
|||||||
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "act_price" && state.sortedInfo.order,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<CurrencyFormatter>{record.act_price}</CurrencyFormatter>
|
<>
|
||||||
|
<CurrencyFormatter>{record.act_price}</CurrencyFormatter>
|
||||||
|
{record.prt_dsmk_p && record.prt_dsmk_p !== 0 ? (
|
||||||
|
<span
|
||||||
|
style={{ marginLeft: ".2rem" }}
|
||||||
|
>{`(${record.prt_dsmk_p}%)`}</span>
|
||||||
|
) : (
|
||||||
|
<></>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -313,9 +325,12 @@ export function JobLinesComponent({
|
|||||||
if (e.key === "clear") {
|
if (e.key === "clear") {
|
||||||
setSelectedLines([]);
|
setSelectedLines([]);
|
||||||
} else {
|
} else {
|
||||||
|
const markedTypes = [e.key];
|
||||||
|
if (e.key === "PAN") markedTypes.push("PAP");
|
||||||
|
if (e.key === "PAS") markedTypes.push("PASL");
|
||||||
setSelectedLines([
|
setSelectedLines([
|
||||||
...selectedLines,
|
...selectedLines,
|
||||||
...jobLines.filter((item) => item.part_type === e.key),
|
...jobLines.filter((item) => markedTypes.includes(item.part_type)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -354,7 +369,8 @@ export function JobLinesComponent({
|
|||||||
disabled={
|
disabled={
|
||||||
(job && !job.converted) ||
|
(job && !job.converted) ||
|
||||||
(selectedLines.length > 0 ? false : true) ||
|
(selectedLines.length > 0 ? false : true) ||
|
||||||
jobRO
|
jobRO ||
|
||||||
|
technician
|
||||||
}
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPartsOrderContext({
|
setPartsOrderContext({
|
||||||
@@ -378,7 +394,7 @@ export function JobLinesComponent({
|
|||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
filteredInfo: {
|
filteredInfo: {
|
||||||
part_type: ["PAN,PAL,PAA,PAS,PASL"],
|
part_type: ["PAN,PAL,PAA,PAP,PAS,PASL"],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -389,7 +405,7 @@ export function JobLinesComponent({
|
|||||||
<Button>{t("jobs.actions.mark")}</Button>
|
<Button>{t("jobs.actions.mark")}</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<Button
|
<Button
|
||||||
disabled={jobRO}
|
disabled={jobRO || technician}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setJobLineEditContext({
|
setJobLineEditContext({
|
||||||
actions: { refetch: refetch },
|
actions: { refetch: refetch },
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ export default function JobLinesUpsertModalComponent({
|
|||||||
// }),
|
// }),
|
||||||
// ]}
|
// ]}
|
||||||
>
|
>
|
||||||
<InputCurrency />
|
<InputNumber precision={1} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow>
|
<LayoutFormRow>
|
||||||
@@ -210,6 +210,13 @@ export default function JobLinesUpsertModalComponent({
|
|||||||
>
|
>
|
||||||
<InputCurrency precision={2} min={0} />
|
<InputCurrency precision={2} min={0} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("joblines.fields.prt_dsmk_p")}
|
||||||
|
name="prt_dsmk_p"
|
||||||
|
initialValue={0}
|
||||||
|
>
|
||||||
|
<InputNumber precision={0} min={0} max={100} />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import { selectJobReadOnly } from "../../redux/application/application.selectors
|
|||||||
import { setModalContext } from "../../redux/modals/modals.actions";
|
import { setModalContext } from "../../redux/modals/modals.actions";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||||
import { TemplateList } from "../../utils/TemplateConstants";
|
import { TemplateList } from "../../utils/TemplateConstants";
|
||||||
import DataLabel from "../data-label/data-label.component";
|
import DataLabel from "../data-label/data-label.component";
|
||||||
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
import PrintWrapperComponent from "../print-wrapper/print-wrapper.component";
|
||||||
@@ -40,14 +40,14 @@ export function JobPayments({
|
|||||||
});
|
});
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: t("payments.fields.created_at"),
|
title: t("payments.fields.date"),
|
||||||
dataIndex: "created_at",
|
dataIndex: "date",
|
||||||
key: "created_at",
|
key: "date",
|
||||||
|
sorter: (a, b) => dateSort(a.date, b.date),
|
||||||
|
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "created_at" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "date" && state.sortedInfo.order,
|
||||||
render: (text, record) => (
|
render: (text, record) => <DateFormatter>{record.date}</DateFormatter>,
|
||||||
<DateTimeFormatter>{record.created_at}</DateTimeFormatter>
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("payments.fields.payer"),
|
title: t("payments.fields.payer"),
|
||||||
|
|||||||
@@ -69,17 +69,28 @@ export default function JobTotalsTableParts({ job }) {
|
|||||||
x: true,
|
x: true,
|
||||||
}}
|
}}
|
||||||
summary={() => (
|
summary={() => (
|
||||||
<Table.Summary.Row>
|
<>
|
||||||
<Table.Summary.Cell>
|
<Table.Summary.Row>
|
||||||
<strong>{t("jobs.labels.partstotal")}</strong>
|
<Table.Summary.Cell>
|
||||||
</Table.Summary.Cell>
|
{t("jobs.labels.prt_dsmk_total")}
|
||||||
|
</Table.Summary.Cell>
|
||||||
|
|
||||||
<Table.Summary.Cell align="right">
|
<Table.Summary.Cell align="right">
|
||||||
<strong>
|
{Dinero(job.job_totals.parts.parts.prt_dsmk_total).toFormat()}
|
||||||
{Dinero(job.job_totals.parts.parts.total).toFormat()}
|
</Table.Summary.Cell>
|
||||||
</strong>
|
</Table.Summary.Row>
|
||||||
</Table.Summary.Cell>
|
<Table.Summary.Row>
|
||||||
</Table.Summary.Row>
|
<Table.Summary.Cell>
|
||||||
|
<strong>{t("jobs.labels.partstotal")}</strong>
|
||||||
|
</Table.Summary.Cell>
|
||||||
|
|
||||||
|
<Table.Summary.Cell align="right">
|
||||||
|
<strong>
|
||||||
|
{Dinero(job.job_totals.parts.parts.total).toFormat()}
|
||||||
|
</strong>
|
||||||
|
</Table.Summary.Cell>
|
||||||
|
</Table.Summary.Row>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ mutation UNVOID_JOB($jobId: uuid!) {
|
|||||||
}
|
}
|
||||||
insert_notes(objects: {jobid: $jobId, audit: true, created_by: "${
|
insert_notes(objects: {jobid: $jobId, audit: true, created_by: "${
|
||||||
currentUser.email
|
currentUser.email
|
||||||
}", text: "${t("jobs.labels.unvoidnote", { email: currentUser.email })}"}) {
|
}", text: "${t("jobs.labels.unvoidnote")}"}) {
|
||||||
returning {
|
returning {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,7 +104,10 @@ export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
|||||||
).data;
|
).data;
|
||||||
|
|
||||||
let existingVehicles;
|
let existingVehicles;
|
||||||
if (estData.data.available_jobs_by_pk.est_data.vehicle) {
|
if (
|
||||||
|
estData.data.available_jobs_by_pk.est_data.vehicle &&
|
||||||
|
estData.data.available_jobs_by_pk.est_data.vin
|
||||||
|
) {
|
||||||
//There's vehicle data, need to double check the VIN.
|
//There's vehicle data, need to double check the VIN.
|
||||||
existingVehicles = await client.query({
|
existingVehicles = await client.query({
|
||||||
query: SEARCH_VEHICLE_BY_VIN,
|
query: SEARCH_VEHICLE_BY_VIN,
|
||||||
@@ -124,10 +127,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
|||||||
data: {
|
data: {
|
||||||
created_by: currentUser.email,
|
created_by: currentUser.email,
|
||||||
audit: true,
|
audit: true,
|
||||||
text: t("jobs.labels.importnote", {
|
text: t("jobs.labels.importnote"),
|
||||||
date: moment().format("MM/DD/yyy"),
|
|
||||||
time: moment().format("hh:mm a"),
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
queued_for_parts: true,
|
queued_for_parts: true,
|
||||||
@@ -278,10 +278,7 @@ export function JobsAvailableContainer({ bodyshop, currentUser }) {
|
|||||||
jobid: selectedJob,
|
jobid: selectedJob,
|
||||||
created_by: currentUser.email,
|
created_by: currentUser.email,
|
||||||
audit: true,
|
audit: true,
|
||||||
text: t("jobs.labels.supplementnote", {
|
text: t("jobs.labels.supplementnote"),
|
||||||
date: moment().format("MM/DD/yyy"),
|
|
||||||
time: moment().format("hh:mm a"),
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,12 +26,6 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
|
|||||||
const { getFieldValue } = form;
|
const { getFieldValue } = form;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<JobsDetailRatesParts
|
|
||||||
jobRO={false}
|
|
||||||
expanded
|
|
||||||
required={selected && true}
|
|
||||||
form={form}
|
|
||||||
/>
|
|
||||||
<Collapse defaultActiveKey="insurance">
|
<Collapse defaultActiveKey="insurance">
|
||||||
<Collapse.Panel
|
<Collapse.Panel
|
||||||
key="insurance"
|
key="insurance"
|
||||||
@@ -57,7 +51,13 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
|
|||||||
<FormDatePicker />
|
<FormDatePicker />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm">
|
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm">
|
||||||
<Input />
|
<Select>
|
||||||
|
{bodyshop.md_ins_cos.map((s) => (
|
||||||
|
<Select.Option key={s.name} value={s.name}>
|
||||||
|
{s.name}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1">
|
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1">
|
||||||
<Input />
|
<Input />
|
||||||
@@ -312,6 +312,12 @@ export function JobsCreateJobsInfo({ bodyshop, form, selected }) {
|
|||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
<JobsDetailRatesParts
|
||||||
|
jobRO={false}
|
||||||
|
expanded
|
||||||
|
required={selected && true}
|
||||||
|
form={form}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,24 +83,12 @@ export default function JobsCreateVehicleInfoNewComponent() {
|
|||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("vehicles.fields.plate_st")}
|
label={t("vehicles.fields.plate_st")}
|
||||||
name={["vehicle", "data", "plate_st"]}
|
name={["vehicle", "data", "plate_st"]}
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: state.vehicle.new,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<Input disabled={!state.vehicle.new} />
|
<Input disabled={!state.vehicle.new} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("vehicles.fields.plate_no")}
|
label={t("vehicles.fields.plate_no")}
|
||||||
name={["vehicle", "data", "plate_no"]}
|
name={["vehicle", "data", "plate_no"]}
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: state.vehicle.new,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
>
|
||||||
<Input disabled={!state.vehicle.new} />
|
<Input disabled={!state.vehicle.new} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { DatePicker, Form, Tooltip } from "antd";
|
import { DatePicker, Form, Statistic, Tooltip } from "antd";
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -23,6 +23,10 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
|||||||
);
|
);
|
||||||
}, [job.status, bodyshop.md_ro_statuses.post_production_statuses]);
|
}, [job.status, bodyshop.md_ro_statuses.post_production_statuses]);
|
||||||
|
|
||||||
|
const calcRepairDays =
|
||||||
|
job.joblines.reduce((acc, val) => acc + val.mod_lb_hrs, 0) /
|
||||||
|
(bodyshop.target_touchtime === 0 ? 1 : bodyshop.target_touchtime);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FormRow header={t("jobs.forms.estdates")}>
|
<FormRow header={t("jobs.forms.estdates")}>
|
||||||
@@ -52,6 +56,17 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
|
|||||||
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
|
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
|
||||||
<DateTimePicker disabled={jobRO} />
|
<DateTimePicker disabled={jobRO} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Tooltip
|
||||||
|
title={t("jobs.labels.calc_repair_days_tt", {
|
||||||
|
target_touchtime: bodyshop.target_touchtime,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Statistic
|
||||||
|
value={calcRepairDays}
|
||||||
|
precision={1}
|
||||||
|
title={t("jobs.labels.calc_repair_days")}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
<FormRow header={t("jobs.forms.repairdates")}>
|
<FormRow header={t("jobs.forms.repairdates")}>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
|||||||
@@ -54,7 +54,13 @@ export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
|
|||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm">
|
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm">
|
||||||
<Input disabled={jobRO} />
|
<Select disabled={jobRO}>
|
||||||
|
{bodyshop.md_ins_cos.map((s) => (
|
||||||
|
<Select.Option key={s.name} value={s.name}>
|
||||||
|
{s.name}
|
||||||
|
</Select.Option>
|
||||||
|
))}
|
||||||
|
</Select>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1">
|
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1">
|
||||||
<Input disabled={jobRO} />
|
<Input disabled={jobRO} />
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { DownCircleFilled } from "@ant-design/icons";
|
import { DownCircleFilled } from "@ant-design/icons";
|
||||||
import { useApolloClient, useMutation } from "@apollo/client";
|
import { useApolloClient, useMutation } from "@apollo/client";
|
||||||
import { Button, Dropdown, Menu, notification, Popconfirm } from "antd";
|
import { Button, Dropdown, Menu, notification, Popconfirm } from "antd";
|
||||||
import moment from "moment";
|
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
@@ -385,10 +384,7 @@ export function JobsDetailHeaderActions({
|
|||||||
jobid: job.id,
|
jobid: job.id,
|
||||||
created_by: currentUser.email,
|
created_by: currentUser.email,
|
||||||
audit: true,
|
audit: true,
|
||||||
text: t("jobs.labels.voidnote", {
|
text: t("jobs.labels.voidnote"),
|
||||||
date: moment().format("MM/DD/yyy"),
|
|
||||||
time: moment().format("hh:mm a"),
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
import Axios from "axios";
|
import Axios from "axios";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
import {
|
import { INSERT_NEW_JOB, QUERY_JOB_FOR_DUPE } from "../../graphql/jobs.queries";
|
||||||
INSERT_NEW_JOB,
|
|
||||||
QUERY_ALL_JOB_FIELDS,
|
|
||||||
} from "../../graphql/jobs.queries";
|
|
||||||
|
|
||||||
export default async function DuplicateJob(
|
export default async function DuplicateJob(
|
||||||
apolloClient,
|
apolloClient,
|
||||||
@@ -18,33 +15,21 @@ export default async function DuplicateJob(
|
|||||||
const { defaultOpenStatus } = config;
|
const { defaultOpenStatus } = config;
|
||||||
//get a list of all fields on the job
|
//get a list of all fields on the job
|
||||||
const res = await apolloClient.query({
|
const res = await apolloClient.query({
|
||||||
query: QUERY_ALL_JOB_FIELDS,
|
query: QUERY_JOB_FOR_DUPE,
|
||||||
variables: { id: jobId },
|
variables: { id: jobId },
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("res", res);
|
console.log("res", res);
|
||||||
const { jobs_by_pk: existingJob } = res.data;
|
const { jobs_by_pk } = res.data;
|
||||||
|
const existingJob = _.cloneDeep(jobs_by_pk);
|
||||||
|
delete existingJob.__typename;
|
||||||
|
delete existingJob.id;
|
||||||
|
delete existingJob.createdat;
|
||||||
|
delete existingJob.updatedat;
|
||||||
|
|
||||||
const newJob = {
|
const newJob = {
|
||||||
date_estimated: new Date(),
|
...existingJob,
|
||||||
shopid: existingJob.shopid,
|
|
||||||
status: defaultOpenStatus,
|
status: defaultOpenStatus,
|
||||||
ownerid: existingJob.ownerid,
|
|
||||||
ownr_fn: existingJob.ownr_fn,
|
|
||||||
ownr_ln: existingJob.ownr_ln,
|
|
||||||
ownr_co_nm: existingJob.ownr_co_nm,
|
|
||||||
ownr_addr1: existingJob.ownr_addr1,
|
|
||||||
ownr_addr2: existingJob.ownr_addr2,
|
|
||||||
ownr_st: existingJob.ownr_st,
|
|
||||||
ownr_zip: existingJob.ownr_zip,
|
|
||||||
ownr_ctry: existingJob.ownr_ctry,
|
|
||||||
|
|
||||||
ownr_ph1: existingJob.ownr_ph1,
|
|
||||||
vehicleid: existingJob.vehicleid,
|
|
||||||
v_vin: existingJob.v_vin,
|
|
||||||
v_make_desc: existingJob.v_make_desc,
|
|
||||||
v_model_desc: existingJob.v_model_desc,
|
|
||||||
v_model_yr: existingJob.v_model_yr,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const _tempLines = _.cloneDeep(existingJob.joblines);
|
const _tempLines = _.cloneDeep(existingJob.joblines);
|
||||||
@@ -54,24 +39,20 @@ export default async function DuplicateJob(
|
|||||||
line.manual_line = true;
|
line.manual_line = true;
|
||||||
});
|
});
|
||||||
newJob.joblines = keepJobLines ? _tempLines : [];
|
newJob.joblines = keepJobLines ? _tempLines : [];
|
||||||
newJob.job_totals = (
|
|
||||||
await Axios.post("/job/totals", {
|
|
||||||
job: newJob,
|
|
||||||
})
|
|
||||||
).data;
|
|
||||||
|
|
||||||
delete newJob.joblines;
|
delete newJob.joblines;
|
||||||
newJob.joblines = keepJobLines ? { data: _tempLines } : null;
|
newJob.joblines = keepJobLines ? { data: _tempLines } : null;
|
||||||
|
|
||||||
apolloClient
|
const res2 = await apolloClient.mutate({
|
||||||
.mutate({
|
mutation: INSERT_NEW_JOB,
|
||||||
mutation: INSERT_NEW_JOB,
|
variables: { job: [newJob] },
|
||||||
variables: { job: [newJob] },
|
});
|
||||||
})
|
await Axios.post("/job/totalsssu", {
|
||||||
.then((res2) => {
|
id: res2.data.insert_jobs.returning[0].id,
|
||||||
if (completionCallback)
|
});
|
||||||
completionCallback(res2.data.insert_jobs.returning[0].id);
|
|
||||||
});
|
if (completionCallback)
|
||||||
|
completionCallback(res2.data.insert_jobs.returning[0].id);
|
||||||
|
|
||||||
//insert the new job. call the callback with the returned ID when done.
|
//insert the new job. call the callback with the returned ID when done.
|
||||||
|
|
||||||
|
|||||||
@@ -151,17 +151,21 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
<Card
|
<Card
|
||||||
style={{ height: "100%" }}
|
style={{ height: "100%" }}
|
||||||
title={
|
title={
|
||||||
<Link
|
job.vehicle ? (
|
||||||
to={
|
<Link
|
||||||
disabled
|
to={
|
||||||
? "#"
|
disabled
|
||||||
: job.vehicle && `/manage/vehicles/${job.vehicle.id}`
|
? "#"
|
||||||
}
|
: job.vehicle && `/manage/vehicles/${job.vehicle.id}`
|
||||||
>
|
}
|
||||||
{`${job.v_model_yr || ""} ${job.v_color || ""}
|
>
|
||||||
|
{`${job.v_model_yr || ""} ${job.v_color || ""}
|
||||||
${job.v_make_desc || ""}
|
${job.v_make_desc || ""}
|
||||||
${job.v_model_desc || ""}`}
|
${job.v_model_desc || ""}`}
|
||||||
</Link>
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span></span>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -36,8 +36,11 @@ export function JobsDetailRates({ jobRO, form, job }) {
|
|||||||
<CurrencyInput
|
<CurrencyInput
|
||||||
disabled={jobRO}
|
disabled={jobRO}
|
||||||
max={
|
max={
|
||||||
((job.job_totals && job.job_totals.totals.federal_tax.amount) ||
|
Math.round(
|
||||||
0) / 100
|
(job.job_totals &&
|
||||||
|
job.job_totals.totals.federal_tax.amount) ||
|
||||||
|
0
|
||||||
|
) / 100
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { DetermineFileType } from "../documents-upload/documents-upload.utility";
|
||||||
|
|
||||||
|
export const GenerateSrcUrl = (value) => {
|
||||||
|
let extension = value.extension;
|
||||||
|
if (extension && extension.toLowerCase().includes("heic")) extension = "jpg";
|
||||||
|
|
||||||
|
return `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType(
|
||||||
|
value.type
|
||||||
|
)}/upload/${value.key}${extension ? `.${extension}` : ""}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GenerateThumbUrl = (value) =>
|
||||||
|
`${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${DetermineFileType(
|
||||||
|
value.type
|
||||||
|
)}/upload/${process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS}/${
|
||||||
|
value.key
|
||||||
|
}`;
|
||||||
@@ -1,30 +1,87 @@
|
|||||||
import { Button } from "antd";
|
import { Button, Space } from "antd";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import cleanAxios from "../../utils/CleanAxios";
|
||||||
|
import formatBytes from "../../utils/formatbytes";
|
||||||
|
|
||||||
export default function JobsDocumentsDownloadButton({ galleryImages }) {
|
export default function JobsDocumentsDownloadButton({
|
||||||
|
galleryImages,
|
||||||
|
identifier,
|
||||||
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [download, setDownload] = useState(null);
|
||||||
const imagesToDownload = [
|
const imagesToDownload = [
|
||||||
...galleryImages.images.filter((image) => image.isSelected),
|
...galleryImages.images.filter((image) => image.isSelected),
|
||||||
...galleryImages.other.filter((image) => image.isSelected),
|
// ...galleryImages.other.filter((image) => image.isSelected),
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleDownload = () => {
|
const handleDownload = () => {
|
||||||
logImEXEvent("jobs_documents_download");
|
logImEXEvent("jobs_documents_download");
|
||||||
|
|
||||||
axios
|
axios
|
||||||
.post("/media/download", {
|
.post("/media/download", {
|
||||||
ids: imagesToDownload.map((_) => _.key),
|
ids: imagesToDownload.map((_) => _.key),
|
||||||
})
|
})
|
||||||
.then((r) => {
|
.then((r) => {
|
||||||
window.open(r.data);
|
// window.open(r.data);
|
||||||
|
downloadAs(
|
||||||
|
r.data,
|
||||||
|
`${identifier || "documents"}.zip`,
|
||||||
|
(progressEvent) => {
|
||||||
|
setDownload((currentDownloadState) => {
|
||||||
|
return {
|
||||||
|
downloaded: progressEvent.loaded || 0,
|
||||||
|
speed:
|
||||||
|
(progressEvent.loaded || 0) -
|
||||||
|
((currentDownloadState && currentDownloadState.downloaded) ||
|
||||||
|
0),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
() => setDownload(null)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button disabled={imagesToDownload.length < 1} onClick={handleDownload}>
|
<>
|
||||||
{t("documents.actions.download")}
|
<Button
|
||||||
</Button>
|
loading={!!download}
|
||||||
|
disabled={imagesToDownload.length < 1}
|
||||||
|
onClick={handleDownload}
|
||||||
|
>
|
||||||
|
<Space>
|
||||||
|
<span>{t("documents.actions.download")}</span>
|
||||||
|
{download && (
|
||||||
|
<span>{`(${formatBytes(download.downloaded)} @ ${formatBytes(
|
||||||
|
download.speed
|
||||||
|
)} / second)`}</span>
|
||||||
|
)}
|
||||||
|
</Space>
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const downloadAs = (url, name, onDownloadProgress, onCompleted) => {
|
||||||
|
cleanAxios
|
||||||
|
.get(url, {
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/octet-stream",
|
||||||
|
},
|
||||||
|
responseType: "blob",
|
||||||
|
onDownloadProgress: onDownloadProgress,
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
onCompleted && onCompleted();
|
||||||
|
const a = document.createElement("a");
|
||||||
|
const url = window.URL.createObjectURL(response.data);
|
||||||
|
a.href = url;
|
||||||
|
a.download = name;
|
||||||
|
a.click();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("error", err);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { FileExcelFilled } from "@ant-design/icons";
|
import { FileExcelFilled, EditFilled, SyncOutlined } from "@ant-design/icons";
|
||||||
import { Card, Col, Row, Space } from "antd";
|
import { Card, Col, Row, Space, Button } from "antd";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import Gallery from "react-grid-gallery";
|
import Gallery from "react-grid-gallery";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import DocumentsUploadComponent from "../documents-upload/documents-upload.component";
|
import DocumentsUploadComponent from "../documents-upload/documents-upload.component";
|
||||||
import { DetermineFileType } from "../documents-upload/documents-upload.utility";
|
import { DetermineFileType } from "../documents-upload/documents-upload.utility";
|
||||||
|
import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents.utility";
|
||||||
import JobsDocumentsDownloadButton from "./jobs-document-gallery.download.component";
|
import JobsDocumentsDownloadButton from "./jobs-document-gallery.download.component";
|
||||||
import JobsDocumentsGalleryReassign from "./jobs-document-gallery.reassign.component";
|
import JobsDocumentsGalleryReassign from "./jobs-document-gallery.reassign.component";
|
||||||
import JobsDocumentsDeleteButton from "./jobs-documents-gallery.delete.component";
|
import JobsDocumentsDeleteButton from "./jobs-documents-gallery.delete.component";
|
||||||
@@ -17,11 +18,30 @@ function JobsDocumentsComponent({
|
|||||||
billId,
|
billId,
|
||||||
billsCallback,
|
billsCallback,
|
||||||
totalSize,
|
totalSize,
|
||||||
bodyshop,
|
downloadIdentifier,
|
||||||
ignoreSizeLimit,
|
ignoreSizeLimit,
|
||||||
}) {
|
}) {
|
||||||
const [galleryImages, setgalleryImages] = useState({ images: [], other: [] });
|
const [galleryImages, setgalleryImages] = useState({ images: [], other: [] });
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [index, setIndex] = useState(0);
|
||||||
|
|
||||||
|
const onCurrentImageChange = (index) => {
|
||||||
|
setIndex(index);
|
||||||
|
};
|
||||||
|
|
||||||
|
// useEffect(() => {
|
||||||
|
// console.log("Added event listening for reteching.");
|
||||||
|
// window.addEventListener("storage", (ev) => {
|
||||||
|
// if (ev.key === "refetch" && ev.newValue === true) {
|
||||||
|
// refetch && refetch();
|
||||||
|
// localStorage.setItem("refetch", false);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return () => {
|
||||||
|
// window.removeEventListener("storage");
|
||||||
|
// };
|
||||||
|
// }, [refetch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let documents = data.reduce(
|
let documents = data.reduce(
|
||||||
@@ -29,19 +49,14 @@ function JobsDocumentsComponent({
|
|||||||
const fileType = DetermineFileType(value.type);
|
const fileType = DetermineFileType(value.type);
|
||||||
if (value.type.startsWith("image")) {
|
if (value.type.startsWith("image")) {
|
||||||
acc.images.push({
|
acc.images.push({
|
||||||
src: `${
|
src: GenerateSrcUrl(value),
|
||||||
process.env.REACT_APP_CLOUDINARY_ENDPOINT
|
thumbnail: GenerateThumbUrl(value),
|
||||||
}/${DetermineFileType(value.type)}/upload/${value.key}`,
|
|
||||||
thumbnail: `${
|
|
||||||
process.env.REACT_APP_CLOUDINARY_ENDPOINT
|
|
||||||
}/${DetermineFileType(value.type)}/upload/${
|
|
||||||
process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS
|
|
||||||
}/${value.key}`,
|
|
||||||
thumbnailHeight: 225,
|
thumbnailHeight: 225,
|
||||||
thumbnailWidth: 225,
|
thumbnailWidth: 225,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
key: value.key,
|
key: value.key,
|
||||||
extension: value.extension,
|
extension: value.extension,
|
||||||
|
|
||||||
id: value.id,
|
id: value.id,
|
||||||
type: value.type,
|
type: value.type,
|
||||||
size: value.size,
|
size: value.size,
|
||||||
@@ -50,24 +65,18 @@ function JobsDocumentsComponent({
|
|||||||
} else {
|
} else {
|
||||||
let thumb;
|
let thumb;
|
||||||
switch (fileType) {
|
switch (fileType) {
|
||||||
case "video":
|
|
||||||
thumb = `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${fileType}/upload/c_fill,f_png,h_250,w_250/${value.key}`;
|
|
||||||
break;
|
|
||||||
case "raw":
|
case "raw":
|
||||||
thumb = `${window.location.origin}/file.png`;
|
thumb = `${window.location.origin}/file.png`;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
thumb = `${process.env.REACT_APP_CLOUDINARY_ENDPOINT}/${fileType}/upload/${process.env.REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS}/${value.key}`;
|
thumb = GenerateThumbUrl(value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileName = value.key.split("/").pop();
|
const fileName = value.key.split("/").pop();
|
||||||
acc.other.push({
|
acc.other.push({
|
||||||
src: `${
|
source: GenerateSrcUrl(value),
|
||||||
process.env.REACT_APP_CLOUDINARY_ENDPOINT
|
src: "",
|
||||||
}/${fileType}/upload/${fileType === "video" ? "q_auto/" : ""}${
|
|
||||||
value.key
|
|
||||||
}${fileType === "raw" ? `.${value.extension}` : ""}`,
|
|
||||||
thumbnail: thumb,
|
thumbnail: thumb,
|
||||||
tags: [
|
tags: [
|
||||||
{
|
{
|
||||||
@@ -93,6 +102,7 @@ function JobsDocumentsComponent({
|
|||||||
thumbnailHeight: 225,
|
thumbnailHeight: 225,
|
||||||
thumbnailWidth: 225,
|
thumbnailWidth: 225,
|
||||||
isSelected: false,
|
isSelected: false,
|
||||||
|
|
||||||
extension: value.extension,
|
extension: value.extension,
|
||||||
key: value.key,
|
key: value.key,
|
||||||
id: value.id,
|
id: value.id,
|
||||||
@@ -113,11 +123,17 @@ function JobsDocumentsComponent({
|
|||||||
<Row gutter={[16, 16]}>
|
<Row gutter={[16, 16]}>
|
||||||
<Col span={24}>
|
<Col span={24}>
|
||||||
<Space wrap>
|
<Space wrap>
|
||||||
|
<Button onClick={() => refetch && refetch()}>
|
||||||
|
<SyncOutlined />
|
||||||
|
</Button>
|
||||||
<JobsDocumentsGallerySelectAllComponent
|
<JobsDocumentsGallerySelectAllComponent
|
||||||
galleryImages={galleryImages}
|
galleryImages={galleryImages}
|
||||||
setGalleryImages={setgalleryImages}
|
setGalleryImages={setgalleryImages}
|
||||||
/>
|
/>
|
||||||
<JobsDocumentsDownloadButton galleryImages={galleryImages} />
|
<JobsDocumentsDownloadButton
|
||||||
|
galleryImages={galleryImages}
|
||||||
|
identifier={downloadIdentifier}
|
||||||
|
/>
|
||||||
<JobsDocumentsDeleteButton
|
<JobsDocumentsDeleteButton
|
||||||
galleryImages={galleryImages}
|
galleryImages={galleryImages}
|
||||||
deletionCallback={billsCallback || refetch}
|
deletionCallback={billsCallback || refetch}
|
||||||
@@ -144,6 +160,26 @@ function JobsDocumentsComponent({
|
|||||||
<Gallery
|
<Gallery
|
||||||
images={galleryImages.images}
|
images={galleryImages.images}
|
||||||
backdropClosesModal={true}
|
backdropClosesModal={true}
|
||||||
|
currentImageWillChange={onCurrentImageChange}
|
||||||
|
customControls={[
|
||||||
|
<Button
|
||||||
|
style={{
|
||||||
|
float: "right",
|
||||||
|
|
||||||
|
zIndex: "5",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
const newWindow = window.open(
|
||||||
|
`${window.location.protocol}//${window.location.host}/edit?documentId=${galleryImages.images[index].id}`,
|
||||||
|
"_blank",
|
||||||
|
"noopener,noreferrer"
|
||||||
|
);
|
||||||
|
if (newWindow) newWindow.opener = null;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<EditFilled style={{}} />
|
||||||
|
</Button>,
|
||||||
|
]}
|
||||||
onClickImage={(props) => {
|
onClickImage={(props) => {
|
||||||
window.open(
|
window.open(
|
||||||
props.target.src,
|
props.target.src,
|
||||||
@@ -173,11 +209,12 @@ function JobsDocumentsComponent({
|
|||||||
backgroundImage: <FileExcelFilled />,
|
backgroundImage: <FileExcelFilled />,
|
||||||
height: "100%",
|
height: "100%",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
|
cursor: "pointer",
|
||||||
};
|
};
|
||||||
}}
|
}}
|
||||||
onClickThumbnail={(index) => {
|
onClickThumbnail={(index) => {
|
||||||
window.open(
|
window.open(
|
||||||
galleryImages.other[index].src,
|
galleryImages.other[index].source,
|
||||||
"_blank",
|
"_blank",
|
||||||
"toolbar=0,location=0,menubar=0"
|
"toolbar=0,location=0,menubar=0"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export default function JobsDocumentsContainer({
|
|||||||
return (
|
return (
|
||||||
<JobDocuments
|
<JobDocuments
|
||||||
data={(data && data.documents) || documentsList || []}
|
data={(data && data.documents) || documentsList || []}
|
||||||
|
downloadIdentifier={data && data.jobs_by_pk.ro_number}
|
||||||
totalSize={data && data.documents_aggregate.aggregate.sum.size}
|
totalSize={data && data.documents_aggregate.aggregate.sum.size}
|
||||||
billId={billId}
|
billId={billId}
|
||||||
jobId={jobId}
|
jobId={jobId}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { Link, useHistory, useLocation } from "react-router-dom";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||||
import { alphaSort } from "../../utils/sorters";
|
|
||||||
import StartChatButton from "../chat-open-button/chat-open-button.component";
|
import StartChatButton from "../chat-open-button/chat-open-button.component";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
@@ -32,7 +31,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
dataIndex: "ro_number",
|
dataIndex: "ro_number",
|
||||||
key: "ro_number",
|
key: "ro_number",
|
||||||
width: "8%",
|
width: "8%",
|
||||||
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
|
sorter: true, //(a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||||
sortOrder: sortcolumn === "ro_number" && sortorder,
|
sortOrder: sortcolumn === "ro_number" && sortorder,
|
||||||
|
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
@@ -44,12 +43,12 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.owner"),
|
title: t("jobs.fields.owner"),
|
||||||
dataIndex: "owner",
|
dataIndex: "ownr_ln",
|
||||||
key: "owner",
|
key: "ownr_ln",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
// sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
//sorter: true, // (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
|
||||||
width: "25%",
|
width: "25%",
|
||||||
// sortOrder: sortcolumn === "owner" && sortorder,
|
//sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.owner ? (
|
return record.owner ? (
|
||||||
<Link to={"/manage/owners/" + record.owner.id}>
|
<Link to={"/manage/owners/" + record.owner.id}>
|
||||||
@@ -80,7 +79,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
key: "status",
|
key: "status",
|
||||||
width: "10%",
|
width: "10%",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: (a, b) => alphaSort(a.status, b.status),
|
sorter: true, // (a, b) => alphaSort(a.status, b.status),
|
||||||
sortOrder: sortcolumn === "status" && sortorder,
|
sortOrder: sortcolumn === "status" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.status || t("general.labels.na");
|
return record.status || t("general.labels.na");
|
||||||
@@ -117,7 +116,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
key: "plate_no",
|
key: "plate_no",
|
||||||
width: "8%",
|
width: "8%",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: (a, b) => alphaSort(a.plate_no, b.plate_no),
|
sorter: true, //(a, b) => alphaSort(a.plate_no, b.plate_no),
|
||||||
sortOrder: sortcolumn === "plate_no" && sortorder,
|
sortOrder: sortcolumn === "plate_no" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.plate_no ? record.plate_no : "";
|
return record.plate_no ? record.plate_no : "";
|
||||||
@@ -129,7 +128,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
key: "clm_no",
|
key: "clm_no",
|
||||||
width: "12%",
|
width: "12%",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
|
sorter: true, //(a, b) => alphaSort(a.clm_no, b.clm_no),
|
||||||
sortOrder: sortcolumn === "clm_no" && sortorder,
|
sortOrder: sortcolumn === "clm_no" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.clm_no ? (
|
return record.clm_no ? (
|
||||||
@@ -150,7 +149,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
dataIndex: "clm_total",
|
dataIndex: "clm_total",
|
||||||
key: "clm_total",
|
key: "clm_total",
|
||||||
width: "10%",
|
width: "10%",
|
||||||
sorter: (a, b) => a.clm_total - b.clm_total,
|
sorter: true, //(a, b) => a.clm_total - b.clm_total,
|
||||||
sortOrder: sortcolumn === "clm_total" && sortorder,
|
sortOrder: sortcolumn === "clm_total" && sortorder,
|
||||||
render: (text, record) => {
|
render: (text, record) => {
|
||||||
return record.clm_total ? (
|
return record.clm_total ? (
|
||||||
@@ -173,7 +172,7 @@ export function JobsList({ bodyshop, refetch, loading, jobs, total }) {
|
|||||||
|
|
||||||
const handleTableChange = (pagination, filters, sorter) => {
|
const handleTableChange = (pagination, filters, sorter) => {
|
||||||
search.page = pagination.current;
|
search.page = pagination.current;
|
||||||
search.sortcolumn = sorter.columnKey;
|
search.sortcolumn = sorter.column && sorter.column.key;
|
||||||
search.sortorder = sorter.order;
|
search.sortorder = sorter.order;
|
||||||
if (filters.status) {
|
if (filters.status) {
|
||||||
search.statusFilters = JSON.stringify(_.flattenDeep(filters.status));
|
search.statusFilters = JSON.stringify(_.flattenDeep(filters.status));
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ export function JobNotesComponent({
|
|||||||
dataIndex: "text",
|
dataIndex: "text",
|
||||||
key: "text",
|
key: "text",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
|
render: (text, record) => (
|
||||||
|
<span style={{ whiteSpace: "pre-line" }}>{text}</span>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export function LaborAllocationsTable({
|
|||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<strong
|
<strong
|
||||||
style={{
|
style={{
|
||||||
color: record.difference > 0 ? "green" : "red",
|
color: record.difference >= 0 ? "green" : "red",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{record.difference}
|
{record.difference}
|
||||||
|
|||||||
@@ -31,55 +31,19 @@ export default function OwnerDetailFormComponent({ form, loading }) {
|
|||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
|
||||||
<LayoutFormRow header={t("owners.forms.address")}>
|
<LayoutFormRow header={t("owners.forms.address")}>
|
||||||
<Form.Item
|
<Form.Item label={t("owners.fields.ownr_addr1")} name="ownr_addr1">
|
||||||
label={t("owners.fields.ownr_addr1")}
|
|
||||||
name="ownr_addr1"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("owners.fields.ownr_addr2")} name="ownr_addr2">
|
<Form.Item label={t("owners.fields.ownr_addr2")} name="ownr_addr2">
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item label={t("owners.fields.ownr_city")} name="ownr_city">
|
||||||
label={t("owners.fields.ownr_city")}
|
|
||||||
name="ownr_city"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item label={t("owners.fields.ownr_st")} name="ownr_st">
|
||||||
label={t("owners.fields.ownr_st")}
|
|
||||||
name="ownr_st"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item label={t("owners.fields.ownr_zip")} name="ownr_zip">
|
||||||
label={t("owners.fields.ownr_zip")}
|
|
||||||
name="ownr_zip"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("owners.fields.ownr_ctry")} name="ownr_ctry">
|
<Form.Item label={t("owners.fields.ownr_ctry")} name="ownr_ctry">
|
||||||
|
|||||||
@@ -237,6 +237,11 @@ export function PartsOrderListTableComponent({
|
|||||||
<DateFormatter>{record.deliver_by}</DateFormatter>
|
<DateFormatter>{record.deliver_by}</DateFormatter>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("parts_orders.fields.orderedby"),
|
||||||
|
dataIndex: "orderedby",
|
||||||
|
key: "orderedby",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("general.labels.actions"),
|
title: t("general.labels.actions"),
|
||||||
dataIndex: "actions",
|
dataIndex: "actions",
|
||||||
@@ -336,6 +341,7 @@ export function PartsOrderListTableComponent({
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
title: t("general.labels.actions"),
|
title: t("general.labels.actions"),
|
||||||
dataIndex: "actions",
|
dataIndex: "actions",
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ export default function PartsOrderModalComponent({
|
|||||||
<Form.Item required={false} key={field.key}>
|
<Form.Item required={false} key={field.key}>
|
||||||
<LayoutFormRow grow noDivider>
|
<LayoutFormRow grow noDivider>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
span={8}
|
||||||
label={t("parts_orders.fields.line_desc")}
|
label={t("parts_orders.fields.line_desc")}
|
||||||
key={`${index}line_desc`}
|
key={`${index}line_desc`}
|
||||||
name={[field.name, "line_desc"]}
|
name={[field.name, "line_desc"]}
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ export function PartsOrderModalContainer({
|
|||||||
po: [
|
po: [
|
||||||
{
|
{
|
||||||
...values,
|
...values,
|
||||||
|
orderedby: currentUser.email,
|
||||||
jobid: jobId,
|
jobid: jobId,
|
||||||
user_email: currentUser.email,
|
user_email: currentUser.email,
|
||||||
return: isReturn,
|
return: isReturn,
|
||||||
|
|||||||
@@ -82,7 +82,31 @@ export function PhonebookFormComponent({
|
|||||||
<Form.Item label={t("phonebook.fields.lastname")} name="lastname">
|
<Form.Item label={t("phonebook.fields.lastname")} name="lastname">
|
||||||
<Input disabled={hasNoAccess} />
|
<Input disabled={hasNoAccess} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("phonebook.fields.company")} name="company">
|
<Form.Item
|
||||||
|
label={t("phonebook.fields.company")}
|
||||||
|
name="company"
|
||||||
|
dependencies={["firstname", "lastname"]}
|
||||||
|
rules={[
|
||||||
|
({ getFieldsValue }) => ({
|
||||||
|
validator(rule, value) {
|
||||||
|
const { firstname, lastname, company } = getFieldsValue([
|
||||||
|
"firstname",
|
||||||
|
"lastname",
|
||||||
|
"company",
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (
|
||||||
|
(firstname && firstname.trim() !== "") ||
|
||||||
|
(lastname && lastname.trim() !== "") ||
|
||||||
|
(company && company.trim() !== "")
|
||||||
|
) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(t("phonebook.labels.onenamerequired"));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
>
|
||||||
<Input disabled={hasNoAccess} />
|
<Input disabled={hasNoAccess} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
|||||||
@@ -225,8 +225,10 @@ const r = ({ technician, state }) => {
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "totalhours" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "totalhours" && state.sortedInfo.order,
|
||||||
render: (text, record) =>
|
render: (text, record) =>
|
||||||
record.labhrs.aggregate.sum.mod_lb_hrs +
|
(
|
||||||
record.larhrs.aggregate.sum.mod_lb_hrs,
|
record.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
|
record.larhrs.aggregate.sum.mod_lb_hrs
|
||||||
|
).toFixed(1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: i18n.t("production.labels.alert"),
|
title: i18n.t("production.labels.alert"),
|
||||||
|
|||||||
@@ -1,6 +1,20 @@
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import React, { useMemo } from "react";
|
import React, { useMemo } from "react";
|
||||||
export default function ProductionlistColumnTouchTime({ job }) {
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
|
});
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(ProductionlistColumnTouchTime);
|
||||||
|
|
||||||
|
export function ProductionlistColumnTouchTime({ bodyshop, job }) {
|
||||||
let ct = useMemo(() => {
|
let ct = useMemo(() => {
|
||||||
if (!!job.actual_in) {
|
if (!!job.actual_in) {
|
||||||
const totalHrs =
|
const totalHrs =
|
||||||
@@ -18,5 +32,7 @@ export default function ProductionlistColumnTouchTime({ job }) {
|
|||||||
return 0;
|
return 0;
|
||||||
}, [job]);
|
}, [job]);
|
||||||
|
|
||||||
return <span>{ct}</span>;
|
const underTarget = ct < bodyshop.target_touchtime;
|
||||||
|
|
||||||
|
return <span style={{ color: underTarget && "tomato" }}>{ct}</span>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ 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 CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||||
export default function ShopInfoGeneral({ form }) {
|
export default function ShopInfoGeneral({ form }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
@@ -425,6 +425,18 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<InputNumber min={0} max={1} precision={2} />
|
<InputNumber min={0} max={1} precision={2} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.jc_hourly_rates.mapa")}
|
||||||
|
name={["jc_hourly_rates", "mapa"]}
|
||||||
|
>
|
||||||
|
<CurrencyInput />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.fields.jc_hourly_rates.mash")}
|
||||||
|
name={["jc_hourly_rates", "mash"]}
|
||||||
|
>
|
||||||
|
<CurrencyInput />
|
||||||
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
<LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}>
|
<LayoutFormRow grow header={t("bodyshop.labels.messagingpresets")}>
|
||||||
<Form.List name={["md_messaging_presets"]}>
|
<Form.List name={["md_messaging_presets"]}>
|
||||||
|
|||||||
@@ -76,28 +76,10 @@ export default function VehicleDetailFormComponent({ form, loading }) {
|
|||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
|
||||||
<LayoutFormRow header={t("vehicles.forms.registration")}>
|
<LayoutFormRow header={t("vehicles.forms.registration")}>
|
||||||
<Form.Item
|
<Form.Item label={t("vehicles.fields.plate_st")} name="plate_st">
|
||||||
label={t("vehicles.fields.plate_st")}
|
|
||||||
name="plate_st"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item label={t("vehicles.fields.plate_no")} name="plate_no">
|
||||||
label={t("vehicles.fields.plate_no")}
|
|
||||||
name="plate_no"
|
|
||||||
rules={[
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
//message: t("general.validation.required"),
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input />
|
<Input />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</LayoutFormRow>
|
</LayoutFormRow>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ function VehicleDetailFormContainer({ vehicle, refetch }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={t("menus.header.owners")}
|
title={t("menus.header.vehicles")}
|
||||||
extra={
|
extra={
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ export const INSERT_APPOINTMENT = gql`
|
|||||||
title
|
title
|
||||||
isintake
|
isintake
|
||||||
block
|
block
|
||||||
|
color
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
update_jobs(
|
update_jobs(
|
||||||
@@ -110,6 +111,7 @@ export const QUERY_APPOINTMENT_BY_DATE = gql`
|
|||||||
title
|
title
|
||||||
isintake
|
isintake
|
||||||
block
|
block
|
||||||
|
color
|
||||||
job {
|
job {
|
||||||
alt_transport
|
alt_transport
|
||||||
ro_number
|
ro_number
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export const QUERY_BILLS_BY_JOBID = gql`
|
|||||||
order_date
|
order_date
|
||||||
deliver_by
|
deliver_by
|
||||||
return
|
return
|
||||||
|
orderedby
|
||||||
parts_order_lines {
|
parts_order_lines {
|
||||||
id
|
id
|
||||||
act_price
|
act_price
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export const QUERY_BODYSHOP = gql`
|
|||||||
md_ccc_rates
|
md_ccc_rates
|
||||||
enforce_referral
|
enforce_referral
|
||||||
website
|
website
|
||||||
|
jc_hourly_rates
|
||||||
employees {
|
employees {
|
||||||
id
|
id
|
||||||
active
|
active
|
||||||
@@ -171,6 +172,7 @@ export const UPDATE_SHOP = gql`
|
|||||||
md_ccc_rates
|
md_ccc_rates
|
||||||
enforce_referral
|
enforce_referral
|
||||||
website
|
website
|
||||||
|
jc_hourly_rates
|
||||||
employees {
|
employees {
|
||||||
id
|
id
|
||||||
first_name
|
first_name
|
||||||
@@ -197,6 +199,28 @@ export const QUERY_INTAKE_CHECKLIST = gql`
|
|||||||
scheduled_delivery
|
scheduled_delivery
|
||||||
intakechecklist
|
intakechecklist
|
||||||
status
|
status
|
||||||
|
labhrs: joblines_aggregate(
|
||||||
|
where: {
|
||||||
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
aggregate {
|
||||||
|
sum {
|
||||||
|
mod_lb_hrs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
larhrs: joblines_aggregate(
|
||||||
|
where: {
|
||||||
|
_and: [{ mod_lbr_ty: { _eq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
aggregate {
|
||||||
|
sum {
|
||||||
|
mod_lb_hrs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -1,7 +1,26 @@
|
|||||||
import { gql } from "@apollo/client";
|
import { gql } from "@apollo/client";
|
||||||
|
|
||||||
|
export const GET_DOCUMENT_BY_PK = gql`
|
||||||
|
query GET_DOCUMENT_BY_PK($documentId: uuid!) {
|
||||||
|
documents_by_pk(id: $documentId) {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
key
|
||||||
|
type
|
||||||
|
size
|
||||||
|
takenat
|
||||||
|
extension
|
||||||
|
jobid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const GET_DOCUMENTS_BY_JOB = gql`
|
export const GET_DOCUMENTS_BY_JOB = gql`
|
||||||
query GET_DOCUMENTS_BY_JOB($jobId: uuid!) {
|
query GET_DOCUMENTS_BY_JOB($jobId: uuid!) {
|
||||||
|
jobs_by_pk(id: $jobId) {
|
||||||
|
id
|
||||||
|
ro_number
|
||||||
|
}
|
||||||
documents_aggregate(where: { jobid: { _eq: $jobId } }) {
|
documents_aggregate(where: { jobid: { _eq: $jobId } }) {
|
||||||
aggregate {
|
aggregate {
|
||||||
sum {
|
sum {
|
||||||
@@ -9,15 +28,14 @@ export const GET_DOCUMENTS_BY_JOB = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
documents(
|
documents(order_by: { takenat: desc }, where: { jobid: { _eq: $jobId } }) {
|
||||||
order_by: { updated_at: desc }
|
|
||||||
where: { jobid: { _eq: $jobId } }
|
|
||||||
) {
|
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
key
|
key
|
||||||
type
|
type
|
||||||
size
|
size
|
||||||
|
takenat
|
||||||
|
extension
|
||||||
bill {
|
bill {
|
||||||
id
|
id
|
||||||
invoice_number
|
invoice_number
|
||||||
@@ -51,6 +69,7 @@ export const INSERT_NEW_DOCUMENT = gql`
|
|||||||
name
|
name
|
||||||
key
|
key
|
||||||
size
|
size
|
||||||
|
takenat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +89,7 @@ export const QUERY_TEMPORARY_DOCS = gql`
|
|||||||
query QUERY_TEMPORARY_DOCS {
|
query QUERY_TEMPORARY_DOCS {
|
||||||
documents(
|
documents(
|
||||||
where: { jobid: { _is_null: true } }
|
where: { jobid: { _is_null: true } }
|
||||||
order_by: { updated_at: desc }
|
order_by: { takenat: desc }
|
||||||
) {
|
) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
@@ -78,6 +97,7 @@ export const QUERY_TEMPORARY_DOCS = gql`
|
|||||||
type
|
type
|
||||||
extension
|
extension
|
||||||
size
|
size
|
||||||
|
takenat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -94,6 +114,7 @@ export const UPDATE_DOCUMENT = gql`
|
|||||||
type
|
type
|
||||||
key
|
key
|
||||||
size
|
size
|
||||||
|
takenat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -528,6 +528,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
tax_part
|
tax_part
|
||||||
db_ref
|
db_ref
|
||||||
manual_line
|
manual_line
|
||||||
|
prt_dsmk_p
|
||||||
billlines(limit: 1, order_by: { bill: { date: desc } }) {
|
billlines(limit: 1, order_by: { bill: { date: desc } }) {
|
||||||
id
|
id
|
||||||
quantity
|
quantity
|
||||||
@@ -564,6 +565,7 @@ export const GET_JOB_BY_PK = gql`
|
|||||||
stripeid
|
stripeid
|
||||||
transactionid
|
transactionid
|
||||||
memo
|
memo
|
||||||
|
date
|
||||||
}
|
}
|
||||||
cccontracts {
|
cccontracts {
|
||||||
id
|
id
|
||||||
@@ -1055,6 +1057,236 @@ export const SEARCH_FOR_JOBS = gql`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const QUERY_JOB_FOR_DUPE = gql`
|
||||||
|
query QUERY_JOB_FOR_DUPE($id: uuid!) {
|
||||||
|
jobs_by_pk(id: $id) {
|
||||||
|
id
|
||||||
|
agt_addr1
|
||||||
|
agt_addr2
|
||||||
|
agt_city
|
||||||
|
agt_co_id
|
||||||
|
agt_co_nm
|
||||||
|
agt_ct_fn
|
||||||
|
agt_ct_ln
|
||||||
|
agt_ct_ph
|
||||||
|
agt_ct_phx
|
||||||
|
agt_ctry
|
||||||
|
agt_ea
|
||||||
|
agt_faxx
|
||||||
|
agt_fax
|
||||||
|
agt_lic_no
|
||||||
|
agt_ph1
|
||||||
|
agt_ph1x
|
||||||
|
agt_ph2
|
||||||
|
agt_zip
|
||||||
|
agt_st
|
||||||
|
agt_ph2x
|
||||||
|
area_of_damage
|
||||||
|
cat_no
|
||||||
|
cieca_stl
|
||||||
|
cieca_ttl
|
||||||
|
clm_addr1
|
||||||
|
clm_addr2
|
||||||
|
clm_city
|
||||||
|
clm_ct_fn
|
||||||
|
clm_ct_ln
|
||||||
|
clm_ct_ph
|
||||||
|
clm_ct_phx
|
||||||
|
clm_ctry
|
||||||
|
clm_ea
|
||||||
|
clm_fax
|
||||||
|
clm_faxx
|
||||||
|
clm_ofc_id
|
||||||
|
clm_ofc_nm
|
||||||
|
clm_ph1
|
||||||
|
clm_ph1x
|
||||||
|
clm_ph2
|
||||||
|
clm_ph2x
|
||||||
|
clm_st
|
||||||
|
clm_title
|
||||||
|
clm_total
|
||||||
|
clm_zip
|
||||||
|
cust_pr
|
||||||
|
est_addr1
|
||||||
|
est_addr2
|
||||||
|
est_city
|
||||||
|
est_co_nm
|
||||||
|
est_ct_fn
|
||||||
|
est_ct_ln
|
||||||
|
est_ctry
|
||||||
|
est_ea
|
||||||
|
est_ph1
|
||||||
|
est_st
|
||||||
|
est_zip
|
||||||
|
federal_tax_rate
|
||||||
|
ins_addr1
|
||||||
|
ins_addr2
|
||||||
|
ins_city
|
||||||
|
ins_co_id
|
||||||
|
ins_co_nm
|
||||||
|
ins_ct_fn
|
||||||
|
ins_ct_ln
|
||||||
|
ins_ct_ph
|
||||||
|
ins_ct_phx
|
||||||
|
ins_ctry
|
||||||
|
ins_ea
|
||||||
|
ins_fax
|
||||||
|
ins_faxx
|
||||||
|
ins_memo
|
||||||
|
ins_ph1
|
||||||
|
ins_ph1x
|
||||||
|
ins_ph2
|
||||||
|
ins_ph2x
|
||||||
|
ins_st
|
||||||
|
ins_title
|
||||||
|
ins_zip
|
||||||
|
insd_addr1
|
||||||
|
insd_addr2
|
||||||
|
insd_city
|
||||||
|
insd_co_nm
|
||||||
|
insd_ctry
|
||||||
|
insd_ea
|
||||||
|
insd_fax
|
||||||
|
insd_faxx
|
||||||
|
insd_fn
|
||||||
|
insd_ln
|
||||||
|
insd_ph1
|
||||||
|
insd_ph1x
|
||||||
|
insd_ph2
|
||||||
|
insd_ph2x
|
||||||
|
insd_st
|
||||||
|
insd_title
|
||||||
|
insd_zip
|
||||||
|
labor_rate_desc
|
||||||
|
labor_rate_id
|
||||||
|
local_tax_rate
|
||||||
|
other_amount_payable
|
||||||
|
owner_owing
|
||||||
|
ownerid
|
||||||
|
ownr_addr1
|
||||||
|
ownr_addr2
|
||||||
|
ownr_city
|
||||||
|
ownr_co_nm
|
||||||
|
ownr_ctry
|
||||||
|
ownr_ea
|
||||||
|
ownr_fax
|
||||||
|
ownr_faxx
|
||||||
|
ownr_fn
|
||||||
|
ownr_ln
|
||||||
|
ownr_ph1
|
||||||
|
ownr_ph1x
|
||||||
|
ownr_ph2
|
||||||
|
ownr_ph2x
|
||||||
|
ownr_st
|
||||||
|
ownr_title
|
||||||
|
ownr_zip
|
||||||
|
parts_tax_rates
|
||||||
|
plate_no
|
||||||
|
plate_st
|
||||||
|
po_number
|
||||||
|
rate_la1
|
||||||
|
rate_la2
|
||||||
|
rate_la3
|
||||||
|
rate_la4
|
||||||
|
rate_laa
|
||||||
|
rate_lab
|
||||||
|
rate_lad
|
||||||
|
rate_lae
|
||||||
|
rate_lag
|
||||||
|
rate_laf
|
||||||
|
rate_lam
|
||||||
|
rate_lar
|
||||||
|
rate_las
|
||||||
|
rate_lau
|
||||||
|
rate_ma2s
|
||||||
|
rate_ma2t
|
||||||
|
rate_ma3s
|
||||||
|
rate_mabl
|
||||||
|
rate_macs
|
||||||
|
rate_mahw
|
||||||
|
rate_mapa
|
||||||
|
rate_mash
|
||||||
|
rate_matd
|
||||||
|
regie_number
|
||||||
|
selling_dealer
|
||||||
|
selling_dealer_contact
|
||||||
|
servicing_dealer
|
||||||
|
servicing_dealer_contact
|
||||||
|
shopid
|
||||||
|
|
||||||
|
state_tax_rate
|
||||||
|
|
||||||
|
tax_lbr_rt
|
||||||
|
tax_levies_rt
|
||||||
|
tax_paint_mat_rt
|
||||||
|
tax_predis
|
||||||
|
tax_prethr
|
||||||
|
tax_pstthr
|
||||||
|
tax_str_rt
|
||||||
|
tax_sub_rt
|
||||||
|
tax_thramt
|
||||||
|
tax_tow_rt
|
||||||
|
unit_number
|
||||||
|
v_color
|
||||||
|
v_make_desc
|
||||||
|
v_model_desc
|
||||||
|
v_model_yr
|
||||||
|
v_vin
|
||||||
|
vehicleid
|
||||||
|
joblines(where: { removed: { _eq: false } }) {
|
||||||
|
act_price
|
||||||
|
alt_co_id
|
||||||
|
alt_overrd
|
||||||
|
alt_part_i
|
||||||
|
alt_partm
|
||||||
|
bett_amt
|
||||||
|
alt_partno
|
||||||
|
bett_pctg
|
||||||
|
bett_tax
|
||||||
|
bett_type
|
||||||
|
cert_part
|
||||||
|
db_hrs
|
||||||
|
db_price
|
||||||
|
db_ref
|
||||||
|
est_seq
|
||||||
|
glass_flag
|
||||||
|
id
|
||||||
|
lbr_amt
|
||||||
|
lbr_hrs_j
|
||||||
|
lbr_inc
|
||||||
|
lbr_op
|
||||||
|
lbr_op_j
|
||||||
|
lbr_tax
|
||||||
|
lbr_typ_j
|
||||||
|
line_desc
|
||||||
|
line_ind
|
||||||
|
line_ref
|
||||||
|
misc_amt
|
||||||
|
misc_sublt
|
||||||
|
misc_tax
|
||||||
|
mod_lb_hrs
|
||||||
|
mod_lbr_ty
|
||||||
|
oem_partno
|
||||||
|
op_code_desc
|
||||||
|
paint_stg
|
||||||
|
paint_tone
|
||||||
|
part_qty
|
||||||
|
part_type
|
||||||
|
price_inc
|
||||||
|
price_j
|
||||||
|
prt_dsmk_m
|
||||||
|
prt_dsmk_p
|
||||||
|
status
|
||||||
|
tax_part
|
||||||
|
unq_seq
|
||||||
|
manual_line
|
||||||
|
}
|
||||||
|
driveable
|
||||||
|
towin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const QUERY_ALL_JOB_FIELDS = gql`
|
export const QUERY_ALL_JOB_FIELDS = gql`
|
||||||
query QUERY_ALL_JOB_FIELDS($id: uuid!) {
|
query QUERY_ALL_JOB_FIELDS($id: uuid!) {
|
||||||
jobs_by_pk(id: $id) {
|
jobs_by_pk(id: $id) {
|
||||||
@@ -1484,6 +1716,7 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
|
|||||||
op_code_desc
|
op_code_desc
|
||||||
profitcenter_labor
|
profitcenter_labor
|
||||||
profitcenter_part
|
profitcenter_part
|
||||||
|
prt_dsmk_p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AlertOutlined } from "@ant-design/icons";
|
import { AlertOutlined } from "@ant-design/icons";
|
||||||
import * as Sentry from "@sentry/react";
|
import * as Sentry from "@sentry/react";
|
||||||
import { Button, notification } from "antd";
|
import { Button, notification, Space } from "antd";
|
||||||
//import "antd/dist/antd.css";
|
//import "antd/dist/antd.css";
|
||||||
import "antd/dist/antd.less";
|
import "antd/dist/antd.less";
|
||||||
import Dinero from "dinero.js";
|
import Dinero from "dinero.js";
|
||||||
@@ -26,8 +26,7 @@ Dinero.globalRoundingMode = "HALF_EVEN";
|
|||||||
|
|
||||||
if (process.env.NODE_ENV !== "development") {
|
if (process.env.NODE_ENV !== "development") {
|
||||||
Sentry.init({
|
Sentry.init({
|
||||||
dsn:
|
dsn: "https://fd7e89369b6b4bdc9c6c4c9f22fa4ee4@o492140.ingest.sentry.io/5651027",
|
||||||
"https://fd7e89369b6b4bdc9c6c4c9f22fa4ee4@o492140.ingest.sentry.io/5651027",
|
|
||||||
integrations: [
|
integrations: [
|
||||||
// new Integrations.BrowserTracing(),
|
// new Integrations.BrowserTracing(),
|
||||||
// new Sentry.Integrations.Breadcrumbs({ console: true }),
|
// new Sentry.Integrations.Breadcrumbs({ console: true }),
|
||||||
@@ -57,21 +56,30 @@ const onServiceWorkerUpdate = (registration) => {
|
|||||||
console.log("onServiceWorkerUpdate", registration);
|
console.log("onServiceWorkerUpdate", registration);
|
||||||
|
|
||||||
const btn = (
|
const btn = (
|
||||||
<Button
|
<Space flex>
|
||||||
type="primary"
|
<Button
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
if (registration && registration.waiting) {
|
window.open("https://imex-online.noticeable.news/", "_blank");
|
||||||
await registration.unregister();
|
}}
|
||||||
// Makes Workbox call skipWaiting()
|
>
|
||||||
registration.waiting.postMessage({ type: "SKIP_WAITING" });
|
{i18n.t("general.actions.viewreleasenotes")}
|
||||||
// Once the service worker is unregistered, we can reload the page to let
|
</Button>
|
||||||
// the browser download a fresh copy of our app (invalidating the cache)
|
<Button
|
||||||
window.location.reload();
|
type="primary"
|
||||||
}
|
onClick={async () => {
|
||||||
}}
|
if (registration && registration.waiting) {
|
||||||
>
|
await registration.unregister();
|
||||||
{i18n.t("general.actions.refresh")}
|
// Makes Workbox call skipWaiting()
|
||||||
</Button>
|
registration.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>
|
||||||
);
|
);
|
||||||
notification.open({
|
notification.open({
|
||||||
icon: <AlertOutlined />,
|
icon: <AlertOutlined />,
|
||||||
|
|||||||
@@ -35,13 +35,14 @@ export function AllJobs({ setBreadcrumbs, setSelectedHeader }) {
|
|||||||
offset: page ? (page - 1) * 25 : 0,
|
offset: page ? (page - 1) * 25 : 0,
|
||||||
limit: 25,
|
limit: 25,
|
||||||
...(statusFilters ? { statusList: JSON.parse(statusFilters) } : {}),
|
...(statusFilters ? { statusList: JSON.parse(statusFilters) } : {}),
|
||||||
order: [
|
order: [
|
||||||
{
|
{
|
||||||
[sortcolumn || "created_at"]: sortorder
|
[sortcolumn || "created_at"]:
|
||||||
? sortorder === "descend"
|
sortorder && sortorder !== "false"
|
||||||
? "desc"
|
? sortorder === "descend"
|
||||||
: "asc"
|
? "desc"
|
||||||
: "desc",
|
: "asc"
|
||||||
|
: "desc",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -155,6 +155,13 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
|||||||
layout="vertical"
|
layout="vertical"
|
||||||
autoComplete={"off"}
|
autoComplete={"off"}
|
||||||
initialValues={{
|
initialValues={{
|
||||||
|
tax_tow_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
tax_str_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
tax_paint_mat_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
tax_shop_mat_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
tax_sub_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
tax_lbr_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
tax_levies_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
parts_tax_rates: {
|
parts_tax_rates: {
|
||||||
PAA: {
|
PAA: {
|
||||||
prt_type: "PAA",
|
prt_type: "PAA",
|
||||||
@@ -220,6 +227,30 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
|||||||
prt_tax_in: true,
|
prt_tax_in: true,
|
||||||
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
},
|
},
|
||||||
|
PASL: {
|
||||||
|
prt_type: "PASL",
|
||||||
|
prt_discp: 0,
|
||||||
|
prt_mktyp: false,
|
||||||
|
prt_mkupp: 0,
|
||||||
|
prt_tax_in: true,
|
||||||
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
},
|
||||||
|
PAP: {
|
||||||
|
prt_type: "PAP",
|
||||||
|
prt_discp: 0,
|
||||||
|
prt_mktyp: false,
|
||||||
|
prt_mkupp: 0,
|
||||||
|
prt_tax_in: true,
|
||||||
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
},
|
||||||
|
PAO: {
|
||||||
|
prt_type: "PAO",
|
||||||
|
prt_discp: 0,
|
||||||
|
prt_mktyp: false,
|
||||||
|
prt_mkupp: 0,
|
||||||
|
prt_tax_in: true,
|
||||||
|
prt_tax_rt: bodyshop.bill_tax_rates.state_tax_rate / 100,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -181,7 +181,10 @@ const mapStateToProps = createStructuredSelector({
|
|||||||
|
|
||||||
export function Manage({ match, conflict, bodyshop }) {
|
export function Manage({ match, conflict, bodyshop }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
useEffect(() => {
|
||||||
|
const widgetId = "IABVNO4scRKY11XBQkNr";
|
||||||
|
window.noticeable.render("widget", widgetId);
|
||||||
|
}, []);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.title = t("titles.app");
|
document.title = t("titles.app");
|
||||||
}, [t]);
|
}, [t]);
|
||||||
@@ -383,11 +386,22 @@ export function Manage({ match, conflict, bodyshop }) {
|
|||||||
<ChatAffixContainer />
|
<ChatAffixContainer />
|
||||||
<BackTop />
|
<BackTop />
|
||||||
<Footer>
|
<Footer>
|
||||||
<div style={{ textAlign: "center", margin: "1rem 0rem" }}>
|
<div
|
||||||
<div>
|
style={{
|
||||||
{`ImEX Online V.${process.env.NODE_ENV} - ${
|
display: "flex",
|
||||||
process.env.REACT_APP_GIT_SHA
|
flexDirection: "column",
|
||||||
} - ${preval`module.exports = new Date().toLocaleString("en-US", {timeZone: "America/Los_Angeles"});`}`}
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
margin: "1rem 0rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex" }}>
|
||||||
|
<div>
|
||||||
|
{`ImEX Online ${
|
||||||
|
process.env.REACT_APP_GIT_SHA
|
||||||
|
} - ${preval`module.exports = new Date().toLocaleString("en-US", {timeZone: "America/Los_Angeles"});`}`}
|
||||||
|
</div>
|
||||||
|
<div id="noticeable-widget" style={{ marginLeft: "1rem" }} />
|
||||||
</div>
|
</div>
|
||||||
<Link to="/about" target="_blank" style={{ color: "#ccc" }}>
|
<Link to="/about" target="_blank" style={{ color: "#ccc" }}>
|
||||||
Disclaimer
|
Disclaimer
|
||||||
|
|||||||
@@ -48,3 +48,8 @@ export const setPartnerVersion = (version) => ({
|
|||||||
type: ApplicationActionTypes.SET_PARTNER_VERSION,
|
type: ApplicationActionTypes.SET_PARTNER_VERSION,
|
||||||
payload: version,
|
payload: version,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const setOnline = (isOnline) => ({
|
||||||
|
type: ApplicationActionTypes.SET_ONLINE_STATUS,
|
||||||
|
payload: isOnline,
|
||||||
|
});
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import ApplicationActionTypes from "./application.types";
|
|||||||
|
|
||||||
const INITIAL_STATE = {
|
const INITIAL_STATE = {
|
||||||
loading: false,
|
loading: false,
|
||||||
|
online: true,
|
||||||
breadcrumbs: [],
|
breadcrumbs: [],
|
||||||
recentItems: [],
|
recentItems: [],
|
||||||
selectedHeader: "home",
|
selectedHeader: "home",
|
||||||
@@ -21,6 +22,11 @@ const applicationReducer = (state = INITIAL_STATE, action) => {
|
|||||||
...state,
|
...state,
|
||||||
selectedHeader: action.payload,
|
selectedHeader: action.payload,
|
||||||
};
|
};
|
||||||
|
case ApplicationActionTypes.SET_ONLINE_STATUS:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
online: action.payload,
|
||||||
|
};
|
||||||
case ApplicationActionTypes.ADD_RECENT_ITEM:
|
case ApplicationActionTypes.ADD_RECENT_ITEM:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -40,3 +40,7 @@ export const selectJobReadOnly = createSelector(
|
|||||||
[selectApplication],
|
[selectApplication],
|
||||||
(application) => application.jobReadOnly
|
(application) => application.jobReadOnly
|
||||||
);
|
);
|
||||||
|
export const selectOnline = createSelector(
|
||||||
|
[selectApplication],
|
||||||
|
(application) => application.online
|
||||||
|
);
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ const ApplicationActionTypes = {
|
|||||||
SET_SELECTED_HEADER: "SET_SELECTED_HEADER",
|
SET_SELECTED_HEADER: "SET_SELECTED_HEADER",
|
||||||
SET_JOB_READONLY: "SET_JOB_READONLY",
|
SET_JOB_READONLY: "SET_JOB_READONLY",
|
||||||
SET_PARTNER_VERSION: "SET_PARTNER_VERSION",
|
SET_PARTNER_VERSION: "SET_PARTNER_VERSION",
|
||||||
|
SET_ONLINE_STATUS: "SET_ONLINE_STATUS",
|
||||||
};
|
};
|
||||||
export default ApplicationActionTypes;
|
export default ApplicationActionTypes;
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import Fingerprint2 from "@fingerprintjs/fingerprintjs";
|
import Fingerprint2 from "@fingerprintjs/fingerprintjs";
|
||||||
|
import { notification } from "antd";
|
||||||
|
import i18next from "i18next";
|
||||||
import LogRocket from "logrocket";
|
import LogRocket from "logrocket";
|
||||||
import { all, call, delay, put, select, takeLatest } from "redux-saga/effects";
|
import { all, call, delay, put, select, takeLatest } from "redux-saga/effects";
|
||||||
import {
|
import {
|
||||||
@@ -100,6 +102,10 @@ export function* updateUserDetails(userDetails) {
|
|||||||
try {
|
try {
|
||||||
yield updateCurrentUser(userDetails.payload);
|
yield updateCurrentUser(userDetails.payload);
|
||||||
yield put(updateUserDetailsSuccess(userDetails.payload));
|
yield put(updateUserDetailsSuccess(userDetails.payload));
|
||||||
|
notification.open({
|
||||||
|
type: "success",
|
||||||
|
message: i18next.t("profile.successes.updated"),
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//yield put(signOutFailure(error.message));
|
//yield put(signOutFailure(error.message));
|
||||||
}
|
}
|
||||||
@@ -158,6 +164,16 @@ export function* onSignInSuccess() {
|
|||||||
|
|
||||||
export function* signInSuccessSaga({ payload }) {
|
export function* signInSuccessSaga({ payload }) {
|
||||||
LogRocket.identify(payload.email);
|
LogRocket.identify(payload.email);
|
||||||
|
try {
|
||||||
|
// window.$crisp.push(["set", "user:email", [payload.email]]);
|
||||||
|
window.$crisp.push([
|
||||||
|
"set",
|
||||||
|
"user:nickname",
|
||||||
|
[payload.displayName || payload.email],
|
||||||
|
]);
|
||||||
|
} catch (error) {
|
||||||
|
console.log("Error updating Crisp settings.", error);
|
||||||
|
}
|
||||||
|
|
||||||
// if (!payload.email.includes("@imex.")) yield put(setInstanceId(payload.uid));
|
// if (!payload.email.includes("@imex.")) yield put(setInstanceId(payload.uid));
|
||||||
analytics.setUserId(payload.email);
|
analytics.setUserId(payload.email);
|
||||||
@@ -214,10 +230,16 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
|
|||||||
try {
|
try {
|
||||||
const userEmail = yield select((state) => state.user.currentUser.email);
|
const userEmail = yield select((state) => state.user.currentUser.email);
|
||||||
|
|
||||||
|
window.$crisp.push(["set", "user:company", [payload.shopname]]);
|
||||||
|
|
||||||
const authRecord = payload.associations.filter(
|
const authRecord = payload.associations.filter(
|
||||||
(a) => a.useremail === userEmail
|
(a) => a.useremail === userEmail
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (authRecord[0] && authRecord[0].user.validemail) {
|
||||||
|
window.$crisp.push(["set", "user:email", [authRecord[0].user.email]]);
|
||||||
|
}
|
||||||
|
|
||||||
yield put(setAuthlevel(authRecord[0] ? authRecord[0].authlevel : 0));
|
yield put(setAuthlevel(authRecord[0] ? authRecord[0].authlevel : 0));
|
||||||
yield put(
|
yield put(
|
||||||
updateUserDetailsSuccess(
|
updateUserDetailsSuccess(
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"deleting": "Error encountered while deleting allocation. {{message}}",
|
"deleting": "Error encountered while deleting allocation. {{message}}",
|
||||||
"saving": "Error while allocating. {{message}}",
|
"saving": "Error while allocating. {{message}}",
|
||||||
"validation": "Please ensure all fields are entered correctly. "
|
"validation": "Please ensure all fields are entered correctly. "
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
@@ -167,6 +167,7 @@
|
|||||||
"exported": "Bill exported successfully."
|
"exported": "Bill exported successfully."
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"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."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -218,6 +219,10 @@
|
|||||||
"invoice_federal_tax_rate": "Invoices - Federal Tax Rate",
|
"invoice_federal_tax_rate": "Invoices - Federal Tax Rate",
|
||||||
"invoice_local_tax_rate": "Invoices - Local Tax Rate",
|
"invoice_local_tax_rate": "Invoices - Local Tax Rate",
|
||||||
"invoice_state_tax_rate": "Invoices - Provincial/State Tax Rate",
|
"invoice_state_tax_rate": "Invoices - Provincial/State Tax Rate",
|
||||||
|
"jc_hourly_rates": {
|
||||||
|
"mapa": "Job Costing - Paint Materials Hourly Cost Rate",
|
||||||
|
"mash": "Job Costing - Shop Materials Hourly Cost Rate"
|
||||||
|
},
|
||||||
"lastnumberworkingdays": "Scoreboard - Last Number of Working Days",
|
"lastnumberworkingdays": "Scoreboard - Last Number of Working Days",
|
||||||
"logo_img_path": "Shop Logo",
|
"logo_img_path": "Shop Logo",
|
||||||
"logo_img_path_height": "Logo Image Height",
|
"logo_img_path_height": "Logo Image Height",
|
||||||
@@ -555,7 +560,7 @@
|
|||||||
"driverinformation": "Driver's Information",
|
"driverinformation": "Driver's Information",
|
||||||
"findcontract": "Find Contract",
|
"findcontract": "Find Contract",
|
||||||
"findermodal": "Contract Finder",
|
"findermodal": "Contract Finder",
|
||||||
"noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.",
|
"noteconvertedfrom": "R.O. created from converted Courtesy Car Contract {{agreementnumber}}.",
|
||||||
"populatefromjob": "Populate from Job",
|
"populatefromjob": "Populate from Job",
|
||||||
"rates": "Contract Rates",
|
"rates": "Contract Rates",
|
||||||
"time": "Time",
|
"time": "Time",
|
||||||
@@ -673,7 +678,7 @@
|
|||||||
"documents": {
|
"documents": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"delete": "Delete Selected Documents",
|
"delete": "Delete Selected Documents",
|
||||||
"download": "Download Selected Documents",
|
"download": "Download Selected Images",
|
||||||
"reassign": "Reassign to another Job",
|
"reassign": "Reassign to another Job",
|
||||||
"selectallimages": "Select All Images",
|
"selectallimages": "Select All Images",
|
||||||
"selectallotherdocuments": "Select All Other Documents"
|
"selectallotherdocuments": "Select All Other Documents"
|
||||||
@@ -683,7 +688,8 @@
|
|||||||
"deleting_cloudinary": "Error deleting document from storage. {{message}}",
|
"deleting_cloudinary": "Error deleting document from storage. {{message}}",
|
||||||
"getpresignurl": "Error obtaining presigned URL for document. {{message}}",
|
"getpresignurl": "Error obtaining presigned URL for document. {{message}}",
|
||||||
"insert": "Unable to upload file. {{message}}",
|
"insert": "Unable to upload file. {{message}}",
|
||||||
"nodocuments": "There are no documents."
|
"nodocuments": "There are no documents.",
|
||||||
|
"updating": "Error updating document. {{error}}"
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.",
|
"confirmdelete": "Are you sure you want to delete these documents. This CANNOT be undone.",
|
||||||
@@ -696,10 +702,12 @@
|
|||||||
"upload": "Upload",
|
"upload": "Upload",
|
||||||
"upload_limitexceeded": "Uploading all selected documents will exceed the job storage limit for your shop. ",
|
"upload_limitexceeded": "Uploading all selected documents will exceed the job storage limit for your shop. ",
|
||||||
"upload_limitexceeded_title": "Unable to upload document(s)",
|
"upload_limitexceeded_title": "Unable to upload document(s)",
|
||||||
|
"uploading": "Uploading...",
|
||||||
"usage": "of job storage used. ({{used}} / {{total}})"
|
"usage": "of job storage used. ({{used}} / {{total}})"
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"delete": "Document(s) deleted successfully.",
|
"delete": "Document(s) deleted successfully.",
|
||||||
|
"edituploaded": "Edited document uploaded successfully. Please close this window and refresh the documents list.",
|
||||||
"insert": "Uploaded document successfully. ",
|
"insert": "Uploaded document successfully. ",
|
||||||
"updated": "Document updated successfully. "
|
"updated": "Document updated successfully. "
|
||||||
}
|
}
|
||||||
@@ -762,6 +770,11 @@
|
|||||||
"unique_employee_number": "You must enter a unique employee number."
|
"unique_employee_number": "You must enter a unique employee number."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"exportlogs": {
|
||||||
|
"fields": {
|
||||||
|
"createdat": "Created At"
|
||||||
|
}
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"add": "Add",
|
"add": "Add",
|
||||||
@@ -785,7 +798,11 @@
|
|||||||
"selectall": "Select All",
|
"selectall": "Select All",
|
||||||
"submit": "Submit",
|
"submit": "Submit",
|
||||||
"submitticket": "Submit a Support Ticket",
|
"submitticket": "Submit a Support Ticket",
|
||||||
"view": "View"
|
"view": "View",
|
||||||
|
"viewreleasenotes": "See What's Changed"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"notfound": "No record was found."
|
||||||
},
|
},
|
||||||
"itemtypes": {
|
"itemtypes": {
|
||||||
"contract": "CC Contract",
|
"contract": "CC Contract",
|
||||||
@@ -820,6 +837,8 @@
|
|||||||
"monday": "Monday",
|
"monday": "Monday",
|
||||||
"na": "N/A",
|
"na": "N/A",
|
||||||
"no": "No",
|
"no": "No",
|
||||||
|
"nointernet": "It looks like you're not connected to the internet.",
|
||||||
|
"nointernet_sub": "Please check your connection and try again. ",
|
||||||
"none": "None",
|
"none": "None",
|
||||||
"out": "Out",
|
"out": "Out",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
@@ -950,6 +969,7 @@
|
|||||||
},
|
},
|
||||||
"profitcenter_labor": "Profit Center: Labor",
|
"profitcenter_labor": "Profit Center: Labor",
|
||||||
"profitcenter_part": "Profit Center: Part",
|
"profitcenter_part": "Profit Center: Part",
|
||||||
|
"prt_dsmk_p": "Line Markup %",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"total": "Total",
|
"total": "Total",
|
||||||
"unq_seq": "Seq #"
|
"unq_seq": "Seq #"
|
||||||
@@ -1122,6 +1142,7 @@
|
|||||||
"ownr_ea": "Email",
|
"ownr_ea": "Email",
|
||||||
"ownr_ph1": "Phone 1",
|
"ownr_ph1": "Phone 1",
|
||||||
"paa": "Aftermarket",
|
"paa": "Aftermarket",
|
||||||
|
"pac": "Rechromed",
|
||||||
"pae": "Existing",
|
"pae": "Existing",
|
||||||
"pag": "Glass",
|
"pag": "Glass",
|
||||||
"pal": "LKQ",
|
"pal": "LKQ",
|
||||||
@@ -1226,6 +1247,8 @@
|
|||||||
"rate": "PVRT Rate"
|
"rate": "PVRT Rate"
|
||||||
},
|
},
|
||||||
"ca_gst_all_if_null": "If the job is marked as a \"GST Registrant\" and this value is set to $0, the customer will be responsible for paying all of the GST by default. ",
|
"ca_gst_all_if_null": "If the job is marked as a \"GST Registrant\" and this value is set to $0, the customer will be responsible for paying all of the GST by default. ",
|
||||||
|
"calc_repair_days": "Calculated Repair Days",
|
||||||
|
"calc_repair_days_tt": "This is the approximate number of days required to complete the repair according to the target touch time in your shop configuration (current set to {{target_touchtime}}).",
|
||||||
"cards": {
|
"cards": {
|
||||||
"customer": "Customer Information",
|
"customer": "Customer Information",
|
||||||
"damage": "Area of Damage",
|
"damage": "Area of Damage",
|
||||||
@@ -1279,7 +1302,7 @@
|
|||||||
"gppercent": "% G.P.",
|
"gppercent": "% G.P.",
|
||||||
"hrs_claimed": "Hours Claimed",
|
"hrs_claimed": "Hours Claimed",
|
||||||
"hrs_total": "Hours Total",
|
"hrs_total": "Hours Total",
|
||||||
"importnote": "The job was initially imported on {{date}} at {{time}}.",
|
"importnote": "The job was initially imported.",
|
||||||
"inproduction": "In Production",
|
"inproduction": "In Production",
|
||||||
"intakechecklist": "Intake Checklist",
|
"intakechecklist": "Intake Checklist",
|
||||||
"job": "Job Details",
|
"job": "Job Details",
|
||||||
@@ -1314,6 +1337,7 @@
|
|||||||
"partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice).<br/>\nItems such as shop and paint materials, labor online lines, etc. are not included in this total.",
|
"partstotal": "This is the total of all parts and sublet amounts on the vehicle (some of these may require an in-house invoice).<br/>\nItems such as shop and paint materials, labor online lines, etc. are not included in this total.",
|
||||||
"totalreturns": "The total amount of returns created for this job."
|
"totalreturns": "The total amount of returns created for this job."
|
||||||
},
|
},
|
||||||
|
"prt_dsmk_total": "Line Item Markup",
|
||||||
"rates": "Rates",
|
"rates": "Rates",
|
||||||
"rates_subtotal": "All Rates Subtotal",
|
"rates_subtotal": "All Rates Subtotal",
|
||||||
"reconciliation": {
|
"reconciliation": {
|
||||||
@@ -1339,19 +1363,19 @@
|
|||||||
"state_tax_amt": "Provincial/State Taxes",
|
"state_tax_amt": "Provincial/State Taxes",
|
||||||
"subletstotal": "Sublets Total",
|
"subletstotal": "Sublets Total",
|
||||||
"subtotal": "Subtotal",
|
"subtotal": "Subtotal",
|
||||||
"supplementnote": "The job had a supplement imported on {{date}} at {{time}}.",
|
"supplementnote": "The job had a supplement imported.",
|
||||||
"suspense": "Suspense",
|
"suspense": "Suspense",
|
||||||
"total_cost": "Total Cost",
|
"total_cost": "Total Cost",
|
||||||
"total_cust_payable": "Total Customer Amount Payable",
|
"total_cust_payable": "Total Customer Amount Payable",
|
||||||
"total_repairs": "Total Repairs",
|
"total_repairs": "Total Repairs",
|
||||||
"total_sales": "Total Sales",
|
"total_sales": "Total Sales",
|
||||||
"totals": "Totals",
|
"totals": "Totals",
|
||||||
"unvoidnote": "This job was unvoided by {{email}}.",
|
"unvoidnote": "This job was unvoided.",
|
||||||
"vehicle_info": "Vehicle",
|
"vehicle_info": "Vehicle",
|
||||||
"vehicleassociation": "Vehicle Association",
|
"vehicleassociation": "Vehicle Association",
|
||||||
"viewallocations": "View Allocations",
|
"viewallocations": "View Allocations",
|
||||||
"voidjob": "Are you sure you want to void this job? This cannot be easily undone. ",
|
"voidjob": "Are you sure you want to void this job? This cannot be easily undone. ",
|
||||||
"voidnote": "This repair order was voided on {{date}} at {{time}}."
|
"voidnote": "This job was voided."
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"addedtoproduction": "Job added to production board.",
|
"addedtoproduction": "Job added to production board.",
|
||||||
@@ -1398,6 +1422,7 @@
|
|||||||
"entertimeticket": "Enter Time Tickets",
|
"entertimeticket": "Enter Time Tickets",
|
||||||
"export": "Export",
|
"export": "Export",
|
||||||
"export-logs": "Export Logs",
|
"export-logs": "Export Logs",
|
||||||
|
"help": "Help",
|
||||||
"home": "Home",
|
"home": "Home",
|
||||||
"jobs": "Jobs",
|
"jobs": "Jobs",
|
||||||
"owners": "Owners",
|
"owners": "Owners",
|
||||||
@@ -1580,6 +1605,7 @@
|
|||||||
"oem_partno": "Part #",
|
"oem_partno": "Part #",
|
||||||
"order_date": "Order Date",
|
"order_date": "Order Date",
|
||||||
"order_number": "Order Number",
|
"order_number": "Order Number",
|
||||||
|
"orderedby": "Ordered By",
|
||||||
"quantity": "Qty.",
|
"quantity": "Qty.",
|
||||||
"return": "Return",
|
"return": "Return",
|
||||||
"status": "Status"
|
"status": "Status"
|
||||||
@@ -1662,6 +1688,8 @@
|
|||||||
"state": "Province/State"
|
"state": "Province/State"
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
|
"noneselected": "No phone book entry selected. ",
|
||||||
|
"onenamerequired": "At least one name related field is required.",
|
||||||
"vendorcategory": "Vendor"
|
"vendorcategory": "Vendor"
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
@@ -1730,7 +1758,10 @@
|
|||||||
"payment_receipt": "Payment Receipt",
|
"payment_receipt": "Payment Receipt",
|
||||||
"payment_request": "Payment Request",
|
"payment_request": "Payment Request",
|
||||||
"payments_by_job": "Job Payments",
|
"payments_by_job": "Job Payments",
|
||||||
|
"purchases_by_ro_detail": "Purchases - Detail",
|
||||||
|
"purchases_by_ro_summary": "Purchases - Summary",
|
||||||
"qc_sheet": "Quality Control Sheet",
|
"qc_sheet": "Quality Control Sheet",
|
||||||
|
"ro_totals": "RO Totals",
|
||||||
"ro_with_description": "RO Summary with Descriptions",
|
"ro_with_description": "RO Summary with Descriptions",
|
||||||
"supplement_request": "Supplement Request",
|
"supplement_request": "Supplement Request",
|
||||||
"thank_you_ro": "Thank You Letter",
|
"thank_you_ro": "Thank You Letter",
|
||||||
@@ -1813,6 +1844,9 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"activeshop": "Active Shop"
|
"activeshop": "Active Shop"
|
||||||
|
},
|
||||||
|
"successes": {
|
||||||
|
"updated": "Profile updated successfully."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"reportcenter": {
|
"reportcenter": {
|
||||||
@@ -1828,6 +1862,7 @@
|
|||||||
"objects": {
|
"objects": {
|
||||||
"appointments": "Appointments",
|
"appointments": "Appointments",
|
||||||
"bills": "Bills",
|
"bills": "Bills",
|
||||||
|
"exportlogs": "Export Logs",
|
||||||
"jobs": "Jobs",
|
"jobs": "Jobs",
|
||||||
"payments": "Payments",
|
"payments": "Payments",
|
||||||
"timetickets": "Timetickets"
|
"timetickets": "Timetickets"
|
||||||
@@ -1835,27 +1870,41 @@
|
|||||||
"vendor": "Vendor"
|
"vendor": "Vendor"
|
||||||
},
|
},
|
||||||
"templates": {
|
"templates": {
|
||||||
|
"attendance_detail": "Attendance (All Employees)",
|
||||||
"attendance_employee": "Employee Attendance",
|
"attendance_employee": "Employee Attendance",
|
||||||
|
"attendance_summary": "Attendance Summary (All Employees)",
|
||||||
"credits_not_received_date": "Credits not Received by Date",
|
"credits_not_received_date": "Credits not Received by Date",
|
||||||
"estimator_detail": "Jobs by Estimator (Detail)",
|
"estimator_detail": "Jobs by Estimator (Detail)",
|
||||||
"estimator_summary": "Jobs by Estimator (Summary)",
|
"estimator_summary": "Jobs by Estimator (Summary)",
|
||||||
|
"export_payables": "Export Log - Payables",
|
||||||
|
"export_payments": "Export Log - Payments",
|
||||||
|
"export_receivables": "Export Log - Receivables",
|
||||||
|
"gsr_by_delivery_date": "Gross Sales by Delivery Date",
|
||||||
"gsr_by_estimator": "Gross Sales by Estimator",
|
"gsr_by_estimator": "Gross Sales by Estimator",
|
||||||
|
"gsr_by_exported_date": "Gross Sales by Export Date",
|
||||||
|
"gsr_by_ins_co": "Gross Sales by Insurance Company'",
|
||||||
"gsr_by_make": "Gross Sales by Vehicle Make",
|
"gsr_by_make": "Gross Sales by Vehicle Make",
|
||||||
|
"gsr_by_referral": "Gross Sales by Referral Source",
|
||||||
|
"gsr_by_ro": "Gross Sales by RO",
|
||||||
"gsr_labor_only": "Gross Sales - Labor Only",
|
"gsr_labor_only": "Gross Sales - Labor Only",
|
||||||
"hours_sold_detail_closed": "Hours Sold Detail - Closed",
|
"hours_sold_detail_closed": "Hours Sold Detail - Closed",
|
||||||
"hours_sold_detail_closed_source": "Hours Sold Detail - Closed by Source",
|
"hours_sold_detail_closed_ins_co": "Hours Sold Detail - Closed by Source",
|
||||||
"hours_sold_detail_open": "Hours Sold Detail - Open",
|
"hours_sold_detail_open": "Hours Sold Detail - Open",
|
||||||
"hours_sold_detail_open_source": "Hours Sold Detail - Open by Source",
|
"hours_sold_detail_open_ins_co": "Hours Sold Detail - Open by Source",
|
||||||
"hours_sold_summary_closed": "Hours Sold Summary - Closed",
|
"hours_sold_summary_closed": "Hours Sold Summary - Closed",
|
||||||
"hours_sold_summary_closed_source": "Hours Sold Summary - Closed by Source",
|
"hours_sold_summary_closed_ins_co": "Hours Sold Summary - Closed by Source",
|
||||||
"hours_sold_summary_open": "Hours Sold Summary - Open",
|
"hours_sold_summary_open": "Hours Sold Summary - Open",
|
||||||
"hours_sold_summary_open_source": "Hours Sold Summary - Open by Source",
|
"hours_sold_summary_open_ins_co": "Hours Sold Summary - Open by Source",
|
||||||
"job_costing_ro_date_detail": "Job Costing by RO - Detail",
|
"job_costing_ro_date_detail": "Job Costing by RO - Detail",
|
||||||
"job_costing_ro_date_summary": "Job Costing by RO - Summary",
|
"job_costing_ro_date_summary": "Job Costing by RO - Summary",
|
||||||
"job_costing_ro_estimator": "Job Costing by Estimator",
|
"job_costing_ro_estimator": "Job Costing by Estimator",
|
||||||
"job_costing_ro_source": "Job Costing by RO Source",
|
"job_costing_ro_ins_co": "Job Costing by RO Source",
|
||||||
"open_orders": "Open Orders by Date",
|
"open_orders": "Open Orders by Date",
|
||||||
"payments_by_date_type": "Payments by Date Range",
|
"open_orders_estimator": "Open Orders by Estimator",
|
||||||
|
"open_orders_ins_co": "Open Orders by Insurance Company",
|
||||||
|
"parts_backorder": "Backordered Parts",
|
||||||
|
"payments_by_date": "Payments by Date",
|
||||||
|
"payments_by_date_type": "Payments by Date and Type",
|
||||||
"purchases_by_cost_center_detail": "Purchases by Cost Center (Detail)",
|
"purchases_by_cost_center_detail": "Purchases by Cost Center (Detail)",
|
||||||
"purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)",
|
"purchases_by_cost_center_summary": "Purchases by Cost Center (Summary)",
|
||||||
"purchases_by_date_range_detail": "Purchases by Date - Detail",
|
"purchases_by_date_range_detail": "Purchases by Date - Detail",
|
||||||
@@ -1865,11 +1914,15 @@
|
|||||||
"purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed",
|
"purchases_grouped_by_vendor_detailed": "Purchases Grouped by Vendor - Detailed",
|
||||||
"purchases_grouped_by_vendor_summary": "Purchases Grouped by Vendor - Summary",
|
"purchases_grouped_by_vendor_summary": "Purchases Grouped by Vendor - Summary",
|
||||||
"schedule": "Appointment Schedule",
|
"schedule": "Appointment Schedule",
|
||||||
"supplement_ratio_source": "Supplement Ratio by Source",
|
"supplement_ratio_ins_co": "Supplement Ratio by Source",
|
||||||
|
"thank_you_date": "Thank You Letters",
|
||||||
"timetickets": "Time Tickets",
|
"timetickets": "Time Tickets",
|
||||||
"timetickets_employee": "Employee Time Tickets",
|
"timetickets_employee": "Employee Time Tickets",
|
||||||
"timetickets_summary": "Time Tickets Summary",
|
"timetickets_summary": "Time Tickets Summary",
|
||||||
"void_ros": "Void ROs"
|
"unclaimed_hrs": "Unclaimed Hours",
|
||||||
|
"void_ros": "Void ROs",
|
||||||
|
"work_in_progress_labour": "Work in Progress - Labor",
|
||||||
|
"work_in_progress_payables": "Work in Progress - Payables"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scoreboard": {
|
"scoreboard": {
|
||||||
|
|||||||
@@ -167,6 +167,7 @@
|
|||||||
"exported": ""
|
"exported": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"manualinhouse": "",
|
||||||
"unique_invoice_number": ""
|
"unique_invoice_number": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -218,6 +219,10 @@
|
|||||||
"invoice_federal_tax_rate": "",
|
"invoice_federal_tax_rate": "",
|
||||||
"invoice_local_tax_rate": "",
|
"invoice_local_tax_rate": "",
|
||||||
"invoice_state_tax_rate": "",
|
"invoice_state_tax_rate": "",
|
||||||
|
"jc_hourly_rates": {
|
||||||
|
"mapa": "",
|
||||||
|
"mash": ""
|
||||||
|
},
|
||||||
"lastnumberworkingdays": "",
|
"lastnumberworkingdays": "",
|
||||||
"logo_img_path": "",
|
"logo_img_path": "",
|
||||||
"logo_img_path_height": "",
|
"logo_img_path_height": "",
|
||||||
@@ -683,7 +688,8 @@
|
|||||||
"deleting_cloudinary": "",
|
"deleting_cloudinary": "",
|
||||||
"getpresignurl": "Error al obtener la URL prescrita para el documento. {{message}}",
|
"getpresignurl": "Error al obtener la URL prescrita para el documento. {{message}}",
|
||||||
"insert": "Incapaz de cargar el archivo. {{message}}",
|
"insert": "Incapaz de cargar el archivo. {{message}}",
|
||||||
"nodocuments": "No hay documentos"
|
"nodocuments": "No hay documentos",
|
||||||
|
"updating": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"confirmdelete": "",
|
"confirmdelete": "",
|
||||||
@@ -696,10 +702,12 @@
|
|||||||
"upload": "Subir",
|
"upload": "Subir",
|
||||||
"upload_limitexceeded": "",
|
"upload_limitexceeded": "",
|
||||||
"upload_limitexceeded_title": "",
|
"upload_limitexceeded_title": "",
|
||||||
|
"uploading": "",
|
||||||
"usage": ""
|
"usage": ""
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"delete": "Documento eliminado con éxito.",
|
"delete": "Documento eliminado con éxito.",
|
||||||
|
"edituploaded": "",
|
||||||
"insert": "Documento cargado con éxito.",
|
"insert": "Documento cargado con éxito.",
|
||||||
"updated": ""
|
"updated": ""
|
||||||
}
|
}
|
||||||
@@ -762,6 +770,11 @@
|
|||||||
"unique_employee_number": ""
|
"unique_employee_number": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"exportlogs": {
|
||||||
|
"fields": {
|
||||||
|
"createdat": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"add": "",
|
"add": "",
|
||||||
@@ -785,7 +798,11 @@
|
|||||||
"selectall": "",
|
"selectall": "",
|
||||||
"submit": "",
|
"submit": "",
|
||||||
"submitticket": "",
|
"submitticket": "",
|
||||||
"view": ""
|
"view": "",
|
||||||
|
"viewreleasenotes": ""
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"notfound": ""
|
||||||
},
|
},
|
||||||
"itemtypes": {
|
"itemtypes": {
|
||||||
"contract": "",
|
"contract": "",
|
||||||
@@ -820,6 +837,8 @@
|
|||||||
"monday": "",
|
"monday": "",
|
||||||
"na": "N / A",
|
"na": "N / A",
|
||||||
"no": "",
|
"no": "",
|
||||||
|
"nointernet": "",
|
||||||
|
"nointernet_sub": "",
|
||||||
"none": "",
|
"none": "",
|
||||||
"out": "Afuera",
|
"out": "Afuera",
|
||||||
"password": "",
|
"password": "",
|
||||||
@@ -950,6 +969,7 @@
|
|||||||
},
|
},
|
||||||
"profitcenter_labor": "",
|
"profitcenter_labor": "",
|
||||||
"profitcenter_part": "",
|
"profitcenter_part": "",
|
||||||
|
"prt_dsmk_p": "",
|
||||||
"status": "Estado",
|
"status": "Estado",
|
||||||
"total": "",
|
"total": "",
|
||||||
"unq_seq": "Seq #"
|
"unq_seq": "Seq #"
|
||||||
@@ -1122,6 +1142,7 @@
|
|||||||
"ownr_ea": "Email",
|
"ownr_ea": "Email",
|
||||||
"ownr_ph1": "Teléfono 1",
|
"ownr_ph1": "Teléfono 1",
|
||||||
"paa": "",
|
"paa": "",
|
||||||
|
"pac": "",
|
||||||
"pae": "",
|
"pae": "",
|
||||||
"pag": "",
|
"pag": "",
|
||||||
"pal": "",
|
"pal": "",
|
||||||
@@ -1226,6 +1247,8 @@
|
|||||||
"rate": ""
|
"rate": ""
|
||||||
},
|
},
|
||||||
"ca_gst_all_if_null": "",
|
"ca_gst_all_if_null": "",
|
||||||
|
"calc_repair_days": "",
|
||||||
|
"calc_repair_days_tt": "",
|
||||||
"cards": {
|
"cards": {
|
||||||
"customer": "Información al cliente",
|
"customer": "Información al cliente",
|
||||||
"damage": "Área de Daño",
|
"damage": "Área de Daño",
|
||||||
@@ -1314,6 +1337,7 @@
|
|||||||
"partstotal": "",
|
"partstotal": "",
|
||||||
"totalreturns": ""
|
"totalreturns": ""
|
||||||
},
|
},
|
||||||
|
"prt_dsmk_total": "",
|
||||||
"rates": "Tarifas",
|
"rates": "Tarifas",
|
||||||
"rates_subtotal": "",
|
"rates_subtotal": "",
|
||||||
"reconciliation": {
|
"reconciliation": {
|
||||||
@@ -1398,6 +1422,7 @@
|
|||||||
"entertimeticket": "",
|
"entertimeticket": "",
|
||||||
"export": "",
|
"export": "",
|
||||||
"export-logs": "",
|
"export-logs": "",
|
||||||
|
"help": "",
|
||||||
"home": "Casa",
|
"home": "Casa",
|
||||||
"jobs": "Trabajos",
|
"jobs": "Trabajos",
|
||||||
"owners": "propietarios",
|
"owners": "propietarios",
|
||||||
@@ -1580,6 +1605,7 @@
|
|||||||
"oem_partno": "",
|
"oem_partno": "",
|
||||||
"order_date": "",
|
"order_date": "",
|
||||||
"order_number": "",
|
"order_number": "",
|
||||||
|
"orderedby": "",
|
||||||
"quantity": "",
|
"quantity": "",
|
||||||
"return": "",
|
"return": "",
|
||||||
"status": ""
|
"status": ""
|
||||||
@@ -1662,6 +1688,8 @@
|
|||||||
"state": ""
|
"state": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
|
"noneselected": "",
|
||||||
|
"onenamerequired": "",
|
||||||
"vendorcategory": ""
|
"vendorcategory": ""
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
@@ -1730,7 +1758,10 @@
|
|||||||
"payment_receipt": "",
|
"payment_receipt": "",
|
||||||
"payment_request": "",
|
"payment_request": "",
|
||||||
"payments_by_job": "",
|
"payments_by_job": "",
|
||||||
|
"purchases_by_ro_detail": "",
|
||||||
|
"purchases_by_ro_summary": "",
|
||||||
"qc_sheet": "",
|
"qc_sheet": "",
|
||||||
|
"ro_totals": "",
|
||||||
"ro_with_description": "",
|
"ro_with_description": "",
|
||||||
"supplement_request": "",
|
"supplement_request": "",
|
||||||
"thank_you_ro": "",
|
"thank_you_ro": "",
|
||||||
@@ -1813,6 +1844,9 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"activeshop": ""
|
"activeshop": ""
|
||||||
|
},
|
||||||
|
"successes": {
|
||||||
|
"updated": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"reportcenter": {
|
"reportcenter": {
|
||||||
@@ -1828,6 +1862,7 @@
|
|||||||
"objects": {
|
"objects": {
|
||||||
"appointments": "",
|
"appointments": "",
|
||||||
"bills": "",
|
"bills": "",
|
||||||
|
"exportlogs": "",
|
||||||
"jobs": "",
|
"jobs": "",
|
||||||
"payments": "",
|
"payments": "",
|
||||||
"timetickets": ""
|
"timetickets": ""
|
||||||
@@ -1835,26 +1870,40 @@
|
|||||||
"vendor": ""
|
"vendor": ""
|
||||||
},
|
},
|
||||||
"templates": {
|
"templates": {
|
||||||
|
"attendance_detail": "",
|
||||||
"attendance_employee": "",
|
"attendance_employee": "",
|
||||||
|
"attendance_summary": "",
|
||||||
"credits_not_received_date": "",
|
"credits_not_received_date": "",
|
||||||
"estimator_detail": "",
|
"estimator_detail": "",
|
||||||
"estimator_summary": "",
|
"estimator_summary": "",
|
||||||
|
"export_payables": "",
|
||||||
|
"export_payments": "",
|
||||||
|
"export_receivables": "",
|
||||||
|
"gsr_by_delivery_date": "",
|
||||||
"gsr_by_estimator": "",
|
"gsr_by_estimator": "",
|
||||||
|
"gsr_by_exported_date": "",
|
||||||
|
"gsr_by_ins_co": "",
|
||||||
"gsr_by_make": "",
|
"gsr_by_make": "",
|
||||||
|
"gsr_by_referral": "",
|
||||||
|
"gsr_by_ro": "",
|
||||||
"gsr_labor_only": "",
|
"gsr_labor_only": "",
|
||||||
"hours_sold_detail_closed": "",
|
"hours_sold_detail_closed": "",
|
||||||
"hours_sold_detail_closed_source": "",
|
"hours_sold_detail_closed_ins_co": "",
|
||||||
"hours_sold_detail_open": "",
|
"hours_sold_detail_open": "",
|
||||||
"hours_sold_detail_open_source": "",
|
"hours_sold_detail_open_ins_co": "",
|
||||||
"hours_sold_summary_closed": "",
|
"hours_sold_summary_closed": "",
|
||||||
"hours_sold_summary_closed_source": "",
|
"hours_sold_summary_closed_ins_co": "",
|
||||||
"hours_sold_summary_open": "",
|
"hours_sold_summary_open": "",
|
||||||
"hours_sold_summary_open_source": "",
|
"hours_sold_summary_open_ins_co": "",
|
||||||
"job_costing_ro_date_detail": "",
|
"job_costing_ro_date_detail": "",
|
||||||
"job_costing_ro_date_summary": "",
|
"job_costing_ro_date_summary": "",
|
||||||
"job_costing_ro_estimator": "",
|
"job_costing_ro_estimator": "",
|
||||||
"job_costing_ro_source": "",
|
"job_costing_ro_ins_co": "",
|
||||||
"open_orders": "",
|
"open_orders": "",
|
||||||
|
"open_orders_estimator": "",
|
||||||
|
"open_orders_ins_co": "",
|
||||||
|
"parts_backorder": "",
|
||||||
|
"payments_by_date": "",
|
||||||
"payments_by_date_type": "",
|
"payments_by_date_type": "",
|
||||||
"purchases_by_cost_center_detail": "",
|
"purchases_by_cost_center_detail": "",
|
||||||
"purchases_by_cost_center_summary": "",
|
"purchases_by_cost_center_summary": "",
|
||||||
@@ -1865,11 +1914,15 @@
|
|||||||
"purchases_grouped_by_vendor_detailed": "",
|
"purchases_grouped_by_vendor_detailed": "",
|
||||||
"purchases_grouped_by_vendor_summary": "",
|
"purchases_grouped_by_vendor_summary": "",
|
||||||
"schedule": "",
|
"schedule": "",
|
||||||
"supplement_ratio_source": "",
|
"supplement_ratio_ins_co": "",
|
||||||
|
"thank_you_date": "",
|
||||||
"timetickets": "",
|
"timetickets": "",
|
||||||
"timetickets_employee": "",
|
"timetickets_employee": "",
|
||||||
"timetickets_summary": "",
|
"timetickets_summary": "",
|
||||||
"void_ros": ""
|
"unclaimed_hrs": "",
|
||||||
|
"void_ros": "",
|
||||||
|
"work_in_progress_labour": "",
|
||||||
|
"work_in_progress_payables": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scoreboard": {
|
"scoreboard": {
|
||||||
|
|||||||
@@ -167,6 +167,7 @@
|
|||||||
"exported": ""
|
"exported": ""
|
||||||
},
|
},
|
||||||
"validation": {
|
"validation": {
|
||||||
|
"manualinhouse": "",
|
||||||
"unique_invoice_number": ""
|
"unique_invoice_number": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -218,6 +219,10 @@
|
|||||||
"invoice_federal_tax_rate": "",
|
"invoice_federal_tax_rate": "",
|
||||||
"invoice_local_tax_rate": "",
|
"invoice_local_tax_rate": "",
|
||||||
"invoice_state_tax_rate": "",
|
"invoice_state_tax_rate": "",
|
||||||
|
"jc_hourly_rates": {
|
||||||
|
"mapa": "",
|
||||||
|
"mash": ""
|
||||||
|
},
|
||||||
"lastnumberworkingdays": "",
|
"lastnumberworkingdays": "",
|
||||||
"logo_img_path": "",
|
"logo_img_path": "",
|
||||||
"logo_img_path_height": "",
|
"logo_img_path_height": "",
|
||||||
@@ -683,7 +688,8 @@
|
|||||||
"deleting_cloudinary": "",
|
"deleting_cloudinary": "",
|
||||||
"getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document. {{message}}",
|
"getpresignurl": "Erreur lors de l'obtention de l'URL présignée pour le document. {{message}}",
|
||||||
"insert": "Incapable de télécharger le fichier. {{message}}",
|
"insert": "Incapable de télécharger le fichier. {{message}}",
|
||||||
"nodocuments": "Il n'y a pas de documents."
|
"nodocuments": "Il n'y a pas de documents.",
|
||||||
|
"updating": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"confirmdelete": "",
|
"confirmdelete": "",
|
||||||
@@ -696,10 +702,12 @@
|
|||||||
"upload": "Télécharger",
|
"upload": "Télécharger",
|
||||||
"upload_limitexceeded": "",
|
"upload_limitexceeded": "",
|
||||||
"upload_limitexceeded_title": "",
|
"upload_limitexceeded_title": "",
|
||||||
|
"uploading": "",
|
||||||
"usage": ""
|
"usage": ""
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
"delete": "Le document a bien été supprimé.",
|
"delete": "Le document a bien été supprimé.",
|
||||||
|
"edituploaded": "",
|
||||||
"insert": "Document téléchargé avec succès.",
|
"insert": "Document téléchargé avec succès.",
|
||||||
"updated": ""
|
"updated": ""
|
||||||
}
|
}
|
||||||
@@ -762,6 +770,11 @@
|
|||||||
"unique_employee_number": ""
|
"unique_employee_number": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"exportlogs": {
|
||||||
|
"fields": {
|
||||||
|
"createdat": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"general": {
|
"general": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"add": "",
|
"add": "",
|
||||||
@@ -785,7 +798,11 @@
|
|||||||
"selectall": "",
|
"selectall": "",
|
||||||
"submit": "",
|
"submit": "",
|
||||||
"submitticket": "",
|
"submitticket": "",
|
||||||
"view": ""
|
"view": "",
|
||||||
|
"viewreleasenotes": ""
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"notfound": ""
|
||||||
},
|
},
|
||||||
"itemtypes": {
|
"itemtypes": {
|
||||||
"contract": "",
|
"contract": "",
|
||||||
@@ -820,6 +837,8 @@
|
|||||||
"monday": "",
|
"monday": "",
|
||||||
"na": "N / A",
|
"na": "N / A",
|
||||||
"no": "",
|
"no": "",
|
||||||
|
"nointernet": "",
|
||||||
|
"nointernet_sub": "",
|
||||||
"none": "",
|
"none": "",
|
||||||
"out": "En dehors",
|
"out": "En dehors",
|
||||||
"password": "",
|
"password": "",
|
||||||
@@ -950,6 +969,7 @@
|
|||||||
},
|
},
|
||||||
"profitcenter_labor": "",
|
"profitcenter_labor": "",
|
||||||
"profitcenter_part": "",
|
"profitcenter_part": "",
|
||||||
|
"prt_dsmk_p": "",
|
||||||
"status": "Statut",
|
"status": "Statut",
|
||||||
"total": "",
|
"total": "",
|
||||||
"unq_seq": "Seq #"
|
"unq_seq": "Seq #"
|
||||||
@@ -1122,6 +1142,7 @@
|
|||||||
"ownr_ea": "Email",
|
"ownr_ea": "Email",
|
||||||
"ownr_ph1": "Téléphone 1",
|
"ownr_ph1": "Téléphone 1",
|
||||||
"paa": "",
|
"paa": "",
|
||||||
|
"pac": "",
|
||||||
"pae": "",
|
"pae": "",
|
||||||
"pag": "",
|
"pag": "",
|
||||||
"pal": "",
|
"pal": "",
|
||||||
@@ -1226,6 +1247,8 @@
|
|||||||
"rate": ""
|
"rate": ""
|
||||||
},
|
},
|
||||||
"ca_gst_all_if_null": "",
|
"ca_gst_all_if_null": "",
|
||||||
|
"calc_repair_days": "",
|
||||||
|
"calc_repair_days_tt": "",
|
||||||
"cards": {
|
"cards": {
|
||||||
"customer": "Informations client",
|
"customer": "Informations client",
|
||||||
"damage": "Zone de dommages",
|
"damage": "Zone de dommages",
|
||||||
@@ -1314,6 +1337,7 @@
|
|||||||
"partstotal": "",
|
"partstotal": "",
|
||||||
"totalreturns": ""
|
"totalreturns": ""
|
||||||
},
|
},
|
||||||
|
"prt_dsmk_total": "",
|
||||||
"rates": "Les taux",
|
"rates": "Les taux",
|
||||||
"rates_subtotal": "",
|
"rates_subtotal": "",
|
||||||
"reconciliation": {
|
"reconciliation": {
|
||||||
@@ -1398,6 +1422,7 @@
|
|||||||
"entertimeticket": "",
|
"entertimeticket": "",
|
||||||
"export": "",
|
"export": "",
|
||||||
"export-logs": "",
|
"export-logs": "",
|
||||||
|
"help": "",
|
||||||
"home": "Accueil",
|
"home": "Accueil",
|
||||||
"jobs": "Emplois",
|
"jobs": "Emplois",
|
||||||
"owners": "Propriétaires",
|
"owners": "Propriétaires",
|
||||||
@@ -1580,6 +1605,7 @@
|
|||||||
"oem_partno": "",
|
"oem_partno": "",
|
||||||
"order_date": "",
|
"order_date": "",
|
||||||
"order_number": "",
|
"order_number": "",
|
||||||
|
"orderedby": "",
|
||||||
"quantity": "",
|
"quantity": "",
|
||||||
"return": "",
|
"return": "",
|
||||||
"status": ""
|
"status": ""
|
||||||
@@ -1662,6 +1688,8 @@
|
|||||||
"state": ""
|
"state": ""
|
||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
|
"noneselected": "",
|
||||||
|
"onenamerequired": "",
|
||||||
"vendorcategory": ""
|
"vendorcategory": ""
|
||||||
},
|
},
|
||||||
"successes": {
|
"successes": {
|
||||||
@@ -1730,7 +1758,10 @@
|
|||||||
"payment_receipt": "",
|
"payment_receipt": "",
|
||||||
"payment_request": "",
|
"payment_request": "",
|
||||||
"payments_by_job": "",
|
"payments_by_job": "",
|
||||||
|
"purchases_by_ro_detail": "",
|
||||||
|
"purchases_by_ro_summary": "",
|
||||||
"qc_sheet": "",
|
"qc_sheet": "",
|
||||||
|
"ro_totals": "",
|
||||||
"ro_with_description": "",
|
"ro_with_description": "",
|
||||||
"supplement_request": "",
|
"supplement_request": "",
|
||||||
"thank_you_ro": "",
|
"thank_you_ro": "",
|
||||||
@@ -1813,6 +1844,9 @@
|
|||||||
},
|
},
|
||||||
"labels": {
|
"labels": {
|
||||||
"activeshop": ""
|
"activeshop": ""
|
||||||
|
},
|
||||||
|
"successes": {
|
||||||
|
"updated": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"reportcenter": {
|
"reportcenter": {
|
||||||
@@ -1828,6 +1862,7 @@
|
|||||||
"objects": {
|
"objects": {
|
||||||
"appointments": "",
|
"appointments": "",
|
||||||
"bills": "",
|
"bills": "",
|
||||||
|
"exportlogs": "",
|
||||||
"jobs": "",
|
"jobs": "",
|
||||||
"payments": "",
|
"payments": "",
|
||||||
"timetickets": ""
|
"timetickets": ""
|
||||||
@@ -1835,26 +1870,40 @@
|
|||||||
"vendor": ""
|
"vendor": ""
|
||||||
},
|
},
|
||||||
"templates": {
|
"templates": {
|
||||||
|
"attendance_detail": "",
|
||||||
"attendance_employee": "",
|
"attendance_employee": "",
|
||||||
|
"attendance_summary": "",
|
||||||
"credits_not_received_date": "",
|
"credits_not_received_date": "",
|
||||||
"estimator_detail": "",
|
"estimator_detail": "",
|
||||||
"estimator_summary": "",
|
"estimator_summary": "",
|
||||||
|
"export_payables": "",
|
||||||
|
"export_payments": "",
|
||||||
|
"export_receivables": "",
|
||||||
|
"gsr_by_delivery_date": "",
|
||||||
"gsr_by_estimator": "",
|
"gsr_by_estimator": "",
|
||||||
|
"gsr_by_exported_date": "",
|
||||||
|
"gsr_by_ins_co": "",
|
||||||
"gsr_by_make": "",
|
"gsr_by_make": "",
|
||||||
|
"gsr_by_referral": "",
|
||||||
|
"gsr_by_ro": "",
|
||||||
"gsr_labor_only": "",
|
"gsr_labor_only": "",
|
||||||
"hours_sold_detail_closed": "",
|
"hours_sold_detail_closed": "",
|
||||||
"hours_sold_detail_closed_source": "",
|
"hours_sold_detail_closed_ins_co": "",
|
||||||
"hours_sold_detail_open": "",
|
"hours_sold_detail_open": "",
|
||||||
"hours_sold_detail_open_source": "",
|
"hours_sold_detail_open_ins_co": "",
|
||||||
"hours_sold_summary_closed": "",
|
"hours_sold_summary_closed": "",
|
||||||
"hours_sold_summary_closed_source": "",
|
"hours_sold_summary_closed_ins_co": "",
|
||||||
"hours_sold_summary_open": "",
|
"hours_sold_summary_open": "",
|
||||||
"hours_sold_summary_open_source": "",
|
"hours_sold_summary_open_ins_co": "",
|
||||||
"job_costing_ro_date_detail": "",
|
"job_costing_ro_date_detail": "",
|
||||||
"job_costing_ro_date_summary": "",
|
"job_costing_ro_date_summary": "",
|
||||||
"job_costing_ro_estimator": "",
|
"job_costing_ro_estimator": "",
|
||||||
"job_costing_ro_source": "",
|
"job_costing_ro_ins_co": "",
|
||||||
"open_orders": "",
|
"open_orders": "",
|
||||||
|
"open_orders_estimator": "",
|
||||||
|
"open_orders_ins_co": "",
|
||||||
|
"parts_backorder": "",
|
||||||
|
"payments_by_date": "",
|
||||||
"payments_by_date_type": "",
|
"payments_by_date_type": "",
|
||||||
"purchases_by_cost_center_detail": "",
|
"purchases_by_cost_center_detail": "",
|
||||||
"purchases_by_cost_center_summary": "",
|
"purchases_by_cost_center_summary": "",
|
||||||
@@ -1865,11 +1914,15 @@
|
|||||||
"purchases_grouped_by_vendor_detailed": "",
|
"purchases_grouped_by_vendor_detailed": "",
|
||||||
"purchases_grouped_by_vendor_summary": "",
|
"purchases_grouped_by_vendor_summary": "",
|
||||||
"schedule": "",
|
"schedule": "",
|
||||||
"supplement_ratio_source": "",
|
"supplement_ratio_ins_co": "",
|
||||||
|
"thank_you_date": "",
|
||||||
"timetickets": "",
|
"timetickets": "",
|
||||||
"timetickets_employee": "",
|
"timetickets_employee": "",
|
||||||
"timetickets_summary": "",
|
"timetickets_summary": "",
|
||||||
"void_ros": ""
|
"unclaimed_hrs": "",
|
||||||
|
"void_ros": "",
|
||||||
|
"work_in_progress_labour": "",
|
||||||
|
"work_in_progress_payables": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scoreboard": {
|
"scoreboard": {
|
||||||
|
|||||||
@@ -230,6 +230,14 @@ export const TemplateList = (type, context) => {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
group: "financial",
|
group: "financial",
|
||||||
},
|
},
|
||||||
|
ro_totals: {
|
||||||
|
title: i18n.t("printcenter.jobs.ro_totals"),
|
||||||
|
description: "All Jobs Notes",
|
||||||
|
subject: i18n.t("printcenter.jobs.ro_totals"),
|
||||||
|
key: "ro_totals",
|
||||||
|
disabled: false,
|
||||||
|
group: "financial",
|
||||||
|
},
|
||||||
job_costing_ro: {
|
job_costing_ro: {
|
||||||
title: i18n.t("printcenter.jobs.job_costing_ro"),
|
title: i18n.t("printcenter.jobs.job_costing_ro"),
|
||||||
description: "All Jobs Notes",
|
description: "All Jobs Notes",
|
||||||
@@ -238,6 +246,22 @@ export const TemplateList = (type, context) => {
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
group: "financial",
|
group: "financial",
|
||||||
},
|
},
|
||||||
|
purchases_by_ro_detail: {
|
||||||
|
title: i18n.t("printcenter.jobs.purchases_by_ro_detail"),
|
||||||
|
description: "All Jobs Notes",
|
||||||
|
subject: i18n.t("printcenter.jobs.purchases_by_ro_detail"),
|
||||||
|
key: "purchases_by_ro_detail",
|
||||||
|
disabled: false,
|
||||||
|
group: "financial",
|
||||||
|
},
|
||||||
|
purchases_by_ro_summary: {
|
||||||
|
title: i18n.t("printcenter.jobs.purchases_by_ro_summary"),
|
||||||
|
description: "All Jobs Notes",
|
||||||
|
subject: i18n.t("printcenter.jobs.purchases_by_ro_summary"),
|
||||||
|
key: "purchases_by_ro_summary",
|
||||||
|
disabled: false,
|
||||||
|
group: "financial",
|
||||||
|
},
|
||||||
filing_coversheet_portrait: {
|
filing_coversheet_portrait: {
|
||||||
title: i18n.t("printcenter.jobs.filing_coversheet_portrait"),
|
title: i18n.t("printcenter.jobs.filing_coversheet_portrait"),
|
||||||
description: "All Jobs Notes",
|
description: "All Jobs Notes",
|
||||||
@@ -361,6 +385,16 @@ export const TemplateList = (type, context) => {
|
|||||||
...(!type || type === "csi" ? {} : {}),
|
...(!type || type === "csi" ? {} : {}),
|
||||||
...(!type || type === "report_center"
|
...(!type || type === "report_center"
|
||||||
? {
|
? {
|
||||||
|
payments_by_date: {
|
||||||
|
title: i18n.t("reportcenter.templates.payments_by_date"),
|
||||||
|
subject: i18n.t("reportcenter.templates.payments_by_date"),
|
||||||
|
key: "payments_by_date",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.payments"),
|
||||||
|
field: i18n.t("payments.fields.date"),
|
||||||
|
},
|
||||||
|
},
|
||||||
payments_by_date_type: {
|
payments_by_date_type: {
|
||||||
title: i18n.t("reportcenter.templates.payments_by_date_type"),
|
title: i18n.t("reportcenter.templates.payments_by_date_type"),
|
||||||
subject: i18n.t("reportcenter.templates.payments_by_date_type"),
|
subject: i18n.t("reportcenter.templates.payments_by_date_type"),
|
||||||
@@ -521,7 +555,28 @@ export const TemplateList = (type, context) => {
|
|||||||
idtype: "employee",
|
idtype: "employee",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
},
|
},
|
||||||
|
attendance_detail: {
|
||||||
|
title: i18n.t("reportcenter.templates.attendance_detail"),
|
||||||
|
subject: i18n.t("reportcenter.templates.attendance_detail"),
|
||||||
|
key: "attendance_detail",
|
||||||
|
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||||
|
field: i18n.t("timetickets.fields.date"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
attendance_summary: {
|
||||||
|
title: i18n.t("reportcenter.templates.attendance_summary"),
|
||||||
|
subject: i18n.t("reportcenter.templates.attendance_summary"),
|
||||||
|
key: "attendance_summary",
|
||||||
|
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.timetickets"),
|
||||||
|
field: i18n.t("timetickets.fields.date"),
|
||||||
|
},
|
||||||
|
},
|
||||||
attendance_employee: {
|
attendance_employee: {
|
||||||
title: i18n.t("reportcenter.templates.attendance_employee"),
|
title: i18n.t("reportcenter.templates.attendance_employee"),
|
||||||
subject: i18n.t("reportcenter.templates.attendance_employee"),
|
subject: i18n.t("reportcenter.templates.attendance_employee"),
|
||||||
@@ -559,15 +614,15 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
hours_sold_detail_closed_source: {
|
hours_sold_detail_closed_ins_co: {
|
||||||
title: i18n.t(
|
title: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_detail_closed_source"
|
"reportcenter.templates.hours_sold_detail_closed_ins_co"
|
||||||
),
|
),
|
||||||
description: "",
|
description: "",
|
||||||
subject: i18n.t(
|
subject: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_detail_closed_source"
|
"reportcenter.templates.hours_sold_detail_closed_ins_co"
|
||||||
),
|
),
|
||||||
key: "hours_sold_detail_closed_source",
|
key: "hours_sold_detail_closed_ins_co",
|
||||||
//idtype: "vendor",
|
//idtype: "vendor",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
rangeFilter: {
|
rangeFilter: {
|
||||||
@@ -589,15 +644,15 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
hours_sold_summary_closed_source: {
|
hours_sold_summary_closed_ins_co: {
|
||||||
title: i18n.t(
|
title: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_summary_closed_source"
|
"reportcenter.templates.hours_sold_summary_closed_ins_co"
|
||||||
),
|
),
|
||||||
description: "",
|
description: "",
|
||||||
subject: i18n.t(
|
subject: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_summary_closed_source"
|
"reportcenter.templates.hours_sold_summary_closed_ins_co"
|
||||||
),
|
),
|
||||||
key: "hours_sold_summary_closed_source",
|
key: "hours_sold_summary_closed_ins_co",
|
||||||
//idtype: "vendor",
|
//idtype: "vendor",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
rangeFilter: {
|
rangeFilter: {
|
||||||
@@ -619,15 +674,15 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
hours_sold_detail_open_source: {
|
hours_sold_detail_open_ins_co: {
|
||||||
title: i18n.t(
|
title: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_detail_open_source"
|
"reportcenter.templates.hours_sold_detail_open_ins_co"
|
||||||
),
|
),
|
||||||
description: "",
|
description: "",
|
||||||
subject: i18n.t(
|
subject: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_detail_open_source"
|
"reportcenter.templates.hours_sold_detail_open_ins_co"
|
||||||
),
|
),
|
||||||
key: "hours_sold_detail_open_source",
|
key: "hours_sold_detail_open_ins_co",
|
||||||
//idtype: "vendor",
|
//idtype: "vendor",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
rangeFilter: {
|
rangeFilter: {
|
||||||
@@ -649,15 +704,15 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
hours_sold_summary_open_source: {
|
hours_sold_summary_open_ins_co: {
|
||||||
title: i18n.t(
|
title: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_summary_open_source"
|
"reportcenter.templates.hours_sold_summary_open_ins_co"
|
||||||
),
|
),
|
||||||
description: "",
|
description: "",
|
||||||
subject: i18n.t(
|
subject: i18n.t(
|
||||||
"reportcenter.templates.hours_sold_summary_open_source"
|
"reportcenter.templates.hours_sold_summary_open_ins_co"
|
||||||
),
|
),
|
||||||
key: "hours_sold_summary_open_source",
|
key: "hours_sold_summary_open_ins_co",
|
||||||
//idtype: "vendor",
|
//idtype: "vendor",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
rangeFilter: {
|
rangeFilter: {
|
||||||
@@ -689,11 +744,11 @@ export const TemplateList = (type, context) => {
|
|||||||
field: i18n.t("jobs.fields.date_invoiced"),
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
supplement_ratio_source: {
|
supplement_ratio_ins_co: {
|
||||||
title: i18n.t("reportcenter.templates.supplement_ratio_source"),
|
title: i18n.t("reportcenter.templates.supplement_ratio_ins_co"),
|
||||||
description: "",
|
description: "",
|
||||||
subject: i18n.t("reportcenter.templates.supplement_ratio_source"),
|
subject: i18n.t("reportcenter.templates.supplement_ratio_ins_co"),
|
||||||
key: "supplement_ratio_source",
|
key: "supplement_ratio_ins_co",
|
||||||
//idtype: "vendor",
|
//idtype: "vendor",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
rangeFilter: {
|
rangeFilter: {
|
||||||
@@ -727,11 +782,11 @@ export const TemplateList = (type, context) => {
|
|||||||
field: i18n.t("jobs.fields.date_invoiced"),
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
job_costing_ro_source: {
|
job_costing_ro_ins_co: {
|
||||||
title: i18n.t("reportcenter.templates.job_costing_ro_source"),
|
title: i18n.t("reportcenter.templates.job_costing_ro_ins_co"),
|
||||||
description: "",
|
description: "",
|
||||||
subject: i18n.t("reportcenter.templates.job_costing_ro_source"),
|
subject: i18n.t("reportcenter.templates.job_costing_ro_ins_co"),
|
||||||
key: "job_costing_ro_source",
|
key: "job_costing_ro_ins_co",
|
||||||
//idtype: "vendor",
|
//idtype: "vendor",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
rangeFilter: {
|
rangeFilter: {
|
||||||
@@ -789,6 +844,67 @@ export const TemplateList = (type, context) => {
|
|||||||
field: i18n.t("jobs.fields.date_invoiced"),
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
gsr_by_delivery_date: {
|
||||||
|
title: i18n.t("reportcenter.templates.gsr_by_delivery_date"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.gsr_by_delivery_date"),
|
||||||
|
key: "gsr_by_delivery_date",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.actual_delivery"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
gsr_by_referral: {
|
||||||
|
title: i18n.t("reportcenter.templates.gsr_by_referral"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.gsr_by_referral"),
|
||||||
|
key: "gsr_by_referral",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
gsr_by_ro: {
|
||||||
|
title: i18n.t("reportcenter.templates.gsr_by_ro"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.gsr_by_ro"),
|
||||||
|
key: "gsr_by_ro",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
gsr_by_ins_co: {
|
||||||
|
title: i18n.t("reportcenter.templates.gsr_by_ins_co"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.gsr_by_ins_co"),
|
||||||
|
key: "gsr_by_ins_co",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
gsr_by_exported_date: {
|
||||||
|
title: i18n.t("reportcenter.templates.gsr_by_exported_date"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.gsr_by_exported_date"),
|
||||||
|
key: "gsr_by_exported_date",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_exported"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
gsr_by_estimator: {
|
gsr_by_estimator: {
|
||||||
title: i18n.t("reportcenter.templates.gsr_by_estimator"),
|
title: i18n.t("reportcenter.templates.gsr_by_estimator"),
|
||||||
description: "",
|
description: "",
|
||||||
@@ -825,6 +941,126 @@ export const TemplateList = (type, context) => {
|
|||||||
field: i18n.t("jobs.fields.date_open"),
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
open_orders_estimator: {
|
||||||
|
title: i18n.t("reportcenter.templates.open_orders_estimator"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.open_orders_estimator"),
|
||||||
|
key: "open_orders_estimator",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
open_orders_ins_co: {
|
||||||
|
title: i18n.t("reportcenter.templates.open_orders_ins_co"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.open_orders_ins_co"),
|
||||||
|
key: "open_orders_ins_co",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
export_payables: {
|
||||||
|
title: i18n.t("reportcenter.templates.export_payables"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.export_payables"),
|
||||||
|
key: "export_payables",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.exportlogs"),
|
||||||
|
field: i18n.t("exportlogs.fields.createdat"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
export_payments: {
|
||||||
|
title: i18n.t("reportcenter.templates.export_payments"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.export_payments"),
|
||||||
|
key: "export_payments",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.exportlogs"),
|
||||||
|
field: i18n.t("exportlogs.fields.createdat"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
export_receivables: {
|
||||||
|
title: i18n.t("reportcenter.templates.export_receivables"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.export_receivables"),
|
||||||
|
key: "export_receivables",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.exportlogs"),
|
||||||
|
field: i18n.t("exportlogs.fields.createdat"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
parts_backorder: {
|
||||||
|
title: i18n.t("reportcenter.templates.parts_backorder"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.parts_backorder"),
|
||||||
|
key: "parts_backorder",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.actual_in"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
thank_you_date: {
|
||||||
|
title: i18n.t("reportcenter.templates.thank_you_date"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.thank_you_date"),
|
||||||
|
key: "thank_you_date",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_invoiced"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
unclaimed_hrs: {
|
||||||
|
title: i18n.t("reportcenter.templates.unclaimed_hrs"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.unclaimed_hrs"),
|
||||||
|
key: "unclaimed_hrs",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
work_in_progress_labour: {
|
||||||
|
title: i18n.t("reportcenter.templates.work_in_progress_labour"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.work_in_progress_labour"),
|
||||||
|
key: "work_in_progress_labour",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
work_in_progress_payables: {
|
||||||
|
title: i18n.t("reportcenter.templates.work_in_progress_payables"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.work_in_progress_payables"),
|
||||||
|
key: "work_in_progress_payables",
|
||||||
|
//idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.jobs"),
|
||||||
|
field: i18n.t("jobs.fields.date_open"),
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
...(!type || type === "courtesycarcontract"
|
...(!type || type === "courtesycarcontract"
|
||||||
|
|||||||
@@ -5696,6 +5696,11 @@ exenv@^1.2.2:
|
|||||||
resolved "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz"
|
resolved "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz"
|
||||||
integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=
|
integrity sha1-KueOhdmJQVhnCwPUe+wfA72Ru50=
|
||||||
|
|
||||||
|
exifr@^7.0.0:
|
||||||
|
version "7.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/exifr/-/exifr-7.0.0.tgz#065d54639f2999ac901dd8475db99b4d3f31f11e"
|
||||||
|
integrity sha512-5JRtopcolAfsX4YGcvTkldXyFDC+VPV40DxhSdRvrDr4OJQHtyccNoYl4aRzYBnVVpNueMmenS0KhzLiyNSfEQ==
|
||||||
|
|
||||||
exit@^0.1.2:
|
exit@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz"
|
resolved "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz"
|
||||||
@@ -8297,6 +8302,11 @@ map-visit@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
object-visit "^1.0.0"
|
object-visit "^1.0.0"
|
||||||
|
|
||||||
|
markerjs2@^2.8.1:
|
||||||
|
version "2.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/markerjs2/-/markerjs2-2.8.1.tgz#33c455cc1edd8fa9a5e5b39ed782dcd1b923c917"
|
||||||
|
integrity sha512-M9AflvjOD5aIcBM0HZWW6u1h/NRdzfq73B9ILv1YehF88PeF0tYT5HIsi9PaSJ6EUOR/vWysZN08f3EyDCJixw==
|
||||||
|
|
||||||
material-colors@^1.2.1:
|
material-colors@^1.2.1:
|
||||||
version "1.2.6"
|
version "1.2.6"
|
||||||
resolved "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz"
|
resolved "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
Must set the environment variables using:
|
||||||
|
|
||||||
Must set the environment variables using:
|
firebase functions:config:set auth.graphql_endpoint="https://bodyshop-dev-db.herokuapp.com/v1/graphql" auth.hasura_secret_admin_key="Dev-BodyShopApp!"
|
||||||
|
|
||||||
firebase functions:config:set auth.graphql_endpoint="https://bodyshop-dev-db.herokuapp.com/v1/graphql" auth.hasura_secret_admin_key="Dev-BodyShopAppBySnaptSoftware!"
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
endpoint: https://bodyshop-dev-db.herokuapp.com
|
endpoint: https://bodyshop-dev-db.herokuapp.com
|
||||||
admin_secret: Dev-BodyShopAppBySnaptSoftware!
|
admin_secret: Dev-BodyShopApp!
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."documents" DROP COLUMN "takenat";
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."documents" ADD COLUMN "takenat" timestamptz NULL;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: drop_insert_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
_or:
|
||||||
|
- job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
- bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- billid
|
||||||
|
- bodyshopid
|
||||||
|
- created_at
|
||||||
|
- extension
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
- key
|
||||||
|
- name
|
||||||
|
- size
|
||||||
|
- type
|
||||||
|
- updated_at
|
||||||
|
- uploaded_by
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: create_insert_permission
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: drop_insert_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
_or:
|
||||||
|
- job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
- bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- billid
|
||||||
|
- bodyshopid
|
||||||
|
- created_at
|
||||||
|
- extension
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
- key
|
||||||
|
- name
|
||||||
|
- size
|
||||||
|
- takenat
|
||||||
|
- type
|
||||||
|
- updated_at
|
||||||
|
- uploaded_by
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: create_insert_permission
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: true
|
||||||
|
columns:
|
||||||
|
- billid
|
||||||
|
- bodyshopid
|
||||||
|
- created_at
|
||||||
|
- extension
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
- key
|
||||||
|
- name
|
||||||
|
- size
|
||||||
|
- type
|
||||||
|
- updated_at
|
||||||
|
- uploaded_by
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
_or:
|
||||||
|
- job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
- bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: true
|
||||||
|
columns:
|
||||||
|
- billid
|
||||||
|
- bodyshopid
|
||||||
|
- created_at
|
||||||
|
- extension
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
- key
|
||||||
|
- name
|
||||||
|
- size
|
||||||
|
- takenat
|
||||||
|
- type
|
||||||
|
- updated_at
|
||||||
|
- uploaded_by
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
_or:
|
||||||
|
- job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
- bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: documents
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."bodyshops" ADD CONSTRAINT "bodyshops_autohouseid_key"
|
||||||
|
UNIQUE ("autohouseid");
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."bodyshops" DROP CONSTRAINT "bodyshops_autohouseid_key";
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."bodyshops" DROP COLUMN "jc_hourly_rates";
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."bodyshops" ADD COLUMN "jc_hourly_rates" jsonb NULL
|
||||||
|
DEFAULT jsonb_build_object();
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: false
|
||||||
|
columns:
|
||||||
|
- accountingconfig
|
||||||
|
- address1
|
||||||
|
- address2
|
||||||
|
- appt_alt_transport
|
||||||
|
- appt_colors
|
||||||
|
- appt_length
|
||||||
|
- bill_tax_rates
|
||||||
|
- city
|
||||||
|
- country
|
||||||
|
- created_at
|
||||||
|
- default_adjustment_rate
|
||||||
|
- deliverchecklist
|
||||||
|
- email
|
||||||
|
- enforce_class
|
||||||
|
- enforce_referral
|
||||||
|
- federal_tax_id
|
||||||
|
- id
|
||||||
|
- imexshopid
|
||||||
|
- inhousevendorid
|
||||||
|
- insurance_vendor_id
|
||||||
|
- intakechecklist
|
||||||
|
- jobsizelimit
|
||||||
|
- logo_img_path
|
||||||
|
- md_categories
|
||||||
|
- md_ccc_rates
|
||||||
|
- md_classes
|
||||||
|
- md_hour_split
|
||||||
|
- md_ins_cos
|
||||||
|
- md_labor_rates
|
||||||
|
- md_messaging_presets
|
||||||
|
- md_notes_presets
|
||||||
|
- md_order_statuses
|
||||||
|
- md_parts_locations
|
||||||
|
- md_payment_types
|
||||||
|
- md_rbac
|
||||||
|
- md_referral_sources
|
||||||
|
- md_responsibility_centers
|
||||||
|
- md_ro_statuses
|
||||||
|
- messagingservicesid
|
||||||
|
- phone
|
||||||
|
- prodtargethrs
|
||||||
|
- production_config
|
||||||
|
- region_config
|
||||||
|
- schedule_end_time
|
||||||
|
- schedule_start_time
|
||||||
|
- scoreboard_target
|
||||||
|
- shopname
|
||||||
|
- shoprates
|
||||||
|
- speedprint
|
||||||
|
- ssbuckets
|
||||||
|
- state
|
||||||
|
- state_tax_id
|
||||||
|
- stripe_acct_id
|
||||||
|
- sub_status
|
||||||
|
- target_touchtime
|
||||||
|
- template_header
|
||||||
|
- textid
|
||||||
|
- updated_at
|
||||||
|
- use_fippa
|
||||||
|
- website
|
||||||
|
- workingdays
|
||||||
|
- zip_post
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
associations:
|
||||||
|
user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: drop_select_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
allow_aggregations: false
|
||||||
|
columns:
|
||||||
|
- accountingconfig
|
||||||
|
- address1
|
||||||
|
- address2
|
||||||
|
- appt_alt_transport
|
||||||
|
- appt_colors
|
||||||
|
- appt_length
|
||||||
|
- bill_tax_rates
|
||||||
|
- city
|
||||||
|
- country
|
||||||
|
- created_at
|
||||||
|
- default_adjustment_rate
|
||||||
|
- deliverchecklist
|
||||||
|
- email
|
||||||
|
- enforce_class
|
||||||
|
- enforce_referral
|
||||||
|
- federal_tax_id
|
||||||
|
- id
|
||||||
|
- imexshopid
|
||||||
|
- inhousevendorid
|
||||||
|
- insurance_vendor_id
|
||||||
|
- intakechecklist
|
||||||
|
- jc_hourly_rates
|
||||||
|
- jobsizelimit
|
||||||
|
- logo_img_path
|
||||||
|
- md_categories
|
||||||
|
- md_ccc_rates
|
||||||
|
- md_classes
|
||||||
|
- md_hour_split
|
||||||
|
- md_ins_cos
|
||||||
|
- md_labor_rates
|
||||||
|
- md_messaging_presets
|
||||||
|
- md_notes_presets
|
||||||
|
- md_order_statuses
|
||||||
|
- md_parts_locations
|
||||||
|
- md_payment_types
|
||||||
|
- md_rbac
|
||||||
|
- md_referral_sources
|
||||||
|
- md_responsibility_centers
|
||||||
|
- md_ro_statuses
|
||||||
|
- messagingservicesid
|
||||||
|
- phone
|
||||||
|
- prodtargethrs
|
||||||
|
- production_config
|
||||||
|
- region_config
|
||||||
|
- schedule_end_time
|
||||||
|
- schedule_start_time
|
||||||
|
- scoreboard_target
|
||||||
|
- shopname
|
||||||
|
- shoprates
|
||||||
|
- speedprint
|
||||||
|
- ssbuckets
|
||||||
|
- state
|
||||||
|
- state_tax_id
|
||||||
|
- stripe_acct_id
|
||||||
|
- sub_status
|
||||||
|
- target_touchtime
|
||||||
|
- template_header
|
||||||
|
- textid
|
||||||
|
- updated_at
|
||||||
|
- use_fippa
|
||||||
|
- website
|
||||||
|
- workingdays
|
||||||
|
- zip_post
|
||||||
|
computed_fields: []
|
||||||
|
filter:
|
||||||
|
associations:
|
||||||
|
user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: create_select_permission
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: drop_update_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- accountingconfig
|
||||||
|
- address1
|
||||||
|
- address2
|
||||||
|
- appt_alt_transport
|
||||||
|
- appt_colors
|
||||||
|
- appt_length
|
||||||
|
- bill_tax_rates
|
||||||
|
- city
|
||||||
|
- country
|
||||||
|
- created_at
|
||||||
|
- default_adjustment_rate
|
||||||
|
- deliverchecklist
|
||||||
|
- email
|
||||||
|
- enforce_class
|
||||||
|
- enforce_referral
|
||||||
|
- federal_tax_id
|
||||||
|
- id
|
||||||
|
- inhousevendorid
|
||||||
|
- insurance_vendor_id
|
||||||
|
- intakechecklist
|
||||||
|
- logo_img_path
|
||||||
|
- md_categories
|
||||||
|
- md_ccc_rates
|
||||||
|
- md_classes
|
||||||
|
- md_hour_split
|
||||||
|
- md_ins_cos
|
||||||
|
- md_labor_rates
|
||||||
|
- md_messaging_presets
|
||||||
|
- md_notes_presets
|
||||||
|
- md_order_statuses
|
||||||
|
- md_parts_locations
|
||||||
|
- md_payment_types
|
||||||
|
- md_rbac
|
||||||
|
- md_referral_sources
|
||||||
|
- md_responsibility_centers
|
||||||
|
- md_ro_statuses
|
||||||
|
- phone
|
||||||
|
- prodtargethrs
|
||||||
|
- production_config
|
||||||
|
- schedule_end_time
|
||||||
|
- schedule_start_time
|
||||||
|
- scoreboard_target
|
||||||
|
- shopname
|
||||||
|
- shoprates
|
||||||
|
- speedprint
|
||||||
|
- ssbuckets
|
||||||
|
- state
|
||||||
|
- state_tax_id
|
||||||
|
- target_touchtime
|
||||||
|
- updated_at
|
||||||
|
- use_fippa
|
||||||
|
- website
|
||||||
|
- workingdays
|
||||||
|
- zip_post
|
||||||
|
filter:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: create_update_permission
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: drop_update_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
columns:
|
||||||
|
- accountingconfig
|
||||||
|
- address1
|
||||||
|
- address2
|
||||||
|
- appt_alt_transport
|
||||||
|
- appt_colors
|
||||||
|
- appt_length
|
||||||
|
- bill_tax_rates
|
||||||
|
- city
|
||||||
|
- country
|
||||||
|
- created_at
|
||||||
|
- default_adjustment_rate
|
||||||
|
- deliverchecklist
|
||||||
|
- email
|
||||||
|
- enforce_class
|
||||||
|
- enforce_referral
|
||||||
|
- federal_tax_id
|
||||||
|
- id
|
||||||
|
- inhousevendorid
|
||||||
|
- insurance_vendor_id
|
||||||
|
- intakechecklist
|
||||||
|
- jc_hourly_rates
|
||||||
|
- logo_img_path
|
||||||
|
- md_categories
|
||||||
|
- md_ccc_rates
|
||||||
|
- md_classes
|
||||||
|
- md_hour_split
|
||||||
|
- md_ins_cos
|
||||||
|
- md_labor_rates
|
||||||
|
- md_messaging_presets
|
||||||
|
- md_notes_presets
|
||||||
|
- md_order_statuses
|
||||||
|
- md_parts_locations
|
||||||
|
- md_payment_types
|
||||||
|
- md_rbac
|
||||||
|
- md_referral_sources
|
||||||
|
- md_responsibility_centers
|
||||||
|
- md_ro_statuses
|
||||||
|
- phone
|
||||||
|
- prodtargethrs
|
||||||
|
- production_config
|
||||||
|
- schedule_end_time
|
||||||
|
- schedule_start_time
|
||||||
|
- scoreboard_target
|
||||||
|
- shopname
|
||||||
|
- shoprates
|
||||||
|
- speedprint
|
||||||
|
- ssbuckets
|
||||||
|
- state
|
||||||
|
- state_tax_id
|
||||||
|
- target_touchtime
|
||||||
|
- updated_at
|
||||||
|
- use_fippa
|
||||||
|
- website
|
||||||
|
- workingdays
|
||||||
|
- zip_post
|
||||||
|
filter:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: bodyshops
|
||||||
|
schema: public
|
||||||
|
type: create_update_permission
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."vehicles" ALTER COLUMN "v_vin" SET NOT NULL;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."vehicles" ALTER COLUMN "v_vin" DROP NOT NULL;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE ONLY "public"."joblines" ALTER COLUMN "prt_dsmk_p" DROP DEFAULT;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE ONLY "public"."joblines" ALTER COLUMN "prt_dsmk_p" SET DEFAULT
|
||||||
|
0;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: "update joblines \nset prt_dsmk_p = 0 where joblines.prt_dsmk_p is null;"
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."conversations" DROP COLUMN "archived";
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."conversations" ADD COLUMN "archived" boolean NOT NULL
|
||||||
|
DEFAULT false;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."parts_orders" DROP COLUMN "orderedby";
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: ALTER TABLE "public"."parts_orders" ADD COLUMN "orderedby" text NULL;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: alter table "public"."parts_orders" drop constraint "parts_orders_orderedby_fkey";
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
- args:
|
||||||
|
cascade: false
|
||||||
|
read_only: false
|
||||||
|
sql: |-
|
||||||
|
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;
|
||||||
|
type: run_sql
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: parts_orders
|
||||||
|
schema: public
|
||||||
|
type: drop_insert_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- created_at
|
||||||
|
- deliver_by
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
- order_date
|
||||||
|
- order_number
|
||||||
|
- return
|
||||||
|
- returnfrombill
|
||||||
|
- status
|
||||||
|
- updated_at
|
||||||
|
- user_email
|
||||||
|
- vendorid
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: parts_orders
|
||||||
|
schema: public
|
||||||
|
type: create_insert_permission
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
- args:
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: parts_orders
|
||||||
|
schema: public
|
||||||
|
type: drop_insert_permission
|
||||||
|
- args:
|
||||||
|
permission:
|
||||||
|
check:
|
||||||
|
job:
|
||||||
|
bodyshop:
|
||||||
|
associations:
|
||||||
|
_and:
|
||||||
|
- user:
|
||||||
|
authid:
|
||||||
|
_eq: X-Hasura-User-Id
|
||||||
|
- active:
|
||||||
|
_eq: true
|
||||||
|
columns:
|
||||||
|
- created_at
|
||||||
|
- deliver_by
|
||||||
|
- id
|
||||||
|
- jobid
|
||||||
|
- order_date
|
||||||
|
- order_number
|
||||||
|
- orderedby
|
||||||
|
- return
|
||||||
|
- returnfrombill
|
||||||
|
- status
|
||||||
|
- updated_at
|
||||||
|
- user_email
|
||||||
|
- vendorid
|
||||||
|
set: {}
|
||||||
|
role: user
|
||||||
|
table:
|
||||||
|
name: parts_orders
|
||||||
|
schema: public
|
||||||
|
type: create_insert_permission
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user