Compare commits
30 Commits
feature/IO
...
feature/IO
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ad520ab23e | ||
|
|
db1b701a96 | ||
|
|
2746421c09 | ||
|
|
5217120994 | ||
|
|
77f72a2a12 | ||
|
|
a84ad4ee32 | ||
|
|
2cacd75822 | ||
|
|
217a0b84ac | ||
|
|
f53ed8c427 | ||
|
|
f8b7588a04 | ||
|
|
ee3cb4456d | ||
|
|
e01a2af5a4 | ||
|
|
9c0cb5f80b | ||
|
|
1f726aca4d | ||
|
|
b9f398cf2d | ||
|
|
ff73a14610 | ||
|
|
1e44d4fe42 | ||
|
|
0f42875d1b | ||
|
|
a0f1299006 | ||
|
|
87d8a5d746 | ||
|
|
268851902a | ||
|
|
68bb7d2529 | ||
|
|
d50db12330 | ||
|
|
1438986c18 | ||
|
|
c047699fbb | ||
|
|
cadcfc9b0d | ||
|
|
55023ceaca | ||
|
|
45e143578c | ||
|
|
28a41f7637 | ||
|
|
2a2edeadb9 |
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,9 @@ export default function BillCmdReturnsTableComponent({ form, returnLoading, retu
|
||||
{fields.map((field, index) => (
|
||||
<tr key={field.key}>
|
||||
<td>
|
||||
<Form.Item hidden key={`${index}id`} name={[field.name, "id"]}>
|
||||
<ReadOnlyFormItemComponent />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
// label={t("joblines.fields.line_desc")}
|
||||
key={`${index}line_desc`}
|
||||
|
||||
@@ -373,9 +373,11 @@ export function BillFormComponent({
|
||||
"local_tax_rate"
|
||||
]);
|
||||
let totals;
|
||||
if (!!values.total && !!values.billlines && values.billlines.length > 0)
|
||||
if (!!values.total && !!values.billlines && values.billlines.length > 0) {
|
||||
totals = CalculateBillTotal(values);
|
||||
if (totals)
|
||||
}
|
||||
|
||||
if (totals) {
|
||||
return (
|
||||
// TODO: Align is not correct
|
||||
// eslint-disable-next-line react/no-unknown-property
|
||||
@@ -414,7 +416,7 @@ export function BillFormComponent({
|
||||
<Statistic
|
||||
title={t("bills.labels.discrepancy")}
|
||||
styles={{
|
||||
value: {
|
||||
content: {
|
||||
color: totals.discrepancy.getAmount() === 0 ? "green" : "red"
|
||||
}
|
||||
}}
|
||||
@@ -427,6 +429,7 @@ export function BillFormComponent({
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}}
|
||||
</Form.Item>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { DeleteFilled, DollarCircleFilled } from "@ant-design/icons";
|
||||
import { useTreatmentsWithConfig } from "@splitsoftware/splitio-react";
|
||||
import { Button, Checkbox, Form, Input, InputNumber, Select, Space, Switch, Table, Tooltip } from "antd";
|
||||
import { useRef } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
@@ -32,6 +33,7 @@ export function BillEnterModalLinesComponent({
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { setFieldsValue, getFieldsValue, getFieldValue } = form;
|
||||
const firstFieldRefs = useRef({});
|
||||
|
||||
const CONTROL_HEIGHT = 32;
|
||||
|
||||
@@ -90,6 +92,7 @@ export function BillEnterModalLinesComponent({
|
||||
});
|
||||
};
|
||||
|
||||
// Only fill actual_cost when the user forward-tabs out of Retail (actual_price)
|
||||
const autofillActualCost = (index) => {
|
||||
Promise.resolve().then(() => {
|
||||
const retailRaw = form.getFieldValue(["billlines", index, "actual_price"]);
|
||||
@@ -154,6 +157,9 @@ export function BillEnterModalLinesComponent({
|
||||
),
|
||||
formInput: (record, index) => (
|
||||
<BillLineSearchSelect
|
||||
ref={(el) => {
|
||||
firstFieldRefs.current[index] = el;
|
||||
}}
|
||||
disabled={disabled}
|
||||
options={lineData}
|
||||
style={{
|
||||
@@ -164,10 +170,9 @@ export function BillEnterModalLinesComponent({
|
||||
}}
|
||||
allowRemoved={form.getFieldValue("is_credit_memo") || false}
|
||||
onSelect={(value, opt) => {
|
||||
const d = normalizeDiscount(discount);
|
||||
const retail = Number(opt.cost);
|
||||
const computedActual = Number.isFinite(retail) ? round2(retail * (1 - d)) : null;
|
||||
|
||||
// IMPORTANT:
|
||||
// Do NOT autofill actual_cost here. It should only fill when the user forward-tabs
|
||||
// from Retail (actual_price) -> Actual Cost (actual_cost).
|
||||
setFieldsValue({
|
||||
billlines: (getFieldValue("billlines") || []).map((item, idx) => {
|
||||
if (idx !== index) return item;
|
||||
@@ -178,7 +183,7 @@ export function BillEnterModalLinesComponent({
|
||||
quantity: opt.part_qty || 1,
|
||||
actual_price: opt.cost,
|
||||
original_actual_price: opt.cost,
|
||||
actual_cost: isBlank(item.actual_cost) ? computedActual : item.actual_cost,
|
||||
// actual_cost intentionally untouched here
|
||||
cost_center: opt.part_type
|
||||
? bodyshopHasDmsKey(bodyshop)
|
||||
? opt.part_type !== "PAE"
|
||||
@@ -205,7 +210,7 @@ export function BillEnterModalLinesComponent({
|
||||
label: t("billlines.fields.line_desc"),
|
||||
rules: [{ required: true }]
|
||||
}),
|
||||
formInput: () => <Input.TextArea disabled={disabled} autoSize />
|
||||
formInput: () => <Input.TextArea disabled={disabled} autoSize tabIndex={0} />
|
||||
},
|
||||
{
|
||||
title: t("billlines.fields.quantity"),
|
||||
@@ -234,7 +239,7 @@ export function BillEnterModalLinesComponent({
|
||||
})
|
||||
]
|
||||
}),
|
||||
formInput: () => <InputNumber precision={0} min={1} disabled={disabled} />
|
||||
formInput: () => <InputNumber precision={0} min={1} disabled={disabled} tabIndex={0} />
|
||||
},
|
||||
{
|
||||
title: t("billlines.fields.actual_price"),
|
||||
@@ -251,9 +256,10 @@ export function BillEnterModalLinesComponent({
|
||||
<CurrencyInput
|
||||
min={0}
|
||||
disabled={disabled}
|
||||
onBlur={() => autofillActualCost(index)}
|
||||
tabIndex={0}
|
||||
// NOTE: Autofill should only happen on forward Tab out of Retail
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Tab") autofillActualCost(index);
|
||||
if (e.key === "Tab" && !e.shiftKey) autofillActualCost(index);
|
||||
}}
|
||||
/>
|
||||
),
|
||||
@@ -328,8 +334,9 @@ export function BillEnterModalLinesComponent({
|
||||
min={0}
|
||||
disabled={disabled}
|
||||
controls={false}
|
||||
tabIndex={0}
|
||||
style={{ width: "100%", height: CONTROL_HEIGHT }}
|
||||
onFocus={() => autofillActualCost(index)}
|
||||
// NOTE: No auto-fill on focus/blur; only triggered from Retail on Tab
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
@@ -392,7 +399,7 @@ export function BillEnterModalLinesComponent({
|
||||
rules: [{ required: true }]
|
||||
}),
|
||||
formInput: () => (
|
||||
<Select showSearch style={{ minWidth: "3rem" }} disabled={disabled}>
|
||||
<Select showSearch style={{ minWidth: "3rem" }} disabled={disabled} tabIndex={0}>
|
||||
{bodyshopHasDmsKey(bodyshop)
|
||||
? CiecaSelect(true, false)
|
||||
: responsibilityCenters.costs.map((item) => <Select.Option key={item.name}>{item.name}</Select.Option>)}
|
||||
@@ -412,7 +419,7 @@ export function BillEnterModalLinesComponent({
|
||||
name: [field.name, "location"]
|
||||
}),
|
||||
formInput: () => (
|
||||
<Select disabled={disabled}>
|
||||
<Select disabled={disabled} tabIndex={0}>
|
||||
{bodyshop.md_parts_locations.map((loc, idx) => (
|
||||
<Select.Option key={idx} value={loc}>
|
||||
{loc}
|
||||
@@ -432,7 +439,7 @@ export function BillEnterModalLinesComponent({
|
||||
key: `${field.name}deductedfromlbr`,
|
||||
name: [field.name, "deductedfromlbr"]
|
||||
}),
|
||||
formInput: () => <Switch disabled={disabled} />,
|
||||
formInput: () => <Switch disabled={disabled} tabIndex={0} />,
|
||||
additional: (record, index) => (
|
||||
<Form.Item shouldUpdate noStyle style={{ display: "inline-block" }}>
|
||||
{() => {
|
||||
@@ -517,9 +524,13 @@ export function BillEnterModalLinesComponent({
|
||||
formItemProps: (field) => ({
|
||||
key: `${field.name}fedtax`,
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "federal"]
|
||||
name: [field.name, "applicable_taxes", "federal"],
|
||||
initialValue: InstanceRenderManager({
|
||||
imex: true,
|
||||
rome: false
|
||||
})
|
||||
}),
|
||||
formInput: () => <Switch disabled={disabled} />
|
||||
formInput: () => <Switch disabled={disabled} tabIndex={0} />
|
||||
}
|
||||
]
|
||||
}),
|
||||
@@ -534,7 +545,7 @@ export function BillEnterModalLinesComponent({
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "state"]
|
||||
}),
|
||||
formInput: () => <Switch disabled={disabled} />
|
||||
formInput: () => <Switch disabled={disabled} tabIndex={0} />
|
||||
},
|
||||
|
||||
...InstanceRenderManager({
|
||||
@@ -550,7 +561,7 @@ export function BillEnterModalLinesComponent({
|
||||
valuePropName: "checked",
|
||||
name: [field.name, "applicable_taxes", "local"]
|
||||
}),
|
||||
formInput: () => <Switch disabled={disabled} />
|
||||
formInput: () => <Switch disabled={disabled} tabIndex={0} />
|
||||
}
|
||||
]
|
||||
}),
|
||||
@@ -570,6 +581,7 @@ export function BillEnterModalLinesComponent({
|
||||
icon={<DeleteFilled />}
|
||||
disabled={disabled || invLen > 0}
|
||||
onClick={() => remove(record.name)}
|
||||
tabIndex={0}
|
||||
/>
|
||||
|
||||
{Simple_Inventory.treatment === "on" && (
|
||||
@@ -641,12 +653,19 @@ export function BillEnterModalLinesComponent({
|
||||
<Button
|
||||
disabled={disabled}
|
||||
onClick={() => {
|
||||
const newIndex = fields.length;
|
||||
add(
|
||||
InstanceRenderManager({
|
||||
imex: { applicable_taxes: { federal: true } },
|
||||
rome: { applicable_taxes: { federal: false } }
|
||||
})
|
||||
);
|
||||
setTimeout(() => {
|
||||
const firstField = firstFieldRefs.current[newIndex];
|
||||
if (firstField?.focus) {
|
||||
firstField.focus();
|
||||
}
|
||||
}, 100);
|
||||
}}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
|
||||
@@ -36,7 +36,7 @@ export function DashboardTotalProductionHours({ bodyshop, data, ...cardProps })
|
||||
<Statistic
|
||||
title={t("dashboard.labels.prodhrs")}
|
||||
value={hours.total.toFixed(1)}
|
||||
styles={{ value: { color: aboveTargetHours ? "green" : "red" } }}
|
||||
styles={{ content: { color: aboveTargetHours ? "green" : "red" } }}
|
||||
/>
|
||||
</Space>
|
||||
</Card>
|
||||
|
||||
@@ -404,7 +404,7 @@ export default function CdkLikePostForm({ bodyshop, socket, job, logsRef, mode,
|
||||
<Typography.Title>=</Typography.Title>
|
||||
<Statistic
|
||||
title={t("jobs.labels.dms.notallocated")}
|
||||
styles={{ value: { color: discrep.getAmount() === 0 ? "green" : "red" } }}
|
||||
styles={{ content: { color: discrep.getAmount() === 0 ? "green" : "red" } }}
|
||||
value={discrep.toFormat()}
|
||||
/>
|
||||
<Button disabled={disablePost} htmlType="submit">
|
||||
|
||||
@@ -14,8 +14,11 @@ export default function GlobalSearch() {
|
||||
const [callSearch, { loading, error, data }] = useLazyQuery(GLOBAL_SEARCH_QUERY);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const executeSearch = (v) => {
|
||||
if (v && v.variables.search && v.variables.search !== "" && v.variables.search.length >= 3) callSearch(v);
|
||||
const executeSearch = (variables) => {
|
||||
if (variables?.search !== "" && variables?.search?.length >= 3)
|
||||
callSearch({
|
||||
variables
|
||||
});
|
||||
};
|
||||
const debouncedExecuteSearch = _.debounce(executeSearch, 750);
|
||||
|
||||
@@ -157,7 +160,9 @@ export default function GlobalSearch() {
|
||||
return (
|
||||
<AutoComplete
|
||||
options={options}
|
||||
onSearch={handleSearch}
|
||||
showSearch={{
|
||||
onSearch: handleSearch
|
||||
}}
|
||||
defaultActiveFirstOption
|
||||
onKeyDown={(e) => {
|
||||
if (e.key !== "Enter") return;
|
||||
|
||||
@@ -97,7 +97,7 @@ export function Jobd3RdPartyModal({ bodyshop, jobId, job, technician }) {
|
||||
return (
|
||||
<>
|
||||
<Button onClick={showModal}>{t("printcenter.jobs.3rdpartypayer")}</Button>
|
||||
<Modal open={isModalVisible} onOk={handleOk} onCancel={handleCancel}>
|
||||
<Modal open={isModalVisible} onOk={handleOk} onCancel={handleCancel} getContainer={() => document.body}>
|
||||
<Form onFinish={handleFinish} autoComplete={"off"} layout="vertical" form={form}>
|
||||
<Form.Item label={t("bills.fields.vendor")} name="vendorid">
|
||||
<VendorSearchSelect options={VendorAutoCompleteData?.vendors} onSelect={handleVendorSelect} />
|
||||
|
||||
@@ -1,29 +1,65 @@
|
||||
import { useMemo } from "react";
|
||||
import { Tag, Tooltip } from "antd";
|
||||
import { Tooltip } from "antd";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
const mapDispatchToProps = () => ({
|
||||
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||
});
|
||||
const mapDispatchToProps = () => ({});
|
||||
|
||||
const colorMap = {
|
||||
gray: { bg: "#fafafa", border: "#d9d9d9", text: "#000000" },
|
||||
gold: { bg: "#fffbe6", border: "#ffe58f", text: "#d48806" },
|
||||
red: { bg: "#fff1f0", border: "#ffccc7", text: "#cf1322" },
|
||||
blue: { bg: "#e6f7ff", border: "#91d5ff", text: "#0958d9" },
|
||||
green: { bg: "#f6ffed", border: "#b7eb8f", text: "#389e0d" },
|
||||
orange: { bg: "#fff7e6", border: "#ffd591", text: "#d46b08" }
|
||||
};
|
||||
|
||||
function CompactTag({ color = "gray", children, tooltip = "" }) {
|
||||
const colors = colorMap[color] || colorMap.gray;
|
||||
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
padding: "0 2px",
|
||||
fontSize: "12px",
|
||||
lineHeight: "20px",
|
||||
backgroundColor: colors.bg,
|
||||
border: `1px solid ${colors.border}`,
|
||||
borderRadius: "2px",
|
||||
color: colors.text,
|
||||
minWidth: "24px",
|
||||
textAlign: "center"
|
||||
}}
|
||||
>
|
||||
<Tooltip title={tooltip}>{children}</Tooltip>
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(JobPartsQueueCount);
|
||||
|
||||
export function JobPartsQueueCount({ bodyshop, parts }) {
|
||||
const { t } = useTranslation();
|
||||
const partsStatus = useMemo(() => {
|
||||
if (!parts) return null;
|
||||
|
||||
const statusKeys = ["default_bo", "default_ordered", "default_received", "default_returned"];
|
||||
|
||||
return parts.reduce(
|
||||
(acc, val) => {
|
||||
if (val.part_type === "PAS" || val.part_type === "PASL") return acc;
|
||||
acc.total = acc.total + val.count;
|
||||
acc[val.status] = acc[val.status] + val.count;
|
||||
|
||||
acc.total += val.count;
|
||||
|
||||
// NOTE: if val.status is null, object key becomes "null"
|
||||
acc[val.status] = (acc[val.status] ?? 0) + val.count;
|
||||
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
@@ -34,45 +70,38 @@ export function JobPartsQueueCount({ bodyshop, parts }) {
|
||||
);
|
||||
}, [bodyshop, parts]);
|
||||
|
||||
if (!parts) return null;
|
||||
if (!parts || !partsStatus) return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(auto-fit, minmax(40px, 1fr))",
|
||||
gap: "8px",
|
||||
width: "100%",
|
||||
justifyItems: "start"
|
||||
display: "inline-flex", // ✅ shrink-wraps, fixes the “extra box” to the right
|
||||
gap: 2,
|
||||
alignItems: "center",
|
||||
whiteSpace: "nowrap"
|
||||
}}
|
||||
>
|
||||
<Tooltip title="Total">
|
||||
<Tag style={{ minWidth: "40px", textAlign: "center" }}>{partsStatus.total}</Tag>
|
||||
</Tooltip>
|
||||
<Tooltip title={t("dashboard.errors.status_normal")}>
|
||||
<Tag color="gold" style={{ minWidth: "40px", textAlign: "center" }}>
|
||||
{partsStatus["null"]}
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
<Tooltip title={bodyshop.md_order_statuses.default_bo}>
|
||||
<Tag color="red" style={{ minWidth: "40px", textAlign: "center" }}>
|
||||
{partsStatus[bodyshop.md_order_statuses.default_bo]}
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
<Tooltip title={bodyshop.md_order_statuses.default_ordered}>
|
||||
<Tag color="blue" style={{ minWidth: "40px", textAlign: "center" }}>
|
||||
{partsStatus[bodyshop.md_order_statuses.default_ordered]}
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
<Tooltip title={bodyshop.md_order_statuses.default_received}>
|
||||
<Tag color="green" style={{ minWidth: "40px", textAlign: "center" }}>
|
||||
{partsStatus[bodyshop.md_order_statuses.default_received]}
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
<Tooltip title={bodyshop.md_order_statuses.default_returned}>
|
||||
<Tag color="orange" style={{ minWidth: "40px", textAlign: "center" }}>
|
||||
{partsStatus[bodyshop.md_order_statuses.default_returned]}
|
||||
</Tag>
|
||||
</Tooltip>
|
||||
<CompactTag tooltip="Total" color="gray">
|
||||
{partsStatus.total}
|
||||
</CompactTag>
|
||||
|
||||
<CompactTag tooltip="No Status" color="gold">
|
||||
{partsStatus["null"]}
|
||||
</CompactTag>
|
||||
|
||||
<CompactTag tooltip={bodyshop.md_order_statuses.default_bo} color="red">
|
||||
{partsStatus[bodyshop.md_order_statuses.default_bo]}
|
||||
</CompactTag>
|
||||
|
||||
<CompactTag tooltip={bodyshop.md_order_statuses.default_ordered} color="blue">
|
||||
{partsStatus[bodyshop.md_order_statuses.default_ordered]}
|
||||
</CompactTag>
|
||||
<CompactTag tooltip={bodyshop.md_order_statuses.default_received} color="green">
|
||||
{partsStatus[bodyshop.md_order_statuses.default_received]}
|
||||
</CompactTag>
|
||||
<CompactTag tooltip={bodyshop.md_order_statuses.default_returned} color="orange">
|
||||
{partsStatus[bodyshop.md_order_statuses.default_returned]}
|
||||
</CompactTag>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,10 +18,17 @@ const mapStateToProps = createStructuredSelector({
|
||||
* @param parts
|
||||
* @param displayMode
|
||||
* @param popoverPlacement
|
||||
* @param countsOnly
|
||||
* @returns {JSX.Element}
|
||||
* @constructor
|
||||
*/
|
||||
export function JobPartsReceived({ bodyshop, parts, displayMode = "full", popoverPlacement = "top" }) {
|
||||
export function JobPartsReceived({
|
||||
bodyshop,
|
||||
parts,
|
||||
displayMode = "full",
|
||||
popoverPlacement = "top",
|
||||
countsOnly = false
|
||||
}) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -61,6 +68,8 @@ export function JobPartsReceived({ bodyshop, parts, displayMode = "full", popove
|
||||
[canOpen]
|
||||
);
|
||||
|
||||
if (countsOnly) return <JobPartsQueueCount parts={parts} />;
|
||||
|
||||
const displayText =
|
||||
displayMode === "compact" ? summary.percentLabel : `${summary.percentLabel} (${summary.received}/${summary.total})`;
|
||||
|
||||
@@ -74,7 +83,7 @@ export function JobPartsReceived({ bodyshop, parts, displayMode = "full", popove
|
||||
trigger={["click"]}
|
||||
placement={popoverPlacement}
|
||||
content={
|
||||
<div onClick={stop} style={{ minWidth: 260 }}>
|
||||
<div onClick={stop}>
|
||||
<JobPartsQueueCount parts={parts} />
|
||||
</div>
|
||||
}
|
||||
@@ -99,7 +108,8 @@ JobPartsReceived.propTypes = {
|
||||
bodyshop: PropTypes.object,
|
||||
parts: PropTypes.array,
|
||||
displayMode: PropTypes.oneOf(["full", "compact"]),
|
||||
popoverPlacement: PropTypes.string
|
||||
popoverPlacement: PropTypes.string,
|
||||
countsOnly: PropTypes.bool
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(JobPartsReceived);
|
||||
|
||||
@@ -2,6 +2,7 @@ import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { store } from "../../redux/store";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { Tooltip } from "antd";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
@@ -11,15 +12,27 @@ const mapDispatchToProps = () => ({
|
||||
});
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(OwnerNameDisplay);
|
||||
|
||||
export function OwnerNameDisplay({ bodyshop, ownerObject }) {
|
||||
export function OwnerNameDisplay({ bodyshop, ownerObject, withToolTip = false }) {
|
||||
const emptyTest = ownerObject?.ownr_fn + ownerObject?.ownr_ln + ownerObject?.ownr_co_nm;
|
||||
|
||||
if (!emptyTest || emptyTest === "null" || emptyTest.trim() === "") return "N/A";
|
||||
|
||||
if (bodyshop.last_name_first)
|
||||
return `${ownerObject?.ownr_ln || ""}, ${ownerObject?.ownr_fn || ""} ${ownerObject?.ownr_co_nm || ""}`.trim();
|
||||
|
||||
return `${ownerObject?.ownr_fn || ""} ${ownerObject?.ownr_ln || ""} ${ownerObject.ownr_co_nm || ""}`.trim();
|
||||
let returnString;
|
||||
if (bodyshop.last_name_first) {
|
||||
returnString =
|
||||
`${ownerObject?.ownr_ln || ""}, ${ownerObject?.ownr_fn || ""} ${ownerObject?.ownr_co_nm || ""}`.trim();
|
||||
} else {
|
||||
returnString = `${ownerObject?.ownr_fn || ""} ${ownerObject?.ownr_ln || ""} ${ownerObject.ownr_co_nm || ""}`.trim();
|
||||
}
|
||||
if (withToolTip) {
|
||||
return (
|
||||
<Tooltip title={returnString} mouseEnterDelay={0.5}>
|
||||
{returnString}
|
||||
</Tooltip>
|
||||
);
|
||||
} else {
|
||||
return returnString;
|
||||
}
|
||||
}
|
||||
|
||||
export function OwnerNameDisplayFunction(ownerObject, forceFirstLast = false) {
|
||||
|
||||
@@ -16,9 +16,10 @@ const OwnerSearchSelect = ({ value, onChange, onBlur, disabled, ref }) => {
|
||||
SEARCH_OWNERS_BY_ID_FOR_AUTOCOMPLETE
|
||||
);
|
||||
|
||||
const executeSearch = (v) => {
|
||||
if (v && v.variables?.search !== "" && v.variables.search.length >= 2) callSearch({ variables: v.variables });
|
||||
const executeSearch = (variables) => {
|
||||
if (variables?.search !== "" && variables?.search?.length >= 2) callSearch({ variables });
|
||||
};
|
||||
|
||||
const debouncedExecuteSearch = _.debounce(executeSearch, 500);
|
||||
|
||||
const handleSearch = (value) => {
|
||||
|
||||
@@ -1,94 +1,121 @@
|
||||
import { DownOutlined } from "@ant-design/icons";
|
||||
import { Dropdown, InputNumber, Space } from "antd";
|
||||
import { Button, Divider, Dropdown, InputNumber, Space, theme } from "antd";
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { logImEXEvent } from "../../firebase/firebase.utils";
|
||||
|
||||
const DISCOUNT_PRESETS = [5, 10, 15, 20, 25, 40];
|
||||
|
||||
export default function PartsOrderModalPriceChange({ form, field }) {
|
||||
const { t } = useTranslation();
|
||||
const menu = {
|
||||
items: [
|
||||
{
|
||||
key: "5",
|
||||
label: t("parts_orders.labels.discount", { percent: "5%" })
|
||||
},
|
||||
{
|
||||
key: "10",
|
||||
label: t("parts_orders.labels.discount", { percent: "10%" })
|
||||
},
|
||||
{
|
||||
key: "15",
|
||||
label: t("parts_orders.labels.discount", { percent: "15%" })
|
||||
},
|
||||
{
|
||||
key: "20",
|
||||
label: t("parts_orders.labels.discount", { percent: "20%" })
|
||||
},
|
||||
{
|
||||
key: "25",
|
||||
label: t("parts_orders.labels.discount", { percent: "25%" })
|
||||
},
|
||||
{
|
||||
key: "40",
|
||||
label: t("parts_orders.labels.discount", { percent: "40%" })
|
||||
},
|
||||
{
|
||||
key: "custom",
|
||||
label: (
|
||||
<Space.Compact>
|
||||
<InputNumber
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyUp={(e) => {
|
||||
if (e.key === "Enter") {
|
||||
const values = form.getFieldsValue();
|
||||
const { parts_order_lines } = values;
|
||||
const { token } = theme.useToken();
|
||||
|
||||
form.setFieldsValue({
|
||||
parts_order_lines: {
|
||||
data: parts_order_lines.data.map((p, idx) => {
|
||||
if (idx !== field.name) return p;
|
||||
console.log(p, e.target.value, (p.act_price || 0) * ((100 - (e.target.value || 0)) / 100));
|
||||
return {
|
||||
...p,
|
||||
act_price: (p.act_price || 0) * ((100 - (e.target.value || 0)) / 100)
|
||||
};
|
||||
})
|
||||
}
|
||||
});
|
||||
e.target.value = 0;
|
||||
}
|
||||
}}
|
||||
min={0}
|
||||
max={100}
|
||||
/>
|
||||
<span style={{ padding: "0 11px", backgroundColor: "#fafafa", border: "1px solid #d9d9d9", borderLeft: 0 }}>%</span>
|
||||
</Space.Compact>
|
||||
)
|
||||
const [open, setOpen] = useState(false);
|
||||
const [customPercent, setCustomPercent] = useState(0);
|
||||
|
||||
const applyDiscountPercent = (percent) => {
|
||||
const pct = Number(percent) || 0;
|
||||
|
||||
const values = form.getFieldsValue();
|
||||
const parts_order_lines = values?.parts_order_lines;
|
||||
const data = Array.isArray(parts_order_lines?.data) ? parts_order_lines.data : [];
|
||||
if (!data.length) return;
|
||||
|
||||
form.setFieldsValue({
|
||||
parts_order_lines: {
|
||||
data: data.map((p, idx) => {
|
||||
if (idx !== field.name) return p;
|
||||
return {
|
||||
...p,
|
||||
act_price: (p.act_price || 0) * ((100 - pct) / 100)
|
||||
};
|
||||
})
|
||||
}
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const applyCustom = () => {
|
||||
logImEXEvent("parts_order_manual_discount", {});
|
||||
applyDiscountPercent(customPercent);
|
||||
setCustomPercent(0);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const menu = {
|
||||
// Kill the menu “card” styling so our wrapper becomes the single card.
|
||||
style: {
|
||||
background: "transparent",
|
||||
boxShadow: "none"
|
||||
},
|
||||
items: DISCOUNT_PRESETS.map((pct) => ({
|
||||
key: String(pct),
|
||||
label: t("parts_orders.labels.discount", { percent: `${pct}%` })
|
||||
})),
|
||||
onClick: ({ key }) => {
|
||||
logImEXEvent("parts_order_manual_discount", {});
|
||||
if (key === "custom") return;
|
||||
const values = form.getFieldsValue();
|
||||
const { parts_order_lines } = values;
|
||||
form.setFieldsValue({
|
||||
parts_order_lines: {
|
||||
data: parts_order_lines.data.map((p, idx) => {
|
||||
if (idx !== field.name) return p;
|
||||
return {
|
||||
...p,
|
||||
act_price: (p.act_price || 0) * ((100 - key) / 100)
|
||||
};
|
||||
})
|
||||
}
|
||||
});
|
||||
applyDiscountPercent(key);
|
||||
setOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropdown menu={menu} trigger="click">
|
||||
<Dropdown
|
||||
menu={menu}
|
||||
trigger={["click"]}
|
||||
open={open}
|
||||
onOpenChange={(nextOpen) => setOpen(nextOpen)}
|
||||
getPopupContainer={(triggerNode) => triggerNode?.parentElement ?? document.body}
|
||||
popupRender={(menus) => (
|
||||
<div
|
||||
// This makes the whole dropdown (menu + footer) look like one panel in both light/dark.
|
||||
style={{
|
||||
background: token.colorBgElevated,
|
||||
borderRadius: token.borderRadiusLG,
|
||||
boxShadow: token.boxShadowSecondary,
|
||||
overflow: "hidden",
|
||||
minWidth: 180
|
||||
}}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
{menus}
|
||||
|
||||
<Divider style={{ margin: 0 }} />
|
||||
|
||||
<div style={{ padding: token.paddingXS }}>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<InputNumber
|
||||
value={customPercent}
|
||||
min={0}
|
||||
max={100}
|
||||
precision={0}
|
||||
controls={false}
|
||||
style={{ width: "100%" }}
|
||||
formatter={(v) => (v === null || v === undefined ? "" : `${v}%`)}
|
||||
parser={(v) =>
|
||||
String(v ?? "")
|
||||
.replace("%", "")
|
||||
.trim()
|
||||
}
|
||||
onChange={(v) => setCustomPercent(v ?? 0)}
|
||||
onKeyDown={(e) => {
|
||||
e.stopPropagation();
|
||||
if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
applyCustom();
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Button type="primary" onClick={applyCustom}>
|
||||
{t("general.labels.apply")}
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
>
|
||||
<Space>
|
||||
%
|
||||
<DownOutlined />
|
||||
% <DownOutlined />
|
||||
</Space>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
@@ -93,16 +93,6 @@ export function PartsOrderModalContainer({
|
||||
};
|
||||
});
|
||||
|
||||
const missingIdx = forcedLines.findIndex((l) => !l?.job_line_id);
|
||||
if (missingIdx !== -1) {
|
||||
notification.error({
|
||||
title: t("parts_orders.errors.creating"),
|
||||
description: `Missing job_line_id for parts line #${missingIdx + 1}`
|
||||
});
|
||||
setSaving(false);
|
||||
return;
|
||||
}
|
||||
|
||||
let insertResult;
|
||||
try {
|
||||
insertResult = await insertPartOrder({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import { useQuery } from "@apollo/client/react";
|
||||
import { Button, Card, Input, Space, Table } from "antd";
|
||||
import { Button, Card, Checkbox, Input, Space, Table } from "antd";
|
||||
import _ from "lodash";
|
||||
import queryString from "query-string";
|
||||
import { useState } from "react";
|
||||
@@ -31,6 +31,8 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
const { selected, sortcolumn, sortorder, statusFilters } = searchParams;
|
||||
const history = useNavigate();
|
||||
const [filter, setFilter] = useLocalStorage("filter_parts_queue", null);
|
||||
const [viewTimeStamp, setViewTimeStamp] = useLocalStorage("parts_queue_timestamps", false);
|
||||
const [countsOnly, setCountsOnly] = useLocalStorage("parts_queue_counts_only", false);
|
||||
|
||||
const { loading, error, data, refetch } = useQuery(QUERY_PARTS_QUEUE, {
|
||||
fetchPolicy: "network-only",
|
||||
@@ -92,6 +94,7 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
title: t("jobs.fields.ro_number"),
|
||||
dataIndex: "ro_number",
|
||||
key: "ro_number",
|
||||
width: "110px",
|
||||
sorter: (a, b) => alphaSort(a.ro_number, b.ro_number),
|
||||
sortOrder: sortcolumn === "ro_number" && sortorder,
|
||||
|
||||
@@ -103,16 +106,20 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
title: t("jobs.fields.owner"),
|
||||
dataIndex: "ownr_ln",
|
||||
key: "ownr_ln",
|
||||
width: "8%",
|
||||
ellipsis: {
|
||||
showTitle: true
|
||||
},
|
||||
sorter: (a, b) => alphaSort(OwnerNameDisplayFunction(a), OwnerNameDisplayFunction(b)),
|
||||
sortOrder: sortcolumn === "ownr_ln" && sortorder,
|
||||
render: (text, record) => {
|
||||
return record.ownerid ? (
|
||||
<Link to={"/manage/owners/" + record.ownerid}>
|
||||
<OwnerNameDisplay ownerObject={record} />
|
||||
<OwnerNameDisplay ownerObject={record} withToolTip />
|
||||
</Link>
|
||||
) : (
|
||||
<span>
|
||||
<OwnerNameDisplay ownerObject={record} />
|
||||
<OwnerNameDisplay ownerObject={record} withToolTip />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -187,7 +194,7 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => dateSort(a.scheduled_in, b.scheduled_in),
|
||||
sortOrder: sortcolumn === "scheduled_in" && sortorder,
|
||||
render: (text, record) => <DateTimeFormatter>{record.scheduled_in}</DateTimeFormatter>
|
||||
render: (text, record) => <DateTimeFormatter hideTime={!viewTimeStamp}>{record.scheduled_in}</DateTimeFormatter>
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.scheduled_completion"),
|
||||
@@ -196,7 +203,9 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
ellipsis: true,
|
||||
sorter: (a, b) => dateSort(a.scheduled_completion, b.scheduled_completion),
|
||||
sortOrder: sortcolumn === "scheduled_completion" && sortorder,
|
||||
render: (text, record) => <DateTimeFormatter>{record.scheduled_completion}</DateTimeFormatter>
|
||||
render: (text, record) => (
|
||||
<DateTimeFormatter hideTime={!viewTimeStamp}>{record.scheduled_completion}</DateTimeFormatter>
|
||||
)
|
||||
},
|
||||
// {
|
||||
// title: t("vehicles.fields.plate_no"),
|
||||
@@ -227,16 +236,23 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
title: t("jobs.fields.updated_at"),
|
||||
dataIndex: "updated_at",
|
||||
key: "updated_at",
|
||||
width: "110px",
|
||||
sorter: (a, b) => dateSort(a.updated_at, b.updated_at),
|
||||
sortOrder: sortcolumn === "updated_at" && sortorder,
|
||||
render: (text, record) => <TimeAgoFormatter>{record.updated_at}</TimeAgoFormatter>
|
||||
render: (text, record) => <TimeAgoFormatter removeAgoString>{record.updated_at}</TimeAgoFormatter>
|
||||
},
|
||||
{
|
||||
title: t("jobs.fields.partsstatus"),
|
||||
dataIndex: "partsstatus",
|
||||
key: "partsstatus",
|
||||
width: countsOnly ? "180px" : "110px",
|
||||
render: (text, record) => (
|
||||
<JobPartsReceived parts={record.joblines_status} displayMode="full" popoverPlacement="topLeft" />
|
||||
<JobPartsReceived
|
||||
parts={record.joblines_status}
|
||||
displayMode="full"
|
||||
popoverPlacement="middle"
|
||||
countsOnly={countsOnly}
|
||||
/>
|
||||
)
|
||||
},
|
||||
{
|
||||
@@ -249,6 +265,7 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
title: t("jobs.fields.queued_for_parts"),
|
||||
dataIndex: "queued_for_parts",
|
||||
key: "queued_for_parts",
|
||||
width: "120px",
|
||||
sorter: (a, b) => a.queued_for_parts - b.queued_for_parts,
|
||||
sortOrder: sortcolumn === "queued_for_parts" && sortorder,
|
||||
filteredValue: filter?.queued_for_parts || null,
|
||||
@@ -275,6 +292,12 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
<Button onClick={() => refetch()}>
|
||||
<SyncOutlined />
|
||||
</Button>
|
||||
<Checkbox checked={countsOnly} onChange={(e) => setCountsOnly(e.target.checked)}>
|
||||
{t("parts.labels.view_counts_only")}
|
||||
</Checkbox>
|
||||
<Checkbox checked={viewTimeStamp} onChange={(e) => setViewTimeStamp(e.target.checked)}>
|
||||
{t("parts.labels.view_timestamps")}
|
||||
</Checkbox>
|
||||
<Input.Search
|
||||
className="imex-table-header__search"
|
||||
placeholder={t("general.labels.search")}
|
||||
@@ -299,7 +322,7 @@ export function PartsQueueListComponent({ bodyshop }) {
|
||||
rowKey="id"
|
||||
dataSource={jobs}
|
||||
style={{ height: "100%" }}
|
||||
scroll={{ x: true }}
|
||||
//scroll={{ x: true }}
|
||||
onChange={handleTableChange}
|
||||
rowSelection={{
|
||||
onSelect: (record) => {
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function PaymentFormTotalPayments({ jobid }) {
|
||||
{balance && (
|
||||
<Statistic
|
||||
title={t("payments.labels.balance")}
|
||||
styles={{ value: { color: balance.getAmount() !== 0 ? "red" : "green" } }}
|
||||
styles={{ content: { color: balance.getAmount() !== 0 ? "red" : "green" } }}
|
||||
value={(balance && balance.toFormat()) || ""}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -108,7 +108,7 @@ export function PrintCenterJobsLabels({ jobId }) {
|
||||
</Card>
|
||||
);
|
||||
return (
|
||||
<Popover content={content} open={isModalVisible}>
|
||||
<Popover content={content} open={isModalVisible} getPopupContainer={(trigger) => trigger.parentElement}>
|
||||
<Button onClick={() => setIsModalVisible(true)}>{t("printcenter.jobs.labels.labels")}</Button>
|
||||
</Popover>
|
||||
);
|
||||
|
||||
@@ -18,9 +18,10 @@ const VehicleSearchSelect = ({ value, onChange, onBlur, disabled, ref }) => {
|
||||
SEARCH_VEHICLES_BY_ID_FOR_AUTOCOMPLETE
|
||||
);
|
||||
|
||||
const executeSearch = (v) => {
|
||||
if (v && v.variables?.search !== "" && v.variables.search.length >= 2) callSearch({ variables: v.variables });
|
||||
const executeSearch = (variables) => {
|
||||
if (variables?.search !== "" && variables?.search?.length >= 2) callSearch({ variables });
|
||||
};
|
||||
|
||||
const debouncedExecuteSearch = _.debounce(executeSearch, 500);
|
||||
|
||||
const handleSearch = (value) => {
|
||||
|
||||
@@ -510,7 +510,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
|
||||
<Statistic
|
||||
title={t("jobs.labels.pimraryamountpayable")}
|
||||
styles={{
|
||||
value: {
|
||||
content: {
|
||||
color: discrep.getAmount() >= 0 ? "green" : "red"
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -17,7 +17,10 @@ import "./tech.page.styles.scss";
|
||||
import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component.jsx";
|
||||
import { lazyDev } from "../../utils/lazyWithPreload.jsx";
|
||||
|
||||
const TimeTicketModalContainer = lazyDev(() => import("../../components/time-ticket-modal/time-ticket-modal.container"));
|
||||
const NoteUpsertModal = lazyDev(() => import("../../components/note-upsert-modal/note-upsert-modal.container.jsx"));
|
||||
const TimeTicketModalContainer = lazyDev(
|
||||
() => import("../../components/time-ticket-modal/time-ticket-modal.container")
|
||||
);
|
||||
const EmailOverlayContainer = lazyDev(() => import("../../components/email-overlay/email-overlay.container.jsx"));
|
||||
const PrintCenterModalContainer = lazyDev(
|
||||
() => import("../../components/print-center-modal/print-center-modal.container")
|
||||
@@ -34,7 +37,9 @@ const TimeTicketModalTask = lazyDev(
|
||||
const TechAssignedProdJobs = lazyDev(() => import("../tech-assigned-prod-jobs/tech-assigned-prod-jobs.component"));
|
||||
const TechDispatchedParts = lazyDev(() => import("../tech-dispatched-parts/tech-dispatched-parts.page"));
|
||||
|
||||
const TaskUpsertModalContainer = lazyDev(() => import("../../components/task-upsert-modal/task-upsert-modal.container"));
|
||||
const TaskUpsertModalContainer = lazyDev(
|
||||
() => import("../../components/task-upsert-modal/task-upsert-modal.container")
|
||||
);
|
||||
|
||||
const { Content } = Layout;
|
||||
|
||||
@@ -70,6 +75,8 @@ export function TechPage({ technician }) {
|
||||
<TechHeader />
|
||||
|
||||
<TaskUpsertModalContainer />
|
||||
<NoteUpsertModal />
|
||||
|
||||
<Content className="tech-content-container">
|
||||
<ErrorBoundary>
|
||||
<Suspense
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"arrivedon": "Arrived on: ",
|
||||
"arrivingjobs": "Arriving Jobs",
|
||||
"blocked": "Blocked",
|
||||
"bp": "B/P",
|
||||
"cancelledappointment": "Canceled appointment for: ",
|
||||
"completingjobs": "Completing Jobs",
|
||||
"dataconsistency": "<0>{{ro_number}}</0> has a data consistency issue. It may have been excluded for scheduling purposes. CODE: {{code}}.",
|
||||
@@ -59,18 +60,17 @@
|
||||
"noarrivingjobs": "No Jobs are arriving.",
|
||||
"nocompletingjobs": "No Jobs scheduled for completion.",
|
||||
"nodateselected": "No date has been selected.",
|
||||
"owner": "Owner",
|
||||
"priorappointments": "Previous Appointments",
|
||||
"reminder": "This is {{shopname}} reminding you about an appointment on {{date}} at {{time}}. Please let us know if you are not able to make the appointment. We look forward to seeing you soon. ",
|
||||
"ro_number": "RO #",
|
||||
"scheduled_completion": "Scheduled Completion",
|
||||
"scheduledfor": "Scheduled appointment for: ",
|
||||
"severalerrorsfound": "Several Jobs have issues which may prevent accurate smart scheduling. Click to expand.",
|
||||
"smartscheduling": "Smart Scheduling",
|
||||
"smspaymentreminder": "This is {{shopname}} reminding you about your remaining balance of {{amount}}. To pay for the said balance click the link {{payment_link}}.",
|
||||
"suggesteddates": "Suggested Dates",
|
||||
"ro_number": "RO #",
|
||||
"owner": "Owner",
|
||||
"vehicle": "Vehicle",
|
||||
"bp": "B/P",
|
||||
"scheduled_completion": "Scheduled Completion"
|
||||
"vehicle": "Vehicle"
|
||||
},
|
||||
"successes": {
|
||||
"canceled": "Appointment canceled successfully.",
|
||||
@@ -90,6 +90,11 @@
|
||||
"actions": "Actions"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"manager": {
|
||||
"description": "Click anywhere to enable the message ding."
|
||||
}
|
||||
},
|
||||
"audit": {
|
||||
"fields": {
|
||||
"cc": "CC",
|
||||
@@ -149,11 +154,6 @@
|
||||
"tasks_updated": "Task '{{title}}' updated by {{updatedBy}}"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"manager": {
|
||||
"description": "Click anywhere to enable the message ding."
|
||||
}
|
||||
},
|
||||
"billlines": {
|
||||
"actions": {
|
||||
"newline": "New Line"
|
||||
@@ -281,9 +281,9 @@
|
||||
},
|
||||
"errors": {
|
||||
"creatingdefaultview": "Error creating default view.",
|
||||
"duplicate_insurance_company": "Duplicate insurance company name. Each insurance company name must be unique",
|
||||
"loading": "Unable to load shop details. Please call technical support.",
|
||||
"saving": "Error encountered while saving. {{message}}",
|
||||
"duplicate_insurance_company": "Duplicate insurance company name. Each insurance company name must be unique"
|
||||
"saving": "Error encountered while saving. {{message}}"
|
||||
},
|
||||
"fields": {
|
||||
"ReceivableCustomField": "QBO Receivable Custom Field {{number}}",
|
||||
@@ -564,21 +564,18 @@
|
||||
"responsibilitycenter_tax_tier": "Tax {{typeNum}} Tier {{typeNumIterator}}",
|
||||
"responsibilitycenter_tax_type": "Tax {{typeNum}} Type",
|
||||
"responsibilitycenters": {
|
||||
"gogcode": "GOG Code (BreakOut)",
|
||||
"item_type": "Item Type",
|
||||
"item_type_gog": "GOG",
|
||||
"item_type_paint": "Paint Materials",
|
||||
"item_type_freight": "Freight",
|
||||
"taxable_flag": "Taxable?",
|
||||
"taxable": "Taxable",
|
||||
"nontaxable": "Non-taxable",
|
||||
"ap": "Accounts Payable",
|
||||
"ar": "Accounts Receivable",
|
||||
"ats": "ATS",
|
||||
"federal_tax": "Federal Tax",
|
||||
"federal_tax_itc": "Federal Tax Credit",
|
||||
"gogcode": "GOG Code (BreakOut)",
|
||||
"gst_override": "GST Override Account #",
|
||||
"invoiceexemptcode": "QuickBooks US - Invoice Tax Exempt Code",
|
||||
"item_type": "Item Type",
|
||||
"item_type_freight": "Freight",
|
||||
"item_type_gog": "GOG",
|
||||
"item_type_paint": "Paint Materials",
|
||||
"itemexemptcode": "QuickBooks US - Line Item Tax Exempt Code",
|
||||
"la1": "LA1",
|
||||
"la2": "LA2",
|
||||
@@ -597,6 +594,7 @@
|
||||
"local_tax": "Local Tax",
|
||||
"mapa": "Paint Materials",
|
||||
"mash": "Shop Materials",
|
||||
"nontaxable": "Non-taxable",
|
||||
"paa": "Aftermarket",
|
||||
"pac": "Chrome",
|
||||
"pag": "Glass",
|
||||
@@ -617,6 +615,8 @@
|
||||
"state": "State Tax Applies"
|
||||
},
|
||||
"state_tax": "State Tax",
|
||||
"taxable": "Taxable",
|
||||
"taxable_flag": "Taxable?",
|
||||
"tow": "Towing"
|
||||
},
|
||||
"schedule_end_time": "Schedule Ending Time",
|
||||
@@ -678,8 +678,6 @@
|
||||
"zip_post": "Zip/Postal Code"
|
||||
},
|
||||
"labels": {
|
||||
"parts_shop_management": "Shop Management",
|
||||
"parts_vendor_management": "Vendor Management",
|
||||
"2tiername": "Name => RO",
|
||||
"2tiersetup": "2 Tier Setup",
|
||||
"2tiersource": "Source => RO",
|
||||
@@ -702,11 +700,11 @@
|
||||
"payers": "Payers"
|
||||
},
|
||||
"cdk_dealerid": "CDK Dealer ID",
|
||||
"rr_dealerid": "Reynolds Store Number",
|
||||
"costsmapping": "Costs Mapping",
|
||||
"dms_allocations": "DMS Allocations",
|
||||
"pbs_serialnumber": "PBS Serial Number",
|
||||
"profitsmapping": "Profits Mapping",
|
||||
"rr_dealerid": "Reynolds Store Number",
|
||||
"title": "DMS"
|
||||
},
|
||||
"emaillater": "Email Later",
|
||||
@@ -733,6 +731,8 @@
|
||||
"followers": "Notifications"
|
||||
},
|
||||
"orderstatuses": "Order Statuses",
|
||||
"parts_shop_management": "Shop Management",
|
||||
"parts_vendor_management": "Vendor Management",
|
||||
"partslocations": "Parts Locations",
|
||||
"partsscan": "Parts Scanning",
|
||||
"printlater": "Print Later",
|
||||
@@ -1228,8 +1228,6 @@
|
||||
},
|
||||
"general": {
|
||||
"actions": {
|
||||
"select": "Select",
|
||||
"optional": "Optional",
|
||||
"add": "Add",
|
||||
"autoupdate": "{{app}} will automatically update in {{time}} seconds. Please save all changes.",
|
||||
"calculate": "Calculate",
|
||||
@@ -1249,6 +1247,7 @@
|
||||
"login": "Login",
|
||||
"next": "Next",
|
||||
"ok": "Ok",
|
||||
"optional": "Optional",
|
||||
"previous": "Previous",
|
||||
"print": "Print",
|
||||
"refresh": "Refresh",
|
||||
@@ -1259,6 +1258,7 @@
|
||||
"save": "Save",
|
||||
"saveandnew": "Save and New",
|
||||
"saveas": "Save As",
|
||||
"select": "Select",
|
||||
"selectall": "Select All",
|
||||
"send": "Send",
|
||||
"sendbysms": "Send by SMS",
|
||||
@@ -1288,8 +1288,7 @@
|
||||
"vehicle": "Vehicle"
|
||||
},
|
||||
"labels": {
|
||||
"selected": "Selected",
|
||||
"settings": "Settings",
|
||||
"apply": "Apply",
|
||||
"actions": "Actions",
|
||||
"areyousure": "Are you sure?",
|
||||
"barcode": "Barcode",
|
||||
@@ -1343,8 +1342,10 @@
|
||||
"search": "Search...",
|
||||
"searchresults": "Results for {{search}}",
|
||||
"selectdate": "Select date...",
|
||||
"selected": "Selected",
|
||||
"sendagain": "Send Again",
|
||||
"sendby": "Send By",
|
||||
"settings": "Settings",
|
||||
"signin": "Sign In",
|
||||
"sms": "SMS",
|
||||
"status": "Status",
|
||||
@@ -1587,13 +1588,13 @@
|
||||
"labels": {
|
||||
"adjustmenttobeadded": "Adjustment to be added: {{adjustment}}",
|
||||
"billref": "Latest Bill",
|
||||
"bulk_location_help": "This will set the same location on all selected lines.",
|
||||
"convertedtolabor": "This line has been converted to labor. Ensure you adjust the profit center for the amount accordingly.",
|
||||
"edit": "Edit Line",
|
||||
"ioucreated": "IOU",
|
||||
"new": "New Line",
|
||||
"nostatus": "No Status",
|
||||
"presets": "Jobline Presets",
|
||||
"bulk_location_help": "This will set the same location on all selected lines."
|
||||
"presets": "Jobline Presets"
|
||||
},
|
||||
"successes": {
|
||||
"created": "Job line created successfully.",
|
||||
@@ -1701,9 +1702,9 @@
|
||||
"actual_delivery": "Actual Delivery",
|
||||
"actual_in": "Actual In",
|
||||
"acv_amount": "ACV Amount",
|
||||
"admin_clerk": "Admin Clerk",
|
||||
"adjustment_bottom_line": "Adjustments",
|
||||
"adjustmenthours": "Adjustment Hours",
|
||||
"admin_clerk": "Admin Clerk",
|
||||
"alt_transport": "Alt. Trans.",
|
||||
"area_of_damage_impact": {
|
||||
"10": "Left Front Side",
|
||||
@@ -1784,9 +1785,8 @@
|
||||
"ded_status": "Deductible Status",
|
||||
"depreciation_taxes": "Betterment/Depreciation/Taxes",
|
||||
"dms": {
|
||||
"first_name": "First Name",
|
||||
"last_name": "Last Name",
|
||||
"address": "Customer Address",
|
||||
"advisor": "Advisor #",
|
||||
"amount": "Amount",
|
||||
"center": "Center",
|
||||
"control_type": {
|
||||
@@ -1799,12 +1799,13 @@
|
||||
"dms_model_override": "Override DMS Make/Model",
|
||||
"dms_unsold": "New, Unsold Vehicle",
|
||||
"dms_wip_acctnumber": "Cost WIP DMS Acct #",
|
||||
"first_name": "First Name",
|
||||
"id": "DMS ID",
|
||||
"inservicedate": "In Service Date",
|
||||
"journal": "Journal #",
|
||||
"make_override": "Make Override",
|
||||
"advisor": "Advisor #",
|
||||
"last_name": "Last Name",
|
||||
"lines": "Posting Lines",
|
||||
"make_override": "Make Override",
|
||||
"name1": "Customer Name",
|
||||
"payer": {
|
||||
"amount": "Amount",
|
||||
@@ -1945,7 +1946,7 @@
|
||||
"amount": "Amount",
|
||||
"name": "Name"
|
||||
},
|
||||
"queued_for_parts": "Queued for Parts",
|
||||
"queued_for_parts": "Queued",
|
||||
"rate_ats": "ATS Rate",
|
||||
"rate_ats_flat": "ATS Flat Rate",
|
||||
"rate_la1": "LA1",
|
||||
@@ -2447,6 +2448,7 @@
|
||||
"labels": {
|
||||
"addlabel": "Add a label to this conversation.",
|
||||
"archive": "Archive",
|
||||
"mark_unread": "Mark as unread",
|
||||
"maxtenimages": "You can only select up to a maximum of 10 images at a time.",
|
||||
"messaging": "Messaging",
|
||||
"no_consent": "Opted-out",
|
||||
@@ -2459,8 +2461,7 @@
|
||||
"selectmedia": "Select Media",
|
||||
"sentby": "Sent by {{by}} at {{time}}",
|
||||
"typeamessage": "Send a message...",
|
||||
"unarchive": "Unarchive",
|
||||
"mark_unread": "Mark as unread"
|
||||
"unarchive": "Unarchive"
|
||||
},
|
||||
"render": {
|
||||
"conversation_list": "Conversation List"
|
||||
@@ -2614,20 +2615,20 @@
|
||||
"name": "Owner Details"
|
||||
},
|
||||
"labels": {
|
||||
"cell": "Cell",
|
||||
"create_new": "Create a new owner record.",
|
||||
"deleteconfirm": "Are you sure you want to delete this owner? This cannot be undone.",
|
||||
"email": "Email",
|
||||
"existing_owners": "Existing Owners",
|
||||
"fromclaim": "Current Claim",
|
||||
"fromowner": "Historical Owner Record",
|
||||
"relatedjobs": "Related Jobs",
|
||||
"updateowner": "Update Owner",
|
||||
"work": "Work",
|
||||
"home": "Home",
|
||||
"cell": "Cell",
|
||||
"other": "Other",
|
||||
"email": "Email",
|
||||
"phone": "Phone",
|
||||
"sms": "SMS"
|
||||
"relatedjobs": "Related Jobs",
|
||||
"sms": "SMS",
|
||||
"updateowner": "Update Owner",
|
||||
"work": "Work"
|
||||
},
|
||||
"successes": {
|
||||
"delete": "Owner deleted successfully.",
|
||||
@@ -2638,6 +2639,10 @@
|
||||
"actions": {
|
||||
"order": "Order Parts",
|
||||
"orderinhouse": "Order as In House"
|
||||
},
|
||||
"labels": {
|
||||
"view_counts_only": "View Parts Counts Only",
|
||||
"view_timestamps": "Show timestamps"
|
||||
}
|
||||
},
|
||||
"parts_dispatch": {
|
||||
@@ -2987,8 +2992,6 @@
|
||||
"settings": "Error saving board settings: {{error}}"
|
||||
},
|
||||
"labels": {
|
||||
"click_for_statuses": "Click to view parts statuses",
|
||||
"partsreceived": "Parts Received",
|
||||
"actual_in": "Actual In",
|
||||
"addnewprofile": "Add New Profile",
|
||||
"alert": "Alert",
|
||||
@@ -3007,6 +3010,7 @@
|
||||
"card_size": "Card Size",
|
||||
"cardcolor": "Colored Cards",
|
||||
"cardsettings": "Card Settings",
|
||||
"click_for_statuses": "Click to view parts statuses",
|
||||
"clm_no": "Claim Number",
|
||||
"comment": "Comment",
|
||||
"compact": "Compact Cards",
|
||||
@@ -3027,6 +3031,7 @@
|
||||
"orientation": "Board Orientation",
|
||||
"ownr_nm": "Customer Name",
|
||||
"paintpriority": "P/P",
|
||||
"partsreceived": "Parts Received",
|
||||
"partsstatus": "Parts Status",
|
||||
"production_note": "Production Note",
|
||||
"refinishhours": "R",
|
||||
@@ -3573,17 +3578,12 @@
|
||||
}
|
||||
},
|
||||
"titles": {
|
||||
"parts_settings": "Parts Management Settings | {{app}}",
|
||||
"simplified-parts-jobs": "Parts Management | {{app}}",
|
||||
"accounting-payables": "Payables | {{app}}",
|
||||
"accounting-payments": "Payments | {{app}}",
|
||||
"accounting-receivables": "Receivables | {{app}}",
|
||||
"all_tasks": "All Tasks | {{app}}",
|
||||
"app": "",
|
||||
"bc": {
|
||||
"simplified-parts-jobs": "Jobs",
|
||||
"parts": "Parts",
|
||||
"parts_settings": "Settings",
|
||||
"accounting-payables": "Payables",
|
||||
"accounting-payments": "Payments",
|
||||
"accounting-receivables": "Receivables",
|
||||
@@ -3615,7 +3615,9 @@
|
||||
"my_tasks": "My Tasks",
|
||||
"owner-detail": "{{name}}",
|
||||
"owners": "Owners",
|
||||
"parts": "Parts",
|
||||
"parts-queue": "Parts Queue",
|
||||
"parts_settings": "Settings",
|
||||
"payments-all": "All Payments",
|
||||
"phonebook": "Phonebook",
|
||||
"productionboard": "Production Board - Visual",
|
||||
@@ -3627,6 +3629,7 @@
|
||||
"shop-csi": "CSI Responses",
|
||||
"shop-templates": "Shop Templates",
|
||||
"shop-vendors": "Vendors",
|
||||
"simplified-parts-jobs": "Jobs",
|
||||
"tasks": "Tasks",
|
||||
"temporarydocs": "Temporary Documents",
|
||||
"timetickets": "Time Tickets",
|
||||
@@ -3662,7 +3665,9 @@
|
||||
"my_tasks": "My Tasks | {{app}}",
|
||||
"owners": "All Owners | {{app}}",
|
||||
"owners-detail": "{{name}} | {{app}}",
|
||||
"parts": "",
|
||||
"parts-queue": "Parts Queue | {{app}}",
|
||||
"parts_settings": "Parts Management Settings | {{app}}",
|
||||
"payments-all": "Payments | {{app}}",
|
||||
"phonebook": "Phonebook | {{app}}",
|
||||
"productionboard": "Production Board - Visual | {{app}}",
|
||||
@@ -3678,6 +3683,7 @@
|
||||
"shop-csi": "CSI Responses | {{app}}",
|
||||
"shop-templates": "Shop Templates | {{app}}",
|
||||
"shop_vendors": "Vendors | {{app}}",
|
||||
"simplified-parts-jobs": "Parts Management | {{app}}",
|
||||
"tasks": "Tasks",
|
||||
"techconsole": "Technician Console | {{app}}",
|
||||
"techjobclock": "Technician Job Clock | {{app}}",
|
||||
@@ -3838,10 +3844,10 @@
|
||||
"user": {
|
||||
"actions": {
|
||||
"changepassword": "Change Password",
|
||||
"signout": "Sign Out",
|
||||
"updateprofile": "Update Profile",
|
||||
"dark_theme": "Switch to Dark Theme",
|
||||
"light_theme": "Switch to Light Theme",
|
||||
"dark_theme": "Switch to Dark Theme"
|
||||
"signout": "Sign Out",
|
||||
"updateprofile": "Update Profile"
|
||||
},
|
||||
"errors": {
|
||||
"updating": "Error updating user or association {{message}}"
|
||||
@@ -3855,14 +3861,14 @@
|
||||
"labels": {
|
||||
"actions": "Actions",
|
||||
"changepassword": "Change Password",
|
||||
"profileinfo": "Profile Info",
|
||||
"user_settings": "User Settings",
|
||||
"play_sound_for_new_messages": "Play a sound for new messages",
|
||||
"notification_sound_on": "Sound is ON",
|
||||
"notification_sound_off": "Sound is OFF",
|
||||
"notification_sound_enabled": "Notification sound enabled",
|
||||
"notification_sound_disabled": "Notification sound disabled",
|
||||
"notification_sound_help": "Toggle the ding for incoming chat messages."
|
||||
"notification_sound_enabled": "Notification sound enabled",
|
||||
"notification_sound_help": "Toggle the ding for incoming chat messages.",
|
||||
"notification_sound_off": "Sound is OFF",
|
||||
"notification_sound_on": "Sound is ON",
|
||||
"play_sound_for_new_messages": "Play a sound for new messages",
|
||||
"profileinfo": "Profile Info",
|
||||
"user_settings": "User Settings"
|
||||
},
|
||||
"successess": {
|
||||
"passwordchanged": "Password changed successfully. "
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"arrivedon": "Llegado el:",
|
||||
"arrivingjobs": "",
|
||||
"blocked": "",
|
||||
"bp": "",
|
||||
"cancelledappointment": "Cita cancelada para:",
|
||||
"completingjobs": "",
|
||||
"dataconsistency": "",
|
||||
@@ -59,18 +60,17 @@
|
||||
"noarrivingjobs": "",
|
||||
"nocompletingjobs": "",
|
||||
"nodateselected": "No se ha seleccionado ninguna fecha.",
|
||||
"owner": "",
|
||||
"priorappointments": "Nombramientos previos",
|
||||
"reminder": "",
|
||||
"ro_number": "",
|
||||
"scheduled_completion": "",
|
||||
"scheduledfor": "Cita programada para:",
|
||||
"severalerrorsfound": "",
|
||||
"smartscheduling": "",
|
||||
"smspaymentreminder": "",
|
||||
"suggesteddates": "",
|
||||
"ro_number": "",
|
||||
"owner": "",
|
||||
"vehicle": "",
|
||||
"bp": "",
|
||||
"scheduled_completion": ""
|
||||
"vehicle": ""
|
||||
},
|
||||
"successes": {
|
||||
"canceled": "Cita cancelada con éxito.",
|
||||
@@ -90,6 +90,11 @@
|
||||
"actions": "Comportamiento"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"manager": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"audit": {
|
||||
"fields": {
|
||||
"cc": "",
|
||||
@@ -149,11 +154,6 @@
|
||||
"tasks_updated": ""
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"manager": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"billlines": {
|
||||
"actions": {
|
||||
"newline": ""
|
||||
@@ -281,9 +281,9 @@
|
||||
},
|
||||
"errors": {
|
||||
"creatingdefaultview": "",
|
||||
"duplicate_insurance_company": "",
|
||||
"loading": "No se pueden cargar los detalles de la tienda. Por favor llame al soporte técnico.",
|
||||
"saving": "",
|
||||
"duplicate_insurance_company": ""
|
||||
"saving": ""
|
||||
},
|
||||
"fields": {
|
||||
"ReceivableCustomField": "",
|
||||
@@ -564,21 +564,18 @@
|
||||
"responsibilitycenter_tax_tier": "",
|
||||
"responsibilitycenter_tax_type": "",
|
||||
"responsibilitycenters": {
|
||||
"gogcode": "",
|
||||
"item_type": "Item Type",
|
||||
"item_type_gog": "",
|
||||
"item_type_paint": "",
|
||||
"item_type_freight": "",
|
||||
"taxable_flag": "",
|
||||
"taxable": "",
|
||||
"nontaxable": "",
|
||||
"ap": "",
|
||||
"ar": "",
|
||||
"ats": "",
|
||||
"federal_tax": "",
|
||||
"federal_tax_itc": "",
|
||||
"gogcode": "",
|
||||
"gst_override": "",
|
||||
"invoiceexemptcode": "",
|
||||
"item_type": "Item Type",
|
||||
"item_type_freight": "",
|
||||
"item_type_gog": "",
|
||||
"item_type_paint": "",
|
||||
"itemexemptcode": "",
|
||||
"la1": "",
|
||||
"la2": "",
|
||||
@@ -597,6 +594,7 @@
|
||||
"local_tax": "",
|
||||
"mapa": "",
|
||||
"mash": "",
|
||||
"nontaxable": "",
|
||||
"paa": "",
|
||||
"pac": "",
|
||||
"pag": "",
|
||||
@@ -617,6 +615,8 @@
|
||||
"state": ""
|
||||
},
|
||||
"state_tax": "",
|
||||
"taxable": "",
|
||||
"taxable_flag": "",
|
||||
"tow": ""
|
||||
},
|
||||
"schedule_end_time": "",
|
||||
@@ -678,8 +678,6 @@
|
||||
"zip_post": ""
|
||||
},
|
||||
"labels": {
|
||||
"parts_shop_management": "",
|
||||
"parts_vendor_management": "",
|
||||
"2tiername": "",
|
||||
"2tiersetup": "",
|
||||
"2tiersource": "",
|
||||
@@ -702,11 +700,11 @@
|
||||
"payers": ""
|
||||
},
|
||||
"cdk_dealerid": "",
|
||||
"rr_dealerid": "",
|
||||
"costsmapping": "",
|
||||
"dms_allocations": "",
|
||||
"pbs_serialnumber": "",
|
||||
"profitsmapping": "",
|
||||
"rr_dealerid": "",
|
||||
"title": ""
|
||||
},
|
||||
"emaillater": "",
|
||||
@@ -733,6 +731,8 @@
|
||||
"followers": ""
|
||||
},
|
||||
"orderstatuses": "",
|
||||
"parts_shop_management": "",
|
||||
"parts_vendor_management": "",
|
||||
"partslocations": "",
|
||||
"partsscan": "",
|
||||
"printlater": "",
|
||||
@@ -1247,6 +1247,7 @@
|
||||
"login": "",
|
||||
"next": "",
|
||||
"ok": "",
|
||||
"optional": "",
|
||||
"previous": "",
|
||||
"print": "",
|
||||
"refresh": "",
|
||||
@@ -1257,6 +1258,7 @@
|
||||
"save": "Salvar",
|
||||
"saveandnew": "",
|
||||
"saveas": "",
|
||||
"select": "",
|
||||
"selectall": "",
|
||||
"send": "",
|
||||
"sendbysms": "",
|
||||
@@ -1286,9 +1288,8 @@
|
||||
"vehicle": ""
|
||||
},
|
||||
"labels": {
|
||||
"selected": "",
|
||||
"apply": "",
|
||||
"actions": "Comportamiento",
|
||||
"settings": "",
|
||||
"areyousure": "",
|
||||
"barcode": "código de barras",
|
||||
"cancel": "",
|
||||
@@ -1341,8 +1342,10 @@
|
||||
"search": "Buscar...",
|
||||
"searchresults": "",
|
||||
"selectdate": "",
|
||||
"selected": "",
|
||||
"sendagain": "",
|
||||
"sendby": "",
|
||||
"settings": "",
|
||||
"signin": "",
|
||||
"sms": "",
|
||||
"status": "",
|
||||
@@ -1585,13 +1588,13 @@
|
||||
"labels": {
|
||||
"adjustmenttobeadded": "",
|
||||
"billref": "",
|
||||
"bulk_location_help": "",
|
||||
"convertedtolabor": "",
|
||||
"edit": "Línea de edición",
|
||||
"ioucreated": "",
|
||||
"new": "Nueva línea",
|
||||
"nostatus": "",
|
||||
"presets": "",
|
||||
"bulk_location_help": ""
|
||||
"presets": ""
|
||||
},
|
||||
"successes": {
|
||||
"created": "",
|
||||
@@ -1700,8 +1703,8 @@
|
||||
"actual_in": "Real en",
|
||||
"acv_amount": "",
|
||||
"adjustment_bottom_line": "Ajustes",
|
||||
"admin_clerk": "",
|
||||
"adjustmenthours": "",
|
||||
"admin_clerk": "",
|
||||
"alt_transport": "",
|
||||
"area_of_damage_impact": {
|
||||
"10": "",
|
||||
@@ -1782,9 +1785,8 @@
|
||||
"ded_status": "Estado deducible",
|
||||
"depreciation_taxes": "Depreciación / Impuestos",
|
||||
"dms": {
|
||||
"first_name": "",
|
||||
"last_name": "",
|
||||
"address": "",
|
||||
"advisor": "",
|
||||
"amount": "",
|
||||
"center": "",
|
||||
"control_type": {
|
||||
@@ -1795,21 +1797,23 @@
|
||||
"dms_make": "",
|
||||
"dms_model": "",
|
||||
"dms_model_override": "",
|
||||
"make_override": "",
|
||||
"advisor": "",
|
||||
"dms_unsold": "",
|
||||
"dms_wip_acctnumber": "",
|
||||
"first_name": "",
|
||||
"id": "",
|
||||
"inservicedate": "",
|
||||
"journal": "",
|
||||
"last_name": "",
|
||||
"lines": "",
|
||||
"make_override": "",
|
||||
"name1": "",
|
||||
"payer": {
|
||||
"amount": "",
|
||||
"control_type": "",
|
||||
"controlnumber": "",
|
||||
"dms_acctnumber": "",
|
||||
"name": ""
|
||||
"name": "",
|
||||
"payer_type": ""
|
||||
},
|
||||
"sale": "",
|
||||
"sale_dms_acctnumber": "",
|
||||
@@ -2444,6 +2448,7 @@
|
||||
"labels": {
|
||||
"addlabel": "",
|
||||
"archive": "",
|
||||
"mark_unread": "",
|
||||
"maxtenimages": "",
|
||||
"messaging": "Mensajería",
|
||||
"no_consent": "",
|
||||
@@ -2456,8 +2461,7 @@
|
||||
"selectmedia": "",
|
||||
"sentby": "",
|
||||
"typeamessage": "Enviar un mensaje...",
|
||||
"unarchive": "",
|
||||
"mark_unread": ""
|
||||
"unarchive": ""
|
||||
},
|
||||
"render": {
|
||||
"conversation_list": ""
|
||||
@@ -2611,20 +2615,20 @@
|
||||
"name": ""
|
||||
},
|
||||
"labels": {
|
||||
"cell": "",
|
||||
"create_new": "Crea un nuevo registro de propietario.",
|
||||
"deleteconfirm": "",
|
||||
"email": "",
|
||||
"existing_owners": "Propietarios existentes",
|
||||
"fromclaim": "",
|
||||
"fromowner": "",
|
||||
"relatedjobs": "",
|
||||
"updateowner": "",
|
||||
"work": "",
|
||||
"home": "",
|
||||
"cell": "",
|
||||
"other": "",
|
||||
"email": "",
|
||||
"phone": "",
|
||||
"sms": ""
|
||||
"relatedjobs": "",
|
||||
"sms": "",
|
||||
"updateowner": "",
|
||||
"work": ""
|
||||
},
|
||||
"successes": {
|
||||
"delete": "",
|
||||
@@ -2635,6 +2639,10 @@
|
||||
"actions": {
|
||||
"order": "Pedido de piezas",
|
||||
"orderinhouse": ""
|
||||
},
|
||||
"labels": {
|
||||
"view_counts_only": "",
|
||||
"view_timestamps": ""
|
||||
}
|
||||
},
|
||||
"parts_dispatch": {
|
||||
@@ -2984,8 +2992,6 @@
|
||||
"settings": ""
|
||||
},
|
||||
"labels": {
|
||||
"click_for_statuses": "",
|
||||
"partsreceived": "",
|
||||
"actual_in": "",
|
||||
"addnewprofile": "",
|
||||
"alert": "",
|
||||
@@ -3004,6 +3010,7 @@
|
||||
"card_size": "",
|
||||
"cardcolor": "",
|
||||
"cardsettings": "",
|
||||
"click_for_statuses": "",
|
||||
"clm_no": "",
|
||||
"comment": "",
|
||||
"compact": "",
|
||||
@@ -3024,6 +3031,7 @@
|
||||
"orientation": "",
|
||||
"ownr_nm": "",
|
||||
"paintpriority": "",
|
||||
"partsreceived": "",
|
||||
"partsstatus": "",
|
||||
"production_note": "",
|
||||
"refinishhours": "",
|
||||
@@ -3570,18 +3578,12 @@
|
||||
}
|
||||
},
|
||||
"titles": {
|
||||
"simplified-parts-jobs": "",
|
||||
"parts": "",
|
||||
"parts_settings": "",
|
||||
"accounting-payables": "",
|
||||
"accounting-payments": "",
|
||||
"accounting-receivables": "",
|
||||
"all_tasks": "",
|
||||
"app": "",
|
||||
"bc": {
|
||||
"simplified-parts-jobs": "",
|
||||
"parts": "",
|
||||
"parts_settings": "",
|
||||
"accounting-payables": "",
|
||||
"accounting-payments": "",
|
||||
"accounting-receivables": "",
|
||||
@@ -3613,7 +3615,9 @@
|
||||
"my_tasks": "",
|
||||
"owner-detail": "",
|
||||
"owners": "",
|
||||
"parts": "",
|
||||
"parts-queue": "",
|
||||
"parts_settings": "",
|
||||
"payments-all": "",
|
||||
"phonebook": "",
|
||||
"productionboard": "",
|
||||
@@ -3625,6 +3629,7 @@
|
||||
"shop-csi": "",
|
||||
"shop-templates": "",
|
||||
"shop-vendors": "",
|
||||
"simplified-parts-jobs": "",
|
||||
"tasks": "",
|
||||
"temporarydocs": "",
|
||||
"timetickets": "",
|
||||
@@ -3660,7 +3665,9 @@
|
||||
"my_tasks": "",
|
||||
"owners": "Todos los propietarios | {{app}}",
|
||||
"owners-detail": "",
|
||||
"parts": "",
|
||||
"parts-queue": "",
|
||||
"parts_settings": "",
|
||||
"payments-all": "",
|
||||
"phonebook": "",
|
||||
"productionboard": "",
|
||||
@@ -3676,6 +3683,7 @@
|
||||
"shop-csi": "",
|
||||
"shop-templates": "",
|
||||
"shop_vendors": "Vendedores | {{app}}",
|
||||
"simplified-parts-jobs": "",
|
||||
"tasks": "",
|
||||
"techconsole": "{{app}}",
|
||||
"techjobclock": "{{app}}",
|
||||
@@ -3836,10 +3844,10 @@
|
||||
"user": {
|
||||
"actions": {
|
||||
"changepassword": "",
|
||||
"signout": "desconectar",
|
||||
"updateprofile": "Actualización del perfil",
|
||||
"dark_theme": "",
|
||||
"light_theme": "",
|
||||
"dark_theme": ""
|
||||
"signout": "desconectar",
|
||||
"updateprofile": "Actualización del perfil"
|
||||
},
|
||||
"errors": {
|
||||
"updating": ""
|
||||
@@ -3853,14 +3861,14 @@
|
||||
"labels": {
|
||||
"actions": "",
|
||||
"changepassword": "",
|
||||
"profileinfo": "",
|
||||
"user_settings": "",
|
||||
"play_sound_for_new_messages": "",
|
||||
"notification_sound_on": "",
|
||||
"notification_sound_off": "",
|
||||
"notification_sound_enabled": "",
|
||||
"notification_sound_disabled": "",
|
||||
"notification_sound_help": ""
|
||||
"notification_sound_enabled": "",
|
||||
"notification_sound_help": "",
|
||||
"notification_sound_off": "",
|
||||
"notification_sound_on": "",
|
||||
"play_sound_for_new_messages": "",
|
||||
"profileinfo": "",
|
||||
"user_settings": ""
|
||||
},
|
||||
"successess": {
|
||||
"passwordchanged": ""
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"arrivedon": "Arrivé le:",
|
||||
"arrivingjobs": "",
|
||||
"blocked": "",
|
||||
"bp": "",
|
||||
"cancelledappointment": "Rendez-vous annulé pour:",
|
||||
"completingjobs": "",
|
||||
"dataconsistency": "",
|
||||
@@ -59,18 +60,17 @@
|
||||
"noarrivingjobs": "",
|
||||
"nocompletingjobs": "",
|
||||
"nodateselected": "Aucune date n'a été sélectionnée.",
|
||||
"owner": "",
|
||||
"priorappointments": "Rendez-vous précédents",
|
||||
"reminder": "",
|
||||
"ro_number": "",
|
||||
"scheduled_completion": "",
|
||||
"scheduledfor": "Rendez-vous prévu pour:",
|
||||
"severalerrorsfound": "",
|
||||
"smartscheduling": "",
|
||||
"smspaymentreminder": "",
|
||||
"suggesteddates": "",
|
||||
"ro_number": "",
|
||||
"owner": "",
|
||||
"vehicle": "",
|
||||
"bp": "",
|
||||
"scheduled_completion": ""
|
||||
"vehicle": ""
|
||||
},
|
||||
"successes": {
|
||||
"canceled": "Rendez-vous annulé avec succès.",
|
||||
@@ -90,6 +90,11 @@
|
||||
"actions": "actes"
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"manager": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"audit": {
|
||||
"fields": {
|
||||
"cc": "",
|
||||
@@ -149,11 +154,6 @@
|
||||
"tasks_updated": ""
|
||||
}
|
||||
},
|
||||
"audio": {
|
||||
"manager": {
|
||||
"description": ""
|
||||
}
|
||||
},
|
||||
"billlines": {
|
||||
"actions": {
|
||||
"newline": ""
|
||||
@@ -281,9 +281,9 @@
|
||||
},
|
||||
"errors": {
|
||||
"creatingdefaultview": "",
|
||||
"duplicate_insurance_company": "",
|
||||
"loading": "Impossible de charger les détails de la boutique. Veuillez appeler le support technique.",
|
||||
"saving": "",
|
||||
"duplicate_insurance_company": ""
|
||||
"saving": ""
|
||||
},
|
||||
"fields": {
|
||||
"ReceivableCustomField": "",
|
||||
@@ -564,21 +564,18 @@
|
||||
"responsibilitycenter_tax_tier": "",
|
||||
"responsibilitycenter_tax_type": "",
|
||||
"responsibilitycenters": {
|
||||
"gogcode": "",
|
||||
"item_type": "Item Type",
|
||||
"item_type_gog": "",
|
||||
"item_type_paint": "",
|
||||
"item_type_freight": "",
|
||||
"taxable_flag": "",
|
||||
"taxable": "",
|
||||
"nontaxable": "",
|
||||
"ap": "",
|
||||
"ar": "",
|
||||
"ats": "",
|
||||
"federal_tax": "",
|
||||
"federal_tax_itc": "",
|
||||
"gogcode": "",
|
||||
"gst_override": "",
|
||||
"invoiceexemptcode": "",
|
||||
"item_type": "Item Type",
|
||||
"item_type_freight": "",
|
||||
"item_type_gog": "",
|
||||
"item_type_paint": "",
|
||||
"itemexemptcode": "",
|
||||
"la1": "",
|
||||
"la2": "",
|
||||
@@ -597,6 +594,7 @@
|
||||
"local_tax": "",
|
||||
"mapa": "",
|
||||
"mash": "",
|
||||
"nontaxable": "",
|
||||
"paa": "",
|
||||
"pac": "",
|
||||
"pag": "",
|
||||
@@ -617,6 +615,8 @@
|
||||
"state": ""
|
||||
},
|
||||
"state_tax": "",
|
||||
"taxable": "",
|
||||
"taxable_flag": "",
|
||||
"tow": ""
|
||||
},
|
||||
"schedule_end_time": "",
|
||||
@@ -678,8 +678,6 @@
|
||||
"zip_post": ""
|
||||
},
|
||||
"labels": {
|
||||
"parts_shop_management": "",
|
||||
"parts_vendor_management": "",
|
||||
"2tiername": "",
|
||||
"2tiersetup": "",
|
||||
"2tiersource": "",
|
||||
@@ -702,11 +700,11 @@
|
||||
"payers": ""
|
||||
},
|
||||
"cdk_dealerid": "",
|
||||
"rr_dealerid": "",
|
||||
"costsmapping": "",
|
||||
"dms_allocations": "",
|
||||
"pbs_serialnumber": "",
|
||||
"profitsmapping": "",
|
||||
"rr_dealerid": "",
|
||||
"title": ""
|
||||
},
|
||||
"emaillater": "",
|
||||
@@ -733,6 +731,8 @@
|
||||
"followers": ""
|
||||
},
|
||||
"orderstatuses": "",
|
||||
"parts_shop_management": "",
|
||||
"parts_vendor_management": "",
|
||||
"partslocations": "",
|
||||
"partsscan": "",
|
||||
"printlater": "",
|
||||
@@ -1247,6 +1247,7 @@
|
||||
"login": "",
|
||||
"next": "",
|
||||
"ok": "",
|
||||
"optional": "",
|
||||
"previous": "",
|
||||
"print": "",
|
||||
"refresh": "",
|
||||
@@ -1257,6 +1258,7 @@
|
||||
"save": "sauvegarder",
|
||||
"saveandnew": "",
|
||||
"saveas": "",
|
||||
"select": "",
|
||||
"selectall": "",
|
||||
"send": "",
|
||||
"sendbysms": "",
|
||||
@@ -1286,8 +1288,7 @@
|
||||
"vehicle": ""
|
||||
},
|
||||
"labels": {
|
||||
"selected": "",
|
||||
"settings": "",
|
||||
"apply": "",
|
||||
"actions": "actes",
|
||||
"areyousure": "",
|
||||
"barcode": "code à barre",
|
||||
@@ -1341,8 +1342,10 @@
|
||||
"search": "Chercher...",
|
||||
"searchresults": "",
|
||||
"selectdate": "",
|
||||
"selected": "",
|
||||
"sendagain": "",
|
||||
"sendby": "",
|
||||
"settings": "",
|
||||
"signin": "",
|
||||
"sms": "",
|
||||
"status": "",
|
||||
@@ -1585,13 +1588,13 @@
|
||||
"labels": {
|
||||
"adjustmenttobeadded": "",
|
||||
"billref": "",
|
||||
"bulk_location_help": "",
|
||||
"convertedtolabor": "",
|
||||
"edit": "Ligne d'édition",
|
||||
"ioucreated": "",
|
||||
"new": "Nouvelle ligne",
|
||||
"nostatus": "",
|
||||
"presets": "",
|
||||
"bulk_location_help": ""
|
||||
"presets": ""
|
||||
},
|
||||
"successes": {
|
||||
"created": "",
|
||||
@@ -1699,9 +1702,9 @@
|
||||
"actual_delivery": "Livraison réelle",
|
||||
"actual_in": "En réel",
|
||||
"acv_amount": "",
|
||||
"admin_clerk": "",
|
||||
"adjustment_bottom_line": "Ajustements",
|
||||
"adjustmenthours": "",
|
||||
"admin_clerk": "",
|
||||
"alt_transport": "",
|
||||
"area_of_damage_impact": {
|
||||
"10": "",
|
||||
@@ -1782,9 +1785,8 @@
|
||||
"ded_status": "Statut de franchise",
|
||||
"depreciation_taxes": "Amortissement / taxes",
|
||||
"dms": {
|
||||
"first_name": "",
|
||||
"last_name": "",
|
||||
"address": "",
|
||||
"advisor": "",
|
||||
"amount": "",
|
||||
"center": "",
|
||||
"control_type": {
|
||||
@@ -1795,21 +1797,23 @@
|
||||
"dms_make": "",
|
||||
"dms_model": "",
|
||||
"dms_model_override": "",
|
||||
"make_override": "",
|
||||
"advisor": "",
|
||||
"dms_unsold": "",
|
||||
"dms_wip_acctnumber": "",
|
||||
"first_name": "",
|
||||
"id": "",
|
||||
"inservicedate": "",
|
||||
"journal": "",
|
||||
"last_name": "",
|
||||
"lines": "",
|
||||
"make_override": "",
|
||||
"name1": "",
|
||||
"payer": {
|
||||
"amount": "",
|
||||
"control_type": "",
|
||||
"controlnumber": "",
|
||||
"dms_acctnumber": "",
|
||||
"name": ""
|
||||
"name": "",
|
||||
"payer_type": ""
|
||||
},
|
||||
"sale": "",
|
||||
"sale_dms_acctnumber": "",
|
||||
@@ -2433,7 +2437,6 @@
|
||||
"actions": {
|
||||
"link": "",
|
||||
"new": "",
|
||||
|
||||
"openchat": ""
|
||||
},
|
||||
"errors": {
|
||||
@@ -2445,6 +2448,7 @@
|
||||
"labels": {
|
||||
"addlabel": "",
|
||||
"archive": "",
|
||||
"mark_unread": "",
|
||||
"maxtenimages": "",
|
||||
"messaging": "Messagerie",
|
||||
"no_consent": "",
|
||||
@@ -2457,8 +2461,7 @@
|
||||
"selectmedia": "",
|
||||
"sentby": "",
|
||||
"typeamessage": "Envoyer un message...",
|
||||
"unarchive": "",
|
||||
"mark_unread": ""
|
||||
"unarchive": ""
|
||||
},
|
||||
"render": {
|
||||
"conversation_list": ""
|
||||
@@ -2612,20 +2615,20 @@
|
||||
"name": ""
|
||||
},
|
||||
"labels": {
|
||||
"cell": "",
|
||||
"create_new": "Créez un nouvel enregistrement de propriétaire.",
|
||||
"deleteconfirm": "",
|
||||
"email": "",
|
||||
"existing_owners": "Propriétaires existants",
|
||||
"fromclaim": "",
|
||||
"fromowner": "",
|
||||
"relatedjobs": "",
|
||||
"updateowner": "",
|
||||
"work": "",
|
||||
"home": "",
|
||||
"cell": "",
|
||||
"other": "",
|
||||
"email": "",
|
||||
"phone": "",
|
||||
"sms": ""
|
||||
"relatedjobs": "",
|
||||
"sms": "",
|
||||
"updateowner": "",
|
||||
"work": ""
|
||||
},
|
||||
"successes": {
|
||||
"delete": "",
|
||||
@@ -2636,6 +2639,10 @@
|
||||
"actions": {
|
||||
"order": "Commander des pièces",
|
||||
"orderinhouse": ""
|
||||
},
|
||||
"labels": {
|
||||
"view_counts_only": "",
|
||||
"view_timestamps": ""
|
||||
}
|
||||
},
|
||||
"parts_dispatch": {
|
||||
@@ -2985,8 +2992,6 @@
|
||||
"settings": ""
|
||||
},
|
||||
"labels": {
|
||||
"click_for_statuses": "",
|
||||
"partsreceived": "",
|
||||
"actual_in": "",
|
||||
"addnewprofile": "",
|
||||
"alert": "",
|
||||
@@ -3005,6 +3010,7 @@
|
||||
"card_size": "",
|
||||
"cardcolor": "",
|
||||
"cardsettings": "",
|
||||
"click_for_statuses": "",
|
||||
"clm_no": "",
|
||||
"comment": "",
|
||||
"compact": "",
|
||||
@@ -3025,6 +3031,7 @@
|
||||
"orientation": "",
|
||||
"ownr_nm": "",
|
||||
"paintpriority": "",
|
||||
"partsreceived": "",
|
||||
"partsstatus": "",
|
||||
"production_note": "",
|
||||
"refinishhours": "",
|
||||
@@ -3571,18 +3578,12 @@
|
||||
}
|
||||
},
|
||||
"titles": {
|
||||
"simplified-parts-jobs": "",
|
||||
"parts": "",
|
||||
"parts_settings": "",
|
||||
"accounting-payables": "",
|
||||
"accounting-payments": "",
|
||||
"accounting-receivables": "",
|
||||
"all_tasks": "",
|
||||
"app": "",
|
||||
"bc": {
|
||||
"simplified-parts-jobs": "",
|
||||
"parts": "",
|
||||
"parts_settings": "",
|
||||
"accounting-payables": "",
|
||||
"accounting-payments": "",
|
||||
"accounting-receivables": "",
|
||||
@@ -3614,7 +3615,9 @@
|
||||
"my_tasks": "",
|
||||
"owner-detail": "",
|
||||
"owners": "",
|
||||
"parts": "",
|
||||
"parts-queue": "",
|
||||
"parts_settings": "",
|
||||
"payments-all": "",
|
||||
"phonebook": "",
|
||||
"productionboard": "",
|
||||
@@ -3626,6 +3629,7 @@
|
||||
"shop-csi": "",
|
||||
"shop-templates": "",
|
||||
"shop-vendors": "",
|
||||
"simplified-parts-jobs": "",
|
||||
"tasks": "",
|
||||
"temporarydocs": "",
|
||||
"timetickets": "",
|
||||
@@ -3661,7 +3665,9 @@
|
||||
"my_tasks": "",
|
||||
"owners": "Tous les propriétaires | {{app}}",
|
||||
"owners-detail": "",
|
||||
"parts": "",
|
||||
"parts-queue": "",
|
||||
"parts_settings": "",
|
||||
"payments-all": "",
|
||||
"phonebook": "",
|
||||
"productionboard": "",
|
||||
@@ -3677,6 +3683,7 @@
|
||||
"shop-csi": "",
|
||||
"shop-templates": "",
|
||||
"shop_vendors": "Vendeurs | {{app}}",
|
||||
"simplified-parts-jobs": "",
|
||||
"tasks": "",
|
||||
"techconsole": "{{app}}",
|
||||
"techjobclock": "{{app}}",
|
||||
@@ -3837,10 +3844,10 @@
|
||||
"user": {
|
||||
"actions": {
|
||||
"changepassword": "",
|
||||
"signout": "Déconnexion",
|
||||
"updateprofile": "Mettre à jour le profil",
|
||||
"dark_theme": "",
|
||||
"light_theme": "",
|
||||
"dark_theme": ""
|
||||
"signout": "Déconnexion",
|
||||
"updateprofile": "Mettre à jour le profil"
|
||||
},
|
||||
"errors": {
|
||||
"updating": ""
|
||||
@@ -3854,14 +3861,14 @@
|
||||
"labels": {
|
||||
"actions": "",
|
||||
"changepassword": "",
|
||||
"profileinfo": "",
|
||||
"user_settings": "",
|
||||
"play_sound_for_new_messages": "",
|
||||
"notification_sound_on": "",
|
||||
"notification_sound_off": "",
|
||||
"notification_sound_enabled": "",
|
||||
"notification_sound_disabled": "",
|
||||
"notification_sound_help": ""
|
||||
"notification_sound_enabled": "",
|
||||
"notification_sound_help": "",
|
||||
"notification_sound_off": "",
|
||||
"notification_sound_on": "",
|
||||
"play_sound_for_new_messages": "",
|
||||
"profileinfo": "",
|
||||
"user_settings": ""
|
||||
},
|
||||
"successess": {
|
||||
"passwordchanged": ""
|
||||
|
||||
@@ -5,8 +5,10 @@ export function DateFormatter(props) {
|
||||
return props.children ? dayjs(props.children).format(props.includeDay ? "ddd MM/DD/YYYY" : "MM/DD/YYYY") : null;
|
||||
}
|
||||
|
||||
export function DateTimeFormatter(props) {
|
||||
return props.children ? dayjs(props.children).format(props.format ? props.format : "MM/DD/YYYY hh:mm a") : null;
|
||||
export function DateTimeFormatter({ hideTime, ...props }) {
|
||||
return props.children
|
||||
? dayjs(props.children).format(props.format ? props.format : `MM/DD/YYYY${hideTime ? "" : " hh:mm a"}`)
|
||||
: null;
|
||||
}
|
||||
|
||||
export function DateTimeFormatterFunction(date) {
|
||||
@@ -17,11 +19,11 @@ export function TimeFormatter(props) {
|
||||
return props.children ? dayjs(props.children).format(props.format ? props.format : "hh:mm a") : null;
|
||||
}
|
||||
|
||||
export function TimeAgoFormatter(props) {
|
||||
export function TimeAgoFormatter({ removeAgoString = false, ...props }) {
|
||||
const m = dayjs(props.children);
|
||||
return props.children ? (
|
||||
<Tooltip placement="top" title={m.format("MM/DD/YYY hh:mm A")}>
|
||||
{m.fromNow()}
|
||||
<Tooltip placement="top" title={m.format("MM/DD/YYYY hh:mm A")}>
|
||||
{m.fromNow(removeAgoString)}
|
||||
</Tooltip>
|
||||
) : null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user