Compare commits
2 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5310866302 | ||
|
|
e3ab229ac5 |
@@ -253,10 +253,6 @@ export function ContractConvertToRo({ bodyshop, currentUser, contract, disabled
|
||||
}
|
||||
};
|
||||
|
||||
if (currentUser?.email) {
|
||||
newJob.created_user_email = currentUser.email;
|
||||
}
|
||||
|
||||
//Calcualte the new job totals.
|
||||
|
||||
const newTotals = (
|
||||
|
||||
@@ -43,18 +43,16 @@ export function JobCreateIOU({ bodyshop, currentUser, job, selectedJobLines, tec
|
||||
const handleCreateIou = async () => {
|
||||
setLoading(true);
|
||||
//Query all of the job details to recreate.
|
||||
const iouId = await CreateIouForJob({
|
||||
apolloClient: client,
|
||||
jobLinesToKeep: selectedJobLines,
|
||||
jobId: job.id,
|
||||
config: {
|
||||
const iouId = await CreateIouForJob(
|
||||
client,
|
||||
job.id,
|
||||
{
|
||||
status: bodyshop.md_ro_statuses.default_open,
|
||||
bodyshopid: bodyshop.id,
|
||||
useremail: currentUser.email
|
||||
},
|
||||
currentUser
|
||||
});
|
||||
|
||||
selectedJobLines
|
||||
);
|
||||
notification.open({
|
||||
type: "success",
|
||||
message: t("jobs.successes.ioucreated"),
|
||||
|
||||
@@ -154,10 +154,6 @@ export function JobsAvailableContainer({ bodyshop, currentUser, insertAuditTrail
|
||||
: {})
|
||||
};
|
||||
|
||||
if (currentUser?.email) {
|
||||
newJob.created_user_email = currentUser.email;
|
||||
}
|
||||
|
||||
if (selectedOwner) {
|
||||
newJob.ownerid = selectedOwner;
|
||||
delete newJob.owner;
|
||||
|
||||
@@ -175,33 +175,25 @@ export function JobsDetailHeaderActions({
|
||||
};
|
||||
|
||||
const handleDuplicate = () =>
|
||||
DuplicateJob({
|
||||
apolloClient: client,
|
||||
jobId: job.id,
|
||||
config: { defaultOpenStatus: bodyshop.md_ro_statuses.default_imported },
|
||||
completionCallback: (newJobId) => {
|
||||
DuplicateJob(
|
||||
client,
|
||||
job.id,
|
||||
{ defaultOpenStatus: bodyshop.md_ro_statuses.default_imported },
|
||||
(newJobId) => {
|
||||
history(`/manage/jobs/${newJobId}`);
|
||||
notification.success({
|
||||
message: t("jobs.successes.duplicated")
|
||||
});
|
||||
},
|
||||
keepJobLines: true,
|
||||
currentUser
|
||||
});
|
||||
true
|
||||
);
|
||||
|
||||
const handleDuplicateConfirm = () =>
|
||||
DuplicateJob({
|
||||
apolloClient: client,
|
||||
jobId: job.id,
|
||||
config: { defaultOpenStatus: bodyshop.md_ro_statuses.default_imported },
|
||||
completionCallback: (newJobId) => {
|
||||
history(`/manage/jobs/${newJobId}`);
|
||||
notification.success({
|
||||
message: t("jobs.successes.duplicated")
|
||||
});
|
||||
},
|
||||
keepJobLines: false,
|
||||
currentUser
|
||||
DuplicateJob(client, job.id, { defaultOpenStatus: bodyshop.md_ro_statuses.default_imported }, (newJobId) => {
|
||||
history(`/manage/jobs/${newJobId}`);
|
||||
notification.success({
|
||||
message: t("jobs.successes.duplicated")
|
||||
});
|
||||
});
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
|
||||
@@ -5,14 +5,7 @@ import { INSERT_NEW_JOB, QUERY_JOB_FOR_DUPE } from "../../graphql/jobs.queries";
|
||||
import dayjs from "../../utils/day";
|
||||
import i18n from "i18next";
|
||||
|
||||
export default async function DuplicateJob({
|
||||
apolloClient,
|
||||
jobId,
|
||||
config,
|
||||
completionCallback,
|
||||
keepJobLines = false,
|
||||
currentUser
|
||||
}) {
|
||||
export default async function DuplicateJob(apolloClient, jobId, config, completionCallback, keepJobLines = false) {
|
||||
logImEXEvent("job_duplicate");
|
||||
|
||||
const { defaultOpenStatus } = config;
|
||||
@@ -26,7 +19,6 @@ export default async function DuplicateJob({
|
||||
const existingJob = _.cloneDeep(jobs_by_pk);
|
||||
delete existingJob.__typename;
|
||||
delete existingJob.id;
|
||||
delete existingJob.created_user_email;
|
||||
delete existingJob.createdat;
|
||||
delete existingJob.updatedat;
|
||||
delete existingJob.cieca_stl;
|
||||
@@ -37,10 +29,6 @@ export default async function DuplicateJob({
|
||||
status: defaultOpenStatus
|
||||
};
|
||||
|
||||
if (currentUser?.email) {
|
||||
newJob.created_user_email = currentUser.email;
|
||||
}
|
||||
|
||||
const _tempLines = _.cloneDeep(existingJob.joblines);
|
||||
_tempLines.forEach((line) => {
|
||||
delete line.id;
|
||||
@@ -67,7 +55,7 @@ export default async function DuplicateJob({
|
||||
return;
|
||||
}
|
||||
|
||||
export async function CreateIouForJob({ apolloClient, jobId, config, jobLinesToKeep, currentUser }) {
|
||||
export async function CreateIouForJob(apolloClient, jobId, config, jobLinesToKeep) {
|
||||
logImEXEvent("job_create_iou");
|
||||
|
||||
const { status } = config;
|
||||
@@ -121,9 +109,6 @@ export async function CreateIouForJob({ apolloClient, jobId, config, jobLinesToK
|
||||
delete newJob.joblines;
|
||||
newJob.joblines = { data: _tempLines };
|
||||
|
||||
if (currentUser?.email) {
|
||||
newJob.created_user_email = currentUser.email;
|
||||
}
|
||||
const res2 = await apolloClient.mutate({
|
||||
mutation: INSERT_NEW_JOB,
|
||||
variables: { job: [newJob] }
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { DeleteFilled } from "@ant-design/icons";
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import { Button, DatePicker, Form, Input, InputNumber, Radio, Select, Space, Switch } from "antd";
|
||||
import { Button, Form, Input, InputNumber, Select, Space, Switch } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import DatePickerRanges from "../../utils/DatePickerRanges";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import FeatureWrapper, { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
|
||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||
import FormItemEmail from "../form-items-formatted/email-form-item.component";
|
||||
@@ -26,14 +23,6 @@ export default connect(mapStateToProps, mapDispatchToProps)(ShopInfoGeneral);
|
||||
export function ShopInfoGeneral({ form, bodyshop }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const {
|
||||
treatments: { ClosingPeriod, ADPPayroll }
|
||||
} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["ClosingPeriod", "ADPPayroll"],
|
||||
splitKey: bodyshop?.imexshopid
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<LayoutFormRow header={t("bodyshop.labels.businessinformation")} id="businessinformation">
|
||||
@@ -143,299 +132,6 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
||||
<InputNumber min={0} />
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow header={t("bodyshop.labels.accountingsetup")} id="accountingsetup">
|
||||
{[
|
||||
...(HasFeatureAccess({ featureName: "export", bodyshop })
|
||||
? [
|
||||
<Form.Item
|
||||
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
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<InputNumber />
|
||||
</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>
|
||||
]
|
||||
: [])
|
||||
]
|
||||
: []),
|
||||
<Form.Item
|
||||
key="accumulatePayableLines"
|
||||
name={["accountingconfig", "accumulatePayableLines"]}
|
||||
label={t("bodyshop.fields.accumulatePayableLines")}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
]}
|
||||
</LayoutFormRow>
|
||||
<FeatureWrapper featureName="scoreboard" noauth={() => null}>
|
||||
<LayoutFormRow header={t("bodyshop.labels.scoreboardsetup")} id="scoreboardsetup">
|
||||
<Form.Item
|
||||
@@ -499,6 +195,19 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
||||
</FeatureWrapper>
|
||||
<LayoutFormRow header={t("bodyshop.labels.systemsettings")} id="systemsettings">
|
||||
{[
|
||||
<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>,
|
||||
<Form.Item
|
||||
key="md_referral_sources"
|
||||
name={["md_referral_sources"]}
|
||||
@@ -1568,11 +1277,3 @@ export function ShopInfoGeneral({ form, bodyshop }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const ReceivableCustomFieldSelect = (
|
||||
<Select allowClear>
|
||||
<Select.Option value="v_vin">VIN</Select.Option>
|
||||
<Select.Option value="clm_no">Claim No.</Select.Option>
|
||||
<Select.Option value="ded_amt">Deductible Amount</Select.Option>
|
||||
</Select>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DeleteFilled } from "@ant-design/icons";
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import { Button, Form, Input, InputNumber, Select, Space, Switch } from "antd";
|
||||
import { Button, DatePicker, Form, Input, InputNumber, Radio, Select, Space, Switch } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
@@ -14,6 +14,7 @@ import FormListMoveArrows from "../form-list-move-arrows/form-list-move-arrows.c
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
|
||||
import ShopInfoResponsibilitycentersTaxesComponent from "./shop-info.responsibilitycenters.taxes.component";
|
||||
import DatePickerRanges from "../../utils/DatePickerRanges";
|
||||
|
||||
const SelectorDiv = styled.div`
|
||||
.ant-form-item .ant-select {
|
||||
@@ -34,11 +35,11 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const {
|
||||
treatments: { Qb_Multi_Ar, DmsAp }
|
||||
treatments: { ClosingPeriod, ADPPayroll, Qb_Multi_Ar, DmsAp }
|
||||
} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Qb_Multi_Ar", "DmsAp"],
|
||||
splitKey: bodyshop && bodyshop.imexshopid
|
||||
names: ["ClosingPeriod", "ADPPayroll", "Qb_Multi_Ar", "DmsAp"],
|
||||
splitKey: bodyshop?.imexshopid
|
||||
});
|
||||
|
||||
const [costOptions, setCostOptions] = useState([
|
||||
@@ -58,19 +59,313 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
||||
setProfitOptions([...(form.getFieldValue(["md_responsibility_centers", "profits"]).map((i) => i && i.name) || [])]);
|
||||
};
|
||||
|
||||
const ReceivableCustomFieldSelect = (
|
||||
<Select allowClear>
|
||||
<Select.Option value="v_vin">VIN</Select.Option>
|
||||
<Select.Option value="clm_no">Claim No.</Select.Option>
|
||||
<Select.Option value="ded_amt">Deductible Amount</Select.Option>
|
||||
</Select>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<RbacWrapper action="shop:responsibilitycenter">
|
||||
<LayoutFormRow header={t("bodyshop.labels.accountingsetup")} id="accountingsetup">
|
||||
{[
|
||||
...(HasFeatureAccess({ featureName: "export", bodyshop })
|
||||
? !bodyshop.cdk_dealerid && !bodyshop.pbs_serialnumber
|
||||
? [
|
||||
<Form.Item
|
||||
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="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>,
|
||||
<Form.Item
|
||||
key="accumulatePayableLines"
|
||||
name={["accountingconfig", "accumulatePayableLines"]}
|
||||
label={t("bodyshop.fields.accumulatePayableLines")}
|
||||
valuePropName="checked"
|
||||
>
|
||||
<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
|
||||
//message: t("general.validation.required"),
|
||||
}
|
||||
]}
|
||||
>
|
||||
<InputNumber />
|
||||
</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>,
|
||||
...(HasFeatureAccess({ featureName: "export", bodyshop })
|
||||
? [
|
||||
...(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>
|
||||
{(bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber) && (
|
||||
<>
|
||||
{bodyshop.cdk_dealerid && (
|
||||
<DataLabel label={t("bodyshop.labels.dms.cdk_dealerid")}>{form.getFieldValue("cdk_dealerid")}</DataLabel>
|
||||
)}
|
||||
{bodyshop.pbs_serialnumber && (
|
||||
<DataLabel label={t("bodyshop.labels.dms.pbs_serialnumber")}>
|
||||
{form.getFieldValue("pbs_serialnumber")}
|
||||
</DataLabel>
|
||||
)}
|
||||
<LayoutFormRow id="dmsconfiguration">
|
||||
{bodyshop.cdk_dealerid && (
|
||||
<DataLabel label={t("bodyshop.labels.dms.cdk_dealerid")}>
|
||||
{form.getFieldValue("cdk_dealerid")}
|
||||
</DataLabel>
|
||||
)}
|
||||
{bodyshop.pbs_serialnumber && (
|
||||
<DataLabel label={t("bodyshop.labels.dms.pbs_serialnumber")}>
|
||||
{form.getFieldValue("pbs_serialnumber")}
|
||||
</DataLabel>
|
||||
)}
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow>
|
||||
<Form.Item
|
||||
label={t("bodyshop.fields.dms.default_journal")}
|
||||
@@ -307,13 +602,6 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
|
||||
</LayoutFormRow>
|
||||
</>
|
||||
)}
|
||||
{bodyshop.pbs_serialnumber && (
|
||||
<>
|
||||
<DataLabel label={t("bodyshop.labels.dms.pbs_serialnumber")}>
|
||||
{form.getFieldValue("pbs_serialnumber")}
|
||||
</DataLabel>
|
||||
</>
|
||||
)}
|
||||
{HasFeatureAccess({ featureName: "export", bodyshop }) && (
|
||||
<>
|
||||
<LayoutFormRow header={t("bodyshop.labels.responsibilitycenters.costs")} id="costs">
|
||||
|
||||
@@ -9,23 +9,21 @@ import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
import { INSERT_NEW_JOB } from "../../graphql/jobs.queries";
|
||||
import { QUERY_OWNER_FOR_JOB_CREATION } from "../../graphql/owners.queries";
|
||||
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
|
||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import JobsCreateComponent from "./jobs-create.component";
|
||||
import JobCreateContext from "./jobs-create.context";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
currentUser: selectCurrentUser
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||
setSelectedHeader: (key) => dispatch(setSelectedHeader(key))
|
||||
});
|
||||
|
||||
function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, currentUser }) {
|
||||
function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader }) {
|
||||
const { t } = useTranslation();
|
||||
const notification = useNotification();
|
||||
|
||||
@@ -76,7 +74,7 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, curr
|
||||
}, [t, setBreadcrumbs, setSelectedHeader]);
|
||||
|
||||
const runInsertJob = (job) => {
|
||||
insertJob({ variables: { job } })
|
||||
insertJob({ variables: { job: job } })
|
||||
.then((resp) => {
|
||||
setState({
|
||||
...state,
|
||||
@@ -152,11 +150,6 @@ function JobsCreateContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, curr
|
||||
if (job.owner === null) delete job.owner;
|
||||
if (job.vehicle === null) delete job.vehicle;
|
||||
|
||||
// Associate to the current user if one exists
|
||||
if (currentUser?.email) {
|
||||
job.created_user_email = currentUser.email;
|
||||
}
|
||||
|
||||
runInsertJob(job);
|
||||
};
|
||||
|
||||
|
||||
@@ -3684,7 +3684,6 @@
|
||||
- completed_tasks
|
||||
- converted
|
||||
- created_at
|
||||
- created_user_email
|
||||
- cust_pr
|
||||
- date_estimated
|
||||
- date_exported
|
||||
@@ -3962,7 +3961,6 @@
|
||||
- completed_tasks
|
||||
- converted
|
||||
- created_at
|
||||
- created_user_email
|
||||
- cust_pr
|
||||
- date_estimated
|
||||
- date_exported
|
||||
@@ -4253,7 +4251,6 @@
|
||||
- completed_tasks
|
||||
- converted
|
||||
- created_at
|
||||
- created_user_email
|
||||
- cust_pr
|
||||
- date_estimated
|
||||
- date_exported
|
||||
@@ -4644,7 +4641,7 @@
|
||||
request_transform:
|
||||
body:
|
||||
action: transform
|
||||
template: "{\r\n \"event\": {\r\n \"session_variables\": {\r\n \"x-hasura-user-id\": {{$body?.event?.session_variables?.x-hasura-user-id ?? \"Internal\"}},\r\n \"x-hasura-role\": {{$body?.event?.session_variables?.x-hasura-role ?? \"Internal\"}}\r\n }, \r\n \"op\": {{$body.event.op}},\r\n \"data\": {\r\n \"new\": {\r\n \"id\": {{$body.event.data.new.id}},\r\n \"shopid\": {{$body.event.data.new?.shopid}},\r\n \"ro_number\": {{$body.event.data.new?.ro_number}},\r\n \"created_user_email\": {{$body.event.data.new?.created_user_email}}\r\n }\r\n }\r\n },\r\n \"trigger\": {\r\n \"name\": \"notifications_jobs_autoadd\"\r\n },\r\n \"table\": {\r\n \"schema\": \"public\",\r\n \"name\": \"jobs\"\r\n }\r\n}\r\n"
|
||||
template: "{\r\n \"event\": {\r\n \"session_variables\": {\r\n \"x-hasura-user-id\": {{$body?.event?.session_variables?.x-hasura-user-id ?? \"Internal\"}},\r\n \"x-hasura-role\": {{$body?.event?.session_variables?.x-hasura-role ?? \"Internal\"}}\r\n }, \r\n \"op\": {{$body.event.op}},\r\n \"data\": {\r\n \"new\": {\r\n \"id\": {{$body.event.data.new.id}},\r\n \"shopid\": {{$body.event.data.new?.shopid}},\r\n \"ro_number\": {{$body.event.data.new?.ro_number}}\r\n }\r\n }\r\n },\r\n \"trigger\": {\r\n \"name\": \"notifications_jobs_autoadd\"\r\n },\r\n \"table\": {\r\n \"schema\": \"public\",\r\n \"name\": \"jobs\"\r\n }\r\n}\r\n"
|
||||
method: POST
|
||||
query_params: {}
|
||||
template_engine: Kriti
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
-- Could not auto-generate a down migration.
|
||||
-- Please write an appropriate down migration for the SQL below:
|
||||
-- alter table "public"."jobs" add column "created_user_email" text
|
||||
-- null;
|
||||
@@ -1,2 +0,0 @@
|
||||
alter table "public"."jobs" add column "created_user_email" text
|
||||
null;
|
||||
@@ -3089,19 +3089,17 @@ exports.INSERT_JOB_WATCHERS = `
|
||||
`;
|
||||
|
||||
exports.GET_NOTIFICATION_WATCHERS = `
|
||||
query GET_NOTIFICATION_WATCHERS($shopId: uuid!, $employeeIds: [uuid!]!, $createdUserEmail: String!) {
|
||||
query GET_NOTIFICATION_WATCHERS($shopId: uuid!, $employeeIds: [uuid!]!) {
|
||||
associations(where: {
|
||||
_and: [
|
||||
{ shopid: { _eq: $shopId } },
|
||||
{ active: { _eq: true } },
|
||||
{ notifications_autoadd: { _eq: true } },
|
||||
{ useremail: { _eq: $createdUserEmail } }
|
||||
{ notifications_autoadd: { _eq: true } }
|
||||
]
|
||||
}) {
|
||||
id
|
||||
useremail
|
||||
}
|
||||
|
||||
employees(where: { id: { _in: $employeeIds }, shopid: { _eq: $shopId }, active: { _eq: true } }) {
|
||||
user_email
|
||||
}
|
||||
|
||||
@@ -39,7 +39,6 @@ const autoAddWatchers = async (req) => {
|
||||
const jobId = event?.data?.new?.id;
|
||||
const shopId = event?.data?.new?.shopid;
|
||||
const roNumber = event?.data?.new?.ro_number || "unknown";
|
||||
const createdUserEmail = event?.data?.new?.created_user_email || "Unknown";
|
||||
|
||||
if (!jobId || !shopId) {
|
||||
throw new Error(`Missing jobId (${jobId}) or shopId (${shopId}) for auto-add watchers`);
|
||||
@@ -62,8 +61,7 @@ const autoAddWatchers = async (req) => {
|
||||
const [notificationData, existingWatchersData] = await Promise.all([
|
||||
gqlClient.request(GET_NOTIFICATION_WATCHERS, {
|
||||
shopId,
|
||||
employeeIds: notificationFollowers,
|
||||
createdUserEmail
|
||||
employeeIds: notificationFollowers
|
||||
}),
|
||||
gqlClient.request(GET_JOB_WATCHERS_MINIMAL, { jobid: jobId })
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user