Skip to content

Commit

Permalink
Merge pull request #1320 from betagouv/fix/certs
Browse files Browse the repository at this point in the history
[fix] Attestations
  • Loading branch information
nmrgt authored Apr 16, 2021
2 parents 3b5aad3 + b5f1eef commit d09464d
Show file tree
Hide file tree
Showing 15 changed files with 117 additions and 138 deletions.
13 changes: 13 additions & 0 deletions api/db/migrations/20210415162735-carpool_identities_add_index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';
/**
* Cast all foreign keys *_id as integer to match PostgreSQL types
* Current type is 'varchar' as fkeys were migrated from MongoDB
* as a toString() of ObjectID objects.
*/
var { createMigration } = require('../helpers/createMigration');

var { setup, up, down } = createMigration(['carpool/20210415162735-carpool_identities_add_index'], __dirname);

exports.setup = setup;
exports.up = up;
exports.down = down;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DROP INDEX IF EXISTS carpool.identities_created_at_idx;
DROP INDEX IF EXISTS carpool.identities_phone_trunc_travel_pass_name_travel_pass_user_id_idx;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
CREATE INDEX
IF NOT EXISTS identities_created_at_idx
ON carpool.identities (created_at);

CREATE INDEX
IF NOT EXISTS identities_phone_trunc_travel_pass_name_travel_pass_user_id_idx
ON carpool.identities (phone_trunc, travel_pass_name, travel_pass_user_id);
7 changes: 5 additions & 2 deletions api/providers/pdfcert/src/PdfCertProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,11 @@ export class PdfCertProvider implements PdfCertProviderInterface {
color: rgb(0.95, 0.95, 0.95),
});

this.text('Points :', { x: 60, y: totalY, font: this.fonts.bold });
this.text(`${data.data.total_pt || 0}`, { x: 110, y: totalY, font: this.fonts.bold });
this.text('Distance :', { x: 60, y: totalY, font: this.fonts.bold });
this.text(`${data.data.total_km || 0} km`, { x: 120, y: totalY, font: this.fonts.bold });

this.text('Points :', { x: 180, y: totalY, font: this.fonts.bold });
this.text(`${data.data.total_pt || 0}`, { x: 230, y: totalY, font: this.fonts.bold });

this.text('Reste à charge :', { x: 330, y: totalY, font: this.fonts.bold });
this.text(`${this.currency(data.data.total_rm)} €`, { x: 440, y: totalY, font: this.fonts.bold });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ export interface IdentityMetaInterface {
operator_id: number;
}

export interface findUuidOptions {
generate?: boolean;
interval?: number;
}

export interface IdentityRepositoryProviderInterface {
create(identity: IdentityInterface, meta: IdentityMetaInterface): Promise<{ _id: number; uuid: string }>;
delete(_id: number): Promise<void>;
findUuid(identity: IdentityInterface, meta: IdentityMetaInterface): Promise<string>;
findUuid(identity: IdentityInterface, meta: IdentityMetaInterface, options?: findUuidOptions): Promise<string>;
}

export abstract class IdentityRepositoryProviderInterfaceResolver implements IdentityRepositoryProviderInterface {
Expand All @@ -22,7 +27,11 @@ export abstract class IdentityRepositoryProviderInterfaceResolver implements Ide
throw new Error('Not implemented');
}

public async findUuid(identity: IdentityInterface, meta: IdentityMetaInterface): Promise<string> {
public async findUuid(
identity: IdentityInterface,
meta: IdentityMetaInterface,
options?: findUuidOptions,
): Promise<string> {
throw new Error('Not implemented');
}
}
27 changes: 16 additions & 11 deletions api/services/carpool/src/providers/IdentityRepositoryProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
IdentityRepositoryProviderInterface,
IdentityRepositoryProviderInterfaceResolver,
IdentityMetaInterface,
findUuidOptions,
} from '../interfaces/IdentityRepositoryProviderInterface';

