diff --git a/src/subdomains/core/buy-crypto/routes/buy/buy.service.ts b/src/subdomains/core/buy-crypto/routes/buy/buy.service.ts index 4843d3b864..86d62e56e7 100644 --- a/src/subdomains/core/buy-crypto/routes/buy/buy.service.ts +++ b/src/subdomains/core/buy-crypto/routes/buy/buy.service.ts @@ -73,7 +73,9 @@ export class BuyService { select: ['id', 'user'], }); const userVolume = await this.getUserVolume(user.id); - await this.userService.updateBuyVolume(user.id, userVolume.volume, userVolume.annualVolume); + const monthlyVolume = await this.getMonthlyVolume(user.id); + + await this.userService.updateBuyVolume(user.id, userVolume.volume, userVolume.annualVolume, monthlyVolume.volume); } async getUserVolume(userId: number): Promise<{ volume: number; annualVolume: number }> { @@ -85,6 +87,17 @@ export class BuyService { .getRawOne<{ volume: number; annualVolume: number }>(); } + async getMonthlyVolume(userId: number): Promise<{ volume: number }> { + return this.buyRepo + .createQueryBuilder('buy') + .select('SUM(volume)', 'volume') + .where('userId = :id', { id: userId }) + .andWhere('buy.created >= :startOfMonth', { + startOfMonth: new Date(new Date().getFullYear(), new Date().getMonth(), 1), + }) + .getRawOne<{ volume: number }>(); + } + async getTotalVolume(): Promise { return this.buyRepo .createQueryBuilder('buy') diff --git a/src/subdomains/core/buy-crypto/routes/swap/swap.service.ts b/src/subdomains/core/buy-crypto/routes/swap/swap.service.ts index 0a1a9d97ca..0247672dce 100644 --- a/src/subdomains/core/buy-crypto/routes/swap/swap.service.ts +++ b/src/subdomains/core/buy-crypto/routes/swap/swap.service.ts @@ -95,7 +95,14 @@ export class SwapService { select: ['id', 'user'], }); const userVolume = await this.getUserVolume(user.id); - await this.userService.updateCryptoVolume(user.id, userVolume.volume, userVolume.annualVolume); + const monthlyVolume = await this.getMonthlyVolume(user.id); + + await this.userService.updateCryptoVolume( + user.id, + userVolume.volume, + userVolume.annualVolume, + monthlyVolume.volume, + ); } async getUserVolume(userId: number): Promise<{ volume: number; annualVolume: number }> { @@ -107,6 +114,17 @@ export class SwapService { .getRawOne<{ volume: number; annualVolume: number }>(); } + async getMonthlyVolume(userId: number): Promise<{ volume: number }> { + return this.swapRepo + .createQueryBuilder('crypto') + .select('SUM(volume)', 'volume') + .where('userId = :id', { id: userId }) + .andWhere('crypto.created >= :startOfMonth', { + startOfMonth: new Date(new Date().getFullYear(), new Date().getMonth(), 1), + }) + .getRawOne<{ volume: number }>(); + } + async getTotalVolume(): Promise { return this.swapRepo .createQueryBuilder('crypto') diff --git a/src/subdomains/core/sell-crypto/route/sell.service.ts b/src/subdomains/core/sell-crypto/route/sell.service.ts index 48970f728d..02a127802c 100644 --- a/src/subdomains/core/sell-crypto/route/sell.service.ts +++ b/src/subdomains/core/sell-crypto/route/sell.service.ts @@ -284,7 +284,9 @@ export class SellService { select: ['id', 'user'], }); const userVolume = await this.getUserVolume(user.id); - await this.userService.updateSellVolume(user.id, userVolume.volume, userVolume.annualVolume); + const monthlyVolume = await this.getMonthlyVolume(user.id); + + await this.userService.updateSellVolume(user.id, userVolume.volume, userVolume.annualVolume, monthlyVolume.volume); } async getUserVolume(userId: number): Promise<{ volume: number; annualVolume: number }> { @@ -296,6 +298,17 @@ export class SellService { .getRawOne<{ volume: number; annualVolume: number }>(); } + async getMonthlyVolume(userId: number): Promise<{ volume: number }> { + return this.sellRepo + .createQueryBuilder('sell') + .select('SUM(volume)', 'volume') + .where('userId = :id', { id: userId }) + .andWhere('sell.created >= :startOfMonth', { + startOfMonth: new Date(new Date().getFullYear(), new Date().getMonth(), 1), + }) + .getRawOne<{ volume: number }>(); + } + async getTotalVolume(): Promise { return this.sellRepo .createQueryBuilder('sell') diff --git a/src/subdomains/generic/user/models/user-data/user-data.entity.ts b/src/subdomains/generic/user/models/user-data/user-data.entity.ts index 92ae538de6..743e0c3152 100644 --- a/src/subdomains/generic/user/models/user-data/user-data.entity.ts +++ b/src/subdomains/generic/user/models/user-data/user-data.entity.ts @@ -293,18 +293,28 @@ export class UserData extends IEntity { apiFilterCT?: string; // Volumes + + @Column({ type: 'float', default: 0 }) + monthlyBuyVolume: number; // CHF + @Column({ type: 'float', default: 0 }) annualBuyVolume: number; // CHF @Column({ type: 'float', default: 0 }) buyVolume: number; // CHF + @Column({ type: 'float', default: 0 }) + monthlySellVolume: number; // CHF + @Column({ type: 'float', default: 0 }) annualSellVolume: number; // CHF @Column({ type: 'float', default: 0 }) sellVolume: number; // CHF + @Column({ type: 'float', default: 0 }) + monthlyCryptoVolume: number; // CHF + @Column({ type: 'float', default: 0 }) annualCryptoVolume: number; // CHF diff --git a/src/subdomains/generic/user/models/user/dto/user-dto.mapper.ts b/src/subdomains/generic/user/models/user/dto/user-dto.mapper.ts index 0efdbab538..e1d70390ff 100644 --- a/src/subdomains/generic/user/models/user/dto/user-dto.mapper.ts +++ b/src/subdomains/generic/user/models/user/dto/user-dto.mapper.ts @@ -62,9 +62,9 @@ export class UserDtoMapper { private static mapVolumes(user: UserData | User): VolumesDto { const dto: VolumesDto = { - buy: { total: user.buyVolume, annual: user.annualBuyVolume }, - sell: { total: user.sellVolume, annual: user.annualSellVolume }, - swap: { total: user.cryptoVolume, annual: user.annualCryptoVolume }, + buy: { total: user.buyVolume, annual: user.annualBuyVolume, monthly: user.monthlyBuyVolume }, + sell: { total: user.sellVolume, annual: user.annualSellVolume, monthly: user.monthlySellVolume }, + swap: { total: user.cryptoVolume, annual: user.annualCryptoVolume, monthly: user.monthlyCryptoVolume }, }; return Object.assign(new VolumesDto(), dto); diff --git a/src/subdomains/generic/user/models/user/dto/user.dto.ts b/src/subdomains/generic/user/models/user/dto/user.dto.ts index 130dd84a95..d73b86e376 100644 --- a/src/subdomains/generic/user/models/user/dto/user.dto.ts +++ b/src/subdomains/generic/user/models/user/dto/user.dto.ts @@ -13,6 +13,9 @@ export class VolumeInformation { @ApiProperty() annual: number; + + @ApiProperty() + monthly: number; } export class TradingLimit { diff --git a/src/subdomains/generic/user/models/user/user.entity.ts b/src/subdomains/generic/user/models/user/user.entity.ts index 8ddea97a29..8b150f0d7a 100644 --- a/src/subdomains/generic/user/models/user/user.entity.ts +++ b/src/subdomains/generic/user/models/user/user.entity.ts @@ -67,18 +67,27 @@ export class User extends IEntity { @Column({ length: 256, nullable: true }) apiFilterCT?: string; + @Column({ type: 'float', default: 0 }) + monthlyBuyVolume: number; // CHF + @Column({ type: 'float', default: 0 }) annualBuyVolume: number; // CHF @Column({ type: 'float', default: 0 }) buyVolume: number; // CHF + @Column({ type: 'float', default: 0 }) + monthlySellVolume: number; // CHF + @Column({ type: 'float', default: 0 }) annualSellVolume: number; // CHF @Column({ type: 'float', default: 0 }) sellVolume: number; // CHF + @Column({ type: 'float', default: 0 }) + monthlyCryptoVolume: number; // CHF + @Column({ type: 'float', default: 0 }) annualCryptoVolume: number; // CHF diff --git a/src/subdomains/generic/user/models/user/user.service.ts b/src/subdomains/generic/user/models/user/user.service.ts index 9ff068599f..08bfd898fa 100644 --- a/src/subdomains/generic/user/models/user/user.service.ts +++ b/src/subdomains/generic/user/models/user/user.service.ts @@ -379,28 +379,38 @@ export class UserService { await this.userRepo.update({ annualSellVolume: Not(0) }, { annualSellVolume: 0 }); } - async updateBuyVolume(userId: number, volume: number, annualVolume: number): Promise { + @DfxCron(CronExpression.EVERY_1ST_DAY_OF_MONTH_AT_MIDNIGHT) + async resetMonthVolumes(): Promise { + await this.userRepo.update({ monthlyBuyVolume: Not(0) }, { monthlyBuyVolume: 0 }); + await this.userRepo.update({ monthlySellVolume: Not(0) }, { monthlySellVolume: 0 }); + await this.userRepo.update({ monthlyCryptoVolume: Not(0) }, { monthlyCryptoVolume: 0 }); + } + + async updateBuyVolume(userId: number, volume: number, annualVolume: number, monthlyVolume: number): Promise { await this.userRepo.update(userId, { buyVolume: Util.round(volume, Config.defaultVolumeDecimal), annualBuyVolume: Util.round(annualVolume, Config.defaultVolumeDecimal), + monthlyBuyVolume: Util.round(monthlyVolume, Config.defaultVolumeDecimal), }); await this.updateUserDataVolume(userId); } - async updateCryptoVolume(userId: number, volume: number, annualVolume: number): Promise { + async updateCryptoVolume(userId: number, volume: number, annualVolume: number, monthlyVolume: number): Promise { await this.userRepo.update(userId, { cryptoVolume: Util.round(volume, Config.defaultVolumeDecimal), annualCryptoVolume: Util.round(annualVolume, Config.defaultVolumeDecimal), + monthlyCryptoVolume: Util.round(monthlyVolume, Config.defaultVolumeDecimal), }); await this.updateUserDataVolume(userId); } - async updateSellVolume(userId: number, volume: number, annualVolume: number): Promise { + async updateSellVolume(userId: number, volume: number, annualVolume: number, monthlyVolume: number): Promise { await this.userRepo.update(userId, { sellVolume: Util.round(volume, Config.defaultVolumeDecimal), annualSellVolume: Util.round(annualVolume, Config.defaultVolumeDecimal), + monthlySellVolume: Util.round(monthlyVolume, Config.defaultVolumeDecimal), }); await this.updateUserDataVolume(userId); @@ -615,9 +625,9 @@ export class UserService { user.buyVolume + user.sellVolume + user.cryptoVolume >= Config.support.blackSquad.limit ? Config.support.blackSquad.link : undefined, - buyVolume: { total: user.buyVolume, annual: user.annualBuyVolume }, - sellVolume: { total: user.sellVolume, annual: user.annualSellVolume }, - cryptoVolume: { total: user.cryptoVolume, annual: user.annualCryptoVolume }, + buyVolume: { total: user.buyVolume, annual: user.annualBuyVolume, monthly: user.monthlyBuyVolume }, + sellVolume: { total: user.sellVolume, annual: user.annualSellVolume, monthly: user.monthlySellVolume }, + cryptoVolume: { total: user.cryptoVolume, annual: user.annualCryptoVolume, monthly: user.monthlyCryptoVolume }, stakingBalance: 0, }; }