/// <summary>
        /// Saves a new batchoutput or updates an already existing BatchOutPut.
        /// </summary>
        /// <param name="Batch">BatchOutPut to be saved or updated.</param>
        /// <param name="BatchId">BatchOutPutId of the BatchOutPut creating or updating</param>
        /// <returns>BatchOutPutId</returns>
        public long SaveBatchOutPut(BatchOutPutDTO batchOutPutDTO, string userId)
        {
            long batchOutPutId = 0;

            if (batchOutPutDTO.BatchOutPutId == 0)
            {
                var batchOutPut = new BatchOutPut()
                {
                    Loss            = batchOutPutDTO.Loss,
                    FlourOutPut     = batchOutPutDTO.FlourOutPut,
                    BrandOutPut     = batchOutPutDTO.BrandOutPut,
                    BatchId         = batchOutPutDTO.BatchId,
                    LossPercentage  = batchOutPutDTO.LossPercentage,
                    BrandPercentage = batchOutPutDTO.BrandPercentage,
                    FlourPercentage = batchOutPutDTO.FlourPercentage,
                    BranchId        = batchOutPutDTO.BranchId,
                    SectorId        = batchOutPutDTO.SectorId,
                    CreatedOn       = DateTime.Now,
                    TimeStamp       = DateTime.Now,
                    CreatedBy       = userId,
                    Deleted         = false,
                };

                this.UnitOfWork.Get <BatchOutPut>().AddNew(batchOutPut);
                this.UnitOfWork.SaveChanges();
                batchOutPutId = batchOutPut.BatchOutPutId;


                return(batchOutPutId);
            }

            else
            {
                var result = this.UnitOfWork.Get <BatchOutPut>().AsQueryable()
                             .FirstOrDefault(e => e.BatchOutPutId == batchOutPutDTO.BatchOutPutId);
                if (result != null)
                {
                    result.Loss            = batchOutPutDTO.Loss;
                    result.FlourOutPut     = batchOutPutDTO.FlourOutPut;
                    result.BrandOutPut     = batchOutPutDTO.BrandOutPut;
                    result.BatchId         = batchOutPutDTO.BatchId;
                    result.LossPercentage  = batchOutPutDTO.LossPercentage;
                    result.BrandPercentage = batchOutPutDTO.BrandPercentage;
                    result.FlourPercentage = batchOutPutDTO.FlourPercentage;
                    result.SectorId        = batchOutPutDTO.SectorId;
                    result.BranchId        = batchOutPutDTO.BranchId;
                    result.UpdatedBy       = userId;
                    result.TimeStamp       = DateTime.Now;
                    result.Deleted         = batchOutPutDTO.Deleted;
                    result.DeletedBy       = batchOutPutDTO.DeletedBy;
                    result.DeletedOn       = batchOutPutDTO.DeletedOn;

                    this.UnitOfWork.Get <BatchOutPut>().Update(result);
                    this.UnitOfWork.SaveChanges();
                }
                return(batchOutPutDTO.BatchOutPutId);
            }
        }
        public long Save(BatchOutPut model)
        {
            var batchOutPutId = _batchOutPutService.SaveBatchOutPut(model, userId);

            return(batchOutPutId);
        }
        /// <summary>
        /// Maps Batch EF object to Batch Model Object and
        /// returns the Batch model object.
        /// </summary>
        /// <param name="result">EF Batch object to be mapped.</param>
        /// <returns>Batch Model Object.</returns>
        public Batch MapEFToModel(EF.Models.Batch data)
        {
            var batch = new Batch()
            {
                BatchId  = data.BatchId,
                Name     = data.Name,
                Quantity = data.Quantity,
                BranchId = data.BranchId,

                BranchName = data.Branch != null ? data.Branch.Name : "",
                SectorName = data.Sector != null ? data.Sector.Name : "",
                SectorId   = data.SectorId,
                CreatedOn  = data.CreatedOn,
                TimeStamp  = data.TimeStamp,
                Deleted    = data.Deleted,
                BranchMillingChargeRate = data.Branch != null? data.Branch.MillingChargeRate:0,
                CreatedBy = _userService.GetUserFullName(data.AspNetUser),
                UpdatedBy = _userService.GetUserFullName(data.AspNetUser1),
            };


            var batchOutPuts = GetAllBatchOutPutsForABatch(data.BatchId);
            List <BatchOutPut> batchOutPutList = new List <BatchOutPut>();

            if (batchOutPuts.Any())
            {
                foreach (var outPut in batchOutPuts)
                {
                    var batchOutPut = new BatchOutPut()
                    {
                        Grades          = outPut.Grades,
                        TotalBuveraCost = outPut.TotalBuveraCost,
                        TotalQuantity   = outPut.TotalQuantity,
                        BrandOutPut     = outPut.BrandOutPut,
                        FlourPercentage = outPut.FlourPercentage,
                        BrandPercentage = outPut.BrandPercentage,
                        FlourOutPut     = outPut.FlourOutPut,
                        LossPercentage  = outPut.LossPercentage,
                        Loss            = outPut.Loss,
                    };
                    batchOutPutList.Add(batchOutPut);
                    batch.TotalBuveraCost = batchOutPut.TotalBuveraCost;
                    batch.TotalQuantity   = batchOutPut.TotalQuantity;
                    batch.FlourOutPut     = batchOutPut.FlourOutPut;
                    batch.LossPercentage  = batchOutPut.LossPercentage;
                    batch.Loss            = Convert.ToDouble(batchOutPut.Loss);
                    batch.BrandOutPut     = batchOutPut.BrandOutPut;
                    batch.BrandPercentage = batchOutPut.BrandPercentage;
                    batch.FlourPercentage = batchOutPut.FlourPercentage;
                    batch.Grades          = batchOutPut.Grades;
                }
            }
            batch.MillingCharge = batch.BranchMillingChargeRate * batch.FlourOutPut;

            var    otherExpenses    = GetAllOtherExpensesForABatch(data.BatchId);
            double otherExpenseCost = 0;
            List <OtherExpense> otherExpenseList = new List <OtherExpense>();

            if (otherExpenses.Any())
            {
                foreach (var other in otherExpenses)
                {
                    var otherExpense = new OtherExpense()
                    {
                        Amount      = other.Amount,
                        Description = other.Description,
                    };
                    otherExpenseList.Add(otherExpense);
                    otherExpenseCost = otherExpenseCost + other.Amount;
                }
                batch.TotalOtherExpenseCost = otherExpenseCost;
                batch.OtherExpenses         = otherExpenseList;
            }

            var            utilities   = GetAllUtilitiesForABatch(data.BatchId);
            double         utilityCost = 0;
            List <Utility> utilityList = new List <Utility>();

            if (utilities.Any())
            {
                foreach (var utility in utilities)
                {
                    var utilityObject = new Utility()
                    {
                        Amount      = utility.Amount,
                        Description = utility.Description,
                    };
                    utilityList.Add(utility);
                    utilityCost = utilityCost + utility.Amount;
                }
                batch.TotalUtilityCost = utilityCost;
                batch.Utilities        = utilityList;
            }

            var    factoryExpenses     = GetAllFactoryExpensesForABatch(data.BatchId);
            double totalFactoryExpense = 0;
            double factoryExpenseCost  = 0;
            List <FactoryExpense> factoryExpenseList = new List <FactoryExpense>();

            if (factoryExpenses.Any())
            {
                foreach (var item in factoryExpenses)
                {
                    var factoryExpense = new FactoryExpense()
                    {
                        Amount      = item.Amount,
                        Description = item.Description,
                    };
                    factoryExpenseList.Add(factoryExpense);
                    factoryExpenseCost = factoryExpenseCost + item.Amount;
                }
                batch.FactoryExpenseCost = factoryExpenseCost;
                batch.FactoryExpenses    = factoryExpenseList;
            }
            var    machineRepairs = GetAllMachineRepairsForABatch(data.BatchId);
            double machineCosts   = 0;
            List <MachineRepair> machineRepairList = new List <MachineRepair>();

            if (machineRepairs.Any())
            {
                foreach (var repair in machineRepairs)
                {
                    var machineRepair = new MachineRepair()
                    {
                        Amount      = repair.Amount,
                        Description = repair.Description,
                    };
                    machineRepairList.Add(machineRepair);
                    machineCosts = machineRepair.Amount + machineCosts;
                }
                batch.MachineRepairs   = machineRepairList;
                batch.TotalMachineCost = machineCosts;
            }
            totalFactoryExpense           = batch.TotalMachineCost + batch.FactoryExpenseCost;
            batch.TotalFactoryExpenseCost = totalFactoryExpense;
            batch.MillingChargeBalance    = ComputeMillingChargeBalance(batch.MillingCharge, batch.TotalFactoryExpenseCost);

            var               labourCosts      = GetAllLabourCostsForABatch(data.BatchId);
            double            totalLabourCosts = 0;
            List <LabourCost> labourCostList   = new List <LabourCost>();

            // labourCostList.AddRange(AddBatchLabourCostsAutomatically(data));
            if (labourCosts.Any())
            {
                foreach (var labour in labourCosts)
                {
                    var labourCost = new LabourCost()
                    {
                        ActivityName = labour.ActivityName,
                        Amount       = labour.Amount,
                        Quantity     = labour.Quantity,
                        Rate         = labour.Rate,
                    };
                    labourCostList.Add(labourCost);
                    totalLabourCosts = totalLabourCosts + labour.Amount;
                }
                batch.TotalLabourCosts = totalLabourCosts;
                batch.LabourCosts      = labourCostList;
            }

            if (data.BatchSupplies != null)
            {
                if (data.BatchSupplies.Any())
                {
                    double        totalSupplyAmount = 0;
                    List <Supply> supplies          = new List <Supply>();
                    var           batchSupplies     = data.BatchSupplies.AsQueryable().Where(m => m.BatchId == data.BatchId);
                    foreach (var batchSupply in batchSupplies)
                    {
                        var supply = new Supply()
                        {
                            SupplyId     = batchSupply.Supply.SupplyId,
                            Quantity     = batchSupply.Supply.Quantity,
                            SupplierId   = batchSupply.Supply.SupplierId,
                            Price        = batchSupply.Supply.Price,
                            Amount       = batchSupply.Supply.Amount,
                            SupplierName = _userService.GetUserFullName(batchSupply.Supply.AspNetUser2),
                        };
                        supplies.Add(supply);
                        totalSupplyAmount = totalSupplyAmount + supply.Amount;
                    }
                    batch.Supplies          = supplies;
                    batch.TotalSupplyAmount = totalSupplyAmount;
                }


                batch.TotalProductionCost = ComputeTotalProductionCost(batch.MillingCharge, batch.TotalLabourCosts, batch.TotalBuveraCost);
            }

            return(batch);
        }
        /// <summary>
        /// Maps BatchOutPut EF object to Batch Model Object and
        /// returns the BatchOutPut model object.
        /// </summary>
        /// <param name="result">EF BatchOutPut object to be mapped.</param>
        /// <returns>BatchOutPut Model Object.</returns>
        public BatchOutPut MapEFToModel(EF.Models.BatchOutPut data)
        {
            var batchOutPut = new BatchOutPut()
            {
                BatchOutPutId   = data.BatchOutPutId,
                BatchId         = data.BatchId,
                FlourOutPut     = data.FlourOutPut,
                BrandOutPut     = data.BrandOutPut,
                BrandPercentage = data.BrandPercentage,
                FlourPercentage = data.FlourPercentage,
                Loss            = data.Loss,
                LossPercentage  = data.LossPercentage,
                BranchId        = data.BranchId,
                BranchName      = data.Branch != null? data.Branch.Name :"",
                SectorId        = data.SectorId,
                SectorName      = data.Sector != null? data.Sector.Name : "",
                CreatedOn       = data.CreatedOn,
                TimeStamp       = data.TimeStamp,
                Deleted         = data.Deleted,
                CreatedBy       = _userService.GetUserFullName(data.AspNetUser),
                UpdatedBy       = _userService.GetUserFullName(data.AspNetUser1),
            };


            if (data.BatchGradeSizes != null)
            {
                if (data.BatchGradeSizes.Any())
                {
                    List <Grade> grades         = new List <Grade>();
                    var          distinctGrades = data.BatchGradeSizes.GroupBy(g => g.GradeId).Select(o => o.First()).ToList();
                    foreach (var batchGradeSize in distinctGrades)
                    {
                        var grade = new Grade()
                        {
                            GradeId   = batchGradeSize.Grade.GradeId,
                            Value     = batchGradeSize.Grade.Value,
                            CreatedOn = batchGradeSize.Grade.CreatedOn,
                            TimeStamp = batchGradeSize.Grade.TimeStamp,
                            Deleted   = batchGradeSize.Grade.Deleted,
                            CreatedBy = _userService.GetUserFullName(batchGradeSize.Grade.AspNetUser),
                            UpdatedBy = _userService.GetUserFullName(batchGradeSize.Grade.AspNetUser1),
                        };
                        List <Denomination> denominations = new List <Denomination>();
                        if (batchGradeSize.Grade.BatchGradeSizes != null)
                        {
                            if (batchGradeSize.Grade.BatchGradeSizes.Any())
                            {
                                var distinctSizes = batchGradeSize.Grade.BatchGradeSizes.GroupBy(s => s.SizeId).Select(o => o.First()).ToList();
                                foreach (var ogs in distinctSizes)
                                {
                                    var denomination = new Denomination()
                                    {
                                        DenominationId = ogs.SizeId,
                                        Value          = ogs.Size != null ? ogs.Size.Value : 0,
                                        Quantity       = ogs.Quantity,
                                        Rate           = ogs.Size.Rate,
                                        Amount         = ogs.Quantity * (Convert.ToDouble(ogs.Size.Rate)),
                                    };
                                    batchOutPut.TotalQuantity   += (ogs.Quantity * ogs.Size.Value);
                                    batchOutPut.TotalBuveraCost += denomination.Amount;
                                    denominations.Add(denomination);
                                }
                            }
                            grade.Denominations = denominations;
                        }
                        grades.Add(grade);
                    }
                    batchOutPut.Grades = grades;
                }
            }

            return(batchOutPut);
        }
        public long SaveBatchOutPut(BatchOutPut batchOutPut, string userId)
        {
            List <StockGradeSize> stockGradeSizeList = new List <StockGradeSize>();
            double batchQuantity  = BatchQuantity(batchOutPut.BatchId);
            var    batchOutPutDTO = new DTO.BatchOutPutDTO()
            {
                BatchId         = batchOutPut.BatchId,
                BrandOutPut     = batchOutPut.BrandOutPut,
                FlourOutPut     = batchOutPut.FlourOutPut,
                BranchId        = batchOutPut.BranchId,
                SectorId        = batchOutPut.SectorId,
                Loss            = ComputeBatchLoss(batchOutPut.BrandOutPut, batchOutPut.FlourOutPut, batchQuantity),
                FlourPercentage = ComputePercentageBatchFlourOutPut(batchOutPut.FlourOutPut, batchQuantity),
                BrandPercentage = ComputePercentageBatchBrandOutPut(batchOutPut.BrandOutPut, batchQuantity),
                LossPercentage  = ComputePercentageBatchLoss(batchOutPut.BrandOutPut, batchOutPut.FlourOutPut, batchQuantity),
                Deleted         = batchOutPut.Deleted,
                CreatedBy       = batchOutPut.CreatedBy,
                CreatedOn       = batchOutPut.CreatedOn
            };

            var batchOutPutId = this._dataService.SaveBatchOutPut(batchOutPutDTO, userId);

            if (batchOutPut.Grades != null)
            {
                double totalBuveraQuantity = 0;
                if (batchOutPut.Grades.Any())
                {
                    List <BatchGradeSize> batchGradeSizeList = new List <BatchGradeSize>();

                    foreach (var grade in batchOutPut.Grades)
                    {
                        var gradeId = grade.GradeId;
                        if (grade.Denominations != null)
                        {
                            if (grade.Denominations.Any())
                            {
                                foreach (var denomination in grade.Denominations)
                                {
                                    var batchGradeSize = new BatchGradeSize()
                                    {
                                        GradeId       = gradeId,
                                        SizeId        = denomination.DenominationId,
                                        BatchOutPutId = batchOutPutId,
                                        Quantity      = denomination.Quantity,
                                        TimeStamp     = DateTime.Now
                                    };
                                    batchGradeSizeList.Add(batchGradeSize);

                                    var stockGradeSize = new StockGradeSize()
                                    {
                                        GradeId   = gradeId,
                                        SizeId    = denomination.DenominationId,
                                        Quantity  = denomination.Quantity,
                                        TimeStamp = DateTime.Now
                                    };
                                    stockGradeSizeList.Add(stockGradeSize);



                                    var inOrOut = false;
                                    //Method that updates buvera into storeBuveraGradeSize table(storeBuvera stock)
                                    var storeBuveraGradeSize = new StoreBuveraGradeSizeDTO()
                                    {
                                        StoreId  = batchOutPut.StoreId,
                                        GradeId  = batchGradeSize.GradeId,
                                        SizeId   = batchGradeSize.SizeId,
                                        Quantity = batchGradeSize.Quantity,
                                    };

                                    this._buveraDataService.SaveStoreBuveraGradeSize(storeBuveraGradeSize, inOrOut);
                                    totalBuveraQuantity = denomination.Quantity + totalBuveraQuantity;
                                }
                            }
                        }
                    }

                    var buveraDTO = new DTO.BuveraDTO()
                    {
                        TotalQuantity = totalBuveraQuantity,
                        BranchId      = batchOutPut.BranchId,
                        FromSupplier  = Convert.ToString(batchOutPut.StoreId),
                        ToReceiver    = Convert.ToString(batchOutPut.BatchId),
                        StoreId       = batchOutPut.StoreId,
                    };

                    var buveraId = this._buveraDataService.SaveBuvera(buveraDTO, userId);
                    this._dataService.PurgeBatchGradeSize(batchOutPutId);
                    this.SaveBatchGradeSizeList(batchGradeSizeList);
                }
            }
            UpdateBatchSupply(batchOutPut.BatchId, supplyStatusIdComplete, userId);
            if (batchOutPut.BrandOutPut != 0 && batchOutPut.FlourOutPut != 0)
            {
                var stock = new Stock()
                {
                    SectorId      = batchOutPut.SectorId,
                    BranchId      = batchOutPut.BranchId,
                    BatchId       = batchOutPut.BatchId,
                    InOrOut       = true,
                    StoreId       = batchOutPut.StoreId,
                    ProductId     = brandId,
                    ProductOutPut = batchOutPut.BrandOutPut,
                };
                _stockService.SaveStock(stock, userId);
                var flourStock = new Stock()
                {
                    SectorId       = batchOutPut.SectorId,
                    BranchId       = batchOutPut.BranchId,
                    BatchId        = batchOutPut.BatchId,
                    InOrOut        = true,
                    StoreId        = batchOutPut.StoreId,
                    ProductId      = flourId,
                    ProductOutPut  = batchOutPut.FlourOutPut,
                    StockGradeSize = stockGradeSizeList
                };
                _stockService.SaveStock(flourStock, userId);
            }

            return(batchOutPutId);
        }
        public long SaveBatchOutPut(BatchOutPut batchOutPut, string userId)
        {
            List <StockGradeSize> stockGradeSizeList = new List <StockGradeSize>();
            double batchQuantity  = BatchQuantity(batchOutPut.BatchId);
            var    batchOutPutDTO = new DTO.BatchOutPutDTO()
            {
                BatchId         = batchOutPut.BatchId,
                BrandOutPut     = batchOutPut.BrandOutPut,
                FlourOutPut     = batchOutPut.FlourOutPut,
                BranchId        = batchOutPut.BranchId,
                SectorId        = batchOutPut.SectorId,
                Loss            = ComputeBatchLoss(batchOutPut.BrandOutPut, batchOutPut.FlourOutPut, batchQuantity),
                FlourPercentage = ComputePercentageBatchFlourOutPut(batchOutPut.FlourOutPut, batchQuantity),
                BrandPercentage = ComputePercentageBatchBrandOutPut(batchOutPut.BrandOutPut, batchQuantity),
                LossPercentage  = ComputePercentageBatchLoss(batchOutPut.BrandOutPut, batchOutPut.FlourOutPut, batchQuantity),
                Deleted         = batchOutPut.Deleted,
                CreatedBy       = batchOutPut.CreatedBy,
                CreatedOn       = batchOutPut.CreatedOn
            };

            var batchOutPutId = this._dataService.SaveBatchOutPut(batchOutPutDTO, userId);

            if (batchOutPut.Grades != null)
            {
                if (batchOutPut.Grades.Any())
                {
                    List <BatchGradeSize> batchGradeSizeList = new List <BatchGradeSize>();

                    foreach (var grade in batchOutPut.Grades)
                    {
                        var gradeId = grade.GradeId;
                        if (grade.Denominations != null)
                        {
                            if (grade.Denominations.Any())
                            {
                                foreach (var denomination in grade.Denominations)
                                {
                                    var batchGradeSize = new BatchGradeSize()
                                    {
                                        GradeId       = gradeId,
                                        SizeId        = denomination.DenominationId,
                                        BatchOutPutId = batchOutPutId,
                                        Quantity      = denomination.Quantity,
                                        TimeStamp     = DateTime.Now
                                    };
                                    batchGradeSizeList.Add(batchGradeSize);

                                    var stockGradeSize = new StockGradeSize()
                                    {
                                        GradeId   = gradeId,
                                        SizeId    = denomination.DenominationId,
                                        Quantity  = denomination.Quantity,
                                        TimeStamp = DateTime.Now
                                    };
                                    stockGradeSizeList.Add(stockGradeSize);
                                }
                            }
                        }
                    }
                    this._dataService.PurgeBatchGradeSize(batchOutPutId);
                    this.SaveBatchGradeSizeList(batchGradeSizeList);
                }
            }
            UpdateBatchSupply(batchOutPut.BatchId, supplyStatusIdComplete, userId);
            if (batchOutPut.BrandOutPut != 0 && batchOutPut.FlourOutPut != 0)
            {
                var stock = new Stock()
                {
                    SectorId      = batchOutPut.SectorId,
                    BranchId      = batchOutPut.BranchId,
                    BatchId       = batchOutPut.BatchId,
                    InOrOut       = true,
                    StoreId       = batchOutPut.StoreId,
                    ProductId     = brandId,
                    ProductOutPut = batchOutPut.BrandOutPut,
                };
                _stockService.SaveStock(stock, userId);
                var flourStock = new Stock()
                {
                    SectorId       = batchOutPut.SectorId,
                    BranchId       = batchOutPut.BranchId,
                    BatchId        = batchOutPut.BatchId,
                    InOrOut        = true,
                    StoreId        = batchOutPut.StoreId,
                    ProductId      = flourId,
                    ProductOutPut  = batchOutPut.FlourOutPut,
                    StockGradeSize = stockGradeSizeList
                };
                _stockService.SaveStock(flourStock, userId);
            }

            return(batchOutPutId);
        }