@@ -2354,6 +2354,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>is_credit_memo_short</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>local_tax_rate</name>
|
<name>local_tax_rate</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -26589,6 +26610,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>parts_received</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>parts_tax_rates</name>
|
<name>parts_tax_rates</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -31189,6 +31231,37 @@
|
|||||||
</folder_node>
|
</folder_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>owner</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>labels</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>noownerinfo</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
<name>owners</name>
|
<name>owners</name>
|
||||||
<children>
|
<children>
|
||||||
@@ -36508,6 +36581,58 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>bodyshop</name>
|
||||||
|
<children>
|
||||||
|
<folder_node>
|
||||||
|
<name>labels</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>qbo_departmentid</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>qbo_usa</name>
|
||||||
|
<definition_loaded>false</definition_loaded>
|
||||||
|
<description></description>
|
||||||
|
<comment></comment>
|
||||||
|
<default_text></default_text>
|
||||||
|
<translations>
|
||||||
|
<translation>
|
||||||
|
<language>en-US</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>es-MX</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
<translation>
|
||||||
|
<language>fr-CA</language>
|
||||||
|
<approved>false</approved>
|
||||||
|
</translation>
|
||||||
|
</translations>
|
||||||
|
</concept_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
|
</children>
|
||||||
|
</folder_node>
|
||||||
<concept_node>
|
<concept_node>
|
||||||
<name>cardsettings</name>
|
<name>cardsettings</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
@@ -36865,6 +36990,27 @@
|
|||||||
</translation>
|
</translation>
|
||||||
</translations>
|
</translations>
|
||||||
</concept_node>
|
</concept_node>
|
||||||
|
<concept_node>
|
||||||
|
<name>stickyheader</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>sublets</name>
|
<name>sublets</name>
|
||||||
<definition_loaded>false</definition_loaded>
|
<definition_loaded>false</definition_loaded>
|
||||||
|
|||||||
@@ -55,6 +55,7 @@
|
|||||||
"react-resizable": "^3.0.4",
|
"react-resizable": "^3.0.4",
|
||||||
"react-router-dom": "^5.3.0",
|
"react-router-dom": "^5.3.0",
|
||||||
"react-scripts": "^4.0.3",
|
"react-scripts": "^4.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.8",
|
"recharts": "^2.1.8",
|
||||||
|
|||||||
@@ -162,10 +162,19 @@ export function AccountingPayablesTableComponent({
|
|||||||
const dataSource = state.search
|
const dataSource = state.search
|
||||||
? payments.filter(
|
? payments.filter(
|
||||||
(v) =>
|
(v) =>
|
||||||
(v.vendor.name || "")
|
(v.paymentnum || "")
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(state.search.toLowerCase()) ||
|
.includes(state.search.toLowerCase()) ||
|
||||||
(v.invoice_number || "")
|
((v.job && v.job.ro_number) || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(state.search.toLowerCase()) ||
|
||||||
|
((v.job && v.job.ownr_fn) || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(state.search.toLowerCase()) ||
|
||||||
|
((v.job && v.job.ownr_ln) || "")
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(state.search.toLowerCase()) ||
|
||||||
|
((v.job && v.job.ownr_co_nm) || "")
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(state.search.toLowerCase())
|
.includes(state.search.toLowerCase())
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { Link } from "react-router-dom";
|
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 { alphaSort } from "../../utils/sorters";
|
import { alphaSort, dateSort } from "../../utils/sorters";
|
||||||
import JobExportButton from "../jobs-close-export-button/jobs-close-export-button.component";
|
import JobExportButton from "../jobs-close-export-button/jobs-close-export-button.component";
|
||||||
import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-button.component";
|
import JobsExportAllButton from "../jobs-export-all-button/jobs-export-all-button.component";
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ import { connect } from "react-redux";
|
|||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
import QboAuthorizeComponent from "../qbo-authorize/qbo-authorize.component";
|
||||||
|
import { DateFormatter } from "../../utils/DateFormatter";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
@@ -62,6 +63,18 @@ export function AccountingReceivablesTableComponent({
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: t("jobs.fields.date_invoiced"),
|
||||||
|
dataIndex: "date_invoiced",
|
||||||
|
key: "date_invoiced",
|
||||||
|
sorter: (a, b) => dateSort(a.date_invoiced, b.date_invoiced),
|
||||||
|
sortOrder:
|
||||||
|
state.sortedInfo.columnKey === "date_invoiced" &&
|
||||||
|
state.sortedInfo.order,
|
||||||
|
render: (text, record) => (
|
||||||
|
<DateFormatter>{record.date_invoiced}</DateFormatter>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: t("jobs.fields.owner"),
|
title: t("jobs.fields.owner"),
|
||||||
dataIndex: "owner",
|
dataIndex: "owner",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export default function JobReconciliationBillsTable({
|
|||||||
dataIndex: "line_desc",
|
dataIndex: "line_desc",
|
||||||
key: "line_desc",
|
key: "line_desc",
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
minWidth: "65rem",
|
width: "10rem",
|
||||||
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
sorter: (a, b) => alphaSort(a.line_desc, b.line_desc),
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "line_desc" && state.sortedInfo.order,
|
||||||
@@ -72,11 +72,11 @@ export default function JobReconciliationBillsTable({
|
|||||||
state.sortedInfo.columnKey === "quantity" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "quantity" && state.sortedInfo.order,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t("bills.fields.is_credit_memo"),
|
title: t("bills.fields.is_credit_memo_short"),
|
||||||
dataIndex: "is_credit_memo",
|
dataIndex: "is_credit_memo",
|
||||||
key: "is_credit_memo",
|
key: "is_credit_memo",
|
||||||
sorter: (a, b) => a.bill.is_credit_memo - b.bill.is_credit_memo,
|
sorter: (a, b) => a.bill.is_credit_memo - b.bill.is_credit_memo,
|
||||||
width: "8rem",
|
width: "3rem",
|
||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "is_credit_memo" &&
|
state.sortedInfo.columnKey === "is_credit_memo" &&
|
||||||
state.sortedInfo.order,
|
state.sortedInfo.order,
|
||||||
|
|||||||
@@ -63,10 +63,11 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
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();
|
||||||
console.log(
|
|
||||||
"🚀 ~ file: jobs-detail-header.component.jsx ~ line 64 ~ vehicleTitle",
|
const ownerTitle = `${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
||||||
vehicleTitle.length
|
job.ownr_co_nm || ""
|
||||||
);
|
}`.trim();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row gutter={[16, 16]} style={{ alignItems: "stretch" }}>
|
<Row gutter={[16, 16]} style={{ alignItems: "stretch" }}>
|
||||||
<Col {...colSpan}>
|
<Col {...colSpan}>
|
||||||
@@ -159,9 +160,9 @@ export function JobsDetailHeader({ job, bodyshop, disabled }) {
|
|||||||
style={{ height: "100%" }}
|
style={{ height: "100%" }}
|
||||||
title={
|
title={
|
||||||
<Link to={disabled ? "#" : `/manage/owners/${job.owner.id}`}>
|
<Link to={disabled ? "#" : `/manage/owners/${job.owner.id}`}>
|
||||||
{`${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
{ownerTitle.length > 0
|
||||||
job.ownr_co_nm || ""
|
? ownerTitle
|
||||||
}`}
|
: t("owner.labels.noownerinfo")}
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -61,20 +61,22 @@ export default function ProductionBoardCard(
|
|||||||
<PauseCircleOutlined style={{ color: "orangered" }} />
|
<PauseCircleOutlined style={{ color: "orangered" }} />
|
||||||
)}
|
)}
|
||||||
<span style={{ fontWeight: "bolder" }}>
|
<span style={{ fontWeight: "bolder" }}>
|
||||||
{card.ro_number || t("general.labels.na")}
|
<Link
|
||||||
|
to={
|
||||||
|
technician
|
||||||
|
? `/tech/joblookup?selected=${card.id}`
|
||||||
|
: `/manage/jobs/${card.id}`
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{card.ro_number || t("general.labels.na")}
|
||||||
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
extra={
|
extra={
|
||||||
technician ? (
|
<Link to={{ search: `?selected=${card.id}` }}>
|
||||||
<Link to={`/tech/joblookup?selected=${card.id}`}>
|
<EyeFilled />
|
||||||
<EyeFilled />
|
</Link>
|
||||||
</Link>
|
|
||||||
) : (
|
|
||||||
<Link to={`/manage/jobs/${card.id}`}>
|
|
||||||
<EyeFilled />
|
|
||||||
</Link>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Row>
|
<Row>
|
||||||
|
|||||||
@@ -131,6 +131,13 @@ export default function ProductionBoardKanbanCardSettings({
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
valuePropName="checked"
|
||||||
|
label={t("production.labels.stickyheader")}
|
||||||
|
name="stickyheader"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
</Form>
|
</Form>
|
||||||
|
|||||||
@@ -1,26 +1,27 @@
|
|||||||
|
import { SyncOutlined } from "@ant-design/icons";
|
||||||
import { useApolloClient } from "@apollo/client";
|
import { useApolloClient } from "@apollo/client";
|
||||||
import Board, { moveCard } from "@asseinfo/react-kanban";
|
import Board, { moveCard } from "@asseinfo/react-kanban";
|
||||||
//import "@asseinfo/react-kanban/dist/styles.css";
|
import { Button, Grid, notification, PageHeader, Space, Statistic } from "antd";
|
||||||
import "./production-board-kanban.styles.scss";
|
|
||||||
import { SyncOutlined } from "@ant-design/icons";
|
|
||||||
import { Grid, notification, Button, PageHeader, Space, Statistic } from "antd";
|
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
import { Sticky, StickyContainer } from "react-sticky";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries";
|
|
||||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
|
||||||
import ProductionBoardCard from "../production-board-kanban-card/production-board-kanban-card.component";
|
|
||||||
import { createBoardData } from "./production-board-kanban.utils.js";
|
|
||||||
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
|
|
||||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
|
||||||
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
|
|
||||||
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
|
||||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
|
||||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
|
||||||
import ProductionBoardKanbanCardSettings from "./production-board-kanban.card-settings.component";
|
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
|
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||||
|
import { generate_UPDATE_JOB_KANBAN } from "../../graphql/jobs.queries";
|
||||||
|
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||||
|
import { selectTechnician } from "../../redux/tech/tech.selectors";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||||
|
import IndefiniteLoading from "../indefinite-loading/indefinite-loading.component";
|
||||||
|
import ProductionBoardFilters from "../production-board-filters/production-board-filters.component";
|
||||||
|
import ProductionBoardCard from "../production-board-kanban-card/production-board-kanban-card.component";
|
||||||
|
import ProductionListDetailComponent from "../production-list-detail/production-list-detail.component";
|
||||||
|
import ProductionBoardKanbanCardSettings from "./production-board-kanban.card-settings.component";
|
||||||
|
//import "@asseinfo/react-kanban/dist/styles.css";
|
||||||
|
import "./production-board-kanban.styles.scss";
|
||||||
|
import { createBoardData } from "./production-board-kanban.utils.js";
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
bodyshop: selectBodyshop,
|
bodyshop: selectBodyshop,
|
||||||
technician: selectTechnician,
|
technician: selectTechnician,
|
||||||
@@ -183,9 +184,52 @@ export function ProductionBoardKanbanComponent({
|
|||||||
: standardSizes[selectedBreakpoint[0]]
|
: standardSizes[selectedBreakpoint[0]]
|
||||||
: "250";
|
: "250";
|
||||||
|
|
||||||
|
const stickyHeader = {
|
||||||
|
renderColumnHeader: ({ title }) => (
|
||||||
|
<Sticky>
|
||||||
|
{({
|
||||||
|
style,
|
||||||
|
|
||||||
|
// the following are also available but unused in this example
|
||||||
|
isSticky,
|
||||||
|
wasSticky,
|
||||||
|
distanceFromTop,
|
||||||
|
distanceFromBottom,
|
||||||
|
calculatedHeight,
|
||||||
|
}) => (
|
||||||
|
<div
|
||||||
|
className="react-kanban-column-header"
|
||||||
|
style={{ ...style, zIndex: "99", backgroundColor: "#ddd" }}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Sticky>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
const cardSettings =
|
||||||
|
associationSettings &&
|
||||||
|
associationSettings.kanban_settings &&
|
||||||
|
Object.keys(associationSettings.kanban_settings).length > 0
|
||||||
|
? associationSettings.kanban_settings
|
||||||
|
: {
|
||||||
|
ats: true,
|
||||||
|
clm_no: true,
|
||||||
|
compact: false,
|
||||||
|
ownr_nm: true,
|
||||||
|
sublets: true,
|
||||||
|
ins_co_nm: true,
|
||||||
|
production_note: true,
|
||||||
|
employeeassignments: true,
|
||||||
|
scheduled_completion: true,
|
||||||
|
stickyheader: false,
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container width={width}>
|
<Container width={width}>
|
||||||
<IndefiniteLoading loading={isMoving} />
|
<IndefiniteLoading loading={isMoving} />
|
||||||
|
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={
|
title={
|
||||||
<Space>
|
<Space>
|
||||||
@@ -215,34 +259,19 @@ export function ProductionBoardKanbanComponent({
|
|||||||
</Space>
|
</Space>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<ProductionListDetailComponent jobs={data} />
|
||||||
<Board
|
<StickyContainer>
|
||||||
children={boardLanes}
|
<Board
|
||||||
disableCardDrag={isMoving}
|
style={{ height: "100%" }}
|
||||||
renderCard={(card) =>
|
children={boardLanes}
|
||||||
ProductionBoardCard(
|
disableCardDrag={isMoving}
|
||||||
technician,
|
{...(cardSettings.stickyheader && stickyHeader)}
|
||||||
card,
|
renderCard={(card) =>
|
||||||
bodyshop,
|
ProductionBoardCard(technician, card, bodyshop, cardSettings)
|
||||||
associationSettings &&
|
}
|
||||||
associationSettings.kanban_settings &&
|
onCardDragEnd={handleDragEnd}
|
||||||
Object.keys(associationSettings.kanban_settings).length > 0
|
/>
|
||||||
? associationSettings.kanban_settings
|
</StickyContainer>
|
||||||
: {
|
|
||||||
ats: true,
|
|
||||||
clm_no: true,
|
|
||||||
compact: false,
|
|
||||||
ownr_nm: true,
|
|
||||||
sublets: true,
|
|
||||||
ins_co_nm: true,
|
|
||||||
production_note: true,
|
|
||||||
employeeassignments: true,
|
|
||||||
scheduled_completion: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
onCardDragEnd={handleDragEnd}
|
|
||||||
/>
|
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import ProductionListColumnStatus from "./production-list-columns.status.compone
|
|||||||
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
import ProductionListColumnCategory from "./production-list-columns.status.category";
|
||||||
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.component";
|
||||||
import ProductionListColumnComment from "./production-list-columns.comment.component";
|
import ProductionListColumnComment from "./production-list-columns.comment.component";
|
||||||
|
import ProductionListColumnPartsReceived from "./production-list-columns.partsreceived.component";
|
||||||
|
|
||||||
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
||||||
return [
|
return [
|
||||||
@@ -96,7 +97,7 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
sortOrder:
|
sortOrder:
|
||||||
state.sortedInfo.columnKey === "actual_in" && state.sortedInfo.order,
|
state.sortedInfo.columnKey === "actual_in" && state.sortedInfo.order,
|
||||||
render: (text, record) => (
|
render: (text, record) => (
|
||||||
<ProductionListDate record={record} field="actual_in" time/>
|
<ProductionListDate record={record} field="actual_in" time />
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -477,6 +478,14 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
|
|||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: i18n.t("jobs.labels.parts_received"),
|
||||||
|
dataIndex: "parts_received",
|
||||||
|
key: "parts_received",
|
||||||
|
render: (text, record) => (
|
||||||
|
<ProductionListColumnPartsReceived record={record} />
|
||||||
|
),
|
||||||
|
},
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
export default r;
|
export default r;
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import { useMemo } from "react";
|
||||||
|
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
|
||||||
|
)(ProductionListColumnPartsReceived);
|
||||||
|
|
||||||
|
export function ProductionListColumnPartsReceived({ bodyshop, record }) {
|
||||||
|
const amount = useMemo(() => {
|
||||||
|
const amount = record.joblines_status.reduce(
|
||||||
|
(acc, val) => {
|
||||||
|
acc.total += val.count;
|
||||||
|
acc.received =
|
||||||
|
val.status === bodyshop.md_order_statuses.default_received
|
||||||
|
? acc.received + val.count
|
||||||
|
: acc.received;
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{ total: 0, received: 0 }
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
...amount,
|
||||||
|
percent:
|
||||||
|
amount.total !== 0
|
||||||
|
? ((amount.received / amount.total) * 100).toFixed(0) + "%"
|
||||||
|
: "N/A",
|
||||||
|
};
|
||||||
|
}, [record, bodyshop.md_order_statuses]);
|
||||||
|
|
||||||
|
return `${amount.percent} (${amount.received}/${amount.total})`;
|
||||||
|
}
|
||||||
@@ -88,12 +88,6 @@ export function ProductionListTable({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const handleTableChange = (pagination, filters, sorter) => {
|
const handleTableChange = (pagination, filters, sorter) => {
|
||||||
console.log(
|
|
||||||
"🚀 ~ file: production-list-table.component.jsx ~ line 91 ~ pagination, filters, sorter",
|
|
||||||
pagination,
|
|
||||||
filters,
|
|
||||||
sorter
|
|
||||||
);
|
|
||||||
setState({
|
setState({
|
||||||
...state,
|
...state,
|
||||||
filteredInfo: filters,
|
filteredInfo: filters,
|
||||||
|
|||||||
@@ -163,6 +163,27 @@ export default function ShopInfoGeneral({ form }) {
|
|||||||
>
|
>
|
||||||
<Switch />
|
<Switch />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item shouldUpdate noStyle>
|
||||||
|
{() => (
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.labels.qbo_usa")}
|
||||||
|
shouldUpdate
|
||||||
|
valuePropName="checked"
|
||||||
|
name={["accountingconfig", "qbo_usa"]}
|
||||||
|
>
|
||||||
|
<Switch
|
||||||
|
disabled={!form.getFieldValue(["accountingconfig", "qbo"])}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label={t("bodyshop.labels.qbo_departmentid")}
|
||||||
|
name={["accountingconfig", "qbo_departmentid"]}
|
||||||
|
>
|
||||||
|
<Input />
|
||||||
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={t("bodyshop.labels.accountingtiers")}
|
label={t("bodyshop.labels.accountingtiers")}
|
||||||
rules={[
|
rules={[
|
||||||
|
|||||||
@@ -146,6 +146,11 @@ export const QUERY_EXACT_JOB_IN_PRODUCTION = gql`
|
|||||||
employee_refinish
|
employee_refinish
|
||||||
employee_prep
|
employee_prep
|
||||||
employee_csr
|
employee_csr
|
||||||
|
joblines_status{
|
||||||
|
part_type
|
||||||
|
status
|
||||||
|
count
|
||||||
|
}
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: {
|
where: {
|
||||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
@@ -219,6 +224,11 @@ export const QUERY_EXACT_JOBS_IN_PRODUCTION = gql`
|
|||||||
employee_refinish
|
employee_refinish
|
||||||
employee_prep
|
employee_prep
|
||||||
employee_csr
|
employee_csr
|
||||||
|
joblines_status{
|
||||||
|
part_type
|
||||||
|
status
|
||||||
|
count
|
||||||
|
}
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: {
|
where: {
|
||||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
@@ -294,6 +304,11 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
|
|||||||
employee_prep
|
employee_prep
|
||||||
employee_csr
|
employee_csr
|
||||||
suspended
|
suspended
|
||||||
|
joblines_status{
|
||||||
|
part_type
|
||||||
|
status
|
||||||
|
count
|
||||||
|
}
|
||||||
labhrs: joblines_aggregate(
|
labhrs: joblines_aggregate(
|
||||||
where: {
|
where: {
|
||||||
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
_and: [{ mod_lbr_ty: { _neq: "LAR" } }, { removed: { _eq: false } }]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
confirmPasswordReset,
|
confirmPasswordReset,
|
||||||
signInWithEmailAndPassword,
|
signInWithEmailAndPassword,
|
||||||
signOut,
|
signOut,
|
||||||
|
sendPasswordResetEmail,
|
||||||
} from "firebase/auth";
|
} from "firebase/auth";
|
||||||
import { doc } from "firebase/firestore";
|
import { doc } from "firebase/firestore";
|
||||||
import i18next from "i18next";
|
import i18next from "i18next";
|
||||||
@@ -223,16 +224,16 @@ export function* signInSuccessSaga({ payload }) {
|
|||||||
export function* onSendPasswordResetStart() {
|
export function* onSendPasswordResetStart() {
|
||||||
yield takeLatest(
|
yield takeLatest(
|
||||||
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START,
|
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START,
|
||||||
sendPasswordResetEmail
|
sendPasswordResetEmailSaga
|
||||||
);
|
);
|
||||||
yield takeLatest(
|
yield takeLatest(
|
||||||
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START_AGAIN,
|
UserActionTypes.SEND_PASSWORD_RESET_EMAIL_START_AGAIN,
|
||||||
sendPasswordResetEmail
|
sendPasswordResetEmailSaga
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export function* sendPasswordResetEmail({ payload }) {
|
export function* sendPasswordResetEmailSaga({ payload }) {
|
||||||
try {
|
try {
|
||||||
yield sendPasswordResetEmail(payload, {
|
yield sendPasswordResetEmail(auth, payload, {
|
||||||
url: "https://imex.online/passwordreset",
|
url: "https://imex.online/passwordreset",
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -269,7 +270,7 @@ export function* SetAuthLevelFromShopDetails({ payload }) {
|
|||||||
const userEmail = yield select((state) => state.user.currentUser.email);
|
const userEmail = yield select((state) => state.user.currentUser.email);
|
||||||
try {
|
try {
|
||||||
console.log("Setting shop timezone.");
|
console.log("Setting shop timezone.");
|
||||||
// moment.tz.setDefault(payload.timezone);
|
// moment.tz.setDefault(payload.timezone);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
"federal_tax_rate": "Federal Tax Rate",
|
"federal_tax_rate": "Federal Tax Rate",
|
||||||
"invoice_number": "Invoice Number",
|
"invoice_number": "Invoice Number",
|
||||||
"is_credit_memo": "Credit Memo?",
|
"is_credit_memo": "Credit Memo?",
|
||||||
|
"is_credit_memo_short": "CM",
|
||||||
"local_tax_rate": "Local Tax Rate",
|
"local_tax_rate": "Local Tax Rate",
|
||||||
"ro_number": "RO Number",
|
"ro_number": "RO Number",
|
||||||
"state_tax_rate": "Provincial/State Tax Rate",
|
"state_tax_rate": "Provincial/State Tax Rate",
|
||||||
@@ -1563,6 +1564,7 @@
|
|||||||
"override_header": "Override estimate header on import?",
|
"override_header": "Override estimate header on import?",
|
||||||
"ownerassociation": "Owner Association",
|
"ownerassociation": "Owner Association",
|
||||||
"parts": "Parts",
|
"parts": "Parts",
|
||||||
|
"parts_received": "Parts Rec.",
|
||||||
"parts_tax_rates": "Parts Tax rates",
|
"parts_tax_rates": "Parts Tax rates",
|
||||||
"partsfilter": "Parts Only",
|
"partsfilter": "Parts Only",
|
||||||
"partssubletstotal": "Parts & Sublets Total",
|
"partssubletstotal": "Parts & Sublets Total",
|
||||||
@@ -1842,6 +1844,11 @@
|
|||||||
"updated": "Note updated successfully."
|
"updated": "Note updated successfully."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"owner": {
|
||||||
|
"labels": {
|
||||||
|
"noownerinfo": "No owner information."
|
||||||
|
}
|
||||||
|
},
|
||||||
"owners": {
|
"owners": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"update": "Update Selected Records"
|
"update": "Update Selected Records"
|
||||||
@@ -2171,6 +2178,12 @@
|
|||||||
"ats": "Alternative Transportation",
|
"ats": "Alternative Transportation",
|
||||||
"bodyhours": "B",
|
"bodyhours": "B",
|
||||||
"bodypriority": "B/P",
|
"bodypriority": "B/P",
|
||||||
|
"bodyshop": {
|
||||||
|
"labels": {
|
||||||
|
"qbo_departmentid": "QBO Department ID",
|
||||||
|
"qbo_usa": "QBO USA"
|
||||||
|
}
|
||||||
|
},
|
||||||
"cardsettings": "Card Settings",
|
"cardsettings": "Card Settings",
|
||||||
"clm_no": "Claim Number",
|
"clm_no": "Claim Number",
|
||||||
"comment": "Comment",
|
"comment": "Comment",
|
||||||
@@ -2188,6 +2201,7 @@
|
|||||||
"refinishhours": "R",
|
"refinishhours": "R",
|
||||||
"scheduled_completion": "Scheduled Completion",
|
"scheduled_completion": "Scheduled Completion",
|
||||||
"selectview": "Select a View",
|
"selectview": "Select a View",
|
||||||
|
"stickyheader": "Sticky Header (BETA)",
|
||||||
"sublets": "Sublets",
|
"sublets": "Sublets",
|
||||||
"totalhours": "Total Hrs ",
|
"totalhours": "Total Hrs ",
|
||||||
"touchtime": "T/T",
|
"touchtime": "T/T",
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
"federal_tax_rate": "",
|
"federal_tax_rate": "",
|
||||||
"invoice_number": "",
|
"invoice_number": "",
|
||||||
"is_credit_memo": "",
|
"is_credit_memo": "",
|
||||||
|
"is_credit_memo_short": "",
|
||||||
"local_tax_rate": "",
|
"local_tax_rate": "",
|
||||||
"ro_number": "",
|
"ro_number": "",
|
||||||
"state_tax_rate": "",
|
"state_tax_rate": "",
|
||||||
@@ -1563,6 +1564,7 @@
|
|||||||
"override_header": "¿Anular encabezado estimado al importar?",
|
"override_header": "¿Anular encabezado estimado al importar?",
|
||||||
"ownerassociation": "",
|
"ownerassociation": "",
|
||||||
"parts": "Partes",
|
"parts": "Partes",
|
||||||
|
"parts_received": "",
|
||||||
"parts_tax_rates": "",
|
"parts_tax_rates": "",
|
||||||
"partsfilter": "",
|
"partsfilter": "",
|
||||||
"partssubletstotal": "",
|
"partssubletstotal": "",
|
||||||
@@ -1842,6 +1844,11 @@
|
|||||||
"updated": "Nota actualizada con éxito."
|
"updated": "Nota actualizada con éxito."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"owner": {
|
||||||
|
"labels": {
|
||||||
|
"noownerinfo": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"owners": {
|
"owners": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"update": ""
|
"update": ""
|
||||||
@@ -2171,6 +2178,12 @@
|
|||||||
"ats": "",
|
"ats": "",
|
||||||
"bodyhours": "",
|
"bodyhours": "",
|
||||||
"bodypriority": "",
|
"bodypriority": "",
|
||||||
|
"bodyshop": {
|
||||||
|
"labels": {
|
||||||
|
"qbo_departmentid": "",
|
||||||
|
"qbo_usa": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
"comment": "",
|
"comment": "",
|
||||||
@@ -2188,6 +2201,7 @@
|
|||||||
"refinishhours": "",
|
"refinishhours": "",
|
||||||
"scheduled_completion": "",
|
"scheduled_completion": "",
|
||||||
"selectview": "",
|
"selectview": "",
|
||||||
|
"stickyheader": "",
|
||||||
"sublets": "",
|
"sublets": "",
|
||||||
"totalhours": "",
|
"totalhours": "",
|
||||||
"touchtime": "",
|
"touchtime": "",
|
||||||
|
|||||||
@@ -157,6 +157,7 @@
|
|||||||
"federal_tax_rate": "",
|
"federal_tax_rate": "",
|
||||||
"invoice_number": "",
|
"invoice_number": "",
|
||||||
"is_credit_memo": "",
|
"is_credit_memo": "",
|
||||||
|
"is_credit_memo_short": "",
|
||||||
"local_tax_rate": "",
|
"local_tax_rate": "",
|
||||||
"ro_number": "",
|
"ro_number": "",
|
||||||
"state_tax_rate": "",
|
"state_tax_rate": "",
|
||||||
@@ -1563,6 +1564,7 @@
|
|||||||
"override_header": "Remplacer l'en-tête d'estimation à l'importation?",
|
"override_header": "Remplacer l'en-tête d'estimation à l'importation?",
|
||||||
"ownerassociation": "",
|
"ownerassociation": "",
|
||||||
"parts": "les pièces",
|
"parts": "les pièces",
|
||||||
|
"parts_received": "",
|
||||||
"parts_tax_rates": "",
|
"parts_tax_rates": "",
|
||||||
"partsfilter": "",
|
"partsfilter": "",
|
||||||
"partssubletstotal": "",
|
"partssubletstotal": "",
|
||||||
@@ -1842,6 +1844,11 @@
|
|||||||
"updated": "Remarque mise à jour avec succès."
|
"updated": "Remarque mise à jour avec succès."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"owner": {
|
||||||
|
"labels": {
|
||||||
|
"noownerinfo": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"owners": {
|
"owners": {
|
||||||
"actions": {
|
"actions": {
|
||||||
"update": ""
|
"update": ""
|
||||||
@@ -2171,6 +2178,12 @@
|
|||||||
"ats": "",
|
"ats": "",
|
||||||
"bodyhours": "",
|
"bodyhours": "",
|
||||||
"bodypriority": "",
|
"bodypriority": "",
|
||||||
|
"bodyshop": {
|
||||||
|
"labels": {
|
||||||
|
"qbo_departmentid": "",
|
||||||
|
"qbo_usa": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
"cardsettings": "",
|
"cardsettings": "",
|
||||||
"clm_no": "",
|
"clm_no": "",
|
||||||
"comment": "",
|
"comment": "",
|
||||||
@@ -2188,6 +2201,7 @@
|
|||||||
"refinishhours": "",
|
"refinishhours": "",
|
||||||
"scheduled_completion": "",
|
"scheduled_completion": "",
|
||||||
"selectview": "",
|
"selectview": "",
|
||||||
|
"stickyheader": "",
|
||||||
"sublets": "",
|
"sublets": "",
|
||||||
"totalhours": "",
|
"totalhours": "",
|
||||||
"touchtime": "",
|
"touchtime": "",
|
||||||
|
|||||||
@@ -11293,7 +11293,7 @@ raf-schd@^4.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
|
resolved "https://registry.yarnpkg.com/raf-schd/-/raf-schd-4.0.3.tgz#5d6c34ef46f8b2a0e880a8fcdb743efc5bfdbc1a"
|
||||||
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
|
integrity sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==
|
||||||
|
|
||||||
raf@3.x, raf@^3.4.0, raf@^3.4.1, raf@~3.4.0:
|
raf@3.x, raf@^3.3.0, raf@^3.4.0, raf@^3.4.1, raf@~3.4.0:
|
||||||
version "3.4.1"
|
version "3.4.1"
|
||||||
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||||
@@ -12085,6 +12085,14 @@ react-smooth@^2.0.0:
|
|||||||
raf "^3.4.0"
|
raf "^3.4.0"
|
||||||
react-transition-group "2.9.0"
|
react-transition-group "2.9.0"
|
||||||
|
|
||||||
|
react-sticky@^6.0.3:
|
||||||
|
version "6.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-sticky/-/react-sticky-6.0.3.tgz#7a18b643e1863da113d7f7036118d2a75d9ecde4"
|
||||||
|
integrity sha512-LNH4UJlRatOqo29/VHxDZOf6fwbgfgcHO4mkEFvrie5FuaZCSTGtug5R8NGqJ0kSnX8gHw8qZN37FcvnFBJpTQ==
|
||||||
|
dependencies:
|
||||||
|
prop-types "^15.5.8"
|
||||||
|
raf "^3.3.0"
|
||||||
|
|
||||||
react-sublime-video@^0.2.5:
|
react-sublime-video@^0.2.5:
|
||||||
version "0.2.5"
|
version "0.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/react-sublime-video/-/react-sublime-video-0.2.5.tgz#c967b8e9a374b36d6a5d1b63b93fa6ec02e54842"
|
resolved "https://registry.yarnpkg.com/react-sublime-video/-/react-sublime-video-0.2.5.tgz#c967b8e9a374b36d6a5d1b63b93fa6ec02e54842"
|
||||||
|
|||||||
2
logs/IM_1234_30032022_080308.xml
Normal file
2
logs/IM_1234_30032022_080308.xml
Normal file
File diff suppressed because one or more lines are too long
2
logs/IM_1234_30032022_080358.xml
Normal file
2
logs/IM_1234_30032022_080358.xml
Normal file
File diff suppressed because one or more lines are too long
30873
logs/oAuthClient-log.log
30873
logs/oAuthClient-log.log
File diff suppressed because one or more lines are too long
@@ -611,6 +611,32 @@ exports.default = function ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//QB USA with GST
|
||||||
|
//This was required for the No. 1 Collision Group.
|
||||||
|
if (
|
||||||
|
bodyshop.accountingconfig &&
|
||||||
|
bodyshop.accountingconfig.qbo &&
|
||||||
|
bodyshop.accountingconfig.qbo_usa &&
|
||||||
|
bodyshop.region_config.includes("CA_")
|
||||||
|
) {
|
||||||
|
InvoiceLineAdd.push({
|
||||||
|
DetailType: "SalesItemLineDetail",
|
||||||
|
Amount: Dinero(jobs_by_pk.job_totals.totals.federal_tax).toFormat(
|
||||||
|
DineroQbFormat
|
||||||
|
),
|
||||||
|
SalesItemLineDetail: {
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
|
ItemRef: {
|
||||||
|
value:
|
||||||
|
items[bodyshop.md_responsibility_centers.taxes.federal.accountitem],
|
||||||
|
},
|
||||||
|
Qty: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return InvoiceLineAdd;
|
return InvoiceLineAdd;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -626,7 +652,7 @@ const findTaxCode = ({ local, state, federal }, taxcode) => {
|
|||||||
} else if (t.length > 1) {
|
} else if (t.length > 1) {
|
||||||
return "Multiple Tax Codes Match";
|
return "Multiple Tax Codes Match";
|
||||||
} else {
|
} else {
|
||||||
return "No Tax Code Matches";
|
return "";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
exports.findTaxCode = findTaxCode;
|
exports.findTaxCode = findTaxCode;
|
||||||
|
|||||||
@@ -174,6 +174,55 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
|||||||
req
|
req
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const lines = bill.billlines.map((il) =>
|
||||||
|
generateBillLine(
|
||||||
|
il,
|
||||||
|
accounts,
|
||||||
|
bill.job.class,
|
||||||
|
bill.job.bodyshop.md_responsibility_centers.sales_tax_codes,
|
||||||
|
classes,
|
||||||
|
taxCodes,
|
||||||
|
bill.job.bodyshop.md_responsibility_centers.costs
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
//QB USA with GST
|
||||||
|
//This was required for the No. 1 Collision Group.
|
||||||
|
if (
|
||||||
|
bill.job.bodyshop.accountingconfig &&
|
||||||
|
bill.job.bodyshop.accountingconfig.qbo &&
|
||||||
|
bill.job.bodyshop.accountingconfig.qbo_usa &&
|
||||||
|
bill.job.bodyshop.region_config.includes("CA_")
|
||||||
|
) {
|
||||||
|
lines.push({
|
||||||
|
DetailType: "AccountBasedExpenseLineDetail",
|
||||||
|
|
||||||
|
AccountBasedExpenseLineDetail: {
|
||||||
|
...(bill.job.class
|
||||||
|
? { ClassRef: { value: classes[bill.job.class] } }
|
||||||
|
: {}),
|
||||||
|
AccountRef: {
|
||||||
|
value:
|
||||||
|
accounts[
|
||||||
|
bill.job.bodyshop.md_responsibility_centers.taxes.federal
|
||||||
|
.accountdesc
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
Amount: Dinero({
|
||||||
|
amount: Math.round(
|
||||||
|
bill.billlines.reduce((acc, val) => {
|
||||||
|
return acc + val.actual_cost * val.quantity;
|
||||||
|
}, 0) * 100
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.percentage(bill.federal_tax_rate)
|
||||||
|
|
||||||
|
.toFormat(DineroQbFormat),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const billQbo = {
|
const billQbo = {
|
||||||
VendorRef: {
|
VendorRef: {
|
||||||
value: vendor.Id,
|
value: vendor.Id,
|
||||||
@@ -192,17 +241,7 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
|||||||
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
||||||
|
|
||||||
PrivateNote: `RO ${bill.job.ro_number || ""}`,
|
PrivateNote: `RO ${bill.job.ro_number || ""}`,
|
||||||
Line: bill.billlines.map((il) =>
|
Line: lines,
|
||||||
generateBillLine(
|
|
||||||
il,
|
|
||||||
accounts,
|
|
||||||
bill.job.class,
|
|
||||||
bill.job.bodyshop.md_responsibility_centers.sales_tax_codes,
|
|
||||||
classes,
|
|
||||||
taxCodes,
|
|
||||||
bill.job.bodyshop.md_responsibility_centers.costs
|
|
||||||
)
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
logger.log("qbo-payable-objectlog", "DEBUG", req.user.email, bill.id, {
|
logger.log("qbo-payable-objectlog", "DEBUG", req.user.email, bill.id, {
|
||||||
billQbo,
|
billQbo,
|
||||||
@@ -282,7 +321,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
|
|||||||
url: urlBuilder(
|
url: urlBuilder(
|
||||||
qbo_realmId,
|
qbo_realmId,
|
||||||
"query",
|
"query",
|
||||||
`select * From Account where AccountType = 'Cost of Goods Sold'`
|
`select * From Account where AccountType in ('Cost of Goods Sold', 'Other Current Liability')`
|
||||||
),
|
),
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
|
|||||||
@@ -455,6 +455,25 @@ async function InsertInvoice(
|
|||||||
CustomerRef: {
|
CustomerRef: {
|
||||||
value: parentTierRef.Id,
|
value: parentTierRef.Id,
|
||||||
},
|
},
|
||||||
|
...(bodyshop.accountingconfig.qbo_departmentid &&
|
||||||
|
bodyshop.accountingconfig.qbo_departmentid.trim() !== "" && {
|
||||||
|
DepartmentRef: { value: bodyshop.accountingconfig.qbo_departmentid },
|
||||||
|
}),
|
||||||
|
|
||||||
|
...(bodyshop.accountingconfig &&
|
||||||
|
bodyshop.accountingconfig.qbo &&
|
||||||
|
bodyshop.accountingconfig.qbo_usa &&
|
||||||
|
bodyshop.region_config.includes("CA_") && {
|
||||||
|
TxnTaxDetail: {
|
||||||
|
TxnTaxCodeRef: {
|
||||||
|
value:
|
||||||
|
taxCodes[
|
||||||
|
bodyshop.md_responsibility_centers.taxes.state.accountitem
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
...(bodyshop.accountingconfig.printlater
|
...(bodyshop.accountingconfig.printlater
|
||||||
? { PrintStatus: "NeedToPrint" }
|
? { PrintStatus: "NeedToPrint" }
|
||||||
: {}),
|
: {}),
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ exports.default = async (req, res) => {
|
|||||||
const { bodyshops } = await client.request(queries.GET_AUTOHOUSE_SHOPS);
|
const { bodyshops } = await client.request(queries.GET_AUTOHOUSE_SHOPS);
|
||||||
|
|
||||||
const specificShopIds = req.body.bodyshopIds; // ['uuid]
|
const specificShopIds = req.body.bodyshopIds; // ['uuid]
|
||||||
const start = req.body.start; //YYYY-MM-DD
|
const { start, end } = req.body; //YYYY-MM-DD
|
||||||
const allxmlsToUpload = [];
|
const allxmlsToUpload = [];
|
||||||
const allErrors = [];
|
const allErrors = [];
|
||||||
try {
|
try {
|
||||||
@@ -58,6 +58,7 @@ exports.default = async (req, res) => {
|
|||||||
start: start
|
start: start
|
||||||
? moment(start).startOf("day")
|
? moment(start).startOf("day")
|
||||||
: moment().subtract(3, "days").startOf("day"),
|
: moment().subtract(3, "days").startOf("day"),
|
||||||
|
...(end && { end: moment(end).startOf("day") }),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -184,6 +185,11 @@ exports.default = async (req, res) => {
|
|||||||
const CreateRepairOrderTag = (job, errorCallback) => {
|
const CreateRepairOrderTag = (job, errorCallback) => {
|
||||||
//Level 2
|
//Level 2
|
||||||
|
|
||||||
|
if (!job.job_totals) {
|
||||||
|
errorCallback({ job, error: { toString: () => "No job totals for RO." } });
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
const repairCosts = CreateCosts(job);
|
const repairCosts = CreateCosts(job);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -111,6 +111,11 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
|
|||||||
ro_number
|
ro_number
|
||||||
clm_total
|
clm_total
|
||||||
clm_no
|
clm_no
|
||||||
|
v_model_yr
|
||||||
|
v_model_desc
|
||||||
|
v_make_desc
|
||||||
|
v_vin
|
||||||
|
plate_no
|
||||||
ownerid
|
ownerid
|
||||||
ownr_ln
|
ownr_ln
|
||||||
ownr_fn
|
ownr_fn
|
||||||
@@ -176,6 +181,7 @@ query QUERY_JOBS_FOR_RECEIVABLES_EXPORT($ids: [uuid!]!) {
|
|||||||
bodyshops(where: {associations: {active: {_eq: true}}}) {
|
bodyshops(where: {associations: {active: {_eq: true}}}) {
|
||||||
id
|
id
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
|
region_config
|
||||||
accountingconfig
|
accountingconfig
|
||||||
md_ins_cos
|
md_ins_cos
|
||||||
timezone
|
timezone
|
||||||
@@ -389,6 +395,8 @@ query QUERY_BILLS_FOR_PAYABLES_EXPORT($bills: [uuid!]!) {
|
|||||||
bodyshop{
|
bodyshop{
|
||||||
md_responsibility_centers
|
md_responsibility_centers
|
||||||
timezone
|
timezone
|
||||||
|
region_config
|
||||||
|
accountingconfig
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
billlines{
|
billlines{
|
||||||
@@ -550,7 +558,7 @@ exports.QUERY_EMPLOYEE_PIN = `query QUERY_EMPLOYEE_PIN($shopId: uuid!, $employee
|
|||||||
}
|
}
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshopid: uuid!) {
|
exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshopid: uuid!, $end: timestamptz) {
|
||||||
bodyshops_by_pk(id: $bodyshopid){
|
bodyshops_by_pk(id: $bodyshopid){
|
||||||
|
|
||||||
id
|
id
|
||||||
@@ -568,7 +576,7 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshop
|
|||||||
jc_hourly_rates
|
jc_hourly_rates
|
||||||
timezone
|
timezone
|
||||||
}
|
}
|
||||||
jobs(where: {_and: [{converted: {_eq: true}}, {updated_at: {_gt: $start}}, {shopid: {_eq: $bodyshopid}}]}) {
|
jobs(where: {_and: [{converted: {_eq: true}}, {updated_at: {_gt: $start}}, {updated_at: {_lte: $end}}, {shopid: {_eq: $bodyshopid}}]}) {
|
||||||
id
|
id
|
||||||
ro_number
|
ro_number
|
||||||
status
|
status
|
||||||
|
|||||||
Reference in New Issue
Block a user