Skip to content

Commit

Permalink
feat: added decay shelter supply behaviour (#172)
Browse files Browse the repository at this point in the history
- Adicionado o decaimento das prioridades dos suprimentos para
incentivar o usuário a atualizar os dados e para evitar dados
desatualizados na base.

Foi utilizado os seguintes critérios:

- Caso o suprimento seja de prioridade `Urgent` (máxima) e não é
atualizado a mais de 12 horas, ele é atualizado para o status de
`Needing`.

- Caso o suprimento seja de prioridade `Needing` ou `Remaining` e não é
atualizado a mais de 48 horas, sua prioridade é atualizada para sob
controle.

Além disso é salvo todos os logs do shelter supplies conforme já
implementado nos endpoints de update.

--

Foi escolhido a estratégia de aproveitar o retorno da lista de abrigo e
de abrigos únicos para obter a lista de suprimentos ao invés de rodar um
schedule que sempre percorre inteiramente o banco de dados. Dessa forma
essas atualizações serão por demanda.
  • Loading branch information
fagundesjg committed May 27, 2024
2 parents 1748925 + b84bc41 commit 25246e8
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import { Observable } from 'rxjs';

import { ShelterSupplyHistoryAction } from './types';
import { handler } from './utils';
import { prisma } from '../../../prisma/prisma.service';
import { PrismaService } from '../../../prisma/prisma.service';

@Injectable()
export class ShelterSupplyHistoryInterceptor implements NestInterceptor {
constructor(private readonly action: ShelterSupplyHistoryAction) {}

intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const request = context.switchToHttp().getRequest();
handler(prisma, this.action, request);
handler(PrismaService.getInstance(), this.action, request);
return next.handle();
}
}
20 changes: 6 additions & 14 deletions src/interceptors/interceptors/shelter-supply-history/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ import { ShelterSupplyHistoryAction, UserIdentity } from './types';
import { getSessionData } from '@/utils/utils';

