Compare commits

...

18 Commits

Author SHA1 Message Date
Patrick Fic
bee078fe18 Add user definted rates to labor misc for autohouse. 2022-12-20 12:38:41 -08:00
Patrick Fic
8a0281fb43 Merged in release/2022-12-16 (pull request #643)
Release/2022 12 16
2022-12-16 18:59:41 +00:00
Patrick Fic
1df023fd15 Remove unneeded import to fix CI. 2022-12-15 17:09:05 -08:00
Patrick Fic
54277e4548 IO-2131 Resolve job search select filtering issue. 2022-12-15 16:39:47 -08:00
Patrick Fic
cffa1e2172 IO-2121 Add custom label to conversation. 2022-12-15 10:13:30 -08:00
Patrick Fic
6a25dff32d Merged in release/2022-12-16 (pull request #639)
Resolve scheduling loading issue.
2022-12-14 16:59:04 +00:00
Patrick Fic
ecfc365926 Resolve scheduling loading issue. 2022-12-14 08:30:16 -08:00
Patrick Fic
2f0bb4539e Merged in release/2022-12-09 (pull request #638)
Release/2022 12 09
2022-12-10 01:32:06 +00:00
Patrick Fic
2ac7f9b678 Add ownr_co_nm to search own query. 2022-12-09 14:07:27 -08:00
Patrick Fic
e192a63575 IO-2123 Add cc inventory print. 2022-12-09 11:35:13 -08:00
Patrick Fic
4c42522f3a IO-2122 Add time ticket report. 2022-12-09 08:09:53 -08:00
Patrick Fic
dad3dc9e42 Autohouse based updates. 2022-12-08 14:47:51 -08:00
Patrick Fic
b2b754bee0 IO-2118 Add expected production hours to scheduling. 2022-12-05 15:20:37 -08:00
Patrick Fic
8f9f80e8ee IO-2084 Add actualr epair start date. 2022-12-05 14:38:36 -08:00
Patrick Fic
0cf677abbf Merged in release/2022-12-02 (pull request #635)
IO-2116 Add account number to control types for DMS.
2022-12-03 03:16:53 +00:00
Patrick Fic
bc3238aba2 IO-2116 Add account number to control types for DMS. 2022-11-30 08:47:20 -08:00
Patrick Fic
df8c94cda2 Merged in release/2022-11-25 (pull request #632)
IO-2114 Resolve issue with unfound payer.
2022-11-26 00:01:25 +00:00
Patrick Fic
e1dc257279 Merged in release/2022-11-25 (pull request #631)
Release/2022 11 25
2022-11-25 20:57:01 +00:00
31 changed files with 565 additions and 47 deletions

View File

@@ -17,5 +17,4 @@
"no-console": "off"
},
"settings": {}
//"plugins": ["cypress"]
}

View File

@@ -736,6 +736,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>expectedprodhrs</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>history</name>
<definition_loaded>false</definition_loaded>
@@ -4402,6 +4423,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>sendmaterialscosting</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>srcco</name>
<definition_loaded>false</definition_loaded>
@@ -22264,6 +22306,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>date_repairstarted</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>date_scheduled</name>
<definition_loaded>false</definition_loaded>
@@ -22456,6 +22519,32 @@
</translation>
</translations>
</concept_node>
<folder_node>
<name>control_type</name>
<children>
<concept_node>
<name>account_number</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<concept_node>
<name>cost</name>
<definition_loaded>false</definition_loaded>
@@ -32581,11 +32670,53 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>updatinglabel</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
</children>
</folder_node>
<folder_node>
<name>labels</name>
<children>
<concept_node>
<name>addlabel</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>archive</name>
<definition_loaded>false</definition_loaded>
@@ -36430,6 +36561,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>courtesy_car_inventory</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>courtesy_car_terms</name>
<definition_loaded>false</definition_loaded>
@@ -38088,6 +38240,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>timetickets_ro</name>
<definition_loaded>false</definition_loaded>
<description></description>
<comment></comment>
<default_text></default_text>
<translations>
<translation>
<language>en-US</language>
<approved>false</approved>
</translation>
<translation>
<language>es-MX</language>
<approved>false</approved>
</translation>
<translation>
<language>fr-CA</language>
<approved>false</approved>
</translation>
</translations>
</concept_node>
<concept_node>
<name>vehicle_check_in</name>
<definition_loaded>false</definition_loaded>

View File

@@ -6,8 +6,8 @@ import { setSelectedConversation } from "../../redux/messaging/messaging.actions
import { selectSelectedConversation } from "../../redux/messaging/messaging.selectors";
import { TimeAgoFormatter } from "../../utils/DateFormatter";
import PhoneFormatter from "../../utils/PhoneFormatter";
import "./chat-conversation-list.styles.scss";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import "./chat-conversation-list.styles.scss";
const mapStateToProps = createStructuredSelector({
selectedConversation: selectSelectedConversation,
@@ -38,17 +38,20 @@ export function ChatConversationListComponent({
: null
}`}
>
{item.job_conversations.length > 0 ? (
<div className="chat-name">
{item.job_conversations.map((j, idx) => (
<div key={idx}>
<OwnerNameDisplay ownerObject={j.job} />
</div>
))}
</div>
) : (
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
)}
<div sryle={{ display: "inline-block" }}>
{item.label && <div className="chat-name">{item.label}</div>}
{item.job_conversations.length > 0 ? (
<div className="chat-name">
{item.job_conversations.map((j, idx) => (
<div key={idx}>
<OwnerNameDisplay ownerObject={j.job} />
</div>
))}
</div>
) : (
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
)}
</div>
<div sryle={{ display: "inline-block" }}>
<div>
{item.job_conversations.length > 0

View File

@@ -3,6 +3,7 @@ import React from "react";
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import ChatArchiveButton from "../chat-archive-button/chat-archive-button.component";
import ChatConversationTitleTags from "../chat-conversation-title-tags/chat-conversation-title-tags.component";
import ChatLabelComponent from "../chat-label/chat-label.component";
import ChatTagRoContainer from "../chat-tag-ro/chat-tag-ro.container";
export default function ChatConversationTitle({ conversation }) {
@@ -11,6 +12,7 @@ export default function ChatConversationTitle({ conversation }) {
<PhoneNumberFormatter>
{conversation && conversation.phone_num}
</PhoneNumberFormatter>
<ChatLabelComponent conversation={conversation} />
<ChatConversationTitleTags
jobConversations={
(conversation && conversation.job_conversations) || []

View File

@@ -0,0 +1,67 @@
import { PlusOutlined } from "@ant-design/icons";
import { useMutation } from "@apollo/client";
import { Input, notification, Spin, Tag, Tooltip } from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { UPDATE_CONVERSATION_LABEL } from "../../graphql/conversations.queries";
export default function ChatLabel({ conversation }) {
const [loading, setLoading] = useState(false);
const [editing, setEditing] = useState(false);
const [value, setValue] = useState(conversation.label);
const { t } = useTranslation();
const [updateLabel] = useMutation(UPDATE_CONVERSATION_LABEL);
const handleSave = async () => {
setLoading(true);
try {
const response = await updateLabel({
variables: { id: conversation.id, label: value },
});
if (response.errors) {
notification["error"]({
message: t("messages.errors.updatinglabel", {
error: JSON.stringify(response.errors),
}),
});
} else {
setEditing(false);
}
} catch (error) {
notification["error"]({
message: t("messages.errors.updatinglabel", {
error: JSON.stringify(error),
}),
});
} finally {
setLoading(false);
}
};
if (editing) {
return (
<div>
<Input
autoFocus
value={value}
onChange={(e) => setValue(e.target.value)}
onBlur={handleSave}
allowClear
/>
{loading && <Spin size="small" />}
</div>
);
} else {
return conversation.label && conversation.label.trim() !== "" ? (
<Tag style={{ cursor: "pointer" }} onClick={() => setEditing(true)}>
{conversation.label}
</Tag>
) : (
<Tooltip title={t("messaging.labels.addlabel")}>
<PlusOutlined
style={{ cursor: "pointer" }}
onClick={() => setEditing(true)}
/>
</Tooltip>
);
}
}

View File

@@ -1,5 +1,14 @@
import { SyncOutlined, WarningFilled } from "@ant-design/icons";
import { Button, Card, Input, Space, Table, Tooltip } from "antd";
import {
Button,
Card,
Dropdown,
Input,
Menu,
Space,
Table,
Tooltip,
} from "antd";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom";
@@ -7,6 +16,8 @@ import { DateTimeFormatter } from "../../utils/DateFormatter";
import { alphaSort } from "../../utils/sorters";
import { OwnerNameDisplayFunction } from "../owner-name-display/owner-name-display.component";
import moment from "moment";
import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
const [state, setState] = useState({
sortedInfo: {},
@@ -166,6 +177,32 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
<Button onClick={() => refetch()}>
<SyncOutlined />
</Button>
<Dropdown
trigger="click"
overlay={
<Menu>
<Menu.Item
onClick={() =>
GenerateDocument(
{
name: TemplateList("courtesycar").courtesy_car_inventory
.key,
variables: {
//id: contract.id
},
},
{},
"p"
)
}
>
{t("printcenter.courtesycarcontract.courtesy_car_inventory")}
</Menu.Item>
</Menu>
}
>
<Button>{t("general.labels.print")}</Button>
</Dropdown>
<Link to={`/manage/courtesycars/new`}>
<Button>{t("courtesycars.actions.new")}</Button>
</Link>

View File

@@ -345,7 +345,20 @@ export function DmsPostForm({ bodyshop, socket, job, logsRef }) {
t(`jobs.fields.${cdkPayer?.control_type}`)}
</div>
);
else {
else if (
i18n.exists(
`jobs.fields.dms.control_type.${cdkPayer?.control_type}`
)
) {
return (
<div>
{cdkPayer &&
t(
`jobs.fields.dms.control_type.${cdkPayer?.control_type}`
)}
</div>
);
} else {
return null;
}
}}

View File

@@ -59,14 +59,18 @@ export default function JobDetailCardsDatesComponent({ loading, data }) {
<DateTimeFormatter>{data.scheduled_in}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.actual_in ? (
<Timeline.Item>
<label>{t("jobs.fields.actual_in")}: </label>
<DateTimeFormatter>{data.actual_in}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.date_repairstarted ? (
<Timeline.Item>
<label>{t("jobs.fields.date_repairstarted")}: </label>
<DateTimeFormatter>{data.date_repairstarted}</DateTimeFormatter>
</Timeline.Item>
) : null}
{data.scheduled_completion ? (
<Timeline.Item>
<label>{t("jobs.fields.scheduled_completion")}: </label>

View File

@@ -43,11 +43,9 @@ const JobSearchSelect = (
search: value,
...(convertedOnly || notExported
? {
variables: {
...(convertedOnly ? { isConverted: true } : {}),
...(notExported ? { notExported: true } : {}),
...(notInvoiced ? { notInvoiced: true } : {}),
},
...(convertedOnly ? { isConverted: true } : {}),
...(notExported ? { notExported: true } : {}),
...(notInvoiced ? { notInvoiced: true } : {}),
}
: {}),
},
@@ -79,6 +77,7 @@ const JobSearchSelect = (
disabled={disabled}
showSearch
autoFocus
allowClear
style={{
width: "100%",
}}

View File

@@ -126,6 +126,9 @@ export function JobsAdminDatesChange({ insertAuditTrail, job }) {
<Form.Item label={t("jobs.fields.actual_in")} name="actual_in">
<DateTimePicker />
</Form.Item>
<Form.Item label={t("jobs.fields.date_repairstarted")} name="date_repairstarted">
<DateTimePicker />
</Form.Item>
<Form.Item
label={t("jobs.fields.date_last_contacted")}
name="date_last_contacted"

View File

@@ -42,7 +42,10 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
<Form.Item label={t("jobs.fields.date_towin")} name="date_towin">
<DateTimePicker disabled={jobRO} />
</Form.Item>
<Form.Item label={t("jobs.fields.date_rentalresp")} name="date_rentalresp">
<Form.Item
label={t("jobs.fields.date_rentalresp")}
name="date_rentalresp"
>
<DateTimePicker disabled={jobRO} />
</Form.Item>
</FormRow>
@@ -73,6 +76,12 @@ export function JobsDetailDatesComponent({ jobRO, job, bodyshop }) {
title={t("jobs.labels.calc_repair_days")}
/>
</Tooltip>
<Form.Item
label={t("jobs.fields.date_repairstarted")}
name="date_repairstarted"
>
<DateTimePicker disabled={jobRO} />
</Form.Item>
</FormRow>
<FormRow header={t("jobs.forms.repairdates")}>
<Form.Item

View File

@@ -159,7 +159,7 @@ export function PayableExportAll({
} else {
notification["error"]({
message: t("bills.errors.exporting", {
error: JSON.stringify(billUpdateResponse.error),
error: JSON.stringify(billUpdateResponse.errors),
}),
});
}

View File

@@ -534,6 +534,7 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
<JobPartsQueueCount parts={record.joblines_status} record={record} />
),
},
//Added as a place holder for St Claude. Not implemented as it requires another join for a field used by only 1 client.
// {
// title: i18n.t("vehicles.fields.v_paint_codes", { number: "" }),
@@ -555,6 +556,29 @@ const r = ({ technician, state, activeStatuses, bodyshop }) => {
// </span>
// ) : null,
// },
{
title: i18n.t("jobs.fields.date_repairstarted"),
dataIndex: "date_repairstarted",
key: "date_repairstarted",
ellipsis: true,
sorter: (a, b) => dateSort(a.date_repairstarted, b.date_repairstarted),
sortOrder:
state.sortedInfo.columnKey === "date_repairstarted" &&
state.sortedInfo.order,
render: (text, record) => (
<ProductionListDate record={record} field="date_repairstarted" time />
),
},
{
title: i18n.t("jobs.fields.date_repairstarted") + " (HH:MM)",
dataIndex: "date_repairstarted_time",
key: "date_repairstarted_time",
ellipsis: true,
render: (text, record) => (
<TimeFormatter>{record.date_repairstarted}</TimeFormatter>
),
},
];
};
export default r;

View File

@@ -1,19 +1,17 @@
import { Popover } from "antd";
import { RadarChartOutlined } from "@ant-design/icons";
import { Popover, Space } from "antd";
import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import {
PolarAngleAxis,
Legend, PolarAngleAxis,
PolarGrid,
PolarRadiusAxis,
Radar,
Legend,
RadarChart,
Tooltip,
Radar, RadarChart,
Tooltip
} from "recharts";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { RadarChartOutlined } from "@ant-design/icons";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
@@ -23,7 +21,7 @@ const mapDispatchToProps = (dispatch) => ({
export function ScheduleCalendarHeaderGraph({ bodyshop, loadData }) {
const { ssbuckets } = bodyshop;
const { t } = useTranslation();
const data = useMemo(() => {
return (
(loadData &&
@@ -43,6 +41,10 @@ export function ScheduleCalendarHeaderGraph({ bodyshop, loadData }) {
const popContent = (
<div>
<Space>
{t("appointments.labels.expectedprodhrs")}
<strong>{loadData?.expectedHours?.toFixed(1)}</strong>
</Space>
<RadarChart
// cx={300}
// cy={250}

View File

@@ -139,6 +139,12 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
>
<Input />
</Form.Item>
<Form.Item
label={t("bodyshop.fields.dms.sendmaterialscosting")}
name={["cdk_configuration", "sendmaterialscosting"]}
>
<InputNumber min={0} max={100} />
</Form.Item>
{bodyshop.pbs_serialnumber && (
<Form.Item
label={t("bodyshop.fields.dms.disablecontactvehiclecreation")}
@@ -200,7 +206,7 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
// },
// ]}
>
<Select showSearch>
<Select allowClear showSearch>
<Select.Option value="ro_number">
{t("jobs.fields.ro_number")}
</Select.Option>
@@ -210,6 +216,9 @@ export function ShopInfoResponsibilityCenterComponent({ bodyshop, form }) {
<Select.Option value="po_number">
{t("jobs.fields.ponumber")}
</Select.Option>
<Select.Option value="account_number">
{t("jobs.fields.dms.control_type.account_number")}
</Select.Option>
</Select>
</Form.Item>

View File

@@ -43,6 +43,7 @@ export const CONVERSATION_LIST_QUERY = gql`
updated_at
unreadcnt
archived
label
messages_aggregate(
where: { read: { _eq: false }, isoutbound: { _eq: false } }
) {
@@ -88,6 +89,7 @@ export const GET_CONVERSATION_DETAILS = gql`
id
phone_num
archived
label
job_conversations {
jobid
conversationid
@@ -136,3 +138,15 @@ export const TOGGLE_CONVERSATION_ARCHIVE = gql`
}
}
`;
export const UPDATE_CONVERSATION_LABEL = gql`
mutation UPDATE_CONVERSATION_LABEL($id: uuid!, $label: String) {
update_conversations_by_pk(
pk_columns: { id: $id }
_set: { label: $label }
) {
label
id
}
}
`;

View File

@@ -142,6 +142,7 @@ export const QUERY_EXACT_JOB_IN_PRODUCTION = gql`
employee_refinish
employee_prep
employee_csr
date_repairstarted
joblines_status {
part_type
status
@@ -221,6 +222,7 @@ export const QUERY_EXACT_JOBS_IN_PRODUCTION = gql`
employee_refinish
employee_prep
employee_csr
date_repairstarted
joblines_status {
part_type
status
@@ -302,6 +304,7 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
employee_prep
employee_csr
suspended
date_repairstarted
joblines_status {
part_type
status
@@ -672,6 +675,7 @@ export const GET_JOB_BY_PK = gql`
date_towin
date_rentalresp
date_exported
date_repairstarted
status
owner_owing
tax_registration_number
@@ -917,7 +921,7 @@ export const QUERY_JOB_CARD_DETAILS = gql`
date_next_contact
date_open
date_exported
date_repairstarted
date_scheduled
date_estimated
employee_body_rel {

View File

@@ -5,6 +5,7 @@ export const QUERY_SEARCH_OWNER_BY_IDX = gql`
search_owners(args: { search: $search }, limit: 100) {
ownr_fn
ownr_ln
ownr_co_nm
ownr_ph1
ownr_ph2
ownr_addr1

View File

@@ -35,6 +35,7 @@ export function* calculateScheduleLoad({ payload: end }) {
const load = {
productionTotal: {},
productionHours: 0,
};
//Set the current load.
@@ -45,6 +46,10 @@ export function* calculateScheduleLoad({ payload: end }) {
prodJobs.forEach((item) => {
//Add all of the jobs currently in production to the buckets so that we have a starting point.
const bucketId = CheckJobBucket(buckets, item);
load.productionHours =
load.productionHours +
item.labhrs.aggregate.sum.mod_lb_hrs +
item.larhrs.aggregate.sum.mod_lb_hrs;
if (bucketId) {
load.productionTotal[bucketId].count =
load.productionTotal[bucketId].count + 1;
@@ -131,6 +136,10 @@ export function* calculateScheduleLoad({ payload: end }) {
}
});
console.log(
"🚀 ~ file: application.sagas.js:160 ~ function*calculateScheduleLoad ~ load.productionTotal",
load.productionTotal
);
//Propagate the expected load to each day.
const range = Math.round(moment.duration(end.diff(today)).asDays());
for (var day = 0; day < range; day++) {
@@ -149,6 +158,10 @@ export function* calculateScheduleLoad({ payload: end }) {
load[current].jobsIn || [],
load[current].jobsOut || []
);
load[current].expectedHours =
load.productionHours +
(load[current].hoursIn || 0) -
(load[current].hoursOut || 0);
} else {
load[current].expectedLoad = CalculateLoad(
load[prev].expectedLoad,
@@ -156,6 +169,10 @@ export function* calculateScheduleLoad({ payload: end }) {
load[current].jobsIn || [],
load[current].jobsOut || []
);
load[current].expectedHours =
load[prev].expectedHours +
(load[current].hoursIn || 0) -
(load[current].hoursOut || 0);
}
}
yield put(setProblemJobs(problemJobs));

View File

@@ -50,6 +50,7 @@
"cancelledappointment": "Canceled appointment for: ",
"completingjobs": "Completing Jobs",
"dataconsistency": "{{ro_number}} has a data consistency issue. It has been excluded for scheduling purposes. CODE: {{code}}.",
"expectedprodhrs": "Expected Production Hours:",
"history": "History",
"inproduction": "Jobs In Production",
"manualevent": "Add Manual Appointment",
@@ -273,6 +274,7 @@
"itc_local": "Local Tax is ITC?",
"itc_state": "State Tax is ITC?",
"mappingname": "DMS Mapping Name",
"sendmaterialscosting": "Materials Cost as % of Sale",
"srcco": "Source Company #/Dealer #"
},
"email": "General Shop Email",
@@ -1350,6 +1352,7 @@
"date_next_contact": "Next Contact Date",
"date_open": "Open",
"date_rentalresp": "Shop Rental Responsibility Start",
"date_repairstarted": "Repairs Started",
"date_scheduled": "Scheduled",
"date_towin": "Towed In",
"ded_amt": "Deductible",
@@ -1360,6 +1363,9 @@
"address": "Customer Address",
"amount": "Amount",
"center": "Center",
"control_type": {
"account_number": "Account Number"
},
"cost": "Cost",
"cost_dms_acctnumber": "Cost DMS Acct #",
"dms_make": "DMS Make",
@@ -1909,9 +1915,11 @@
},
"errors": {
"invalidphone": "The phone number is invalid. Unable to open conversation. ",
"noattachedjobs": "No jobs have been associated to this conversation. "
"noattachedjobs": "No jobs have been associated to this conversation. ",
"updatinglabel": "Error updating label. {{error}}"
},
"labels": {
"addlabel": "Add a label to this conversation.",
"archive": "Archive",
"maxtenimages": "You can only select up to a maximum of 10 images at a time.",
"messaging": "Messaging",
@@ -2162,6 +2170,7 @@
"courtesycarcontract": {
"courtesy_car_contract": "Courtesy Car Contract",
"courtesy_car_impound": "Impound Charges",
"courtesy_car_inventory": "Courtesy Car Inventory",
"courtesy_car_terms": "Courtesy Car Terms"
},
"errors": {
@@ -2248,6 +2257,7 @@
"supplement_request": "Supplement Request",
"thank_you_ro": "Thank You Letter",
"thirdpartypayer": "Third Party Payer",
"timetickets_ro": "Time Tickets",
"vehicle_check_in": "Vehicle Intake",
"vehicle_delivery_check": "Vehicle Delivery Checklist",
"window_tag": "Window Tag",

View File

@@ -50,6 +50,7 @@
"cancelledappointment": "Cita cancelada para:",
"completingjobs": "",
"dataconsistency": "",
"expectedprodhrs": "",
"history": "",
"inproduction": "",
"manualevent": "",
@@ -273,6 +274,7 @@
"itc_local": "",
"itc_state": "",
"mappingname": "",
"sendmaterialscosting": "",
"srcco": ""
},
"email": "",
@@ -1350,6 +1352,7 @@
"date_next_contact": "",
"date_open": "Abierto",
"date_rentalresp": "",
"date_repairstarted": "",
"date_scheduled": "Programado",
"date_towin": "",
"ded_amt": "Deducible",
@@ -1360,6 +1363,9 @@
"address": "",
"amount": "",
"center": "",
"control_type": {
"account_number": ""
},
"cost": "",
"cost_dms_acctnumber": "",
"dms_make": "",
@@ -1909,9 +1915,11 @@
},
"errors": {
"invalidphone": "",
"noattachedjobs": ""
"noattachedjobs": "",
"updatinglabel": ""
},
"labels": {
"addlabel": "",
"archive": "",
"maxtenimages": "",
"messaging": "Mensajería",
@@ -2162,6 +2170,7 @@
"courtesycarcontract": {
"courtesy_car_contract": "",
"courtesy_car_impound": "",
"courtesy_car_inventory": "",
"courtesy_car_terms": ""
},
"errors": {
@@ -2248,6 +2257,7 @@
"supplement_request": "",
"thank_you_ro": "",
"thirdpartypayer": "",
"timetickets_ro": "",
"vehicle_check_in": "",
"vehicle_delivery_check": "",
"window_tag": "",

View File

@@ -50,6 +50,7 @@
"cancelledappointment": "Rendez-vous annulé pour:",
"completingjobs": "",
"dataconsistency": "",
"expectedprodhrs": "",
"history": "",
"inproduction": "",
"manualevent": "",
@@ -273,6 +274,7 @@
"itc_local": "",
"itc_state": "",
"mappingname": "",
"sendmaterialscosting": "",
"srcco": ""
},
"email": "",
@@ -1350,6 +1352,7 @@
"date_next_contact": "",
"date_open": "Ouvrir",
"date_rentalresp": "",
"date_repairstarted": "",
"date_scheduled": "Prévu",
"date_towin": "",
"ded_amt": "Déductible",
@@ -1360,6 +1363,9 @@
"address": "",
"amount": "",
"center": "",
"control_type": {
"account_number": ""
},
"cost": "",
"cost_dms_acctnumber": "",
"dms_make": "",
@@ -1909,9 +1915,11 @@
},
"errors": {
"invalidphone": "",
"noattachedjobs": ""
"noattachedjobs": "",
"updatinglabel": ""
},
"labels": {
"addlabel": "",
"archive": "",
"maxtenimages": "",
"messaging": "Messagerie",
@@ -2162,6 +2170,7 @@
"courtesycarcontract": {
"courtesy_car_contract": "",
"courtesy_car_impound": "",
"courtesy_car_inventory": "",
"courtesy_car_terms": ""
},
"errors": {
@@ -2248,6 +2257,7 @@
"supplement_request": "",
"thank_you_ro": "",
"thirdpartypayer": "",
"timetickets_ro": "",
"vehicle_check_in": "",
"vehicle_delivery_check": "",
"window_tag": "",

View File

@@ -488,6 +488,14 @@ export const TemplateList = (type, context) => {
disabled: false,
group: "pre",
},
timetickets_ro: {
title: i18n.t("printcenter.jobs.timetickets_ro"),
description: "CASL Authorization",
subject: i18n.t("printcenter.jobs.timetickets_ro"),
key: "timetickets_ro",
disabled: false,
group: "financial",
},
}
: {}),
...(!type || type === "job_special"
@@ -1731,6 +1739,21 @@ export const TemplateList = (type, context) => {
},
}
: {}),
...(!type || type === "courtesycar"
? {
courtesy_car_inventory: {
title: i18n.t(
"printcenter.courtesycarcontract.courtesy_car_inventory"
),
description: "Est Detail",
subject: i18n.t(
"printcenter.courtesycarcontract.courtesy_car_inventory"
),
key: "courtesy_car_inventory",
disabled: false,
},
}
: {}),
...(!type || type === "bill"
? {
inhouse_invoice: {

View File

@@ -1241,6 +1241,7 @@
- bodyshopid
- created_at
- id
- label
- phone_num
- unreadcnt
- updated_at
@@ -1252,6 +1253,7 @@
- bodyshopid
- created_at
- id
- label
- phone_num
- unreadcnt
- updated_at
@@ -1273,6 +1275,7 @@
- bodyshopid
- created_at
- id
- label
- phone_num
- unreadcnt
- updated_at
@@ -3025,6 +3028,7 @@
- date_next_contact
- date_open
- date_rentalresp
- date_repairstarted
- date_scheduled
- date_towin
- ded_amt
@@ -3288,6 +3292,7 @@
- date_next_contact
- date_open
- date_rentalresp
- date_repairstarted
- date_scheduled
- date_towin
- ded_amt
@@ -3561,6 +3566,7 @@
- date_next_contact
- date_open
- date_rentalresp
- date_repairstarted
- date_scheduled
- date_towin
- ded_amt

View File

@@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."jobs" add column "date_repairstarted" timestamptz
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."jobs" add column "date_repairstarted" timestamptz
null;

View File

@@ -0,0 +1,4 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- alter table "public"."conversations" add column "label" text
-- null;

View File

@@ -0,0 +1,2 @@
alter table "public"."conversations" add column "label" text
null;

View File

@@ -209,6 +209,48 @@ exports.default = async function (socket, jobid) {
// console.log("NO MASH ACCOUNT FOUND!!");
}
}
console.log(
Number.isInteger(bodyshop?.cdk_configuration?.sendmaterialscosting),
typeof Number.isInteger(bodyshop?.cdk_configuration?.sendmaterialscosting)
);
if (!!bodyshop?.cdk_configuration?.sendmaterialscosting) {
//Manually send the percentage of the costing.
//Paint Mat
const mapaAccountName = selectedDmsAllocationConfig.costs.MAPA;
const mapaAccount = bodyshop.md_responsibility_centers.costs.find(
(c) => c.name === mapaAccountName
);
if (mapaAccount) {
if (!costCenterHash[mapaAccountName])
costCenterHash[mapaAccountName] = Dinero();
costCenterHash[mapaAccountName] = costCenterHash[mapaAccountName].add(
Dinero(job.job_totals.rates.mapa.total).percentage(
bodyshop?.cdk_configuration?.sendmaterialscosting
)
);
} else {
//console.log("NO MAPA ACCOUNT FOUND!!");
}
//Shop Mat
const mashAccountName = selectedDmsAllocationConfig.costs.MASH;
const mashAccount = bodyshop.md_responsibility_centers.costs.find(
(c) => c.name === mashAccountName
);
if (mashAccount) {
if (!costCenterHash[mashAccountName])
costCenterHash[mashAccountName] = Dinero();
costCenterHash[mashAccountName] = costCenterHash[mashAccountName].add(
Dinero(job.job_totals.rates.mash.total).percentage(
bodyshop?.cdk_configuration?.sendmaterialscosting
)
);
} else {
// console.log("NO MASH ACCOUNT FOUND!!");
}
}
const { ca_bc_pvrt } = job;
if (ca_bc_pvrt) {
// const pvrtAccount = bodyshop.md_responsibility_centers.profits.find(

View File

@@ -334,12 +334,17 @@ const CreateRepairOrderTag = (job, errorCallback) => {
.format(AhDateFormat)) ||
"",
InsInspDate: null,
StartDate:
(job.actual_in &&
moment(job.actual_in)
.tz(job.bodyshop.timezone)
.format(AhDateFormat)) ||
"",
StartDate: job.date_repairstarted
? (job.date_repairstarted &&
moment(job.date_repairstarted)
.tz(job.bodyshop.timezone)
.format(AhDateFormat)) ||
""
: (job.date_repairstarted &&
moment(job.actual_in)
.tz(job.bodyshop.timezone)
.format(AhDateFormat)) ||
"",
PartsOrder: null,
TeardownHold: null,
SupplementSubmittedDate: null,
@@ -496,7 +501,13 @@ const CreateRepairOrderTag = (job, errorCallback) => {
FrameHours: job.job_totals.rates.laf.hours.toFixed(2),
GlassHours: job.job_totals.rates.lag.hours.toFixed(2),
DetailHours: job.job_totals.rates.lad.hours.toFixed(2),
LaborMiscHours: 0,
LaborMiscHours: (
job.job_totals.rates.la1.hours +
job.job_totals.rates.la2.hours +
job.job_totals.rates.la3.hours +
job.job_totals.rates.la4.hours +
job.job_totals.rates.lau.hours
).toFixed(2),
PartsTotal: Dinero(job.job_totals.parts.parts.total).toFormat(
AHDineroFormat
@@ -579,8 +590,14 @@ const CreateRepairOrderTag = (job, errorCallback) => {
),
DetailLaborTotalCost:
repairCosts.DetailLaborTotalCost.toFormat(AHDineroFormat),
LaborMiscTotal: 0,
LaborMiscTotalCost: 0,
LaborMiscTotal: Dinero(job.job_totals.rates.la1.total)
.add(Dinero(job.job_totals.rates.la2.total))
.add(Dinero(job.job_totals.rates.la3.total))
.add(Dinero(job.job_totals.rates.la4.total))
.add(Dinero(job.job_totals.rates.lau.total))
.toFormat(AHDineroFormat),
LaborMiscTotalCost:
repairCosts.LaborMiscTotalCost.toFormat(AHDineroFormat),
MiscellaneousChargeTotal: 0,
MiscellaneousChargeTotalCost: 0,
PMTotal: Dinero(job.job_totals.rates.mapa.total).toFormat(
@@ -852,6 +869,12 @@ const CreateCosts = (job) => {
GlassLaborTotalCost: ticketTotalsByCostCenter[defaultCosts.LAG] || Dinero(),
DetailLaborTotalCost:
ticketTotalsByCostCenter[defaultCosts.LAD] || Dinero(),
LaborMiscTotalCost: (ticketTotalsByCostCenter[defaultCosts.LA1] || Dinero())
.add(ticketTotalsByCostCenter[defaultCosts.LA2] || Dinero())
.add(ticketTotalsByCostCenter[defaultCosts.LA2] || Dinero())
.add(ticketTotalsByCostCenter[defaultCosts.LA3] || Dinero())
.add(ticketTotalsByCostCenter[defaultCosts.LA4] || Dinero())
.add(ticketTotalsByCostCenter[defaultCosts.LAU] || Dinero()),
PMTotalCost: billTotalsByCostCenters[defaultCosts.MAPA] || Dinero(),
BMTotalCost: billTotalsByCostCenters[defaultCosts.MASH] || Dinero(),
MiscTotalCost: billTotalsByCostCenters[defaultCosts.PAO] || Dinero(),

View File

@@ -695,6 +695,7 @@ exports.AUTOHOUSE_QUERY = `query AUTOHOUSE_EXPORT($start: timestamptz, $bodyshop
driveable
parts_tax_rates
ded_amt
date_repairstarted
joblines(where: {removed: {_eq: false}}) {
id
line_no
@@ -1010,6 +1011,7 @@ vehicle{
date_scheduled
date_invoiced
date_exported
date_repairstarted
status
owner_owing
tax_registration_number