Skip to content

Instantly share code, notes, and snippets.

@Ompluscator
Last active September 19, 2021 14:32
Aggregate
func (ca *CustomerAccount) GetIBANForCurrency(currency Currency) (string, error) {
for _, account := range ca.accounts {
if account.IsForCurrency(currency) {
return account.iban, nil
}
}
return "", errors.New("this account does not support this currency")
}
func (ca *CustomerAccount) MarkAsDeleted() error {
if ca.accounts.HasMoney() {
return errors.New("there are still money on bank account")
}
if ca.accounts.InDebt() {
return errors.New("bank account is in debt")
}
ca.isDeleted = true
return nil
}
func (ca *CustomerAccount) CreateAccountForCurrency(currency Currency) error {
if ca.accounts.HasCurrency(currency) {
return errors.New("there is already bank account for that currency")
}
ca.accounts = append(ca.accounts, NewBankAccount(currency))
return nil
}
func (ca *CustomerAccount) AddMoney(amount int, currency Currency) error {
if ca.isDeleted {
return errors.New("account is deleted")
}
if ca.isLocked {
return errors.New("account is locked")
}
return ca.accounts.AddMoney(amount, currency)
}
// entity
type Currency struct {
id uuid.UUID
//
// some fields
//
}
func (c Currency) Equal(other Currency) bool {
return c.id == other.id
}
// entity
type BankAccount struct {
id uuid.UUID
iban string
amount int
currency Currency
}
func NewBankAccount(currency Currency) BankAccount {
return BankAccount{
//
// define fields
//
}
}
func (ba BankAccount) HasMoney() bool {
return ba.amount > 0
}
func (ba BankAccount) InDebt() bool {
return ba.amount > 0
}
func (ba BankAccount) IsForCurrency(currency Currency) bool {
return ba.currency.Equal(currency)
}
type BankAccounts []BankAccount
func (bas BankAccounts) HasMoney() bool {
for _, ba := range bas {
if ba.HasMoney() {
return true
}
}
return false
}
func (bas BankAccounts) InDebt() bool {
for _, ba := range bas {
if ba.InDebt() {
return true
}
}
return false
}
func (bas BankAccounts) HasCurrency(currency Currency) bool {
for _, ba := range bas {
if ba.IsForCurrency(currency) {
return true
}
}
return false
}
// entity and aggregate
type CustomerAccount struct {
id uuid.UUID
isDeleted bool
//
// some fields
//
accounts BankAccounts
//
// some fields
//
}
func (ca *CustomerAccount) MarkAsDeleted() error {
if ca.accounts.HasMoney() {
return errors.New("there are still money on bank account")
}
if ca.accounts.InDebt() {
return errors.New("bank account is in debt")
}
ca.isDeleted = true
return nil
}
func (ca *CustomerAccount) CreateAccountForCurrency(currency Currency) error {
if ca.accounts.HasCurrency(currency) {
return errors.New("there is already bank account for that currency")
}
ca.accounts = append(o.accounts, NewBankAccount(currency))
return nil
}
type Person struct {
id uuid.UUID
//
// some fields
//
birthday time.Time
}
type Company struct {
id uuid.UUID
//
// some fields
//
isLiquid bool
}
type Customer struct {
id uuid.UUID
person *Person
company *Company
//
// some fields
//
}
func (c *Customer) IsLegal() bool {
if c.person != nil {
return c.person.birthday.AddDate(18, 0, 0).Before(time.Now())
} else {
return c.company.isLiquid
}
}
type Person struct {
id uuid.UUID // local identity
//
// some fields
//
}
type Company struct {
id uuid.UUID // local identity
//
// some fields
//
}
type Customer struct {
id uuid.UUID // global identity
person *Person
company *Company
//
// some fields
//
}
type CustomerAccount struct {
id uuid.UUID
//
// some fields
//
customer Customer // the wrong way with referencing
//
// some fields
//
}
type CustomerAccount struct {
id uuid.UUID
//
// some fields
//
customerID uuid.UUID // the right way with identity
//
// some fields
//
}
type Customer struct {
id uuid.UUID
person *Person
company *Company
//
// some fields
//
}
type CustomerRepository interface {
Search(ctx context.Context, specification CustomerSpecification) ([]Customer, error)
Create(ctx context.Context, customer Customer) (*Customer, error)
UpdatePerson(ctx context.Context, customer Customer) (*Customer, error)
UpdateCompany(ctx context.Context, customer Customer) (*Customer, error)
//
// and many other methods
//
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment