Skip to content

Commit

Permalink
feat: add ban ids
Browse files Browse the repository at this point in the history
  • Loading branch information
fufeck committed Apr 10, 2024
1 parent 9551ca5 commit 08cd924
Show file tree
Hide file tree
Showing 14 changed files with 218 additions and 46 deletions.
81 changes: 63 additions & 18 deletions apps/api/src/lib/utils/csv.utils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,51 @@
import { validate } from '@ban-team/validateur-bal';
import { normalize } from '@ban-team/adresses-util/lib/voies';
import { chain, compact, keyBy, min, max } from 'lodash';

import { beautifyUppercased, beautifyNomAlt } from './string.utils';
import { ObjectId } from 'mongodb';
import { PositionTypeEnum } from '@/shared/schemas/position_type.enum';
import { Position } from '@/shared/schemas/position.schema';

interface Row {
parsedValues: Record<string, any>;
additionalValues: any;
localizedValues: any;
isValid: boolean;
}

export function extractIdBanAdresse({
parsedValues,
additionalValues,
}: Row): string | null {
return (
parsedValues.id_ban_adresse ||
additionalValues?.uid_adresse.idBanAdresse ||
null
);
}

export function extractIdBanToponyme({
parsedValues,
additionalValues,
}: Row): string | null {
return (
parsedValues.id_ban_toponyme ||
additionalValues?.uid_adresse.idBanToponyme ||
null
);
}

