Skip to content

Commit

Permalink
refactor: change occupancy’s type to the shared occupancy model
Browse files Browse the repository at this point in the history
  • Loading branch information
Falinor committed Nov 28, 2024
1 parent c02b6c0 commit 25ef101
Show file tree
Hide file tree
Showing 14 changed files with 118 additions and 101 deletions.
9 changes: 8 additions & 1 deletion packages/models/src/DatafoncierHousing.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import fp from 'lodash/fp';

import { Occupancy, OCCUPANCY_VALUES } from './Occupancy';

/**
* @see http://doc-datafoncier.cerema.fr/ff/doc_fftp/table/pb0010_local/last/
*/
Expand Down Expand Up @@ -57,7 +59,7 @@ export interface DatafoncierHousing {
dloy48a: number | null;
top48a: string;
dnatlc: string;
ccthp: string;
ccthp: string | null;
proba_rprs: string;
typeact: string | null;
loghvac: string | null;
Expand Down Expand Up @@ -140,3 +142,8 @@ export function toAddress(housing: DatafoncierHousing): string {
const city = housing.idcomtxt;
return `${streetNumber}${repetition} ${street}, ${zipcode} ${city}`;
}

export function toOccupancy(ccthp: DatafoncierHousing['ccthp']): Occupancy {
const occupancy = OCCUPANCY_VALUES.find((occupancy) => occupancy === ccthp);
return occupancy ?? Occupancy.UNKNOWN;
}
24 changes: 24 additions & 0 deletions packages/models/src/test/DatafoncierHousing.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Occupancy, OCCUPANCY_VALUES } from '../Occupancy';
import { toOccupancy } from '../DatafoncierHousing';

describe('DatafoncierHousing', () => {
describe('toOccupancy', () => {
it.each(OCCUPANCY_VALUES)('should return %s', (ccthp) => {
const actual = toOccupancy(ccthp);

expect(actual).toBe(ccthp);
});

it(`should return ${Occupancy.UNKNOWN} when ccthp is null`, () => {
const actual = toOccupancy(null);

expect(actual).toBe(Occupancy.UNKNOWN);
});

it(`should return ${Occupancy.UNKNOWN} otherwise`, () => {
const actual = toOccupancy('test');

expect(actual).toBe(Occupancy.UNKNOWN);
});
});
});
15 changes: 7 additions & 8 deletions server/src/controllers/housingController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import {
} from '~/repositories/campaignHousingRepository';
import { faker } from '@faker-js/faker/locale/fr';
import { OwnerApi } from '~/models/OwnerApi';
import { Occupancy, OCCUPANCY_VALUES } from '@zerologementvacant/models';

