Merge branch 'release/2023-01-27' into feature/america

This commit is contained in:
Patrick Fic
2023-01-27 15:33:59 -08:00
15 changed files with 245 additions and 47 deletions

View File

@@ -1,4 +1,4 @@
<babeledit_project version="1.2" be_version="2.7.1">
<babeledit_project be_version="2.7.1" version="1.2">
<!--
BabelEdit project file
@@ -736,6 +736,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>expectedjobs</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>expectedprodhrs</name>
<definition_loaded>false</definition_loaded>
@@ -41489,6 +41510,48 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>jobs_completed_not_invoiced</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>jobs_invoiced_not_exported</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>jobs_reconcile</name>
<definition_loaded>false</definition_loaded>
@@ -41615,6 +41678,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>open_orders_specific_csr</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>open_orders_status</name>
<definition_loaded>false</definition_loaded>
@@ -42224,6 +42308,27 @@
</translation>
</translations>
</concept_node>
<concept_node>
<name>scheduled_parts_list</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>scoreboard_detail</name>
<definition_loaded>false</definition_loaded>

View File

@@ -1,6 +1,5 @@
import { useLazyQuery } from "@apollo/client";
import { LoadingOutlined } from "@ant-design/icons";
import { AutoComplete, Divider, Space } from "antd";
import { AutoComplete, Divider, Input, Space } from "antd";
import _ from "lodash";
import React from "react";
import { useTranslation } from "react-i18next";
@@ -9,7 +8,7 @@ import { GLOBAL_SEARCH_QUERY } from "../../graphql/search.queries";
import PhoneNumberFormatter from "../../utils/PhoneFormatter";
import AlertComponent from "../alert/alert.component";
import OwnerNameDisplay, {
OwnerNameDisplayFunction,
OwnerNameDisplayFunction
} from "../owner-name-display/owner-name-display.component";
import VehicleVinDisplay from "../vehicle-vin-display/vehicle-vin-display.component";
export default function GlobalSearch() {
@@ -178,13 +177,18 @@ export default function GlobalSearch() {
<AutoComplete
options={options}
onSearch={handleSearch}
suffixIcon={loading && <LoadingOutlined spin />}
defaultActiveFirstOption
placeholder={t("general.labels.globalsearch")}
allowClear
onSelect={(val, opt) => {
history.push(opt.label.props.to);
}}
></AutoComplete>
>
<Input.Search
size="large"
placeholder={t("general.labels.globalsearch")}
enterButton
allowClear
loading={loading}
/>
</AutoComplete>
);
}

View File

