var legacyDetails = _migration.TransactionDetails
.Where(x => x.TransactionID.Equals(legacy.TransactionID))
.Where(x => x.DetailRowType.In("H", "M", "X"))
.OrderBy(x => x.DetailRowOrder)
if (type.Equals(TransactionType.PayrollRemittance))
var header = legacyDetails.First();
header.DetailRowType = "H";
var header = legacyDetails
.Where(x => x.DetailRowType.Equals("H"))
var mandatoryAccountId = _migration.MandatoryAccountSettings
.First().RetainedEarningsAccountID;
legacyDetails.Add(header);
legacyDetails.Add(new Legacy.Models.TransactionDetails()
TransactionDetailType = "O",
AccountID = mandatoryAccountId,
Description = header.Description,
Column = header.Column.Equals("C") ? "D" : "C",
foreach (var legacyDetail in legacyDetails)
var detailType = Legacy.EnumConverters.TransactionDetailTypeForCode(legacyDetail.TransactionDetailType);
var personId = GetNewId(legacyDetail.ContactID);
if (legacyDetail.DetailRowType.Equals("H"))
switch (transaction.Type)
case TransactionType.BankTransfer:
detailType = TransactionDetailType.BankTransfer;
case TransactionType.Deposit:
detailType = TransactionDetailType.Deposit;
if (string.IsNullOrEmpty(legacy.PSAContactID))
var cashSale = _migration.Contacts.SingleOrDefault(x => x.CompanyName.Equals("Cash Sale"));
personId = GetNewId(cashSale.ContactID);
personId = GetNewId(legacy.PSAContactID);
case TransactionType.Withdrawal:
detailType = TransactionDetailType.Withdrawal;
if (string.IsNullOrEmpty(legacy.PSAContactID))
var oneTimeSupplier = _migration.Contacts.SingleOrDefault(x => x.CompanyName.Equals("One Time Supplier"));
personId = GetNewId(oneTimeSupplier.ContactID);
personId = GetNewId(legacy.PSAContactID);
if (RequiresNumber(type))
var accountId = await GetNewAccountIdAsync(subscriptionId, legacyDetail.AccountID);
var account = await _dbContext.Accounts.SingleAsync(x => x.Id.Equals(accountId));
var multiplier = ColumnMultiplier(detailType, account, legacyDetail.Column);
var detail = new TransactionDetail()
Description = legacyDetail.Description,
if (type.In(TransactionType.GeneralJournal, TransactionType.Inventory, TransactionType.OpeningBalance) || legacyDetail.ScreenAmount.Equals(0M))
detail.Amount = legacyDetail.Amount * multiplier;
detail.Quantity = legacyDetail.Quantity * multiplier;
var taxType = Legacy.EnumConverters.TransactionDetailTaxforCode(legacyDetail.TaxCode);
detail.AmountBeforeTax = legacyDetail.ScreenAmount * multiplier;
detail.Amount = amount * multiplier;
detail.GstAmount = legacyDetail.ScreenGSTAmount * multiplier;
detail.PstAmount = legacyDetail.ScreenPSTAmount * multiplier;
detail.Quantity = legacyDetail.Quantity * multiplier;
case TransactionDetailType.PayablePayment:
case TransactionDetailType.ReceivablePayment:
detail.PaymentForId = transactionIds[legacyDetail.TransactionIDBeingPaidOff];
case TransactionDetailType.CapitalAssetPurchase:
case TransactionDetailType.CapitalAssetSale:
detail.CapitalAssetId = GetNewId(legacyDetail.CapitalAssetID);
transaction.Details.Add(detail);
var result = await _transactionService.CreateAsync(subscriptionId, fiscalYear.Id, transaction);
transactionIds.Add(legacy.TransactionID, result.Id);
foreach (var post in result.Details.SelectMany(x => x.Posts))
var account = await _accountService.GetAsync(subscriptionId, post.AccountId);
if ((account.Group.Type.IsDebitAccount() && post.Amount > 0) || (account.Group.Type.IsCreditAccount() && post.Amount < 0))
debits += Math.Abs(post.Amount);
credits += Math.Abs(post.Amount);
var legacyPosts = _migration.TransactionDetails.Where(x => x.TransactionID.Equals(legacy.TransactionID));
if (!legacyPosts.Where(x => x.Column.Equals("D")).Sum(x => x.Amount).Equals(debits) ||
!legacyPosts.Where(x => x.Column.Equals("C")).Sum(x => x.Amount).Equals(credits))
throw new InvalidDataException("Posts do not match.");