export function extractCodeCommune({ parsedValues, additionalValues }) {
export function extractCodeCommune({
parsedValues,
additionalValues,
}: Row): string | null {
return (
parsedValues.commune_insee || additionalValues?.cle_interop?.codeCommune
);
}

export function extractPosition(row) {
export function extractPosition(row: Row): Position {
return {
source: row.parsedValues.source || null,
type: row.parsedValues.position || PositionTypeEnum.INCONNUE,
Expand All @@ -22,27 +56,28 @@ export function extractPosition(row) {
};
}

export function extractPositions(rows) {
export function extractPositions(rows: Row[]): Position[] {
return rows
.filter((r) => r.parsedValues.long && r.parsedValues.lat)
.map((r) => extractPosition(r));
}

export function extractDate(row) {
export function extractDate(row: Row): Date | null {
if (row.parsedValues.date_der_maj) {
return new Date(row.parsedValues.date_der_maj);
}
}

export function extractData(rows, codeCommune) {
export function extractData(rows: Row[], codeCommune: string) {
const toponymes = chain(rows)
.filter((r) => r.parsedValues.numero === 99999)
.groupBy((r) => normalize(r.parsedValues.voie_nom))
.map((toponymeRows) => {
.filter((r: Row) => r.parsedValues.numero === 99999)
.groupBy((r: Row) => normalize(r.parsedValues.voie_nom))
.map((toponymeRows: Row[]) => {
const date = extractDate(toponymeRows[0]) || new Date();

return {
_id: new ObjectId(),
banId: extractIdBanToponyme(toponymeRows[0]),
commune: codeCommune,
nom: beautifyUppercased(toponymeRows[0].parsedValues.voie_nom),
nomAlt: toponymeRows[0].localizedValues.voie_nom
Expand All @@ -58,13 +93,14 @@ export function extractData(rows, codeCommune) {
const toponymesIndex = keyBy(toponymes, (t) => normalize(t.nom));

const voies = chain(rows)
.filter((r) => r.parsedValues.numero !== 99999)
.groupBy((r) => normalize(r.parsedValues.voie_nom))
.map((voieRows) => {
.filter((r: Row) => r.parsedValues.numero !== 99999)
.groupBy((r: Row) => normalize(r.parsedValues.voie_nom))
.map((voieRows: Row[]) => {
const dates = compact(voieRows.map((r) => r.parsedValues.date_der_maj));

return {
_id: new ObjectId(),
banId: extractIdBanToponyme(voieRows[0]),
commune: codeCommune,
nom: beautifyUppercased(voieRows[0].parsedValues.voie_nom),
nomAlt: voieRows[0].localizedValues.voie_nom
Expand All @@ -79,14 +115,14 @@ export function extractData(rows, codeCommune) {
const voiesIndex = keyBy(voies, (v) => normalize(v.nom));

const numeros = chain(rows)
.filter((r) => r.parsedValues.numero !== 99999)
.filter((r: Row) => r.parsedValues.numero !== 99999)
.groupBy(
(r) =>
(r: Row) =>
`${r.parsedValues.numero}@@@${r.parsedValues.suffixe}@@@${normalize(
r.parsedValues.voie_nom,
)}`,
)
.map((numeroRows) => {
.map((numeroRows: Row[]) => {
const date = extractDate(numeroRows[0]) || new Date();

const voieString = normalize(numeroRows[0].parsedValues.voie_nom);
Expand All @@ -100,6 +136,7 @@ export function extractData(rows, codeCommune) {
if (toponymeString && !(toponymeString in toponymesIndex)) {
const toponyme = {
_id: new ObjectId(),
banId: extractIdBanToponyme(numeroRows[0]),
commune: codeCommune,
nom: beautifyUppercased(
numeroRows[0].parsedValues.lieudit_complement_nom,
Expand All @@ -117,6 +154,7 @@ export function extractData(rows, codeCommune) {

return {
_id: new ObjectId(),
banId: extractIdBanAdresse(numeroRows[0]),
commune: codeCommune,
voie: voiesIndex[voieString]._id,
toponyme: toponymeString ? toponymesIndex[toponymeString]._id : null,
Expand All @@ -136,17 +174,23 @@ export function extractData(rows, codeCommune) {

export async function extractFromCsv(file: Buffer, codeCommune: string) {
try {
const { rows, parseOk } = await validate(file, { profile: '1.3-relax' });
const {
rows,
parseOk,
}: {
rows: Row[];
parseOk: boolean;
} = await validate(file, { profile: '1.4-relax' });

if (!parseOk) {
return { isValid: false };
}

const accepted = rows.filter(({ isValid }) => isValid);
const rejected = rows.filter(({ isValid }) => !isValid);
const accepted: Row[] = rows.filter(({ isValid }) => isValid);
const rejected: Row[] = rows.filter(({ isValid }) => !isValid);

const communesData = extractData(
accepted.filter((r) => extractCodeCommune(r) === codeCommune),
accepted.filter((r: Row) => extractCodeCommune(r) === codeCommune),
codeCommune,
);

Expand All @@ -159,6 +203,7 @@ export async function extractFromCsv(file: Buffer, codeCommune: string) {
toponymes: communesData.toponymes,
};
} catch (error) {
console.log(error);
return { isValid: false, validationError: error.message };
}
}
4 changes: 4 additions & 0 deletions apps/api/src/modules/base_locale/base_locale.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,13 @@ import { ToponymeModule } from '@/modules/toponyme/toponyme.module';
import { CommuneModule } from './sub_modules/commune/commune.module';
import { PopulateModule } from './sub_modules/populate/populate.module';
import { SearchQueryPipe } from './pipe/search_query.pipe';
import { HttpModule } from '@nestjs/axios';
import { ConfigModule } from '@nestjs/config';

@Module({
imports: [
ConfigModule,
HttpModule,
MongooseModule.forFeature([
{ name: BaseLocale.name, schema: BaseLocaleSchema },
]),
Expand Down
27 changes: 26 additions & 1 deletion apps/api/src/modules/base_locale/base_locale.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
PipelineStage,
} from 'mongoose';
import { uniq, difference, groupBy } from 'lodash';
import { ConfigService } from '@nestjs/config';
import { HttpService } from '@nestjs/axios';

import { BaseLocale } from '@/shared/schemas/base_locale/base_locale.schema';
import { MailerService } from '@/shared/modules/mailer/mailer.service';
Expand Down Expand Up @@ -45,10 +47,14 @@ import { ImportFileBaseLocaleDTO } from './dto/import_file_base_locale.dto';
import { RecoverBaseLocaleDTO } from './dto/recover_base_locale.dto';
import { AllDeletedInBalDTO } from './dto/all_deleted_in_bal.dto';
import { PopulateVoie } from '@/shared/schemas/voie/voie.populate';
import { catchError, firstValueFrom } from 'rxjs';
import { AxiosError } from 'axios';

@Injectable()
export class BaseLocaleService {
constructor(
private configService: ConfigService,
private readonly httpService: HttpService,
@InjectModel(BaseLocale.name) private baseLocaleModel: Model<BaseLocale>,
private readonly mailerService: MailerService,
@Inject(forwardRef(() => VoieService))
Expand Down Expand Up @@ -109,11 +115,29 @@ export class BaseLocaleService {
return query.lean().exec();
}

public async getIdBanCommune(codeCommune: string): Promise<string> {
const banApiUrl = this.configService.get<string>('BAN_API_URL');
const url = `${banApiUrl}/api/district/cog/${codeCommune}`;

const { data } = await firstValueFrom(
await this.httpService.get<any>(url).pipe(
catchError((error: AxiosError) => {
console.error('error', error.response.data);
throw error;
}),
),
);

return data.response[0].id;
}

async createOne(
createInput: CreateBaseLocaleDTO,
sendMail: boolean = true,
): Promise<BaseLocale> {
const banId: string = await this.getIdBanCommune(createInput.commune);
const newBaseLocale = await this.baseLocaleModel.create({
banId,
...createInput,
token: generateBase62String(20),
status: StatusBaseLocalEnum.DRAFT,
Expand All @@ -133,8 +157,9 @@ export class BaseLocaleService {
createDemoInput: CreateDemoBaseLocaleDTO,
): Promise<BaseLocale> {
const { commune, populate } = createDemoInput;

const banId: string = await this.getIdBanCommune(createDemoInput.commune);
const newDemoBaseLocale = await this.baseLocaleModel.create({
banId,
token: generateBase62String(20),
commune,
nom: `Adresses de ${getCommune(commune).nom} [démo]`,
Expand Down
3 changes: 3 additions & 0 deletions apps/api/src/modules/numeros/numero.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { FilterQuery, Model, ProjectionType, SortOrder, Types } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { omit, uniq } from 'lodash';
import { uuid } from 'uuidv4';

import { Numero } from '@/shared/schemas/numero/numero.schema';
import { NumeroPopulate } from '@/shared/schemas/numero/numero.populate';
Expand Down Expand Up @@ -115,6 +116,7 @@ export class NumeroService {

const numero = {
_bal: baseLocale._id,
banId: rawNumero.banId || uuid(),
numero: rawNumero.numero,
comment: rawNumero.comment,
toponyme: rawNumero.toponyme,
Expand Down Expand Up @@ -175,6 +177,7 @@ export class NumeroService {
// CREATE NUMERO
const numero: Partial<Numero> = {
_bal: voie._bal,
banId: uuid(),
commune: voie.commune,
voie: voie._id,
numero: createNumeroDto.numero,
Expand Down
5 changes: 4 additions & 1 deletion apps/api/src/modules/toponyme/toponyme.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { FilterQuery, Model, ProjectionType, Types } from 'mongoose';
import { InjectModel } from '@nestjs/mongoose';
import { groupBy } from 'lodash';
import { uuid } from 'uuidv4';

import { Toponyme } from '@/shared/schemas/toponyme/toponyme.schema';
import { BaseLocale } from '@/shared/schemas/base_locale/base_locale.schema';
Expand Down Expand Up @@ -103,11 +104,12 @@ export class ToponymeService {

public async create(
bal: BaseLocale,
createToponymeDto: CreateToponymeDTO,
createToponymeDto: CreateToponymeDTO | Partial<Toponyme>,
): Promise<Toponyme> {
// CREATE OBJECT TOPONYME
const toponyme: Partial<Toponyme> = {
_bal: bal._id,
banId: uuid(),
commune: bal.commune,
nom: createToponymeDto.nom,
positions: createToponymeDto.positions || [],
Expand Down Expand Up @@ -206,6 +208,7 @@ export class ToponymeService {
const toponyme = {
_id: rawToponyme._id,
_bal: baseLocale._id,
banId: rawToponyme.banId || uuid(),
nom: cleanNom(rawToponyme.nom),
positions: rawToponyme.positions || [],
parcelles: rawToponyme.parcelles || [],
Expand Down
7 changes: 5 additions & 2 deletions apps/api/src/modules/voie/voie.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { InjectModel } from '@nestjs/mongoose';
import { FilterQuery, Model, ProjectionType, Types } from 'mongoose';
import { groupBy } from 'lodash';
import { uuid } from 'uuidv4';

import { Voie } from '@/shared/schemas/voie/voie.schema';
import { TypeNumerotationEnum } from '@/shared/schemas/voie/type_numerotation.enum';
Expand All @@ -30,7 +31,6 @@ import { Numero } from '@/shared/schemas/numero/numero.schema';
import { BBox as BboxTurf } from '@turf/helpers';
import { Toponyme } from '@/shared/schemas/toponyme/toponyme.schema';
import { ToponymeService } from '@/modules/toponyme/toponyme.service';
import { CreateToponymeDTO } from '../toponyme/dto/create_toponyme.dto';
import {
getTilesByLineString,
getTilesByPosition,
Expand Down Expand Up @@ -113,6 +113,7 @@ export class VoieService {
// CREATE OBJECT VOIE
const voie: Partial<Voie> = {
_bal: bal._id,
banId: uuid(),
commune: bal.commune,
nom: createVoieDto.nom,
typeNumerotation:
Expand Down Expand Up @@ -145,6 +146,7 @@ export class VoieService {
const voie = {
_id: rawVoie._id,
_bal: baseLocale._id,
banId: rawVoie.banId || uuid(),
nom: cleanNom(rawVoie.nom),
code: rawVoie.code || null,
commune: rawVoie.commune,
Expand Down Expand Up @@ -368,9 +370,10 @@ export class VoieService {
);

// CREATE TOPONYME
const payload: CreateToponymeDTO = {
const payload: Partial<Toponyme> = {
nom: voie.nom,
nomAlt: voie.nomAlt,
banId: voie.banId,
};
const toponyme: Toponyme = await this.toponymeService.create(
baseLocale,
Expand Down
Loading

0 comments on commit 08cd924

Please sign in to comment.