WIP Read Only for Jobs BOD-409

This commit is contained in:
Patrick Fic
2020-09-28 14:00:35 -07:00
parent a7051c0f86
commit 3ee003000d
22 changed files with 278 additions and 129 deletions

View File

@@ -13439,6 +13439,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>federal_tax_rate</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>ins_addr1</name>
<definition_loaded>false</definition_loaded>
@@ -14053,6 +14074,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>local_tax_rate</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>loss_date</name>
<definition_loaded>false</definition_loaded>
@@ -15376,6 +15418,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>state_tax_rate</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>status</name>
<definition_loaded>false</definition_loaded>

View File

@@ -11,6 +11,12 @@ import { alphaSort } from "../../utils/sorters";
import queryString from "query-string";
import { useLocation } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
setPartsOrderContext: (context) =>
dispatch(setModalContext({ context: context, modal: "partsOrder" })),
@@ -21,6 +27,7 @@ const mapDispatchToProps = (dispatch) => ({
});
export function BillsListTableComponent({
jobRO,
job,
billsQuery,
handleOnRowClick,
@@ -94,11 +101,15 @@ export function BillsListTableComponent({
key: "actions",
render: (text, record) => (
<div>
<Link
to={`/manage/bills?billid=${record.id}&vendorid=${record.vendorid}`}
>
<Button>{t("bills.actions.edit")}</Button>
</Link>
{jobRO ? (
<Button disabled>{t("bills.actions.edit")}</Button>
) : (
<Link
to={`/manage/bills?billid=${record.id}&vendorid=${record.vendorid}`}
>
<Button>{t("bills.actions.edit")}</Button>
</Link>
)}
</div>
),
},
@@ -227,7 +238,7 @@ export function BillsListTableComponent({
</Descriptions.Item>
</Descriptions>
<Button
disabled={record.is_credit_memo}
disabled={record.is_credit_memo || jobRO}
onClick={() =>
setPartsOrderContext({
actions: {},
@@ -292,6 +303,7 @@ export function BillsListTableComponent({
{job ? (
<div>
<Button
disabled={jobRO}
onClick={() => {
setBillEnterContext({
actions: { refetch: billsQuery.refetch },

View File

@@ -3,16 +3,9 @@ import Axios from "axios";
import React, { useState } from "react";
import { useMutation } from "react-apollo";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobCalculateTotals({ bodyshop, job }) {
export default function JobCalculateTotals({ job, disabled }) {
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
const [updateJob] = useMutation(UPDATE_JOB);
@@ -49,10 +42,9 @@ export function JobCalculateTotals({ bodyshop, job }) {
return (
<div>
<Button loading={loading} onClick={handleCalculate}>
<Button loading={loading} onClick={handleCalculate} disabled={disabled}>
{t("jobs.actions.recalculate")}
</Button>
</div>
);
}
export default connect(mapStateToProps, null)(JobCalculateTotals);

View File

@@ -15,6 +15,13 @@ import JobLineNotePopup from "../job-line-note-popup/job-line-note-popup.compone
// import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
setJobLineEditContext: (context) =>
dispatch(setModalContext({ context: context, modal: "jobLineEdit" })),
@@ -23,6 +30,7 @@ const mapDispatchToProps = (dispatch) => ({
});
export function JobLinesComponent({
jobRO,
setPartsOrderContext,
loading,
refetch,
@@ -179,13 +187,17 @@ export function JobLinesComponent({
title: t("joblines.fields.notes"),
dataIndex: "notes",
key: "notes",
render: (text, record) => <JobLineNotePopup jobline={record} />,
render: (text, record) => (
<JobLineNotePopup disabled={jobRO} jobline={record} />
),
},
{
title: t("joblines.fields.location"),
dataIndex: "location",
key: "location",
render: (text, record) => <JobLineLocationPopup jobline={record} />,
render: (text, record) => (
<JobLineLocationPopup jobline={record} disabled={jobRO} />
),
},
{
title: t("joblines.fields.status"),
@@ -244,6 +256,7 @@ export function JobLinesComponent({
render: (text, record) => (
<div>
<Button
disabled={jobRO}
onClick={() => {
setJobLineEditContext({
actions: { refetch: refetch },
@@ -309,7 +322,9 @@ export function JobLinesComponent({
</Button>
<Button
disabled={
!job.converted || (selectedLines.length > 0 ? false : true)
!job.converted ||
(selectedLines.length > 0 ? false : true) ||
jobRO
}
onClick={() => {
setPartsOrderContext({
@@ -345,6 +360,7 @@ export function JobLinesComponent({
// />
}
<Button
disabled={jobRO}
onClick={() => {
setJobLineEditContext({
actions: { refetch: refetch },
@@ -398,4 +414,4 @@ export function JobLinesComponent({
</div>
);
}
export default connect(null, mapDispatchToProps)(JobLinesComponent);
export default connect(mapStateToProps, mapDispatchToProps)(JobLinesComponent);

View File

@@ -6,8 +6,10 @@ import { Select, Button, Popover } from "antd";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
@@ -15,6 +17,7 @@ const mapDispatchToProps = (dispatch) => ({
export function JobEmployeeAssignments({
bodyshop,
jobRO,
body,
refinish,
prep,
@@ -52,7 +55,7 @@ export function JobEmployeeAssignments({
</Select>
<Button
type="primary"
disabled={!assignment.employeeid}
disabled={!assignment.employeeid || jobRO}
onClick={() => {
handleAdd(assignment);
setVisibility(false);
@@ -79,14 +82,18 @@ export function JobEmployeeAssignments({
}`}</span>
<MinusOutlined
operation="body"
onClick={() => handleRemove("body")}
disabled={jobRO}
onClick={() => !jobRO && handleRemove("body")}
/>
</div>
) : (
<PlusCircleFilled
disabled={jobRO}
onClick={() => {
setAssignment({ operation: "body" });
setVisibility(true);
if (!jobRO) {
setAssignment({ operation: "body" });
setVisibility(true);
}
}}
/>
)}
@@ -101,15 +108,19 @@ export function JobEmployeeAssignments({
prep.last_name || ""
}`}</span>
<MinusOutlined
disabled={jobRO}
operation="prep"
onClick={() => handleRemove("prep")}
onClick={() => !jobRO && handleRemove("prep")}
/>
</div>
) : (
<PlusCircleFilled
disabled={jobRO}
onClick={() => {
setAssignment({ operation: "prep" });
setVisibility(true);
if (!jobRO) {
setAssignment({ operation: "prep" });
setVisibility(true);
}
}}
/>
)}
@@ -124,15 +135,19 @@ export function JobEmployeeAssignments({
refinish.last_name || ""
}`}</span>
<MinusOutlined
disabled={jobRO}
operation="refinish"
onClick={() => handleRemove("refinish")}
onClick={() => !jobRO && handleRemove("refinish")}
/>
</div>
) : (
<PlusCircleFilled
disabled={jobRO}
onClick={() => {
setAssignment({ operation: "refinish" });
setVisibility(true);
if (!jobRO) {
setAssignment({ operation: "refinish" });
setVisibility(true);
}
}}
/>
)}

View File

@@ -16,7 +16,7 @@ const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function JobLineLocationPopup({ bodyshop, jobline }) {
export function JobLineLocationPopup({ bodyshop, jobline, disabled }) {
const [editing, setEditing] = useState(false);
const [loading, setLoading] = useState(false);
const [location, setLocation] = useState(jobline.location);
@@ -73,7 +73,7 @@ export function JobLineLocationPopup({ bodyshop, jobline }) {
return (
<div
style={{ width: "100%", minHeight: "2rem", cursor: "pointer" }}
onClick={() => setEditing(true)}
onClick={() => !disabled && setEditing(true)}
>
{jobline.location}
</div>

View File

@@ -5,7 +5,7 @@ import { useMutation } from "react-apollo";
import { UPDATE_JOB_LINE } from "../../graphql/jobs-lines.queries";
import { useTranslation } from "react-i18next";
export default function JobLineNotePopup({ jobline }) {
export default function JobLineNotePopup({ jobline, disabled }) {
const [editing, setEditing] = useState(false);
const [loading, setLoading] = useState(false);
const [note, setNote] = useState(jobline.note);
@@ -57,7 +57,7 @@ export default function JobLineNotePopup({ jobline }) {
return (
<div
style={{ width: "100%", minHeight: "2rem", cursor: "pointer" }}
onClick={() => setEditing(true)}
onClick={() => !disabled && setEditing(true)}
>
{jobline.notes}
</div>

View File

@@ -6,12 +6,14 @@ 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 JobCalculateTotals from "../job-calculate-totals/job-calculate-totals.component";
import "./job-totals-table.styles.scss";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
});
@@ -20,14 +22,14 @@ const colSpan = {
lg: { span: 12 },
};
export function JobsTotalsTableComponent({ bodyshop, job }) {
export function JobsTotalsTableComponent({ bodyshop, jobRO, job }) {
const { t } = useTranslation();
if (!!!job.job_totals) {
return (
<Result
title={t("jobs.errors.nofinancial")}
extra={<JobCalculateTotals job={job} />}
extra={<JobCalculateTotals job={job} disabled={jobRO} />}
/>
);
}
@@ -333,7 +335,7 @@ export function JobsTotalsTableComponent({ bodyshop, job }) {
value={Dinero(job.job_totals.totals.net_repairs).toFormat()}
/>
</div>
<JobCalculateTotals job={job} />
<JobCalculateTotals job={job} disabled={jobRO} />
<Editor
value={{
CIECA: job.cieca_ttl && job.cieca_ttl.data,

View File

@@ -1,21 +1,23 @@
import { DownCircleFilled } from "@ant-design/icons";
import { Button, Dropdown, Menu, notification } from "antd";
import React, { useState, useEffect } from "react";
import React, { useEffect, useState } from "react";
import { useMutation } from "react-apollo";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { UPDATE_JOB_STATUS } from "../../graphql/jobs.queries";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function JobsChangeStatus({ job, bodyshop }) {
export function JobsChangeStatus({ job, bodyshop, jobRO }) {
const { t } = useTranslation();
const [availableStatuses, setAvailableStatuses] = useState([]);
@@ -70,6 +72,7 @@ export function JobsChangeStatus({ job, bodyshop }) {
overlay={statusmenu}
trigger={["click"]}
key="changestatus"
disabled={jobRO}
>
<Button>
{t("jobs.actions.changestatus")} <DownCircleFilled />

View File

@@ -1,21 +1,23 @@
import { Button, notification, Popover, Form, Select } from "antd";
import { Button, Form, notification, Popover, Select } from "antd";
import React, { useState } from "react";
import { useMutation } from "react-apollo";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { CONVERT_JOB_TO_RO } from "../../graphql/jobs.queries";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function JobsConvertButton({ bodyshop, job, refetch }) {
export function JobsConvertButton({ bodyshop, job, refetch, jobRO }) {
const [visible, setVisible] = useState(false);
const [mutationConvertJob] = useMutation(CONVERT_JOB_TO_RO);
const { t } = useTranslation();
@@ -88,7 +90,7 @@ export function JobsConvertButton({ bodyshop, job, refetch }) {
className="imex-flex-row__margin"
type="danger"
style={{ display: job.converted ? "none" : "" }}
disabled={job.converted}
disabled={job.converted || jobRO}
onClick={() => setVisible(true)}
>
{t("jobs.actions.convert")}

View File

@@ -3,6 +3,7 @@ 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 FormDatePicker from "../form-date-picker/form-date-picker.component";
import InputNumberCalculator from "../form-input-number-calculator/form-input-number-calculator.component";
@@ -13,7 +14,7 @@ import Car from "../job-damage-visual/job-damage-visual.component";
import FormRow from "../layout-form-row/layout-form-row.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
@@ -22,7 +23,7 @@ const mapDispatchToProps = (dispatch) => ({
const lossColFields = { sm: { span: 24 }, md: { span: 18 }, lg: { span: 20 } };
const lossColDamage = { sm: { span: 24 }, md: { span: 6 }, lg: { span: 4 } };
export function JobsDetailGeneral({ bodyshop, job, form }) {
export function JobsDetailGeneral({ bodyshop, jobRO, job, form }) {
const { getFieldValue } = form;
const { t } = useTranslation();
@@ -30,10 +31,10 @@ export function JobsDetailGeneral({ bodyshop, job, form }) {
<div>
<FormRow header={t("jobs.forms.claiminfo")}>
<Form.Item label={t("jobs.fields.clm_no")} name="clm_no">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ded_status")} name="ded_status">
<Select>
<Select disabled={jobRO}>
<Select.Option value="W">
{t("jobs.labels.deductible.waived")}
</Select.Option>
@@ -46,34 +47,34 @@ export function JobsDetailGeneral({ bodyshop, job, form }) {
</Select>
</Form.Item>
<Form.Item label={t("jobs.fields.ded_amt")} name="ded_amt">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.policy_no")} name="policy_no">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.regie_number")} name="regie_number">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_co_id")} name="ins_co_id">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_co_nm")} name="ins_co_nm">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_addr1")} name="ins_addr1">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_city")} name="ins_city">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_ct_ln")} name="ins_ct_ln">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_ct_fn")} name="ins_ct_fn">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ins_ph1")} name="ins_ph1">
<FormItemPhone customInput={Input} />
<FormItemPhone customInput={Input} disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.ins_ea")}
@@ -85,13 +86,13 @@ export function JobsDetailGeneral({ bodyshop, job, form }) {
},
]}
>
<FormItemEmail email={getFieldValue("ins_ea")} />
<FormItemEmail email={getFieldValue("ins_ea")} disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.referralsource")}
name="referral_source"
>
<Select>
<Select disabled={jobRO}>
{bodyshop.md_referral_sources.map((s) => (
<Select.Option key={s} value={s}>
{s}
@@ -104,35 +105,35 @@ export function JobsDetailGeneral({ bodyshop, job, form }) {
<Col {...lossColFields}>
<FormRow header={t("jobs.forms.lossinfo")}>
<Form.Item label={t("jobs.fields.loss_desc")} name="loss_desc">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.loss_date")} name="loss_date">
<FormDatePicker />
<FormDatePicker disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.kmin")} name="kmin">
<InputNumberCalculator precision={1} min={0} />
<InputNumberCalculator precision={1} min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.kmout")} name="kmout">
<InputNumberCalculator precision={1} min={0} />
<InputNumberCalculator precision={1} min={0} disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.ponumber")} name="po_number">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.unitnumber")} name="unit_number">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.specialcoveragepolicy")}
valuePropName="checked"
name="special_coverage_policy"
>
<Switch />
<Switch disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.tax_registration_number")}
name="tax_registration_number"
>
<Input />
<Input disabled={jobRO} />
</Form.Item>
</FormRow>
</Col>
@@ -150,16 +151,16 @@ export function JobsDetailGeneral({ bodyshop, job, form }) {
<FormRow header={t("jobs.forms.appraiserinfo")}>
<Form.Item label={t("jobs.fields.est_co_nm")} name="est_co_nm">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ct_fn")} name="est_ct_fn">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ct_ln")} name="est_ct_ln">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.est_ph1")} name="est_ph1">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.est_ea")}
@@ -171,16 +172,16 @@ export function JobsDetailGeneral({ bodyshop, job, form }) {
},
]}
>
<FormItemEmail email={getFieldValue("est_ea")} />
<FormItemEmail email={getFieldValue("est_ea")} disabled={jobRO} />
</Form.Item>
</FormRow>
<FormRow header={t("jobs.forms.other")}>
<Form.Item label={t("jobs.fields.csr")} name="csr">
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.category")} name="category">
<Select>
<Select disabled={jobRO}>
{bodyshop.md_categories.map((s) => (
<Select.Option key={s} value={s}>
{s}
@@ -193,25 +194,25 @@ export function JobsDetailGeneral({ bodyshop, job, form }) {
label={t("jobs.fields.selling_dealer")}
name="selling_dealer"
>
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.servicing_dealer")}
name="servicing_dealer"
>
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.selling_dealer_contact")}
name="selling_dealer_contact"
>
<Input />
<Input disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.servicing_dealer_contact")}
name="servicing_dealer_contact"
>
<Input />
<Input disabled={jobRO} />
</Form.Item>
</FormRow>
</div>

View File

@@ -12,9 +12,11 @@ import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
import JobsDetaiLheaderCsi from "./jobs-detail-header-actions.csi.component";
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
@@ -36,6 +38,7 @@ export function JobsDetailHeaderActions({
setBillEnterContext,
setPaymentContext,
setJobCostingContext,
jobRO,
}) {
const { t } = useTranslation();
const client = useApolloClient();
@@ -58,7 +61,7 @@ export function JobsDetailHeaderActions({
const statusmenu = (
<Menu key="popovermenu">
<Menu.Item
disabled={!jobInPreProduction || !job.converted}
disabled={!jobInPreProduction || !job.converted || jobRO}
onClick={() => {
logImEXEvent("job_header_schedule");
@@ -75,10 +78,16 @@ export function JobsDetailHeaderActions({
</Menu.Item>
<Menu.Item
disabled={
!!job.intakechecklist || !jobInPreProduction || !job.converted
!!job.intakechecklist ||
!jobInPreProduction ||
!job.converted ||
jobRO
}
>
{!!job.intakechecklist || !jobInPreProduction || !job.converted ? (
{!!job.intakechecklist ||
!jobInPreProduction ||
!job.converted ||
jobRO ? (
t("jobs.actions.intake")
) : (
<Link to={`/manage/jobs/${job.id}/intake`}>
@@ -86,7 +95,7 @@ export function JobsDetailHeaderActions({
</Link>
)}
</Menu.Item>
<Menu.Item disabled={!jobInProduction}>
<Menu.Item disabled={!jobInProduction || jobRO}>
{!jobInProduction ? (
t("jobs.actions.deliver")
) : (
@@ -97,6 +106,7 @@ export function JobsDetailHeaderActions({
</Menu.Item>
<Menu.Item
key="enterpayments"
disabled={jobRO}
onClick={() => {
logImEXEvent("job_header_enter_payment");
@@ -108,7 +118,7 @@ export function JobsDetailHeaderActions({
>
{t("menus.header.enterpayment")}
</Menu.Item>
<Menu.Item key="cccontract">
<Menu.Item key="cccontract" disabled={jobRO}>
<Link
to={{
pathname: "/manage/courtesycars/contracts/new",
@@ -120,7 +130,7 @@ export function JobsDetailHeaderActions({
</Menu.Item>
<Menu.Item
key="addtoproduction"
disabled={!!!job.converted || !!job.inproduction}
disabled={!!!job.converted || !!job.inproduction || jobRO}
onClick={() => AddToProduction(client, job.id, refetch)}
>
{t("jobs.actions.addtoproduction")}
@@ -148,6 +158,7 @@ export function JobsDetailHeaderActions({
</Menu.Item>
<Menu.Item
key="postbills"
disabled={jobRO}
onClick={() => {
logImEXEvent("job_header_enter_bills");
@@ -162,10 +173,10 @@ export function JobsDetailHeaderActions({
{t("jobs.actions.postbills")}
</Menu.Item>
<Menu.Item
disabled={!!job.date_invoiced || !jobInPostProduction}
disabled={!!job.date_invoiced || !jobInPostProduction || jobRO}
key="closejob"
>
{!!job.date_invoiced || !jobInPostProduction ? (
{!!job.date_invoiced || !jobInPostProduction || jobRO ? (
t("menus.jobsactions.closejob")
) : (
<Link

View File

@@ -4,8 +4,8 @@ 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 { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
import JobsChangeStatus from "../jobs-change-status/jobs-change-status.component";
@@ -16,7 +16,7 @@ import VehicleTagPopoverComponent from "../vehicle-tag-popover/vehicle-tag-popov
import "./jobs-detail-header.styles.scss";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
@@ -25,11 +25,10 @@ const mapDispatchToProps = (dispatch) => ({
});
export function JobsDetailHeader({
setPrintCenterContext,
jobRO,
job,
refetch,
setPrintCenterContext,
bodyshop,
setScheduleContext,
loading,
form,
}) {
@@ -60,6 +59,7 @@ export function JobsDetailHeader({
<Button
type="primary"
loading={loading}
disabled={jobRO}
className="imex-flex-row__margin"
onClick={() => form.submit()}
>

View File

@@ -10,7 +10,7 @@ const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
export function JobsDetailRatesChangeButton({ form, bodyshop }) {
export function JobsDetailRatesChangeButton({ disabled, form, bodyshop }) {
const { t } = useTranslation();
const handleClick = ({ item, key, keyPath }) => {
@@ -30,7 +30,7 @@ export function JobsDetailRatesChangeButton({ form, bodyshop }) {
);
return (
<Dropdown overlay={menu}>
<Dropdown overlay={menu} disabled={disabled}>
<a
className="ant-dropdown-link"
href=" #"

View File

@@ -1,11 +1,18 @@
import { Form, InputNumber, Select } from "antd";
import { Form, InputNumber, Select, Switch } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
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 FormRow from "../layout-form-row/layout-form-row.component";
export default function JobsDetailRates({ job, form }) {
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
const mapStateToProps = createStructuredSelector({
jobRO: selectJobReadOnly,
});
export function JobsDetailRates({ job, jobRO, form }) {
const { t } = useTranslation();
return (
@@ -18,127 +25,128 @@ export default function JobsDetailRates({ job, form }) {
label={t("jobs.fields.depreciation_taxes")}
name="depreciation_taxes"
>
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.other_amount_payable")}
name="other_amount_payable"
>
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.towing_payable")}
name="towing_payable"
>
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.storage_payable")}
name="storage_payable"
>
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.adjustment_bottom_line")}
name="adjustment_bottom_line"
>
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.ca_gst_registrant")}
name="ca_gst_registrant"
valuePropName="checked"
>
<Switch />
<Switch disabled={jobRO} />
</Form.Item>
</FormRow>
<JobsDetailRatesChangeButton form={form} />
<JobsDetailRatesChangeButton form={form} disabled={jobRO} />
<FormRow header={t("jobs.forms.laborrates")}>
<Form.Item label={t("jobs.fields.rate_laa")} name="rate_laa">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lab")} name="rate_lab">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lad")} name="rate_lad">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lae")} name="rate_lae">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lar")} name="rate_lar">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_las")} name="rate_las">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_laf")} name="rate_laf">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lam")} name="rate_lam">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lag")} name="rate_lag">
<CurrencyInput />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la1")} name="rate_la1">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la2")} name="rate_la2">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la3")} name="rate_la3">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_la4")} name="rate_la4">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_lau")} name="rate_lau">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mapa")} name="rate_mapa">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mash")} name="rate_mash">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mahw")} name="rate_mahw">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma2s")} name="rate_ma2s">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_ma3s")} name="rate_ma3s">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_mabl")} name="rate_mabl">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_macs")} name="rate_macs">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.rate_matd")} name="rate_matd">
<CurrencyInput />
<CurrencyInput disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.federal_tax_rate")}
name="federal_tax_rate"
>
<InputNumber min={0} max={1} precision={2} />
<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} />
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
</Form.Item>
<Form.Item
label={t("jobs.fields.local_tax_rate")}
name="local_tax_rate"
>
<InputNumber min={0} max={1} precision={2} />
<InputNumber min={0} max={1} precision={2} disabled={jobRO} />
</Form.Item>
</FormRow>
</div>
);
}
export default connect(mapStateToProps, null)(JobsDetailRates);

View File

@@ -4,6 +4,7 @@ import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
@@ -12,6 +13,7 @@ import JobTotalsTable from "../job-totals-table/job-totals-table.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
const mapDispatchToProps = (dispatch) => ({
@@ -23,6 +25,7 @@ const stripeTestEnv = process.env.REACT_APP_STRIPE_PUBLIC_KEY; //.includes("test
export function JobsDetailTotals({
job,
jobRO,
bodyshop,
setPaymentContext,
refetch,
@@ -96,6 +99,7 @@ export function JobsDetailTotals({
</table>
<Space direction="vertical">
<Button
disabled={jobRO}
onClick={() =>
setPaymentContext({
actions: { refetch: refetch },

View File

@@ -17,6 +17,7 @@ export function PartsOrderLineBackorderButton({
partsOrderStatus,
partsLineId,
jobLineId,
disabled,
bodyshop,
}) {
const [visibility, setVisibility] = useState(false);
@@ -84,7 +85,12 @@ export function PartsOrderLineBackorderButton({
);
return (
<Popover destroyTooltipOnHide content={popContent} visible={visibility}>
<Popover
destroyTooltipOnHide
content={popContent}
visible={visibility}
disabled={disabled}
>
<Button loading={loading} onClick={handlePopover}>
{isAlreadyBackordered
? t("parts_orders.actions.receive")

View File

@@ -13,9 +13,10 @@ import { DateFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters";
import PartsOrderLineBackorderButton from "../parts-order-line-backorder-button/parts-order-line-backorder-button.component";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
jobRO: selectJobReadOnly,
bodyshop: selectBodyshop,
});
@@ -27,8 +28,8 @@ const mapDispatchToProps = (dispatch) => ({
export function PartsOrderListTableComponent({
setBillEnterContext,
bodyshop,
jobRO,
job,
billsQuery,
handleOnRowClick,
}) {
@@ -90,6 +91,7 @@ export function PartsOrderListTableComponent({
key: "actions",
render: (text, record) => (
<Button
disabled={jobRO}
onClick={() => {
logImEXEvent("parts_order_receive_bill");
@@ -197,6 +199,7 @@ export function PartsOrderListTableComponent({
render: (text, record) => (
<div>
<PartsOrderLineBackorderButton
disabled={jobRO}
partsOrderStatus={record.status}
partsLineId={record.id}
jobLineId={record.job_line_id}

View File

@@ -26,6 +26,7 @@ import FormFieldsChanged from "../../components/form-fields-changed-alert/form-f
import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component";
import { selectBodyshop } from "../../redux/user/user.selectors";
import JobsDetailChecklists from "../../components/jobs-detail-checklists/jobs-detail-checklists.component";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
const JobsLinesContainer = lazy(() =>
import("../../components/job-detail-lines/job-lines.container")
@@ -79,6 +80,7 @@ const JobReconciliationModal = lazy(() =>
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
jobRO: selectJobReadOnly,
});
export function JobsDetailPage({
@@ -86,7 +88,7 @@ export function JobsDetailPage({
mutationUpdateJob,
handleSubmit,
refetch,
bodyshop,
jobRO,
}) {
const { t } = useTranslation();
const [form] = Form.useForm();

View File

@@ -854,6 +854,7 @@
"est_number": "Estimate #",
"est_ph1": "Appraiser Phone #",
"federal_tax_payable": "Federal Tax Payable",
"federal_tax_rate": "Federal Tax Rate",
"ins_addr1": "Insurance Co. Address",
"ins_city": "Insurance City",
"ins_co_id": "Insurance Co. ID",
@@ -885,6 +886,7 @@
"lar": "Refinish",
"las": "Structural",
"lau": "LAU",
"local_tax_rate": "Local Tax Rate",
"loss_date": "Loss Date",
"loss_desc": "Loss Description",
"ma2s": "2 Stage Paint",
@@ -948,6 +950,7 @@
"servicing_dealer": "Servicing Dealer",
"servicing_dealer_contact": "Servicing Dealer Contact",
"specialcoveragepolicy": "Special Coverage Policy",
"state_tax_rate": "State Tax Rate",
"status": "Job Status",
"storage_payable": "Storage/PVRT",
"tax_registration_number": "Tax Registration Number",

View File

@@ -854,6 +854,7 @@
"est_number": "Numero Estimado",
"est_ph1": "Número de teléfono del tasador",
"federal_tax_payable": "Impuesto federal por pagar",
"federal_tax_rate": "",
"ins_addr1": "Dirección de Insurance Co.",
"ins_city": "Ciudad de seguros",
"ins_co_id": "ID de la compañía de seguros",
@@ -885,6 +886,7 @@
"lar": "",
"las": "",
"lau": "",
"local_tax_rate": "",
"loss_date": "Fecha de pérdida",
"loss_desc": "",
"ma2s": "",
@@ -948,6 +950,7 @@
"servicing_dealer": "Distribuidor de servicio",
"servicing_dealer_contact": "Servicio Contacto con el concesionario",
"specialcoveragepolicy": "Política de cobertura especial",
"state_tax_rate": "",
"status": "Estado del trabajo",
"storage_payable": "Almacenamiento / PVRT",
"tax_registration_number": "",

View File

@@ -854,6 +854,7 @@
"est_number": "Numéro d'estimation",
"est_ph1": "Numéro de téléphone de l'évaluateur",
"federal_tax_payable": "Impôt fédéral à payer",
"federal_tax_rate": "",
"ins_addr1": "Adresse Insurance Co.",
"ins_city": "Insurance City",
"ins_co_id": "ID de la compagnie d'assurance",
@@ -885,6 +886,7 @@
"lar": "",
"las": "",
"lau": "",
"local_tax_rate": "",
"loss_date": "Date de perte",
"loss_desc": "",
"ma2s": "",
@@ -948,6 +950,7 @@
"servicing_dealer": "Concessionnaire",
"servicing_dealer_contact": "Contacter le concessionnaire",
"specialcoveragepolicy": "Politique de couverture spéciale",
"state_tax_rate": "",
"status": "Statut de l'emploi",
"storage_payable": "Stockage / PVRT",
"tax_registration_number": "",