/*
Expand Down Expand Up @@ -55,7 +56,7 @@ export class IdentityRepositoryProvider implements IdentityRepositoryProviderInt
identity.travel_pass_name,
identity.travel_pass_user_id,
identity.over_18,
await this.findUuid(identity, meta),
await this.findUuid(identity, meta, { generate: true, interval: 30 }),
],
});

Expand All @@ -79,7 +80,13 @@ export class IdentityRepositoryProvider implements IdentityRepositoryProviderInt
return;
}

public async findUuid(identity: IdentityInterface, meta: IdentityMetaInterface): Promise<string> {
public async findUuid(
identity: IdentityInterface,
meta: IdentityMetaInterface,
options?: findUuidOptions,
): Promise<string> {
const opts: findUuidOptions = { generate: false, interval: 0, ...options };

/*
* 1. Select uuid from the exact phone number
* 2. Select uuid from the phone_trunc and operator_user_id
Expand All @@ -92,27 +99,25 @@ export class IdentityRepositoryProvider implements IdentityRepositoryProviderInt
(
SELECT created_at as datetime, uuid FROM ${this.table}
WHERE phone IS NOT NULL and phone = $1::varchar
AND created_at >= (NOW() - '30 days'::interval)::timestamp
${opts.interval > 0 ? `AND created_at >= (NOW() - '${opts.interval} days'::interval)::timestamp` : ''}
ORDER BY created_at DESC LIMIT 1
) UNION
(
SELECT ci.created_at as datetime, ci.uuid FROM ${this.table} as ci
JOIN carpool.carpools AS cp ON cp.identity_id = ci._id
WHERE ci.phone_trunc IS NOT NULL AND ci.phone_trunc = $2::varchar
AND cp.operator_id = $3::int AND ci.operator_user_id = $4::varchar
AND ci.created_at >= (NOW() - '30 days'::interval)::timestamp
${opts.interval > 0 ? `AND ci.created_at >= (NOW() - '${opts.interval} days'::interval)::timestamp` : ''}
ORDER BY ci.created_at DESC LIMIT 1
) UNION
(
SELECT created_at as datetime, uuid FROM ${this.table}
WHERE phone_trunc IS NOT NULL AND phone_trunc = $2::varchar
AND travel_pass_name = $5::varchar AND travel_pass_user_id = $6::varchar
AND created_at >= (NOW() - '30 days'::interval)::timestamp
${opts.interval > 0 ? `AND created_at >= (NOW() - '${opts.interval} days'::interval)::timestamp` : ''}
ORDER BY created_at DESC LIMIT 1
) UNION
(
SELECT to_timestamp(0)::timestamp as datetime, uuid_generate_v4() as uuid
)
${opts.generate ? ' UNION (SELECT to_timestamp(0)::timestamp as datetime, uuid_generate_v4() as uuid )' : ''}
ORDER BY datetime DESC
LIMIT 1
`,
Expand All @@ -126,10 +131,10 @@ export class IdentityRepositoryProvider implements IdentityRepositoryProviderInt
],
};

const result = await this.connection.getClient().query(query);
const result = await this.connection.getClient().query<{ datetime: Date; uuid: string }>(query);

if (result.rowCount !== 1) {
throw new Error('Cant find uuid for this person');
if (!result.rowCount) {
throw new Error('Cannot find UUID for this person');
}

return result.rows[0].uuid;
Expand Down
18 changes: 7 additions & 11 deletions api/services/certificate/src/actions/CreateCertificateAction.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { upperFirst, omit } from 'lodash';
import { handler, KernelInterfaceResolver, ConfigInterfaceResolver } from '@ilos/common';
import { handler, KernelInterfaceResolver, ConfigInterfaceResolver, ContextType } from '@ilos/common';
import { Action as AbstractAction } from '@ilos/core';
import { DateProviderInterfaceResolver } from '@pdc/provider-date';
import {
environmentBlacklistMiddleware,
copyGroupIdAndApplyGroupPermissionMiddlewares,
} from '@pdc/provider-middleware';
import { copyGroupIdAndApplyGroupPermissionMiddlewares } from '@pdc/provider-middleware';

import { handlerConfig, ParamsInterface, ResultInterface } from '../shared/certificate/create.contract';
import { alias } from '../shared/certificate/create.schema';
Expand All @@ -21,7 +18,6 @@ import { IdentityIdentifiersInterface } from '../shared/certificate/common/inter
@handler({
...handlerConfig,
middlewares: [
environmentBlacklistMiddleware('production'),
['validate', alias],
...copyGroupIdAndApplyGroupPermissionMiddlewares({
operator: 'operator.certificate.create',
Expand All @@ -40,13 +36,13 @@ export class CreateCertificateAction extends AbstractAction {
super();
}

public async handle(params: ParamsInterface): Promise<WithHttpStatus<ResultInterface>> {
public async handle(params: ParamsInterface, context: ContextType): Promise<WithHttpStatus<ResultInterface>> {
const { identity, tz, operator_id, start_at, end_at, positions } = this.castParams(params);

// fetch the data for this identity and operator and map to template object
// get the last available UUID for the person. They can have many
const personUUID = await this.findPerson(identity, operator_id);
const operator = await this.findOperator(operator_id);
const operator = await this.findOperator(operator_id, context);

// fetch the data for this identity and operator and map to template object
const certs = await this.findTrips({ identity, operator_id, tz, start_at, end_at, positions });
Expand Down Expand Up @@ -102,13 +98,13 @@ export class CreateCertificateAction extends AbstractAction {
);
}

private async findOperator(operator_id: number): Promise<any> {
private async findOperator(operator_id: number, context: ContextType): Promise<any> {
return this.kernel.call(
'operator:quickfind',
{ _id: operator_id, thumbnail: false },
{
...context,
channel: { service: 'certificate' },
call: { user: { permissions: ['operator.read'] } },
},
);
}
Expand All @@ -125,7 +121,7 @@ export class CreateCertificateAction extends AbstractAction {
* Will be refactored when the ID engine is up and running
*/
private castParams(params: ParamsInterface): ParamsInterface & { start_at: Date; end_at: Date } {
const origin = new Date('2020-01-01T00:00:00+0100'); // Europe/Paris
const origin = new Date('2019-01-01T00:00:00+0100'); // Europe/Paris
const end_at_max = new Date().getTime() - this.config.get('delays.create.end_at_buffer', 6) * 86400000;

let { start_at, end_at } = params;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { Action as AbstractAction } from '@ilos/core';
import { handler } from '@ilos/common';
import {
environmentBlacklistMiddleware,
hasPermissionMiddleware,
channelServiceWhitelistMiddleware,
} from '@pdc/provider-middleware';
import { hasPermissionMiddleware, channelServiceWhitelistMiddleware } from '@pdc/provider-middleware';

import { CertificateRepositoryProviderInterfaceResolver } from '../interfaces/CertificateRepositoryProviderInterface';
import { handlerConfig, ResultInterface, ParamsInterface } from '../shared/certificate/find.contract';
Expand All @@ -13,7 +9,6 @@ import { alias } from '../shared/certificate/find.schema';
@handler({
...handlerConfig,
middlewares: [
environmentBlacklistMiddleware('production'),
hasPermissionMiddleware('common.certificate.find'),
channelServiceWhitelistMiddleware('proxy'),
['validate', alias],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { handler } from '@ilos/common';
import { Action as AbstractAction } from '@ilos/core';
import {
environmentBlacklistMiddleware,
copyGroupIdAndApplyGroupPermissionMiddlewares,
} from '@pdc/provider-middleware';
import { copyGroupIdAndApplyGroupPermissionMiddlewares } from '@pdc/provider-middleware';

import { CertificateInterface } from '../shared/certificate/common/interfaces/CertificateInterface';
import { CertificateRepositoryProviderInterfaceResolver } from '../interfaces/CertificateRepositoryProviderInterface';
Expand All @@ -18,7 +15,6 @@ import { alias } from '../shared/certificate/list.schema';
@handler({
...handlerConfig,
middlewares: [
environmentBlacklistMiddleware('production'),
['validate', alias],
...copyGroupIdAndApplyGroupPermissionMiddlewares({
operator: 'operator.certificate.list',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,10 @@ export class CarpoolPgRepositoryProvider implements CarpoolRepositoryProviderInt
)
SELECT
year AS y,
month AS m,
COUNT(*) AS trips,
SUM(km) AS km,
year::int AS y,
month::int AS m,
COUNT(*)::int AS trips,
SUM(km)::real AS km,
GREATEST(SUM(rac), 0)::real AS rm -- cast to 4-byte float
FROM merged
GROUP BY year, month
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ export class CertificateListComponent extends DestroyObservable implements OnIni
console.error(err);
throw err;
}),
catchHttpStatus(401, (err) => {
this.toastr.error('Non connecté');
throw err;
}),
catchHttpStatus(403, (err) => {
this.toastr.error('Action non autorisée');
throw err;
}),
catchHttpStatus(404, (err) => {
this.toastr.error('Identité non trouvée');
throw err;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ <h3>Plus d'informations</h3>
<ul>
<li>
<a
href="https://registre-preuve-de-covoiturage.gitbook.io/produit/boite-a-outils/attestations-de-covoiturage"
href="https://doc.covoiturage.beta.gouv.fr/employeurs-et-employes-developper-du-forfait-mobilite-durables/telecharger-les-attestations-operateurs"
target="_blank"
rel="noopener noreferrer"
>Accéder à la documentation</a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ <h3>Données de l'attestation</h3>
</td>
</tr>

<tr *ngIf="data.total_km !== undefined">
<td>Distance</td>
<td>{{ data.total_km }} kilomètres</td>
</tr>

<tr *ngIf="data.total_point !== undefined">
<td>Points</td>
<td>{{ data.total_point }} points</td>
Expand Down
Loading

0 comments on commit d09464d

Please sign in to comment.