1

私が開発している会計システムの DDD アプローチに従っています。

2 つの部分があります (以下のドメインを参照)。

  1. トランザクションの作成: トランザクション (AccountingTransaction) は、現金が元帳からクライアントのアカウントに、またはその逆に、またはある元帳から別の元帳に移動されるときに、親 (集約ルート) として作成されます。つまり、Transaction(AccountingTransaction) は複数の LedgerTransaction または CashTransaction を持つことができます。
  2. アカウントの照合 : 各元帳の貸方と借方を毎日照合する必要があります。

これは私のドメインがどのように見えるかです:

  1. AccountingTransaction は集約ルートです。
  2. LedgerTransaction と CashTransaction は、AccountingTransaction の子エンティティです。
  3. AccountingTransaction には、CashTransactions と LedgerTransactions のリストがあります。
  4. Ledger は集約ルートです。
 public class AccountingTransaction : AggregateRoot
    {
        public string AccountingTransactionId { get; private set; }
        public TransactionStatus TransactionStatus { get; private set; } //enum
        
        private List<CashTransaction> _cashTransactions = new List<CashTransaction>();
        public IReadOnlyList<CashTransaction> CashTransactions => new ReadOnlyCollection<CashTransaction>(_cashTransactions);
        private List<LedgerTransaction> _ledgerTransactions = new List<LedgerTransaction>();
        public IReadOnlyList<LedgerTransaction> LedgerTransactions => new ReadOnlyCollection<LedgerTransaction>(_ledgerTransactions);
        private AccountingTransaction(string transactionId, List<CashTransaction> cashTransactions, List<LedgerTransaction> ledgerTransactions, TransactionStatus transactionStatus)
        {
            //Code omitted for brevity
        }
        public static IResult<AccountingTransaction> CreateTransaction(string transactionId, List<CashTransaction> cashTransactions, List<LedgerTransaction> ledgerTransactions, List<ClientAccount> clientAccounts, List<Ledger> ledgerAccounts)
        {
            
            //Factory method
            //Maintain invaraint and creates a new transaction
        }
        public IResult CancelTransaction(string username)
        {
            
        }
    }

 public class LedgerTransaction
    {
        public int Id { get; private set; }
        public string LedgerAccountId { get; private set; }
        public string TransactionId { get; private set; }
        public string EntryDescription { get; private set; }
        public DateTime? ReconciledOn { get; private set; }
        public TransactionAmount TransactionAmount { get; private set; } //Value object
        private LedgerTransaction(int id, TransactionAmount transactionAmount,
            string transactionId,
            string entryDescription,
            string batchId,
            string ledgerAccountId)
        {
            //Code omitted for brevity
        }

        internal static IResult<LedgerTransaction> CreateTransaction(/*List of arguments*/)
        {
            //Factory method
            //Code omitted for brevity
        }
    }

public class CashTransaction
    {
        public int Id { get; private set; }
        public string ClientAccountId { get; private set; }
        public string TransactionId { get; private set; }
        public TransactionAmount TransactionAmount { get; private set; }//Value object
        public string EntryDescription { get; private set; }
        private CashTransaction(int id, 
            TransactionAmount transactionAmount,
            string transactionId,
            string entryDescription,
            string clientAccountId)
        {
            Id = id;
            TransactionAmount = transactionAmount;
            TransactionId = transactionId;
            EntryDescription = entryDescription;
            ClientAccountId = clientAccountId;
        }
        internal static IResult<CashTransaction> CreateTransaction(/*List of arguments*/)
        {
            //Factory method
            //Code omitted for brevity
        }
    }

public class Ledger : AggregateRoot
    {
        public string AccountId { get; private set; }
        public string Name { get; private set; }
        public LedgerType LedgerType { get; set; }
        public Currency Currency { get; private set; }
    }

したがって、最初の部分 (トランザクションの作成) は非常にうまく機能し、元帳勘定の調整にどのようにアプローチするべきかについて悩んでいます。

問題:アカウントを調整するには、特定の日に、ReconciledOn (ドメイン クラスを参照) が null である特定の Ledger に属するすべての Ledger トランザクションを取得する必要があります。次に、すべての借方と貸方の合計が 0 であることを確認する必要があります。そうでない場合は、エラーを報告する必要があります。一致する借方と貸方が異なる集約ルート (AccountingTransaction) に属することも可能です。これは、集約ルート (AccountingTransaction) の外で Ledger トランザクションを取得する必要があることも意味します。これは DDD に反しており、おそらく LedgerTransactions テーブルに対して直接書き込み操作を実行します。

これにどのようにアプローチすればよいかアドバイスしてください。ドメインクラスに欠陥はありますか?

私はあなたの助けに感謝します。

ありがとうございました!

4

2 に答える 2