feature/IO-3558-Reynolds-Part-2 - Prevent exporting without early ro / add a way to fake sconvert state in admin panel
This commit is contained in:
@@ -208,16 +208,16 @@ export default function RRPostForm({
|
||||
});
|
||||
};
|
||||
|
||||
// Check if early RO was created (job has dms_id)
|
||||
const hasEarlyRO = !!job?.dms_id;
|
||||
// Check if early RO was created (job has all early RO fields)
|
||||
const hasEarlyRO = !!(job?.dms_id && job?.dms_customer_id && job?.dms_advisor_id);
|
||||
|
||||
return (
|
||||
<Card title={t("jobs.labels.dms.postingform")}>
|
||||
{hasEarlyRO && (
|
||||
<Typography.Paragraph type="success" strong style={{ marginBottom: 16 }}>
|
||||
✅ Early RO Created: {job.dms_id}
|
||||
✅ {t("jobs.labels.dms.earlyro.created")} {job.dms_id}
|
||||
<br />
|
||||
<Typography.Text type="secondary">This will update the existing RO with full job data.</Typography.Text>
|
||||
<Typography.Text type="secondary">{t("jobs.labels.dms.earlyro.willupdate")}</Typography.Text>
|
||||
</Typography.Paragraph>
|
||||
)}
|
||||
<Form
|
||||
@@ -372,7 +372,7 @@ export default function RRPostForm({
|
||||
<Statistic title={t("jobs.labels.subtotal")} value={totals.totalSale.toFormat()} />
|
||||
<Typography.Title>=</Typography.Title>
|
||||
<Button disabled={!advisorOk} htmlType="submit" type={hasEarlyRO ? "default" : "primary"}>
|
||||
{hasEarlyRO ? t("jobs.actions.dms.update_ro", "Update RO") : t("jobs.actions.dms.post")}
|
||||
{hasEarlyRO ? t("jobs.actions.dms.update_ro") : t("jobs.actions.dms.post")}
|
||||
</Button>
|
||||
</Space>
|
||||
);
|
||||
|
||||
@@ -106,8 +106,8 @@ export function JobsConvertButton({ bodyshop, job, refetch, jobRO, insertAuditTr
|
||||
setEarlyRoCreated(true); // Mark early RO as created
|
||||
setEarlyRoCreatedThisSession(true); // Mark as created in this session
|
||||
notification.success({
|
||||
title: t("jobs.successes.early_ro_created", "Early RO Created"),
|
||||
message: `RO Number: ${result.roNumber || "N/A"}`
|
||||
title: t("jobs.successes.early_ro_created"),
|
||||
description: `RO Number: ${result.roNumber || "N/A"}`
|
||||
});
|
||||
// Delay refetch to keep success message visible for 2 seconds
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -1998,6 +1998,9 @@ export const QUERY_JOB_CLOSE_DETAILS = gql`
|
||||
qb_multiple_payers
|
||||
lbr_adjustments
|
||||
ownr_ea
|
||||
dms_id
|
||||
dms_customer_id
|
||||
dms_advisor_id
|
||||
payments {
|
||||
amount
|
||||
created_at
|
||||
|
||||
@@ -426,6 +426,24 @@ export function DmsContainer({ bodyshop, setBreadcrumbs, setSelectedHeader, inse
|
||||
|
||||
if (data.jobs_by_pk?.date_exported) return <Result status="warning" title={t("dms.errors.alreadyexported")} />;
|
||||
|
||||
// Check if Reynolds mode requires early RO
|
||||
const hasEarlyRO = !!(data.jobs_by_pk?.dms_id && data.jobs_by_pk?.dms_customer_id && data.jobs_by_pk?.dms_advisor_id);
|
||||
|
||||
if (isRrMode && !hasEarlyRO) {
|
||||
return (
|
||||
<Result
|
||||
status="warning"
|
||||
title={t("dms.errors.earlyrorequired")}
|
||||
subTitle={t("dms.errors.earlyrorequired.message")}
|
||||
extra={
|
||||
<Link to={`/manage/jobs/${jobId}/admin`}>
|
||||
<Button type="primary">{t("general.actions.gotoadmin")}</Button>
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AlertComponent style={{ marginBottom: 10 }} title={bannerMessage} type="warning" showIcon closable />
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { useQuery } from "@apollo/client/react";
|
||||
import { Button, Card, Col, Result, Row, Space, Typography } from "antd";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useMutation, useQuery } from "@apollo/client/react";
|
||||
import { Button, Card, Col, Form, Input, Modal, Result, Row, Select, Space, Switch, Typography } from "antd";
|
||||
import { useEffect, useState, useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
|
||||
import { some } from "lodash";
|
||||
import axios from "axios";
|
||||
import AlertComponent from "../../components/alert/alert.component";
|
||||
import JobCalculateTotals from "../../components/job-calculate-totals/job-calculate-totals.component";
|
||||
import ScoreboardAddButton from "../../components/job-scoreboard-add-button/job-scoreboard-add-button.component";
|
||||
@@ -21,14 +23,16 @@ import LoadingSpinner from "../../components/loading-spinner/loading-spinner.com
|
||||
import NotFound from "../../components/not-found/not-found.component";
|
||||
import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component";
|
||||
import RREarlyROModal from "../../components/dms-post-form/rr-early-ro-modal";
|
||||
import { GET_JOB_BY_PK } from "../../graphql/jobs.queries";
|
||||
import { GET_JOB_BY_PK, CONVERT_JOB_TO_RO } from "../../graphql/jobs.queries";
|
||||
import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions";
|
||||
import { insertAuditTrail } from "../../redux/application/application.actions";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { useSocket } from "../../contexts/SocketIO/useSocket";
|
||||
import { useNotification } from "../../contexts/Notifications/notificationContext";
|
||||
import { DMS_MAP, getDmsMode } from "../../utils/dmsUtils";
|
||||
import InstanceRenderManager from "../../utils/instanceRenderMgr";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
@@ -36,7 +40,8 @@ const mapStateToProps = createStructuredSelector({
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)),
|
||||
setSelectedHeader: (key) => dispatch(setSelectedHeader(key))
|
||||
setSelectedHeader: (key) => dispatch(setSelectedHeader(key)),
|
||||
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
|
||||
});
|
||||
|
||||
const colSpan = {
|
||||
@@ -50,7 +55,7 @@ const cardStyle = {
|
||||
height: "100%"
|
||||
};
|
||||
|
||||
export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, bodyshop }) {
|
||||
export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, bodyshop, insertAuditTrail }) {
|
||||
const { jobId } = useParams();
|
||||
const { loading, error, data, refetch } = useQuery(GET_JOB_BY_PK, {
|
||||
variables: { id: jobId },
|
||||
@@ -61,6 +66,11 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, bodyshop
|
||||
const { socket } = useSocket(); // Extract socket from context
|
||||
const notification = useNotification();
|
||||
const [showEarlyROModal, setShowEarlyROModal] = useState(false);
|
||||
const [showConvertModal, setShowConvertModal] = useState(false);
|
||||
const [convertLoading, setConvertLoading] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
const [mutationConvertJob] = useMutation(CONVERT_JOB_TO_RO);
|
||||
const allFormValues = Form.useWatch([], form);
|
||||
|
||||
// Get Fortellis treatment for proper DMS mode detection
|
||||
const {
|
||||
@@ -105,13 +115,53 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, bodyshop
|
||||
|
||||
const handleEarlyROSuccess = (result) => {
|
||||
notification.success({
|
||||
title: t("jobs.successes.early_ro_created", "Early RO Created"),
|
||||
message: `RO Number: ${result.roNumber || "N/A"}`
|
||||
title: t("jobs.successes.early_ro_created"),
|
||||
description: `RO Number: ${result.roNumber || "N/A"}`
|
||||
});
|
||||
setShowEarlyROModal(false);
|
||||
refetch?.();
|
||||
};
|
||||
|
||||
const handleConvert = async ({ employee_csr, category, ...values }) => {
|
||||
if (!job?.id) return;
|
||||
setConvertLoading(true);
|
||||
const res = await mutationConvertJob({
|
||||
variables: {
|
||||
jobId: job.id,
|
||||
job: {
|
||||
converted: true,
|
||||
...(bodyshop?.enforce_conversion_csr ? { employee_csr } : {}),
|
||||
...(bodyshop?.enforce_conversion_category ? { category } : {}),
|
||||
...values
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (values.ca_gst_registrant) {
|
||||
await axios.post("/job/totalsssu", {
|
||||
id: job.id
|
||||
});
|
||||
}
|
||||
|
||||
if (!res.errors) {
|
||||
refetch();
|
||||
notification.success({
|
||||
title: t("jobs.successes.converted")
|
||||
});
|
||||
|
||||
insertAuditTrail({
|
||||
jobid: job.id,
|
||||
operation: AuditTrailMapping.jobconverted(res.data.update_jobs.returning[0].ro_number),
|
||||
type: "jobconverted"
|
||||
});
|
||||
|
||||
setShowConvertModal(false);
|
||||
}
|
||||
setConvertLoading(false);
|
||||
};
|
||||
|
||||
const submitDisabled = useCallback(() => some(allFormValues, (v) => v === undefined), [allFormValues]);
|
||||
|
||||
if (loading) return <LoadingSpinner />;
|
||||
if (error) return <AlertComponent title={error.message} type="error" />;
|
||||
if (!data.jobs_by_pk) return <NotFound />;
|
||||
@@ -138,7 +188,12 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, bodyshop
|
||||
<JobsAdminRemoveAR job={data ? data.jobs_by_pk : {}} />
|
||||
{isReynoldsMode && job?.converted && !job?.dms_id && !job?.dms_customer_id && !job?.dms_advisor_id && (
|
||||
<Button className="ant-btn ant-btn-default" onClick={() => setShowEarlyROModal(true)}>
|
||||
Create RR RO
|
||||
{t("jobs.actions.dms.createearlyro", "Create RR RO")}
|
||||
</Button>
|
||||
)}
|
||||
{isReynoldsMode && !job?.converted && !job?.dms_id && (
|
||||
<Button type="primary" danger onClick={() => setShowConvertModal(true)}>
|
||||
{t("jobs.actions.convertwithoutearlyro", "Convert without Early RO")}
|
||||
</Button>
|
||||
)}
|
||||
</Space>
|
||||
@@ -176,6 +231,161 @@ export function JobsCloseContainer({ setBreadcrumbs, setSelectedHeader, bodyshop
|
||||
socket={socket}
|
||||
job={job}
|
||||
/>
|
||||
|
||||
{/* Convert without Early RO Modal */}
|
||||
<Modal
|
||||
open={showConvertModal}
|
||||
onCancel={() => setShowConvertModal(false)}
|
||||
title={t("jobs.actions.convertwithoutearlyro", "Convert without Early RO")}
|
||||
footer={null}
|
||||
width={700}
|
||||
destroyOnHidden
|
||||
>
|
||||
<Form
|
||||
layout="vertical"
|
||||
form={form}
|
||||
onFinish={handleConvert}
|
||||
initialValues={{
|
||||
driveable: true,
|
||||
towin: job?.towin,
|
||||
ca_gst_registrant: job?.ca_gst_registrant,
|
||||
employee_csr: job?.employee_csr,
|
||||
category: job?.category,
|
||||
referral_source: job?.referral_source,
|
||||
referral_source_extra: job?.referral_source_extra ?? ""
|
||||
}}
|
||||
>
|
||||
<Form.Item
|
||||
name={["ins_co_nm"]}
|
||||
label={t("jobs.fields.ins_co_nm")}
|
||||
rules={[
|
||||
{
|
||||
required: true
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Select showSearch>
|
||||
{bodyshop?.md_ins_cos?.map((s, i) => (
|
||||
<Select.Option key={i} value={s.name}>
|
||||
{s.name}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
{bodyshop?.enforce_class && (
|
||||
<Form.Item
|
||||
name={"class"}
|
||||
label={t("jobs.fields.class")}
|
||||
rules={[
|
||||
{
|
||||
required: bodyshop.enforce_class
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Select>
|
||||
{bodyshop?.md_classes?.map((s) => (
|
||||
<Select.Option key={s} value={s}>
|
||||
{s}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
)}
|
||||
{bodyshop?.enforce_referral && (
|
||||
<>
|
||||
<Form.Item
|
||||
name={"referral_source"}
|
||||
label={t("jobs.fields.referralsource")}
|
||||
rules={[
|
||||
{
|
||||
required: bodyshop.enforce_referral
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Select>
|
||||
{bodyshop?.md_referral_sources?.map((s) => (
|
||||
<Select.Option key={s} value={s}>
|
||||
{s}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.referral_source_extra")} name="referral_source_extra">
|
||||
<Input />
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
{bodyshop?.enforce_conversion_csr && (
|
||||
<Form.Item
|
||||
name={"employee_csr"}
|
||||
label={t(
|
||||
InstanceRenderManager({
|
||||
imex: "jobs.fields.employee_csr",
|
||||
rome: "jobs.fields.employee_csr_writer"
|
||||
})
|
||||
)}
|
||||
rules={[
|
||||
{
|
||||
required: bodyshop.enforce_conversion_csr
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Select
|
||||
showSearch={{
|
||||
optionFilterProp: "children",
|
||||
filterOption: (input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
|
||||
}}
|
||||
style={{ width: 200 }}
|
||||
>
|
||||
{bodyshop?.employees
|
||||
?.filter((emp) => emp.active)
|
||||
?.map((emp) => (
|
||||
<Select.Option value={emp.id} key={emp.id} name={`${emp.first_name} ${emp.last_name}`}>
|
||||
{`${emp.first_name} ${emp.last_name}`}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
)}
|
||||
{bodyshop?.enforce_conversion_category && (
|
||||
<Form.Item
|
||||
name={"category"}
|
||||
label={t("jobs.fields.category")}
|
||||
rules={[
|
||||
{
|
||||
required: bodyshop.enforce_conversion_category
|
||||
}
|
||||
]}
|
||||
>
|
||||
<Select allowClear>
|
||||
{bodyshop?.md_categories?.map((s) => (
|
||||
<Select.Option key={s} value={s}>
|
||||
{s}
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
</Form.Item>
|
||||
)}
|
||||
{bodyshop?.region_config?.toLowerCase().startsWith("ca") && (
|
||||
<Form.Item label={t("jobs.fields.ca_gst_registrant")} name="ca_gst_registrant" valuePropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
)}
|
||||
<Form.Item label={t("jobs.fields.driveable")} name="driveable" valuePropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<Form.Item label={t("jobs.fields.towin")} name="towin" valuePropName="checked">
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
|
||||
<Space wrap style={{ marginTop: 16 }}>
|
||||
<Button disabled={submitDisabled()} type="primary" danger onClick={() => form.submit()} loading={convertLoading}>
|
||||
{t("jobs.actions.convert")}
|
||||
</Button>
|
||||
<Button onClick={() => setShowConvertModal(false)}>{t("general.actions.close")}</Button>
|
||||
</Space>
|
||||
</Form>
|
||||
</Modal>
|
||||
</RbacWrapper>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Modal,
|
||||
Popconfirm,
|
||||
Row,
|
||||
Select,
|
||||
@@ -42,7 +43,7 @@ import { setModalContext } from "../../redux/modals/modals.actions.js";
|
||||
import { selectBodyshop, selectCurrentUser } from "../../redux/user/user.selectors";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import dayjs from "../../utils/day";
|
||||
import { bodyshopHasDmsKey } from "../../utils/dmsUtils.js";
|
||||
import { bodyshopHasDmsKey, DMS_MAP, getDmsMode } from "../../utils/dmsUtils.js";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -71,6 +72,11 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
const notification = useNotification();
|
||||
|
||||
const hasDMSKey = bodyshopHasDmsKey(bodyshop);
|
||||
const dmsMode = getDmsMode(bodyshop, "off");
|
||||
const isReynoldsMode = dmsMode === DMS_MAP.reynolds;
|
||||
const hasEarlyRO = !!(job?.dms_id && job?.dms_customer_id && job?.dms_advisor_id);
|
||||
const canSendToDMS = !isReynoldsMode || hasEarlyRO;
|
||||
const [showEarlyROModal, setShowEarlyROModal] = useState(false);
|
||||
|
||||
const {
|
||||
treatments: { Qb_Multi_Ar, ClosingPeriod }
|
||||
@@ -82,18 +88,18 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
|
||||
const handleFinish = async ({ removefromproduction, ...values }) => {
|
||||
setLoading(true);
|
||||
|
||||
|
||||
// Validate that all joblines have valid IDs
|
||||
const joblinesWithIds = values.joblines.filter(jl => jl && jl.id);
|
||||
const joblinesWithIds = values.joblines.filter((jl) => jl && jl.id);
|
||||
if (joblinesWithIds.length !== values.joblines.length) {
|
||||
notification.error({
|
||||
title: t("jobs.errors.invalidjoblines"),
|
||||
message: t("jobs.errors.missingjoblineids")
|
||||
description: t("jobs.errors.missingjoblineids")
|
||||
});
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const result = await client.mutate({
|
||||
mutation: generateJobLinesUpdatesForInvoicing(values.joblines)
|
||||
});
|
||||
@@ -208,9 +214,17 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
{bodyshopHasDmsKey(bodyshop) && (
|
||||
<Link to={`/manage/dms?jobId=${job.id}`}>
|
||||
<Button disabled={job.date_exported || !jobRO}>{t("jobs.actions.sendtodms")}</Button>
|
||||
</Link>
|
||||
<>
|
||||
{canSendToDMS ? (
|
||||
<Link to={`/manage/dms?jobId=${job.id}`}>
|
||||
<Button disabled={job.date_exported || !jobRO}>{t("jobs.actions.sendtodms")}</Button>
|
||||
</Link>
|
||||
) : (
|
||||
<Button disabled={job.date_exported || !jobRO} onClick={() => setShowEarlyROModal(true)}>
|
||||
{t("jobs.actions.sendtodms")}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
<Button
|
||||
onClick={() => {
|
||||
@@ -527,6 +541,30 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
<Divider />
|
||||
<JobsCloseLines job={job} />
|
||||
</Form>
|
||||
|
||||
{/* Early RO Required Modal */}
|
||||
<Modal
|
||||
open={showEarlyROModal}
|
||||
onCancel={() => setShowEarlyROModal(false)}
|
||||
footer={null}
|
||||
title={
|
||||
<Space>
|
||||
<Typography.Text type="warning" style={{ fontSize: "1.2em" }}>
|
||||
⚠️
|
||||
</Typography.Text>
|
||||
<span>{t("dms.errors.earlyrorequired")}</span>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Space orientation="vertical" size="large" style={{ width: "100%" }}>
|
||||
<Typography.Paragraph>{t("dms.errors.earlyrorequired.message")}</Typography.Paragraph>
|
||||
<Link to={`/manage/jobs/${job.id}/admin`}>
|
||||
<Button type="primary" block onClick={() => setShowEarlyROModal(false)}>
|
||||
{t("general.actions.gotoadmin")}
|
||||
</Button>
|
||||
</Link>
|
||||
</Space>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1047,7 +1047,9 @@
|
||||
},
|
||||
"dms": {
|
||||
"errors": {
|
||||
"alreadyexported": "This job has already been sent to the DMS. If you need to resend it, please use admin permissions to mark the job for re-export."
|
||||
"alreadyexported": "This job has already been sent to the DMS. If you need to resend it, please use admin permissions to mark the job for re-export.",
|
||||
"earlyrorequired": "Early RO Required",
|
||||
"earlyrorequired.message": "This job requires an early Repair Order to be created before posting to Reynolds. Please use the admin panel to create the early RO first."
|
||||
},
|
||||
"labels": {
|
||||
"refreshallocations": "Refresh to see DMS Allocations."
|
||||
@@ -1244,6 +1246,7 @@
|
||||
"deselectall": "Deselect All",
|
||||
"download": "Download",
|
||||
"edit": "Edit",
|
||||
"gotoadmin": "Go to Admin Panel",
|
||||
"login": "Login",
|
||||
"next": "Next",
|
||||
"ok": "Ok",
|
||||
@@ -1622,11 +1625,13 @@
|
||||
"changestatus": "Change Status",
|
||||
"changestimator": "Change Estimator",
|
||||
"convert": "Convert",
|
||||
"convertwithoutearlyro": "Convert without Early RO",
|
||||
"createiou": "Create IOU",
|
||||
"deliver": "Deliver",
|
||||
"deliver_quick": "Quick Deliver",
|
||||
"dms": {
|
||||
"addpayer": "Add Payer",
|
||||
"createearlyro": "Create RR RO",
|
||||
"createnewcustomer": "Create New Customer",
|
||||
"findmakemodelcode": "Find Make/Model Code",
|
||||
"getmakes": "Get Makes",
|
||||
@@ -1635,6 +1640,7 @@
|
||||
},
|
||||
"post": "Post",
|
||||
"refetchmakesmodels": "Refetch Make and Model Codes",
|
||||
"update_ro": "Update RO",
|
||||
"usegeneric": "Use Generic Customer",
|
||||
"useselected": "Use Selected Customer"
|
||||
},
|
||||
@@ -2107,6 +2113,11 @@
|
||||
"damageto": "Damage to $t(jobs.fields.area_of_damage_impact.{{area_of_damage}}).",
|
||||
"defaultstory": "B/S RO: {{ro_number}}. Owner: {{ownr_nm}}. Insurance Co: {{ins_co_nm}}. Claim/PO #: {{clm_po}}",
|
||||
"disablebillwip": "Cost and WIP for bills has been ignored per shop configuration.",
|
||||
"earlyro": {
|
||||
"created": "Early RO Created:",
|
||||
"fields": "Required fields:",
|
||||
"willupdate": "This will update the existing RO with full job data."
|
||||
},
|
||||
"invoicedatefuture": "Invoice date must be today or in the future for CDK posting.",
|
||||
"kmoutnotgreaterthankmin": "Mileage out must be greater than mileage in.",
|
||||
"logs": "Logs",
|
||||
@@ -2264,6 +2275,7 @@
|
||||
"delete": "Job deleted successfully.",
|
||||
"deleted": "Job deleted successfully.",
|
||||
"duplicated": "Job duplicated successfully. ",
|
||||
"early_ro_created": "Early RO Created",
|
||||
"exported": "Job(s) exported successfully. ",
|
||||
"invoiced": "Job closed and invoiced successfully.",
|
||||
"ioucreated": "IOU created successfully. Click to see.",
|
||||
|
||||
@@ -1047,7 +1047,9 @@
|
||||
},
|
||||
"dms": {
|
||||
"errors": {
|
||||
"alreadyexported": ""
|
||||
"alreadyexported": "",
|
||||
"earlyrorequired": "",
|
||||
"earlyrorequired.message": ""
|
||||
},
|
||||
"labels": {
|
||||
"refreshallocations": ""
|
||||
@@ -1244,6 +1246,7 @@
|
||||
"deselectall": "",
|
||||
"download": "",
|
||||
"edit": "Editar",
|
||||
"gotoadmin": "",
|
||||
"login": "",
|
||||
"next": "",
|
||||
"ok": "",
|
||||
@@ -1622,11 +1625,13 @@
|
||||
"changestatus": "Cambiar Estado",
|
||||
"changestimator": "",
|
||||
"convert": "Convertir",
|
||||
"convertwithoutearlyro": "",
|
||||
"createiou": "",
|
||||
"deliver": "",
|
||||
"deliver_quick": "",
|
||||
"dms": {
|
||||
"addpayer": "",
|
||||
"createearlyro": "",
|
||||
"createnewcustomer": "",
|
||||
"findmakemodelcode": "",
|
||||
"getmakes": "",
|
||||
@@ -1635,6 +1640,7 @@
|
||||
},
|
||||
"post": "",
|
||||
"refetchmakesmodels": "",
|
||||
"update_ro": "",
|
||||
"usegeneric": "",
|
||||
"useselected": ""
|
||||
},
|
||||
@@ -2107,6 +2113,11 @@
|
||||
"damageto": "",
|
||||
"defaultstory": "",
|
||||
"disablebillwip": "",
|
||||
"earlyro": {
|
||||
"created": "",
|
||||
"fields": "",
|
||||
"willupdate": ""
|
||||
},
|
||||
"invoicedatefuture": "",
|
||||
"kmoutnotgreaterthankmin": "",
|
||||
"logs": "",
|
||||
@@ -2264,6 +2275,7 @@
|
||||
"delete": "",
|
||||
"deleted": "Trabajo eliminado con éxito.",
|
||||
"duplicated": "",
|
||||
"early_ro_created": "",
|
||||
"exported": "",
|
||||
"invoiced": "",
|
||||
"ioucreated": "",
|
||||
|
||||
@@ -1047,7 +1047,9 @@
|
||||
},
|
||||
"dms": {
|
||||
"errors": {
|
||||
"alreadyexported": ""
|
||||
"alreadyexported": "",
|
||||
"earlyrorequired": "",
|
||||
"earlyrorequired.message": ""
|
||||
},
|
||||
"labels": {
|
||||
"refreshallocations": ""
|
||||
@@ -1244,6 +1246,7 @@
|
||||
"deselectall": "",
|
||||
"download": "",
|
||||
"edit": "modifier",
|
||||
"gotoadmin": "",
|
||||
"login": "",
|
||||
"next": "",
|
||||
"ok": "",
|
||||
@@ -1622,11 +1625,13 @@
|
||||
"changestatus": "Changer le statut",
|
||||
"changestimator": "",
|
||||
"convert": "Convertir",
|
||||
"convertwithoutearlyro": "",
|
||||
"createiou": "",
|
||||
"deliver": "",
|
||||
"deliver_quick": "",
|
||||
"dms": {
|
||||
"addpayer": "",
|
||||
"createearlyro": "",
|
||||
"createnewcustomer": "",
|
||||
"findmakemodelcode": "",
|
||||
"getmakes": "",
|
||||
@@ -1635,6 +1640,7 @@
|
||||
},
|
||||
"post": "",
|
||||
"refetchmakesmodels": "",
|
||||
"update_ro": "",
|
||||
"usegeneric": "",
|
||||
"useselected": ""
|
||||
},
|
||||
@@ -2107,6 +2113,11 @@
|
||||
"damageto": "",
|
||||
"defaultstory": "",
|
||||
"disablebillwip": "",
|
||||
"earlyro": {
|
||||
"created": "",
|
||||
"fields": "",
|
||||
"willupdate": ""
|
||||
},
|
||||
"invoicedatefuture": "",
|
||||
"kmoutnotgreaterthankmin": "",
|
||||
"logs": "",
|
||||
@@ -2264,6 +2275,7 @@
|
||||
"delete": "",
|
||||
"deleted": "Le travail a bien été supprimé.",
|
||||
"duplicated": "",
|
||||
"early_ro_created": "",
|
||||
"exported": "",
|
||||
"invoiced": "",
|
||||
"ioucreated": "",
|
||||
|
||||
Reference in New Issue
Block a user