Merge branch 'master-AIO' into feature/IO-2458-RO-Closer

This commit is contained in:
Patrick Fic
2024-03-22 08:41:12 -07:00
63 changed files with 1754 additions and 2657 deletions

View File

@@ -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}}

View File

@@ -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);
}}

View File

@@ -172,6 +172,7 @@ function BillEnterModalContainer({
],
},
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID", "GET_JOB_BY_PK"],
awaitRefetchQueries: true
});
await Promise.all(
@@ -239,6 +240,7 @@ function BillEnterModalContainer({
if (markPolReceived && markPolReceived.length > 0) {
const r2 = await updatePartsOrderLines({
variables: {partsLineIds: markPolReceived.map((p) => p.id)},
refetchQueries: ["QUERY_PARTS_BILLS_BY_JOBID" ],
});
if (!!r2.errors) {
setLoading(false);
@@ -373,12 +375,13 @@ function BillEnterModalContainer({
});
if (enterAgain) {
// form.resetFields();
form.setFieldsValue({
...formValues,
billlines: [],
});
form.resetFields();
form.resetFields();
form.setFieldsValue({
...formValues,
vendorid:values.vendorid,
billlines: [],
});
// form.resetFields();
} else {
toggleModalVisible();
}

File diff suppressed because it is too large Load Diff

View File

@@ -689,14 +689,14 @@ export function BillEnterModalLinesComponent({
formItemProps: (field) => {
return {
key: `${field.index}fedtax`,
valuePropName: "checked",
// initialValue: true,
name: [
field.name,
"applicable_taxes",
"federal",
],
key: `${field.index}fedtax`,
valuePropName: 'checked',
initialValue: InstanceRenderManager({
imex: true,
rome: false,
promanager: false,
}),
name: [field.name, 'applicable_taxes', 'federal'],
};
},
formInput: (record, index) => (

View File

@@ -12,6 +12,7 @@ import "./chat-affix.styles.scss";
export function ChatAffixContainer({bodyshop, chatVisible}) {
const {t} = useTranslation();
const client = useApolloClient();
useEffect(() => {
if (!bodyshop || !bodyshop.messagingservicesid) return;
@@ -31,6 +32,7 @@ export function ChatAffixContainer({bodyshop, chatVisible}) {
error
);
notification.open({
key: 'fcm',
type: "warning",
message: t("general.errors.fcm"),
btn: (
@@ -62,7 +64,7 @@ export function ChatAffixContainer({bodyshop, chatVisible}) {
SubscribeToTopic();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [bodyshop]);
useEffect(() => {
function handleMessage(payload) {

View File

@@ -61,6 +61,10 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
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 63:
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:

View File

@@ -9,6 +9,7 @@ import axios from "axios";
const fortyFiveDaysAgo = () => dayjs().subtract(45, 'day').toLocaleString();
export default function JobLifecycleDashboardComponent({data, bodyshop, ...cardProps}) {
console.log("🚀 ~ JobLifecycleDashboardComponent ~ bodyshop:", bodyshop)
const {t} = useTranslation();
const [loading, setLoading] = useState(false);
const [lifecycleData, setLifecycleData] = useState(null);
@@ -19,7 +20,7 @@ export default function JobLifecycleDashboardComponent({data, bodyshop, ...cardP
setLoading(true);
const response = await axios.post("/job/lifecycle", {
jobids: data.job_lifecycle.map(x => x.id),
statuses: bodyshop.md_order_statuses
statuses: bodyshop.md_ro_statuses
});
setLifecycleData(response.data.durations);
setLoading(false);
@@ -166,4 +167,4 @@ job_lifecycle: jobs(where: {
}) {
id
actual_in
} `;
} `;

View File

@@ -184,7 +184,7 @@ export function DashboardGridComponent({currentUser, bodyshop}) {
}}
onClick={() => handleRemoveComponent(item.i)}
/>
<TheComponent className="dashboard-card" data={dashboarddata}/>
<TheComponent className="dashboard-card" bodyshop={bodyshop} data={dashboarddata}/>
</LoadingSkeleton>
</div>
);

View File

@@ -1,23 +1,17 @@
import dayjs from "../../utils/day";
import React from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AlertComponent from "../alert/alert.component";
import dayjs from '../../utils/day';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { selectBodyshop } from '../../redux/user/user.selectors';
import AlertComponent from '../alert/alert.component';
import InstanceRenderManager from '../../utils/instanceRenderMgr';
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
function FeatureWrapper({
bodyshop,
featureName,
noauth,
children,
...restProps
}) {
function FeatureWrapper({ bodyshop, featureName, noauth, children, ...restProps }) {
const { t } = useTranslation();
if (HasFeatureAccess({ featureName, bodyshop })) return children;
@@ -25,7 +19,13 @@ function FeatureWrapper({
return (
noauth || (
<AlertComponent
message={t("general.messages.nofeatureaccess", {app: InstanceRenderManager({imex:'$t(titles.imexonline)', rome: '$t(titles.romeonline)', promanager: '$t(titles.promanager)'})})}
message={t('general.messages.nofeatureaccess', {
app: InstanceRenderManager({
imex: '$t(titles.imexonline)',
rome: '$t(titles.romeonline)',
promanager: '$t(titles.promanager)',
}),
})}
type="warning"
/>
)
@@ -33,10 +33,7 @@ function FeatureWrapper({
}
export function HasFeatureAccess({ featureName, bodyshop }) {
return (
bodyshop?.features.allAccess ||
dayjs(bodyshop?.features[featureName]).isAfter(dayjs())
);
return bodyshop?.features.allAccess || dayjs(bodyshop?.features[featureName]).isAfter(dayjs());
}
export default connect(mapStateToProps, null)(FeatureWrapper);

View File

@@ -5,6 +5,7 @@ import {useTranslation} from "react-i18next";
import AlertComponent from "../alert/alert.component";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import "./job-bills-total.styles.scss";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
export default function JobBillsTotalComponent({
loading,
@@ -89,7 +90,7 @@ export default function JobBillsTotalComponent({
.add(Dinero(totals.parts.sublets.total))
.add(Dinero(totals.additional.shipping))
.add(Dinero(totals.additional.towing))
.add(Dinero(totals.additional.additionalCosts)); //TODO:AIO Additional costs were captured for Rome, but not imex. This may need to be evaluated?
.add( InstanceRenderManager({imex: Dinero(), rome: Dinero(totals.additional.additionalCosts),promanager: "USE_ROME" })) ; // Additional costs were captured for Rome, but not imex.
const discrepancy = totalPartsSublet.subtract(billTotals);

View File

@@ -290,7 +290,7 @@ export function JobLinesComponent({
key: 'location',
render: (text, record) => <JobLineLocationPopup jobline={record} disabled={jobRO} />,
},
...(HasFeatureAccess({ featureName: 'bills' })
...(HasFeatureAccess({ featureName: 'bills', bodyshop })
? [
{
title: t('joblines.labels.billref'),

View File

@@ -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>

View File

@@ -44,13 +44,13 @@ export function JobEmployeeAssignmentsContainer({
});
if (refetch) refetch();
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.jobassignmentchange(operation, name),
type: "jobassignmentchange",
});
if (!!result.errors) {
if (!!!result.errors) {
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.jobassignmentchange(operation, name),
type: "jobassignmentchange",
});
} else {
notification["error"]({
message: t("jobs.errors.assigning", {
message: JSON.stringify(result.errors),
@@ -68,19 +68,21 @@ export function JobEmployeeAssignmentsContainer({
variables: {jobId: job.id, job: {[empAssignment]: null}},
});
if (!!result.errors) {
notification["error"]({
message: t("jobs.errors.assigning", {
message: JSON.stringify(result.errors),
}),
});
}
insertAuditTrail({
jobid: job.id,
operation: AuditTrailMapping.jobassignmentremoved(operation),
type: "jobassignmentremoved",});
setLoading(false);
};
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),
}),
});
}
setLoading(false);
};
return (
<div>

View File

@@ -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}/>
),
},
];

View File

@@ -6,6 +6,7 @@ import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
import {selectBodyshop} from "../../redux/user/user.selectors";
import InstanceRenderManager from '../../utils/instanceRenderMgr';
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -29,108 +30,130 @@ export function JobTotalsTableTotals({bodyshop, job}) {
total: job.job_totals.totals.subtotal,
bold: true,
},
...(job.job_totals.totals.us_sales_tax_breakdown
? [
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty1?.tax_type1 ||
"T1"
} - ${[
job.cieca_pft.ty1_rate1,
job.cieca_pft.ty1_rate2,
job.cieca_pft.ty1_rate3,
job.cieca_pft.ty1_rate4,
job.cieca_pft.ty1_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty1Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty2?.tax_type2 ||
"T2"
} - ${[
job.cieca_pft.ty2_rate1,
job.cieca_pft.ty2_rate2,
job.cieca_pft.ty2_rate3,
job.cieca_pft.ty2_rate4,
job.cieca_pft.ty2_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty2Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty3?.tax_type3 ||
"T3"
} - ${[
job.cieca_pft.ty3_rate1,
job.cieca_pft.ty3_rate2,
job.cieca_pft.ty3_rate3,
job.cieca_pft.ty3_rate4,
job.cieca_pft.ty3_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty3Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty4?.tax_type4 ||
"T4"
} - ${[
job.cieca_pft.ty4_rate1,
job.cieca_pft.ty4_rate2,
job.cieca_pft.ty4_rate3,
job.cieca_pft.ty4_rate4,
job.cieca_pft.ty4_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty4Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty5?.tax_type5 ||
"TT"
} - ${[
job.cieca_pft.ty5_rate1,
job.cieca_pft.ty5_rate2,
job.cieca_pft.ty5_rate3,
job.cieca_pft.ty5_rate4,
job.cieca_pft.ty5_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty5Tax,
},
{
key: t("jobs.labels.total_sales_tax"),
bold: true,
total: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty1Tax)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty2Tax)
)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty3Tax)
)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty4Tax)
)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty5Tax)
).toJSON(),
},
].filter((item) => item.total.amount !== 0)
: [
{
key: t("jobs.labels.state_tax_amt"),
total: job.job_totals.totals.state_tax,
},
]),
...InstanceRenderManager({imex: [ {
key: t("jobs.labels.local_tax_amt"),
total: job.job_totals.totals.local_tax,
},
{
key: t("jobs.labels.state_tax_amt"),
total: job.job_totals.totals.state_tax,
},
...(bodyshop.region_config === "CA_BC"
? [
{
key: t("jobs.fields.ca_bc_pvrt"),
total: job.job_totals.additional.pvrt,
},
]
: []),
{
key: t("jobs.labels.federal_tax_amt"),
total: job.job_totals.totals.federal_tax,
},],
promanager: "USE_ROME",
rome: [(job.job_totals.totals.us_sales_tax_breakdown
? [
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty1?.tax_type1 ||
"T1"
} - ${[
job.cieca_pft.ty1_rate1,
job.cieca_pft.ty1_rate2,
job.cieca_pft.ty1_rate3,
job.cieca_pft.ty1_rate4,
job.cieca_pft.ty1_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty1Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty2?.tax_type2 ||
"T2"
} - ${[
job.cieca_pft.ty2_rate1,
job.cieca_pft.ty2_rate2,
job.cieca_pft.ty2_rate3,
job.cieca_pft.ty2_rate4,
job.cieca_pft.ty2_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty2Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty3?.tax_type3 ||
"T3"
} - ${[
job.cieca_pft.ty3_rate1,
job.cieca_pft.ty3_rate2,
job.cieca_pft.ty3_rate3,
job.cieca_pft.ty3_rate4,
job.cieca_pft.ty3_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty3Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty4?.tax_type4 ||
"T4"
} - ${[
job.cieca_pft.ty4_rate1,
job.cieca_pft.ty4_rate2,
job.cieca_pft.ty4_rate3,
job.cieca_pft.ty4_rate4,
job.cieca_pft.ty4_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty4Tax,
},
{
key: `${
bodyshop.md_responsibility_centers.taxes.tax_ty5?.tax_type5 ||
"TT"
} - ${[
job.cieca_pft.ty5_rate1,
job.cieca_pft.ty5_rate2,
job.cieca_pft.ty5_rate3,
job.cieca_pft.ty5_rate4,
job.cieca_pft.ty5_rate5,
]
.filter((i) => i > 0)
.join(", ")}%`,
total: job.job_totals.totals.us_sales_tax_breakdown.ty5Tax,
},
{
key: t("jobs.labels.total_sales_tax"),
bold: true,
total: Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty1Tax)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty2Tax)
)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty3Tax)
)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty4Tax)
)
.add(
Dinero(job.job_totals.totals.us_sales_tax_breakdown.ty5Tax)
).toJSON(),
},
].filter((item) => item.total.amount !== 0)
: [
{
key: t("jobs.labels.state_tax_amt"),
total: job.job_totals.totals.state_tax,
},
])]
}),
{
key: t("jobs.labels.total_repairs"),

View File

@@ -6,6 +6,7 @@ import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
import {logImEXEvent} from "../../firebase/firebase.utils";
import {selectBodyshop} from "../../redux/user/user.selectors";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -29,19 +30,25 @@ export function JobsCloseAutoAllocate({bodyshop, joblines, form, disabled}) {
ret.profitcenter_labor = null;
}
//Verify that this is also manually updated in server/job-costing
if (!jl.part_type && !jl.mod_lbr_ty) {
const lineDesc = jl.line_desc ? jl.line_desc.toLowerCase() : "";
if (lineDesc.includes("shop materials")) {
ret.profitcenter_part = defaults.profits["MASH"];
} else if (lineDesc.includes("paint/materials")) {
ret.profitcenter_part = defaults.profits["MAPA"];
} else if (lineDesc.includes("ats amount")) {
ret.profitcenter_part = defaults.profits["ATS"];
} else if (jl.act_price > 0) {
ret.profitcenter_part = defaults.profits["PAO"];
} else {
ret.profitcenter_part = null;
}
if (
InstanceRenderManager({
imex: !jl.part_type && !jl.mod_lbr_ty,
rome: !ret.profitcenter_part,
promanager: 'USE_ROME',
})
) {
const lineDesc = jl.line_desc ? jl.line_desc.toLowerCase() : '';
if (lineDesc.includes('shop materials')) {
ret.profitcenter_part = defaults.profits['MASH'];
} else if (lineDesc.includes('paint/materials')) {
ret.profitcenter_part = defaults.profits['MAPA'];
} else if (lineDesc.includes('ats amount')) {
ret.profitcenter_part = defaults.profits['ATS'];
} else if (jl.act_price > 0) {
ret.profitcenter_part = defaults.profits['PAO'];
} else {
ret.profitcenter_part = null;
}
}
return ret;
}),

View File

@@ -1,261 +1,225 @@
import {Divider, Form, Input, InputNumber, Select, Space, Switch, Tooltip,} from "antd";
import React from "react";
import {useTranslation} from "react-i18next";
import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
import {selectJobReadOnly} from "../../redux/application/application.selectors";
import {selectBodyshop} from "../../redux/user/user.selectors";
import CABCpvrtCalculator from "../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component";
import CurrencyInput from "../form-items-formatted/currency-form-item.component";
import JobsDetailRatesChangeButton from "../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component";
import JobsMarkPstExempt from "../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component";
import FormRow from "../layout-form-row/layout-form-row.component";
import JobsDetailRatesLabor from "./jobs-detail-rates.labor.component";
import JobsDetailRatesMaterials from "./jobs-detail-rates.materials.component";
import JobsDetailRatesOther from "./jobs-detail-rates.other.component";
import JobsDetailRatesParts from "./jobs-detail-rates.parts.component";
import JobsDetailRatesTaxes from "./jobs-detail-rates.taxes.component";
import JobsDetailRatesProfileOVerride from "./jobs-detail-rates.profile-override.component";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
import { Divider, Form, Input, InputNumber, Select, Space, Switch, Tooltip } from 'antd';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { selectJobReadOnly } from '../../redux/application/application.selectors';
import { selectBodyshop } from '../../redux/user/user.selectors';
import CABCpvrtCalculator from '../ca-bc-pvrt-calculator/ca-bc-pvrt-calculator.component';
import CurrencyInput from '../form-items-formatted/currency-form-item.component';
import JobsDetailRatesChangeButton from '../jobs-detail-rates-change-button/jobs-detail-rates-change-button.component';
import JobsMarkPstExempt from '../jobs-mark-pst-exempt/jobs-mark-pst-exempt.component';
import FormRow from '../layout-form-row/layout-form-row.component';
import JobsDetailRatesLabor from './jobs-detail-rates.labor.component';
import JobsDetailRatesMaterials from './jobs-detail-rates.materials.component';
import JobsDetailRatesOther from './jobs-detail-rates.other.component';
import JobsDetailRatesParts from './jobs-detail-rates.parts.component';
import JobsDetailRatesTaxes from './jobs-detail-rates.taxes.component';
import JobsDetailRatesProfileOVerride from './jobs-detail-rates.profile-override.component';
import InstanceRenderManager from '../../utils/instanceRenderMgr';
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
});
export function JobsDetailRates({jobRO, form, job, bodyshop}) {
const {t} = useTranslation();
return (
<div>
<FormRow>
<Form.Item label={t("jobs.fields.class")} name="class">
<Select disabled={true}/>
</Form.Item>
<Form.Item
label={t("jobs.fields.depreciation_taxes")}
name="depreciation_taxes"
>
<CurrencyInput disabled={jobRO} min={0}/>
</Form.Item>
{bodyshop.region_config.toLowerCase().startsWith("ca") && (
<Tooltip title={t("jobs.labels.ca_gst_all_if_null")}>
<Form.Item
label={t("jobs.fields.ca_customer_gst")}
name="ca_customer_gst"
>
<CurrencyInput
disabled={jobRO}
min={0}
max={
Math.round(
(job.job_totals &&
job.job_totals.totals.federal_tax.amount) ||
0
) / 100
}
/>
</Form.Item>
</Tooltip>
)}
<Form.Item
label={t("jobs.fields.other_amount_payable")}
name="other_amount_payable"
>
<CurrencyInput disabled={jobRO} min={0}/>
</Form.Item>
<Form.Item
label={t("jobs.fields.towing_payable")}
name="towing_payable"
>
<CurrencyInput disabled={jobRO} min={0}/>
</Form.Item>
<Form.Item
label={t("jobs.fields.storage_payable")}
name="storage_payable"
>
<CurrencyInput disabled={jobRO} min={0}/>
</Form.Item>
<Form.Item
label={t("jobs.fields.adjustment_bottom_line")}
name="adjustment_bottom_line"
>
<CurrencyInput disabled={jobRO || bodyshop.cdk_dealerid}/>
</Form.Item>
{bodyshop.region_config === "CA_BC" && (
<Space align="center">
<Form.Item label={t("jobs.fields.ca_bc_pvrt")} name="ca_bc_pvrt">
<CurrencyInput disabled={jobRO} min={0}/>
</Form.Item>
<CABCpvrtCalculator form={form} disabled={jobRO}/>
</Space>
)}
<Form.Item
label={t("jobs.fields.auto_add_ats")}
name="auto_add_ats"
valuePropName="checked"
>
<Switch disabled={jobRO}/>
</Form.Item>
<Form.Item
noStyle
shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}
>
{() => {
if (form.getFieldValue("auto_add_ats"))
return (
<Form.Item
label={t("jobs.fields.rate_ats")}
name="rate_ats"
initialValue={bodyshop.shoprates.rate_atp}
>
<CurrencyInput disabled={jobRO}/>
</Form.Item>
);
return null;
}}
</Form.Item>
</FormRow>
{
InstanceRenderManager({imex:
<FormRow>
<Form.Item
label={t("jobs.fields.federal_tax_rate")}
name="federal_tax_rate"
>
<InputNumber min={0} max={1} precision={2} disabled={jobRO}/>
export function JobsDetailRates({ jobRO, form, job, bodyshop }) {
const { t } = useTranslation();
return (
<div>
<FormRow>
<Form.Item label={t('jobs.fields.class')} name="class">
<Select disabled={true} />
</Form.Item>
<Form.Item label={t('jobs.fields.depreciation_taxes')} name="depreciation_taxes">
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
{bodyshop.region_config.toLowerCase().startsWith('ca') && (
<Tooltip title={t('jobs.labels.ca_gst_all_if_null')}>
<Form.Item label={t('jobs.fields.ca_customer_gst')} name="ca_customer_gst">
<CurrencyInput
disabled={jobRO}
min={0}
max={
Math.round((job.job_totals && job.job_totals.totals.federal_tax.amount) || 0) /
100
}
/>
</Form.Item>
</Tooltip>
)}
<Form.Item label={t('jobs.fields.other_amount_payable')} name="other_amount_payable">
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Form.Item label={t('jobs.fields.towing_payable')} name="towing_payable">
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Form.Item label={t('jobs.fields.storage_payable')} name="storage_payable">
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<Form.Item label={t('jobs.fields.adjustment_bottom_line')} name="adjustment_bottom_line">
<CurrencyInput disabled={jobRO || bodyshop.cdk_dealerid} />
</Form.Item>
{bodyshop.region_config === 'CA_BC' && (
<Space align="center">
<Form.Item label={t('jobs.fields.ca_bc_pvrt')} name="ca_bc_pvrt">
<CurrencyInput disabled={jobRO} min={0} />
</Form.Item>
<CABCpvrtCalculator form={form} disabled={jobRO} />
</Space>
)}
<Form.Item
label={t("jobs.fields.state_tax_rate")}
name="state_tax_rate"
label={t('jobs.fields.auto_add_ats')}
name="auto_add_ats"
valuePropName="checked"
>
<InputNumber
<Switch disabled={jobRO} />
</Form.Item>
<Form.Item noStyle shouldUpdate={(prev, cur) => prev.auto_add_ats !== cur.auto_add_ats}>
{() => {
if (form.getFieldValue('auto_add_ats'))
return (
<Form.Item
label={t('jobs.fields.rate_ats')}
name="rate_ats"
initialValue={bodyshop.shoprates.rate_atp}
>
<CurrencyInput disabled={jobRO} />
</Form.Item>
);
return null;
}}
</Form.Item>
</FormRow>
{InstanceRenderManager({
imex: (
<FormRow>
<Form.Item label={t('jobs.fields.federal_tax_rate')} name="federal_tax_rate">
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.state_tax_rate')} name="state_tax_rate">
<InputNumber
min={0}
max={1}
precision={2}
disabled={jobRO}
autoComplete="new-password"
/>
</Form.Item>
<Form.Item
label={t("jobs.fields.local_tax_rate")}
name="local_tax_rate"
>
<InputNumber min={0} max={1} precision={2} disabled={jobRO}/>
</Form.Item>
{bodyshop.region_config.toLowerCase().startsWith("ca") && (
<Form.Item
label={t("jobs.fields.ca_gst_registrant")}
/>
</Form.Item>
<Form.Item label={t('jobs.fields.local_tax_rate')} name="local_tax_rate">
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
</Form.Item>
{bodyshop.region_config.toLowerCase().startsWith('ca') && (
<Form.Item
label={t('jobs.fields.ca_gst_registrant')}
name="ca_gst_registrant"
valuePropName="checked"
>
<Switch disabled={jobRO}/>
</Form.Item>
)}
</FormRow>})
}
<Divider
orientation="left"
type="horizontal"
style={{marginTop: ".8rem", float: "right"}}
>
{t("jobs.forms.laborrates")}
</Divider>
<Space>
<JobsDetailRatesChangeButton form={form} disabled={jobRO}/>
<JobsMarkPstExempt form={form}/>
</Space>
<FormRow noDivider>
<Form.Item
label={t("jobs.fields.labor_rate_desc")}
name="labor_rate_desc"
>
<Input disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
{
// <Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
// <CurrencyInput min={0}disabled={jobRO} />
// </Form.Item>
// <Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
// <CurrencyInput min={0}disabled={jobRO} />
// </Form.Item>
}
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
<CurrencyInput min={0} disabled={jobRO}/>
</Form.Item>
</FormRow>
{
InstanceRenderManager({rome: <>
<Divider orientation="left">Tax Profile</Divider>
<JobsDetailRatesProfileOVerride form={form}/>
<JobsDetailRatesParts form={form}/>
<JobsDetailRatesLabor form={form}/>
<JobsDetailRatesMaterials form={form}/>
<JobsDetailRatesOther form={form}/>
<JobsDetailRatesTaxes form={form}/>
</>})
}
</div>
);
>
<Switch disabled={jobRO} />
</Form.Item>
)}
</FormRow>
),
})}
<Divider orientation="left" type="horizontal" style={{ marginTop: '.8rem', float: 'right' }}>
{t('jobs.forms.laborrates')}
</Divider>
<Space>
<JobsDetailRatesChangeButton form={form} disabled={jobRO} />
<JobsMarkPstExempt form={form} />
</Space>
<FormRow noDivider>
<Form.Item label={t('jobs.fields.labor_rate_desc')} name="labor_rate_desc">
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_laa')} name="rate_laa">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_lab')} name="rate_lab">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_lad')} name="rate_lad">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_lae')} name="rate_lae">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_lar')} name="rate_lar">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_las')} name="rate_las">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_laf')} name="rate_laf">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_lam')} name="rate_lam">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_lag')} name="rate_lag">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_la1')} name="rate_la1">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_la2')} name="rate_la2">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_la3')} name="rate_la3">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_la4')} name="rate_la4">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_lau')} name="rate_lau">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_mapa')} name="rate_mapa">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_mash')} name="rate_mash">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_mahw')} name="rate_mahw">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_ma2s')} name="rate_ma2s">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t('jobs.fields.rate_ma3s')} name="rate_ma3s">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
{
// <Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
// <CurrencyInput min={0}disabled={jobRO} />
// </Form.Item>
// <Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
// <CurrencyInput min={0}disabled={jobRO} />
// </Form.Item>
}
<Form.Item label={t('jobs.fields.rate_matd')} name="rate_matd">
<CurrencyInput min={0} disabled={jobRO} />
</Form.Item>
</FormRow>
{InstanceRenderManager({
imex: <JobsDetailRatesParts form={form} />,
rome: (
<>
<Divider orientation="left">Tax Profile</Divider>
<JobsDetailRatesProfileOVerride form={form} />
<JobsDetailRatesParts form={form} />
<JobsDetailRatesLabor form={form} />
<JobsDetailRatesMaterials form={form} />
<JobsDetailRatesOther form={form} />
<JobsDetailRatesTaxes form={form} />
</>
),
promanager: "USE_ROME"
})}
</div>
);
}
export default connect(mapStateToProps, null)(JobsDetailRates);

