mirror of
https://github.com/HamzaSha1/zod-backend.git
synced 2025-08-25 05:42:27 +00:00
feat: add-account-details
This commit is contained in:
@ -11,6 +11,14 @@ export class Account {
|
||||
@Index({ unique: true })
|
||||
accountReference!: string;
|
||||
|
||||
@Index({ unique: true })
|
||||
@Column('varchar', { length: 255, nullable: false, name: 'account_number' })
|
||||
accountNumber!: string;
|
||||
|
||||
@Index({ unique: true })
|
||||
@Column('varchar', { length: 255, nullable: false, name: 'iban' })
|
||||
iban!: string;
|
||||
|
||||
@Column('varchar', { length: 255, nullable: false, name: 'currency' })
|
||||
currency!: string;
|
||||
|
||||
|
@ -1,16 +1,19 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { CreateApplicationResponse } from '~/common/modules/neoleap/dtos/response';
|
||||
import { Account } from '../entities/account.entity';
|
||||
|
||||
@Injectable()
|
||||
export class AccountRepository {
|
||||
constructor(@InjectRepository(Account) private readonly accountRepository: Repository<Account>) {}
|
||||
|
||||
createAccount(accountId: string): Promise<Account> {
|
||||
createAccount(data: CreateApplicationResponse): Promise<Account> {
|
||||
return this.accountRepository.save(
|
||||
this.accountRepository.create({
|
||||
accountReference: accountId,
|
||||
accountReference: data.accountId,
|
||||
accountNumber: data.accountNumber,
|
||||
iban: data.iBan,
|
||||
balance: 0,
|
||||
currency: '682',
|
||||
}),
|
||||
@ -24,6 +27,13 @@ export class AccountRepository {
|
||||
});
|
||||
}
|
||||
|
||||
getAccountByAccountNumber(accountNumber: string): Promise<Account | null> {
|
||||
return this.accountRepository.findOne({
|
||||
where: { accountNumber },
|
||||
relations: ['cards'],
|
||||
});
|
||||
}
|
||||
|
||||
topUpAccountBalance(accountReference: string, amount: number) {
|
||||
return this.accountRepository.increment({ accountReference }, 'balance', amount);
|
||||
}
|
||||
|
@ -34,6 +34,13 @@ export class CardRepository {
|
||||
return this.cardRepository.findOne({ where: { cardReference: referenceNumber }, relations: ['account'] });
|
||||
}
|
||||
|
||||
getCardByAccountNumber(accountNumber: string): Promise<Card | null> {
|
||||
return this.cardRepository.findOne({
|
||||
where: { account: { accountNumber } },
|
||||
relations: ['account'],
|
||||
});
|
||||
}
|
||||
|
||||
getActiveCardForCustomer(customerId: string): Promise<Card | null> {
|
||||
return this.cardRepository.findOne({
|
||||
where: { customerId, status: CardStatus.ACTIVE },
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Injectable, UnprocessableEntityException } from '@nestjs/common';
|
||||
import { CreateApplicationResponse } from '~/common/modules/neoleap/dtos/response';
|
||||
import { Account } from '../entities/account.entity';
|
||||
import { AccountRepository } from '../repositories/account.repository';
|
||||
|
||||
@ -6,8 +7,8 @@ import { AccountRepository } from '../repositories/account.repository';
|
||||
export class AccountService {
|
||||
constructor(private readonly accountRepository: AccountRepository) {}
|
||||
|
||||
createAccount(accountId: string): Promise<Account> {
|
||||
return this.accountRepository.createAccount(accountId);
|
||||
createAccount(data: CreateApplicationResponse): Promise<Account> {
|
||||
return this.accountRepository.createAccount(data);
|
||||
}
|
||||
|
||||
async getAccountByReferenceNumber(accountReference: string): Promise<Account> {
|
||||
@ -18,6 +19,14 @@ export class AccountService {
|
||||
return account;
|
||||
}
|
||||
|
||||
async getAccountByAccountNumber(accountNumber: string): Promise<Account> {
|
||||
const account = await this.accountRepository.getAccountByAccountNumber(accountNumber);
|
||||
if (!account) {
|
||||
throw new UnprocessableEntityException('ACCOUNT.NOT_FOUND');
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
async creditAccountBalance(accountReference: string, amount: number) {
|
||||
return this.accountRepository.topUpAccountBalance(accountReference, amount);
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export class CardService {
|
||||
|
||||
@Transactional()
|
||||
async createCard(customerId: string, cardData: CreateApplicationResponse): Promise<Card> {
|
||||
const account = await this.accountService.createAccount(cardData.accountId);
|
||||
const account = await this.accountService.createAccount(cardData);
|
||||
return this.cardRepository.createCard(customerId, account.id, cardData);
|
||||
}
|
||||
|
||||
@ -37,6 +37,15 @@ export class CardService {
|
||||
return card;
|
||||
}
|
||||
|
||||
async getCardByAccountNumber(accountNumber: string): Promise<Card> {
|
||||
const card = await this.cardRepository.getCardByAccountNumber(accountNumber);
|
||||
|
||||
if (!card) {
|
||||
throw new BadRequestException('CARD.NOT_FOUND');
|
||||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
async getActiveCardForCustomer(customerId: string): Promise<Card> {
|
||||
const card = await this.cardRepository.getActiveCardForCustomer(customerId);
|
||||
if (!card) {
|
||||
|
@ -20,7 +20,7 @@ export class TransactionService {
|
||||
|
||||
@Transactional()
|
||||
async createCardTransaction(body: CardTransactionWebhookRequest) {
|
||||
const card = await this.cardService.getCardByReferenceNumber(body.cardId);
|
||||
const card = await this.cardService.getCardByAccountNumber(body.cardId);
|
||||
const existingTransaction = await this.findExistingTransaction(body.transactionId, card.account.accountReference);
|
||||
|
||||
if (existingTransaction) {
|
||||
|
@ -37,4 +37,14 @@ export class CreateApplicationResponse extends InquireApplicationResponse {
|
||||
@Expose()
|
||||
@ApiProperty()
|
||||
accountId!: string;
|
||||
|
||||
@Transform(({ obj }) => obj.AccountDetailsList?.[0]?.AccountNumber)
|
||||
@Expose()
|
||||
@ApiProperty()
|
||||
accountNumber!: string;
|
||||
|
||||
@Transform(({ obj }) => obj.AccountDetailsList?.[0]?.UserData5)
|
||||
@Expose()
|
||||
@ApiProperty()
|
||||
iBan!: string;
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
export class AddAccountNumberAndIbanToAccountEntity1753948642040 implements MigrationInterface {
|
||||
name = 'AddAccountNumberAndIbanToAccountEntity1753948642040';
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// Step 1: Add columns as nullable
|
||||
await queryRunner.query(`ALTER TABLE "accounts" ADD "account_number" character varying(255)`);
|
||||
await queryRunner.query(`ALTER TABLE "accounts" ADD "iban" character varying(255)`);
|
||||
|
||||
// Step 2: Populate dummy values or correct ones
|
||||
await queryRunner.query(`
|
||||
UPDATE "accounts"
|
||||
SET "account_number" = 'TEMP_ACC_' || id,
|
||||
"iban" = 'TEMP_IBAN_' || id
|
||||
`);
|
||||
|
||||
// Step 3: Alter columns to be NOT NULL
|
||||
await queryRunner.query(`ALTER TABLE "accounts" ALTER COLUMN "account_number" SET NOT NULL`);
|
||||
await queryRunner.query(`ALTER TABLE "accounts" ALTER COLUMN "iban" SET NOT NULL`);
|
||||
|
||||
// Step 4: Add unique indexes
|
||||
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_ffd1ae96513bfb2c6eada0f7d3" ON "accounts" ("account_number")`);
|
||||
await queryRunner.query(`CREATE UNIQUE INDEX "IDX_9a4b004902294416b096e7556e" ON "accounts" ("iban")`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_9a4b004902294416b096e7556e"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_ffd1ae96513bfb2c6eada0f7d3"`);
|
||||
await queryRunner.query(`ALTER TABLE "accounts" DROP COLUMN "iban"`);
|
||||
await queryRunner.query(`ALTER TABLE "accounts" DROP COLUMN "account_number"`);
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
export * from './1753869637732-seed-default-avatar';
|
||||
export * from './1733750228289-initial-migration';
|
||||
export * from './1733990253208-seeds-default-tasks-logo';
|
||||
export * from './1734247702310-seeds-goals-categories';
|
||||
export * from './1733750228289-initial-migration';
|
||||
export * from './1753869637732-seed-default-avatar';
|
||||
export * from './1753874205042-add-neoleap-related-entities';
|
||||
export * from './1753948642040-add-account-number-and-iban-to-account-entity';
|
||||
|
Reference in New Issue
Block a user