PageRenderTime 181ms CodeModel.GetById 3ms app.highlight 148ms RepoModel.GetById 1ms app.codeStats 1ms

/Apttus.SNowPS/Apttus.SNowPS.Repository/Products/ProdQuoteRepository.cs

https://bitbucket.org/Apttus_karanmonga/ase-d11
C# | 1411 lines | 971 code | 178 blank | 262 comment | 259 complexity | a2d4d3ab98388a4c4e3c9f6bcd0a1e53 MD5 | raw file
   1/****************************************************************************************
   2@Name: QuoteRepository.cs
   3@Author: Asha Tank
   4@CreateDate: 11 Oct 2017
   5@Description: Quote header related process
   6@UsedBy: This will be used by ProdQuoteRepository controller
   7@ModifiedBy: 
   8@ModifiedDate: 
   9@ChangeDescription: 
  10*****************************************************************************************/
  11using Apttus.DataAccess.Common.Enums;
  12using Apttus.DataAccess.Common.Model;
  13using Apttus.SNowPS.Common;
  14using Apttus.SNowPS.Model;
  15using Newtonsoft.Json;
  16using Newtonsoft.Json.Linq;
  17using System;
  18using System.Collections.Generic;
  19using System.Linq;
  20using System.Net.Http;
  21using System.Xml.Linq;
  22using System.IO;
  23using System.Reflection;
  24
  25namespace Apttus.SNowPS.Respository
  26{
  27    public class ProdQuoteRepository
  28    {
  29        /// <summary>
  30        /// Calculate financial fields of quote header for paased quote id 
  31        /// </summary>
  32        /// <param name="QuoteId"></param>
  33        /// <param name="accessToken"></param>
  34        /// <returns></returns>
  35        public HttpResponseMessage GetQuoteDetail(string QuoteId, string accessToken)
  36        {
  37            var errors = new List<Model.ErrorInfo>();
  38            try
  39            {
  40                //Build AQL Query to fetch Quote,Quote Line Items & Product details
  41                var query = new Query(Constants.OBJ_QUOTE);
  42                query.AddColumns(Constants.OBJ_FIELDQUOTELINEITEM.Split(Constants.CHAR_COMMA));
  43                Expression exp = new Expression(ExpressionOperator.AND);
  44                exp.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId));
  45
  46                query.SetCriteria(exp);
  47
  48                Join quoteLineItem = new Join(Constants.OBJ_QUOTE, Constants.OBJ_CPQ_QUOTELINEITEM, Constants.FIELD_ID, Constants.FIELD_QUOTEID, JoinType.LEFT);
  49                quoteLineItem.EntityAlias = Constants.OBJ_CPQ_QUOTELINEITEM;
  50                query.AddJoin(quoteLineItem);
  51
  52                Join lineItem = new Join(Constants.OBJ_CPQ_QUOTELINEITEM, Constants.OBJ_LINEITEM, Constants.FIELD_DERIVEDFROMId, Constants.FIELD_ID, JoinType.LEFT);
  53                lineItem.EntityAlias = Constants.OBJ_LINEITEM;
  54                query.AddJoin(lineItem);
  55
  56                Join product = new Join(Constants.OBJ_CPQ_QUOTELINEITEM, Constants.OBJ_PRODUCT, Constants.FIELD_PRODUCTID, Constants.FIELD_ID, JoinType.LEFT);
  57                product.EntityAlias = Constants.OBJ_PRODUCT;
  58                query.AddJoin(product);
  59
  60                var jsonQuery = query.Serialize();
  61                //
  62
  63                var reqConfig = new RequestConfigModel();
  64                reqConfig.accessToken = accessToken;
  65                reqConfig.searchType = SearchType.AQL;
  66                reqConfig.objectName = Constants.OBJ_QUOTE;
  67
  68                var response = Utilities.Search(jsonQuery, reqConfig);
  69                ResultQuoteHeaderModel resultQuoteHeaderModel = new ResultQuoteHeaderModel();
  70                if (response != null && response.IsSuccessStatusCode)
  71                {
  72                    var responseString = JObject.Parse(response.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
  73                    List<QuoteQuoteLineDetails> QuoteLineList = new List<QuoteQuoteLineDetails>();
  74                    QuoteLineList = JsonConvert.DeserializeObject<List<QuoteQuoteLineDetails>>(responseString);
  75
  76                    if (QuoteLineList != null && QuoteLineList.Count > 0)
  77                    {
  78                        DailyExcnageRate objDailyExcnageRate = new DailyExcnageRate();
  79                        objDailyExcnageRate = GetExchangeRateDetails(QuoteLineList.FirstOrDefault().cpq_lineitem.CurrencyId, accessToken);
  80
  81                        decimal EstimatedTotal = 0;
  82                        decimal ProfesionalServiceTotal = 0;
  83
  84                        //Calculate quote fields 
  85                        for (int i = 0; i < QuoteLineList.Count; i++)
  86                        {
  87                            switch (QuoteLineList[i].crm_Product.ContributesTo.Value)
  88                            {
  89                                case Constants.TOTALPSREVENUE:
  90                                    resultQuoteHeaderModel.ext_EducationalServicesandKnowledgeandOther = resultQuoteHeaderModel.ext_EducationalServicesandKnowledgeandOther + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
  91                                    resultQuoteHeaderModel.ext_TotalServicesRevenue = resultQuoteHeaderModel.ext_TotalServicesRevenue + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
  92                                    resultQuoteHeaderModel.ext_TotalPSRevenue = resultQuoteHeaderModel.ext_TotalPSRevenue + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
  93                                    break;
  94                                case Constants.SUBSCRIPTIONANDLICENSEREVENUE:
  95                                    resultQuoteHeaderModel.ext_TotalLicenseValue = resultQuoteHeaderModel.ext_TotalLicenseValue + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
  96                                    resultQuoteHeaderModel.ext_TotalSubscriptionACV = resultQuoteHeaderModel.ext_TotalSubscriptionACV + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.AnnualContractValue);
  97                                    break;
  98                                case Constants.LICENSEREVENUE:
  99                                    resultQuoteHeaderModel.ext_TotalLicenseValue = resultQuoteHeaderModel.ext_TotalLicenseValue + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
 100                                    break;
 101                                case Constants.TRAININGREVENUE:
 102                                    resultQuoteHeaderModel.ext_TotalServicesRevenue = resultQuoteHeaderModel.ext_TotalServicesRevenue + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
 103                                    resultQuoteHeaderModel.ext_TotalTrainingRevenue = resultQuoteHeaderModel.ext_TotalTrainingRevenue + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
 104                                    break;
 105                                case Constants.OTHERREVENUE:
 106                                    resultQuoteHeaderModel.ext_TotalOtherRevenue = resultQuoteHeaderModel.ext_TotalOtherRevenue + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
 107                                    break;
 108
 109                            }
 110                            if (QuoteLineList[i].crm_Product.Family != null && QuoteLineList[i].crm_Product.Family.Value == "Professional Services")
 111                            {
 112                                ProfesionalServiceTotal = ProfesionalServiceTotal + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
 113                            }
 114                            resultQuoteHeaderModel.ext_TotalAnnualListPrice = resultQuoteHeaderModel.ext_TotalAnnualListPrice + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.AnnualContractValue);
 115                            EstimatedTotal = EstimatedTotal + Convert.ToDecimal(QuoteLineList[i].cpq_QuoteLineItem.EstimatedTotal);
 116                        }
 117                        resultQuoteHeaderModel.ext_PreTaxTotals = Convert.ToDecimal(resultQuoteHeaderModel.ext_TotalLicenseValue + resultQuoteHeaderModel.ext_TotalServicesRevenue + resultQuoteHeaderModel.ext_TotalOtherRevenue);
 118                        if (ProfesionalServiceTotal != 0)
 119                        {
 120                            resultQuoteHeaderModel.ext_EstimatedTravelExpenseFees = (ProfesionalServiceTotal * 10) / 100;
 121                        }
 122                        resultQuoteHeaderModel.ext_EstimatedTotal = EstimatedTotal + resultQuoteHeaderModel.ext_EstimatedTravelExpenseFees;
 123                        resultQuoteHeaderModel.Id = QuoteLineList.FirstOrDefault().Id;
 124
 125                        //Calculation of USD fields
 126                        resultQuoteHeaderModel.ext_USDTotalAnnualListPrice = Convert.ToDecimal(objDailyExcnageRate.ext_Rate * resultQuoteHeaderModel.ext_TotalAnnualListPrice);
 127                        resultQuoteHeaderModel.ext_USDTotalLicenseValue = Convert.ToDecimal(objDailyExcnageRate.ext_Rate * resultQuoteHeaderModel.ext_TotalLicenseValue);
 128                        resultQuoteHeaderModel.ext_USDTotalOtherRevenue = Convert.ToDecimal(objDailyExcnageRate.ext_Rate * resultQuoteHeaderModel.ext_TotalOtherRevenue);
 129                        resultQuoteHeaderModel.ext_USDTotalPSRevenue = Convert.ToDecimal(objDailyExcnageRate.ext_Rate * resultQuoteHeaderModel.ext_TotalPSRevenue);
 130                        resultQuoteHeaderModel.ext_USDTotalServicesRevenue = Convert.ToDecimal(objDailyExcnageRate.ext_Rate * resultQuoteHeaderModel.ext_TotalServicesRevenue);
 131                        resultQuoteHeaderModel.ext_USDTotalSubscriptionACV = Convert.ToDecimal(objDailyExcnageRate.ext_Rate * resultQuoteHeaderModel.ext_TotalSubscriptionACV);
 132                        resultQuoteHeaderModel.ext_USDTotalTrainingRevenue = Convert.ToDecimal(objDailyExcnageRate.ext_Rate * resultQuoteHeaderModel.ext_TotalTrainingRevenue);
 133                        //Calculation of USD fields end
 134                    }
 135
 136                    //return response
 137                    List<ResultQuoteHeaderModel> quoteHeaderList = new List<ResultQuoteHeaderModel>();
 138                    quoteHeaderList.Add(resultQuoteHeaderModel);
 139
 140                    var responseResult = UpdateQuoteHeader(quoteHeaderList, accessToken);
 141                    return responseResult;
 142                }
 143                else
 144                {
 145                    HttpResponseMessage jsonResponse = new HttpResponseMessage();
 146                    Model.ErrorInfo errorInfo = new Model.ErrorInfo();
 147                    errorInfo.Message = "Error";
 148                    var dict = new Dictionary<string, object>
 149                    {
 150                        {"Message", "Fail to update records"}
 151                    };
 152                    errorInfo.Record = dict;
 153                    errors.Add(errorInfo);
 154                    Utilities.CreateResponse(jsonResponse, errors);
 155                    return jsonResponse;
 156                }
 157            }
 158            catch (Exception ex)
 159            {
 160                var resp = new HttpResponseMessage
 161                {
 162                    Content = new StringContent("Message :" + ex.Message + " " + "StackStrace :" + ex.StackTrace, System.Text.Encoding.UTF8, "application/json"),
 163                    StatusCode = System.Net.HttpStatusCode.BadRequest
 164                };
 165                return resp;
 166            }
 167        }
 168        /// <summary>
 169        /// Get Currency exchange rate based on currency code
 170        /// </summary>
 171        /// <param name="currencyCode"></param>
 172        /// <returns></returns>
 173        public DailyExcnageRate GetExchangeRateDetails(string currencyId, string accessToken)
 174        {
 175            //currencyCode = "USD";
 176            DailyExcnageRate ExchangeRates = new DailyExcnageRate();
 177            accessToken = accessToken != null ? accessToken : Utilities.GetAuthToken();
 178
 179            var reqExchangeRateLineItem = Utilities.GetRequestConfiguration(Constants.OBJ_DAILYEXCHANGERATE, Constants.FIELD_CURRENCYCODE, Constants.FIELD_CURRENCYCODE);
 180            var dictContent = new List<Dictionary<string, object>> { new Dictionary<string, object>() { { "ext_CurrencyCode", currencyId } } };
 181            var resExchangeRate = Utilities.Search(dictContent, reqExchangeRateLineItem);
 182
 183            if (resExchangeRate != null && resExchangeRate.IsSuccessStatusCode)
 184            {
 185                var responseString = JObject.Parse(resExchangeRate.Content.ReadAsStringAsync().Result).SelectToken("SerializedResultEntities").ToString();
 186                List<DailyExcnageRate> ListExchgRates = JsonConvert.DeserializeObject<List<DailyExcnageRate>>(responseString);
 187                // Getting last Created/Modified currency rate
 188                ExchangeRates = ListExchgRates.OrderByDescending(x => x.ModifiedOn).FirstOrDefault();
 189            }
 190            return ExchangeRates;
 191        }
 192
 193        /// <summary>
 194        /// Update Quote Line Items
 195        /// </summary>
 196        /// <param name="lineItems"></param>
 197        /// <param name="accessToken"></param>
 198        /// <returns></returns>
 199        public HttpResponseMessage UpdateQuoteHeader(List<ResultQuoteHeaderModel> quoteHeaderList, string accessToken)
 200        {
 201            var reqConfig = new RequestConfigModel();
 202            reqConfig.accessToken = accessToken;
 203            reqConfig.objectName = Constants.OBJ_QUOTE;
 204
 205            var lstQuoteToUpdate = new List<dynamic>();
 206            foreach (var lstQuoteItems in quoteHeaderList)
 207            {
 208                lstQuoteToUpdate.Add(new
 209                {
 210                    Id = lstQuoteItems.Id,
 211                    ext_EducationalServicesandKnowledgeandOther = lstQuoteItems.ext_EducationalServicesandKnowledgeandOther,
 212                    ext_TotalServicesRevenue = lstQuoteItems.ext_TotalServicesRevenue,
 213                    ext_TotalPSRevenue = lstQuoteItems.ext_TotalPSRevenue,
 214                    ext_TotalSubscriptionACV = lstQuoteItems.ext_TotalSubscriptionACV,
 215                    ext_TotalLicenseValue = lstQuoteItems.ext_TotalLicenseValue,
 216                    ext_TotalTrainingRevenue = lstQuoteItems.ext_TotalTrainingRevenue,
 217                    ext_TotalOtherRevenue = lstQuoteItems.ext_TotalOtherRevenue,
 218                    ext_TotalAnnualListPrice = lstQuoteItems.ext_TotalAnnualListPrice,
 219                    ext_PreTaxTotals = lstQuoteItems.ext_PreTaxTotals,
 220                    ext_EstimatedTravelExpenseFees = lstQuoteItems.ext_EstimatedTravelExpenseFees,
 221                    ext_EstimatedTotal = lstQuoteItems.ext_EstimatedTotal,
 222                    ext_USDTotalAnnualListPrice = lstQuoteItems.ext_USDTotalAnnualListPrice,
 223                    ext_USDTotalLicenseValue = lstQuoteItems.ext_USDTotalLicenseValue,
 224                    ext_USDTotalOtherRevenue = lstQuoteItems.ext_USDTotalOtherRevenue,
 225                    ext_USDTotalPSRevenue = lstQuoteItems.ext_USDTotalPSRevenue,
 226                    ext_USDTotalServicesRevenue = lstQuoteItems.ext_USDTotalServicesRevenue,
 227                    ext_USDTotalSubscriptionACV = lstQuoteItems.ext_USDTotalSubscriptionACV,
 228                    ext_USDTotalTrainingRevenue = lstQuoteItems.ext_USDTotalTrainingRevenue
 229                });
 230            }
 231
 232            var responseString = Utilities.Update(lstQuoteToUpdate, reqConfig);
 233            return responseString;
 234        }
 235
 236
 237        #region Commented Code
 238        ///// <summary>
 239        ///// Calculate financial fields of Quote line items for given QuoteId
 240        ///// </summary>
 241        ///// <param name="QuoteId"></param>
 242        ///// <param name="accessToken"></param>
 243        ///// <returns></returns>
 244        //public HttpResponseMessage UpdateQuoteLineItemFields(string QuoteId, string accessToken)
 245        //{
 246        //    var errors = new List<Model.ErrorInfo>(); 
 247        //    try
 248        //    {
 249        //        //Build AQL Query to fetch Quote,Quote Line Items & Product details
 250        //        var query = new Query(Constants.OBJ_QUOTE);
 251        //        query.AddColumns(Constants.OBJ_FIELDQUOTELINEITEMFINANCIAL.Split(Constants.CHAR_COMMA));
 252        //        Expression exp = new Expression(ExpressionOperator.AND);
 253        //        exp.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId));
 254
 255        //        query.SetCriteria(exp);
 256
 257        //        Join quoteLineItem = new Join(Constants.OBJ_QUOTE, Constants.OBJ_CPQ_QUOTELINEITEM, Constants.FIELD_ID, Constants.FIELD_QUOTEID, JoinType.LEFT);
 258        //        quoteLineItem.EntityAlias = Constants.OBJ_CPQ_QUOTELINEITEM;
 259        //        query.AddJoin(quoteLineItem);
 260
 261        //        Join lineItem = new Join(Constants.OBJ_CPQ_QUOTELINEITEM, Constants.OBJ_LINEITEM, Constants.FIELD_DERIVEDFROMId, Constants.FIELD_ID, JoinType.LEFT);
 262        //        lineItem.EntityAlias = Constants.OBJ_LINEITEM;
 263        //        query.AddJoin(lineItem);
 264
 265        //        Join product = new Join(Constants.OBJ_CPQ_QUOTELINEITEM, Constants.OBJ_PRODUCT, Constants.FIELD_PRODUCTID, Constants.FIELD_ID, JoinType.LEFT);
 266        //        product.EntityAlias = Constants.OBJ_PRODUCT;
 267        //        query.AddJoin(product);
 268
 269        //        var jsonQuery = query.Serialize();
 270
 271        //        var reqConfig = new RequestConfigModel();
 272        //        reqConfig.accessToken = accessToken;
 273        //        reqConfig.searchType = SearchType.AQL;
 274        //        reqConfig.objectName = Constants.OBJ_QUOTE;
 275
 276        //        var response = Utilities.Search(jsonQuery, reqConfig);
 277        //        ResultUSDQuoteHeaderLineItemFields resultQuoteHeaderAndLIneItems = new ResultUSDQuoteHeaderLineItemFields();
 278        //        ResultQuoteHeaderModel resultQuoteHeaderModel = new ResultQuoteHeaderModel();
 279        //        List<ResultQuoteLineItem> lstResultQuoteLineItem = new List<ResultQuoteLineItem>();
 280
 281        //        if (response != null && response.IsSuccessStatusCode)
 282        //        {
 283        //            var responseString = JObject.Parse(response.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 284        //            List<QuoteQuoteLineDetails> QuoteLineList = new List<QuoteQuoteLineDetails>();
 285
 286        //            QuoteLineList = JsonConvert.DeserializeObject<List<QuoteQuoteLineDetails>>(responseString);
 287
 288        //            if (QuoteLineList != null && QuoteLineList.Count > 0)
 289        //            {
 290
 291        //                LineItemRepository lineItemRepo = new LineItemRepository();
 292        //                //Calculate quote line item USD fields 
 293        //                for (int i = 0; i < QuoteLineList.Count; i++)
 294        //                {
 295        //                    ResultQuoteLineItem objResultQuoteLineItem = new ResultQuoteLineItem();
 296
 297        //                    objResultQuoteLineItem.Id = QuoteLineList[i].cpq_QuoteLineItem.Id;
 298
 299        //                    //get daily currenct exchange rates based on currency code
 300        //                    DailyExcnageRate objDailyExcnageRate = lineItemRepo.GetExchangeRateDetails(QuoteLineList[i].cpq_lineitem.CurrencyId, accessToken);
 301
 302        //                    //USD fields
 303        //                    if (objDailyExcnageRate != null)
 304        //                    {
 305        //                        objResultQuoteLineItem.ext_USDAdjustment = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.Ext_AdjustmentAmount;
 306        //                        objResultQuoteLineItem.ext_USDBasePrice = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.BasePrice;
 307        //                        objResultQuoteLineItem.ext_USDTotalValue = objDailyExcnageRate.ext_Rate * (QuoteLineList[i].cpq_QuoteLineItem.NetPrice);
 308        //                        objResultQuoteLineItem.ext_USDListPrice = objDailyExcnageRate.ext_Rate * (QuoteLineList[i].cpq_QuoteLineItem.ListPrice);
 309        //                        objResultQuoteLineItem.ext_USDSalesPrice = objDailyExcnageRate.ext_Rate * (QuoteLineList[i].cpq_QuoteLineItem.NetUnitPrice);
 310        //                        objResultQuoteLineItem.ext_USDAnnualContractValue = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.AnnualContractValue;
 311        //                        objResultQuoteLineItem.ext_USDAnnualListPrice = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.AnnualListPrice;
 312        //                    }
 313        //                    lstResultQuoteLineItem.Add(objResultQuoteLineItem);
 314        //                }
 315        //            }
 316        //            resultQuoteHeaderAndLIneItems.ListQuoteLineItemFinFields = lstResultQuoteLineItem;
 317        //            var responseResult = UpdateQuoteLineItems(lstResultQuoteLineItem, accessToken);
 318        //            return responseResult;
 319        //        }
 320        //        else
 321        //        {
 322        //            HttpResponseMessage jsonResponse = new HttpResponseMessage();
 323        //            Model.ErrorInfo errorInfo = new Model.ErrorInfo();
 324        //            errorInfo.Message = "Error";
 325        //            var dict = new Dictionary<string, object>
 326        //            {
 327        //                {"Message", "Fail to update records"}
 328        //            };
 329        //            errorInfo.Record = dict;
 330        //            errors.Add(errorInfo);
 331        //            Utilities.CreateResponse(jsonResponse, errors);
 332        //            return jsonResponse;
 333        //        }
 334        //        //return response
 335
 336        //    }
 337        //    catch (Exception ex)
 338        //    {
 339        //        var resp = new HttpResponseMessage
 340        //        {
 341        //            Content = new StringContent("Message :" + ex.Message + " " + "StackStrace :" + ex.StackTrace, System.Text.Encoding.UTF8, "application/json"),
 342        //            StatusCode = System.Net.HttpStatusCode.BadRequest
 343        //        };
 344        //        return resp;
 345        //    }
 346        //}
 347        #endregion
 348
 349        /// <summary>
 350        /// Calculate financial fields of Quote line items for given QuoteId
 351        /// </summary>
 352        /// <param name="QuoteId"></param>
 353        /// <param name="accessToken"></param>
 354        /// <returns></returns>
 355        public HttpResponseMessage UpdateQuoteLineItemFields(string QuoteId, string accessToken)
 356        {
 357            var errors = new List<Model.ErrorInfo>();
 358            try
 359            {
 360                //Build AQL Query to fetch Quote,Quote Line Items & Product details
 361                var query = new Query(Constants.OBJ_QUOTE);
 362                query.AddColumns(Constants.OBJ_FIELDQUOTELINEITEMFINANCIAL.Split(Constants.CHAR_COMMA));
 363                Expression exp = new Expression(ExpressionOperator.AND);
 364                exp.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId));
 365
 366                query.SetCriteria(exp);
 367
 368                Join quoteLineItem = new Join(Constants.OBJ_QUOTE, Constants.OBJ_CPQ_QUOTELINEITEM, Constants.FIELD_ID, Constants.FIELD_QUOTEID, JoinType.LEFT);
 369                quoteLineItem.EntityAlias = Constants.OBJ_CPQ_QUOTELINEITEM;
 370                query.AddJoin(quoteLineItem);
 371
 372                Join lineItem = new Join(Constants.OBJ_CPQ_QUOTELINEITEM, Constants.OBJ_LINEITEM, Constants.FIELD_DERIVEDFROMId, Constants.FIELD_ID, JoinType.LEFT);
 373                lineItem.EntityAlias = Constants.OBJ_LINEITEM;
 374                query.AddJoin(lineItem);
 375
 376                Join product = new Join(Constants.OBJ_CPQ_QUOTELINEITEM, Constants.OBJ_PRODUCT, Constants.FIELD_PRODUCTID, Constants.FIELD_ID, JoinType.LEFT);
 377                product.EntityAlias = Constants.OBJ_PRODUCT;
 378                query.AddJoin(product);
 379
 380                var jsonQuery = query.Serialize();
 381
 382                var reqConfig = new RequestConfigModel();
 383                reqConfig.accessToken = accessToken;
 384                reqConfig.searchType = SearchType.AQL;
 385                reqConfig.objectName = Constants.OBJ_QUOTE;
 386
 387                var response = Utilities.Search(jsonQuery, reqConfig);
 388                ResultUSDQuoteHeaderLineItemFields resultQuoteHeaderAndLIneItems = new ResultUSDQuoteHeaderLineItemFields();
 389                ResultQuoteHeaderModel resultQuoteHeaderModel = new ResultQuoteHeaderModel();
 390                List<ResultQuoteLineItem> lstResultQuoteLineItem = new List<ResultQuoteLineItem>();
 391
 392                if (response != null && response.IsSuccessStatusCode)
 393                {
 394                    var responseString = JObject.Parse(response.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 395                    List<QuoteQuoteLineDetails> QuoteLineList = new List<QuoteQuoteLineDetails>();
 396
 397                    QuoteLineList = JsonConvert.DeserializeObject<List<QuoteQuoteLineDetails>>(responseString);
 398
 399                    if (QuoteLineList != null && QuoteLineList.Count > 0)
 400                    {
 401
 402                        LineItemRepository lineItemRepo = new LineItemRepository();
 403                        //Calculate quote line item USD fields 
 404                        for (int i = 0; i < QuoteLineList.Count; i++)
 405                        {
 406                            ResultQuoteLineItem objResultQuoteLineItem = new ResultQuoteLineItem();
 407
 408                            objResultQuoteLineItem.Id = QuoteLineList[i].cpq_QuoteLineItem.Id;
 409                            objResultQuoteLineItem.ext_ListPriceWithAdjustments = QuoteLineList[i].cpq_QuoteLineItem.BasePrice.ConvertToDecimal();
 410
 411                            if (QuoteLineList[i].cpq_QuoteLineItem.ListPrice != 0)
 412                            {
 413                                objResultQuoteLineItem.ext_AdjustmentAmount = (QuoteLineList[i].cpq_QuoteLineItem.ListPrice.ConvertToDecimal() * QuoteLineList[i].cpq_QuoteLineItem.Quantity2.ConvertToDecimal() * QuoteLineList[i].cpq_QuoteLineItem.Term.ConvertToDecimal()) - QuoteLineList[i].cpq_QuoteLineItem.NetPrice.ConvertToDecimal();
 414                                objResultQuoteLineItem.ext_AdjustmentDiscountPercent = objResultQuoteLineItem.ext_AdjustmentAmount * 100 / (QuoteLineList[i].cpq_QuoteLineItem.ListPrice.ConvertToDecimal() * QuoteLineList[i].cpq_QuoteLineItem.Quantity2.ConvertToDecimal() * QuoteLineList[i].cpq_QuoteLineItem.Term.ConvertToDecimal());
 415                            }
 416
 417
 418                            if (QuoteLineList[i].crm_Product.Family != null && QuoteLineList[i].crm_Product.Family.Value.ConvertToStringNull() != null && QuoteLineList[i].cpq_QuoteLineItem.ProductId.Ext_Family.Value.ToString() != Constants.STR_SUBSCRIPTION)
 419                            {
 420                                objResultQuoteLineItem.ext_AnnualContractValue = 0;
 421                                objResultQuoteLineItem.ext_AnnualListPrice = 0;
 422                            }
 423                            else
 424                            {
 425                                if (QuoteLineList[i].cpq_QuoteLineItem.SellingFrequency != null && QuoteLineList[i].cpq_QuoteLineItem.SellingFrequency.ConvertToStringNull() != null && QuoteLineList[i].cpq_QuoteLineItem.SellingFrequency.Value.ToString() == Constants.STR_YEARLY)
 426                                {
 427                                    objResultQuoteLineItem.ext_AnnualContractValue = QuoteLineList[i].cpq_QuoteLineItem.NetUnitPrice.ConvertToDecimal() * QuoteLineList[i].cpq_QuoteLineItem.Quantity2;
 428                                    objResultQuoteLineItem.ext_AnnualListPrice = QuoteLineList[i].cpq_QuoteLineItem.ListPrice.ConvertToDecimal() * QuoteLineList[i].cpq_QuoteLineItem.Quantity2;
 429                                }
 430                                else
 431                                {
 432                                    objResultQuoteLineItem.ext_AnnualContractValue = QuoteLineList[i].cpq_QuoteLineItem.NetUnitPrice.ConvertToDecimal() * 12 * QuoteLineList[i].cpq_QuoteLineItem.Quantity2;
 433                                    objResultQuoteLineItem.ext_AnnualListPrice = QuoteLineList[i].cpq_QuoteLineItem.ListPrice.ConvertToDecimal() * 12 * QuoteLineList[i].cpq_QuoteLineItem.Quantity2;
 434                                }
 435                            }
 436
 437
 438                            objResultQuoteLineItem.ext_EstimatedTax = QuoteLineList[i].cpq_QuoteLineItem.ext_EstimatedTax.ConvertToDecimal();
 439
 440                            //Estimated Total: Total Value + EstimatedTax 
 441                            objResultQuoteLineItem.ext_EstimatedTotal = QuoteLineList[i].cpq_QuoteLineItem.NetPrice.ConvertToDecimal() + objResultQuoteLineItem.ext_EstimatedTax.ConvertToDecimal();
 442
 443                            //Sales Price
 444                            objResultQuoteLineItem.ext_SalesPrice = QuoteLineList[i].cpq_QuoteLineItem.NetUnitPrice.ConvertToDecimal();
 445
 446                            //get daily currenct exchange rates based on currency code
 447                            DailyExcnageRate objDailyExcnageRate = lineItemRepo.GetExchangeRateDetails(QuoteLineList[i].cpq_lineitem.CurrencyId, accessToken);
 448
 449                            //USD fields
 450                            if (objDailyExcnageRate != null)
 451                            {
 452                                objResultQuoteLineItem.ext_USDAdjustment = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.Ext_AdjustmentAmount.ConvertToDecimal();
 453                                objResultQuoteLineItem.ext_USDBasePrice = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.BasePrice.ConvertToDecimal();
 454                                objResultQuoteLineItem.ext_USDTotalValue = objDailyExcnageRate.ext_Rate * (QuoteLineList[i].cpq_QuoteLineItem.NetPrice.ConvertToDecimal());
 455                                objResultQuoteLineItem.ext_USDListPrice = objDailyExcnageRate.ext_Rate * (QuoteLineList[i].cpq_QuoteLineItem.ListPrice.ConvertToDecimal());
 456                                objResultQuoteLineItem.ext_USDSalesPrice = objDailyExcnageRate.ext_Rate * (QuoteLineList[i].cpq_QuoteLineItem.NetUnitPrice.ConvertToDecimal());
 457                                objResultQuoteLineItem.ext_USDAnnualContractValue = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.AnnualContractValue.ConvertToDecimal();
 458                                objResultQuoteLineItem.ext_USDAnnualListPrice = objDailyExcnageRate.ext_Rate * QuoteLineList[i].cpq_QuoteLineItem.AnnualListPrice.ConvertToDecimal();
 459                            }
 460                            lstResultQuoteLineItem.Add(objResultQuoteLineItem);
 461                        }
 462                    }
 463                    resultQuoteHeaderAndLIneItems.ListQuoteLineItemFinFields = lstResultQuoteLineItem;
 464                    var responseResult = UpdateQuoteLineItems(lstResultQuoteLineItem, accessToken);
 465                    return responseResult;
 466                }
 467                else
 468                {
 469                    HttpResponseMessage jsonResponse = new HttpResponseMessage();
 470                    Model.ErrorInfo errorInfo = new Model.ErrorInfo();
 471                    errorInfo.Message = "Error";
 472                    var dict = new Dictionary<string, object>
 473                    {
 474                        {"Message", "Fail to update records"}
 475                    };
 476                    errorInfo.Record = dict;
 477                    errors.Add(errorInfo);
 478                    Utilities.CreateResponse(jsonResponse, errors);
 479                    return jsonResponse;
 480                }
 481                //return response
 482
 483            }
 484            catch (Exception ex)
 485            {
 486                var resp = new HttpResponseMessage
 487                {
 488                    Content = new StringContent("Message :" + ex.Message + " " + "StackStrace :" + ex.StackTrace, System.Text.Encoding.UTF8, "application/json"),
 489                    StatusCode = System.Net.HttpStatusCode.BadRequest
 490                };
 491                return resp;
 492            }
 493        }
 494
 495        /// <summary>
 496        /// Update calculated Quote line items details
 497        /// </summary>
 498        /// <param name="lineItems">list of fileds to be update</param>
 499        /// <returns></returns>
 500        public HttpResponseMessage UpdateQuoteLineItems(List<ResultQuoteLineItem> quoteLineItems, string accessToken)
 501        {
 502            var reqConfig = new RequestConfigModel();
 503            reqConfig.accessToken = accessToken;
 504            reqConfig.objectName = Constants.OBJ_CPQ_QUOTELINEITEM;
 505
 506            var lstLineItemsToUpdate = new List<dynamic>();
 507            foreach (var lstLineItems in quoteLineItems)
 508            {
 509                lstLineItemsToUpdate.Add(new
 510                {
 511                    Id = lstLineItems.Id,
 512                    ext_ListPriceWithAdjustments = lstLineItems.ext_ListPriceWithAdjustments,
 513                    ext_AdjustmentAmount = lstLineItems.ext_AdjustmentAmount,
 514                    ext_AdjustmentDiscountPercent = lstLineItems.ext_AdjustmentDiscountPercent,
 515                    ext_EstimatedTax = lstLineItems.ext_EstimatedTax,
 516                    ext_AnnualContractValue = lstLineItems.ext_AnnualContractValue,
 517                    ext_AnnualListPrice = lstLineItems.ext_AnnualListPrice,
 518                    ext_EstimatedTotal = lstLineItems.ext_EstimatedTotal,
 519                    ext_SalesPrice = lstLineItems.ext_SalesPrice,
 520                    ext_USDAdjustment = lstLineItems.ext_USDAdjustment,
 521                    ext_USDBasePrice = lstLineItems.ext_USDBasePrice,
 522                    ext_USDTotalValue = lstLineItems.ext_USDTotalValue,
 523                    ext_USDListPrice = lstLineItems.ext_USDListPrice,
 524                    ext_USDSalesPrice = lstLineItems.ext_USDSalesPrice,
 525                    ext_USDAnnualContractValue = lstLineItems.ext_USDAnnualContractValue,
 526                    ext_USDAnnualListPrice = lstLineItems.ext_USDAnnualListPrice,
 527                });
 528            }
 529
 530            var responseString = Utilities.Update(lstLineItemsToUpdate, reqConfig);
 531            return responseString;
 532        }
 533        /// <summary>
 534        /// Default quote details based on rule conditions
 535        /// </summary>
 536        /// <param name="QuoteId"></param>
 537        /// <param name="accessToken"></param>
 538        /// <returns></returns>
 539        public HttpResponseMessage DefaultQuoteDetails(string QuoteId, string accessToken)
 540        {
 541            try
 542            {
 543                //Build AQL Query to fetch Quote's opprtunityID
 544                var updateResult = new HttpResponseMessage();
 545                var query = new Query(Constants.OBJ_QUOTE);
 546                query.AddColumns(Constants.OBJ_QUOTEVALIDATE_DEFAULT_SELECTFIELD.Split(Constants.CHAR_COMMA));
 547                Expression exp = new Expression(ExpressionOperator.AND);
 548                exp.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId));
 549
 550                Join account = new Join(Constants.OBJ_QUOTE, Constants.OBJ_ACCOUNT, Constants.FIELD_ACCOUNTID, Constants.FIELD_ID, JoinType.LEFT);
 551                account.EntityAlias = Constants.OBJ_ACCOUNT;
 552                query.AddJoin(account);
 553
 554                query.SetCriteria(exp);
 555
 556                var jsonQuery = query.Serialize();
 557
 558
 559                var reqConfig = new RequestConfigModel();
 560                reqConfig.accessToken = accessToken;
 561                reqConfig.searchType = SearchType.AQL;
 562                reqConfig.objectName = Constants.OBJ_QUOTE;
 563
 564                var response = Utilities.Search(jsonQuery, reqConfig);
 565                ValidateDefaultQuoteResult objValidateDefaultQuoteResult = new ValidateDefaultQuoteResult();
 566                List<Dictionary<string, object>> ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
 567
 568                if (response != null && response.IsSuccessStatusCode)
 569                {
 570                    var responseString = JObject.Parse(response.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 571                    List<QuoteValidate> objQuoteOppoDetails = new List<QuoteValidate>();
 572
 573                    objQuoteOppoDetails = JsonConvert.DeserializeObject<List<QuoteValidate>>(responseString);
 574
 575                    if (objQuoteOppoDetails != null && objQuoteOppoDetails.Count > 0)
 576                    {
 577                        #region "Set default data center based on Country"
 578                        if (objQuoteOppoDetails.FirstOrDefault().crm_Account != null && objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country != null)
 579                        {
 580                            #region get country and data center mapping data from xml file
 581                            Dictionary<string, string> countryDCDict = new Dictionary<string, string>();
 582                            string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"XMLFiles\DataCenterCountryMapping.xml");
 583
 584                            XDocument XDoc = XDocument.Load(path);
 585                            try
 586                            {
 587                                countryDCDict = XDoc.Descendants("Country").ToDictionary(d => (string)d.Attribute("Name"), d => (string)d);
 588
 589                                if (countryDCDict.ContainsKey(objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country))
 590                                {
 591                                    objValidateDefaultQuoteResult.ext_datacenter = countryDCDict[objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country];
 592                                }
 593                                else
 594                                {  //setting default data center to United States
 595                                    objValidateDefaultQuoteResult.ext_datacenter = countryDCDict[Constants.STR_UNITEDSTATES];
 596                                }
 597
 598                            }
 599                            catch (Exception ex)
 600                            {
 601                                objValidateDefaultQuoteResult.ErrorMessage = "DataCenterCountryMapping :" + ex.Message;
 602                            }
 603                            #endregion
 604                        }
 605                        #endregion
 606
 607                        #region "Set Selling entity"
 608                        if (objQuoteOppoDetails.FirstOrDefault().crm_Account != null && objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country != null)
 609                        {
 610
 611                            #region get country and selling entity mapping data from xml file
 612                            Dictionary<string, string> countryDCDict = new Dictionary<string, string>();
 613                            string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"XMLFiles\CountryandSellingEntityMapping.xml");
 614
 615                            XDocument XDoc = XDocument.Load(path);
 616                            try
 617                            {
 618                                countryDCDict = XDoc.Descendants("Country").ToDictionary(d => (string)d.Attribute("Name"), d => (string)d);
 619
 620                                if (countryDCDict.ContainsKey(objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country))
 621                                {
 622                                    objValidateDefaultQuoteResult.ext_SellingEntity = countryDCDict[objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country];
 623                                }
 624                                else
 625                                {
 626                                    objValidateDefaultQuoteResult.ext_SellingEntity = countryDCDict[Constants.STR_NEDERLAND];
 627                                }
 628                            }
 629                            catch (Exception ex)
 630                            {
 631                                objValidateDefaultQuoteResult.ErrorMessage += " CountryandSellingEntityMapping :" + ex.Message;
 632                            }
 633                            #endregion
 634                        }
 635                        #endregion
 636
 637                        #region "Set PriceList based on currency and vice versa"
 638
 639                        //Build AQL Query to fetch pricelist details 
 640                        var priceListId = objQuoteOppoDetails.FirstOrDefault().PriceListId != null ? objQuoteOppoDetails.FirstOrDefault().PriceListId.Id : null;
 641
 642                        if (!string.IsNullOrEmpty(priceListId))
 643                        {
 644                            var queryPricelist = new Query(Constants.OBJ_PRICELIST);
 645                            queryPricelist.AddColumns(Constants.OBJ_PRICELIST_SELECTFIELD.Split(Constants.CHAR_COMMA));
 646                            Expression expPriceList = new Expression(ExpressionOperator.AND);
 647                            expPriceList.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, priceListId));
 648
 649                            queryPricelist.SetCriteria(expPriceList);
 650
 651                            jsonQuery = queryPricelist.Serialize();
 652
 653                            reqConfig = new RequestConfigModel();
 654                            reqConfig.accessToken = accessToken;
 655                            reqConfig.searchType = SearchType.AQL;
 656                            reqConfig.objectName = Constants.OBJ_PRICELIST;
 657
 658                            var responsePricelistDetail = Utilities.Search(jsonQuery, reqConfig);
 659                            if (responsePricelistDetail != null && responsePricelistDetail.IsSuccessStatusCode)
 660                            {
 661                                var responsePriceListString = JObject.Parse(responsePricelistDetail.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 662                                List<QQuoteLineItem> objPriceListResult = new List<QQuoteLineItem>();
 663                                objPriceListResult = JsonConvert.DeserializeObject<List<QQuoteLineItem>>(responsePriceListString);
 664
 665                                if (objPriceListResult != null && objPriceListResult.Count > 0)
 666                                {
 667                                    if (!string.IsNullOrEmpty(objPriceListResult.FirstOrDefault().CurrencyId))
 668                                    {
 669                                        objValidateDefaultQuoteResult.BaseCurrency = objPriceListResult.FirstOrDefault().CurrencyId;
 670                                    }
 671                                }
 672
 673                            }
 674                        }
 675                        // PricelistId will be null when Quote is created outside Apttus
 676                        if (!string.IsNullOrEmpty(objQuoteOppoDetails.FirstOrDefault().ext_BaseCurrency) && string.IsNullOrEmpty(priceListId))
 677                        {
 678                            if (objQuoteOppoDetails.FirstOrDefault().ext_Type.Value.ToLower() == Constants.SERVICES || objQuoteOppoDetails.FirstOrDefault().ext_Type.Value.ToLower() == Constants.STR_TRAINING.ToLower())
 679                            {
 680                                #region get Currency and Pricelist mapping data from xml file for Services
 681
 682                                Dictionary<string, string> currencyDCDict = new Dictionary<string, string>();
 683                                string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"XMLFiles\CurrencyandPriceListMappingServices.xml");
 684
 685                                XDocument XDoc = XDocument.Load(path);
 686                                try
 687                                {
 688                                    currencyDCDict = XDoc.Descendants("Currency").ToDictionary(d => (string)d.Attribute("Name"), d => (string)d);
 689                                    if (currencyDCDict.ContainsKey(objQuoteOppoDetails.FirstOrDefault().ext_BaseCurrency))
 690                                    {
 691                                        objValidateDefaultQuoteResult.PriceListName = currencyDCDict[objQuoteOppoDetails.FirstOrDefault().ext_BaseCurrency];
 692                                        if (objQuoteOppoDetails.FirstOrDefault().ext_BaseCurrency == Constants.STR_USD)
 693                                        {
 694                                            if (objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country == Constants.STR_AUSTRALIA)
 695                                            {
 696                                                objValidateDefaultQuoteResult.PriceListName = "Australian (USD) Services";
 697                                            }
 698                                            else if (objQuoteOppoDetails.FirstOrDefault().crm_Account.ext_Country == Constants.STR_JAPAN)
 699                                            {
 700                                                objValidateDefaultQuoteResult.PriceListName = "Japan (USD) Subscription";
 701                                            }
 702                                        }
 703                                    }
 704                                    else
 705                                    {
 706                                        objValidateDefaultQuoteResult.PriceListName = currencyDCDict[Constants.STR_USD];
 707                                    }
 708                                }
 709                                catch (Exception ex)
 710                                {
 711                                    objValidateDefaultQuoteResult.ErrorMessage += " CurrencyandPriceListMappingServices :" + ex.Message;
 712                                }
 713                                #endregion
 714                            }
 715                            else// Remaining types will be for Subscription
 716                            {
 717                                #region get Currency and Pricelist mapping data from xml file for Subscription
 718                                Dictionary<string, string> currencyDCDict = new Dictionary<string, string>();
 719                                string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"XMLFiles\CurrencyandPriceListMapping.xml");
 720
 721                                XDocument XDoc = XDocument.Load(path);
 722                                try
 723                                {
 724                                    currencyDCDict = XDoc.Descendants("Currency").ToDictionary(d => (string)d.Attribute("Name"), d => (string)d);
 725
 726                                    if (currencyDCDict.ContainsKey(objQuoteOppoDetails.FirstOrDefault().ext_BaseCurrency))
 727                                    {
 728                                        objValidateDefaultQuoteResult.PriceListName = currencyDCDict[objQuoteOppoDetails.FirstOrDefault().ext_BaseCurrency];
 729                                    }
 730                                    else
 731                                    {
 732                                        objValidateDefaultQuoteResult.PriceListName = currencyDCDict[Constants.STR_USD];
 733                                    }
 734                                }
 735                                catch (Exception ex)
 736                                {
 737                                    objValidateDefaultQuoteResult.ErrorMessage += " CurrencyandPriceListMapping :" + ex.Message;
 738                                }
 739                                #endregion
 740                            }
 741                        }
 742                        #endregion
 743
 744                        //Update Quote fileds to default values
 745                        ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
 746                        Dictionary<string, object> QuoteFieldToUpdate = new Dictionary<string, object>();
 747                        QuoteFieldToUpdate.Add("Id", QuoteId);
 748                        if (!string.IsNullOrEmpty(objValidateDefaultQuoteResult.ext_datacenter))
 749                        {
 750                            QuoteFieldToUpdate.Add("ext_datacenter", objValidateDefaultQuoteResult.ext_datacenter);
 751                        }
 752                        if (!string.IsNullOrEmpty(objValidateDefaultQuoteResult.ext_SellingEntity))
 753                        {
 754
 755                            //Build AQL Query to fetch Account details 
 756                            var queryQuote = new Query(Constants.OBJ_ACCOUNT);
 757                            queryQuote.AddColumns(Constants.OBJ_ACCOUNT_SELECTFIELD.Split(Constants.CHAR_COMMA));
 758                            Expression expQuote = new Expression(ExpressionOperator.AND);
 759                            expQuote.AddCondition(new Condition(Constants.FIELD_NAME, FilterOperator.Equal, objValidateDefaultQuoteResult.ext_SellingEntity));
 760
 761                            queryQuote.SetCriteria(expQuote);
 762
 763                            jsonQuery = queryQuote.Serialize();
 764
 765                            reqConfig = new RequestConfigModel();
 766                            reqConfig.accessToken = accessToken;
 767                            reqConfig.searchType = SearchType.AQL;
 768                            reqConfig.objectName = Constants.OBJ_ACCOUNT;
 769
 770                            var responseAccountDetail = Utilities.Search(jsonQuery, reqConfig);
 771                            if (responseAccountDetail != null && responseAccountDetail.IsSuccessStatusCode)
 772                            {
 773                                var responseAccountString = JObject.Parse(responseAccountDetail.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 774                                List<AccountCountry> objAccountResult = new List<AccountCountry>();
 775                                objAccountResult = JsonConvert.DeserializeObject<List<AccountCountry>>(responseAccountString);
 776
 777                                if (objAccountResult != null && objAccountResult.Count > 0)
 778                                {
 779                                    Dictionary<string, object> dictAccount = new Dictionary<string, object>();
 780                                    dictAccount.Add("Id", objAccountResult.FirstOrDefault().Id);
 781                                    dictAccount.Add("Name", objAccountResult.FirstOrDefault().Name);
 782
 783                                    QuoteFieldToUpdate.Add("ext_SellingEntity", dictAccount);
 784                                }
 785                            }
 786
 787
 788                        }
 789                        if (!string.IsNullOrEmpty(objValidateDefaultQuoteResult.PriceListName))
 790                        {
 791
 792                            //Build AQL Query to fetch Account details 
 793                            var queryPriceList = new Query(Constants.OBJ_PRICELIST);
 794                            queryPriceList.AddColumns(Constants.OBJ_PRICELIST_SELECTFIELD.Split(Constants.CHAR_COMMA));
 795                            Expression expPriceLIst = new Expression(ExpressionOperator.AND);
 796                            expPriceLIst.AddCondition(new Condition(Constants.FIELD_NAME, FilterOperator.Equal, objValidateDefaultQuoteResult.PriceListName));
 797
 798                            queryPriceList.SetCriteria(expPriceLIst);
 799
 800                            jsonQuery = queryPriceList.Serialize();
 801
 802                            reqConfig = new RequestConfigModel();
 803                            reqConfig.accessToken = accessToken;
 804                            reqConfig.searchType = SearchType.AQL;
 805                            reqConfig.objectName = Constants.OBJ_PRICELIST;
 806
 807                            var responsePricelistDetail = Utilities.Search(jsonQuery, reqConfig);
 808                            if (responsePricelistDetail != null && responsePricelistDetail.IsSuccessStatusCode)
 809                            {
 810                                var responsePricelistString = JObject.Parse(responsePricelistDetail.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 811                                List<LookUp> objPriceListResult = new List<LookUp>();
 812                                objPriceListResult = JsonConvert.DeserializeObject<List<LookUp>>(responsePricelistString);
 813
 814                                if (objPriceListResult != null && objPriceListResult.Count > 0)
 815                                {
 816                                    Dictionary<string, object> dictAccount = new Dictionary<string, object>();
 817                                    dictAccount.Add("Id", objPriceListResult.FirstOrDefault().Id);
 818                                    dictAccount.Add("Name", objPriceListResult.FirstOrDefault().Name);
 819
 820                                    QuoteFieldToUpdate.Add("PriceListId", dictAccount);
 821                                }
 822                            }
 823
 824
 825                        }
 826                        if (!string.IsNullOrEmpty(objValidateDefaultQuoteResult.BaseCurrency))
 827                        {
 828                            QuoteFieldToUpdate.Add("ext_BaseCurrency", objValidateDefaultQuoteResult.BaseCurrency);
 829                        }
 830                        #region "Set Sales Partner"
 831                        //Build AQL Query to fetch Sales Partner Account details 
 832                        if (objQuoteOppoDetails.Count > 0 && objQuoteOppoDetails.FirstOrDefault().ext_PartnerAccountMDMID != null)
 833                        {
 834                            var querySalesParnterAccount = new Query(Constants.OBJ_ACCOUNT);
 835                            querySalesParnterAccount.AddColumns(Constants.OBJ_ACCOUNT_SELECTFIELD.Split(Constants.CHAR_COMMA));
 836                            Expression expSalesPartner = new Expression(ExpressionOperator.AND);
 837                            expSalesPartner.AddCondition(new Condition(Constants.FIELD_EXTERNALID, FilterOperator.Equal, objQuoteOppoDetails.FirstOrDefault().ext_PartnerAccountMDMID));
 838
 839                            querySalesParnterAccount.SetCriteria(expSalesPartner);
 840
 841                            jsonQuery = querySalesParnterAccount.Serialize();
 842
 843                            reqConfig = new RequestConfigModel();
 844                            reqConfig.accessToken = accessToken;
 845                            reqConfig.searchType = SearchType.AQL;
 846                            reqConfig.objectName = Constants.OBJ_ACCOUNT;
 847
 848                            var responseSalesParnterAccountDetail = Utilities.Search(jsonQuery, reqConfig);
 849
 850                            if (responseSalesParnterAccountDetail != null && responseSalesParnterAccountDetail.IsSuccessStatusCode)
 851                            {
 852                                var responseAccountString = JObject.Parse(responseSalesParnterAccountDetail.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 853                                List<AccountCountry> objAccountResult = new List<AccountCountry>();
 854                                objAccountResult = JsonConvert.DeserializeObject<List<AccountCountry>>(responseAccountString);
 855
 856                                if (objAccountResult != null && objAccountResult.Count > 0)
 857                                {
 858                                    Dictionary<string, object> dictAccount = new Dictionary<string, object>();
 859                                    dictAccount.Add("Id", objAccountResult.FirstOrDefault().Id);
 860                                    dictAccount.Add("Name", objAccountResult.FirstOrDefault().Name);
 861                                    QuoteFieldToUpdate.Add("ext_SalesPartner", dictAccount);
 862                                }
 863                            }
 864                        }
 865                        #endregion
 866
 867                        ListQuoteFieldToUpdate.Add(QuoteFieldToUpdate);
 868                        updateResult = UpdateQuoteIsPrimary(ListQuoteFieldToUpdate, accessToken);
 869                    }
 870                }
 871
 872                if (updateResult.IsSuccessStatusCode)
 873                {//Create response message
 874                    var resp = new HttpResponseMessage
 875                    {
 876                        Content = new StringContent(JsonConvert.SerializeObject(objValidateDefaultQuoteResult), System.Text.Encoding.UTF8, "application/json"),
 877                        StatusCode = System.Net.HttpStatusCode.OK
 878                    };
 879                    return resp;
 880                }
 881                else
 882                {
 883                    return updateResult;
 884                }
 885            }
 886            catch (Exception ex)
 887            {
 888                var resp = new HttpResponseMessage
 889                {
 890                    Content = new StringContent("Message :" + ex.Message + " " + "StackStrace :" + ex.StackTrace, System.Text.Encoding.UTF8, "application/json"),
 891                    StatusCode = System.Net.HttpStatusCode.BadRequest
 892                };
 893                return resp;
 894            }
 895
 896        }
 897
 898        /// <summary>
 899        /// Validate Quote details
 900        /// </summary>
 901        /// <param name="QuoteId"></param>
 902        /// <param name="setIsPrimary"></param>
 903        /// <param name="accessToken"></param>
 904        /// <returns></returns>
 905        public HttpResponseMessage ValidateQuoteDetails(string QuoteId, bool setIsPrimary, string accessToken)
 906        {
 907            try
 908            {
 909                //Build AQL Query to fetch Quote's opprtunityID
 910                var updateResult = new HttpResponseMessage();
 911                var query = new Query(Constants.OBJ_QUOTE);
 912                query.AddColumns(Constants.OBJ_QUOTEVALIDATE_DEFAULT_SELECTFIELD.Split(Constants.CHAR_COMMA));
 913                Expression exp = new Expression(ExpressionOperator.AND);
 914                exp.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId));
 915
 916                Join account = new Join(Constants.OBJ_QUOTE, Constants.OBJ_ACCOUNT, Constants.FIELD_ACCOUNTID, Constants.FIELD_ID, JoinType.LEFT);
 917                account.EntityAlias = Constants.OBJ_ACCOUNT;
 918                query.AddJoin(account);
 919
 920                query.SetCriteria(exp);
 921
 922                var jsonQuery = query.Serialize();
 923
 924
 925                var reqConfig = new RequestConfigModel();
 926                reqConfig.accessToken = accessToken;
 927                reqConfig.searchType = SearchType.AQL;
 928                reqConfig.objectName = Constants.OBJ_QUOTE;
 929
 930                var response = Utilities.Search(jsonQuery, reqConfig);
 931                ValidateDefaultQuoteResult objValidateDefaultQuoteResult = new ValidateDefaultQuoteResult();
 932                List<Dictionary<string, object>> ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
 933
 934                if (response != null && response.IsSuccessStatusCode)
 935                {
 936                    var responseString = JObject.Parse(response.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 937                    List<QuoteValidate> objQuoteOppoDetails = new List<QuoteValidate>();
 938
 939                    objQuoteOppoDetails = JsonConvert.DeserializeObject<List<QuoteValidate>>(responseString);
 940
 941                    if (objQuoteOppoDetails != null && objQuoteOppoDetails.Count > 0)
 942                    {
 943                        #region "Validate and Set IsPrimary true for only current Quote"
 944                        //Validate all quotes for an opportunity and update current Quote IsPrimary field set to true and rest of the Quotes IsPrimary will be set to false.
 945                        if (objQuoteOppoDetails.FirstOrDefault().IsPrimary != null)
 946                        {
 947                            setIsPrimary = Convert.ToBoolean(ConversionHelper.ConvertToBool(objQuoteOppoDetails.FirstOrDefault().IsPrimary));
 948                        }
 949                        else
 950                        {
 951                            setIsPrimary = false;
 952                        }
 953                        if (setIsPrimary && objQuoteOppoDetails.FirstOrDefault().ext_OpportunitySysId != null)
 954                        {
 955                            //Build AQL Query to fetch all quotes of opprtunityID 
 956                            var queryQuote = new Query(Constants.OBJ_QUOTE);
 957                            queryQuote.AddColumns(Constants.OBJ_QUOTEOPPORTUNITY_SELECTFIELD.Split(Constants.CHAR_COMMA));
 958                            Expression expQuote = new Expression(ExpressionOperator.AND);
 959                            expQuote.AddCondition(new Condition(Constants.FIELD_OPPORTUNITYSYSID, FilterOperator.Equal, objQuoteOppoDetails[0].ext_OpportunitySysId));
 960
 961                            queryQuote.SetCriteria(expQuote);
 962
 963                            jsonQuery = queryQuote.Serialize();
 964
 965                            reqConfig = new RequestConfigModel();
 966                            reqConfig.accessToken = accessToken;
 967                            reqConfig.searchType = SearchType.AQL;
 968                            reqConfig.objectName = Constants.OBJ_QUOTE;
 969
 970                            var responseQuotewithOppo = Utilities.Search(jsonQuery, reqConfig);
 971                            if (responseQuotewithOppo != null && responseQuotewithOppo.IsSuccessStatusCode)
 972                            {
 973                                var responseQuotewithOppoString = JObject.Parse(responseQuotewithOppo.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
 974                                List<QuoteValidate> objQuoteOppoResult = new List<QuoteValidate>();
 975                                objQuoteOppoResult = JsonConvert.DeserializeObject<List<QuoteValidate>>(responseQuotewithOppoString);
 976
 977                                //Check for any other Quote is set to IsPrimary to true 
 978                                ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
 979                                Dictionary<string, object> QuoteFieldToUpdate = new Dictionary<string, object>();
 980                                var otherQuoteIsPrimary = objQuoteOppoResult.Where(x => x.Id != QuoteId && x.IsPrimary == true);
 981                                if (otherQuoteIsPrimary != null && otherQuoteIsPrimary.Count() > 0)
 982                                {
 983                                    //Set any other Quotes IsPrimary value to false
 984                                    foreach (var item in otherQuoteIsPrimary)
 985                                    {
 986                                        QuoteFieldToUpdate = new Dictionary<string, object>();
 987                                        QuoteFieldToUpdate.Add("Id", item.Id);
 988                                        QuoteFieldToUpdate.Add("IsPrimary", false);
 989                                        ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
 990                                        ListQuoteFieldToUpdate.Add(QuoteFieldToUpdate);
 991
 992                                        UpdateQuoteIsPrimary(ListQuoteFieldToUpdate, accessToken);
 993                                    }
 994                                }
 995
 996                                //Update only current Quote as IsPrimary true
 997                                QuoteFieldToUpdate = new Dictionary<string, object>();
 998                                QuoteFieldToUpdate.Add("Id", QuoteId);
 999                                QuoteFieldToUpdate.Add("IsPrimary", true);
1000                                ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
1001                                ListQuoteFieldToUpdate.Add(QuoteFieldToUpdate);
1002
1003                                updateResult = UpdateQuoteIsPrimary(ListQuoteFieldToUpdate, accessToken);
1004                                objValidateDefaultQuoteResult.IsPrimarySet = updateResult.IsSuccessStatusCode;
1005                            }
1006                        }
1007                        #endregion
1008
1009                        #region "Currency Based on pricing"
1010                        if (objQuoteOppoDetails.Count > 0 && objQuoteOppoDetails.FirstOrDefault().PriceListId != null)
1011                        {
1012                            var queryPriceListCurrency = new Query(Constants.OBJ_PRICELIST);
1013                            queryPriceListCurrency.AddColumns(Constants.OBJ_PRICELIST_SELECTFIELD.Split(Constants.CHAR_COMMA));
1014                            Expression expPriceListCurrency = new Expression(ExpressionOperator.AND);
1015                            expPriceListCurrency.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, objQuoteOppoDetails.FirstOrDefault().PriceListId.Id));
1016
1017                            queryPriceListCurrency.SetCriteria(expPriceListCurrency);
1018
1019                            jsonQuery = queryPriceListCurrency.Serialize();
1020
1021                            reqConfig = new RequestConfigModel();
1022                            reqConfig.accessToken = accessToken;
1023                            reqConfig.searchType = SearchType.AQL;
1024                            reqConfig.objectName = Constants.OBJ_PRICELIST;
1025
1026                            var responsePricelistCurrencyDetail = Utilities.Search(jsonQuery, reqConfig);
1027                            if (responsePricelistCurrencyDetail != null && responsePricelistCurrencyDetail.IsSuccessStatusCode)
1028                            {
1029                                var responsePricelistString = JObject.Parse(responsePricelistCurrencyDetail.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
1030                                List<QQuoteLineItem> objPriceListResult = new List<QQuoteLineItem>();
1031                                objPriceListResult = JsonConvert.DeserializeObject<List<QQuoteLineItem>>(responsePricelistString);
1032
1033                                if (objPriceListResult != null && objPriceListResult.Count > 0)
1034                                {
1035                                    ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
1036                                    Dictionary<string, object> QuoteFieldToUpdate = new Dictionary<string, object>();
1037
1038                                    QuoteFieldToUpdate = new Dictionary<string, object>();
1039                                    QuoteFieldToUpdate.Add("Id", QuoteId);
1040                                    QuoteFieldToUpdate.Add("ext_BaseCurrency", Convert.ToString(objPriceListResult.FirstOrDefault().CurrencyId));
1041                                    ListQuoteFieldToUpdate = new List<Dictionary<string, object>>();
1042                                    ListQuoteFieldToUpdate.Add(QuoteFieldToUpdate);
1043
1044                                    updateResult = UpdateQuoteIsPrimary(ListQuoteFieldToUpdate, accessToken);
1045                                    //objValidateDefaultQuoteResult.IsPrimarySet = updateResult.IsSuccessStatusCode;
1046                                }
1047                            }
1048                        }
1049                        #endregion
1050                    }
1051                }
1052                return updateResult;
1053            }
1054            catch (Exception ex)
1055            {
1056                var resp = new HttpResponseMessage
1057                {
1058                    Content = new StringContent("Message :" + ex.Message + " " + "StackStrace :" + ex.StackTrace, System.Text.Encoding.UTF8, "application/json"),
1059                    StatusCode = System.Net.HttpStatusCode.BadRequest
1060                };
1061                return resp;
1062            }
1063
1064        }
1065
1066        /// <summary>
1067        /// To update IsPrimary field of Quote
1068        /// </summary>
1069        /// <param name="quoteHeaderList"></param>
1070        /// <param name="accessToken"></param>
1071        /// <returns></returns>
1072        public HttpResponseMessage UpdateQuoteIsPrimary(List<Dictionary<string, object>> quoteHeaderList, string accessToken)
1073        {
1074            var reqConfig = new RequestConfigModel();
1075            reqConfig.accessToken = accessToken;
1076            reqConfig.objectName = Constants.OBJ_QUOTE;
1077            var responseString = Utilities.Update(quoteHeaderList, reqConfig);
1078            return responseString;
1079        }
1080
1081        #region Approvals On Quote
1082
1083        /// <summary>
1084        /// Get, Calculate and update Approval Fields
1085        /// </summary>
1086        /// <param name="QuoteId"></param>
1087        /// <param name="accessToken"></param>
1088        /// <returns></returns>
1089        public HttpResponseMessage CalculateApprovalFields(string QuoteId, string accessToken)
1090        {
1091            try
1092            {
1093                //Build AQL Query to fetch Quote's opprtunityID
1094                var updateResult = new HttpResponseMessage();
1095                var query = new Query(Constants.OBJ_QUOTE);
1096                query.AddColumns(Constants.OBJ_APPROVALCALCULATION_DEFAULT_SELECTFIELDS.Split(Constants.CHAR_COMMA));
1097                Expression exp = new Expression(ExpressionOperator.AND);
1098                exp.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId));
1099                query.SetCriteria(exp);
1100
1101                Join quoteLineItem = new Join(Constants.OBJ_QUOTE, Constants.OBJ_CPQ_QUOTELINEITEM, Constants.FIELD_ID, Constants.FIELD_QUOTEID, JoinType.LEFT, Constants.OBJALIAS_QUOTELINEITEM);
1102                query.AddJoin(quoteLineItem);
1103
1104                Join agreement = new Join(Constants.OBJ_QUOTE, Constants.OBJ_AGREEMENT, Constants.FIELD_EXT_REFAGREEMENT, Constants.FIELD_ID, JoinType.LEFT, Constants.OBJALIAS_AGREEMENT);
1105                query.AddJoin(agreement);
1106
1107                var jsonQuery = query.Serialize();
1108                var reqConfig = new RequestConfigModel()
1109                {
1110                    accessToken = accessToken,
1111                    searchType = SearchType.AQL,
1112                    objectName = Constants.OBJ_QUOTE
1113                };
1114                var response = Utilities.Search(jsonQuery, reqConfig);
1115                if (response != null && response.IsSuccessStatusCode)
1116                {
1117                    var responseString = JObject.Parse(response.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
1118                    var quoteDetails = JsonConvert.DeserializeObject<List<QuoteResponseApproval>>(responseString);
1119
1120                    if (quoteDetails != null && quoteDetails.Count() > 0)
1121                    {
1122                        //Inialize variables
1123                        double ext_DealSize = 0.0;
1124                        decimal ext_MaxDiscount = 0.0m;
1125                        int ext_RenewalCount = 0;
1126                        bool ext_ApproverUserDiscount = false;
1127                        bool ext_CustomerSatisfactionException = false;
1128                        bool ext_EndOfLifeProducts = false;
1129
1130                        //Logic to update Approval Fields
1131                        DealSizeCalculation(quoteDetails, ref ext_DealSize, accessToken);
1132                        MaxDiscountCalculation(quoteDetails, ref ext_MaxDiscount);
1133                        RenewalCountCalculation(quoteDetails, ref ext_RenewalCount);
1134                        ApproverUserDiscountCalculation(quoteDetails, ref ext_ApproverUserDiscount);
1135                        CustomerSatisfactionExceptionApprovalCalculation(quoteDetails, ref ext_CustomerSatisfactionException);
1136                        EndOfLifeProductsApprovalCalculation(quoteDetails, ref ext_EndOfLifeProducts);
1137
1138                        //Add all approval fields into dictionary
1139                        var QuoteFieldToUpdate = new Dictionary<string, object>
1140                        {
1141                            { "Id", QuoteId },
1142                            { "ext_DealSize", ext_DealSize },
1143                            { "ext_MaxDiscount", ext_MaxDiscount },
1144                            { "ext_RenewalCount", ext_RenewalCount },
1145                            { "ext_ApproverUserDiscount", ext_ApproverUserDiscount },
1146                            { "ext_EndOfLifeProductsApproval", ext_EndOfLifeProducts },
1147                            { "ext_CustomerSatisfactionExceptionApproval", ext_MaxDiscount }
1148                        };
1149
1150                        //Update fields via API
1151                        updateResult = UpdateQuoteWithApprovalFields(new List<Dictionary<string, object>>() { QuoteFieldToUpdate }, accessToken);
1152                    }
1153                }
1154                return updateResult;
1155            }
1156            catch (Exception ex)
1157            {
1158                //TODO
1159                throw;
1160            }
1161
1162        }
1163
1164        /// <summary>
1165        /// Deal size calculation
1166        /// </summary>
1167        /// <param name="quoteDetails"></param>
1168        /// <param name="ext_DealSize"></param>
1169        /// <returns></returns>
1170        private void DealSizeCalculation(List<QuoteResponseApproval> quoteDetails, ref double ext_DealSize, string accessToken)
1171        {
1172            // Get subscription products 
1173            var subscriptionFamilyQuoteDetails = quoteDetails.Where(q => q.QLI.ProductId.ext_Family != null && q.QLI.ProductId.ext_Family.Key.ConvertToStringNull() == Constants.STR_PRODUCT_FAMILY_SUBSCRIPTIONS).ToList();
1174
1175            // New Business 
1176            if (quoteDetails.Where(q => q.ext_Type.ConvertToStringNull() != null && q.ext_Type.Key.ConvertToStringNull() != null && q.ext_Type.Key == Enums.QuoteType.NewBusiness.GetEnumDisplayName()).Count() > 0)
1177            {
1178                //  A field on Quote Header.Rollup of USD Annual List Price of all the subscription products in the cart. 
1179                ext_DealSize = subscriptionFamilyQuoteDetails.Sum(s => s.QLI.ext_USDAnnualListPrice.ConvertToDouble());
1180            }
1181
1182            // Upsell  
1183            if (quoteDetails.Where(q => !string.IsNullOrEmpty(q.ext_Type.Key) && q.ext_Type.Key == Enums.QuoteType.LicenseUpsell.GetEnumDisplayName()).Count() > 0)
1184            {
1185                //USD Total Annual List Price = Total Annual List Value from the agreement 
1186                ext_DealSize = quoteDetails.First().AGR.ext_QuoteId.ext_DealSize.ConvertToDouble();
1187
1188                //Calculate rollup of USD Annual List Price of all the subscription products in the cart
1189                var rollUpUSDAnnualListPrice = 0.0;
1190                //objResultQuoteLineItem.ext_USDListPrice = objDailyExcnageRate.ext_Rate * (QuoteLineList[i].cpq_QuoteLineItem.BasePrice); //To Do: Replace 'BasePrice' with 'ListPrice' while calculating QLI.ext_USDListPrice!!
1191                subscriptionFamilyQuoteDetails.ForEach(p => rollUpUSDAnnualListPrice += (p.QLI.ext_USDListPrice.ConvertToDouble() * p.QLI.ext_ContractQuantity.ConvertToDouble()));
1192
1193                // Total Deal Size = Previous value(Agreement's DealSize) + ollup of USD Annual List Price of all the subscription products
1194                ext_DealSize += rollUpUSDAnnualListPrice;
1195            }
1196        }
1197        /// <summary>
1198        /// Max Discount Calculation
1199        /// </summary>
1200        /// <param name="quoteDetails"></param>
1201        /// <param name="ext_MaxDiscount"></param>
1202        /// <returns></returns>
1203        private void MaxDiscountCalculation(List<QuoteResponseApproval> quoteDetails, ref decimal ext_MaxDiscount)
1204        {
1205            var quoteType = quoteDetails.First().ext_Type?.Key.ConvertToStringNull();
1206            var salesType = quoteDetails.First().ext_salestype?.Key.ConvertToStringNull();
1207
1208            if ((quoteType == Enums.QuoteType.NewBusiness.GetEnumDisplayName() || quoteType == Enums.QuoteType.LicenseUpsell.GetEnumDisplayName())
1209                    && (salesType == "Direct" || salesType == "InDirect"))
1210            {
1211                // Maximum % of all the discounts on line item. 
1212                ext_MaxDiscount = quoteDetails.Max(s => (s.QLI.ext_AdjustmentDiscountPercent.ConvertToDecimal()));
1213            }
1214        }
1215        /// <summary>
1216        /// Renewal count calculations
1217        /// </summary>
1218        /// <param name="quoteDetails"></param>
1219        /// <param name="ext_RenewalCount"></param>
1220        /// <returns></returns>
1221        private void RenewalCountCalculation(List<QuoteResponseApproval> quoteDetails, ref int ext_RenewalCount)
1222        {
1223            // ext_AdjustmentDiscountPercent Renewal Count -If this.proposal has a previous proposal ( another field on quote ) and that previous proposal doesnt have any predecessor, the count will be calculated as 1.
1224            var quote = quoteDetails.First();
1225            if (quote.ext_Type != null && quote.ext_Type.Key.ConvertToStringNull() != null && quote.ext_Type.Key == "Renewal" && quote.AGR != null && quote.AGR.ext_QuoteId != null && quote.AGR.ext_QuoteId.Id.ConvertToString() != null)
1226            {
1227                ext_RenewalCount = 1;
1228            }
1229
1230        }
1231        /// <summary>
1232        /// Approver User Discount Calculation
1233        /// </summary>
1234        /// <param name="quoteDetails"></param>
1235        /// <param name="ext_ApproverUserDiscount"></param>
1236        /// <returns></returns>
1237        private void ApproverUserDiscountCalculation(List<QuoteResponseApproval> quoteDetails, ref bool ext_ApproverUserDiscount)
1238        {
1239            // For Direct Sale 
1240            if (quoteDetails.Where(q => q.ext_salestype != null && q.ext_salestype.Key.ConvertToStringNull() != null && q.ext_salestype.Key.Equals("Direct")).Count() > 0)
1241            {
1242                ext_ApproverUserDiscount = ((quoteDetails.Where(q => q.ext_salestype != null && q.ext_salestype.Key.ConvertToStringNull() != null && q.ext_salestype.Key == "Direct"
1243                                                    && q.QLI.AttributeValueId.ext_UserModel != null && q.QLI.AttributeValueId.ext_UserModel.Key.ConvertToStringNull() != null && q.QLI.AttributeValueId.ext_UserModel.Key == "Approver User"
1244                                                    && q.AccountId.ext_Segment != null && q.AccountId.ext_Segment.Key.ConvertToStringNull() != null && (q.AccountId.ext_Segment.Key.Equals("Commercial")
1245                                                                                        || q.AccountId.ext_Segment.Key.Equals("Mid-Market") || q.AccountId.ext_Segment.Key.Equals("Small Business"))).Count() > 0
1246                                             && quoteDetails.Max(s => s.QLI.ext_AdjustmentDiscountPercent.ConvertToDecimal()) == 100.ConvertToDecimal())
1247                                           ? true
1248                                           : false);
1249            }
1250            // For InDirect Sale 
1251            else if (quoteDetails.Where(q => q.ext_salestype != null && q.ext_salestype.Key.ConvertToStringNull() != null && q.ext_salestype.Key.Equals("Indirect")
1252                            && q.ext_SalesPartner != null && !string.IsNullOrEmpty(q.ext_SalesPartner.Name)).Count() > 0)
1253            {
1254                ext_ApproverUserDiscount = ((quoteDetails.Where(q => q.ext_salestype != null && !string.IsNullOrEmpty(q.ext_salestype.Key) && q.ext_salestype.Key.Equals("Indirect")
1255                                                && q.QLI.AttributeValueId.ext_UserModel != null && q.QLI.AttributeValueId.ext_UserModel.Key.ConvertToStringNull() != null && q.QLI.AttributeValueId.ext_UserModel.Key.Equals("Approver User")
1256                                                && q.ext_SalesPartner.ext_Segment != null && q.ext_SalesPartner.ext_Segment.Key.ConvertToStringNull() != null && (q.ext_SalesPartner.ext_Segment.Key.Equals("Commercial")
1257                                                        || q.ext_SalesPartner.ext_Segment.Key.Equals("Mid-Market") || q.ext_SalesPartner.ext_Segment.Key.Equals("Small Business"))).Count() > 0
1258                                              && quoteDetails.Max(s => s.QLI.ext_AdjustmentDiscountPercent.ConvertToDecimal()) == 100.ConvertToDecimal())
1259                                            ? true
1260                                            : false);
1261
1262            }
1263        }
1264        /// <summary>
1265        /// Customer Satisfaction Exception Approval Calculation
1266        /// </summary>
1267        /// <param name="quoteDetails"></param>
1268        /// <param name="ext_CustomerSatisfactionException"></param>
1269        /// <returns></returns>
1270        private void CustomerSatisfactionExceptionApprovalCalculation(List<QuoteResponseApproval> quoteDetails, ref bool ext_CustomerSatisfactionException)
1271        {
1272            if (quoteDetails.Where(s => s.QLI.ext_AdjustmentDiscountPercent.ConvertToDecimal() == 100.ConvertToDecimal()).ToList().Count > 0)
1273            {
1274                ext_CustomerSatisfactionException = true;
1275            }
1276        }
1277        /// <summary>
1278        /// Customer Satisfaction Exception Approval Calculation
1279        /// </summary>
1280        /// <param name="quoteDetails"></param>
1281        /// <param name="ext_EndOfLifeProducts"></param>
1282        /// <returns></returns>
1283        private void EndOfLifeProductsApprovalCalculation(List<QuoteResponseApproval> quoteDetails, ref bool ext_EndOfLifeProducts)
1284        {
1285            if (quoteDetails.Where(q => q.ext_Type != null && q.ext_Type.Key.ConvertToStringNull() != null && q.ext_Type.Key.Equals("new_business")
1286                    && q.QLI.ProductId.ConvertToStringNull() != null && q.QLI.ProductId.ext_ProductLifecycleStatus.ConvertToStringNull() != null
1287                        && q.QLI.ProductId.ext_ProductLifecycleStatus.Key.ConvertToStringNull() != null && q.QLI.ProductId.ext_ProductLifecycleStatus.Key.Equals("EOS And Inactive")).Count() > 0)
1288            {
1289                ext_EndOfLifeProducts = true;
1290            }
1291        }
1292
1293        private HttpResponseMessage UpdateQuoteWithApprovalFields(List<Dictionary<string, object>> quoteHeaderList, string accessToken)
1294        {
1295            var reqConfig = new RequestConfigModel()
1296            {
1297                accessToken = accessToken,
1298                objectName = Constants.OBJ_QUOTE
1299            };
1300            var responseString = Utilities.Update(quoteHeaderList, reqConfig);
1301            return responseString;
1302        }
1303
1304
1305        /// <summary>
1306        /// Get, Calculate and update Approval Fields
1307        /// </summary>
1308        /// <param name="QuoteId"></param>
1309        /// <param name="accessToken"></param>
1310        /// <returns></returns>
1311        public HttpResponseMessage CalculatePSApprovalFields(string QuoteId, string accessToken)
1312        {
1313            try
1314            {
1315                var updateResult = new HttpResponseMessage();
1316
1317                //Build AQL Query to fetch Quote's opprtunityID
1318                var query = new Query(Constants.OBJ_QUOTE);
1319                query.AddColumns(Constants.OBJ_PSAPPROVALCALCULATION_DEFAULT_SELECTFIELDS.Split(Constants.CHAR_COMMA));
1320                Expression exp = new Expression(ExpressionOperator.AND);
1321                exp.AddCondition(new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId));
1322                query.SetCriteria(exp);
1323
1324                Join quoteLineItem = new Join(Constants.OBJ_QUOTE, Constants.OBJ_CPQ_QUOTELINEITEM, Constants.FIELD_ID, Constants.FIELD_QUOTEID, JoinType.LEFT, Constants.OBJALIAS_QUOTELINEITEM)
1325                {
1326                    JoinCriteria = new Expression { Conditions = new List<Condition>() { new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId) } }
1327                };
1328                query.AddJoin(quoteLineItem);
1329
1330                Join quoteMileStone = new Join(Constants.OBJ_QUOTE, Constants.OBJ_EXT_MILESTONE, Constants.FIELD_ID, Constants.FIELD_EXT_QUOTEID, JoinType.LEFT, Constants.OBJALIAS_MILESTONE)
1331                {
1332                    JoinCriteria = new Expression { Conditions = new List<Condition>() { new Condition(Constants.FIELD_ID, FilterOperator.Equal, QuoteId) } }
1333                };
1334                query.AddJoin(quoteMileStone);
1335
1336                var jsonQuery = query.Serialize();
1337                var reqConfig = new RequestConfigModel()
1338                {
1339                    accessToken = accessToken,
1340                    searchType = SearchType.AQL,
1341                    objectName = Constants.OBJ_QUOTE
1342                };
1343                var response = Utilities.Search(jsonQuery, reqConfig);
1344                if (response != null && response.IsSuccessStatusCode)
1345                {
1346                    var responseString = JObject.Parse(response.Content.ReadAsStringAsync().Result).SelectToken(Constants.NODE_SERIALIZEDRESULTENTITIES).ToString();
1347                    var quoteDetails = JsonConvert.DeserializeObject<List<PSQuoteResponseApproval>>(responseString);
1348                    decimal ext_TEDiscount = 0.0m;
1349                    decimal ext_AverageDiscount = 0.0m;
1350                    bool ext_MilestoneExists = false;
1351
1352                    //Logic to update PS Approval Fields
1353                    if (quoteDetails != null && quoteDetails.Count() > 0)
1354                    {
1355                        ext_MilestoneExists = (quoteDetails.Where(x => (x.MS != null) && (x.MS.Id.ConvertToStringNull() != null)).Count() > 0) ? true : false;
1356                        CalculateTEDiscount(quoteDetails, ref ext_TEDiscount);
1357                        CalculateAverageDiscount(quoteDetails, ref ext_AverageDiscount);
1358
1359                        //Update all PS approval fields
1360                        var QuoteFieldToUpdate = new Dictionary<string, object>
1361                        {
1362                            { "ext_MilestoneExists", ext_MilestoneExists },
1363                            { "ext_TEDiscount2", ext_TEDiscount.ConvertToDecimal() },
1364                            { "ext_AverageDiscount", ext_AverageDiscount },
1365                            { "Id", QuoteId}
1366                        };
1367                        updateResult = UpdateQuoteWithApprovalFields(new List<Dictionary<string, object>>() { QuoteFieldToUpdate }, accessToken);
1368                    }
1369                }
1370                return updateResult;
1371            }
1372            catch (Exception ex)
1373            {
1374                //TODO
1375                throw;
1376            }
1377
1378        }
1379        /// <summary>
1380        /// TE discount Calculation
1381        /// </summary>
1382        /// <param name="quoteDetails"></param>
1383        /// <param name="ext_TEDiscount"></param>
1384        /// <returns></returns>
1385        private void CalculateTEDiscount(List<PSQuoteResponseApproval> quoteDetails, ref decimal ext_TEDiscount)
1386        {
1387            var TAndEProducts = quoteDetails.Where(s => s.QLI.ProductId != null && s.QLI.ProductId.Name.ConvertToStringNull() != null && s.QLI.ProductId.Name.Equals("Travel and Expense"));
1388            if (TAndEProducts.Count() > 0)
1389            {
1390                ext_TEDiscount = TAndEProducts.Max(x => x.QLI.ext_AdjustmentDiscountPercent.ConvertToDecimal());
1391            }
1392        }
1393        /// <summary>
1394        /// Average discount Calculation
1395        /// </summary>
1396        /// <param name="quoteDetails"></param>
1397        /// <param name="ext_TEDiscount"></param>
1398        /// <returns></returns>
1399        private void CalculateAverageDiscount(List<PSQuoteResponseApproval> quoteDetails, ref decimal ext_AverageDiscount)
1400        {
1401            var filterdQLIs = quoteDetails.Where(s => s.QLI.ext_AdjustmentDiscountPercent != null && s.QLI.ext_AdjustmentDiscountPercent != 0.0m);
1402            if (filterdQLIs.Count() > 0)
1403            {
1404                ext_AverageDiscount = filterdQLIs.Sum(x => x.QLI.ext_AdjustmentDiscountPercent.ConvertToDecimal()) / filterdQLIs.Count();
1405            }
1406        }
1407
1408        #endregion Approvals On Quote
1409
1410    }
1411}