describe('Housing API', () => {
const { app } = createServer();
Expand Down Expand Up @@ -151,12 +152,10 @@ describe('Housing API', () => {
});

it('should sort housings by occupancy', async () => {
const housings = Object.values(OccupancyKindApi).map<HousingApi>(
(occupancy) => ({
...genHousingApi(faker.helpers.arrayElement(establishment.geoCodes)),
occupancy
})
);
const housings = OCCUPANCY_VALUES.map<HousingApi>((occupancy) => ({
...genHousingApi(faker.helpers.arrayElement(establishment.geoCodes)),
occupancy
}));
const owner = genOwnerApi();
await Promise.all([
Housing().insert(housings.map(formatHousingRecordApi)),
Expand Down Expand Up @@ -357,8 +356,8 @@ describe('Housing API', () => {
vacancyReasons: [randomstring.generate()]
},
occupancyUpdate: {
occupancy: OccupancyKindApi.Vacant,
occupancyIntended: OccupancyKindApi.DemolishedOrDivided
occupancy: Occupancy.VACANT,
occupancyIntended: Occupancy.DEMOLISHED_OR_DIVIDED
},
note: {
content: randomstring.generate(),
Expand Down
2 changes: 1 addition & 1 deletion server/src/controllers/housingController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ async function list(
),
energyConsumption:
rawFilters?.energyConsumption as unknown as EnergyConsumptionGradesApi[],
occupancies: rawFilters?.occupancies as unknown as OccupancyKindApi[],
occupancies: rawFilters?.occupancies,
establishmentIds:
[UserRoles.Admin, UserRoles.Visitor].includes(role) &&
rawFilters?.establishmentIds?.length
Expand Down
8 changes: 4 additions & 4 deletions server/src/models/HousingApi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fp from 'lodash/fp';
import { assert, MarkRequired } from 'ts-essentials';

import { HousingSource } from '@zerologementvacant/models';
import { HousingSource, Occupancy } from '@zerologementvacant/models';
import { OwnerApi } from './OwnerApi';
import { HousingStatusApi } from './HousingStatusApi';
import { Sort } from './SortApi';
Expand Down Expand Up @@ -52,9 +52,9 @@ export interface HousingRecordApi {
precisions?: string[];
energyConsumption?: EnergyConsumptionGradesApi;
energyConsumptionAt?: Date;
occupancy: OccupancyKindApi;
occupancyRegistered: OccupancyKindApi;
occupancyIntended?: OccupancyKindApi;
occupancy: Occupancy;
occupancyRegistered: Occupancy;
occupancyIntended?: Occupancy;
source: HousingSource | null;
}

Expand Down
6 changes: 3 additions & 3 deletions server/src/models/HousingFiltersApi.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OwnershipKind } from '@zerologementvacant/models';
import { EnergyConsumptionGradesApi, OccupancyKindApi } from './HousingApi';
import { Occupancy, OwnershipKind } from '@zerologementvacant/models';
import { EnergyConsumptionGradesApi } from './HousingApi';
import { body, ValidationChain } from 'express-validator';
import { isArrayOf, isInteger, isString, isUUID } from '~/utils/validators';

Expand Down Expand Up @@ -40,7 +40,7 @@ export interface HousingFiltersApi {
subStatus?: string[];
query?: string;
energyConsumption?: EnergyConsumptionGradesApi[];
occupancies?: OccupancyKindApi[];
occupancies?: Occupancy[];
}

const validators = (property = 'filters'): ValidationChain[] => [
Expand Down
26 changes: 8 additions & 18 deletions server/src/repositories/housingRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import {
HousingSource,
INTERNAL_CO_CONDOMINIUM_VALUES,
INTERNAL_MONO_CONDOMINIUM_VALUES,
Occupancy,
PaginationOptions
} from '@zerologementvacant/models';
import db, { toRawArray, where } from '~/infra/database';
import {
EnergyConsumptionGradesApi,
HousingApi,
HousingRecordApi,
HousingSortApi,
OccupancyKindApi
HousingSortApi
} from '~/models/HousingApi';
import { OwnerDBO, ownerTable, parseOwnerApi } from './ownerRepository';
import { HousingFiltersApi } from '~/models/HousingFiltersApi';
Expand Down Expand Up @@ -608,23 +608,13 @@ function filteredQuery(opts: ListQueryOptions) {
whereBuilder.orWhere('vacancy_start_year', 2019);
}
if (filters.vacancyYears?.includes('2018to2015')) {
whereBuilder.orWhereBetween('vacancy_start_year', [
2015,
2018
]);
whereBuilder.orWhereBetween('vacancy_start_year', [2015, 2018]);
}
if (filters.vacancyYears?.includes('2014to2010')) {
whereBuilder.orWhereBetween('vacancy_start_year', [
2010,
2014
]);
whereBuilder.orWhereBetween('vacancy_start_year', [2010, 2014]);
}
if (filters.vacancyYears?.includes('before2010')) {
whereBuilder.orWhere(
'vacancy_start_year',
'<',
2010
);
whereBuilder.orWhere('vacancy_start_year', '<', 2010);
}
if (filters.vacancyYears?.includes('missingData')) {
whereBuilder.orWhere('vacancy_start_year', 0);
Expand Down Expand Up @@ -907,9 +897,9 @@ export interface HousingRecordDBO {
status: HousingStatusApi;
sub_status?: string | null;
precisions?: string[];
occupancy: OccupancyKindApi;
occupancy_source: OccupancyKindApi;
occupancy_intended?: OccupancyKindApi;
occupancy: Occupancy;
occupancy_source: Occupancy;
occupancy_intended?: Occupancy;
energy_consumption_bdnb?: EnergyConsumptionGradesApi;
energy_consumption_at_bdnb?: Date;
}
Expand Down
48 changes: 23 additions & 25 deletions server/src/repositories/test/housingRepository.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ import {
HousingOwnerDBO,
HousingOwners
} from '../housingOwnerRepository';
import {
EnergyConsumptionGradesApi,
HousingApi,
OccupancyKindApi
} from '~/models/HousingApi';
import { EnergyConsumptionGradesApi, HousingApi } from '~/models/HousingApi';
import { formatLocalityApi, Localities } from '../localityRepository';
import { LocalityApi } from '~/models/LocalityApi';
import { BuildingApi } from '~/models/BuildingApi';
Expand Down Expand Up @@ -69,6 +65,8 @@ import {
INTERNAL_CO_CONDOMINIUM_VALUES,
INTERNAL_MONO_CONDOMINIUM_VALUES,
isSecondaryOwner,
Occupancy,
OCCUPANCY_VALUES,
OwnershipKind,
ROOM_COUNT_VALUES
} from '@zerologementvacant/models';
Expand Down Expand Up @@ -181,12 +179,10 @@ describe('Housing repository', () => {

describe('by occupancy', () => {
beforeEach(async () => {
const housings: HousingApi[] = Object.values(OccupancyKindApi).map(
(occupancy) => ({
...genHousingApi(),
occupancy
})
);
const housings: HousingApi[] = OCCUPANCY_VALUES.map((occupancy) => ({
...genHousingApi(),
occupancy
}));
await Housing().insert(housings.map(formatHousingRecordApi));
const owner = genOwnerApi();
await Owners().insert(formatOwnerApi(owner));
Expand All @@ -197,7 +193,7 @@ describe('Housing repository', () => {
);
});

test.each(Object.values(OccupancyKindApi))(
test.each(OCCUPANCY_VALUES)(
'should filter by %s',
async (occupancy) => {
const actual = await housingRepository.find({
Expand Down Expand Up @@ -871,10 +867,13 @@ describe('Housing repository', () => {
.map((_, i) => ({
...genHousingApi(),
vacancyStartYear: ReferenceDataYear - i
})).concat([ {
...genHousingApi(),
vacancyStartYear: 0
} ]);
}))
.concat([
{
...genHousingApi(),
vacancyStartYear: 0
}
]);
await Housing().insert(housingList.map(formatHousingRecordApi));
});

Expand Down Expand Up @@ -902,7 +901,7 @@ describe('Housing repository', () => {
filter: ['2018to2015'],
predicate: (housing: HousingApi) => {
const vacancyStartYear = housing.vacancyStartYear as number;
return vacancyStartYear >= 2015 && vacancyStartYear <= 2018;
return vacancyStartYear >= 2015 && vacancyStartYear <= 2018;
}
},
{
Expand Down Expand Up @@ -1177,8 +1176,7 @@ describe('Housing repository', () => {
return new Array(vacant + other).fill('0').map((_, i) => ({
...genHousingApi(),
buildingId,
occupancy:
i < vacant ? OccupancyKindApi.Vacant : OccupancyKindApi.Rent
occupancy: i < vacant ? Occupancy.VACANT : Occupancy.RENT
}));
}

Expand Down Expand Up @@ -1651,8 +1649,8 @@ describe('Housing repository', () => {
await Housing().insert(formatHousingRecordApi(original));
const update: HousingApi = {
...original,
occupancy: OccupancyKindApi.Rent,
occupancyIntended: OccupancyKindApi.CommercialOrOffice
occupancy: Occupancy.RENT,
occupancyIntended: Occupancy.COMMERCIAL_OR_OFFICE
};

await housingRepository.save(update, { onConflict: 'merge' });
Expand All @@ -1668,14 +1666,14 @@ describe('Housing repository', () => {
it('should update specific fields of an existing housing', async () => {
const original: HousingApi = {
...genHousingApi(oneOf(establishment.geoCodes)),
occupancy: OccupancyKindApi.Vacant,
occupancyIntended: OccupancyKindApi.Rent
occupancy: Occupancy.VACANT,
occupancyIntended: Occupancy.RENT
};
await Housing().insert(formatHousingRecordApi(original));
const update: HousingApi = {
...original,
occupancy: OccupancyKindApi.Rent,
occupancyIntended: OccupancyKindApi.CommercialOrOffice
occupancy: Occupancy.RENT,
occupancyIntended: Occupancy.COMMERCIAL_OR_OFFICE
};

await housingRepository.save(update, {
Expand Down
13 changes: 7 additions & 6 deletions server/src/scripts/import-lovac/housings/housing-processor.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { WritableStream } from 'node:stream/web';
import { v4 as uuidv4 } from 'uuid';

import { Occupancy } from '@zerologementvacant/models';
import { ReporterError, ReporterOptions } from '~/scripts/import-lovac/infra';
import { createLogger } from '~/infra/logger';
import { HousingApi, OccupancyKindApi } from '~/models/HousingApi';
import { HousingApi } from '~/models/HousingApi';
import { HousingStatusApi } from '~/models/HousingStatusApi';
import { HousingEventApi } from '~/models/EventApi';
import { UserApi } from '~/models/UserApi';
Expand Down Expand Up @@ -38,13 +39,13 @@ export function createHousingProcessor(opts: ProcessorOptions) {
logger.debug('Processing housing...', { chunk });

if (!chunk.dataFileYears.includes('lovac-2024')) {
if (chunk.occupancy === OccupancyKindApi.Vacant) {
if (chunk.occupancy === Occupancy.VACANT) {
if (!isInProgress(chunk) && !isCompleted(chunk)) {
await Promise.all([
housingRepository.update(
{ geoCode: chunk.geoCode, id: chunk.id },
{
occupancy: OccupancyKindApi.Unknown,
occupancy: Occupancy.UNKNOWN,
status: HousingStatusApi.Completed,
subStatus: 'Sortie de la vacance'
}
Expand All @@ -57,7 +58,7 @@ export function createHousingProcessor(opts: ProcessorOptions) {
section: 'Situation',
conflict: false,
old: chunk,
new: { ...chunk, occupancy: OccupancyKindApi.Unknown },
new: { ...chunk, occupancy: Occupancy.UNKNOWN },
createdAt: new Date(),
createdBy: auth.id,
housingId: chunk.id,
Expand All @@ -71,10 +72,10 @@ export function createHousingProcessor(opts: ProcessorOptions) {
section: 'Situation',
conflict: false,
// This event should come after the above one
old: { ...chunk, occupancy: OccupancyKindApi.Unknown },
old: { ...chunk, occupancy: Occupancy.UNKNOWN },
new: {
...chunk,
occupancy: OccupancyKindApi.Unknown,
occupancy: Occupancy.UNKNOWN,
status: HousingStatusApi.Completed,
subStatus: 'Sortie de la vacance'
},
Expand Down
Loading

0 comments on commit 25ef101

Please sign in to comment.