From 2cfcdc25c7d19b2ff256d6d83528159e21518273 Mon Sep 17 00:00:00 2001 From: DioChuks Date: Wed, 25 Mar 2026 21:06:31 +0100 Subject: [PATCH 1/5] feat: add patch distribution --- .../distribution/distribution.controller.ts | 32 +++++++++++++++++-- .../v1/distribution/distribution.dto.ts | 3 +- .../v1/distribution/distribution.service.ts | 31 +++++++++++++++++- .../distribution/distribution.validation.ts | 9 +++++- .../v1/distribution/distrubtion.routes.ts | 4 ++- 5 files changed, 73 insertions(+), 6 deletions(-) diff --git a/src/components/v1/distribution/distribution.controller.ts b/src/components/v1/distribution/distribution.controller.ts index 5e68d98..2218c88 100644 --- a/src/components/v1/distribution/distribution.controller.ts +++ b/src/components/v1/distribution/distribution.controller.ts @@ -1,8 +1,8 @@ import type { Request, Response } from "express" import AppDataSource from "../../../config/persistence/data-source" import { DistributionEntity } from "./distribution.entity" -import { DistributionService } from "./Distribution.service" -import type { ApiResponse, DistributionResponseDto, CreateDistributionDto } from "./distribution.dto" +import { DistributionService } from "./distribution.service" +import type { ApiResponse, DistributionResponseDto, CreateDistributionDto, UpdateDistributionDto } from "./distribution.dto" const distributionRepository = AppDataSource.getRepository(DistributionEntity) const distributionService = new DistributionService(distributionRepository) @@ -33,3 +33,31 @@ export const createDistribution = async (req: Request, res: Response): Promise => { + try { + const { id } = req.params + const validatedData = req.body as UpdateDistributionDto + + const distribution = await distributionService.updateDistribution(id, validatedData) + + const response: ApiResponse = { + data: distribution, + success: true, + message: "Distribution updated successfully", + } + + res.status(200).json(response) + } catch (error) { + console.error("Error in updateDistribution:", error) + + const errorResponse: ApiResponse = { + data: null, + success: false, + message: error instanceof Error ? error.message : "Internal server error", + } + + const status = error instanceof Error && error.message === "Distribution not found" ? 404 : 500 + res.status(status).json(errorResponse) + } +} + diff --git a/src/components/v1/distribution/distribution.dto.ts b/src/components/v1/distribution/distribution.dto.ts index b86e100..edf3b4e 100644 --- a/src/components/v1/distribution/distribution.dto.ts +++ b/src/components/v1/distribution/distribution.dto.ts @@ -1,7 +1,8 @@ import type { DistributionType, Network } from "../../../types/enums" -import type { CreateDistributionInput } from "./distribution.validation" +import type { CreateDistributionInput, UpdateDistributionInput } from "./distribution.validation" export type CreateDistributionDto = CreateDistributionInput +export type UpdateDistributionDto = UpdateDistributionInput export interface DistributionResponseDto { id: string diff --git a/src/components/v1/distribution/distribution.service.ts b/src/components/v1/distribution/distribution.service.ts index 9459ba6..4d4db2b 100644 --- a/src/components/v1/distribution/distribution.service.ts +++ b/src/components/v1/distribution/distribution.service.ts @@ -1,6 +1,6 @@ import type { Repository } from "typeorm" import type { DistributionEntity } from "./distribution.entity" -import type { CreateDistributionDto, DistributionResponseDto } from "./distribution.dto" +import type { CreateDistributionDto, DistributionResponseDto, UpdateDistributionDto } from "./distribution.dto" import { DistributionStatus, Network } from "../../../types/enums" export class DistributionService { @@ -20,6 +20,35 @@ export class DistributionService { } } + async updateDistribution(id: string, updateData: UpdateDistributionDto): Promise { + try { + const distribution = await this.distributionRepository.findOne({ where: { id } }) + if (!distribution) { + throw new Error("Distribution not found") + } + + const updatedFields: Partial = { ...updateData } + + if (updateData.totalAmount || updateData.usdRate) { + const totalAmount = updateData.totalAmount ?? distribution.totalAmount + const usdRate = updateData.usdRate ?? distribution.usdRate + updatedFields.totalUsdAmount = this.calculateTotalUsdAmount(totalAmount, usdRate) + } + + if (updateData.metadata) { + updatedFields.metadata = this.processMetadata(updateData.metadata) + } + + Object.assign(distribution, updatedFields) + const savedDistribution = await this.distributionRepository.save(distribution) + + return this.formatDistributionResponse(savedDistribution) + } catch (error) { + console.error("Error updating distribution:", error) + throw error instanceof Error ? error : new Error("Failed to update distribution") + } + } + private prepareDistributionData(data: CreateDistributionDto): Partial { const distributionData: Partial = { userAddress: data.userAddress.toLowerCase(), diff --git a/src/components/v1/distribution/distribution.validation.ts b/src/components/v1/distribution/distribution.validation.ts index 9e17b4f..69b1b8e 100644 --- a/src/components/v1/distribution/distribution.validation.ts +++ b/src/components/v1/distribution/distribution.validation.ts @@ -1,5 +1,5 @@ import { z } from "zod" -import { DistributionType, Network } from "../../../types/enums" +import { DistributionType, DistributionStatus, Network } from "../../../types/enums" export class ValidationError extends Error { constructor(message: string) { @@ -49,4 +49,11 @@ export const createDistributionSchema = z.object({ metadata: z.record(z.any()).optional(), }) +export const updateDistributionSchema = createDistributionSchema.partial().extend({ + status: z.nativeEnum(DistributionStatus, { + errorMap: () => ({ message: "status must be a valid DistributionStatus" }), + }).optional(), +}) + export type CreateDistributionInput = z.infer +export type UpdateDistributionInput = z.infer diff --git a/src/components/v1/distribution/distrubtion.routes.ts b/src/components/v1/distribution/distrubtion.routes.ts index 96cc192..ce5ded9 100644 --- a/src/components/v1/distribution/distrubtion.routes.ts +++ b/src/components/v1/distribution/distrubtion.routes.ts @@ -1,12 +1,14 @@ import EnhancedRouter from "../../../utils/enhancedRouter" import policyMiddleware from "../../../appMiddlewares/policy.middleware" -import { createDistributionSchema } from "./distribution.validation" +import { createDistributionSchema, updateDistributionSchema } from "./distribution.validation" import { createDistribution, + updateDistribution, } from "./distribution.controller" const distributionRouter = new EnhancedRouter() distributionRouter.post("/distributions", policyMiddleware(createDistributionSchema), createDistribution) +distributionRouter.patch("/distributions/:id", policyMiddleware(updateDistributionSchema), updateDistribution) export default distributionRouter.getRouter() From d81148405be66f8e45a5b1bc12242b02dc4cb7ee Mon Sep 17 00:00:00 2001 From: Liam Dio <44742525+DioChuks@users.noreply.github.com> Date: Wed, 25 Mar 2026 21:24:32 +0100 Subject: [PATCH 2/5] Update src/components/v1/distribution/distribution.service.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- src/components/v1/distribution/distribution.service.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/v1/distribution/distribution.service.ts b/src/components/v1/distribution/distribution.service.ts index 4d4db2b..3fe552f 100644 --- a/src/components/v1/distribution/distribution.service.ts +++ b/src/components/v1/distribution/distribution.service.ts @@ -29,6 +29,16 @@ export class DistributionService { const updatedFields: Partial = { ...updateData } + if (updateData.userAddress !== undefined) { + updatedFields.userAddress = updateData.userAddress.toLowerCase() + } + if (updateData.tokenAddress !== undefined) { + updatedFields.tokenAddress = updateData.tokenAddress.toLowerCase() + } + if (updateData.tokenSymbol !== undefined) { + updatedFields.tokenSymbol = updateData.tokenSymbol.toUpperCase() + } + if (updateData.totalAmount || updateData.usdRate) { const totalAmount = updateData.totalAmount ?? distribution.totalAmount const usdRate = updateData.usdRate ?? distribution.usdRate From 79a311d54b5cc56d613a3e84119ec10c704b3d2e Mon Sep 17 00:00:00 2001 From: DioChuks Date: Wed, 25 Mar 2026 21:25:47 +0100 Subject: [PATCH 3/5] fix: potential major issues --- .../v1/distribution/distribution.controller.ts | 7 +++---- .../v1/distribution/distribution.validation.ts | 4 ++++ .../v1/distribution/distrubtion.routes.ts | 13 +++++++++++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/v1/distribution/distribution.controller.ts b/src/components/v1/distribution/distribution.controller.ts index 2218c88..846b360 100644 --- a/src/components/v1/distribution/distribution.controller.ts +++ b/src/components/v1/distribution/distribution.controller.ts @@ -50,14 +50,13 @@ export const updateDistribution = async (req: Request, res: Response): Promise = { data: null, success: false, - message: error instanceof Error ? error.message : "Internal server error", + message: isNotFound && error instanceof Error ? error.message : "Internal server error", } - - const status = error instanceof Error && error.message === "Distribution not found" ? 404 : 500 res.status(status).json(errorResponse) } } - diff --git a/src/components/v1/distribution/distribution.validation.ts b/src/components/v1/distribution/distribution.validation.ts index 69b1b8e..368c696 100644 --- a/src/components/v1/distribution/distribution.validation.ts +++ b/src/components/v1/distribution/distribution.validation.ts @@ -55,5 +55,9 @@ export const updateDistributionSchema = createDistributionSchema.partial().exten }).optional(), }) +export const updateDistributionParamsSchema = z.object({ + id: z.string().uuid("id must be a valid UUID"), +}) + export type CreateDistributionInput = z.infer export type UpdateDistributionInput = z.infer diff --git a/src/components/v1/distribution/distrubtion.routes.ts b/src/components/v1/distribution/distrubtion.routes.ts index ce5ded9..a653607 100644 --- a/src/components/v1/distribution/distrubtion.routes.ts +++ b/src/components/v1/distribution/distrubtion.routes.ts @@ -1,6 +1,10 @@ import EnhancedRouter from "../../../utils/enhancedRouter" import policyMiddleware from "../../../appMiddlewares/policy.middleware" -import { createDistributionSchema, updateDistributionSchema } from "./distribution.validation" +import { + createDistributionSchema, + updateDistributionSchema, + updateDistributionParamsSchema, +} from "./distribution.validation" import { createDistribution, updateDistribution, @@ -9,6 +13,11 @@ import { const distributionRouter = new EnhancedRouter() distributionRouter.post("/distributions", policyMiddleware(createDistributionSchema), createDistribution) -distributionRouter.patch("/distributions/:id", policyMiddleware(updateDistributionSchema), updateDistribution) +distributionRouter.patch( + "/distributions/:id", + policyMiddleware(updateDistributionParamsSchema, "params"), + policyMiddleware(updateDistributionSchema), + updateDistribution, +) export default distributionRouter.getRouter() From 9607c5e27381baae5e6c8af3e3f340d10c62ac4f Mon Sep 17 00:00:00 2001 From: DioChuks Date: Wed, 25 Mar 2026 21:36:00 +0100 Subject: [PATCH 4/5] fix: potential minor issue --- src/components/v1/distribution/distribution.service.ts | 4 +++- src/components/v1/distribution/distribution.validation.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/v1/distribution/distribution.service.ts b/src/components/v1/distribution/distribution.service.ts index 3fe552f..656bf7a 100644 --- a/src/components/v1/distribution/distribution.service.ts +++ b/src/components/v1/distribution/distribution.service.ts @@ -45,7 +45,9 @@ export class DistributionService { updatedFields.totalUsdAmount = this.calculateTotalUsdAmount(totalAmount, usdRate) } - if (updateData.metadata) { + if (updateData.metadata === null) { + updatedFields.metadata = null + } else if (updateData.metadata !== undefined) { updatedFields.metadata = this.processMetadata(updateData.metadata) } diff --git a/src/components/v1/distribution/distribution.validation.ts b/src/components/v1/distribution/distribution.validation.ts index 368c696..de8f014 100644 --- a/src/components/v1/distribution/distribution.validation.ts +++ b/src/components/v1/distribution/distribution.validation.ts @@ -46,7 +46,7 @@ export const createDistributionSchema = z.object({ }) .optional(), - metadata: z.record(z.any()).optional(), + metadata: z.record(z.any()).nullable().optional(), }) export const updateDistributionSchema = createDistributionSchema.partial().extend({ From c105e16a6b3537391983bcdde8068ffd21a4080f Mon Sep 17 00:00:00 2001 From: DioChuks Date: Thu, 26 Mar 2026 13:27:18 +0100 Subject: [PATCH 5/5] fix: potential major issue --- package-lock.json | 7 +++++++ package.json | 1 + src/components/v1/distribution/distribution.service.ts | 8 ++++---- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index c90ec0d..093d01b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "bcryptjs": "^2.4.3", "cors": "^2.8.5", + "decimal.js": "^10.6.0", "express": "^4.21.1", "express-rate-limit": "^7.5.0", "helmet": "^7.2.0", @@ -2141,6 +2142,12 @@ } } }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "license": "MIT" + }, "node_modules/dedent": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", diff --git a/package.json b/package.json index 2fb7010..dcef087 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "dependencies": { "bcryptjs": "^2.4.3", "cors": "^2.8.5", + "decimal.js": "^10.6.0", "express": "^4.21.1", "express-rate-limit": "^7.5.0", "helmet": "^7.2.0", diff --git a/src/components/v1/distribution/distribution.service.ts b/src/components/v1/distribution/distribution.service.ts index d9d8947..c4f4a06 100644 --- a/src/components/v1/distribution/distribution.service.ts +++ b/src/components/v1/distribution/distribution.service.ts @@ -1,3 +1,4 @@ +import { Decimal } from "decimal.js" import type { Repository } from "typeorm" import type { DistributionEntity } from "./distribution.entity" import type { CreateDistributionDto, DistributionResponseDto, UpdateDistributionDto } from "./distribution.dto" @@ -110,10 +111,9 @@ export class DistributionService { private calculateTotalUsdAmount(totalAmount: string, usdRate: string): string { try { - const amount = Number.parseFloat(totalAmount) - const rate = Number.parseFloat(usdRate) - const totalUsd = amount * rate - return totalUsd.toString() + const amount = new Decimal(totalAmount) + const rate = new Decimal(usdRate) + return amount.mul(rate).toString() } catch (error) { console.warn("Error calculating total USD amount:", error) return "0"