function registerSupplyLog(
prismaService: PrismaService,
body: z.infer<typeof CreateSupplyHistorySchema>,
user: UserIdentity,
user: UserIdentity = {},
) {
const fn = async () => {
const { shelterId, supplyId, ...rest } =
CreateSupplyHistorySchema.parse(body);

const prev = await prismaService.supplyHistory.findFirst({
const prev = await PrismaService.getInstance().supplyHistory.findFirst({
where: {
shelterId,
supplyId,
Expand All @@ -32,7 +31,7 @@ function registerSupplyLog(
},
});

await prismaService.supplyHistory.create({
await PrismaService.getInstance().supplyHistory.create({
data: {
shelterId,
supplyId,
Expand All @@ -57,23 +56,20 @@ function registerSupplyLog(
}

function registerCreateSupplyLog(
prismaService: PrismaService,
body: z.infer<typeof CreateShelterSupplySchema>,
user: UserIdentity,
) {
const payload = CreateShelterSupplySchema.parse(body);
registerSupplyLog(prismaService, payload, user);
registerSupplyLog(payload, user);
}

function registerUpdateSupplyLog(
prismaService: PrismaService,
body: z.infer<typeof UpdateShelterSupplySchema>,
user: UserIdentity,
) {
const payload = UpdateShelterSupplySchema.parse(body);

registerSupplyLog(
prismaService,
{
shelterId: payload.where.shelterId,
supplyId: payload.where.supplyId,
Expand All @@ -85,15 +81,13 @@ function registerUpdateSupplyLog(
}

function registerUpdateManySupplyLog(
prismaService: PrismaService,
body: z.infer<typeof UpdateManyShelterSupplySchema>,
user: UserIdentity,
) {
const { ids, shelterId } = UpdateManyShelterSupplySchema.parse(body);

ids.forEach((id) =>
registerSupplyLog(
prismaService,
{
shelterId,
supplyId: id,
Expand Down Expand Up @@ -124,11 +118,10 @@ function handler(

switch (action) {
case ShelterSupplyHistoryAction.Create:
registerCreateSupplyLog(prismaService, request.body as any, user);
registerCreateSupplyLog(request.body as any, user);
break;
case ShelterSupplyHistoryAction.Update:
registerUpdateSupplyLog(
prismaService,
{
data: request.body as any,
where: request.params as any,
Expand All @@ -138,7 +131,6 @@ function handler(
break;
case ShelterSupplyHistoryAction.UpdateMany:
registerUpdateManySupplyLog(
prismaService,
{
shelterId: (request.params as any).shelterId,
ids: (request.body as any).ids,
Expand All @@ -149,4 +141,4 @@ function handler(
}
}

export { handler };
export { handler, registerSupplyLog };
2 changes: 0 additions & 2 deletions src/prisma/prisma.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,3 @@ export class PrismaService
});
}
}

export const prisma = PrismaService.getInstance();
113 changes: 110 additions & 3 deletions src/shelter/shelter.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { Prisma, ShelterSupply } from '@prisma/client';
import { DefaultArgs } from '@prisma/client/runtime/library';
import { subDays } from 'date-fns';
import { millisecondsToHours, subDays } from 'date-fns';
import * as qs from 'qs';
import { z } from 'zod';

Expand All @@ -13,11 +13,14 @@ import { ShelterSearchPropsSchema } from './types/search.types';
import {
CreateShelterSchema,
FullUpdateShelterSchema,
IShelterSupplyDecay,
UpdateShelterSchema,
} from './types/types';
import { registerSupplyLog } from '@/interceptors/interceptors/shelter-supply-history/utils';

@Injectable()
export class ShelterService implements OnModuleInit {
private logger = new Logger(ShelterService.name);
private voluntaryIds: string[] = [];

constructor(private readonly prismaService: PrismaService) {}
Expand Down Expand Up @@ -93,6 +96,10 @@ export class ShelterService implements OnModuleInit {
select: {
priority: true,
quantity: true,
supplyId: true,
shelterId: true,
createdAt: true,
updatedAt: true,
supply: {
select: {
id: true,
Expand All @@ -115,6 +122,8 @@ export class ShelterService implements OnModuleInit {
},
});

if (data) this.decayShelterSupply(data.shelterSupplies);

return data;
}

Expand Down Expand Up @@ -181,6 +190,8 @@ export class ShelterService implements OnModuleInit {
},
});

this.decayShelterSupply(results.flatMap((r) => r.shelterSupplies));

const parsed = parseTagResponse(queryData, results, this.voluntaryIds);

return {
Expand Down Expand Up @@ -228,4 +239,100 @@ export class ShelterService implements OnModuleInit {
this.voluntaryIds.push(...resp.map((s) => s.id));
});
}

private parseShelterSupply(
shelterSupply: ShelterSupply,
): IShelterSupplyDecay {
return {
shelterId: shelterSupply.shelterId,
supplyId: shelterSupply.supplyId,
priority: shelterSupply.priority,
createdAt: new Date(shelterSupply.createdAt).getTime(),
updatedAt: shelterSupply.updatedAt
? new Date(shelterSupply.updatedAt).getTime()
: 0,
};
}

private canDecayShelterSupply(
shelterSupply: IShelterSupplyDecay,
priorities: SupplyPriority[],
timeInHoursToDecay: number,
): boolean {
return (
priorities.includes(shelterSupply.priority) &&
millisecondsToHours(
new Date().getTime() -
Math.max(shelterSupply.createdAt, shelterSupply.updatedAt),
) > timeInHoursToDecay
);
}

private async handleDecayShelterSupply(
shelterSupplies: IShelterSupplyDecay[],
newPriority: SupplyPriority,
) {
const shelterIds: Set<string> = new Set();
shelterSupplies.forEach((s) => shelterIds.add(s.shelterId));

await this.prismaService.$transaction([
this.prismaService.shelter.updateMany({
where: {
id: {
in: Array.from(shelterIds),
},
},
data: {
updatedAt: new Date().toISOString(),
},
}),
...shelterSupplies.map((s) =>
this.prismaService.shelterSupply.update({
where: {
shelterId_supplyId: {
shelterId: s.shelterId,
supplyId: s.supplyId,
},
},
data: {
priority: newPriority,
updatedAt: new Date().toISOString(),
},
}),
),
]);

shelterSupplies.forEach((s) => {
registerSupplyLog({
shelterId: s.shelterId,
supplyId: s.supplyId,
priority: newPriority,
});
});
}

private async decayShelterSupply(shelterSupplies: ShelterSupply[]) {
this.handleDecayShelterSupply(
shelterSupplies
.map(this.parseShelterSupply)
.filter((f) =>
this.canDecayShelterSupply(f, [SupplyPriority.Urgent], 12),
),

SupplyPriority.Needing,
);

this.handleDecayShelterSupply(
shelterSupplies
.map(this.parseShelterSupply)
.filter((f) =>
this.canDecayShelterSupply(
f,
[SupplyPriority.Needing, SupplyPriority.Remaining],
48,
),
),
SupplyPriority.UnderControl,
);
}
}
8 changes: 8 additions & 0 deletions src/shelter/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ const FullUpdateShelterSchema = ShelterSchema.omit({
.partial()
.transform((args) => removeEmptyStrings<typeof args>(args));

export interface IShelterSupplyDecay {
shelterId: string;
supplyId: string;
priority: number;
createdAt: number;
updatedAt: number;
}

export {
ShelterSchema,
CreateShelterSchema,
Expand Down

0 comments on commit 25246e8

Please sign in to comment.