Compare commits

..

1 Commits

Author SHA1 Message Date
Allan Carr
4e8ea736c5 IO-3285 Shop Config Lite-Basic
Signed-off-by: Allan Carr <allan@imexsystems.ca>
2025-08-07 20:45:04 -07:00
3 changed files with 571 additions and 482 deletions

View File

@@ -145,124 +145,168 @@ export function ShopInfoGeneral({ form, bodyshop }) {
</Form.Item>
</LayoutFormRow>
<LayoutFormRow header={t("bodyshop.labels.accountingsetup")} id="accountingsetup">
{HasFeatureAccess({ featureName: "export", bodyshop }) && (
<>
<Form.Item label={t("bodyshop.labels.qbo")} valuePropName="checked" name={["accountingconfig", "qbo"]}>
<Switch />
</Form.Item>
{InstanceRenderManager({
imex: (
<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
label={t("bodyshop.labels.accountingtiers")}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
name={["accountingconfig", "tiers"]}
>
<Radio.Group>
<Radio value={2}>2</Radio>
<Radio value={3}>3</Radio>
</Radio.Group>
</Form.Item>
<Form.Item shouldUpdate>
{() => {
return (
<Form.Item
label={t("bodyshop.labels.2tiersetup")}
shouldUpdate
rules={[
{
required: form.getFieldValue(["accountingconfig", "tiers"]) === 2
//message: t("general.validation.required"),
}
]}
name={["accountingconfig", "twotierpref"]}
>
<Radio.Group disabled={form.getFieldValue(["accountingconfig", "tiers"]) === 3}>
<Radio value="name">{t("bodyshop.labels.2tiername")}</Radio>
<Radio value="source">{t("bodyshop.labels.2tiersource")}</Radio>
</Radio.Group>
</Form.Item>
);
}}
</Form.Item>
<Form.Item
label={t("bodyshop.labels.printlater")}
valuePropName="checked"
name={["accountingconfig", "printlater"]}
>
<Switch />
</Form.Item>
<Form.Item
label={t("bodyshop.labels.emaillater")}
valuePropName="checked"
name={["accountingconfig", "emaillater"]}
>
<Switch />
</Form.Item>
</>
)}
<Form.Item
label={t("bodyshop.fields.inhousevendorid")}
name={"inhousevendorid"}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.default_adjustment_rate")}
name={"default_adjustment_rate"}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<InputNumber min={0} precision={2} />
</Form.Item>
{InstanceRenderManager({
imex: (
<Form.Item label={t("bodyshop.fields.federal_tax_id")} name="federal_tax_id">
<Input />
</Form.Item>
)
})}
<Form.Item label={t("bodyshop.fields.state_tax_id")} name="state_tax_id">
<Input />
</Form.Item>
{HasFeatureAccess({ featureName: "bills", bodyshop }) && (
<>
{InstanceRenderManager({
imex: (
{[
...(HasFeatureAccess({ featureName: "export", bodyshop })
? [
<Form.Item
label={t("bodyshop.fields.invoice_federal_tax_rate")}
name={["bill_tax_rates", "federal_tax_rate"]}
key="qbo"
label={t("bodyshop.labels.qbo")}
valuePropName="checked"
name={["accountingconfig", "qbo"]}
>
<Switch />
</Form.Item>,
InstanceRenderManager({
imex: (
<Form.Item key="qbo_usa_wrapper" 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
key="qbo_departmentid"
label={t("bodyshop.labels.qbo_departmentid")}
name={["accountingconfig", "qbo_departmentid"]}
>
<Input />
</Form.Item>,
<Form.Item
key="accountingtiers"
label={t("bodyshop.labels.accountingtiers")}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
name={["accountingconfig", "tiers"]}
>
<Radio.Group>
<Radio value={2}>2</Radio>
<Radio value={3}>3</Radio>
</Radio.Group>
</Form.Item>,
<Form.Item key="twotierpref_wrapper" shouldUpdate>
{() => {
return (
<Form.Item
label={t("bodyshop.labels.2tiersetup")}
shouldUpdate
rules={[
{
required: form.getFieldValue(["accountingconfig", "tiers"]) === 2
//message: t("general.validation.required"),
}
]}
name={["accountingconfig", "twotierpref"]}
>
<Radio.Group disabled={form.getFieldValue(["accountingconfig", "tiers"]) === 3}>
<Radio value="name">{t("bodyshop.labels.2tiername")}</Radio>
<Radio value="source">{t("bodyshop.labels.2tiersource")}</Radio>
</Radio.Group>
</Form.Item>
);
}}
</Form.Item>,
<Form.Item
key="printlater"
label={t("bodyshop.labels.printlater")}
valuePropName="checked"
name={["accountingconfig", "printlater"]}
>
<Switch />
</Form.Item>,
<Form.Item
key="emaillater"
label={t("bodyshop.labels.emaillater")}
valuePropName="checked"
name={["accountingconfig", "emaillater"]}
>
<Switch />
</Form.Item>
]
: []),
<Form.Item
key="inhousevendorid"
label={t("bodyshop.fields.inhousevendorid")}
name={"inhousevendorid"}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<Input />
</Form.Item>,
<Form.Item
key="default_adjustment_rate"
label={t("bodyshop.fields.default_adjustment_rate")}
name={"default_adjustment_rate"}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<InputNumber min={0} precision={2} />
</Form.Item>,
InstanceRenderManager({
imex: (
<Form.Item key="federal_tax_id" label={t("bodyshop.fields.federal_tax_id")} name="federal_tax_id">
<Input />
</Form.Item>
)
}),
<Form.Item key="state_tax_id" label={t("bodyshop.fields.state_tax_id")} name="state_tax_id">
<Input />
</Form.Item>,
...(HasFeatureAccess({ featureName: "bills", bodyshop })
? [
InstanceRenderManager({
imex: (
<Form.Item
key="invoice_federal_tax_rate"
label={t("bodyshop.fields.invoice_federal_tax_rate")}
name={["bill_tax_rates", "federal_tax_rate"]}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<InputNumber />
</Form.Item>
)
}),
<Form.Item
key="invoice_state_tax_rate"
label={t("bodyshop.fields.invoice_state_tax_rate")}
name={["bill_tax_rates", "state_tax_rate"]}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<InputNumber />
</Form.Item>,
<Form.Item
key="invoice_local_tax_rate"
label={t("bodyshop.fields.invoice_local_tax_rate")}
name={["bill_tax_rates", "local_tax_rate"]}
rules={[
{
required: true
@@ -272,117 +316,118 @@ export function ShopInfoGeneral({ form, bodyshop }) {
>
<InputNumber />
</Form.Item>
)
})}
<Form.Item
label={t("bodyshop.fields.invoice_state_tax_rate")}
name={["bill_tax_rates", "state_tax_rate"]}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<InputNumber />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.invoice_local_tax_rate")}
name={["bill_tax_rates", "local_tax_rate"]}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<InputNumber />
</Form.Item>
</>
)}
<Form.Item
name={["md_payment_types"]}
label={t("bodyshop.fields.md_payment_types")}
rules={[
{
required: true,
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>
<Form.Item
name={["md_categories"]}
label={t("bodyshop.fields.md_categories")}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>
{HasFeatureAccess({ featureName: "export", bodyshop }) && (
<>
<Form.Item
name={["accountingconfig", "ReceivableCustomField1"]}
label={t("bodyshop.fields.ReceivableCustomField", { number: 1 })}
>
{ReceivableCustomFieldSelect}
</Form.Item>
<Form.Item
name={["accountingconfig", "ReceivableCustomField2"]}
label={t("bodyshop.fields.ReceivableCustomField", { number: 2 })}
>
{ReceivableCustomFieldSelect}
</Form.Item>
<Form.Item
name={["accountingconfig", "ReceivableCustomField3"]}
label={t("bodyshop.fields.ReceivableCustomField", { number: 3 })}
>
{ReceivableCustomFieldSelect}
</Form.Item>
<Form.Item
name={["md_classes"]}
label={t("bodyshop.fields.md_classes")}
rules={[
({ getFieldValue }) => {
return {
required: getFieldValue("enforce_class"),
//message: t("general.validation.required"),
type: "array"
};
}
]}
>
<Select mode="tags" />
</Form.Item>
<Form.Item name={["enforce_class"]} label={t("bodyshop.fields.enforce_class")} valuePropName="checked">
<Switch />
</Form.Item>
{ClosingPeriod.treatment === "on" && (
<Form.Item
name={["accountingconfig", "ClosingPeriod"]}
label={t("bodyshop.fields.closingperiod")} //{t("reportcenter.labels.dates")}
>
<DatePicker.RangePicker format="MM/DD/YYYY" presets={DatePickerRanges} />
</Form.Item>
)}
{ADPPayroll.treatment === "on" && (
<Form.Item name={["accountingconfig", "companyCode"]} label={t("bodyshop.fields.companycode")}>
<Input />
</Form.Item>
)}
{ADPPayroll.treatment === "on" && (
<Form.Item name={["accountingconfig", "batchID"]} label={t("bodyshop.fields.batchid")}>
<Input />
</Form.Item>
)}
</>
)}
]
: []),
<Form.Item
key="md_payment_types"
name={["md_payment_types"]}
label={t("bodyshop.fields.md_payment_types")}
rules={[
{
required: true,
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>,
<Form.Item
key="md_categories"
name={["md_categories"]}
label={t("bodyshop.fields.md_categories")}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>,
...(HasFeatureAccess({ featureName: "export", bodyshop })
? [
<Form.Item
key="ReceivableCustomField1"
name={["accountingconfig", "ReceivableCustomField1"]}
label={t("bodyshop.fields.ReceivableCustomField", { number: 1 })}
>
{ReceivableCustomFieldSelect}
</Form.Item>,
<Form.Item
key="ReceivableCustomField2"
name={["accountingconfig", "ReceivableCustomField2"]}
label={t("bodyshop.fields.ReceivableCustomField", { number: 2 })}
>
{ReceivableCustomFieldSelect}
</Form.Item>,
<Form.Item
key="ReceivableCustomField3"
name={["accountingconfig", "ReceivableCustomField3"]}
label={t("bodyshop.fields.ReceivableCustomField", { number: 3 })}
>
{ReceivableCustomFieldSelect}
</Form.Item>,
<Form.Item
key="md_classes"
name={["md_classes"]}
label={t("bodyshop.fields.md_classes")}
rules={[
({ getFieldValue }) => {
return {
required: getFieldValue("enforce_class"),
//message: t("general.validation.required"),
type: "array"
};
}
]}
>
<Select mode="tags" />
</Form.Item>,
<Form.Item
key="enforce_class"
name={["enforce_class"]}
label={t("bodyshop.fields.enforce_class")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
...(ClosingPeriod.treatment === "on"
? [
<Form.Item
key="ClosingPeriod"
name={["accountingconfig", "ClosingPeriod"]}
label={t("bodyshop.fields.closingperiod")} //{t("reportcenter.labels.dates")}
>
<DatePicker.RangePicker format="MM/DD/YYYY" presets={DatePickerRanges} />
</Form.Item>
]
: []),
...(ADPPayroll.treatment === "on"
? [
<Form.Item
key="companyCode"
name={["accountingconfig", "companyCode"]}
label={t("bodyshop.fields.companycode")}
>
<Input />
</Form.Item>
]
: []),
...(ADPPayroll.treatment === "on"
? [
<Form.Item
key="batchID"
name={["accountingconfig", "batchID"]}
label={t("bodyshop.fields.batchid")}
>
<Input />
</Form.Item>
]
: [])
]
: [])
]}
</LayoutFormRow>
<FeatureWrapper featureName="scoreboard" noauth={() => null}>
<LayoutFormRow header={t("bodyshop.labels.scoreboardsetup")} id="scoreboardsetup">
@@ -446,211 +491,255 @@ export function ShopInfoGeneral({ form, bodyshop }) {
</LayoutFormRow>
</FeatureWrapper>
<LayoutFormRow header={t("bodyshop.labels.systemsettings")} id="systemsettings">
<Form.Item
name={["md_referral_sources"]}
label={t("bodyshop.fields.md_referral_sources")}
rules={[
{
required: true,
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>
<Form.Item name={["enforce_referral"]} label={t("bodyshop.fields.enforce_referral")} valuePropName="checked">
<Switch />
</Form.Item>
<Form.Item
name={["enforce_conversion_csr"]}
label={t("bodyshop.fields.enforce_conversion_csr")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
name={["enforce_conversion_category"]}
label={t("bodyshop.fields.enforce_conversion_category")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
name={["target_touchtime"]}
label={t("bodyshop.fields.target_touchtime")}
rules={[
{
required: true
//message: t("general.validation.required"),
}
]}
>
<InputNumber min={0.1} precision={1} />
</Form.Item>
<Form.Item label={t("bodyshop.fields.use_fippa")} name={["use_fippa"]} valuePropName="checked">
<Switch />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.md_hour_split.prep")}
name={["md_hour_split", "prep"]}
dependencies={[["md_hour_split", "paint"]]}
rules={[
({ getFieldValue }) => ({
validator(rule, value) {
if (!value && !getFieldValue(["md_hour_split", "paint"])) {
return Promise.resolve();
}
if (value + getFieldValue(["md_hour_split", "paint"]) === 1) {
return Promise.resolve();
}
return Promise.reject(t("bodyshop.validation.larsplit"));
{[
<Form.Item
key="md_referral_sources"
name={["md_referral_sources"]}
label={t("bodyshop.fields.md_referral_sources")}
rules={[
{
required: true,
//message: t("general.validation.required"),
type: "array"
}
})
]}
>
<InputNumber min={0} max={1} precision={2} />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.md_hour_split.paint")}
name={["md_hour_split", "paint"]}
dependencies={[["md_hour_split", "prep"]]}
rules={[
({ getFieldValue }) => ({
validator(rule, value) {
if (!value && !getFieldValue(["md_hour_split", "paint"])) {
return Promise.resolve();
}
if (value + getFieldValue(["md_hour_split", "prep"]) === 1) {
return Promise.resolve();
}
return Promise.reject(t("bodyshop.validation.larsplit"));
]}
>
<Select mode="tags" />
</Form.Item>,
<Form.Item
key="enforce_referral"
name={["enforce_referral"]}
label={t("bodyshop.fields.enforce_referral")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="enforce_conversion_csr"
name={["enforce_conversion_csr"]}
label={t("bodyshop.fields.enforce_conversion_csr")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="enforce_conversion_category"
name={["enforce_conversion_category"]}
label={t("bodyshop.fields.enforce_conversion_category")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="target_touchtime"
name={["target_touchtime"]}
label={t("bodyshop.fields.target_touchtime")}
rules={[
{
required: true
//message: t("general.validation.required"),
}
})
]}
>
<InputNumber min={0} max={1} precision={2} />
</Form.Item>
<Form.Item label={t("bodyshop.fields.jc_hourly_rates.mapa")} name={["jc_hourly_rates", "mapa"]}>
<CurrencyInput />
</Form.Item>
<Form.Item label={t("bodyshop.fields.jc_hourly_rates.mash")} name={["jc_hourly_rates", "mash"]}>
<CurrencyInput />
</Form.Item>
<Form.Item
name={["use_paint_scale_data"]}
label={t("bodyshop.fields.use_paint_scale_data")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
name={["attach_pdf_to_email"]}
label={t("bodyshop.fields.attach_pdf_to_email")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
name={["md_from_emails"]}
label={t("bodyshop.fields.md_from_emails")}
// rules={[
// {
// //message: t("general.validation.required"),
// type: "array",
// },
// ]}
>
<Select mode="tags" />
</Form.Item>
<Form.Item
name={["md_email_cc", "parts_order"]}
label={t("bodyshop.fields.md_email_cc", { template: "parts_orders" })}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>
<Form.Item
name={["md_email_cc", "parts_return_slip"]}
label={t("bodyshop.fields.md_email_cc", { template: "parts_returns" })}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>
{HasFeatureAccess({ featureName: "timetickets", bodyshop }) && (
<>
<Form.Item
name={["tt_allow_post_to_invoiced"]}
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
name={["tt_enforce_hours_for_tech_console"]}
label={t("bodyshop.fields.tt_enforce_hours_for_tech_console")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item
name={["bill_allow_post_to_closed"]}
label={t("bodyshop.fields.bill_allow_post_to_closed")}
valuePropName="checked"
>
<Switch />
</Form.Item>
</>
)}
<Form.Item
name={["md_ded_notes"]}
label={t("bodyshop.fields.md_ded_notes")}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.md_functionality_toggles.parts_queue_toggle")}
name={["md_functionality_toggles", "parts_queue_toggle"]}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item name={["last_name_first"]} label={t("bodyshop.fields.last_name_first")} valuePropName="checked">
<Switch />
</Form.Item>
<Form.Item
name={["uselocalmediaserver"]}
label={t("bodyshop.fields.uselocalmediaserver")}
valuePropName="checked"
>
<Switch />
</Form.Item>
<Form.Item name={["localmediaserverhttp"]} label={t("bodyshop.fields.localmediaserverhttp")}>
<Input />
</Form.Item>
<Form.Item name={["localmediaservernetwork"]} label={t("bodyshop.fields.localmediaservernetwork")}>
<Input />
</Form.Item>
<Form.Item name={["localmediatoken"]} label={t("bodyshop.fields.localmediatoken")}>
<Input />
</Form.Item>
]}
>
<InputNumber min={0.1} precision={1} />
</Form.Item>,
<Form.Item key="use_fippa" label={t("bodyshop.fields.use_fippa")} name={["use_fippa"]} valuePropName="checked">
<Switch />
</Form.Item>,
<Form.Item
key="md_hour_split_prep"
label={t("bodyshop.fields.md_hour_split.prep")}
name={["md_hour_split", "prep"]}
dependencies={[["md_hour_split", "paint"]]}
rules={[
({ getFieldValue }) => ({
validator(rule, value) {
if (!value && !getFieldValue(["md_hour_split", "paint"])) {
return Promise.resolve();
}
if (value + getFieldValue(["md_hour_split", "paint"]) === 1) {
return Promise.resolve();
}
return Promise.reject(t("bodyshop.validation.larsplit"));
}
})
]}
>
<InputNumber min={0} max={1} precision={2} />
</Form.Item>,
<Form.Item
key="md_hour_split_paint"
label={t("bodyshop.fields.md_hour_split.paint")}
name={["md_hour_split", "paint"]}
dependencies={[["md_hour_split", "prep"]]}
rules={[
({ getFieldValue }) => ({
validator(rule, value) {
if (!value && !getFieldValue(["md_hour_split", "paint"])) {
return Promise.resolve();
}
if (value + getFieldValue(["md_hour_split", "prep"]) === 1) {
return Promise.resolve();
}
return Promise.reject(t("bodyshop.validation.larsplit"));
}
})
]}
>
<InputNumber min={0} max={1} precision={2} />
</Form.Item>,
<Form.Item
key="jc_hourly_rates_mapa"
label={t("bodyshop.fields.jc_hourly_rates.mapa")}
name={["jc_hourly_rates", "mapa"]}
>
<CurrencyInput />
</Form.Item>,
<Form.Item
key="jc_hourly_rates_mash"
label={t("bodyshop.fields.jc_hourly_rates.mash")}
name={["jc_hourly_rates", "mash"]}
>
<CurrencyInput />
</Form.Item>,
<Form.Item
key="use_paint_scale_data"
name={["use_paint_scale_data"]}
label={t("bodyshop.fields.use_paint_scale_data")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="attach_pdf_to_email"
name={["attach_pdf_to_email"]}
label={t("bodyshop.fields.attach_pdf_to_email")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="md_from_emails"
name={["md_from_emails"]}
label={t("bodyshop.fields.md_from_emails")}
// rules={[
// {
// //message: t("general.validation.required"),
// type: "array",
// },
// ]}
>
<Select mode="tags" />
</Form.Item>,
<Form.Item
key="md_email_cc_parts_order"
name={["md_email_cc", "parts_order"]}
label={t("bodyshop.fields.md_email_cc", { template: "parts_orders" })}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>,
<Form.Item
key="md_email_cc_parts_return_slip"
name={["md_email_cc", "parts_return_slip"]}
label={t("bodyshop.fields.md_email_cc", { template: "parts_returns" })}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>,
...(HasFeatureAccess({ featureName: "timetickets", bodyshop })
? [
<Form.Item
key="tt_allow_post_to_invoiced"
name={["tt_allow_post_to_invoiced"]}
label={t("bodyshop.fields.tt_allow_post_to_invoiced")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="tt_enforce_hours_for_tech_console"
name={["tt_enforce_hours_for_tech_console"]}
label={t("bodyshop.fields.tt_enforce_hours_for_tech_console")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="bill_allow_post_to_closed"
name={["bill_allow_post_to_closed"]}
label={t("bodyshop.fields.bill_allow_post_to_closed")}
valuePropName="checked"
>
<Switch />
</Form.Item>
]
: []),
<Form.Item
key="md_ded_notes"
name={["md_ded_notes"]}
label={t("bodyshop.fields.md_ded_notes")}
rules={[
{
//message: t("general.validation.required"),
type: "array"
}
]}
>
<Select mode="tags" />
</Form.Item>,
<Form.Item
key="parts_queue_toggle"
label={t("bodyshop.fields.md_functionality_toggles.parts_queue_toggle")}
name={["md_functionality_toggles", "parts_queue_toggle"]}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="last_name_first"
name={["last_name_first"]}
label={t("bodyshop.fields.last_name_first")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="uselocalmediaserver"
name={["uselocalmediaserver"]}
label={t("bodyshop.fields.uselocalmediaserver")}
valuePropName="checked"
>
<Switch />
</Form.Item>,
<Form.Item
key="localmediaserverhttp"
name={["localmediaserverhttp"]}
label={t("bodyshop.fields.localmediaserverhttp")}
>
<Input />
</Form.Item>,
<Form.Item
key="localmediaservernetwork"
name={["localmediaservernetwork"]}
label={t("bodyshop.fields.localmediaservernetwork")}
>
<Input />
</Form.Item>,
<Form.Item key="localmediatoken" name={["localmediatoken"]} label={t("bodyshop.fields.localmediatoken")}>
<Input />
</Form.Item>
]}
</LayoutFormRow>
<LayoutFormRow header={t("bodyshop.labels.shop_enabled_features")} id="sharing">
<Form.Item

View File

@@ -10,6 +10,7 @@ const queries = require("../../graphql-client/queries");
const { refresh: refreshOauthToken, setNewRefreshToken } = require("./qbo-callback");
const OAuthClient = require("intuit-oauth");
const moment = require("moment-timezone");
const GraphQLClient = require("graphql-request").GraphQLClient;
const {
QueryInsuranceCo,
InsertInsuranceCo,
@@ -27,7 +28,7 @@ exports.default = async (req, res) => {
clientId: process.env.QBO_CLIENT_ID,
clientSecret: process.env.QBO_SECRET,
environment: process.env.NODE_ENV === "production" ? "production" : "sandbox",
redirectUri: process.env.QBO_REDIRECT_URI
redirectUri: process.env.QBO_REDIRECT_URI,
});
try {
//Fetch the API Access Tokens & Set them for the session.
@@ -130,20 +131,22 @@ exports.default = async (req, res) => {
// //No error. Mark the payment exported & insert export log.
if (elgen) {
await client.setHeaders({ Authorization: BearerToken }).request(queries.QBO_MARK_PAYMENT_EXPORTED, {
paymentId: payment.id,
payment: {
exportedat: moment().tz(bodyshop.timezone)
},
logs: [
{
bodyshopid: bodyshop.id,
paymentid: payment.id,
successful: true,
useremail: req.user.email
}
]
});
const result = await client
.setHeaders({ Authorization: BearerToken })
.request(queries.QBO_MARK_PAYMENT_EXPORTED, {
paymentId: payment.id,
payment: {
exportedat: moment().tz(bodyshop.timezone)
},
logs: [
{
bodyshopid: bodyshop.id,
paymentid: payment.id,
successful: true,
useremail: req.user.email
}
]
});
}
ret.push({ paymentid: payment.id, success: true });
@@ -153,7 +156,7 @@ exports.default = async (req, res) => {
});
//Add the export log error.
if (elgen) {
await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_EXPORT_LOG, {
const result = await client.setHeaders({ Authorization: BearerToken }).request(queries.INSERT_EXPORT_LOG, {
logs: [
{
bodyshopid: bodyshop.id,
@@ -187,7 +190,7 @@ exports.default = async (req, res) => {
}
};
async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef) {
async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef, bodyshop) {
const { paymentMethods, invoices } = await QueryMetaData(
oauthClient,
qbo_realmId,
@@ -224,20 +227,20 @@ async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef)
PaymentRefNum: payment.transactionid,
...(invoices && invoices.length === 1 && invoices[0]
? {
Line: [
{
Amount: Dinero({
amount: Math.round(payment.amount * 100)
}).toFormat(DineroQbFormat),
LinkedTxn: [
{
TxnId: invoices[0].Id,
TxnType: "Invoice"
}
]
}
]
}
Line: [
{
Amount: Dinero({
amount: Math.round(payment.amount * 100)
}).toFormat(DineroQbFormat),
LinkedTxn: [
{
TxnId: invoices[0].Id,
TxnType: "Invoice"
}
]
}
]
}
: {})
};
logger.log("qbo-payments-objectlog", "DEBUG", req.user.email, payment.id, {
@@ -260,7 +263,7 @@ async function InsertPayment(oauthClient, qbo_realmId, req, payment, parentRef)
status: result.response?.status,
bodyshopid: payment.job.shopid,
email: req.user.email
});
})
setNewRefreshToken(req.user.email, result);
return result && result.Bill;
} catch (error) {
@@ -288,7 +291,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: invoice.response?.status,
bodyshopid,
email: req.user.email
});
})
const paymentMethods = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From PaymentMethod`),
method: "POST",
@@ -303,7 +306,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: paymentMethods.response?.status,
bodyshopid,
email: req.user.email
});
})
setNewRefreshToken(req.user.email, paymentMethods);
// const classes = await oauthClient.makeApiCall({
@@ -355,7 +358,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: taxCodes.response?.status,
bodyshopid,
email: req.user.email
});
})
const items = await oauthClient.makeApiCall({
url: urlBuilder(qbo_realmId, "query", `select * From Item`),
method: "POST",
@@ -370,7 +373,7 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
status: items.response?.status,
bodyshopid,
email: req.user.email
});
})
setNewRefreshToken(req.user.email, items);
const itemMapping = {};
@@ -409,8 +412,8 @@ async function QueryMetaData(oauthClient, qbo_realmId, req, ro_number, isCreditM
};
}
async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRef) {
const { invoices, items, taxCodes } = await QueryMetaData(
async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRef, bodyshop) {
const { paymentMethods, invoices, items, taxCodes } = await QueryMetaData(
oauthClient,
qbo_realmId,
req,
@@ -446,14 +449,14 @@ async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRe
TaxCodeRef: {
value:
taxCodes[
findTaxCode(
{
local: false,
federal: false,
state: false
},
payment.job.bodyshop.md_responsibility_centers.sales_tax_codes
)
findTaxCode(
{
local: false,
federal: false,
state: false
},
payment.job.bodyshop.md_responsibility_centers.sales_tax_codes
)
]
}
}
@@ -480,14 +483,12 @@ async function InsertCreditMemo(oauthClient, qbo_realmId, req, payment, parentRe
status: result.response?.status,
bodyshopid: req.user.bodyshopid,
email: req.user.email
});
})
setNewRefreshToken(req.user.email, result);
return result && result.Bill;
} catch (error) {
logger.log("qbo-payables-error", "DEBUG", req.user.email, payment.id, {
error: error,
validationError: JSON.stringify(error?.response?.data),
accountmeta: JSON.stringify({ items, taxCodes }),
error: error && error.message,
method: "InsertCreditMemo"
});
throw error;

View File

@@ -144,7 +144,6 @@ const paymentRefund = async (req, res) => {
logger.log("intellipay-refund-success", "DEBUG", req.user?.email, null, {
requestOptions: options,
response: response?.data,
...logResponseMeta
});