Group and Targeting for new V3 rule set.

This commit is contained in:
Patrick Fic
2024-08-09 12:02:09 -07:00
parent dc94fa0a49
commit 0b2b741123
17 changed files with 5112 additions and 219 deletions

View File

@@ -16,25 +16,6 @@ const RuleSets = [
},
];
function ChangeOfRuleSet({
prevDateMoment = moment(),
newDateMoment = moment(),
}) {
const prevRuleSet = RuleSets.find(
(r) =>
prevDateMoment.isSameOrAfter(r.range[0]) &&
prevDateMoment.isBefore(r.range[1])
);
const newRuleSet = RuleSets.find(
(r) =>
newDateMoment.isSameOrAfter(r.range[0]) &&
newDateMoment.isBefore(r.range[1])
);
return prevRuleSet?.title !== newRuleSet?.title;
}
function WhichRulesetToApply(close_date) {
const DateMoment = close_date ? moment(close_date) : moment();
const newRuleSet = RuleSets.find(

View File

@@ -371,8 +371,11 @@ async function DecodeLinFile(extensionlessFilePath, close_date) {
case "V2":
jobline = V2Ruleset(jobline, joblines);
break;
case "V3":
jobline = V3Ruleset(jobline, joblines);
break;
default:
jobline = V1Ruleset(jobline, joblines);
jobline = V3Ruleset(jobline, joblines);
break;
}
@@ -507,6 +510,11 @@ function V2Ruleset(jobline, joblines) {
return jobline;
}
function V3Ruleset(jobline, joblines) {
//This is the rules psot 09/01/2023. They appear to be a copy of V2 rules. They have been duplicated for structural sake.
V2Ruleset(jobline, joblines);
return jobline;
}
const AdasDescriptions = [
"seat belt",

View File

@@ -0,0 +1,5 @@
-- Could not auto-generate a down migration.
-- Please write an appropriate down migration for the SQL below:
-- update targets
-- set end_date = '2024-08-31'
-- where name = 'V2';

View File

@@ -0,0 +1,3 @@
update targets
set end_date = '2024-08-31'
where name = 'V2';

View File

@@ -9,11 +9,12 @@ import ipcTypes from "../../../ipc.types";
import { selectBodyshop } from "../../../redux/user/user.selectors";
import GroupVerifySwitch from "../group-verify-switch/group-verify-switch.component";
import JobsGroupModalMolecule from "../jobs-group-modal/jobs-group-modal.molecule";
import { WhichRulesetToApply } from "../../../util/constants";
const { ipcRenderer } = window;
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
bodyshop: selectBodyshop,
bodyshop: selectBodyshop
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
@@ -29,11 +30,11 @@ export function JobGroupMolecule({ bodyshop, jobId, group, job }) {
event: "CHANGE_VEHICLE_GROUP",
vehicle: `${job.v_model_yr} ${job.v_makedesc} ${job.v_model} (${job.v_type})`,
oldGroup: group,
newGroup: value.key,
newGroup: value.key
});
setLoading(true);
const result = await updateJob({
variables: { jobId: jobId, job: { group: value.key } },
variables: { jobId: jobId, job: { group: value.key } }
});
if (!result.errors) {
@@ -44,12 +45,30 @@ export function JobGroupMolecule({ bodyshop, jobId, group, job }) {
setLoading(false);
};
const menu = (
<Menu
onClick={handleMenuClick}
items={bodyshop.groups.map((g, idx) => ({ key: g, title: g, label: g }))}
></Menu>
);
const RulesetToApply = WhichRulesetToApply(job.close_date);
const menu =
RulesetToApply === "V3" ? (
<Menu
onClick={handleMenuClick}
disabled
items={[
{ label: "Group 1", value: "Group 1", },
{ label: "Group 2", value: "Group 2", },
{ label: "Group 3", value: "Group 3", },
{ label: "Group 4", value: "Group 4", },
{ label: "Group 5", value: "Group 5", },
{ label: "Group 6", value: "Group 6", },
{ label: "Group 7", value: "Group 7", },
{ label: "Group 8", value: "Group 8", },
{ label: "Group 9", value: "Group 9", },
{ label: "Group 10", value: "Group 10", },
{ label: "Group 11", value: "Group 11", },
{ label: "Group 12", value: "Group 12", }
]}
></Menu>
) : (
<Menu onClick={handleMenuClick} items={bodyshop.groups.map((g, idx) => ({ key: g, title: g, label: g }))}></Menu>
);
return (
<Space align="top">
@@ -67,11 +86,7 @@ export function JobGroupMolecule({ bodyshop, jobId, group, job }) {
)}
{group && (
<div style={{ marginLeft: ".2rem" }}>
<GroupVerifySwitch
job={job}
loading={loading}
loadingCallback={setLoading}
/>
<GroupVerifySwitch job={job} loading={loading} loadingCallback={setLoading} />
</div>
)}
<JobsGroupModalMolecule />

View File

@@ -1,4 +1,5 @@
import { Alert, Descriptions, Skeleton, Tooltip } from "antd";
import { Alert, Descriptions, Skeleton, Tooltip, Space } from "antd";
import { WarningOutlined } from "@ant-design/icons";
import React from "react";
import CurrencyFormatterAtom from "../../atoms/currency-formatter/currency-formatter.atom";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
@@ -71,7 +72,12 @@ export default function JobsDetailDescriptionMolecule({ loading, job }) {
<Descriptions.Item label="Loss Date">
{job.loss_date ? dayjs(job.loss_date).format(DateFormat) : "No Loss Date"}
</Descriptions.Item>
<Descriptions.Item label="Mileage">{job.v_mileage}</Descriptions.Item>
<Descriptions.Item label="Mileage">
<Space>
{job.v_mileage}
{job.v_mileage < 20000 && <WarningOutlined style={{ color: "tomato" }} />}
</Space>
</Descriptions.Item>
</Descriptions>
</PageHeader>
</div>

View File

@@ -1,49 +1,36 @@
import { Skeleton, Statistic } from "antd";
import { Skeleton, Statistic, Space, Tooltip } from "antd";
import { WarningOutlined } from "@ant-design/icons";
import React, { useCallback } from "react";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectSelectedJobTargetPc } from "../../../redux/application/application.selectors";
import {
CalculateJobRpsDollars,
CalculateJobRpsPc,
} from "../../../util/CalculateJobRps";
import { CalculateJobRpsDollars, CalculateJobRpsPc } from "../../../util/CalculateJobRps";
import ErrorResultAtom from "../../atoms/error-result/error-result.atom";
const mapStateToProps = createStructuredSelector({
selectedJobTargetPc: selectSelectedJobTargetPc,
selectedJobTargetPc: selectSelectedJobTargetPc
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobsTargetsStatsMolecule);
export default connect(mapStateToProps, mapDispatchToProps)(JobsTargetsStatsMolecule);
export function JobsTargetsStatsMolecule({
loading,
job,
selectedJobTargetPc,
}) {
export function JobsTargetsStatsMolecule({ loading, job, selectedJobTargetPc }) {
// eslint-disable-next-line react-hooks/exhaustive-deps
const { actPriceSum, jobRpsDollars } = useCallback(
CalculateJobRpsDollars(job, true),
[job, CalculateJobRpsDollars]
);
const { actPriceSum, jobRpsDollars } = useCallback(CalculateJobRpsDollars(job, true), [job, CalculateJobRpsDollars]);
// eslint-disable-next-line react-hooks/exhaustive-deps
const { dbPriceSum, jobRpsPc } = useCallback(
CalculateJobRpsPc(job, jobRpsDollars, true),
[job, jobRpsDollars, CalculateJobRpsPc]
);
const { dbPriceSum, jobRpsPc } = useCallback(CalculateJobRpsPc(job, jobRpsDollars, true), [
job,
jobRpsDollars,
CalculateJobRpsPc
]);
if (loading) return <Skeleton active />;
if (!job)
return (
<ErrorResultAtom
title="Error displaying job totals."
errorMessage="It looks like this job doesn't exist."
/>
<ErrorResultAtom title="Error displaying job totals." errorMessage="It looks like this job doesn't exist." />
);
const targetRpsDollars = dbPriceSum.percentage(selectedJobTargetPc * 100);
@@ -55,60 +42,51 @@ export function JobsTargetsStatsMolecule({
alignItems: "center",
justifyContent: "space-around",
marginTop: "2rem",
marginBottom: "1rem",
marginBottom: "1rem"
}}
>
<div style={{ display: "flex" }}>
<Space>
<Statistic
title="Target RPS %"
value={(selectedJobTargetPc * 100).toFixed(1)}
suffix="%"
suffix={
<Space>
%{" "}
{job.v_mileage < 20000 && (
<Tooltip title="Vehicle is under 20,000 KMs. No expected savings.">
<WarningOutlined style={{ color: "tomato" }} />
</Tooltip>
)}
</Space>
}
style={{ margin: "0rem .5rem" }}
/>
<Statistic
title="Current RPS %"
style={{ margin: "0rem .5rem" }}
valueStyle={{
color:
selectedJobTargetPc > (jobRpsPc || 0) ? "tomato" : "seagreen",
color: selectedJobTargetPc > (jobRpsPc || 0) ? "tomato" : "seagreen"
}}
value={((jobRpsPc || 0) * 100).toFixed(1)}
suffix="%"
/>
</div>
<div style={{ display: "flex" }}>
<Statistic
title="Target RPS $"
style={{ margin: "0rem .5rem" }}
value={targetRpsDollars.toFormat()}
/>
<Statistic
title="Current RPS $"
style={{ margin: "0rem .5rem" }}
value={jobRpsDollars.toFormat()}
/>
</Space>
<Space>
<Statistic title="Target RPS $" style={{ margin: "0rem .5rem" }} value={targetRpsDollars.toFormat()} />
<Statistic title="Current RPS $" style={{ margin: "0rem .5rem" }} value={jobRpsDollars.toFormat()} />
<Statistic
title="Diff."
style={{ margin: "0rem .5rem" }}
valueStyle={{
color:
dollarDiff && dollarDiff.getAmount() <= 0 ? "tomato" : "seagreen",
color: dollarDiff && dollarDiff.getAmount() <= 0 ? "tomato" : "seagreen"
}}
value={dollarDiff && dollarDiff.toFormat()}
/>
</div>
<div style={{ display: "flex" }}>
<Statistic
title="DB Price Total"
style={{ margin: "0rem .5rem" }}
value={dbPriceSum.toFormat()}
/>
<Statistic
title="Actual Price Total"
style={{ margin: "0rem .5rem" }}
value={actPriceSum.toFormat()}
/>
</div>
</Space>
<Space>
<Statistic title="DB Price Total" style={{ margin: "0rem .5rem" }} value={dbPriceSum.toFormat()} />
<Statistic title="Actual Price Total" style={{ margin: "0rem .5rem" }} value={actPriceSum.toFormat()} />
</Space>
</div>
);
}

View File

@@ -1,6 +1,6 @@
import { CloudUploadOutlined } from "@ant-design/icons";
import { Alert, Input, Space, Table } from "antd";
import dayjs from '../../../util/day.js';
import { CloudUploadOutlined, WarningOutlined } from "@ant-design/icons";
import { Alert, Input, Space, Table, Tooltip } from "antd";
import dayjs from "../../../util/day.js";
import React, { useState } from "react";
import { useMemo } from "react";
import { connect } from "react-redux";
@@ -8,11 +8,7 @@ import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import ipcTypes from "../../../ipc.types";
import { setSelectedJobId } from "../../../redux/application/application.actions";
import {
selectReportData,
selectReportLoading,
selectScorecard,
} from "../../../redux/reporting/reporting.selectors";
import { selectReportData, selectReportLoading, selectScorecard } from "../../../redux/reporting/reporting.selectors";
import { alphaSort } from "../../../util/sorters";
import VehicleGroupAlertAtom from "../../atoms/vehicle-group-alert/vehicle-group-alert.atom";
import GroupVerifySwitch from "../group-verify-switch/group-verify-switch.component";
@@ -22,18 +18,13 @@ const { ipcRenderer } = window;
const mapStateToProps = createStructuredSelector({
reportingLoading: selectReportLoading,
reportData: selectReportData,
scoreCard: selectScorecard,
scoreCard: selectScorecard
});
const mapDispatchToProps = (dispatch) => ({
setSelectedJobId: (id) => dispatch(setSelectedJobId(id)),
setSelectedJobId: (id) => dispatch(setSelectedJobId(id))
});
export function ReportingJobsListMolecule({
scoreCard,
reportingLoading,
reportData,
setSelectedJobId,
}) {
export function ReportingJobsListMolecule({ scoreCard, reportingLoading, reportData, setSelectedJobId }) {
const [searchText, setSearchText] = useState("");
const columns = [
@@ -54,7 +45,7 @@ export function ReportingJobsListMolecule({
</Space>
</Link>
),
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no),
sorter: (a, b) => alphaSort(a.clm_no, b.clm_no)
},
{
title: "R4P",
@@ -62,86 +53,86 @@ export function ReportingJobsListMolecule({
key: "close_date",
render: (text, record) => dayjs(record.close_date).format("MM/DD/YYYY"),
defaultSortOrder: "ascend",
sorter: (a, b) =>
dayjs(a.close_date).unix() - dayjs(b.close_date).unix(),
sorter: (a, b) => dayjs(a.close_date).unix() - dayjs(b.close_date).unix()
},
{
title: "Ins Co.",
dataIndex: "ins_co_nm",
key: "ins_co_nm",
sorter: (a, b) => alphaSort(a.ins_co_nm, b.ins_co_nm),
sorter: (a, b) => alphaSort(a.ins_co_nm, b.ins_co_nm)
},
{
title: "First Name",
dataIndex: "ownr_fn",
key: "ownr_fn",
sorter: (a, b) => alphaSort(a.ownr_fn, b.ownr_fn),
sorter: (a, b) => alphaSort(a.ownr_fn, b.ownr_fn)
},
{
title: "Last Name",
dataIndex: "ownr_ln",
key: "ownr_ln",
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln),
sorter: (a, b) => alphaSort(a.ownr_ln, b.ownr_ln)
},
{
title: "Vehicle",
dataIndex: "vehicle",
key: "vehicle",
render: (text, record) => (
<VehicleGroupAlertAtom job={record} showGroup />
),
render: (text, record) => <VehicleGroupAlertAtom job={record} showGroup />
},
{
title: "Database Price Sum",
dataIndex: "dbPriceSum",
key: "dbPriceSum",
sorter: (a, b) => a.dbPriceSum.getAmount() - b.dbPriceSum.getAmount(),
render: (text, record) => record.dbPriceSum.toFormat(),
render: (text, record) => record.dbPriceSum.toFormat()
},
{
title: "Actual Price Sum",
dataIndex: "actPriceSum",
key: "actPriceSum",
sorter: (a, b) => a.actPriceSum.getAmount() - b.actPriceSum.getAmount(),
render: (text, record) => record.actPriceSum.toFormat(),
render: (text, record) => record.actPriceSum.toFormat()
},
{
title: "Group Verified?",
dataIndex: "group_verified",
key: "group_verified",
sorter: (a, b) => a.group_verified - b.group_verified,
render: (text, record) => <GroupVerifySwitch job={record} />,
render: (text, record) => <GroupVerifySwitch job={record} />
},
{
title: "$ (Act./Target)",
dataIndex: "jobRpsDollars",
key: "jobRpsDollars",
render: (text, record) => (
<span
<Space
style={{
color: record.jobRpsPc > record.jobTarget ? "seagreen" : "tomato",
color: record.jobRpsPc > record.jobTarget ? "seagreen" : "tomato"
}}
>
{`${record.jobRpsDollars.toFormat()} / ${record.expectedRpsDollars.toFormat()}`}
</span>
),
{record.v_mileage < 20000 && (
<Tooltip title="Vehicle is under 20,000 KMs. No expected savings.">
<WarningOutlined style={{ color: "tomato" }} />
</Tooltip>
)}
</Space>
)
},
{
title: "% (Act./Target)",
dataIndex: "price_diff_pc",
key: "price_diff_pc",
render: (text, record) => (
<span
<Space
style={{
color: record.jobRpsPc > record.jobTarget ? "seagreen" : "tomato",
color: record.jobRpsPc > record.jobTarget ? "seagreen" : "tomato"
}}
>
{`${(record.jobRpsPc * 100 || 0).toFixed(1)}% / ${(
record.jobTarget * 100
).toFixed(1)}%`}
</span>
),
},
{`${(record.jobRpsPc * 100 || 0).toFixed(1)}% / ${(record.jobTarget * 100).toFixed(1)}%`}
</Space>
)
}
];
const data =
@@ -156,10 +147,7 @@ export function ReportingJobsListMolecule({
)
: reportData;
const ErroredRecords = useMemo(
() => reportData.filter((r) => r.requires_reimport).length,
[reportData]
);
const ErroredRecords = useMemo(() => reportData.filter((r) => r.requires_reimport).length, [reportData]);
return (
<div>
@@ -177,7 +165,7 @@ export function ReportingJobsListMolecule({
onSearch={(val) => {
ipcRenderer.send(ipcTypes.app.toMain.track, {
event: "REPORTS_LIST_SEARCH",
query: val,
query: val
});
setSearchText(val);
}}
@@ -192,26 +180,20 @@ export function ReportingJobsListMolecule({
pagination={false}
dataSource={data}
scroll={{
x: true,
x: true
}}
summary={() => (
<Table.Summary.Row>
<Table.Summary.Cell index={0}>
<strong>Totals</strong>
</Table.Summary.Cell>
<Table.Summary.Cell
index={1}
>{`${data.length} record(s)`}</Table.Summary.Cell>
<Table.Summary.Cell index={1}>{`${data.length} record(s)`}</Table.Summary.Cell>
<Table.Summary.Cell index={2}></Table.Summary.Cell>
<Table.Summary.Cell index={3}></Table.Summary.Cell>
<Table.Summary.Cell index={4}></Table.Summary.Cell>
<Table.Summary.Cell index={5}></Table.Summary.Cell>
<Table.Summary.Cell index={6}>
{scoreCard && scoreCard.allJobsSumDbPrice.toFormat()}
</Table.Summary.Cell>
<Table.Summary.Cell index={7}>
{scoreCard && scoreCard.allJobsSumActPrice.toFormat()}
</Table.Summary.Cell>
<Table.Summary.Cell index={6}>{scoreCard && scoreCard.allJobsSumDbPrice.toFormat()}</Table.Summary.Cell>
<Table.Summary.Cell index={7}>{scoreCard && scoreCard.allJobsSumActPrice.toFormat()}</Table.Summary.Cell>
<Table.Summary.Cell index={8}></Table.Summary.Cell>
</Table.Summary.Row>
)}
@@ -220,7 +202,4 @@ export function ReportingJobsListMolecule({
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ReportingJobsListMolecule);
export default connect(mapStateToProps, mapDispatchToProps)(ReportingJobsListMolecule);

View File

@@ -34,7 +34,8 @@ export function JobsDetailOrganism({ selectedJobId, setSelectedJobTargetPc }) {
group: data.jobs_by_pk && data.jobs_by_pk.group,
v_age: data.jobs_by_pk && data.jobs_by_pk.v_age,
close_date: data.jobs_by_pk && data.jobs_by_pk.close_date,
v_mileage: data.jobs_by_pk && data.jobs_by_pk.v_mileage
v_mileage: data.jobs_by_pk && data.jobs_by_pk.v_mileage,
job: data.jobs_by_pk
});
}, [data, setSelectedJobTargetPc]);

View File

@@ -126,6 +126,7 @@ export const QUERY_JOB_BY_CLM_NO = gql`
jobs(where: { clm_no: { _eq: $clm_no } }) {
id
close_date
requires_reimport
joblines {
id
act_price

File diff suppressed because it is too large Load Diff

View File

@@ -223,5 +223,6 @@
"MACAN",
"FJ CRUISER",
"BRONCO SPORT",
"BRONCO SPORT BADLANDS"
"BRONCO SPORT BADLANDS",
"ESCALADE"
]

View File

@@ -29,9 +29,9 @@ export const setSelectedJobId = (jobId) => ({
type: ApplicationActionTypes.SET_SELECTED_JOB_ID,
payload: jobId
});
export const setSelectedJobTargetPc = ({ group, v_age, close_date, v_mileage }) => ({
export const setSelectedJobTargetPc = ({ group, v_age, close_date, v_mileage, job }) => ({
type: ApplicationActionTypes.SET_SELECTED_JOB_TARGET_PC,
payload: { group, v_age, close_date, v_mileage }
payload: { group, v_age, close_date, v_mileage, job }
});
export const setSelectedJobTargetPcSuccess = (pct) => ({

View File

@@ -7,10 +7,10 @@ export function* onSetTargetPc() {
yield takeLatest(ApplicationActionTypes.SET_SELECTED_JOB_TARGET_PC, CalculateTarget);
}
export function* CalculateTarget({ payload }) {
const { group, v_age, close_date, v_mileage } = payload;
const { group, v_age, close_date, v_mileage, job } = payload;
const targets = yield select((state) => state.user.bodyshop.targets);
yield put(setSelectedJobTargetPcSuccess(GetJobTarget({ group, v_age, targets, close_date, v_mileage })));
yield put(setSelectedJobTargetPcSuccess(GetJobTarget({ group, v_age, targets, close_date, v_mileage, job })));
// const targetsForGroup = targets.filter((t) => t.group === group);
// if (!targetsForGroup) return 0;
// const targetPc = targetsForGroup.filter(

View File

@@ -97,7 +97,7 @@ export function* handleCalculateScoreCard({ payload: jobs }) {
});
const targets = yield select((state) => state.user.bodyshop.targets);
const groups = yield select((state) => state.user.bodyshop.groups);
//const groups = yield select((state) => state.user.bodyshop.groups);
//Check to ensure every job has a group.
const jobsWithNoGroup = jobs
@@ -125,9 +125,12 @@ export function* handleCalculateScoreCard({ payload: jobs }) {
allJobsSumActPrice: Dinero(),
currentRpsPc: 0,
targetRpsPc: 0,
scatterChart: _.sortBy(groups, [(group) => group.toLowerCase()], ["desc"]).reduce((acc, val) => {
return { ...acc, [val]: [] };
}, {})
scatterChart: _.sortBy(_.uniq(jobs.map((j) => j.group)), [(group) => group.toLowerCase()], ["desc"]).reduce(
(acc, val) => {
return { ...acc, [val]: [] };
},
{}
)
};
//Get the RPS on a per job basis.
@@ -139,7 +142,8 @@ export function* handleCalculateScoreCard({ payload: jobs }) {
v_age: job.v_age,
targets,
close_date: job.close_date,
v_mileage: job.v_mileage
v_mileage: job.v_mileage,
job: job
});
scoreCard.shopRpsTotalDollars = scoreCard.shopRpsTotalDollars.add(jobRpsDollars);
const expectedRpsDollars = dbPriceSum.percentage(jobTarget * 100);

View File

@@ -1,7 +1,8 @@
import { V3TargetAndGroupFinder } from "../ipc/ipc-estimate-utils";
import { store } from "../redux/store";
import { WhichRulesetToApply } from "./constants";
export default function GetJobTarget({ group, v_age, targets, close_date, v_mileage }) {
export default function GetJobTarget({ group, v_age, targets, close_date, v_mileage, job }) {
// //Old Validation
// const targetsForGroup = targets.filter((t) => t.group === group);
// console.log(
@@ -27,15 +28,21 @@ export default function GetJobTarget({ group, v_age, targets, close_date, v_mile
//V2 Check
const newTargets = store.getState().user.targets;
const rulesToApply = WhichRulesetToApply(close_date);
const newTargetsForGroup = newTargets.filter((t) => t.name === rulesToApply && t.group === group);
if (rulesToApply === "V3") {
const v3Target = V3TargetAndGroupFinder(job)
return v3Target?.target || 0.023;
} else {
const newTargetsForGroup = newTargets.filter((t) => t.name === rulesToApply && t.group === group);
if (!newTargetsForGroup) return 0;
const newTargetPc = newTargetsForGroup.filter((t) => t.ageGte <= v_age && (t.ageLt ? t.ageLt > v_age : true));
if (!newTargetsForGroup) return 0;
const newTargetPc = newTargetsForGroup.filter((t) => t.ageGte <= v_age && (t.ageLt ? t.ageLt > v_age : true));
if (newTargetPc.length === 0) return 1;
else if (newTargetPc.length === 1) return newTargetPc[0].target;
else {
return 1;
if (newTargetPc.length === 0) return 1;
else if (newTargetPc.length === 1) return newTargetPc[0].target;
else {
return 1;
}
}
}

View File

@@ -1,31 +1,28 @@
import dayjs from './day.js'
import dayjs from "./day.js";
export const DateFormat = "MM/DD/YYYY";
const RuleSets = [
{
title: "V1",
range: [dayjs("2010-01-01"), dayjs("2023-04-01")],
range: [dayjs("2010-01-01"), dayjs("2023-04-01")]
},
{
title: "V2",
range: [dayjs("2023-04-01"), dayjs("2040-01-01")],
range: [dayjs("2023-04-01"), dayjs("2024-09-01")]
},
{
title: "V3",
range: [dayjs("2024-09-01"), dayjs("2040-01-01")]
}
];
//TODO: Verify that this doesnt need to be reversed.
export function ChangeOfRuleSet({
prevDateMoment = dayjs(),
newDateMoment = dayjs(),
}) {
//TODO: Verify that this doesnt need to be reversed.
export function ChangeOfRuleSet({ prevDateMoment = dayjs(), newDateMoment = dayjs() }) {
const prevRuleSet = RuleSets.find(
(r) =>
prevDateMoment.isSameOrAfter(r.range[0]) &&
prevDateMoment.isBefore(r.range[1])
(r) => prevDateMoment.isSameOrAfter(r.range[0]) && prevDateMoment.isBefore(r.range[1])
);
const newRuleSet = RuleSets.find(
(r) =>
newDateMoment.isSameOrAfter(r.range[0]) &&
newDateMoment.isBefore(r.range[1])
(r) => newDateMoment.isSameOrAfter(r.range[0]) && newDateMoment.isBefore(r.range[1])
);
return prevRuleSet?.title !== newRuleSet?.title;
@@ -33,10 +30,7 @@ export function ChangeOfRuleSet({
export function WhichRulesetToApply(close_date) {
const DateMoment = close_date ? dayjs(close_date) : dayjs();
const newRuleSet = RuleSets.find(
(r) =>
DateMoment.isSameOrAfter(r.range[0]) && DateMoment.isBefore(r.range[1])
);
const newRuleSet = RuleSets.find((r) => DateMoment.isSameOrAfter(r.range[0]) && DateMoment.isBefore(r.range[1]));
//console.log("Using ruleset:", newRuleSet);
return newRuleSet?.title;