@@ -1,4 +1,4 @@
|
|||||||
<babeledit_project version="1.2" be_version="2.7.1">
|
<babeledit_project be_version="2.7.1" version="1.2">
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
BabelEdit project file
|
BabelEdit project file
|
||||||
@@ -40261,6 +40261,53 @@
|
|||||||
</concept_node>
|
</concept_node>
|
||||||
</children>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
|
<folder_node>
|
||||||
|
<name>validation</name>
|
||||||
|
<children>
|
||||||
|
<concept_node>
|
||||||
|
<name>clockoffmustbeafterclockon</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>clockoffwithoutclockon</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>
|
</children>
|
||||||
</folder_node>
|
</folder_node>
|
||||||
<folder_node>
|
<folder_node>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
Space,
|
Space,
|
||||||
Switch,
|
Switch,
|
||||||
Table,
|
Table,
|
||||||
Tooltip,
|
Tooltip
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -334,6 +334,19 @@ export function BillEnterModalLinesComponent({
|
|||||||
additional: (record, index) => (
|
additional: (record, index) => (
|
||||||
<Form.Item shouldUpdate style={{ display: "inline-block" }}>
|
<Form.Item shouldUpdate style={{ display: "inline-block" }}>
|
||||||
{() => {
|
{() => {
|
||||||
|
const price = getFieldValue([
|
||||||
|
"billlines",
|
||||||
|
record.name,
|
||||||
|
"actual_price",
|
||||||
|
]);
|
||||||
|
|
||||||
|
const adjustmentRate = getFieldValue([
|
||||||
|
"billlines",
|
||||||
|
record.name,
|
||||||
|
"lbr_adjustment",
|
||||||
|
"rate",
|
||||||
|
]);
|
||||||
|
|
||||||
if (getFieldValue(["billlines", record.name, "deductedfromlbr"]))
|
if (getFieldValue(["billlines", record.name, "deductedfromlbr"]))
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
@@ -406,6 +419,9 @@ export function BillEnterModalLinesComponent({
|
|||||||
>
|
>
|
||||||
<InputNumber precision={2} min={0.01} />
|
<InputNumber precision={2} min={0.01} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
{price &&
|
||||||
|
adjustmentRate &&
|
||||||
|
`${(price / adjustmentRate).toFixed(1)} hrs`}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return <></>;
|
return <></>;
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export default function ScheduleEventContainer({ bodyshop, event, refetch }) {
|
|||||||
job: {
|
job: {
|
||||||
date_scheduled: null,
|
date_scheduled: null,
|
||||||
scheduled_in: null,
|
scheduled_in: null,
|
||||||
|
scheduled_completion:null,
|
||||||
status: bodyshop.md_ro_statuses.default_imported,
|
status: bodyshop.md_ro_statuses.default_imported,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import { createStructuredSelector } from "reselect";
|
import { createStructuredSelector } from "reselect";
|
||||||
import { setPartnerVersion } from "../../redux/application/application.actions";
|
import { setPartnerVersion } from "../../redux/application/application.actions";
|
||||||
|
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
//currentUser: selectCurrentUser
|
//currentUser: selectCurrentUser
|
||||||
|
bodyshop: selectBodyshop,
|
||||||
});
|
});
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
@@ -19,7 +21,7 @@ export default connect(
|
|||||||
mapDispatchToProps
|
mapDispatchToProps
|
||||||
)(PartnerPingComponent);
|
)(PartnerPingComponent);
|
||||||
|
|
||||||
export function PartnerPingComponent({ setPartnerVersion }) {
|
export function PartnerPingComponent({ bodyshop, setPartnerVersion }) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -29,16 +31,25 @@ export function PartnerPingComponent({ setPartnerVersion }) {
|
|||||||
//if (process.env.NODE_ENV === "development") return;
|
//if (process.env.NODE_ENV === "development") return;
|
||||||
const PartnerResponse = await axios.post("http://localhost:1337/ping/");
|
const PartnerResponse = await axios.post("http://localhost:1337/ping/");
|
||||||
const { appver, qbpath } = PartnerResponse.data;
|
const { appver, qbpath } = PartnerResponse.data;
|
||||||
|
if (!bodyshop) return;
|
||||||
setPartnerVersion(appver);
|
setPartnerVersion(appver);
|
||||||
console.log({ appver, qbpath });
|
console.log({ appver, qbpath });
|
||||||
if (!qbpath) {
|
if (
|
||||||
|
!qbpath &&
|
||||||
|
!(
|
||||||
|
bodyshop &&
|
||||||
|
(bodyshop.cdk_dealerid ||
|
||||||
|
bodyshop.pbs_serialnumber ||
|
||||||
|
bodyshop.accountingconfig.qbo)
|
||||||
|
)
|
||||||
|
) {
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
title: "",
|
title: "",
|
||||||
message: t("general.messages.noacctfilepath"),
|
message: t("general.messages.noacctfilepath"),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
notification["error"]({
|
notification["error"]({
|
||||||
title: "",
|
title: "",
|
||||||
message: t("general.messages.partnernotrunning"),
|
message: t("general.messages.partnernotrunning"),
|
||||||
@@ -48,7 +59,7 @@ export function PartnerPingComponent({ setPartnerVersion }) {
|
|||||||
// Execute the created function directly
|
// Execute the created function directly
|
||||||
checkPartnerStatus();
|
checkPartnerStatus();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, []);
|
}, [bodyshop]);
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ import AlertComponent from "../alert/alert.component";
|
|||||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||||
import PartsOrderModalComponent from "./parts-order-modal.component";
|
import PartsOrderModalComponent from "./parts-order-modal.component";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
const mapStateToProps = createStructuredSelector({
|
const mapStateToProps = createStructuredSelector({
|
||||||
currentUser: selectCurrentUser,
|
currentUser: selectCurrentUser,
|
||||||
@@ -57,6 +59,11 @@ export function PartsOrderModalContainer({
|
|||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
|
const { OEConnection_PriceChange } = useTreatments(
|
||||||
|
["OEConnection_PriceChange"],
|
||||||
|
{},
|
||||||
|
bodyshop.imexshopid
|
||||||
|
);
|
||||||
const { visible, context, actions } = partsOrderModal;
|
const { visible, context, actions } = partsOrderModal;
|
||||||
const {
|
const {
|
||||||
jobId,
|
jobId,
|
||||||
@@ -230,11 +237,22 @@ export function PartsOrderModalContainer({
|
|||||||
id: insertResult.data.insert_parts_orders.returning[0].id,
|
id: insertResult.data.insert_parts_orders.returning[0].id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
let po;
|
||||||
|
//Massage the data based on the split. Should they be able to overwrite OEC pricing?
|
||||||
|
if (OEConnection_PriceChange.treatment === "on") {
|
||||||
|
//Set the flag to include the override.
|
||||||
|
po = _.cloneDeep(partsOrder.data.parts_orders_by_pk);
|
||||||
|
po.parts_order_lines.forEach((pol) => {
|
||||||
|
pol.priceChange = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(partsOrder.data.parts_orders_by_pk);
|
||||||
|
|
||||||
const oecResponse = await axios.post(
|
const oecResponse = await axios.post(
|
||||||
"http://localhost:1337/oec/",
|
"http://localhost:1337/oec/",
|
||||||
|
|
||||||
partsOrder.data.parts_orders_by_pk,
|
po || partsOrder.data.parts_orders_by_pk,
|
||||||
{
|
{
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
Authorization: `Bearer ${await auth.currentUser.getIdToken()}`,
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ export function TimeTicketModalComponent({
|
|||||||
>
|
>
|
||||||
<InputNumber min={0} precision={1} />
|
<InputNumber min={0} precision={1} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{isEdit && (
|
{
|
||||||
<>
|
<>
|
||||||
<Form.Item label={t("timetickets.fields.clockon")} name="clockon">
|
<Form.Item label={t("timetickets.fields.clockon")} name="clockon">
|
||||||
<FormDateTimePicker
|
<FormDateTimePicker
|
||||||
@@ -221,7 +221,29 @@ export function TimeTicketModalComponent({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label={t("timetickets.fields.clockoff")} name="clockoff">
|
<Form.Item
|
||||||
|
label={t("timetickets.fields.clockoff")}
|
||||||
|
name="clockoff"
|
||||||
|
rules={[
|
||||||
|
({ getFieldValue }) => ({
|
||||||
|
validator(rule, value) {
|
||||||
|
const clockon = getFieldValue("clockon");
|
||||||
|
|
||||||
|
if (!value) return Promise.resolve();
|
||||||
|
if (!clockon && value)
|
||||||
|
return Promise.reject(
|
||||||
|
t("timetickets.validation.clockoffwithoutclockon")
|
||||||
|
);
|
||||||
|
if (!value.isSameOrAfter(clockon))
|
||||||
|
return Promise.reject(
|
||||||
|
t("timetickets.validation.clockoffmustbeafterclockon")
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.resolve();
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
>
|
||||||
<FormDateTimePicker
|
<FormDateTimePicker
|
||||||
disabled={
|
disabled={
|
||||||
!HasRbacAccess({
|
!HasRbacAccess({
|
||||||
@@ -233,7 +255,7 @@ export function TimeTicketModalComponent({
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
}
|
||||||
|
|
||||||
<Form.Item label={t("timetickets.fields.memo")} name="memo">
|
<Form.Item label={t("timetickets.fields.memo")} name="memo">
|
||||||
<MemoInput />
|
<MemoInput />
|
||||||
|
|||||||
@@ -2406,6 +2406,10 @@
|
|||||||
"clockedout": "Clocked out successfully.",
|
"clockedout": "Clocked out successfully.",
|
||||||
"created": "Time ticket entered successfully.",
|
"created": "Time ticket entered successfully.",
|
||||||
"deleted": "Time ticket deleted successfully."
|
"deleted": "Time ticket deleted successfully."
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"clockoffmustbeafterclockon": "Clock off time must be the same or after clock in time.",
|
||||||
|
"clockoffwithoutclockon": "Clock off time cannot be set without a clock in time."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"titles": {
|
"titles": {
|
||||||
|
|||||||
@@ -2406,6 +2406,10 @@
|
|||||||
"clockedout": "",
|
"clockedout": "",
|
||||||
"created": "",
|
"created": "",
|
||||||
"deleted": ""
|
"deleted": ""
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"clockoffmustbeafterclockon": "",
|
||||||
|
"clockoffwithoutclockon": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"titles": {
|
"titles": {
|
||||||
|
|||||||
@@ -2406,6 +2406,10 @@
|
|||||||
"clockedout": "",
|
"clockedout": "",
|
||||||
"created": "",
|
"created": "",
|
||||||
"deleted": ""
|
"deleted": ""
|
||||||
|
},
|
||||||
|
"validation": {
|
||||||
|
"clockoffmustbeafterclockon": "",
|
||||||
|
"clockoffwithoutclockon": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"titles": {
|
"titles": {
|
||||||
|
|||||||
@@ -815,6 +815,7 @@
|
|||||||
- email
|
- email
|
||||||
- enforce_class
|
- enforce_class
|
||||||
- enforce_referral
|
- enforce_referral
|
||||||
|
- entegral_id
|
||||||
- features
|
- features
|
||||||
- federal_tax_id
|
- federal_tax_id
|
||||||
- id
|
- id
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "appointments_bodyshopid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "appointments_bodyshopid" on
|
||||||
|
"public"."appointments" using btree ("bodyshopid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "appointments_jobid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "appointments_jobid" on
|
||||||
|
"public"."appointments" using btree ("jobid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "appointments_start";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "appointments_start" on
|
||||||
|
"public"."appointments" using btree ("start");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "appointments_end";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "appointments_end" on
|
||||||
|
"public"."appointments" using btree ("end");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "associations_bodyshopid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "associations_bodyshopid" on
|
||||||
|
"public"."associations" using btree ("shopid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "associations_useremail";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "associations_useremail" on
|
||||||
|
"public"."associations" using btree ("useremail");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "invoicelines_billid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "invoicelines_billid" on
|
||||||
|
"public"."billlines" using btree ("billid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "invoicelines_jobid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "invoicelines_jobid" on
|
||||||
|
"public"."billlines" using btree ("joblineid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "bills_jobid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "bills_jobid" on
|
||||||
|
"public"."bills" using btree ("jobid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "conversations_shopid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "conversations_shopid" on
|
||||||
|
"public"."conversations" using btree ("bodyshopid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "documents_shopid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "documents_shopid" on
|
||||||
|
"public"."documents" using btree ("bodyshopid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "documents_jobid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "documents_jobid" on
|
||||||
|
"public"."documents" using btree ("jobid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "documents_billid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "documents_billid" on
|
||||||
|
"public"."documents" using btree ("billid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "jobline_jobid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "jobline_jobid" on
|
||||||
|
"public"."joblines" using btree ("jobid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "jobs_updatedat";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "jobs_updatedat" on
|
||||||
|
"public"."jobs" using btree ("updated_at");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "jobs_bodyshopid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "jobs_bodyshopid" on
|
||||||
|
"public"."jobs" using btree ("shopid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "messages_conversationid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "messages_conversationid" on
|
||||||
|
"public"."messages" using btree ("conversationid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "timetickets_jobid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "timetickets_jobid" on
|
||||||
|
"public"."timetickets" using btree ("jobid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "parts_orders_jobid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "parts_orders_jobid" on
|
||||||
|
"public"."parts_orders" using btree ("jobid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "parts_order_lines_poid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "parts_order_lines_poid" on
|
||||||
|
"public"."parts_order_lines" using btree ("orderid");
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
DROP INDEX IF EXISTS "parts_order_lines_joblineid";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
CREATE INDEX "parts_order_lines_joblineid" on
|
||||||
|
"public"."parts_order_lines" using btree ("job_line_id");
|
||||||
@@ -9,6 +9,7 @@ exports.default = function ({
|
|||||||
qbo = false,
|
qbo = false,
|
||||||
items,
|
items,
|
||||||
taxCodes,
|
taxCodes,
|
||||||
|
classes,
|
||||||
}) {
|
}) {
|
||||||
const InvoiceLineAdd = [];
|
const InvoiceLineAdd = [];
|
||||||
const responsibilityCenters = bodyshop.md_responsibility_centers;
|
const responsibilityCenters = bodyshop.md_responsibility_centers;
|
||||||
@@ -95,6 +96,9 @@ exports.default = function ({
|
|||||||
DetailType: "SalesItemLineDetail",
|
DetailType: "SalesItemLineDetail",
|
||||||
Amount: DineroAmount,
|
Amount: DineroAmount,
|
||||||
SalesItemLineDetail: {
|
SalesItemLineDetail: {
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items[account.accountitem],
|
value: items[account.accountitem],
|
||||||
},
|
},
|
||||||
@@ -161,6 +165,9 @@ exports.default = function ({
|
|||||||
DetailType: "SalesItemLineDetail",
|
DetailType: "SalesItemLineDetail",
|
||||||
Amount: DineroAmount,
|
Amount: DineroAmount,
|
||||||
SalesItemLineDetail: {
|
SalesItemLineDetail: {
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items[account.accountitem],
|
value: items[account.accountitem],
|
||||||
},
|
},
|
||||||
@@ -227,6 +234,9 @@ exports.default = function ({
|
|||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items[mapaAccount.accountitem],
|
value: items[mapaAccount.accountitem],
|
||||||
},
|
},
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
TaxCodeRef: {
|
TaxCodeRef: {
|
||||||
value: QboTaxId,
|
value: QboTaxId,
|
||||||
},
|
},
|
||||||
@@ -290,6 +300,9 @@ exports.default = function ({
|
|||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items[mashAccount.accountitem],
|
value: items[mashAccount.accountitem],
|
||||||
},
|
},
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
TaxCodeRef: {
|
TaxCodeRef: {
|
||||||
value: QboTaxId,
|
value: QboTaxId,
|
||||||
},
|
},
|
||||||
@@ -367,6 +380,9 @@ exports.default = function ({
|
|||||||
amount: Math.round((jobs_by_pk.towing_payable || 0) * 100),
|
amount: Math.round((jobs_by_pk.towing_payable || 0) * 100),
|
||||||
}).toFormat(DineroQbFormat),
|
}).toFormat(DineroQbFormat),
|
||||||
SalesItemLineDetail: {
|
SalesItemLineDetail: {
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items[account.accountitem],
|
value: items[account.accountitem],
|
||||||
},
|
},
|
||||||
@@ -415,6 +431,9 @@ exports.default = function ({
|
|||||||
amount: Math.round((jobs_by_pk.storage_payable || 0) * 100),
|
amount: Math.round((jobs_by_pk.storage_payable || 0) * 100),
|
||||||
}).toFormat(DineroQbFormat),
|
}).toFormat(DineroQbFormat),
|
||||||
SalesItemLineDetail: {
|
SalesItemLineDetail: {
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items[account.accountitem],
|
value: items[account.accountitem],
|
||||||
},
|
},
|
||||||
@@ -466,6 +485,9 @@ exports.default = function ({
|
|||||||
amount: Math.round((jobs_by_pk.adjustment_bottom_line || 0) * 100),
|
amount: Math.round((jobs_by_pk.adjustment_bottom_line || 0) * 100),
|
||||||
}).toFormat(DineroQbFormat),
|
}).toFormat(DineroQbFormat),
|
||||||
SalesItemLineDetail: {
|
SalesItemLineDetail: {
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items[account.accountitem],
|
value: items[account.accountitem],
|
||||||
},
|
},
|
||||||
@@ -554,6 +576,9 @@ exports.default = function ({
|
|||||||
DineroQbFormat
|
DineroQbFormat
|
||||||
),
|
),
|
||||||
SalesItemLineDetail: {
|
SalesItemLineDetail: {
|
||||||
|
...(jobs_by_pk.class
|
||||||
|
? { ClassRef: { value: classes[jobs_by_pk.class] } }
|
||||||
|
: {}),
|
||||||
ItemRef: {
|
ItemRef: {
|
||||||
value: items["PVRT"],
|
value: items["PVRT"],
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -181,11 +181,9 @@ async function InsertBill(oauthClient, qbo_realmId, req, bill, vendor) {
|
|||||||
TxnDate: moment(bill.date).format("YYYY-MM-DD"),
|
TxnDate: moment(bill.date).format("YYYY-MM-DD"),
|
||||||
//DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
|
//DueDate: bill.due_date && moment(bill.due_date).format("YYYY-MM-DD"),
|
||||||
DocNumber: bill.invoice_number,
|
DocNumber: bill.invoice_number,
|
||||||
...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
//...(bill.job.class ? { ClassRef: { Id: classes[bill.job.class] } } : {}),
|
||||||
|
|
||||||
PrivateNote: `RO ${bill.job.ro_number || ""} OWNER ${
|
PrivateNote: `RO ${bill.job.ro_number || ""}`,
|
||||||
bill.job.ownr_fn || ""
|
|
||||||
} ${bill.job.ownr_ln || ""} ${bill.job.ownr_co_nm || ""}`,
|
|
||||||
Line: bill.billlines.map((il) =>
|
Line: bill.billlines.map((il) =>
|
||||||
generateBillLine(
|
generateBillLine(
|
||||||
il,
|
il,
|
||||||
@@ -249,12 +247,11 @@ const generateBillLine = (
|
|||||||
) => {
|
) => {
|
||||||
const account = costCenters.find((c) => c.name === billLine.cost_center);
|
const account = costCenters.find((c) => c.name === billLine.cost_center);
|
||||||
|
|
||||||
console.log(account.accountname, accounts[account.accountname]);
|
|
||||||
return {
|
return {
|
||||||
DetailType: "AccountBasedExpenseLineDetail",
|
DetailType: "AccountBasedExpenseLineDetail",
|
||||||
|
|
||||||
AccountBasedExpenseLineDetail: {
|
AccountBasedExpenseLineDetail: {
|
||||||
...(jobClass ? { ClassRef: { Id: classes[jobClass] } } : {}),
|
...(jobClass ? { ClassRef: { value: classes[jobClass] } } : {}),
|
||||||
TaxCodeRef: {
|
TaxCodeRef: {
|
||||||
value:
|
value:
|
||||||
taxCodes[findTaxCode(billLine.applicable_taxes, ioSalesTaxCodes)],
|
taxCodes[findTaxCode(billLine.applicable_taxes, ioSalesTaxCodes)],
|
||||||
@@ -324,7 +321,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
|
|||||||
classes.json.QueryResponse &&
|
classes.json.QueryResponse &&
|
||||||
classes.json.QueryResponse.Class &&
|
classes.json.QueryResponse.Class &&
|
||||||
classes.json.QueryResponse.Class.forEach((t) => {
|
classes.json.QueryResponse.Class.forEach((t) => {
|
||||||
accountMapping[t.Name] = t.Id;
|
classMapping[t.Name] = t.Id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -356,7 +356,7 @@ async function InsertJob(oauthClient, qbo_realmId, req, job, parentTierRef) {
|
|||||||
exports.InsertJob = InsertJob;
|
exports.InsertJob = InsertJob;
|
||||||
async function QueryMetaData(oauthClient, qbo_realmId, req) {
|
async function QueryMetaData(oauthClient, qbo_realmId, req) {
|
||||||
const items = await oauthClient.makeApiCall({
|
const items = await oauthClient.makeApiCall({
|
||||||
url: urlBuilder(qbo_realmId, "query", `select * From Item`),
|
url: urlBuilder(qbo_realmId, "query", `select * From Item where active=true maxresults 1000`),
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -402,7 +402,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req) {
|
|||||||
classes.json.QueryResponse &&
|
classes.json.QueryResponse &&
|
||||||
classes.json.QueryResponse.Class &&
|
classes.json.QueryResponse.Class &&
|
||||||
classes.json.QueryResponse.Class.forEach((t) => {
|
classes.json.QueryResponse.Class.forEach((t) => {
|
||||||
itemMapping[t.Name] = t.Id;
|
classMapping[t.Name] = t.Id;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -431,13 +431,19 @@ async function InsertInvoice(
|
|||||||
qbo: true,
|
qbo: true,
|
||||||
items,
|
items,
|
||||||
taxCodes,
|
taxCodes,
|
||||||
|
classes
|
||||||
});
|
});
|
||||||
|
|
||||||
const invoiceObj = {
|
const invoiceObj = {
|
||||||
Line: InvoiceLineAdd,
|
Line: InvoiceLineAdd,
|
||||||
TxnDate: moment(job.date_invoiced).format("YYYY-MM-DD"),
|
TxnDate: moment(job.date_invoiced).format("YYYY-MM-DD"),
|
||||||
DocNumber: job.ro_number,
|
DocNumber: job.ro_number,
|
||||||
...(job.class ? { ClassRef: { Id: classes[job.class] } } : {}),
|
...(job.class ? { ClassRef: { value: classes[job.class] } } : {}),
|
||||||
|
CustomerMemo: {
|
||||||
|
value: `${job.clm_no ? `Claim No: ${job.clm_no}` : ``}${
|
||||||
|
job.po_number ? `PO No: ${job.po_number}` : ``
|
||||||
|
}`.trim(),
|
||||||
|
},
|
||||||
CustomerRef: {
|
CustomerRef: {
|
||||||
value: parentTierRef.Id,
|
value: parentTierRef.Id,
|
||||||
},
|
},
|
||||||
@@ -447,6 +453,15 @@ async function InsertInvoice(
|
|||||||
...(bodyshop.accountingconfig.emaillater && job.ownr_ea
|
...(bodyshop.accountingconfig.emaillater && job.ownr_ea
|
||||||
? { EmailStatus: "NeedToSend" }
|
? { EmailStatus: "NeedToSend" }
|
||||||
: {}),
|
: {}),
|
||||||
|
BillAddr: {
|
||||||
|
Line3: `${job.ownr_city || ""}, ${job.ownr_st || ""} ${
|
||||||
|
job.ownr_zip || ""
|
||||||
|
}`.trim(),
|
||||||
|
Line2: job.ownr_addr1 || "",
|
||||||
|
Line1: `${job.ownr_fn || ""} ${job.ownr_ln || ""} ${
|
||||||
|
job.ownr_co_nm || ""
|
||||||
|
}`,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.log("qbo-receivable-objectlog", "DEBUG", req.user.email, job.id, {
|
logger.log("qbo-receivable-objectlog", "DEBUG", req.user.email, job.id, {
|
||||||
|
|||||||
@@ -566,6 +566,13 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshop
|
|||||||
status
|
status
|
||||||
est_ct_fn
|
est_ct_fn
|
||||||
est_ct_ln
|
est_ct_ln
|
||||||
|
ownr_fn
|
||||||
|
ownr_ln
|
||||||
|
ownr_co_nm
|
||||||
|
ownr_addr1
|
||||||
|
ownr_city
|
||||||
|
ownr_st
|
||||||
|
ownr_ph1
|
||||||
ownr_zip
|
ownr_zip
|
||||||
referral_source
|
referral_source
|
||||||
loss_type
|
loss_type
|
||||||
|
|||||||
Reference in New Issue
Block a user