public void AddPurchaseInvoice(PurchaseInvoiceHeader purchaseIvoice, int? purchaseOrderId)
        {
            #region Auto create purchase order
            if (!purchaseOrderId.HasValue)
            {
                var po = new PurchaseOrderHeader()
                {
                    Date = purchaseIvoice.Date,
                    No = GetNextNumber(SequenceNumberTypes.PurchaseOrder).ToString(),
                    Vendor = purchaseIvoice.Vendor,
                    VendorId = purchaseIvoice.VendorId.Value,
                    Description = purchaseIvoice.Description,
                };
                foreach (var line in purchaseIvoice.PurchaseInvoiceLines)
                {
                    var item = _itemRepo.GetById(line.ItemId);

                    po.PurchaseOrderLines.Add(new PurchaseOrderLine()
                    {
                        ItemId = item.Id,
                        MeasurementId = line.MeasurementId,
                        Quantity = line.Quantity,
                        Cost = item.Cost.Value,
                        Discount = line.Discount.HasValue ? line.Discount.Value : 0,
                        Amount = item.Cost.Value * line.Quantity,
                    });
                }
                purchaseIvoice.PurchaseOrders.Add(po);

                var poReceipt = new PurchaseReceiptHeader()
                {
                    Date = DateTime.Now,
                    Vendor = po.Vendor,
                    VendorId = po.VendorId.Value,
                    PurchaseOrderHeaderId = po.Id,
                };

                foreach (var line in purchaseIvoice.PurchaseInvoiceLines)
                {
                    poReceipt.PurchaseReceiptLines.Add(new PurchaseReceiptLine()
                    {
                        ItemId = line.ItemId,
                        MeasurementId = line.MeasurementId,
                        Quantity = line.Quantity,
                        ReceivedQuantity = (line.ReceivedQuantity.HasValue ? line.ReceivedQuantity.Value : 0),
                        Cost = line.Cost.Value,
                        Amount = line.Cost.Value * (line.ReceivedQuantity.HasValue ? line.ReceivedQuantity.Value : 0),
                    });
                }

                po.PurchaseReceipts.Add(poReceipt);

                AddPurchaseOrderReceipt(poReceipt);
            }
            #endregion

            var glHeader = _financialService.CreateGeneralLedgerHeader(DocumentTypes.PurchaseInvoice, purchaseIvoice.Date, purchaseIvoice.Description);

            decimal totalTaxAmount = 0, totalAmount = 0, totalDiscount = 0;
            var taxes = new List<KeyValuePair<int, decimal>>();

            foreach (var line in purchaseIvoice.PurchaseInvoiceLines)
            {
                var lineTaxes = _financialService.ComputeInputTax(purchaseIvoice.VendorId.Value, line.ItemId, line.Quantity, line.Cost.Value, decimal.Zero);

                var lineAmount = line.Quantity * line.Cost;

                var totalLineAmount = lineAmount + lineTaxes.Sum(t => t.Value);

                totalAmount += (decimal)totalLineAmount;

                foreach (var t in lineTaxes)
                    taxes.Add(t);
            }

            if (taxes != null && taxes.Count > 0)
            {
                var groupedTaxes = from t in taxes
                           group t by t.Key into grouped
                           select new
                           {
                               Key = grouped.Key,
                               Value = grouped.Sum(t => t.Value)
                           };

                totalTaxAmount = taxes.Sum(t => t.Value);

                foreach (var tax in groupedTaxes)
                {
                    var tx = _financialService.GetTaxes().Where(t => t.Id == tax.Key).FirstOrDefault();
                    var debitPurchaseTaxAccount = _financialService.CreateGeneralLedgerLine(DrOrCrSide.Dr, tx.PurchasingAccountId.Value, tax.Value);
                    glHeader.GeneralLedgerLines.Add(debitPurchaseTaxAccount);
                }
            }

            if (totalDiscount > 0)
            {

            }

            Vendor vendor = _vendorRepo.GetById(purchaseIvoice.VendorId.Value);
            var creditVendorAccount = _financialService.CreateGeneralLedgerLine(DrOrCrSide.Cr, vendor.AccountsPayableAccountId.Value, totalAmount);
            glHeader.GeneralLedgerLines.Add(creditVendorAccount);

            var debitGRNClearingAccount = _financialService.CreateGeneralLedgerLine(DrOrCrSide.Dr, GetGeneralLedgerSetting().GoodsReceiptNoteClearingAccountId.Value, totalAmount - totalTaxAmount);
            glHeader.GeneralLedgerLines.Add(debitGRNClearingAccount);

            if (_financialService.ValidateGeneralLedgerEntry(glHeader))
            {
                purchaseIvoice.GeneralLedgerHeader = glHeader;

                purchaseIvoice.No = GetNextNumber(SequenceNumberTypes.PurchaseInvoice).ToString();
                _purchaseInvoiceRepo.Insert(purchaseIvoice);

                // TODO: Look for other way to update the purchase order's invoice header id field so that it shall be in a single transaction along with purchase invoice saving
                var purchOrder = _purchaseOrderRepo.GetById(purchaseOrderId.Value);
                purchOrder.PurchaseInvoiceHeaderId = purchaseIvoice.Id;
                _purchaseOrderRepo.Update(purchOrder);
            }
        }
        public ActionResult AddPurchaseReceipt(Models.ViewModels.Purchases.AddPurchaseReceipt model)
        {
            bool hasChanged = false;
            foreach (var line in model.PurchaseReceiptLines)
            {
                if (line.InQty.HasValue && line.InQty.Value != 0)
                {
                    hasChanged = true;
                    break;
                }
            }

            if (!hasChanged)
                return RedirectToAction("PurchaseOrders");

            var po = _purchasingService.GetPurchaseOrderById(model.Id);

            var poReceipt = new PurchaseReceiptHeader()
            {
                Date = DateTime.Now,
                Vendor = po.Vendor,
                VendorId = po.VendorId.Value,
                PurchaseOrderHeaderId = po.Id,
            };

            foreach (var receipt in model.PurchaseReceiptLines)
            {
                if((receipt.InQty + receipt.ReceiptQuantity) > receipt.Quantity)
                    return RedirectToAction("PurchaseOrders");

                poReceipt.PurchaseReceiptLines.Add(new PurchaseReceiptLine()
                {
                    PurchaseOrderLineId = receipt.PurchaseOrderLineId,
                    ItemId = receipt.ItemId,
                    MeasurementId = receipt.UnitOfMeasurementId,
                    Quantity = receipt.Quantity,
                    ReceivedQuantity = (receipt.InQty.HasValue ? receipt.InQty.Value : 0),
                    Cost = receipt.Cost.Value,
                    Amount = receipt.Cost.Value * (receipt.InQty.HasValue ? receipt.InQty.Value : 0),
                });
            }

            _purchasingService.AddPurchaseOrderReceipt(poReceipt);
            return RedirectToAction("PurchaseOrders");
        }
        public void AddPurchaseOrderReceipt(PurchaseReceiptHeader purchaseOrderReceipt)
        {
            var glLines = new List<GeneralLedgerLine>();
            decimal totalAmount = purchaseOrderReceipt.PurchaseReceiptLines.Sum(d => d.Amount);
            decimal taxAmount = purchaseOrderReceipt.GetTotalTax();
            decimal totalDiscount = 0;

            foreach (var lineItem in purchaseOrderReceipt.PurchaseReceiptLines)
            {
                var item = _itemRepo.GetById(lineItem.ItemId);
                decimal lineItemTotalAmountAfterTax = lineItem.Amount - lineItem.LineTaxAmount;

                GeneralLedgerLine debitInventory = _financialService.CreateGeneralLedgerLine(DrOrCrSide.Dr, item.InventoryAccount.Id, lineItemTotalAmountAfterTax);
                glLines.Add(debitInventory);

                GeneralLedgerLine creditGRNClearingAccount = _financialService.CreateGeneralLedgerLine(DrOrCrSide.Cr, GetGeneralLedgerSetting().GoodsReceiptNoteClearingAccountId.Value, lineItemTotalAmountAfterTax);
                glLines.Add(creditGRNClearingAccount);

                lineItem.InventoryControlJournal = _inventoryService.CreateInventoryControlJournal(lineItem.ItemId,
                    lineItem.MeasurementId,
                    DocumentTypes.PurchaseReceipt,
                    lineItem.ReceivedQuantity,
                    null,
                    lineItem.ReceivedQuantity * item.Cost,
                    null);
            }

            if (taxAmount > 0)
            {
            }

            if (totalDiscount > 0)
            {
            }

            GeneralLedgerHeader glHeader = _financialService.CreateGeneralLedgerHeader(DocumentTypes.PurchaseReceipt, purchaseOrderReceipt.Date, string.Empty);
            glHeader.GeneralLedgerLines = glLines;

            if (_financialService.ValidateGeneralLedgerEntry(glHeader))
            {
                purchaseOrderReceipt.GeneralLedgerHeader = glHeader;

                purchaseOrderReceipt.No = GetNextNumber(SequenceNumberTypes.PurchaseReceipt).ToString();
                _purchaseReceiptRepo.Insert(purchaseOrderReceipt);
            }
        }