Skip to content

Commit

Permalink
add domain entities and ports
Browse files Browse the repository at this point in the history
  • Loading branch information
mirexdoors committed Jun 8, 2021
1 parent 99fd9e7 commit 9e0b01f
Show file tree
Hide file tree
Showing 11 changed files with 981 additions and 783 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@nestjs/common": "^7.6.15",
"@nestjs/core": "^7.6.15",
"@nestjs/platform-express": "^7.6.15",
"bignumber.js": "^9.0.1",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^6.6.6"
Expand Down
64 changes: 64 additions & 0 deletions src/domains/entities/account.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { MoneyEntity } from './money.entity';
import { ActivityWindowEntity } from './activity-window.entity';
import { ActivityEntity } from './activity.entity';

export type AccountId = string;

export class AccountEntity {
constructor(
private readonly _id: AccountId,
private readonly _baseLineBalance: MoneyEntity,
private readonly _activityWindow: ActivityWindowEntity,
) {}

get id(): string {
return this._id;
}

get baseLineBalance(): MoneyEntity {
return this._baseLineBalance;
}

get activityWindow(): ActivityWindowEntity {
return this._activityWindow;
}

public calculateBalance(): MoneyEntity {
return MoneyEntity.add(
this._baseLineBalance,
this._activityWindow.calculateBalance(this.id),
);
}

public withdraw(money: MoneyEntity, targetAccountId: AccountId): boolean {
if (!this._mayWithdrawMoney(money)) {
return false;
}

const withdrawal: ActivityEntity = new ActivityEntity(
this.id,
targetAccountId,
new Date(),
money,
);

this._activityWindow.addActivity(withdrawal);
return true;
}

public deposite(money: MoneyEntity, sourceAccountId: AccountId): boolean {
const deposite: ActivityEntity = new ActivityEntity(
sourceAccountId,
this.id,
new Date(),
money,
);

this._activityWindow.addActivity(deposite);
return true;
}

private _mayWithdrawMoney(money: MoneyEntity) {
return MoneyEntity.add(this.calculateBalance(), money.negate());
}
}
30 changes: 30 additions & 0 deletions src/domains/entities/activity-window.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ActivityEntity } from './activity.entity';
import { AccountId } from './account.entity';
import { MoneyEntity } from './money.entity';

export class ActivityWindowEntity {
private readonly _activities: ActivityEntity[] = [];

get activities(): ActivityEntity[] {
return this._activities;
}

addActivity(activity: ActivityEntity) {
this.activities.push(activity);
return this;
}

public calculateBalance(accountId: AccountId): MoneyEntity {
const depositeBalance = this.activities
.filter((activity) => activity.targetAccountId === accountId)
.map((activity) => activity.money)
.reduce(MoneyEntity.add, MoneyEntity.ZERO());

const withdrawalBalance = this.activities
.filter((activity) => activity.sourceAccountId === accountId)
.map((activity) => activity.money)
.reduce(MoneyEntity.add, MoneyEntity.ZERO());

return MoneyEntity.add(depositeBalance, withdrawalBalance.negate());
}
}
27 changes: 27 additions & 0 deletions src/domains/entities/activity.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { AccountId } from './account.entity';
import { MoneyEntity } from './money.entity';

export class ActivityEntity {
constructor(
private readonly _sourceAccountId: AccountId,
private readonly _targetAccountId: AccountId,
private readonly _timestamp: Date,
private readonly _money: MoneyEntity,
) {}

get sourceAccountId(): string {
return this._sourceAccountId;
}

get targetAccountId(): string {
return this._targetAccountId;
}

get timestamp(): Date {
return this._timestamp;
}

get money(): MoneyEntity {
return this._money;
}
}
29 changes: 29 additions & 0 deletions src/domains/entities/money.entity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { BigNumber } from 'bignumber.js';

export class MoneyEntity {
constructor(private readonly _amount: BigNumber) {}

static ZERO() {
return new MoneyEntity(new BigNumber(0));
}

static of(value: number) {
return new MoneyEntity(new BigNumber(value));
}

get amount(): BigNumber {
return this._amount;
}

static add(a: MoneyEntity, b: MoneyEntity): MoneyEntity {
return new MoneyEntity(a.amount.plus(b.amount));
}

negate() {
return new MoneyEntity(this.amount.negated());
}

isPositiveOrZero(): boolean {
return this.amount.comparedTo(0) >= 0;
}
}
5 changes: 5 additions & 0 deletions src/domains/ports/in/get-account-balance.query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {AccountId} from "../../entities/account.entity";

export interface GetAccountBalanceQuery {
getAccountBalance(accountId: AccountId);
}
22 changes: 22 additions & 0 deletions src/domains/ports/in/send-money.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { AccountId } from '../../entities/account.entity';
import { MoneyEntity } from '../../entities/money.entity';

export class SendMoneyCommand {
constructor(
private readonly _sourceAccountId: AccountId,
private readonly _targetAccountId: AccountId,
private readonly _money: MoneyEntity,
) {}

get sourceAccountId(): string {
return this._sourceAccountId;
}

get targetAccountId(): string {
return this._targetAccountId;
}

get money(): MoneyEntity {
return this._money;
}
}
5 changes: 5 additions & 0 deletions src/domains/ports/in/send-money.use-case.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SendMoneyCommand } from './send-money.command';

export interface SendMoneyUseCase {
sendMoney(command: SendMoneyCommand);
}
5 changes: 5 additions & 0 deletions src/domains/ports/out/load-account.port.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AccountId } from '../../entities/account.entity';

export interface LoadAccountPort {
loadAccount(accountId: AccountId);
}
5 changes: 5 additions & 0 deletions src/domains/ports/out/update-account-state.port.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { AccountEntity } from '../../entities/account.entity';

export interface UpdateAccountStatePort {
updateActivities(account: AccountEntity);
}
Loading

0 comments on commit 9e0b01f

Please sign in to comment.