View File

@@ -34,19 +34,20 @@ export function PartDispatchTableComponent({
// const selectedBill = search.billid;
const [searchText, setSearchText] = useState("");
const Templates = TemplateList("job_special");
const Templates = TemplateList("job_special", job);
const {refetch} = billsQuery;
const recordActions = (record) => (
<Space wrap>
<PrintWrapperComponent
templateObject={{
name: Templates.parts_dispatch.key,
variables: {id: record.id},
}}
/>
</Space>
<Space wrap>
<PrintWrapperComponent
templateObject={{
name: Templates.parts_dispatch.key,
variables: { id: record.id },
}}
messageObject={{ subject: Templates.parts_dispatch.subject }}
/>
</Space>
);
const columns = [
{

View File

@@ -7,6 +7,7 @@ import {connect} from "react-redux";
import {createStructuredSelector} from "reselect";
import {selectTechnician} from "../../redux/tech/tech.selectors";
import {selectBodyshop} from "../../redux/user/user.selectors";
import {useSplitTreatments} from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -31,7 +32,13 @@ export function ProductionColumnsComponent({
}) {
const [columns, setColumns] = columnState;
const {t} = useTranslation();
const {
treatments: { Enhanced_Payroll },
} = useSplitTreatments({
attributes: {},
names: ['Enhanced_Payroll'],
splitKey: bodyshop.imexshopid,
});
const handleAdd = (e) => {
setColumns([
...columns,
@@ -41,6 +48,7 @@ export function ProductionColumnsComponent({
state: tableState,
data,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
treatments:{Enhanced_Payroll}
}).filter((i) => i.key === e.key),
]);
};
@@ -52,6 +60,7 @@ export function ProductionColumnsComponent({
state: tableState,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
refetch,
treatments:{Enhanced_Payroll}
});
const menu = {

View File

@@ -29,7 +29,8 @@ import ProductionlistColumnTouchTime from "./prodution-list-columns.touchtime.co
import {store} from "../../redux/store";
import {setModalContext} from "../../redux/modals/modals.actions";
const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
const r = ({technician, state, activeStatuses, data, bodyshop, refetch, treatments}) => {
const {Enhanced_Payroll} = treatments;
return [
{
title: i18n.t("jobs.actions.viewdetail"),
@@ -42,7 +43,7 @@ const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
</Link>
),
},
{
...Enhanced_Payroll.treatment === "on" ? [ {
title: i18n.t("timetickets.actions.claimtasks"),
dataIndex: "claimtasks",
key: "claimtasks",
@@ -64,7 +65,7 @@ const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
{i18n.t("timetickets.actions.claimtasks")}
</div>
),
},
},] : [],
{
title: i18n.t("jobs.fields.ro_number"),
dataIndex: "ro_number",
@@ -326,7 +327,7 @@ const r = ({technician, state, activeStatuses, data, bodyshop, refetch}) => {
onFilter: (value, record) =>
value.includes(record.special_coverage_policy),
render: (text, record) => (
<Checkbox disabled checked={record.special_coverage_policy} />
<Checkbox checked={record.special_coverage_policy} />
),
},

View File

@@ -10,6 +10,7 @@ import {UPDATE_SHOP} from "../../graphql/bodyshop.queries";
import {selectTechnician} from "../../redux/tech/tech.selectors";
import {selectBodyshop, selectCurrentUser,} from "../../redux/user/user.selectors";
import ProductionListColumns from "../production-list-columns/production-list-columns.data";
import {useSplitTreatments} from '@splitsoftware/splitio-react';
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -31,6 +32,12 @@ export function ProductionListTable({
const [updateDefaultProdView] = useMutation(UPDATE_ACTIVE_PROD_LIST_VIEW);
const [updateShop] = useMutation(UPDATE_SHOP);
const {treatments: {Enhanced_Payroll}} = useSplitTreatments({
attributes: {},
names: ["Enhanced_Payroll"],
splitKey: bodyshop.imexshopid,
});
const handleSelect = async (value, option) => {
setColumns(
bodyshop.production_config
@@ -44,6 +51,7 @@ export function ProductionListTable({
state,
data: data,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
treatments:{Enhanced_Payroll}
}).find((e) => e.key === k.key),
width: k.width,
};
@@ -100,6 +108,7 @@ export function ProductionListTable({
refetch,
data: data,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
treatments: {Enhanced_Payroll}
}).find((e) => e.key === k.key),
width: k.width,
};

View File

@@ -28,13 +28,12 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia
const [searchText, setSearchText] = useState("");
const {treatments: {Production_List_Status_Colors}} = useSplitTreatments({
const {treatments: {Production_List_Status_Colors, Enhanced_Payroll}} = useSplitTreatments({
attributes: {},
names: ["Production_List_Status_Colors"],
names: ["Production_List_Status_Colors","Enhanced_Payroll"],
splitKey: bodyshop.imexshopid,
});
const assoc = bodyshop.associations.find(
(a) => a.useremail === currentUser.email
);
@@ -69,6 +68,7 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia
state,
data,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
treatments: {Production_List_Status_Colors, Enhanced_Payroll}
}).find((e) => e.key === k.key),
width: k.width ?? 100,
};
@@ -88,7 +88,8 @@ export function ProductionListTable({loading, data, refetch, bodyshop, technicia
refetch,
state,
data: data,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
activeStatuses: bodyshop.md_ro_statuses.active_statuses,
treatments: {Production_List_Status_Colors, Enhanced_Payroll}
}).find((e) => e.key === k.key),
width: k.width ?? 100,
};

View File

@@ -141,9 +141,10 @@ export function ReportCenterModalComponent({reportCenterModal, bodyshop}) {
const grouped = _.groupBy(FilteredReportsList, "group");
const groupExcludeKeyFilter = [...!HasFeatureAccess({featureName: 'bills'})? ["purchases"]:[],
...!HasFeatureAccess({featureName: 'timetickets'})? ["payroll"]:[],
]
const groupExcludeKeyFilter = [
...(!HasFeatureAccess({ featureName: 'bills', bodyshop }) ? ['purchases'] : []),
...(!HasFeatureAccess({ featureName: 'timetickets', bodyshop }) ? ['payroll'] : []),
];
return (
<div>

View File

@@ -18,7 +18,6 @@ import ShopInfoSpeedPrint from "./shop-info.speedprint.component";
import {useLocation, useNavigate} from "react-router-dom";
import ShopInfoTaskPresets from "./shop-info.task-presets.component";
import queryString from "query-string";
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
import InstanceRenderManager from "../../utils/instanceRenderMgr";
const mapStateToProps = createStructuredSelector({

View File

@@ -241,17 +241,17 @@ export function ShopInfoResponsibilityCenterComponent({bodyshop, form}) {
</Select>
</Form.Item>
<Space align="center">
d
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
<Space align="center">
<DeleteFilled
onClick={() => {
remove(field.name);
}}
/>
<FormListMoveArrows
move={move}
index={index}
total={fields.length}
/>
</Space>
</LayoutFormRow>
</Form.Item>

View File

@@ -8,6 +8,7 @@ import {Link, useLocation, useNavigate} from "react-router-dom";
import {createStructuredSelector} from "reselect";
import RomeLogo from "../../assets/RomeOnlineBlue.png";
import ImEXOnlineLogo from "../../assets/logo192.png";
import ProManagerLogo from '../../assets/promanager/ProManagerLogo.gif';
import InstanceRenderManager from '../../utils/instanceRenderMgr';
import {emailSignInStart, sendPasswordReset,} from "../../redux/user/user.actions";
import {selectCurrentUser, selectLoginLoading, selectSignInError,} from "../../redux/user/user.selectors";
@@ -53,9 +54,9 @@ export function SignInComponent({
return (
<div className="login-container">
<div className="login-logo-container">
<img src={InstanceRenderManager({imex:ImEXOnlineLogo, rome:RomeLogo, promanager:'https://www.web-est.com/img/web_est_logo_software.gif'})} width={200} alt={InstanceRenderManager({imex:t("titles.imexonline"), rome: t("titles.romeonline"), promanager:t("titles.promanager")})}/>
<img src={InstanceRenderManager({imex:ImEXOnlineLogo, rome:RomeLogo, promanager:ProManagerLogo})} width={InstanceRenderManager({imex:200, rome:200,promanager:450})} alt={InstanceRenderManager({imex:t("titles.imexonline"), rome: t("titles.romeonline"), promanager:t("titles.promanager")})}/>
<Typography.Title>{
InstanceRenderManager({imex: t("titles.imexonline"), rome: t("titles.romeonline"), promanager:t("titles.promanager")})
InstanceRenderManager({imex: t("titles.imexonline"), rome: t("titles.romeonline"), promanager:null})
}</Typography.Title>
</div>
<Form onFinish={handleFinish} form={form} size="large">

View File

@@ -65,14 +65,19 @@ export function TimeTicketList({
}, [timetickets]);
const columns = [
{
title: t("timetickets.fields.committed"),
dataIndex: "committed_at",
key: "committed_at",
render: (text, record) => (
<Checkbox disabled checked={record.committed_at}/>
),
},
...(Enhanced_Payroll.treatment === "on"
? [{
title: t("timetickets.fields.committed"),
dataIndex: "committed_at",
key: "committed_at",
render: (text, record) => (
<Checkbox disabled checked={record.committed_at}/>
),
},]
: [
]),
{
title: t("timetickets.fields.date"),
dataIndex: "date",

View File

@@ -16,7 +16,6 @@ import LayoutFormRow from "../layout-form-row/layout-form-row.component";
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
import {HasRbacAccess} from "../rbac-wrapper/rbac-wrapper.component";
import TimeTicketList from "../time-ticket-list/time-ticket-list.component";
import TimeTicketCalculatorComponent from "../time-ticket-calculator/time-ticket-calculator.component";
import {useSplitTreatments} from "@splitsoftware/splitio-react";
const mapStateToProps = createStructuredSelector({

View File

@@ -178,7 +178,7 @@ export function TimeTicketModalContainer({
onCancel={handleCancel}
afterClose={() => form.resetFields()}
footer={
<span>
<Space>
<Button onClick={handleCancel}>{t("general.actions.cancel")}</Button>
<Button
loading={loading}
@@ -198,7 +198,7 @@ export function TimeTicketModalContainer({
{t("general.actions.saveandnew")}
</Button>
)}
</span>
</Space>
}
destroyOnClose
>
@@ -229,9 +229,12 @@ export function TimeTicketModalContainer({
<PageHeader
extra={
<Space>
{
Enhanced_Payroll.treatment === 'on' &&
<TimeTicketsCommitToggleComponent
timeticket={timeTicketModal.context?.timeticket}
/>
}
<Button onClick={handleCancel}>
{t("general.actions.cancel")}
</Button>

View File

@@ -1,92 +1,91 @@
import {HeartOutlined} from "@ant-design/icons";
import {Select, Space, Tag} from "antd";
import React, {forwardRef, useEffect, useState} from "react";
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import { HeartOutlined } from '@ant-design/icons';
import { Select, Space, Tag } from 'antd';
import React, { forwardRef, useEffect, useState } from 'react';
import PhoneNumberFormatter from '../../utils/PhoneFormatter';
const {Option} = Select;
const { Option } = Select;
//To be used as a form element only.
const VendorSearchSelect = (
{value, onChange, options, onSelect, disabled, preferredMake, showPhone},
ref
{ value, onChange, options, onSelect, disabled, preferredMake, showPhone },
ref
) => {
const [option, setOption] = useState(value);
const [option, setOption] = useState(value);
useEffect(() => {
if (value !== option && onChange) {
onChange(option);
}
}, [value, option, onChange]);
useEffect(() => {
if (value !== option && onChange) {
onChange(option);
}
}, [value, option, onChange]);
const favorites =
preferredMake && options
? options.filter(
(o) =>
o.favorite.filter(
(f) => f.toLowerCase() === preferredMake.toLowerCase()
).length > 0
)
: [];
const favorites =
preferredMake && options
? options.filter(
(o) =>
o.favorite.filter((f) => f.toLowerCase() === preferredMake.toLowerCase()).length > 0
)
: [];
return (
<Select
ref={ref}
showSearch
value={option}
style={{
width: "100%",
}}
popupMatchSelectWidth={false}
onChange={setOption}
optionFilterProp="name"
onSelect={onSelect}
disabled={disabled || false}
optionLabelProp={"name"}
>
{favorites
? favorites.map((o) => (
<Option
key={`favorite-${o.id}`}
value={o.id}
name={o.name}
discount={o.discount}
>
<div className="imex-flex-row">
<div style={{flex: 1}}>{o.name}</div>
<Space style={{marginLeft: "1rem"}}>
<HeartOutlined style={{color: "red"}}/>
{o.phone && showPhone && (
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
)}
{o.discount && o.discount !== 0 ? (
<Tag color="green">{`${o.discount * 100}%`}</Tag>
) : null}
</Space>
</div>
</Option>
))
: null}
{options
? options.map((o) => (
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
<div className="imex-flex-row" style={{width: "100%"}}>
<div style={{flex: 1}}>{o.name}</div>
return (
<Select
ref={ref}
showSearch
value={option}
style={{
width: '100%',
}}
labelRender={({ label, value, ...rest }) => {
if (!value || !options) return label;
const discount = options?.find((o) => o.id === value)?.discount;
return (
<div className="imex-flex-row" style={{ width: '100%' }}>
<div style={{ flex: 1 }}>{label}</div>
<Space style={{marginLeft: "1rem"}}>
{o.phone && showPhone && (
<PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>
)}
{o.discount && o.discount !== 0 ? (
<Tag color="green">{`${o.discount * 100}%`}</Tag>
) : null}
</Space>
</div>
</Option>
{discount && discount !== 0 ? <Tag color="green">{`${discount * 100}%`}</Tag> : null}
</div>
);
}}
popupMatchSelectWidth={false}
onChange={setOption}
optionFilterProp="name"
onSelect={onSelect}
disabled={disabled || false}
optionLabelProp={'name'}
>
{favorites
? favorites.map((o) => (
<Option key={`favorite-${o.id}`} value={o.id} name={o.name} discount={o.discount}>
<div className="imex-flex-row">
<div style={{ flex: 1 }}>{o.name}</div>
<Space style={{ marginLeft: '1rem' }}>
<HeartOutlined style={{ color: 'red' }} />
{o.phone && showPhone && <PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>}
{o.discount && o.discount !== 0 ? (
<Tag color="green">{`${o.discount * 100}%`}</Tag>
) : null}
</Space>
</div>
</Option>
))
: null}
{options
? options.map((o) => (
<Option key={o.id} value={o.id} name={o.name} discount={o.discount}>
<div className="imex-flex-row" style={{ width: '100%' }}>
<div style={{ flex: 1 }}>{o.name}</div>
))
: null}
</Select>
);
<Space style={{ marginLeft: '1rem' }}>
{o.phone && showPhone && <PhoneNumberFormatter>{o.phone}</PhoneNumberFormatter>}
{o.discount && o.discount !== 0 ? (
<Tag color="green">{`${o.discount * 100}%`}</Tag>
) : null}
</Space>
</div>
</Option>
))
: null}
</Select>
);
};
export default forwardRef(VendorSearchSelect);