/* * For calculating the offering cost when there could also be discount info involved. * Where it gets more complicated is when there are BULK_DISCOUNTs because each of the * tiers has both a maximum and minimum quantity that needs to be checked. */ private OfferingsDisc CalcOfferingCost(OfferingsDisc offer) { // if the discount type is NULL the totalOfferingCost is just unit_retail * qty if (offer.Type == null) { offer.totalOfferingCost = (Math.Round(Convert.ToDecimal(offer.unit_retail) * offer.Quantity, 2)).ToString(); } else if (offer.Type != "BULK_DISCOUNT") // if the discount isn't NULL and isn't a BULK_DSICOUNT { // check to max use the Quantity isn't > MaxQty otherwise the discount doesn't apply anymore if (offer.Quantity < offer.MaxQty) { offer.totalOfferingCost = (Math.Round(Convert.ToDecimal(offer.discount_price) * offer.Quantity, 2)).ToString(); } else { offer.totalOfferingCost = (Math.Round(Convert.ToDecimal(offer.unit_retail) * offer.Quantity, 2)).ToString(); } } else if (offer.Type == "BULK_DISCOUNT") { // iterate through all of the Tiers in the BULK_DISCOUNT starting from the last one to ensure we're applying the largest discount possible for (int ii = offer.Tiers.Count() - 1; ii >= 0; ii--) { // check if Quantity falls within MinQty and MaxQty of the current Tier if (offer.Quantity <= offer.Tiers[ii].MaxQty && offer.Quantity >= offer.Tiers[ii].MinQty) { offer.discount_price = (Math.Round(Convert.ToDecimal(offer.unit_retail) * (1 - (offer.Tiers[ii].DiscountPercentage / 100)), 2)).ToString(); offer.totalOfferingCost = (Math.Round(Convert.ToDecimal(offer.discount_price) * offer.Quantity, 2)).ToString(); break; } else if (offer.Quantity >= offer.Tiers[ii].MaxQty && ii == 0) // set discount_price to null is no discounts apply { offer.discount_price = null; offer.totalOfferingCost = (Math.Round(Convert.ToDecimal(offer.unit_retail) * offer.Quantity, 2)).ToString(); } } if (offer.discount_price == null) // update total offering cost when no BULK_DISCOUNTS apply { offer.totalOfferingCost = (Math.Round(Convert.ToDecimal(offer.unit_retail) * offer.Quantity, 2)).ToString(); } } return(offer); }
public async Task <IActionResult> AddToBasket(string offeringID, [FromHeader] string authorization, [FromQuery] int qty = 0) { // make sure an offering_key was sent - can't do anything without it if (offeringID == null) { return(BadRequest(new BadRequestError("no offering_key sent."))); } // make sure the quantity is greater than zero if (qty <= 0) { return(BadRequest(new BadRequestError("Quantity is zero"))); } // get the user_id var ID = GetID(); if (ID == null) { return(BadRequest(new BadRequestError("user_id not found."))); } // attempt to retreive the users Basket document var doc = await _bucket.GetAsync <BasketDisc>(ID); int newOffering = 0; BasketDisc userDoc = null; // check to see if a document was retreived, need to create a new one if it wasn't if (doc.Success) { userDoc = doc.Value; // documents are persistent once they have been created so update the doc with the new time if total_items is zero if (userDoc.total_items == 0) { userDoc.Date = DateTimeOffset.Now.ToUnixTimeSeconds(); } // check to see if the offeringID sent in the route is already in the OfferingsDisc array if (userDoc.OfferingsDisc.Exists(i => i.Offering_key == offeringID)) { OfferingsDisc offer = userDoc.OfferingsDisc.Find(i => i.Offering_key == offeringID); // find the index of where the element with offeringID is located in the array var index = userDoc.OfferingsDisc.IndexOf(offer, 0); // update all the information about the offering in the basket userDoc.OfferingsDisc[index].Quantity += qty; userDoc.total_cost = (Convert.ToDecimal(userDoc.total_cost) - Convert.ToDecimal(offer.totalOfferingCost)).ToString(); userDoc.OfferingsDisc[index] = CalcOfferingCost(userDoc.OfferingsDisc[index]); userDoc.total_cost = (Convert.ToDecimal(userDoc.total_cost) + Convert.ToDecimal(offer.totalOfferingCost)).ToString(); } else // if the offeringID isn't in the array set the newOffering flag (used later) { newOffering = 1; } } // if there isn't already a Basket document for the user or the newOffering flag is set if (!doc.Success || newOffering == 1) { // split the authorization header string to remove 'Bearer' and isolate the JWT token string[] auth = authorization.Split(' '); // use the GetOffering() function to send the HTTP request to the CatalogApi to get the information about the offering being added HttpResponseMessage httpResponse = await GetOffering(auth[1], "http://localhost:7000/catalog-api/products/disc/singleOffering/" + offeringID); // make sure the HTTP response from the CatalogApi was successful if (!httpResponse.IsSuccessStatusCode) { return(BadRequest(new BadRequestError(httpResponse.StatusCode.ToString() + " HttpRequest Failed."))); } // read the response as a type OfferingsDisc (what we will be adding to the Basket document) OfferingsDisc offering = await httpResponse.Content.ReadAsAsync <OfferingsDisc>(); offering.Quantity = qty; BasketDisc basket = null; // check to see if the discount type is a BULK_DISCOUNT, need to use interproces communication again to get the tiers information about it if (offering.Type != "BULK_DISCOUNT") { offering = CalcOfferingCost(offering); } else if (offering.Type == "BULK_DISCOUNT") { // get the BULK_DISCOUNT tiers information httpResponse = await GetOffering(auth[1], "http://localhost:7000/catalog-api/products/disc/getDiscount/" + offering.Discount_key); if (!httpResponse.IsSuccessStatusCode) { return(BadRequest(new BadRequestError(httpResponse.StatusCode.ToString() + " HttpRequest Failed."))); } // use the tiers information to correctly calculate the cost of the offering being added offering.Tiers = new List <Tiers>(); offering.Tiers = await httpResponse.Content.ReadAsAsync <List <Tiers> >(); offering = CalcOfferingCost(offering); } // if newOffering is 0 update all the information and insert the Basket document if (newOffering == 0) { basket = new BasketDisc(); basket.Uid = Guid.NewGuid(); basket.Date = DateTimeOffset.Now.ToUnixTimeSeconds(); basket.total_items = 1; basket.OfferingsDisc = new List <OfferingsDisc>(); basket.OfferingsDisc.Add(offering); basket.total_cost = offering.totalOfferingCost; var res = await _bucket.UpsertAsync(ID, basket); if (!res.Success) { return(BadRequest(new BadRequestError("Failed to add document to database - new basket"))); } return(Ok(basket)); } userDoc.total_cost = (Convert.ToDecimal(userDoc.total_cost) + Convert.ToDecimal(offering.totalOfferingCost)).ToString(); userDoc.OfferingsDisc = userDoc.OfferingsDisc.Prepend(offering).ToList(); userDoc.total_items += 1; } // insert the Basket document var result = await _bucket.UpsertAsync(ID, userDoc); if (!result.Success) { return(BadRequest(new BadRequestError("Failed to add userDoc to database"))); } // reutrn 200 OK, we don't need to return userDoc this was for testing return(Ok(userDoc)); }
public async Task <IActionResult> UpdateQuant(string offeringID, int qty = 0) { var ID = GetID(); if (ID == null) { return(BadRequest(new BadRequestError("user_id not found."))); } if (qty < 0) { return(BadRequest(new BadRequestError("Invalid quantity."))); } // using a view to only get the information from the Basket document that we need var query = new ViewQuery().From("dev_BasketDisc", "by_id").Key(new List <string> { ID, offeringID }); var res = await _bucket.QueryAsync <dynamic>(query); // check to make sure the ViewQuery was successful and returned information if (!res.Success || res.Rows.Count() == 0) { return(NotFound(res.Message)); } // set the variables that will be needed from the info retrieved from the query var info = res.Rows.ToList().First().Value; int index = info[0]; OfferingsDisc offering = JsonConvert.DeserializeObject <OfferingsDisc>(info[3].ToString()); decimal total_cost = Convert.ToDecimal(info[1]) - Convert.ToDecimal(offering.totalOfferingCost); if (qty == 0) { /* * If the qty is 0 we need to remove that item from the users Basket document * we also need to update the total_cost and the total_items */ var response = await _bucket.MutateIn <BasketDisc>(ID) .Upsert("total_cost", total_cost.ToString()) .Upsert("total_items", info[2] - 1) .Remove($"offeringsDisc[{index}]") .ExecuteAsync(); if (!response.Success) { return(NotFound(new NotFoundError(response.Message))); } return(Ok(response)); } // if qty > 0 update the users document offering.Quantity = qty; offering = CalcOfferingCost(offering); total_cost += Convert.ToDecimal(offering.totalOfferingCost); var update_res = await _bucket.MutateIn <BasketDisc>(ID) .Upsert("total_cost", total_cost.ToString()) .Replace($"offeringsDisc[{index}]", offering) .ExecuteAsync(); if (!update_res.Success) { return(NotFound(new NotFoundError(update_res.Message))); } return(Ok(update_res)); }
public async Task <IActionResult> AddDocDiscount([FromBody] BasketDisc basket) { // check if the model binds correctly if (ModelState.IsValid) { // get the users ID from the HttpContext var ID = GetID(); // The ID should never be NULL because they wouldn't have been authorized but checking anyways if (ID == null) { return(BadRequest(new BadRequestError("user_id not found."))); } var doc = await _bucket.GetAsync <BasketDisc>(ID); // check to see if a document for the user exists or not if (!doc.Success) // if the user doesn't already have a basket document make a new one { // check to see if the GUID is set or not if (!basket.Uid.HasValue) { basket.Uid = Guid.NewGuid(); } // update the total number of offerings count in the document basket.total_items = basket.OfferingsDisc.Count(); // attempt to insert the new document var response = await _bucket.UpsertAsync(ID, basket); // return a BadReuqest if this fails if (!response.Success) { return(BadRequest(basket)); } // otherwise return 200 OK return(Ok(response.ToString())); } BasketDisc userDoc = doc.Value; // find if the product offering already exists, if it does replace it with the new one if (userDoc.OfferingsDisc.Exists(i => i.Offering_key == basket.OfferingsDisc[0].Offering_key)) { OfferingsDisc userOffering = userDoc.OfferingsDisc.Find(i => i.Offering_key == basket.OfferingsDisc[0].Offering_key); // get the index of duplicate item currently stored in the basket doc if it eists var index = userDoc.OfferingsDisc.IndexOf(userOffering, 0); // if there is a duplicate item add the quantities together if (index != -1) { userDoc.OfferingsDisc[index].Quantity += basket.OfferingsDisc[0].Quantity; } } else // if there isn't a duplicate item insert the new item being added at the beginning of the list { userDoc.OfferingsDisc = userDoc.OfferingsDisc.Prepend(basket.OfferingsDisc[0]).ToList(); } // update the total count of the number of offerings stored in the document userDoc.total_items = userDoc.OfferingsDisc.Count(); // attempt to insert the updated document into the Basket bucket var result = await _bucket.UpsertAsync(ID, userDoc); // if the upsert fails return a bad request if (!result.Success) { return(BadRequest(basket)); } // if document was successfully replaced return 200 OK return(Ok(basket)); } return(Conflict()); }