6
\$\begingroup\$

I recently discovered/came across and have been trying to learn and utilize its features. Here's my first function UpdateTransactionsData(). This method is for a PurchaseDocument class which I have included partially. Basically this function loops through the selected items on the PurchaseDocument, and works out which accounts (chart of accounts, as per accounting) are to be credited/debited for each purchased item.

After I have populated the dictionary properties with the transaction amounts, I use Linq to first remove all the transactions with amount 0 and then to generate XML elements to represent the transactions (provided a sample of the output).

The code works. Am I using LINQ right? Is the code optimal? Can I improve the LINQ code? Should I even be using it?

XmlOutput

<Debit Account="26" Amount="36" />
<Debit Account="24" Amount="188.7" />
<Debit Account="80" Amount="-29.21" />
<Credit Account="57" Amount="253.91" />
<Inventory Item="22007" Adjustment="10" />
<Inventory Item="11389" Adjustment="5" />

PurchaseDocument.cs

public class PurchaseDocument
{
    public Dictionary<int, double> DebitTransactions = new Dictionary<int, double>();
    public Dictionary<int, double> CreditTransactions = new Dictionary<int, double>();
    public Dictionary<int, double> InventoryTransactions = new Dictionary<int, double>();

    #region public ObservableCollection<PurchaseDocumentItem> Items;
    private ObservableCollection<PurchaseDocumentItem> _Items = new ObservableCollection<PurchaseDocumentItem>();
    public ObservableCollection<PurchaseDocumentItem> Items
    {
        get { return _Items; }
        set
        {
            string property = "Items";
            OnPropertyChanging(property);
            _Items = value;
            OnPropertyChanged(property);
        }
    }
    #endregion

    private void UpdateTransactionsData()
    {
        DebitTransactions.Clear();
        CreditTransactions.Clear();
        InventoryTransactions.Clear();
        Entity.TransactionsData = "";

        foreach (PurchaseDocumentItem item in Items.Where(x => x.InventoryItem != null))
        {
            // asset and expense transactions
            int account = (item.InventoryItem.IsService) ? item.InventoryItem.CogsAccountID : item.InventoryItem.AssetAccountID;
            if(!DebitTransactions.ContainsKey(account))
                DebitTransactions.Add(account, 0);
            DebitTransactions[account] += item.Amount;

            // inventory transaction
            if (!item.InventoryItem.IsService)
            {
                if(!InventoryTransactions.ContainsKey(item.ItemID))
                    InventoryTransactions.Add(item.ItemID, 0);
                InventoryTransactions[item.ItemID] += item.Quantity;
            }
        }

        // tax transaction
        int taxaccount = Session.Company.PurchasesTaxAccountID;
        if(!DebitTransactions.ContainsKey(taxaccount))
            DebitTransactions.Add(taxaccount, 0);
        DebitTransactions[taxaccount] -= (double)Tax;

        // freight transaction
        int freightaccount = Session.Company.FreightExpenseAccountID;
        if(!DebitTransactions.ContainsKey(freightaccount))
            DebitTransactions.Add(freightaccount, 0);
        DebitTransactions[freightaccount] += (double)Freight;

        // payables transaction
        int payablesaccount = Session.Company.AccountsPayableID;
        if(!CreditTransactions.ContainsKey(payablesaccount))
            CreditTransactions.Add(payablesaccount, 0);
        CreditTransactions[payablesaccount] += (double)Total;

        // take out all transaction with amount 0
        DebitTransactions = DebitTransactions.Where(x => x.Value != 0).ToDictionary(x => x.Key, x => x.Value);
        CreditTransactions = CreditTransactions.Where(x => x.Value != 0).ToDictionary(x => x.Key, x => x.Value);
        InventoryTransactions = InventoryTransactions.Where(x => x.Value != 0).ToDictionary(x => x.Key, x => x.Value);

        // convert the data to xml
        Entity.TransactionsData += DebitTransactions.Aggregate("", (data, t) => data + "<Debit Account=\"" + t.Key.ToString()  + "\" Amount=\"" + t.Value.ToString() + "\" />" + Environment.NewLine);
        Entity.TransactionsData += CreditTransactions.Aggregate("", (data, t) => data + "<Credit Account=\"" + t.Key.ToString() + "\" Amount=\"" + t.Value.ToString() + "\" />" + Environment.NewLine);
        Entity.TransactionsData += InventoryTransactions.Aggregate("", (data, t) => data + "<Inventory Item=\"" + t.Key.ToString() + "\" Adjustment=\"" + t.Value.ToString() + "\" />" + Environment.NewLine);
    }
}
\$\endgroup\$
2
\$\begingroup\$

I don't see any problem with the LINQ you have.

If you wanted, you could use a little bit of LINQ to get rid of that foreach loop you have. You can create two LINQ queries to query the Items collection, group accounts/items together, and return the sum of the Amounts/Quantities as a Dictionary:

DebitTransactions = (from item in Items
                     where item.InventoryItem != null

                     let account = (item.InventoryItem.IsService) ? item.InventoryItem.CogsAccountID : item.InventoryItem.AssetAccountID

                     group item by account into itemGroup
                     select new 
                     {
                        Account = itemGroup.Key,
                        Amount = itemGroup.Sum(i => i.Amount)
                     }).ToDictionary(k => k.Account, v => v.Amount);

InventoryTransactions = (from item in Items
                         where item.InventoryItem != null && !item.InventoryItem.IsService

                         group item by item.ItemID into itemGroup
                         select new
                         {
                            ItemID = itemGroup.Key
                            Quantity = itemGroup.Sum(i => i.Quantity)
                         }).ToDictionary(k => k.ItemID, v => v.Quantity);

It's a little more messy and probably a little less efficient, but good for learning LINQ.

\$\endgroup\$
  • \$\begingroup\$ Ahh that's great, thanks for your help! Learning a few more things from your code :) \$\endgroup\$ – Saad Imran. Aug 24 '11 at 20:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.