Skip to content

Commit

Permalink
fix(campaign): PMGF 2025 (#2762)
Browse files Browse the repository at this point in the history
* feat(policy): add new PMGF policy

* feat(policy): update end date description

* mv migration to IDFM PR

* add campaign

---------

Co-authored-by: Julien Parmentier <[email protected]>
  • Loading branch information
jonathanfallon and P3rceval authored Jan 21, 2025
1 parent 8131bbf commit e9d277d
Show file tree
Hide file tree
Showing 6 changed files with 469 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const description = `<div _ngcontent-fyn-c231="" id="summary" class="campaignSummaryText-content-text">
<p>Campagne d'incitation au covoiturage du <b>24 octobre 2022 au 31 décembre 2024</b></p>
<p>Campagne d'incitation au covoiturage du <b>24 octobre 2022 au 31 décembre 2025</b></p>
<p>Cette campagne est limitée à <b>400 000 euros</b>.</p>
<p>Les <b>conducteurs</b> effectuant un trajet jusqu'à 30 km sont incités selon les règles suivantes :</p>
<ul>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/* eslint-disable max-len */
export const description =
`<div _ngcontent-fyn-c231="" id="summary" class="campaignSummaryText-content-text">
export const description = `<div _ngcontent-fyn-c231="" id="summary" class="campaignSummaryText-content-text">
<p>Campagne d'incitation au covoiturage du <b> 01 avril 2024 au 31 décembre 2024</b></p>
<p>Campagne d'incitation au covoiturage du <b> 01 avril 2024 au 31 décembre 2025</b></p>
<p>Cette campagne est limitée à <b>242 446,00 €</b>.</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/* eslint-disable max-len */
export const description = `<div _ngcontent-fyn-c231="" id="summary" class="campaignSummaryText-content-text">
<p>Campagne d'incitation au covoiturage du <b> 01 janvier 2025 au 31 décembre 2025</b></p>
<p>Cette campagne est limitée à <b>242 446,00€</b>.</p>
<p>
Les <b> conducteurs </b> effectuant un trajet entre 5 et 40 km
au départ ou à l'arrivée du Pôle Métropolitain Genevois
sont incités selon les règles suivantes.
</p>
<p><strong>Départ <u>et</u> Arrivée au sein du PMGF :</strong></p>
<ul>
<li><b>De 5 à 20 km : 1,50 € pour le conducteur par trajet&nbsp;;</b></li>
<li><b>De 20 à 40 km : 1,50 € pour le conducteur par trajet + 0,125 € par passager par kilomètre supplémentaire&nbsp;;</b></li>
<li><b>Au delà de 40 km : 4,00 € pour le conducteur par trajet et par passager.</b></li>
</ul>
<p><strong>Départ <u>ou</u> Arrivée au sein du PMGF :</strong></p>
<ul>
<li><b>De 5 à 20 km : 0,50 € pour le conducteur par trajet&nbsp;;</b></li>
<li><b>De 20 à 40 km : 0,50 € pour le conducteur par trajet + 0,125 € par passager par kilomètre supplémentaire&nbsp;;</b></li>
<li><b>Au delà de 40 km : 3,00 € pour le conducteur par trajet et par passager.</b></li>
</ul>
<p>Les restrictions suivantes seront appliquées :</p>
<ul>
<li><b>50€ maximum pour le conducteur par mois.</b></li>
</ul>
<p>
La campagne est éligible à l'opérateur de covoiturage
Blablacar Daily
proposant des preuves de classe <b>B</b> ou <b>C</b>
</p>
</div>`;
173 changes: 173 additions & 0 deletions api/src/pdc/services/policy/engine/policies/20250101_PMGFxATMB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import { getOperatorsAt, TimestampedOperators } from "@/pdc/services/policy/engine/helpers/getOperatorsAt.ts";
import { isOperatorClassOrThrow } from "@/pdc/services/policy/engine/helpers/isOperatorClassOrThrow.ts";
import { isOperatorOrThrow } from "@/pdc/services/policy/engine/helpers/isOperatorOrThrow.ts";
import {
LimitTargetEnum,
watchForGlobalMaxAmount,
watchForPersonMaxAmountByMonth,
} from "@/pdc/services/policy/engine/helpers/limits.ts";
import { onDistanceRange, onDistanceRangeOrThrow } from "@/pdc/services/policy/engine/helpers/onDistanceRange.ts";
import { perKm, perSeat } from "@/pdc/services/policy/engine/helpers/per.ts";
import { startsAndEndsAt } from "@/pdc/services/policy/engine/helpers/position.ts";
import { startsOrEndsAtOrThrow } from "@/pdc/services/policy/engine/helpers/startsOrEndsAtOrThrow.ts";
import { AbstractPolicyHandler } from "@/pdc/services/policy/engine/policies/AbstractPolicyHandler.ts";
import { RunnableSlices } from "@/pdc/services/policy/interfaces/engine/PolicyInterface.ts";
import {
OperatorsEnum,
PolicyHandlerInterface,
PolicyHandlerParamsInterface,
PolicyHandlerStaticInterface,
StatelessContextInterface,
TerritoryCodeEnum,
TerritorySelectorsInterface,
} from "@/pdc/services/policy/interfaces/index.ts";
import { description } from "./20240401_PMGFxATMB.html.ts";

// INSERT INTO policy.policies (territory_id, start_date, end_date, name, unit, status, handler, max_amount)
// VALUES (
// 36102,
// '2025-01-01T00:00:00+0200',
// '2025-12-31T00:00:00+0100',
// 'PMGFxATMB 2025',
// 'euro',
// 'draft',
// 'pmgf_x_atmb_2025',
// 24244600
// );

export const PMGFxATMB2025: PolicyHandlerStaticInterface = class extends AbstractPolicyHandler
implements PolicyHandlerInterface {
static readonly id = "pmgf_atmb_2025";

protected operator_class = ["B", "C"];

protected readonly operators: TimestampedOperators = [
{
date: new Date("2025-01-01T00:00:00+0200"),
operators: [OperatorsEnum.BLABLACAR_DAILY],
},
];

constructor(public max_amount: number) {
super();
this.limits = [
[
"ddf5f99c-a40c-413c-bbea-927861cbb2f2",
50_00,
watchForPersonMaxAmountByMonth,
LimitTargetEnum.Driver,
],
[
"cd6a2dd5-5e45-49fe-8618-09d3e8d9c679",
this.max_amount,
watchForGlobalMaxAmount,
], // required
];
}

/**
* Trajets intra-AOM (origine ET destination dans l'AOM)
* - 1,50€ par passager de 5 à 20 km
* - 1,50€ par passager + 0,125€ pour les km > 20 km
* - limite d'incitation à 40 km
*/
protected internalTripsSlices: RunnableSlices = [
{
start: 5_000,
end: 20_000,
fn: (ctx: StatelessContextInterface) => perSeat(ctx, 150),
},
{
start: 20_000,
end: 150_000,
fn: (ctx: StatelessContextInterface) =>
perSeat(
ctx,
perKm(ctx, { amount: 12.5, offset: 20_000, limit: 40_000 }),
),
},
];

/**
* Trajets extra-AOM (origine OU destination dans l'AOM)
* - 0,50€ par passager de 5 à 20 km
* - 0,50€ par passager + 0,125€ pour les km > 20 km
* - limite d'incitation à 40 km
*/
protected externalTripsSlices: RunnableSlices = [
{
start: 5_000,
end: 20_000,
fn: (ctx: StatelessContextInterface) => perSeat(ctx, 50),
},
{
start: 20_000,
end: 150_000,
fn: (ctx: StatelessContextInterface) =>
perSeat(
ctx,
perKm(ctx, { amount: 12.5, offset: 20_000, limit: 40_000 }),
),
},
];

protected territorySelector: TerritorySelectorsInterface = {
[TerritoryCodeEnum.Mobility]: [
"240100750", // CA du Pays de GEX
"247400690", // CC du Genevois
"200011773", // CC Annemasse-Les Voirons-Agglomération
"200067551", // CA Thonon Agglomération
],
[TerritoryCodeEnum.CityGroup]: [
"240100891", // CA du Pays Bellegardien
"247400724", // CC du Pays Rochois
"200000172", // CC Faucigny-Glières
"247400583", // CC Arve et Salève
],
};

protected getSlices(ctx?: StatelessContextInterface): RunnableSlices {
if (!ctx) return this.internalTripsSlices;
return startsAndEndsAt(ctx, this.territorySelector) ? this.internalTripsSlices : this.externalTripsSlices;
}

protected processExclusions(ctx: StatelessContextInterface) {
isOperatorOrThrow(
ctx,
getOperatorsAt(this.operators, ctx.carpool.datetime),
);
isOperatorClassOrThrow(ctx, this.operator_class);
startsOrEndsAtOrThrow(ctx, this.territorySelector);
onDistanceRangeOrThrow(ctx, { min: 4_999, max: 150_000 });
}

processStateless(ctx: StatelessContextInterface): void {
this.processExclusions(ctx);
super.processStateless(ctx);

// Apply each slice and sum up the results
let amount = 0;
for (const { start, fn } of this.getSlices(ctx)) {
if (onDistanceRange(ctx, { min: start })) {
amount += fn(ctx);
}
}

ctx.incentive.set(amount);
}

params(): PolicyHandlerParamsInterface {
return {
tz: "Europe/Paris",
slices: this.getSlices(),
operators: getOperatorsAt(this.operators),
limits: {
glob: this.max_amount,
},
};
}

describe(): string {
return description;
}
};
Loading

0 comments on commit e9d277d

Please sign in to comment.