Merge branch 'release/2024-03-22' into master-AIO
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import {useMutation, useQuery} from "@apollo/client";
|
||||
import {Button, Form, Popconfirm, Space} from "antd";
|
||||
import {Button, Divider, Form, Popconfirm, Space} from "antd";
|
||||
import dayjs from "../../utils/day";
|
||||
import queryString from "query-string";
|
||||
import React, {useState} from "react";
|
||||
@@ -203,7 +203,7 @@ export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail,
|
||||
layout="vertical"
|
||||
>
|
||||
<BillFormContainer form={form} billEdit disabled={exported}/>
|
||||
|
||||
<Divider orientation="left">{t("general.labels.media")}</Divider>
|
||||
{bodyshop.uselocalmediaserver ? (
|
||||
<JobsDocumentsLocalGallery
|
||||
job={{id: data ? data.bills_by_pk.jobid : null}}
|
||||
|
||||
@@ -173,7 +173,11 @@ export function BillDetailEditReturn({
|
||||
</Form>
|
||||
</Modal>
|
||||
<Button
|
||||
disabled={data.bills_by_pk.is_credit_memo || disabled}
|
||||
disabled={
|
||||
data.bills_by_pk.is_credit_memo ||
|
||||
data.bills_by_pk.isinhouse ||
|
||||
disabled
|
||||
}
|
||||
onClick={() => {
|
||||
setOpen(true);
|
||||
}}
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import Icon, { UploadOutlined } from "@ant-design/icons";
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import { useSplitTreatments } from "@splitsoftware/splitio-react";
|
||||
import { Alert, Divider, Form, Input, Select, Space, Statistic, Switch, Upload, } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { MdOpenInNew } from "react-icons/md";
|
||||
import { connect } from "react-redux";
|
||||
import { Link } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { CHECK_BILL_INVOICE_NUMBER } from "../../graphql/bills.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import dayjs from "../../utils/day";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import BillFormLinesExtended from "../bill-form-lines-extended/bill-form-lines-extended.component";
|
||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
|
||||
import JobSearchSelect from "../job-search-select/job-search-select.component";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import VendorSearchSelect from "../vendor-search-select/vendor-search-select.component";
|
||||
import BillFormLines from "./bill-form.lines.component";
|
||||
import { CalculateBillTotal } from "./bill-form.totals.utility";
|
||||
import Icon, { UploadOutlined } from '@ant-design/icons';
|
||||
import { useApolloClient } from '@apollo/client';
|
||||
import { useSplitTreatments } from '@splitsoftware/splitio-react';
|
||||
import { Alert, Divider, Form, Input, Select, Space, Statistic, Switch, Upload } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { MdOpenInNew } from 'react-icons/md';
|
||||
import { connect } from 'react-redux';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { createStructuredSelector } from 'reselect';
|
||||
import { CHECK_BILL_INVOICE_NUMBER } from '../../graphql/bills.queries';
|
||||
import { selectBodyshop } from '../../redux/user/user.selectors';
|
||||
import dayjs from '../../utils/day';
|
||||
import InstanceRenderManager from '../../utils/instanceRenderMgr';
|
||||
import AlertComponent from '../alert/alert.component';
|
||||
import BillFormLinesExtended from '../bill-form-lines-extended/bill-form-lines-extended.component';
|
||||
import FormDatePicker from '../form-date-picker/form-date-picker.component';
|
||||
import FormFieldsChanged from '../form-fields-changed-alert/form-fields-changed-alert.component';
|
||||
import CurrencyInput from '../form-items-formatted/currency-form-item.component';
|
||||
import JobSearchSelect from '../job-search-select/job-search-select.component';
|
||||
import LayoutFormRow from '../layout-form-row/layout-form-row.component';
|
||||
import VendorSearchSelect from '../vendor-search-select/vendor-search-select.component';
|
||||
import BillFormLines from './bill-form.lines.component';
|
||||
import { CalculateBillTotal } from './bill-form.totals.utility';
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -41,20 +41,20 @@ export function BillFormComponent({
|
||||
job,
|
||||
loadOutstandingReturns,
|
||||
loadInventory,
|
||||
preferredMake
|
||||
preferredMake,
|
||||
}) {
|
||||
|
||||
const { t } = useTranslation();
|
||||
const client = useApolloClient();
|
||||
const [discount, setDiscount] = useState(0);
|
||||
|
||||
const {treatments: {Extended_Bill_Posting, ClosingPeriod}} = useSplitTreatments({
|
||||
const {
|
||||
treatments: { Extended_Bill_Posting, ClosingPeriod },
|
||||
} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Extended_Bill_Posting", "ClosingPeriod"],
|
||||
names: ['Extended_Bill_Posting', 'ClosingPeriod'],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
|
||||
const handleVendorSelect = (props, opt) => {
|
||||
setDiscount(opt.discount);
|
||||
|
||||
@@ -62,7 +62,7 @@ export function BillFormComponent({
|
||||
!billEdit &&
|
||||
loadOutstandingReturns({
|
||||
variables: {
|
||||
jobId: form.getFieldValue("jobid"),
|
||||
jobId: form.getFieldValue('jobid'),
|
||||
vendorId: opt.value,
|
||||
},
|
||||
});
|
||||
@@ -71,7 +71,7 @@ export function BillFormComponent({
|
||||
const handleFederalTaxExemptSwitchToggle = (checked) => {
|
||||
// Early gate
|
||||
if (!checked) return;
|
||||
const values = form.getFieldsValue("billlines");
|
||||
const values = form.getFieldsValue('billlines');
|
||||
// Gate bill lines
|
||||
if (!values?.billlines?.length) return;
|
||||
|
||||
@@ -83,23 +83,21 @@ export function BillFormComponent({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (job) form.validateFields(["is_credit_memo"]);
|
||||
if (job) form.validateFields(['is_credit_memo']);
|
||||
}, [job, form]);
|
||||
|
||||
useEffect(() => {
|
||||
const vendorId = form.getFieldValue("vendorid");
|
||||
const vendorId = form.getFieldValue('vendorid');
|
||||
if (vendorId && vendorAutoCompleteOptions) {
|
||||
const matchingVendors = vendorAutoCompleteOptions.filter(
|
||||
(v) => v.id === vendorId
|
||||
);
|
||||
const matchingVendors = vendorAutoCompleteOptions.filter((v) => v.id === vendorId);
|
||||
if (matchingVendors.length === 1) {
|
||||
setDiscount(matchingVendors[0].discount);
|
||||
}
|
||||
}
|
||||
const jobId = form.getFieldValue("jobid");
|
||||
const jobId = form.getFieldValue('jobid');
|
||||
if (jobId) {
|
||||
loadLines({ variables: { id: jobId } });
|
||||
if (form.getFieldValue("is_credit_memo") && vendorId && !billEdit) {
|
||||
if (form.getFieldValue('is_credit_memo') && vendorId && !billEdit) {
|
||||
loadOutstandingReturns({
|
||||
variables: {
|
||||
jobId: jobId,
|
||||
@@ -126,17 +124,13 @@ export function BillFormComponent({
|
||||
return (
|
||||
<div>
|
||||
<FormFieldsChanged form={form} />
|
||||
<Form.Item
|
||||
style={{display: "none"}}
|
||||
name="isinhouse"
|
||||
valuePropName="checked"
|
||||
>
|
||||
<Form.Item style={{ display: 'none' }} name="isinhouse" valuePropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<LayoutFormRow grow>
|
||||
<Form.Item
|
||||
name="jobid"
|
||||
label={t("bills.fields.ro_number")}
|
||||
label={t('bills.fields.ro_number')}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
@@ -149,13 +143,19 @@ export function BillFormComponent({
|
||||
convertedOnly
|
||||
notExported={false}
|
||||
onBlur={() => {
|
||||
if (form.getFieldValue("jobid") !== null && form.getFieldValue("jobid") !== undefined) {
|
||||
loadLines({variables: {id: form.getFieldValue("jobid")}});
|
||||
if (form.getFieldValue("vendorid") !== null && form.getFieldValue("vendorid") !== undefined) {
|
||||
if (
|
||||
form.getFieldValue('jobid') !== null &&
|
||||
form.getFieldValue('jobid') !== undefined
|
||||
) {
|
||||
loadLines({ variables: { id: form.getFieldValue('jobid') } });
|
||||
if (
|
||||
form.getFieldValue('vendorid') !== null &&
|
||||
form.getFieldValue('vendorid') !== undefined
|
||||
) {
|
||||
loadOutstandingReturns({
|
||||
variables: {
|
||||
jobId: form.getFieldValue("jobid"),
|
||||
vendorId: form.getFieldValue("vendorid"),
|
||||
jobId: form.getFieldValue('jobid'),
|
||||
vendorId: form.getFieldValue('vendorid'),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -164,7 +164,7 @@ export function BillFormComponent({
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bills.fields.vendor")}
|
||||
label={t('bills.fields.vendor')}
|
||||
name="vendorid"
|
||||
// style={{ display: billEdit ? "none" : null }}
|
||||
rules={[
|
||||
@@ -174,12 +174,8 @@ export function BillFormComponent({
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
validator(rule, value) {
|
||||
if (
|
||||
value &&
|
||||
!getFieldValue(["isinhouse"]) &&
|
||||
value === bodyshop.inhousevendorid
|
||||
) {
|
||||
return Promise.reject(t("bills.validation.manualinhouse"));
|
||||
if (value && !getFieldValue(['isinhouse']) && value === bodyshop.inhousevendorid) {
|
||||
return Promise.reject(t('bills.validation.manualinhouse'));
|
||||
}
|
||||
return Promise.resolve();
|
||||
},
|
||||
@@ -203,7 +199,7 @@ export function BillFormComponent({
|
||||
type="warning"
|
||||
message={
|
||||
<Space>
|
||||
{t("bills.labels.iouexists")}
|
||||
{t('bills.labels.iouexists')}
|
||||
<Link
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@@ -220,7 +216,7 @@ export function BillFormComponent({
|
||||
))}
|
||||
<LayoutFormRow>
|
||||
<Form.Item
|
||||
label={t("bills.fields.invoice_number")}
|
||||
label={t('bills.fields.invoice_number')}
|
||||
name="invoice_number"
|
||||
validateTrigger="onBlur"
|
||||
hasFeedback
|
||||
@@ -231,7 +227,7 @@ export function BillFormComponent({
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
async validator(rule, value) {
|
||||
const vendorid = getFieldValue("vendorid");
|
||||
const vendorid = getFieldValue('vendorid');
|
||||
if (vendorid && value) {
|
||||
const response = await client.query({
|
||||
query: CHECK_BILL_INVOICE_NUMBER,
|
||||
@@ -245,14 +241,11 @@ export function BillFormComponent({
|
||||
return Promise.resolve();
|
||||
} else if (
|
||||
response.data.bills_aggregate.nodes.length === 1 &&
|
||||
response.data.bills_aggregate.nodes[0].id ===
|
||||
form.getFieldValue("id")
|
||||
response.data.bills_aggregate.nodes[0].id === form.getFieldValue('id')
|
||||
) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.reject(
|
||||
t("bills.validation.unique_invoice_number")
|
||||
);
|
||||
return Promise.reject(t('bills.validation.unique_invoice_number'));
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@@ -263,7 +256,7 @@ export function BillFormComponent({
|
||||
<Input disabled={disabled || disableInvNumber} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bills.fields.date")}
|
||||
label={t('bills.fields.date')}
|
||||
name="date"
|
||||
rules={[
|
||||
{
|
||||
@@ -272,29 +265,22 @@ export function BillFormComponent({
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
validator(rule, value) {
|
||||
if (
|
||||
ClosingPeriod.treatment === "on" &&
|
||||
bodyshop.accountingconfig.ClosingPeriod
|
||||
) {
|
||||
if (ClosingPeriod.treatment === 'on' && bodyshop.accountingconfig.ClosingPeriod) {
|
||||
if (
|
||||
dayjs(value)
|
||||
.startOf("day")
|
||||
.startOf('day')
|
||||
.isSameOrAfter(
|
||||
dayjs(
|
||||
bodyshop.accountingconfig.ClosingPeriod[0]
|
||||
).startOf("day")
|
||||
dayjs(bodyshop.accountingconfig.ClosingPeriod[0]).startOf('day')
|
||||
) &&
|
||||
dayjs(value)
|
||||
.startOf("day")
|
||||
.startOf('day')
|
||||
.isSameOrBefore(
|
||||
dayjs(
|
||||
bodyshop.accountingconfig.ClosingPeriod[1]
|
||||
).endOf("day")
|
||||
dayjs(bodyshop.accountingconfig.ClosingPeriod[1]).endOf('day')
|
||||
)
|
||||
) {
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return Promise.reject(t("bills.validation.closingperiod"));
|
||||
return Promise.reject(t('bills.validation.closingperiod'));
|
||||
}
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
@@ -306,17 +292,13 @@ export function BillFormComponent({
|
||||
<FormDatePicker disabled={disabled} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bills.fields.is_credit_memo")}
|
||||
label={t('bills.fields.is_credit_memo')}
|
||||
name="is_credit_memo"
|
||||
valuePropName="checked"
|
||||
rules={[
|
||||
({ getFieldValue }) => ({
|
||||
validator(rule, value) {
|
||||
if (
|
||||
value === true &&
|
||||
getFieldValue("jobid") &&
|
||||
getFieldValue("vendorid")
|
||||
) {
|
||||
if (value === true && getFieldValue('jobid') && getFieldValue('vendorid')) {
|
||||
//Removed as this would cause an additional reload when validating the form on submit and clear the values.
|
||||
// loadOutstandingReturns({
|
||||
// variables: {
|
||||
@@ -334,7 +316,7 @@ export function BillFormComponent({
|
||||
job.status === bodyshop.md_ro_statuses.default_void) &&
|
||||
(value === false || !value)
|
||||
) {
|
||||
return Promise.reject(t("bills.labels.onlycmforinvoiced"));
|
||||
return Promise.reject(t('bills.labels.onlycmforinvoiced'));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
@@ -345,7 +327,7 @@ export function BillFormComponent({
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label={t("bills.fields.total")}
|
||||
label={t('bills.fields.total')}
|
||||
name="total"
|
||||
rules={[
|
||||
{
|
||||
@@ -357,8 +339,8 @@ export function BillFormComponent({
|
||||
<CurrencyInput min={0} disabled={disabled} />
|
||||
</Form.Item>
|
||||
{!billEdit && (
|
||||
<Form.Item label={t("bills.fields.allpartslocation")} name="location">
|
||||
<Select style={{width: "10rem"}} disabled={disabled} allowClear>
|
||||
<Form.Item label={t('bills.fields.allpartslocation')} name="location">
|
||||
<Select style={{ width: '10rem' }} disabled={disabled} allowClear>
|
||||
{bodyshop.md_parts_locations.map((loc, idx) => (
|
||||
<Select.Option key={idx} value={loc}>
|
||||
{loc}
|
||||
@@ -369,115 +351,99 @@ export function BillFormComponent({
|
||||
)}
|
||||
</LayoutFormRow>
|
||||
<LayoutFormRow>
|
||||
{
|
||||
InstanceRenderManager({imex:
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.federal_tax_rate")}
|
||||
name="federal_tax_rate"
|
||||
>
|
||||
<CurrencyInput min={0} disabled={disabled} />
|
||||
</Form.Item> })
|
||||
|
||||
}
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.state_tax_rate")}
|
||||
name="state_tax_rate"
|
||||
>
|
||||
{InstanceRenderManager({
|
||||
imex: (
|
||||
<Form.Item span={3} label={t('bills.fields.federal_tax_rate')} name="federal_tax_rate">
|
||||
<CurrencyInput min={0} disabled={disabled} />
|
||||
</Form.Item>
|
||||
{
|
||||
InstanceRenderManager({imex: <>
|
||||
<Form.Item
|
||||
span={3}
|
||||
label={t("bills.fields.local_tax_rate")}
|
||||
name="local_tax_rate"
|
||||
>
|
||||
),
|
||||
})}
|
||||
<Form.Item span={3} label={t('bills.fields.state_tax_rate')} name="state_tax_rate">
|
||||
<CurrencyInput min={0} disabled={disabled} />
|
||||
</Form.Item>
|
||||
{InstanceRenderManager({
|
||||
imex: (
|
||||
<>
|
||||
<Form.Item span={3} label={t('bills.fields.local_tax_rate')} name="local_tax_rate">
|
||||
<CurrencyInput min={0} />
|
||||
</Form.Item>
|
||||
{bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (
|
||||
<Form.Item
|
||||
span={2}
|
||||
label={t("bills.labels.federal_tax_exempt")}
|
||||
label={t('bills.labels.federal_tax_exempt')}
|
||||
name="federal_tax_exempt"
|
||||
>
|
||||
<Switch onChange={handleFederalTaxExemptSwitchToggle} />
|
||||
</Form.Item>
|
||||
) : null}
|
||||
</>})
|
||||
}
|
||||
</>
|
||||
),
|
||||
})}
|
||||
<Form.Item shouldUpdate span={13}>
|
||||
{() => {
|
||||
const values = form.getFieldsValue([
|
||||
"billlines",
|
||||
"total",
|
||||
"federal_tax_rate",
|
||||
"state_tax_rate",
|
||||
"local_tax_rate",
|
||||
'billlines',
|
||||
'total',
|
||||
'federal_tax_rate',
|
||||
'state_tax_rate',
|
||||
'local_tax_rate',
|
||||
]);
|
||||
let totals;
|
||||
if (
|
||||
!!values.total &&
|
||||
!!values.billlines &&
|
||||
values.billlines.length > 0
|
||||
)
|
||||
if (!!values.total && !!values.billlines && values.billlines.length > 0)
|
||||
totals = CalculateBillTotal(values);
|
||||
if (!!totals)
|
||||
return (
|
||||
<div align="right">
|
||||
<Space wrap>
|
||||
<Statistic
|
||||
title={t("bills.labels.subtotal")}
|
||||
title={t('bills.labels.subtotal')}
|
||||
value={totals.subtotal.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
{
|
||||
InstanceRenderManager({imex: <Statistic
|
||||
title={t("bills.labels.federal_tax")}
|
||||
{InstanceRenderManager({
|
||||
imex: (
|
||||
<Statistic
|
||||
title={t('bills.labels.federal_tax')}
|
||||
value={totals.federalTax.toFormat()}
|
||||
precision={2}
|
||||
/> })
|
||||
}
|
||||
/>
|
||||
),
|
||||
})}
|
||||
<Statistic
|
||||
title={t("bills.labels.state_tax")}
|
||||
title={t('bills.labels.state_tax')}
|
||||
value={totals.stateTax.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
{
|
||||
InstanceRenderManager({imex: <Statistic
|
||||
title={t("bills.labels.local_tax")}
|
||||
{InstanceRenderManager({
|
||||
imex: (
|
||||
<Statistic
|
||||
title={t('bills.labels.local_tax')}
|
||||
value={totals.localTax.toFormat()}
|
||||
precision={2}
|
||||
/>})
|
||||
}
|
||||
/>
|
||||
),
|
||||
})}
|
||||
<Statistic
|
||||
title={t("bills.labels.entered_total")}
|
||||
title={t('bills.labels.entered_total')}
|
||||
value={totals.enteredTotal.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
<Statistic
|
||||
title={t("bills.labels.bill_total")}
|
||||
title={t('bills.labels.bill_total')}
|
||||
value={totals.invoiceTotal.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
<Statistic
|
||||
title={t("bills.labels.discrepancy")}
|
||||
title={t('bills.labels.discrepancy')}
|
||||
valueStyle={{
|
||||
color:
|
||||
totals.discrepancy.getAmount() === 0
|
||||
? "green"
|
||||
: "red",
|
||||
color: totals.discrepancy.getAmount() === 0 ? 'green' : 'red',
|
||||
}}
|
||||
value={totals.discrepancy.toFormat()}
|
||||
precision={2}
|
||||
/>
|
||||
</Space>
|
||||
{form.getFieldValue("is_credit_memo") ? (
|
||||
<AlertComponent
|
||||
type="warning"
|
||||
message={t("bills.labels.enteringcreditmemo")}
|
||||
/>
|
||||
{form.getFieldValue('is_credit_memo') ? (
|
||||
<AlertComponent type="warning" message={t('bills.labels.enteringcreditmemo')} />
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
@@ -485,9 +451,9 @@ export function BillFormComponent({
|
||||
}}
|
||||
</Form.Item>
|
||||
</LayoutFormRow>
|
||||
<Divider orientation="left">{t("bills.labels.bill_lines")}</Divider>
|
||||
<Divider orientation="left">{t('bills.labels.bill_lines')}</Divider>
|
||||
|
||||
{Extended_Bill_Posting.treatment === "on" ? (
|
||||
{Extended_Bill_Posting.treatment === 'on' ? (
|
||||
<BillFormLinesExtended
|
||||
lineData={lineData}
|
||||
discount={discount}
|
||||
@@ -505,11 +471,13 @@ export function BillFormComponent({
|
||||
billEdit={billEdit}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Divider orientation="left" style={{ display: billEdit ? 'none' : null }}>
|
||||
{t('documents.labels.upload')}
|
||||
</Divider>
|
||||
<Form.Item
|
||||
name="upload"
|
||||
label="Upload"
|
||||
style={{display: billEdit ? "none" : null}}
|
||||
style={{ display: billEdit ? 'none' : null }}
|
||||
valuePropName="fileList"
|
||||
getValueFromEvent={(e) => {
|
||||
if (Array.isArray(e)) {
|
||||
@@ -518,19 +486,12 @@ export function BillFormComponent({
|
||||
return e && e.fileList;
|
||||
}}
|
||||
>
|
||||
<Upload.Dragger
|
||||
multiple={true}
|
||||
name="logo"
|
||||
beforeUpload={() => false}
|
||||
listType="picture"
|
||||
>
|
||||
<Upload.Dragger multiple={true} name="logo" beforeUpload={() => false} listType="picture">
|
||||
<>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<UploadOutlined />
|
||||
</p>
|
||||
<p className="ant-upload-text">
|
||||
Click or drag files to this area to upload.
|
||||
</p>
|
||||
<p className="ant-upload-text">Click or drag files to this area to upload.</p>
|
||||
</>
|
||||
</Upload.Dragger>
|
||||
</Form.Item>
|
||||
|
||||
@@ -60,6 +60,10 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
text: t("courtesycars.status.in"),
|
||||
value: "courtesycars.status.in",
|
||||
},
|
||||
{
|
||||
text: t("courtesycars.status.inservice"),
|
||||
value: "courtesycars.status.inservice",
|
||||
},
|
||||
{
|
||||
text: t("courtesycars.status.out"),
|
||||
value: "courtesycars.status.out",
|
||||
@@ -73,7 +77,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
value: "courtesycars.status.leasereturn",
|
||||
},
|
||||
],
|
||||
onFilter: (value, record) => value.includes(record.status),
|
||||
onFilter: (value, record) => record.status === value,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "status" && state.sortedInfo.order,
|
||||
render: (text, record) => {
|
||||
@@ -176,7 +180,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
title: t("courtesycars.fields.fuel"),
|
||||
dataIndex: "fuel",
|
||||
key: "fuel",
|
||||
sorter: (a, b) => alphaSort(a.fuel, b.fuel),
|
||||
sorter: (a, b) => a.fuel - b.fuel,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "fuel" && state.sortedInfo.order,
|
||||
render: (text, record) => {
|
||||
@@ -185,12 +189,14 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
return t("courtesycars.labels.fuel.full");
|
||||
case 88:
|
||||
return t("courtesycars.labels.fuel.78");
|
||||
case 75:
|
||||
return t("courtesycars.labels.fuel.34");
|
||||
case 63:
|
||||
return t("courtesycars.labels.fuel.58");
|
||||
case 50:
|
||||
return t("courtesycars.labels.fuel.12");
|
||||
case 38:
|
||||
return t("courtesycars.labels.fuel.34");
|
||||
return t("courtesycars.labels.fuel.38");
|
||||
case 25:
|
||||
return t("courtesycars.labels.fuel.14");
|
||||
case 13:
|
||||
|
||||
@@ -23,7 +23,6 @@ export function JobEmployeeAssignments({
|
||||
jobRO,
|
||||
body,
|
||||
refinish,
|
||||
|
||||
prep,
|
||||
csr,
|
||||
handleAdd,
|
||||
@@ -78,7 +77,7 @@ export function JobEmployeeAssignments({
|
||||
setVisibility(false);
|
||||
}}
|
||||
>
|
||||
Assign
|
||||
{t("allocations.actions.assign")}
|
||||
</Button>
|
||||
<Button onClick={() => setVisibility(false)}>Close</Button>
|
||||
</Space>
|
||||
|
||||
@@ -44,13 +44,13 @@ export function JobEmployeeAssignmentsContainer({
|
||||
});
|
||||
if (refetch) refetch();
|
||||
|
||||
if (!!!result.errors) {
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobassignmentchange(operation, name),
|
||||
type: "jobassignmentchange",
|
||||
});
|
||||
|
||||
if (!!result.errors) {
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.assigning", {
|
||||
message: JSON.stringify(result.errors),
|
||||
@@ -68,17 +68,19 @@ export function JobEmployeeAssignmentsContainer({
|
||||
variables: {jobId: job.id, job: {[empAssignment]: null}},
|
||||
});
|
||||
|
||||
if (!!result.errors) {
|
||||
if (!!!result.errors) {
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobassignmentremoved(operation),
|
||||
type: "jobassignmentremoved",
|
||||
});
|
||||
} else {
|
||||
notification["error"]({
|
||||
message: t("jobs.errors.assigning", {
|
||||
message: JSON.stringify(result.errors),
|
||||
}),
|
||||
});
|
||||
}
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobassignmentremoved(operation),
|
||||
type: "jobassignmentremoved",});
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ export default function JobReconciliationBillsTable({
|
||||
state.sortedInfo.order,
|
||||
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.bill.is_credit_memo}/>
|
||||
<Checkbox checked={record.bill.is_credit_memo}/>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -126,7 +126,7 @@ export function BillsListPage({
|
||||
state.sortedInfo.columnKey === "is_credit_memo" &&
|
||||
state.sortedInfo.order,
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.is_credit_memo}/>
|
||||
<Checkbox checked={record.is_credit_memo}/>
|
||||
),
|
||||
},
|
||||
{
|
||||
@@ -136,7 +136,7 @@ export function BillsListPage({
|
||||
sorter: (a, b) => a.exported - b.exported,
|
||||
sortOrder:
|
||||
state.sortedInfo.columnKey === "exported" && state.sortedInfo.order,
|
||||
render: (text, record) => <Checkbox disabled checked={record.exported}/>,
|
||||
render: (text, record) => <Checkbox checked={record.exported}/>,
|
||||
},
|
||||
{
|
||||
title: t("general.labels.actions"),
|
||||
|
||||
@@ -162,9 +162,7 @@ sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||
{ text: "False", value: false },
|
||||
],
|
||||
onFilter: (value, record) => record.successful === value,
|
||||
render: (text, record) => (
|
||||
<Checkbox disabled checked={record.successful}/>
|
||||
),
|
||||
render: (text, record) => <Checkbox checked={record.successful} />,
|
||||
},
|
||||
{
|
||||
title: t("general.labels.message"),
|
||||
|
||||
@@ -1165,6 +1165,7 @@
|
||||
"loadingshop": "Loading shop data...",
|
||||
"loggingin": "Authorizing...",
|
||||
"markedexported": "Manually marked as exported.",
|
||||
"media": "Media",
|
||||
"message": "Message",
|
||||
"monday": "Monday",
|
||||
"na": "N/A",
|
||||
|
||||
@@ -569,6 +569,13 @@
|
||||
table:
|
||||
name: parts_orders
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: billid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -818,6 +825,13 @@
|
||||
table:
|
||||
name: inventory
|
||||
schema: public
|
||||
- name: ioevents
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: bodyshopid
|
||||
table:
|
||||
name: ioevents
|
||||
schema: public
|
||||
- name: jobs
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -846,6 +860,13 @@
|
||||
table:
|
||||
name: phonebook
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: bodyshopid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: timetickets
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -2675,6 +2696,13 @@
|
||||
- table:
|
||||
name: ioevents
|
||||
schema: public
|
||||
object_relationships:
|
||||
- name: bodyshop
|
||||
using:
|
||||
foreign_key_constraint_on: bodyshopid
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: useremail
|
||||
- table:
|
||||
name: job_ar_schema
|
||||
schema: public
|
||||
@@ -2824,6 +2852,13 @@
|
||||
table:
|
||||
name: parts_order_lines
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: joblineid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -3311,6 +3346,13 @@
|
||||
table:
|
||||
name: scoreboard
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: jobid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: timetickets
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -5008,6 +5050,13 @@
|
||||
table:
|
||||
name: parts_order_lines
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: partsorderid
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
@@ -5623,6 +5672,128 @@
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
- table:
|
||||
name: tasks
|
||||
schema: public
|
||||
object_relationships:
|
||||
- name: bill
|
||||
using:
|
||||
foreign_key_constraint_on: billid
|
||||
- name: bodyshop
|
||||
using:
|
||||
foreign_key_constraint_on: bodyshopid
|
||||
- name: job
|
||||
using:
|
||||
foreign_key_constraint_on: jobid
|
||||
- name: jobline
|
||||
using:
|
||||
foreign_key_constraint_on: joblineid
|
||||
- name: parts_order
|
||||
using:
|
||||
foreign_key_constraint_on: partsorderid
|
||||
- name: user
|
||||
using:
|
||||
foreign_key_constraint_on: assigned_to
|
||||
- name: userByCreatedBy
|
||||
using:
|
||||
foreign_key_constraint_on: created_by
|
||||
insert_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
check:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
columns:
|
||||
- completed
|
||||
- deleted
|
||||
- priority
|
||||
- assigned_to
|
||||
- created_by
|
||||
- description
|
||||
- title
|
||||
- completed_at
|
||||
- created_at
|
||||
- deleted_at
|
||||
- due_date
|
||||
- remind_at
|
||||
- updated_at
|
||||
- billid
|
||||
- bodyshopid
|
||||
- id
|
||||
- jobid
|
||||
- joblineid
|
||||
- partsorderid
|
||||
select_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- completed
|
||||
- deleted
|
||||
- priority
|
||||
- assigned_to
|
||||
- created_by
|
||||
- description
|
||||
- title
|
||||
- completed_at
|
||||
- created_at
|
||||
- deleted_at
|
||||
- due_date
|
||||
- remind_at
|
||||
- updated_at
|
||||
- billid
|
||||
- bodyshopid
|
||||
- id
|
||||
- jobid
|
||||
- joblineid
|
||||
- partsorderid
|
||||
filter:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
update_permissions:
|
||||
- role: user
|
||||
permission:
|
||||
columns:
|
||||
- completed
|
||||
- deleted
|
||||
- priority
|
||||
- assigned_to
|
||||
- created_by
|
||||
- description
|
||||
- title
|
||||
- completed_at
|
||||
- created_at
|
||||
- deleted_at
|
||||
- due_date
|
||||
- remind_at
|
||||
- updated_at
|
||||
- billid
|
||||
- bodyshopid
|
||||
- id
|
||||
- jobid
|
||||
- joblineid
|
||||
- partsorderid
|
||||
filter:
|
||||
bodyshop:
|
||||
associations:
|
||||
_and:
|
||||
- user:
|
||||
authid:
|
||||
_eq: X-Hasura-User-Id
|
||||
- active:
|
||||
_eq: true
|
||||
check: null
|
||||
- table:
|
||||
name: timetickets
|
||||
schema: public
|
||||
@@ -6006,6 +6177,13 @@
|
||||
table:
|
||||
name: exportlog
|
||||
schema: public
|
||||
- name: ioevents
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: useremail
|
||||
table:
|
||||
name: ioevents
|
||||
schema: public
|
||||
- name: messages
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
@@ -6034,6 +6212,20 @@
|
||||
table:
|
||||
name: parts_orders
|
||||
schema: public
|
||||
- name: tasks
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: assigned_to
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: tasksByCreatedBy
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
column: created_by
|
||||
table:
|
||||
name: tasks
|
||||
schema: public
|
||||
- name: timetickets
|
||||
using:
|
||||
foreign_key_constraint_on:
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE "public"."tasks";
|
||||
@@ -0,0 +1,18 @@
|
||||
CREATE TABLE "public"."tasks" ("id" uuid NOT NULL DEFAULT gen_random_uuid(), "created_at" timestamptz NOT NULL DEFAULT now(), "updated_at" timestamptz NOT NULL DEFAULT now(), "title" text NOT NULL, "description" Text, "deleted" boolean NOT NULL DEFAULT false, "deleted_at" timestamptz, "due_date" timestamptz, "created_by" text NOT NULL, "assigned_to" Text, "completed" boolean NOT NULL DEFAULT false, "completed_at" timestamptz, "remind_at" timestamptz, "priority" numeric, "bodyshopid" UUID NOT NULL, "jobid" UUID NOT NULL, "joblineid" UUID, "partsorderid" UUID, "billid" UUID, PRIMARY KEY ("id") , FOREIGN KEY ("created_by") REFERENCES "public"."users"("email") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("assigned_to") REFERENCES "public"."users"("email") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("bodyshopid") REFERENCES "public"."bodyshops"("id") ON UPDATE restrict ON DELETE restrict, FOREIGN KEY ("jobid") REFERENCES "public"."jobs"("id") ON UPDATE cascade ON DELETE cascade, FOREIGN KEY ("joblineid") REFERENCES "public"."joblines"("id") ON UPDATE set null ON DELETE set null, FOREIGN KEY ("partsorderid") REFERENCES "public"."parts_orders"("id") ON UPDATE set null ON DELETE set null, FOREIGN KEY ("billid") REFERENCES "public"."bills"("id") ON UPDATE set null ON DELETE set null);
|
||||
CREATE OR REPLACE FUNCTION "public"."set_current_timestamp_updated_at"()
|
||||
RETURNS TRIGGER AS $$
|
||||
DECLARE
|
||||
_new record;
|
||||
BEGIN
|
||||
_new := NEW;
|
||||
_new."updated_at" = NOW();
|
||||
RETURN _new;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
CREATE TRIGGER "set_public_tasks_updated_at"
|
||||
BEFORE UPDATE ON "public"."tasks"
|
||||
FOR EACH ROW
|
||||
EXECUTE PROCEDURE "public"."set_current_timestamp_updated_at"();
|
||||
COMMENT ON TRIGGER "set_public_tasks_updated_at" ON "public"."tasks"
|
||||
IS 'trigger to set value of column "updated_at" to current timestamp on row update';
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
Reference in New Issue
Block a user