@@ -166,16 +166,16 @@ export function JobLinesUpsertModalComponent({
name="ah_detail_line"
valuePropName="checked"
dependencies={["mod_lbr_ty"]}
initialValue={false}
rules={[
({ getFieldValue }) => ({
validator(rule, value) {
console.log(
value === true,
["LA1", "LA2", "LA3", "LA4", "LAU"].includes(
getFieldValue("mod_lbr_ty")
)
);
if (value === false) return Promise.resolve();
if (
value === false ||
value === undefined ||
value === null
)
return Promise.resolve();
if (
value === true &&
["LA1", "LA2", "LA3", "LA4", "LAU"].includes(

View File

@@ -43,14 +43,21 @@ export function JobsConvertButton({
const { t } = useTranslation();
const [form] = Form.useForm();
const handleConvert = async (values) => {
const handleConvert = async ({ employee_csr, ...values }) => {
if (parentFormIsFieldsTouched()) {
alert(t("jobs.labels.savebeforeconversion"));
return;
}
setLoading(true);
const res = await mutationConvertJob({
variables: { jobId: job.id, ...values },
variables: {
jobId: job.id,
job: {
converted: true,
...(bodyshop.enforce_conversion_csr ? { employee_csr } : {}),
...values,
},
},
});
if (values.ca_gst_registrant) {

View File

@@ -4,11 +4,13 @@ import React, { useMemo } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import {
Legend, PolarAngleAxis,
Legend,
PolarAngleAxis,
PolarGrid,
PolarRadiusAxis,
Radar, RadarChart,
Tooltip
Radar,
RadarChart,
Tooltip,
} from "recharts";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
@@ -20,6 +22,10 @@ const mapDispatchToProps = (dispatch) => ({
});
export function ScheduleCalendarHeaderGraph({ bodyshop, loadData }) {
console.log(
"🚀 ~ file: schedule-calendar-header-graph.component.js:23 ~ ScheduleCalendarHeaderGraph ~ loadData",
loadData
);
const { ssbuckets } = bodyshop;
const { t } = useTranslation();
const data = useMemo(() => {
@@ -44,6 +50,8 @@ export function ScheduleCalendarHeaderGraph({ bodyshop, loadData }) {
<Space>
{t("appointments.labels.expectedprodhrs")}
<strong>{loadData?.expectedHours?.toFixed(1)}</strong>
{t("appointments.labels.expectedjobs")}
<strong>{loadData?.expectedJobCount}</strong>
</Space>
<RadarChart
// cx={300}

View File

@@ -85,7 +85,7 @@ export function TimeTicketList({
text: (() => {
const emp = bodyshop.employees.find((e) => e.id === s);
return `${emp.first_name} ${emp.last_name}`;
return `${emp?.first_name} ${emp?.last_name}`;
})(), //
value: [s],
};

View File

@@ -131,6 +131,7 @@ const JobRelatedTicketsTable = ({
return {
id: `${item.jobKey}${costCenter}`,
costCenter,
item,
actHrs: actHrs.toFixed(1),
prodHrs: prodHrs.toFixed(1),
@@ -151,7 +152,9 @@ const JobRelatedTicketsTable = ({
sortOrder:
state.sortedInfo.columnKey === "empname" && state.sortedInfo.order,
render: (text, record) =>
`${record.item.employee.first_name} ${record.item.employee.last_name}`,
`${record.item.employee.first_name} ${record.item.employee.last_name} ${
record.costCenter ? `(${record.costCenter})` : ""
}`.trim(),
},
{
title: t("timetickets.fields.actualhrs"),

View File

@@ -1153,31 +1153,8 @@ export const UPDATE_JOBS = gql`
`;
export const CONVERT_JOB_TO_RO = gql`
mutation CONVERT_JOB_TO_RO(
$jobId: uuid!
$class: String
$ins_co_nm: String!
$ca_gst_registrant: Boolean
$driveable: Boolean
$towin: Boolean
$referral_source: String
$referral_source_extra: String
$employee_csr: uuid
) {
update_jobs(
where: { id: { _eq: $jobId } }
_set: {
converted: true
ins_co_nm: $ins_co_nm
class: $class
ca_gst_registrant: $ca_gst_registrant
towin: $towin
driveable: $driveable
referral_source: $referral_source
referral_source_extra: $referral_source_extra
employee_csr: $employee_csr
}
) {
mutation CONVERT_JOB_TO_RO($jobId: uuid!, $job: jobs_set_input!) {
update_jobs(where: { id: { _eq: $jobId } }, _set: $job) {
returning {
id
ro_number

View File

@@ -154,6 +154,10 @@ export function* calculateScheduleLoad({ payload: end }) {
load[current].jobsIn || [],
load[current].jobsOut || []
);
load[current].expectedJobCount =
prodJobs.length +
(load[current].jobsIn || []).length -
(load[current].jobsOut || []).length;
load[current].expectedHours =
load.productionHours +
(load[current].hoursIn || 0) -
@@ -165,6 +169,10 @@ export function* calculateScheduleLoad({ payload: end }) {
load[current].jobsIn || [],
load[current].jobsOut || []
);
load[current].expectedJobCount =
load[prev].expectedJobCount +
(load[current].jobsIn || []).length -
(load[current].jobsOut || []).length;
load[current].expectedHours =
load[prev].expectedHours +
(load[current].hoursIn || 0) -

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}}.",
"expectedjobs": "Expected Jobs in Production: ",
"expectedprodhrs": "Expected Production Hours:",
"history": "History",
"inproduction": "Jobs In Production",
@@ -2454,12 +2455,15 @@
"job_costing_ro_date_summary": "Job Costing by RO - Summary",
"job_costing_ro_estimator": "Job Costing by Estimator",
"job_costing_ro_ins_co": "Job Costing by RO Source",
"jobs_completed_not_invoiced": "Jobs Completed not Invoiced",
"jobs_invoiced_not_exported": "Jobs Invoiced not Exported",
"jobs_reconcile": "Parts/Sublet/Labor Reconciliation",
"lag_time": "Lag Time",
"open_orders": "Open Orders by Date",
"open_orders_csr": "Open Orders by CSR",
"open_orders_estimator": "Open Orders by Estimator",
"open_orders_ins_co": "Open Orders by Insurance Company",
"open_orders_specific_csr": "Open Orders filtered by CSR",
"open_orders_status": "Open Orders by Status",
"parts_backorder": "IOU Parts List",
"parts_not_recieved": "Parts Not Received",
@@ -2489,6 +2493,7 @@
"returns_grouped_by_vendor_detailed": "Returns Grouped by Vendor - Detailed",
"returns_grouped_by_vendor_summary": "Returns Grouped by Vendor - Summary",
"schedule": "Appointment Schedule",
"scheduled_parts_list": "Parts for Jobs Scheduled In",
"scoreboard_detail": "Scoreboard Detail",
"scoreboard_summary": "Scoreboard Summary",
"supplement_ratio_ins_co": "Supplement Ratio by Source",

View File

@@ -50,6 +50,7 @@
"cancelledappointment": "Cita cancelada para:",
"completingjobs": "",
"dataconsistency": "",
"expectedjobs": "",
"expectedprodhrs": "",
"history": "",
"inproduction": "",
@@ -2454,12 +2455,15 @@
"job_costing_ro_date_summary": "",
"job_costing_ro_estimator": "",
"job_costing_ro_ins_co": "",
"jobs_completed_not_invoiced": "",
"jobs_invoiced_not_exported": "",
"jobs_reconcile": "",
"lag_time": "",
"open_orders": "",
"open_orders_csr": "",
"open_orders_estimator": "",
"open_orders_ins_co": "",
"open_orders_specific_csr": "",
"open_orders_status": "",
"parts_backorder": "",
"parts_not_recieved": "",
@@ -2489,6 +2493,7 @@
"returns_grouped_by_vendor_detailed": "",
"returns_grouped_by_vendor_summary": "",
"schedule": "",
"scheduled_parts_list": "",
"scoreboard_detail": "",
"scoreboard_summary": "",
"supplement_ratio_ins_co": "",

View File

@@ -50,6 +50,7 @@
"cancelledappointment": "Rendez-vous annulé pour:",
"completingjobs": "",
"dataconsistency": "",
"expectedjobs": "",
"expectedprodhrs": "",
"history": "",
"inproduction": "",
@@ -2454,12 +2455,15 @@
"job_costing_ro_date_summary": "",
"job_costing_ro_estimator": "",
"job_costing_ro_ins_co": "",
"jobs_completed_not_invoiced": "",
"jobs_invoiced_not_exported": "",
"jobs_reconcile": "",
"lag_time": "",
"open_orders": "",
"open_orders_csr": "",
"open_orders_estimator": "",
"open_orders_ins_co": "",
"open_orders_specific_csr": "",
"open_orders_status": "",
"parts_backorder": "",
"parts_not_recieved": "",
@@ -2489,6 +2493,7 @@
"returns_grouped_by_vendor_detailed": "",
"returns_grouped_by_vendor_summary": "",
"schedule": "",
"scheduled_parts_list": "",
"scoreboard_detail": "",
"scoreboard_summary": "",
"supplement_ratio_ins_co": "",

View File

@@ -1421,6 +1421,19 @@ export const TemplateList = (type, context) => {
},
group: "jobs",
},
open_orders_specific_csr: {
title: i18n.t("reportcenter.templates.open_orders_specific_csr"),
description: "",
subject: i18n.t("reportcenter.templates.open_orders_specific_csr"),
key: "open_orders_specific_csr",
idtype: "employee",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_open"),
},
group: "jobs",
},
export_payables: {
title: i18n.t("reportcenter.templates.export_payables"),
description: "",
@@ -1734,6 +1747,46 @@ export const TemplateList = (type, context) => {
},
group: "jobs",
},
scheduled_parts_list: {
title: i18n.t("reportcenter.templates.scheduled_parts_list"),
subject: i18n.t("reportcenter.templates.scheduled_parts_list"),
key: "scheduled_parts_list",
//idtype: "vendor",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.scheduled_in"),
},
group: "jobs",
},
jobs_completed_not_invoiced: {
title: i18n.t("reportcenter.templates.jobs_completed_not_invoiced"),
subject: i18n.t(
"reportcenter.templates.jobs_completed_not_invoiced"
),
key: "jobs_completed_not_invoiced",
//idtype: "vendor",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_invoiced"),
},
group: "jobs",
},
jobs_invoiced_not_exported: {
title: i18n.t("reportcenter.templates.jobs_invoiced_not_exported"),
subject: i18n.t(
"reportcenter.templates.jobs_invoiced_not_exported"
),
key: "jobs_invoiced_not_exported",
//idtype: "vendor",
disabled: false,
rangeFilter: {
object: i18n.t("reportcenter.labels.objects.jobs"),
field: i18n.t("jobs.fields.date_invoiced"),
},
group: "jobs",
},
}
: {}),
...(!type || type === "courtesycarcontract"

View File

@@ -0,0 +1,10 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- CREATE OR REPLACE VIEW "public"."joblines_status" AS
-- SELECT j.jobid,
-- j.status,
-- count(1) AS count,
-- j.part_type
-- FROM joblines j
-- WHERE ((j.part_type IS NOT NULL) AND (j.part_type <> 'PAE'::text) AND (j.part_type <> 'PAS'::text) AND (j.part_type <> 'PASL'::text) AND (j.removed IS FALSE))
-- GROUP BY j.jobid, j.status, j.part_type;

View File

@@ -0,0 +1,8 @@
CREATE OR REPLACE VIEW "public"."joblines_status" AS
SELECT j.jobid,
j.status,
count(1) AS count,
j.part_type
FROM joblines j
WHERE ((j.part_type IS NOT NULL) AND (j.part_type <> 'PAE'::text) AND (j.part_type <> 'PAS'::text) AND (j.part_type <> 'PASL'::text) AND (j.removed IS FALSE))
GROUP BY j.jobid, j.status, j.part_type;