/// <summary>
        /// Process grouped billing lines with milestone
        /// </summary>
        /// <param name="invoiceDetails"></param>
        /// <param name="invoiceHeaderVO"></param>
        /// <param name="fromDate"></param>
        /// <param name="toDate"></param>
        /// <returns></returns>
        private List <InvoiceDetailVO> ProcessGroupedBillingLines(List <InvoiceGLDetailVO> invoiceDetails, InvoiceHeaderVO invoiceHeaderVO, DateTime fromDate,
                                                                  DateTime toDate)
        {
            List <InvoiceDetailVO> invoiceDetailVos = new List <InvoiceDetailVO>();

            List <MilestoneVO> milestoneVoList = approveMaintenanceDAL.GetGroupedMilestoneDetails(invoiceHeaderVO,
                                                                                                  invoiceDetails,
                                                                                                  fromDate, toDate);

            //Get milestone details by group
            var groupedMilestones = (from milestone in milestoneVoList
                                     select new
            {
                milestone.ContractMaintenanceID,
                milestone.ContractLineID,
                milestone.ID,
                milestone.GroupId,
                milestone.PeriodFrequencyId
            }).GroupBy(g => new { g.GroupId, g.PeriodFrequencyId }).ToList();

            // How many nonimal line per group
            foreach (var groupedMilestone in groupedMilestones)
            {
                InvoiceDetailVO          invoiceDetail  = new InvoiceDetailVO();
                List <InvoiceGLDetailVO> nominalLineVos = new List <InvoiceGLDetailVO>();

                int totalQty = 0;
                foreach (var item in groupedMilestone)
                {
                    InvoiceGLDetailVO nominalLine =
                        invoiceDetails.FirstOrDefault(c => c.ContractLineId == item.ContractLineID &&
                                                      c.ContractMaintenanceId == item.ContractMaintenanceID &&
                                                      c.MilestoneId == item.ID &&
                                                      c.GroupId == groupedMilestone.Key.GroupId &&
                                                      c.PeriodFrequencyId == groupedMilestone.Key.PeriodFrequencyId);

                    MilestoneVO milestone = milestoneVoList.FirstOrDefault(m => m.ID == item.ID &&
                                                                           m.GroupId == groupedMilestone.Key.GroupId &&
                                                                           m.PeriodFrequencyId == groupedMilestone.Key.PeriodFrequencyId);

                    if (milestone != null)
                    {
                        InvoiceGLDetailVO invoiceGlDetailVO = new InvoiceGLDetailVO(nominalLine);
                        CreateNominalLine(invoiceHeaderVO, invoiceGlDetailVO, milestone);

                        totalQty += milestone.QTY;
                        nominalLineVos.Add(invoiceGlDetailVO);
                    }
                }

                // Check how many coding lines are grouped based on period frequency and group id
                //var grpedMilestoneVo = milestoneVoList.Where(m => m.GroupId == groupedMilestone.Key.GroupId
                //                                                  &&
                //                                                  m.PeriodFrequencyId ==
                //                                                  groupedMilestone.Key.PeriodFrequencyId)
                //                                      .GroupBy(g => g.ContractMaintenanceID).ToList();



                //foreach (var nLine in grpedMilestoneVo)
                //{
                //    InvoiceGLDetailVO nominalLine =
                //        invoiceDetails.FirstOrDefault(c => c.ContractMaintenanceId == nLine.Key &&
                //                                           c.GroupId == groupedMilestone.Key.GroupId &&
                //                                           c.PeriodFrequencyId == groupedMilestone.Key.PeriodFrequencyId);

                //    InvoiceGLDetailVO invoiceGlDetailVO = new InvoiceGLDetailVO(nominalLine);

                //    //InvoiceGLDetailVO nominalLine =
                //    //    approveMaintenanceDAL.GetContractLineBasedOnContractMaintenanceId(nLine.Key);

                //    MilestoneVO milestone =
                //        milestoneVoList.FirstOrDefault(m => m.ContractLineID == invoiceGlDetailVO.ContractLineId
                //                                            && m.ContractMaintenanceID == nLine.Key &&
                //                                            m.IsGrouped == true
                //                                            && m.PeriodFrequencyId == groupedMilestone.Key.PeriodFrequencyId
                //                                            && m.GroupId == groupedMilestone.Key.GroupId);


                //    CreateNominalLine(invoiceHeaderVO, invoiceGlDetailVO, milestone);

                //    totalQty += milestone.QTY;
                //    nominalLineVos.Add(invoiceGlDetailVO);
                //}

                MilestoneVO defaultPrintingBillingLine =
                    milestoneVoList.FirstOrDefault(m => m.GroupId == groupedMilestone.Key.GroupId &&
                                                   m.PeriodFrequencyId == groupedMilestone.Key.PeriodFrequencyId &&
                                                   m.IsDefaultLineInGroup == true);

                //If default print line milestone not found in milestone list then get default milestone line database
                if (defaultPrintingBillingLine == null)
                {
                    MilestoneVO milestoneVO = approveMaintenanceDAL.GetDefaultBillingLine(nominalLineVos[0].ContractId,
                                                                                          nominalLineVos[0].GroupId,
                                                                                          nominalLineVos[0].PeriodFrequencyId,
                                                                                          fromDate, toDate);
                    if (milestoneVO == null)
                    {
                        string error = String.Format(Constants.MILESTONE_MISSING + "'" +
                                                     invoiceHeaderVO.ContractNumber + "',"
                                                     + "Company - '" + invoiceHeaderVO.CompanyId + "'");
                        if (!errorList.Contains(error))
                        {
                            errorList.Add(error);
                        }
                    }
                    else
                    {
                        defaultPrintingBillingLine = milestoneVO;

                        string billingLines = defaultPrintingBillingLine.MilestoneBillingLineVos.Aggregate(string.Empty,
                                                                                                           (current,
                                                                                                            billingLine) =>
                                                                                                           current +
                                                                                                           billingLine
                                                                                                           .LineText);

                        //Generate Billing line details for - extra line for invoice flat file
                        if (string.IsNullOrEmpty(billingLines))
                        {
                            string error =
                                String.Format(Constants.MISSING_BILLING_LINES + "'" + invoiceHeaderVO.ContractNumber + "',"
                                              + "Company - '" + invoiceHeaderVO.CompanyId + "'");

                            errorList.Add(error);
                        }
                    }
                }

                //To check defaultPrintingLine is not null
                if (defaultPrintingBillingLine != null)
                {
                    string billingLines = defaultPrintingBillingLine.MilestoneBillingLineVos.Aggregate(string.Empty,
                                                                                                       (current,
                                                                                                        billingLine) =>
                                                                                                       current +
                                                                                                       billingLine
                                                                                                       .LineText);

                    //Generate Billing line details for - extra line for invoice flat file
                    if (string.IsNullOrEmpty(billingLines))
                    {
                        string error =
                            String.Format(Constants.MISSING_BILLING_LINES + "'" + invoiceHeaderVO.ContractNumber + "',"
                                          + "Company - '" + invoiceHeaderVO.CompanyId + "'");

                        if (!errorList.Contains(error))
                        {
                            errorList.Add(error);
                        }
                    }

                    decimal amount = nominalLineVos.Sum(nLine => nLine.Value);

                    invoiceDetail.isCreaditInvoice = amount < 0;

                    InvoiceBillingLineVO invoiceBillingLine =
                        new InvoiceBillingLineVO(defaultPrintingBillingLine.MilestoneBillingLineVos);

                    invoiceBillingLine.VatCode   = invoiceHeaderVO.VatCode;
                    invoiceBillingLine.Amount    = amount;   //defaultPrintingBillingLine.Amount;
                    invoiceBillingLine.Qty       = totalQty; //defaultPrintingBillingLine.QTY;
                    invoiceBillingLine.UnitPrice =
                        Convert.ToDecimal(String.Format(Constants.STRING_FORMAT_FOR_NUMERIC_VALUE,
                                                        (amount / invoiceBillingLine.Qty)));

                    //Add nominal line
                    invoiceDetail.NominalLinesList = nominalLineVos;
                    // Add X line billing printing line
                    invoiceDetail.InvoiceBillingLines = invoiceBillingLine;

                    //Add N & X line details in header
                    invoiceDetailVos.Add(invoiceDetail);
                }
            }

            return(invoiceDetailVos);
        }
        /// <summary>
        /// Process invoice details - N & X line
        /// </summary>
        /// <param name="invoiceDetails">Invoice details object</param>
        /// <param name="invoiceHeaderVO">Invoice header object</param>
        /// <param name="fromDate">from date</param>
        /// <param name="toDate">to date</param>
        /// <returns></returns>
        private List <InvoiceDetailVO> ProcessInvoiceDetails(List <InvoiceGLDetailVO> invoiceDetails,
                                                             InvoiceHeaderVO invoiceHeaderVO, DateTime fromDate,
                                                             DateTime toDate)
        {
            var invoiceDetailVos = new List <InvoiceDetailVO>();

            //Process only grouped billing details/ milestone lines
            invoiceDetailVos.AddRange(ProcessGroupedBillingLines(invoiceDetails, invoiceHeaderVO, fromDate, toDate));


            // process line for ungrouped milestone & billing details
            foreach (var invoiceGlDetail in invoiceDetails)
            {
                if (invoiceGlDetail.IsGrouped != true)
                {
                    // Get milestone details
                    MilestoneVO milestoneVos = approveMaintenanceDAL.GetMilestoneDetails(invoiceHeaderVO,
                                                                                         invoiceGlDetail,
                                                                                         fromDate, toDate);

                    //foreach (var milestoneVo in milestoneVos)
                    //{
                    if (milestoneVos.IsGrouped == null || milestoneVos.IsGrouped == false)
                    {
                        InvoiceDetailVO invoiceDetailVO = new InvoiceDetailVO();

                        // Create clone object of GL line object
                        InvoiceGLDetailVO nominalLine = new InvoiceGLDetailVO(invoiceGlDetail);

                        if (ValidateJobCode(invoiceHeaderVO, nominalLine) == false)
                        {
                            //ARBS-144-to have customer name and customer code in error file
                            string error =
                                String.Format(Constants.JOB_CODE_MISSING + "'" + invoiceHeaderVO.ContractNumber +
                                              "', "
                                              + "Company - '" + invoiceHeaderVO.CompanyId + " - " +
                                              invoiceHeaderVO.CompanyName + " , Customer Name - " + invoiceHeaderVO.CustomerName + " , Customer Code - " + invoiceHeaderVO.CustomerCode + "'");
                            if (!errorList.Contains(error))
                            {
                                errorList.Add(error);
                            }
                            isValid = false;
                        }

                        CreateNominalLine(invoiceHeaderVO, nominalLine, milestoneVos);

                        //glDetail.TaxCode = invoiceHeaderVO.VatCode;
                        //glDetail.Value = milestoneVo.Amount;
                        //glDetail.RenewalStartDate = String.Format("{0:ddMMyyyy}",
                        //                                          milestoneVo.RenewalStartDate.Value);
                        //glDetail.RenewalEndDate = String.Format("{0:ddMMyyyy}", milestoneVo.RenewalEndDate.Value);
                        //glDetail.ContractDetails = invoiceHeaderVO.CompanyId == 159 ? "N,D," : "Y,D,";
                        //glDetail.ContractDetails += glDetail.RenewalStartDate + " to " +
                        //                            glDetail.RenewalEndDate + ",M" + milestoneVo.ID;

                        //Add GL details to invoice header
                        //invoiceDetailVO.InvoiceGlDetails = glDetail;

                        if (!invoiceDetailVO.NominalLinesList.Contains(nominalLine))
                        {
                            invoiceDetailVO.NominalLinesList.Add(nominalLine);
                        }

                        string billingLines = milestoneVos.MilestoneBillingLineVos.Aggregate(string.Empty,
                                                                                             (current, billingLine)
                                                                                             =>
                                                                                             current +
                                                                                             billingLine.LineText);

                        //Generate Billing line details for - extra line for invoice flat file
                        if (string.IsNullOrEmpty(billingLines))
                        {
                            string error = String.Format(Constants.MISSING_BILLING_LINES + "'" + invoiceHeaderVO.ContractNumber + "'," + "Company - '" + invoiceHeaderVO.CompanyId + "'");
                            if (!errorList.Contains(error))
                            {
                                errorList.Add(error);
                            }
                        }

                        InvoiceBillingLineVO invoiceBillingLine =
                            new InvoiceBillingLineVO(milestoneVos.MilestoneBillingLineVos);

                        invoiceBillingLine.VatCode   = invoiceHeaderVO.VatCode;
                        invoiceBillingLine.Amount    = milestoneVos.Amount;
                        invoiceBillingLine.Qty       = milestoneVos.QTY;
                        invoiceBillingLine.UnitPrice =
                            Convert.ToDecimal(String.Format(Constants.STRING_FORMAT_FOR_NUMERIC_VALUE,
                                                            (milestoneVos.Amount / invoiceBillingLine.Qty)));


                        invoiceDetailVO.isCreaditInvoice = nominalLine.Value < 0;

                        invoiceDetailVO.InvoiceBillingLines = invoiceBillingLine;

                        invoiceDetailVos.Add(invoiceDetailVO);
                        //}
                    }
                }
            }
            // Invoice details associated with header
            return(invoiceDetailVos);
        }