会计系统领域驱动设计

问题描述

我正在为我正在开发的会计系统遵循 DDD 方法

有两部分(见下面的域):

  1. 创建交易:当现金从分类帐转移到客户的帐户或从一个分类帐转移到另一个分类帐时,将创建一个交易(AccountingTransaction)作为父项(聚合根)。一笔交易可以是多方的,即 Transaction(AccountingTransaction) 可以有多个 LedgerTransaction 或 CashTransaction。
  2. Reconcile accounts:我需要每天匹配每个分类账中的贷方和借方。

这是我的域的样子:

  1. AccountingTransaction 是聚合根。
  2. LedgerTransaction 和 CashTransaction 是 AccountingTransaction 的子实体。
  3. AccountingTransaction 将包含 CashTransactions 和 LedgerTransactions 的列表。
  4. 分类帐是总根。
 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<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,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(请参阅域类)为空。然后我需要确保所有借方和贷方总和为 0 - 如果不是,我需要报告错误。匹配的借方和贷方也可能属于不同的聚合根 (AccountingTransaction)。这也意味着我需要在聚合根(AccountingTransaction)之外获取 Ledger 交易,这是针对 DDD 的,然后可能直接在 LedgerTransactions 表上进行写操作。

请告知我应该如何处理这个问题。域类是否存在缺陷?

感谢您的帮助。

谢谢!

解决方法

该域名乍一看不错。这里有几个选项:

  1. 获取所有具有未对帐分类帐交易的 AccountingTransaction 并将它们全部传递以执行对帐服务。这将需要您将一些域逻辑放入存储库(了解什么是未协调事务),但这应该没问题。

  2. 使 LedgerTransaction 成为自己的聚合根。

,

这种冲突表明 LedgerTransaction 希望成为聚合根。