Merged in release/2022-07-29 (pull request #552)
release/2022-07-29 Approved-by: Patrick Fic
This commit is contained in:
@@ -40555,6 +40555,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>parts_not_recieved_vendor</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>payments_by_date</name>
|
<name>payments_by_date</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -41535,6 +41556,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>entries</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>jobs</name>
|
<name>jobs</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -4,18 +4,18 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:4000",
|
"proxy": "http://localhost:4000",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.6.6",
|
"@apollo/client": "^3.6.9",
|
||||||
"@asseinfo/react-kanban": "^2.2.0",
|
"@asseinfo/react-kanban": "^2.2.0",
|
||||||
"@craco/craco": "^6.4.3",
|
"@craco/craco": "^6.4.5",
|
||||||
"@fingerprintjs/fingerprintjs": "^3.3.3",
|
"@fingerprintjs/fingerprintjs": "^3.3.3",
|
||||||
"@jsreport/browser-client": "^3.1.0",
|
"@jsreport/browser-client": "^3.1.0",
|
||||||
"@sentry/react": "^7.1.1",
|
"@sentry/react": "^7.7.0",
|
||||||
"@sentry/tracing": "^7.1.1",
|
"@sentry/tracing": "^7.7.0",
|
||||||
"@splitsoftware/splitio-react": "^1.4.1",
|
"@splitsoftware/splitio-react": "^1.6.0",
|
||||||
"@stripe/react-stripe-js": "^1.8.1",
|
"@stripe/react-stripe-js": "^1.9.0",
|
||||||
"@stripe/stripe-js": "^1.31.0",
|
"@stripe/stripe-js": "^1.32.0",
|
||||||
"@tanem/react-nprogress": "^5.0.1",
|
"@tanem/react-nprogress": "^5.0.8",
|
||||||
"antd": "^4.21.0",
|
"antd": "^4.21.7",
|
||||||
"apollo-link-logger": "^2.0.0",
|
"apollo-link-logger": "^2.0.0",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"craco-less": "^1.20.0",
|
"craco-less": "^1.20.0",
|
||||||
@@ -24,33 +24,33 @@
|
|||||||
"enquire-js": "^0.2.1",
|
"enquire-js": "^0.2.1",
|
||||||
"env-cmd": "^10.1.0",
|
"env-cmd": "^10.1.0",
|
||||||
"exifr": "^7.1.3",
|
"exifr": "^7.1.3",
|
||||||
"firebase": "^9.8.2",
|
"firebase": "^9.9.1",
|
||||||
"graphql": "^16.5.0",
|
"graphql": "^16.5.0",
|
||||||
"i18next": "^21.8.9",
|
"i18next": "^21.8.14",
|
||||||
"i18next-browser-languagedetector": "^6.1.4",
|
"i18next-browser-languagedetector": "^6.1.4",
|
||||||
"jsoneditor": "^9.8.0",
|
"jsoneditor": "^9.9.0",
|
||||||
"jsreport-browser-client-dist": "^1.3.0",
|
"jsreport-browser-client-dist": "^1.3.0",
|
||||||
"libphonenumber-js": "^1.10.6",
|
"libphonenumber-js": "^1.10.9",
|
||||||
"logrocket": "^3.0.0",
|
"logrocket": "^3.0.1",
|
||||||
"markerjs2": "^2.21.4",
|
"markerjs2": "^2.22.0",
|
||||||
"moment-business-days": "^1.2.0",
|
"moment-business-days": "^1.2.0",
|
||||||
"moment-timezone": "^0.5.34",
|
"moment-timezone": "^0.5.34",
|
||||||
"normalize-url": "^7.0.3",
|
"normalize-url": "^7.0.3",
|
||||||
"phone": "^3.1.20",
|
"phone": "^3.1.23",
|
||||||
"preval.macro": "^5.0.0",
|
"preval.macro": "^5.0.0",
|
||||||
"prop-types": "^15.8.1",
|
"prop-types": "^15.8.1",
|
||||||
"query-string": "^7.1.1",
|
"query-string": "^7.1.1",
|
||||||
"rc-queue-anim": "^2.0.0",
|
"rc-queue-anim": "^2.0.0",
|
||||||
"rc-scroll-anim": "^2.7.6",
|
"rc-scroll-anim": "^2.7.6",
|
||||||
"react": "^17.0.2",
|
"react": "^17.0.2",
|
||||||
"react-big-calendar": "^0.40.1",
|
"react-big-calendar": "^1.5.0",
|
||||||
"react-color": "^2.19.3",
|
"react-color": "^2.19.3",
|
||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-drag-listview": "^0.2.1",
|
"react-drag-listview": "^0.2.1",
|
||||||
"react-grid-gallery": "^0.5.5",
|
"react-grid-gallery": "^0.5.5",
|
||||||
"react-grid-layout": "^1.3.4",
|
"react-grid-layout": "^1.3.4",
|
||||||
"react-i18next": "^11.17.0",
|
"react-i18next": "^11.18.1",
|
||||||
"react-icons": "^4.4.0",
|
"react-icons": "^4.4.0",
|
||||||
"react-number-format": "^4.9.3",
|
"react-number-format": "^4.9.3",
|
||||||
"react-redux": "^7.2.8",
|
"react-redux": "^7.2.8",
|
||||||
@@ -60,13 +60,13 @@
|
|||||||
"react-sticky": "^6.0.3",
|
"react-sticky": "^6.0.3",
|
||||||
"react-sublime-video": "^0.2.5",
|
"react-sublime-video": "^0.2.5",
|
||||||
"react-virtualized": "^9.22.3",
|
"react-virtualized": "^9.22.3",
|
||||||
"recharts": "^2.1.10",
|
"recharts": "^2.1.12",
|
||||||
"redux": "^4.2.0",
|
"redux": "^4.2.0",
|
||||||
"redux-persist": "^6.0.0",
|
"redux-persist": "^6.0.0",
|
||||||
"redux-saga": "^1.1.3",
|
"redux-saga": "^1.1.3",
|
||||||
"redux-state-sync": "^3.1.2",
|
"redux-state-sync": "^3.1.4",
|
||||||
"reselect": "^4.1.6",
|
"reselect": "^4.1.6",
|
||||||
"sass": "^1.51.0",
|
"sass": "^1.54.0",
|
||||||
"socket.io-client": "^4.5.1",
|
"socket.io-client": "^4.5.1",
|
||||||
"styled-components": "^5.3.5",
|
"styled-components": "^5.3.5",
|
||||||
"subscriptions-transport-ws": "^0.11.0",
|
"subscriptions-transport-ws": "^0.11.0",
|
||||||
@@ -119,9 +119,9 @@
|
|||||||
"react-error-overlay": "6.0.9"
|
"react-error-overlay": "6.0.9"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sentry/webpack-plugin": "^1.18.9",
|
"@sentry/webpack-plugin": "^1.19.0",
|
||||||
"@testing-library/cypress": "^8.0.2",
|
"@testing-library/cypress": "^8.0.3",
|
||||||
"cypress": "^9.6.1",
|
"cypress": "^10.3.1",
|
||||||
"eslint-plugin-cypress": "^2.12.1",
|
"eslint-plugin-cypress": "^2.12.1",
|
||||||
"react-error-overlay": "6.0.11",
|
"react-error-overlay": "6.0.11",
|
||||||
"redux-logger": "^3.0.6",
|
"redux-logger": "^3.0.6",
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ const BillLineSearchSelect = (
|
|||||||
option.oem_partno
|
option.oem_partno
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(inputValue.toLowerCase())) ||
|
.includes(inputValue.toLowerCase())) ||
|
||||||
|
(option.alt_partno &&
|
||||||
|
option.alt_partno
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(inputValue.toLowerCase())) ||
|
||||||
(option.act_price &&
|
(option.act_price &&
|
||||||
option.act_price.toString().startsWith(inputValue.toString()))
|
option.act_price.toString().startsWith(inputValue.toString()))
|
||||||
);
|
);
|
||||||
@@ -48,14 +52,17 @@ const BillLineSearchSelect = (
|
|||||||
line_desc={item.line_desc}
|
line_desc={item.line_desc}
|
||||||
part_qty={item.part_qty}
|
part_qty={item.part_qty}
|
||||||
oem_partno={item.oem_partno}
|
oem_partno={item.oem_partno}
|
||||||
|
alt_partno={item.alt_partno}
|
||||||
act_price={item.act_price}
|
act_price={item.act_price}
|
||||||
style={{
|
style={{
|
||||||
...(item.removed ? { textDecoration: "line-through" } : {}),
|
...(item.removed ? { textDecoration: "line-through" } : {}),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span>{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
<span>
|
||||||
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
||||||
}`}</span>
|
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
||||||
|
}${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim()}
|
||||||
|
</span>
|
||||||
<span style={{ float: "right", paddingleft: "1rem" }}>
|
<span style={{ float: "right", paddingleft: "1rem" }}>
|
||||||
{item.act_price
|
{item.act_price
|
||||||
? `$${item.act_price && item.act_price.toFixed(2)}`
|
? `$${item.act_price && item.act_price.toFixed(2)}`
|
||||||
|
|||||||
@@ -45,9 +45,11 @@ export const GetSupplementDelta = async (client, jobId, newLines) => {
|
|||||||
return acc + generateUpdateQuery(value, idx);
|
return acc + generateUpdateQuery(value, idx);
|
||||||
}, "");
|
}, "");
|
||||||
|
|
||||||
const removeQueries = existingLines.reduce((acc, value, idx) => {
|
const removeQueries = existingLines
|
||||||
return acc + generateRemoveQuery(value, idx);
|
.filter((l) => !l.manual_line)
|
||||||
}, "");
|
.reduce((acc, value, idx) => {
|
||||||
|
return acc + generateRemoveQuery(value, idx);
|
||||||
|
}, "");
|
||||||
console.log(insertQueries, updateQueries, removeQueries);
|
console.log(insertQueries, updateQueries, removeQueries);
|
||||||
|
|
||||||
if ((insertQueries + updateQueries + removeQueries).trim() === "") {
|
if ((insertQueries + updateQueries + removeQueries).trim() === "") {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Card, Col, Row, Space, Tag } from "antd";
|
|
||||||
import {
|
import {
|
||||||
WarningFilled,
|
|
||||||
ExclamationCircleFilled,
|
ExclamationCircleFilled,
|
||||||
PauseCircleOutlined,
|
PauseCircleOutlined,
|
||||||
|
WarningFilled,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import React, { useMemo } from "react";
|
import { Card, Col, Row, Space, Tag } from "antd";
|
||||||
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
@@ -13,17 +13,17 @@ 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 ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
|
||||||
import DataLabel from "../data-label/data-label.component";
|
import DataLabel from "../data-label/data-label.component";
|
||||||
import JobAltTransportChange from "../job-at-change/job-at-change.component";
|
import JobAltTransportChange from "../job-at-change/job-at-change.component";
|
||||||
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
|
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
|
||||||
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
|
|
||||||
import "./jobs-detail-header.styles.scss";
|
|
||||||
import JobsRelatedRos from "../jobs-related-ros/jobs-related-ros.component";
|
import JobsRelatedRos from "../jobs-related-ros/jobs-related-ros.component";
|
||||||
import { DateTimeFormatter } from "../../utils/DateFormatter";
|
|
||||||
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
|
||||||
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
|
||||||
|
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
|
||||||
|
import ProductionListColumnProductionNote from "../production-list-columns/production-list-columns.productionnote.component";
|
||||||
import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component";
|
import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component";
|
||||||
|
import "./jobs-detail-header.styles.scss";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
jobRO: selectJobReadOnly,
|
jobRO: selectJobReadOnly,
|
||||||
@@ -56,12 +56,6 @@ const colSpan = {
|
|||||||
export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const jobInPostProduction = useMemo(() => {
|
|
||||||
return bodyshop.md_ro_statuses.post_production_statuses.includes(
|
|
||||||
job.status
|
|
||||||
);
|
|
||||||
}, [job.status, bodyshop.md_ro_statuses.post_production_statuses]);
|
|
||||||
|
|
||||||
const vehicleTitle = `${job.v_model_yr || ""} ${job.v_color || ""}
|
const vehicleTitle = `${job.v_model_yr || ""} ${job.v_color || ""}
|
||||||
${job.v_make_desc || ""}
|
${job.v_make_desc || ""}
|
||||||
${job.v_model_desc || ""}`.trim();
|
${job.v_model_desc || ""}`.trim();
|
||||||
@@ -129,11 +123,10 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
</DataLabel>
|
</DataLabel>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{(job.inproduction || jobInPostProduction) && (
|
<DataLabel label={t("jobs.fields.production_vars.note")}>
|
||||||
<DataLabel label={t("jobs.fields.production_vars.note")}>
|
<ProductionListColumnProductionNote record={job} />
|
||||||
<ProductionListColumnProductionNote record={job} />
|
</DataLabel>
|
||||||
</DataLabel>
|
|
||||||
)}
|
|
||||||
<Space>
|
<Space>
|
||||||
{job.special_coverage_policy && (
|
{job.special_coverage_policy && (
|
||||||
<Tag color="tomato">
|
<Tag color="tomato">
|
||||||
|
|||||||
@@ -6,12 +6,17 @@ export const CalculateAllocationsTotals = (
|
|||||||
timetickets,
|
timetickets,
|
||||||
adjustments = []
|
adjustments = []
|
||||||
) => {
|
) => {
|
||||||
|
console.log(
|
||||||
|
"🚀 ~ file: labor-allocations-table.utility.js ~ line 9 ~ adjustments",
|
||||||
|
adjustments
|
||||||
|
);
|
||||||
const responsibilitycenters = bodyshop.md_responsibility_centers;
|
const responsibilitycenters = bodyshop.md_responsibility_centers;
|
||||||
const jobCodes = joblines.map((item) => item.mod_lbr_ty);
|
const jobCodes = joblines.map((item) => item.mod_lbr_ty);
|
||||||
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
|
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
|
||||||
const ticketCodes = timetickets.map((item) => item.ciecacode);
|
const ticketCodes = timetickets.map((item) => item.ciecacode);
|
||||||
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
|
//.filter((value, index, self) => self.indexOf(value) === index && !!value);
|
||||||
const allCodes = [...jobCodes, ...ticketCodes].filter(
|
const adjustmentCodes = Object.keys(adjustments);
|
||||||
|
const allCodes = [...jobCodes, ...ticketCodes, ...adjustmentCodes].filter(
|
||||||
(value, index, self) => self.indexOf(value) === index && !!value
|
(value, index, self) => self.indexOf(value) === index && !!value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
|
import { useQuery } from "@apollo/client";
|
||||||
|
import { Button, Card, Input, Modal, Space, Table, Typography } from "antd";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Dropdown, Button, Table, Space, Card, Input } from "antd";
|
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import ScoreboardRemoveButton from "../scoreboard-remove-button/scorebard-remove-button.component";
|
import { QUERY_SCOREBOARD_PAGINATED } from "../../graphql/scoreboard.queries";
|
||||||
import { DateFormatter } from "../../utils/DateFormatter";
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
import ScoreboardEntryEdit from "../scoreboard-entry-edit/scoreboard-entry-edit.component";
|
import AlertComponent from "../alert/alert.component";
|
||||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||||
|
import ScoreboardEntryEdit from "../scoreboard-entry-edit/scoreboard-entry-edit.component";
|
||||||
|
import ScoreboardRemoveButton from "../scoreboard-remove-button/scorebard-remove-button.component";
|
||||||
|
import { SyncOutlined } from "@ant-design/icons";
|
||||||
export default function ScoreboardJobsList({ scoreBoardlist }) {
|
export default function ScoreboardJobsList({ scoreBoardlist }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [searchText, setSearchText] = useState("");
|
const [state, setState] = useState({
|
||||||
|
visible: false,
|
||||||
|
search: "",
|
||||||
|
current: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
});
|
||||||
|
|
||||||
const jobs = scoreBoardlist
|
const { loading, error, data, refetch } = useQuery(
|
||||||
? searchText === ""
|
QUERY_SCOREBOARD_PAGINATED,
|
||||||
? scoreBoardlist
|
{
|
||||||
: scoreBoardlist.filter(
|
fetchPolicy: "network-only",
|
||||||
(sb) =>
|
nextFetchPolicy: "network-only",
|
||||||
(sb.job.ro_number || "")
|
skip: !state.visible,
|
||||||
.toString()
|
variables: {
|
||||||
.toLowerCase()
|
search: state.search !== "" ? `%${state.search}%` : null,
|
||||||
.includes(searchText.toLowerCase()) ||
|
offset: state.current ? (state.current - 1) * state.pageSize : 0,
|
||||||
(sb.job.ownr_co_nm || "")
|
limit: state.pageSize,
|
||||||
.toLowerCase()
|
order: [
|
||||||
.includes(searchText.toLowerCase()) ||
|
{
|
||||||
(sb.job.ownr_fn || "")
|
date: "desc",
|
||||||
.toLowerCase()
|
},
|
||||||
.includes(searchText.toLowerCase()) ||
|
],
|
||||||
(sb.job.ownr_ln || "")
|
},
|
||||||
.toLowerCase()
|
}
|
||||||
.includes(searchText.toLowerCase()) ||
|
);
|
||||||
(sb.job.v_model_desc || "")
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(searchText.toLowerCase()) ||
|
|
||||||
(sb.job.v_make_desc || "")
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(searchText.toLowerCase())
|
|
||||||
)
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
@@ -97,35 +97,69 @@ export default function ScoreboardJobsList({ scoreBoardlist }) {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const overlay = (
|
|
||||||
<Card
|
|
||||||
style={{ maxWidth: "90vw", padding: "1rem" }}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
extra={
|
|
||||||
<Input.Search
|
|
||||||
placeholder={t("general.labels.search")}
|
|
||||||
onChange={(e) => {
|
|
||||||
setSearchText(e.target.value);
|
|
||||||
}}
|
|
||||||
value={searchText}
|
|
||||||
enterButton
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Table
|
|
||||||
pagination={false}
|
|
||||||
columns={columns}
|
|
||||||
rowKey="id"
|
|
||||||
dataSource={jobs}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown trigger={["click"]} overlay={overlay}>
|
<>
|
||||||
<Button>Jobs</Button>
|
<Modal
|
||||||
</Dropdown>
|
visible={state.visible}
|
||||||
|
destroyOnClose
|
||||||
|
width="80%"
|
||||||
|
cancelButtonProps={{ style: { display: "none" } }}
|
||||||
|
onCancel={() =>
|
||||||
|
setState((state) => ({
|
||||||
|
...state,
|
||||||
|
visible: false,
|
||||||
|
current: 1,
|
||||||
|
search: "",
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{error && (
|
||||||
|
<AlertComponent type="error" message={JSON.stringify(error)} />
|
||||||
|
)}
|
||||||
|
<Card
|
||||||
|
extra={
|
||||||
|
<Space align="middle" wrap>
|
||||||
|
<Button onClick={() => refetch()}>
|
||||||
|
<SyncOutlined />
|
||||||
|
</Button>
|
||||||
|
<Typography.Title level={4}>
|
||||||
|
{t("general.labels.searchresults", { search: state.search })}
|
||||||
|
</Typography.Title>
|
||||||
|
<Input.Search
|
||||||
|
placeholder={t("jobs.fields.ro_number")}
|
||||||
|
allowClear
|
||||||
|
onSearch={(value) => {
|
||||||
|
setState((state) => ({ ...state, search: value }));
|
||||||
|
}}
|
||||||
|
//value={state.search}
|
||||||
|
enterButton
|
||||||
|
/>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
dataSource={data ? data.scoreboard : []}
|
||||||
|
loading={loading}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
onChange={(tableArgs) =>
|
||||||
|
setState((state) => ({ ...state, ...tableArgs }))
|
||||||
|
}
|
||||||
|
pagination={{
|
||||||
|
position: "top",
|
||||||
|
pageSize: state.pageSize || 10,
|
||||||
|
current: state.current || 1,
|
||||||
|
total: data ? data.scoreboard_aggregate.aggregate.count : 0,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Card>
|
||||||
|
</Modal>
|
||||||
|
<Button
|
||||||
|
onClick={() => setState((state) => ({ ...state, visible: true }))}
|
||||||
|
>
|
||||||
|
{t("scoreboard.labels.entries")}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ export default function ScoreboardRemoveButton({ scoreboardId }) {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
const result = await deleteScoreboardEntry({
|
const result = await deleteScoreboardEntry({
|
||||||
variables: { sbId: scoreboardId },
|
variables: { sbId: scoreboardId },
|
||||||
|
awaitRefetchQueries: true,
|
||||||
|
refetchQueries: ["QUERY_SCOREBOARD_PAGINATED"],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!!result.errors) {
|
if (!!result.errors) {
|
||||||
|
|||||||
@@ -185,8 +185,8 @@ export default function ScoreboardTimeTickets() {
|
|||||||
ret.employees[ticket.employee.employee_number].totalOverPeriod +
|
ret.employees[ticket.employee.employee_number].totalOverPeriod +
|
||||||
ticket.productivehrs;
|
ticket.productivehrs;
|
||||||
ret.employees[ticket.employee.employee_number].actualTotalOverPeriod =
|
ret.employees[ticket.employee.employee_number].actualTotalOverPeriod =
|
||||||
ret.employees[ticket.employee.employee_number].actualTotalOverPeriod +
|
ret.employees[ticket.employee.employee_number]
|
||||||
(ticket.actualhrs || 0);
|
.actualTotalOverPeriod + (ticket.actualhrs || 0);
|
||||||
|
|
||||||
if (!totals.employees[ticket.employee.employee_number])
|
if (!totals.employees[ticket.employee.employee_number])
|
||||||
totals.employees[ticket.employee.employee_number] = {
|
totals.employees[ticket.employee.employee_number] = {
|
||||||
@@ -236,8 +236,6 @@ export default function ScoreboardTimeTickets() {
|
|||||||
};
|
};
|
||||||
}, [fixedPeriods, data, startDate, endDate]);
|
}, [fixedPeriods, data, startDate, endDate]);
|
||||||
|
|
||||||
console.log(calculatedData);
|
|
||||||
|
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||||
if (loading) return <LoadingSpinner />;
|
if (loading) return <LoadingSpinner />;
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export const GET_ALL_JOBLINES_BY_PK = gql`
|
|||||||
notes
|
notes
|
||||||
location
|
location
|
||||||
tax_part
|
tax_part
|
||||||
|
manual_line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -197,6 +198,7 @@ export const GET_JOB_LINES_TO_ENTER_BILL = gql`
|
|||||||
line_desc
|
line_desc
|
||||||
part_type
|
part_type
|
||||||
oem_partno
|
oem_partno
|
||||||
|
alt_partno
|
||||||
db_price
|
db_price
|
||||||
act_price
|
act_price
|
||||||
part_qty
|
part_qty
|
||||||
@@ -206,6 +208,7 @@ export const GET_JOB_LINES_TO_ENTER_BILL = gql`
|
|||||||
lbr_op
|
lbr_op
|
||||||
lbr_amt
|
lbr_amt
|
||||||
op_code_desc
|
op_code_desc
|
||||||
|
alt_partno
|
||||||
}
|
}
|
||||||
jobs_by_pk(id: $id) {
|
jobs_by_pk(id: $id) {
|
||||||
id
|
id
|
||||||
|
|||||||
@@ -88,3 +88,41 @@ export const GET_BLOCKED_DAYS = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const QUERY_SCOREBOARD_PAGINATED = gql`
|
||||||
|
query QUERY_SCOREBOARD_PAGINATED(
|
||||||
|
$search: String
|
||||||
|
$offset: Int
|
||||||
|
$limit: Int
|
||||||
|
$order: [scoreboard_order_by!]
|
||||||
|
) {
|
||||||
|
scoreboard(
|
||||||
|
where: { job: { ro_number: { _ilike: $search } } }
|
||||||
|
offset: $offset
|
||||||
|
limit: $limit
|
||||||
|
order_by: $order
|
||||||
|
) {
|
||||||
|
id
|
||||||
|
jobid
|
||||||
|
job {
|
||||||
|
id
|
||||||
|
ro_number
|
||||||
|
invoice_date
|
||||||
|
v_make_desc
|
||||||
|
v_model_desc
|
||||||
|
v_model_yr
|
||||||
|
ownr_fn
|
||||||
|
ownr_ln
|
||||||
|
ownr_co_nm
|
||||||
|
}
|
||||||
|
date
|
||||||
|
bodyhrs
|
||||||
|
painthrs
|
||||||
|
}
|
||||||
|
scoreboard_aggregate(where: { job: { ro_number: { _ilike: $search } } }) {
|
||||||
|
aggregate {
|
||||||
|
count(distinct: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|||||||
@@ -2406,6 +2406,7 @@
|
|||||||
"open_orders_status": "Open Orders by Status",
|
"open_orders_status": "Open Orders by Status",
|
||||||
"parts_backorder": "IOU Parts List",
|
"parts_backorder": "IOU Parts List",
|
||||||
"parts_not_recieved": "Parts Not Received",
|
"parts_not_recieved": "Parts Not Received",
|
||||||
|
"parts_not_recieved_vendor": "Parts Not Received by Vendor",
|
||||||
"payments_by_date": "Payments by Date",
|
"payments_by_date": "Payments by Date",
|
||||||
"payments_by_date_type": "Payments by Date and Type",
|
"payments_by_date_type": "Payments by Date and Type",
|
||||||
"production_by_category": "Production by Category",
|
"production_by_category": "Production by Category",
|
||||||
@@ -2465,6 +2466,7 @@
|
|||||||
"dailyactual": "Actual (D)",
|
"dailyactual": "Actual (D)",
|
||||||
"dailytarget": "Daily",
|
"dailytarget": "Daily",
|
||||||
"efficiencyoverperiod": "Efficiency over Selected Dates",
|
"efficiencyoverperiod": "Efficiency over Selected Dates",
|
||||||
|
"entries": "Scoreboard Entries",
|
||||||
"jobs": "Jobs",
|
"jobs": "Jobs",
|
||||||
"lastmonth": "Last Month",
|
"lastmonth": "Last Month",
|
||||||
"lastweek": "Last Week",
|
"lastweek": "Last Week",
|
||||||
|
|||||||
@@ -2406,6 +2406,7 @@
|
|||||||
"open_orders_status": "",
|
"open_orders_status": "",
|
||||||
"parts_backorder": "",
|
"parts_backorder": "",
|
||||||
"parts_not_recieved": "",
|
"parts_not_recieved": "",
|
||||||
|
"parts_not_recieved_vendor": "",
|
||||||
"payments_by_date": "",
|
"payments_by_date": "",
|
||||||
"payments_by_date_type": "",
|
"payments_by_date_type": "",
|
||||||
"production_by_category": "",
|
"production_by_category": "",
|
||||||
@@ -2465,6 +2466,7 @@
|
|||||||
"dailyactual": "",
|
"dailyactual": "",
|
||||||
"dailytarget": "",
|
"dailytarget": "",
|
||||||
"efficiencyoverperiod": "",
|
"efficiencyoverperiod": "",
|
||||||
|
"entries": "",
|
||||||
"jobs": "",
|
"jobs": "",
|
||||||
"lastmonth": "",
|
"lastmonth": "",
|
||||||
"lastweek": "",
|
"lastweek": "",
|
||||||
|
|||||||
@@ -2406,6 +2406,7 @@
|
|||||||
"open_orders_status": "",
|
"open_orders_status": "",
|
||||||
"parts_backorder": "",
|
"parts_backorder": "",
|
||||||
"parts_not_recieved": "",
|
"parts_not_recieved": "",
|
||||||
|
"parts_not_recieved_vendor": "",
|
||||||
"payments_by_date": "",
|
"payments_by_date": "",
|
||||||
"payments_by_date_type": "",
|
"payments_by_date_type": "",
|
||||||
"production_by_category": "",
|
"production_by_category": "",
|
||||||
@@ -2465,6 +2466,7 @@
|
|||||||
"dailyactual": "",
|
"dailyactual": "",
|
||||||
"dailytarget": "",
|
"dailytarget": "",
|
||||||
"efficiencyoverperiod": "",
|
"efficiencyoverperiod": "",
|
||||||
|
"entries": "",
|
||||||
"jobs": "",
|
"jobs": "",
|
||||||
"lastmonth": "",
|
"lastmonth": "",
|
||||||
"lastweek": "",
|
"lastweek": "",
|
||||||
|
|||||||
@@ -1448,6 +1448,19 @@ export const TemplateList = (type, context) => {
|
|||||||
},
|
},
|
||||||
group: "purchases",
|
group: "purchases",
|
||||||
},
|
},
|
||||||
|
parts_not_recieved_vendor: {
|
||||||
|
title: i18n.t("reportcenter.templates.parts_not_recieved_vendor"),
|
||||||
|
description: "",
|
||||||
|
subject: i18n.t("reportcenter.templates.parts_not_recieved_vendor"),
|
||||||
|
key: "parts_not_recieved_vendor",
|
||||||
|
idtype: "vendor",
|
||||||
|
disabled: false,
|
||||||
|
rangeFilter: {
|
||||||
|
object: i18n.t("reportcenter.labels.objects.parts_orders"),
|
||||||
|
field: i18n.t("parts_orders.fields.order_date"),
|
||||||
|
},
|
||||||
|
group: "purchases",
|
||||||
|
},
|
||||||
scoreboard_detail: {
|
scoreboard_detail: {
|
||||||
title: i18n.t("reportcenter.templates.scoreboard_detail"),
|
title: i18n.t("reportcenter.templates.scoreboard_detail"),
|
||||||
description: "",
|
description: "",
|
||||||
|
|||||||
5348
client/yarn.lock
5348
client/yarn.lock
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
@@ -17,11 +17,11 @@
|
|||||||
"start": "node server.js"
|
"start": "node server.js"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"aws-sdk": "^2.1136.0",
|
"aws-sdk": "^2.1181.0",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"bluebird": "^3.7.2",
|
"bluebird": "^3.7.2",
|
||||||
"body-parser": "^1.20.0",
|
"body-parser": "^1.20.0",
|
||||||
"cloudinary": "^1.30.0",
|
"cloudinary": "^1.30.1",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"cors": "2.8.5",
|
"cors": "2.8.5",
|
||||||
@@ -29,35 +29,33 @@
|
|||||||
"dinero.js": "^1.9.1",
|
"dinero.js": "^1.9.1",
|
||||||
"dotenv": "16.0.1",
|
"dotenv": "16.0.1",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
"firebase-admin": "^10.2.0",
|
"firebase-admin": "^11.0.0",
|
||||||
"graphql": "^16.5.0",
|
"graphql": "^16.5.0",
|
||||||
"graphql-request": "^4.2.0",
|
"graphql-request": "^4.2.0",
|
||||||
"graylog2": "^0.2.1",
|
"graylog2": "^0.2.1",
|
||||||
"inline-css": "^3.0.0",
|
"inline-css": "^4.0.1",
|
||||||
"intuit-oauth": "^4.0.0",
|
"intuit-oauth": "^4.0.0",
|
||||||
"json-2-csv": "^3.17.1",
|
"json-2-csv": "^3.17.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.4",
|
||||||
"moment-timezone": "^0.5.34",
|
"moment-timezone": "^0.5.34",
|
||||||
"multer": "^1.4.4",
|
"multer": "^1.4.5-lts.1",
|
||||||
"node-mailjet": "^3.4.1",
|
"node-mailjet": "^5.1.0",
|
||||||
"node-quickbooks": "^2.0.39",
|
"node-quickbooks": "^2.0.39",
|
||||||
"nodemailer": "^6.7.5",
|
"nodemailer": "^6.7.7",
|
||||||
"phone": "^3.1.17",
|
"phone": "^3.1.23",
|
||||||
"query-string": "^7.1.1",
|
"query-string": "^7.1.1",
|
||||||
"soap": "^0.43.0",
|
"soap": "^0.45.0",
|
||||||
"socket.io": "^4.5.0",
|
"socket.io": "^4.5.0",
|
||||||
"ssh2-sftp-client": "^8.0.0",
|
"ssh2-sftp-client": "^9.0.2",
|
||||||
"stripe": "^9.1.0",
|
"stripe": "^9.15.0",
|
||||||
"twilio": "^3.77.0",
|
"twilio": "^3.80.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"xml2js": "^0.4.23",
|
"xml2js": "^0.4.23",
|
||||||
"xmlbuilder2": "^3.0.2"
|
"xmlbuilder2": "^3.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^6.3.0",
|
"concurrently": "^7.3.0",
|
||||||
"eslint": "^7.31.0",
|
|
||||||
"eslint-plugin-promise": "^5.1.0",
|
|
||||||
"source-map-explorer": "^2.5.2"
|
"source-map-explorer": "^2.5.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
12
server.js
12
server.js
@@ -172,6 +172,18 @@ app.post(
|
|||||||
fb.validateAdmin,
|
fb.validateAdmin,
|
||||||
adm.createShop
|
adm.createShop
|
||||||
);
|
);
|
||||||
|
app.post(
|
||||||
|
"/adm/updateshop",
|
||||||
|
fb.validateFirebaseIdToken,
|
||||||
|
fb.validateAdmin,
|
||||||
|
adm.updateShop
|
||||||
|
);
|
||||||
|
app.post(
|
||||||
|
"/adm/updatecounter",
|
||||||
|
fb.validateFirebaseIdToken,
|
||||||
|
fb.validateAdmin,
|
||||||
|
adm.updateCounter
|
||||||
|
);
|
||||||
|
|
||||||
//Stripe Processing
|
//Stripe Processing
|
||||||
var stripe = require("./server/stripe/payment");
|
var stripe = require("./server/stripe/payment");
|
||||||
|
|||||||
@@ -66,3 +66,55 @@ exports.createShop = async (req, res) => {
|
|||||||
res.status(500).json(error);
|
res.status(500).json(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
exports.updateCounter = async (req, res) => {
|
||||||
|
logger.log("admin-update-counter", "ADMIN", req.user.email, null, {
|
||||||
|
request: req.body,
|
||||||
|
ioadmin: true,
|
||||||
|
});
|
||||||
|
const { id, counter } = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await client.request(
|
||||||
|
`mutation UPDATE_COUNTER($id: uuid!, $counter: counters_set_input!) {
|
||||||
|
update_counters_by_pk(pk_columns: { id: $id }, _set: $counter) {
|
||||||
|
id
|
||||||
|
countertype
|
||||||
|
count
|
||||||
|
prefix
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
counter,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.updateShop = async (req, res) => {
|
||||||
|
logger.log("admin-update-shop", "ADMIN", req.user.email, null, {
|
||||||
|
request: req.body,
|
||||||
|
ioadmin: true,
|
||||||
|
});
|
||||||
|
const { id, bodyshop } = req.body;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await client.request(
|
||||||
|
`mutation UPDATE_BODYSHOP($id: uuid!, $bodyshop: bodyshops_set_input!) {
|
||||||
|
update_bodyshops_by_pk(pk_columns: { id: $id }, _set: $bodyshop) {
|
||||||
|
id
|
||||||
|
|
||||||
|
}
|
||||||
|
}`,
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
bodyshop,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
res.json(result);
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user