private static OrderFulfillment GenerateFulfillment(int fulfillOrderId) { FulfillmentDetails[] fulfillmentList = { new FulfillmentDetails( fulfillmentId: "123", createdAt: new DateTime(2013, 12, 8, 14, 12, 12, DateTimeKind.Local), status: FulfillmentStatusCode.Success, lineItems: new LineItem[] { new LineItem("Bag",10.0, 1) }, trackingCompany: "TestCompany") }; OrderFulfillment orderFulfillment = new OrderFulfillment( merchantOrderId: fulfillOrderId, fulfillments: fulfillmentList); return(orderFulfillment); }
///Use a greedy algorithm to fulfill the order private OrderFulfillment FulfillWithGreedyMultipleShipments(Order order, WarehouseNetwork warehouseNetwork) { var orderFulfillment = new OrderFulfillment(); // <comment for reviewers only:> This is a semi-hacky way to get around "Collection was modified; enumeration operation may not execute." exceptions. It is safe here as long as I know this is the only code modifying the collection var orderKeys = new List <string>(order.Keys); foreach (var warehouse in warehouseNetwork) { var partialOrder = new Order(); foreach (var itemName in orderKeys) { if (!warehouse.Inventory.ContainsKey(itemName)) { continue; } var orderItemQuantity = order[itemName]; var warehouseItemCount = warehouse.Inventory[itemName]; var amountCanFullfill = Math.Min(orderItemQuantity, warehouseItemCount); if (amountCanFullfill > 0) { partialOrder.Add(itemName, amountCanFullfill); //No need to update warehouse inventory directly here //Do need to update order quantity remaining to fulfill, BUT the KeyValuePair object in C# is immutable... need to update the order dictionary itself order[itemName] -= amountCanFullfill; } } if (partialOrder.Count > 0) { orderFulfillment.Add(warehouse.Name, partialOrder); } } return(orderFulfillment); }
public void ToSvRecipient_WhenNullAddress_ReturnsWithNoAddress() { const string name = "Bubba Gump"; var fulfillment = new OrderFulfillment { ShipmentDetails = new OrderFulfillmentShipmentDetails { Recipient = new OrderFulfillmentRecipient { Address = null, DisplayName = name } } }; var recipient = new List <OrderFulfillment> { fulfillment }.ToSvRecipient(); recipient.AddressLine1.Should().BeNullOrEmpty(); recipient.Name.Should().Be(name); }
public static void SendOrdersToRiskifiedExample() { #region preprocessing and loading config string domain = ConfigurationManager.AppSettings["MerchantDomain"]; string authToken = ConfigurationManager.AppSettings["MerchantAuthenticationToken"]; RiskifiedEnvironment riskifiedEnv = (RiskifiedEnvironment)Enum.Parse(typeof(RiskifiedEnvironment), ConfigurationManager.AppSettings["RiskifiedEnvironment"]); // Generating a random starting order number // we need to send the order with a new order number in order to create it on riskified var rand = new Random(); int orderNum = rand.Next(1000, 200000); // Make orderNum a string to use as customer id string idString = $"customerId_{orderNum.ToString()}"; #endregion #region order object creation // generate a new order - the sample generates a fixed order with same details but different order number each time // see GenerateOrder for more info on how to create the Order objects var order = GenerateOrder(orderNum); #endregion #region sending data to riskified // read action from console const string menu = "Commands:\n" + "'p' for checkout\n" + "'e' for checkout denied\n" + "'c' for create\n" + "'u' for update\n" + "'s' for submit\n" + "'d' for cancel\n" + "'r' for partial refund\n" + "'f' for fulfill\n" + "'x' for decision\n" + "'h' for historical sending\n" + "'y' for chargeback submission\n" + "'v' for decide (sync only)\n" + "'l' for eligible for Deco payment \n" + "'o' for opt-in to Deco payment \n" + "'account' for account actions menu\n" + "'q' to quit"; const string accountActionsMenu = "Account Action Commands:\n" + "'li' for login(account)\n" + "'cc' for customer create (account)\n" + "'cu' for customer update (account)\n" + "'lo' for logout (account)\n" + "'pw' for password reset (account)\n" + "'wl' for wishlist (account)\n" + "'re' for redeem (account)\n" + "'co' for contact (account)\n" + "'menu' for main menu\n" + "'q' to quit"; Console.WriteLine(menu); string commandStr = Console.ReadLine(); // loop on console actions while (commandStr != null && (!commandStr.Equals("q"))) { // the OrdersGateway is responsible for sending orders to Riskified servers OrdersGateway gateway = new OrdersGateway(riskifiedEnv, authToken, domain); try { OrderNotification res = null; AccountActionNotification accRes = null; switch (commandStr) { case "menu": case "account": break; case "p": Console.WriteLine("Order checkout Generated with merchant order number: " + orderNum); var orderCheckout = GenerateOrderCheckout(orderNum.ToString()); orderCheckout.Id = orderNum.ToString(); // sending order checkout for creation (if new orderNum) or update (if existing orderNum) res = gateway.Checkout(orderCheckout); break; case "a": Console.WriteLine("Order Advise Generated with merchant order number: " + orderNum); var orderAdviseCheckout = GenerateAdviseOrderCheckout(orderNum.ToString()); orderAdviseCheckout.Id = orderNum.ToString(); // sending order checkout for creation (if new orderNum) or update (if existing orderNum) res = gateway.Advise(orderAdviseCheckout); break; case "e": Console.WriteLine("Order checkout Generated."); var orderCheckoutDenied = GenerateOrderCheckoutDenied(orderNum); Console.Write("checkout to deny id: "); string orderCheckoutDeniedId = Console.ReadLine(); orderCheckoutDenied.Id = orderCheckoutDeniedId; // sending order checkout for creation (if new orderNum) or update (if existing orderNum) res = gateway.CheckoutDenied(orderCheckoutDenied); break; case "c": Console.WriteLine("Order Generated with merchant order number: " + orderNum); order.Id = orderNum.ToString(); orderNum++; // sending order for creation (if new orderNum) or update (if existing orderNum) res = gateway.Create(order); break; case "s": Console.WriteLine("Order Generated with merchant order number: " + orderNum); order.Id = orderNum.ToString(); orderNum++; // sending order for submitting and analysis // it will generate a callback to the notification webhook (if defined) with a decision regarding the order res = gateway.Submit(order); break; case "v": Console.WriteLine("Order Generated with merchant order number: " + orderNum); order.Id = orderNum.ToString(); orderNum++; // sending order for synchronous decision // it will generate a synchronous response with the decision regarding the order // (for sync flow only) res = gateway.Decide(order); break; case "u": Console.Write("Updated order id: "); string upOrderId = Console.ReadLine(); order.Id = int.Parse(upOrderId).ToString(); res = gateway.Update(order); break; case "d": Console.Write("Cancelled order id: "); string canOrderId = Console.ReadLine(); res = gateway.Cancel( new OrderCancellation( merchantOrderId: int.Parse(canOrderId), cancelledAt: DateTime.Now, cancelReason: "Customer cancelled before shipping")); break; case "r": Console.Write("Refunded order id: "); string refOrderId = Console.ReadLine(); res = gateway.PartlyRefund( new OrderPartialRefund( merchantOrderId: int.Parse(refOrderId), partialRefunds: new[] { new PartialRefundDetails( refundId: "12345", refundedAt: DateTime.Now, // make sure to initialize DateTime with the correct timezone amount: 5.3, currency: "USD", reason: "Customer partly refunded on shipping fees") })); break; case "f": Console.Write("Fulfill order id: "); string fulfillOrderId = Console.ReadLine(); OrderFulfillment orderFulfillment = GenerateFulfillment(int.Parse(fulfillOrderId)); res = gateway.Fulfill(orderFulfillment); break; case "x": Console.Write("Decision order id: "); string decisionOrderId = Console.ReadLine(); OrderDecision orderDecision = GenerateDecision(int.Parse(decisionOrderId)); res = gateway.Decision(orderDecision); break; case "h": int startOrderNum = orderNum; var orders = new List <Order>(); var financialStatuses = new[] { "paid", "cancelled", "chargeback" }; for (int i = 0; i < 22; i++) { Order o = GenerateOrder(orderNum++); o.FinancialStatus = financialStatuses[i % 3]; orders.Add(o); } Console.WriteLine("Orders Generated with merchant order numbers: {0} to {1}", startOrderNum, orderNum - 1); // sending 3 historical orders with different processing state Dictionary <string, string> errors; bool success = gateway.SendHistoricalOrders(orders, out errors); if (success) { Console.WriteLine("All historical orders sent successfully"); } else { Console.WriteLine("Some historical orders failed to send:"); Console.WriteLine(String.Join("\n", errors.Select(p => p.Key + ":" + p.Value).ToArray())); } break; case "y": Console.Write("Chargeback order id: "); string chargebackOrderId = Console.ReadLine(); OrderChargeback orderChargeback = GenerateOrderChargeback(chargebackOrderId); res = gateway.Chargeback(orderChargeback); break; case "l": Console.Write("Check Deco eligibility on id: "); string eligibleOrderId = Console.ReadLine(); OrderIdOnly eligibleOrderIdOnly = GenerateOrderIdOnly(eligibleOrderId); res = gateway.Eligible(eligibleOrderIdOnly); break; case "o": Console.Write("Opt-in to Deco payment on id: "); string optInOrderId = Console.ReadLine(); OrderIdOnly optInOrderIdOnly = GenerateOrderIdOnly(optInOrderId); res = gateway.OptIn(optInOrderIdOnly); break; case "li": Console.Write("Login account action"); Login login = GenerateLogin(idString); accRes = gateway.Login(login); break; case "cc": Console.Write("Customer Create account action"); CustomerCreate customerCreate = GenerateCustomerCreate(idString); accRes = gateway.CustomerCreate(customerCreate); break; case "cu": Console.Write("Customer Update account action"); CustomerUpdate customerUpdate = GenerateCustomerUpdate(idString); accRes = gateway.CustomerUpdate(customerUpdate); break; case "lo": Console.Write("Logout account action"); Logout logout = GenerateLogout(idString); accRes = gateway.Logout(logout); break; case "pw": Console.Write("ResetPasswordRequest account action"); ResetPasswordRequest resetPasswordRequest = GenerateResetPasswordRequest(idString); accRes = gateway.ResetPasswordRequest(resetPasswordRequest); break; case "wl": Console.Write("WishlistChanges account action"); WishlistChanges wishlistChanges = GenerateWishlistChanges(idString); accRes = gateway.WishlistChanges(wishlistChanges); break; case "re": Console.Write("Redeem account action"); Redeem redeem = GenerateRedeem(idString); accRes = gateway.Redeem(redeem); break; case "co": Console.Write("Customer Reach-Out account action"); CustomerReachOut customerReachOut = GenerateCustomerReachOut(idString); accRes = gateway.CustomerReachOut(customerReachOut); break; } if (res != null) { Console.WriteLine("\n\nOrder sent successfully:" + "\nStatus at Riskified: " + res.Status + "\nOrder ID received:" + res.Id + "\nDescription: " + res.Description + "\nWarnings: " + (res.Warnings == null ? "---" : string.Join(" \n", res.Warnings)) + "\n\n"); } if (accRes != null) { Console.WriteLine("\n\nAccount Action sent successfully:" + "\nDecision: " + accRes.Decision); } } catch (OrderFieldBadFormatException e) { // catching Console.WriteLine("Exception thrown on order field validation: " + e.Message); } catch (RiskifiedTransactionException e) { Console.WriteLine("Exception thrown on transaction: " + e.Message); } // ask for next action to perform Console.WriteLine(); if (commandStr.Equals("account")) { Console.WriteLine(accountActionsMenu); } else { Console.WriteLine(menu); } commandStr = Console.ReadLine(); } #endregion }
public static int runAll() { try { string domain = ConfigurationManager.AppSettings["MerchantDomain"]; string authToken = ConfigurationManager.AppSettings["MerchantAuthenticationToken"]; RiskifiedEnvironment riskifiedEnv = (RiskifiedEnvironment)Enum.Parse(typeof(RiskifiedEnvironment), ConfigurationManager.AppSettings["RiskifiedEnvironment"]); OrderNotification res = null; var rand = new Random(); int orderNum = rand.Next(1000, 200000); var order = GenerateOrder(orderNum); OrdersGateway gateway = new OrdersGateway(riskifiedEnv, authToken, domain); var orderCheckout = GenerateOrderCheckout(orderNum.ToString()); orderCheckout.Id = orderNum.ToString(); res = gateway.Checkout(orderCheckout); var orderCheckoutDenied = GenerateOrderCheckoutDenied(orderNum); orderNum++; orderCheckoutDenied.Id = orderNum.ToString(); res = gateway.CheckoutDenied(orderCheckoutDenied); orderNum++; order.Id = orderNum.ToString(); res = gateway.Create(order); order.Id = orderNum.ToString(); orderNum++; res = gateway.Submit(order); res = gateway.Update(order); res = gateway.Cancel( new OrderCancellation( merchantOrderId: order.Id, cancelledAt: DateTime.Now, cancelReason: "Customer cancelled before shipping")); order.Id = orderNum.ToString(); orderNum++; // sending order for creation (if new orderNum) or update (if existing orderNum) res = gateway.Create(order); order.Id = orderNum.ToString(); orderNum++; // sending order for submitting and analysis // it will generate a callback to the notification webhook (if defined) with a decision regarding the order res = gateway.Submit(order); order.Id = order.Id; res = gateway.Update(order); res = gateway.Cancel( new OrderCancellation( merchantOrderId: int.Parse(order.Id), cancelledAt: DateTime.Now, cancelReason: "Customer cancelled before shipping")); res = gateway.PartlyRefund( new OrderPartialRefund( merchantOrderId: int.Parse(order.Id), partialRefunds: new[] { new PartialRefundDetails( refundId: "12345", refundedAt: DateTime.Now, // make sure to initialize DateTime with the correct timezone amount: 5.3, currency: "USD", reason: "Customer partly refunded on shipping fees") })); OrderFulfillment orderFulfillment = GenerateFulfillment(int.Parse(order.Id)); res = gateway.Fulfill(orderFulfillment); OrderDecision orderDecision = GenerateDecision(int.Parse(order.Id)); res = gateway.Decision(orderDecision); } catch (Exception ex) { Console.WriteLine("[failed] " + ex.ToString()); return(-1); } return(0); }
/// <summary> /// Validates the cancellation data /// Sends a cancellation message for a specific order (id should already exist) to Riskified server for status and charge fees update /// </summary> /// <param name="orderCancellation"></param> /// <returns>The order notification result containing status,description and sent order id in case of successful transfer</returns> /// <exception cref="OrderFieldBadFormatException">On bad format of the order (missing fields data or invalid data)</exception> /// <exception cref="RiskifiedTransactionException">On errors with the transaction itself (network errors, bad response data)</exception> public OrderNotification Fulfill(OrderFulfillment orderFulfillment) { return(SendOrder(orderFulfillment, HttpUtils.BuildUrl(_env, "/api/fulfill"))); }
/// <summary> /// Validates the cancellation data /// Sends a cancellation message for a specific order (id should already exist) to Riskified server for status and charge fees update /// </summary> /// <param name="orderCancellation"></param> /// <returns>The order notification result containing status,description and sent order id in case of successful transfer</returns> /// <exception cref="OrderFieldBadFormatException">On bad format of the order (missing fields data or invalid data)</exception> /// <exception cref="RiskifiedTransactionException">On errors with the transaction itself (network errors, bad response data)</exception> public OrderNotification Fulfill(OrderFulfillment orderFulfillment) { return(SendOrder(orderFulfillment, HttpUtils.BuildUrl(_riskifiedBaseWebhookUrl, "/api/fulfill"))); }
public async Task <Order> FulfillOrderRows(OrderFulfillment orderFulfillment) => await _client.PostAsync <Order>("api/orderdelivery", orderFulfillment);
public OrderFulfillment GetOrderFulfillment(AmazonOrder amazonOrder) { var orderFulfillment = new OrderFulfillment() { Item=amazonOrder.AmazonOrderId, ItemElementName = ItemChoiceType2.AmazonOrderID, FulfillmentData = new OrderFulfillmentFulfillmentData() { Item="Other", ShippingMethod = "Standard" }, Item1 = new OrderFulfillmentItemCollection() }; orderFulfillment.FulfillmentDate = amazonOrder.Order.ShippingDate.HasValue ? amazonOrder.Order.ShippingDate.Value.ToUniversalTime().AddMinutes(-15) : DateTime.UtcNow.AddMinutes(-15); //-15 because server times differ foreach (var amazonOrderItem in amazonOrder.Items) { var item = new OrderFulfillmentItem() { Item = amazonOrderItem.AmazonOrderItemId, ItemElementName = ItemChoiceType3.AmazonOrderItemCode, Quantity = decimal.ToInt32(amazonOrderItem.QuantityOrdered).ToString() }; orderFulfillment.Item1.Add(item); } return orderFulfillment; }
public ActionResult Save(OrderViewModel viewModel) { if (!ModelState.IsValid) { return(View("New", viewModel)); } var customerInDb = _context.Customers.SingleOrDefault(c => c.Phone == viewModel.Phone); if (customerInDb == null) { var newCustomer = new Customer { Name = viewModel.Name, Phone = viewModel.Phone }; _context.Customers.Add(newCustomer); _context.SaveChanges(); customerInDb = _context.Customers.SingleOrDefault(c => c.Phone == viewModel.Phone); } var applianceInDb = _context.ServiceAppliances.Find(viewModel.ApplianceId); if (applianceInDb == null) { return(HttpNotFound()); } var serviceTypeInDb = _context.ServiceTypes.Find(viewModel.ServiceTypeId); if (serviceTypeInDb == null) { return(HttpNotFound()); } var order = new Order { CustomerId = customerInDb.Id, OrderDate = DateTime.Now, EmployeeId = int.Parse(Session["employeeId"].ToString()), Description = viewModel.Description, OrderNumber = new Random().Next(1000000, 9999999).ToString(), ServiceApplianceId = applianceInDb.Id }; _context.Orders.Add(order); _context.SaveChanges(); var orderInDb = _context.Orders.SingleOrDefault(o => o.OrderNumber == order.OrderNumber); var orderService = new OrderService { OrderId = orderInDb.Id, ServicetypeId = serviceTypeInDb.Id, TotalServicePrice = serviceTypeInDb.Price }; _context.OrderServices.Add(orderService); _context.SaveChanges(); var orderServiceInDb = _context.OrderServices .SingleOrDefault(s => s.OrderId == orderInDb.Id && s.ServicetypeId == serviceTypeInDb.Id); var orderFulfillment = new OrderFulfillment { OrderServiceId = orderServiceInDb.Id, DateDone = null, DateStart = null, EmployeeId = null }; _context.OrderFulfillments.Add(orderFulfillment); _context.SaveChanges(); return(RedirectToAction("Index")); }
/// <summary> /// Post a fulfillment of an order /// </summary> /// <param name="orderId">Requested order ID, specifies the order to update.</param> /// /// <param name="orderFulfillment">Requested order ID</param> /// <returns>The <see cref="Order"/>.</returns> public virtual async Task <Entities.Order> UpdateFulfillmentAsync(string orderId, OrderFulfillment orderFulfillment) { var req = PrepareRequest($"orders/{orderId}/fulfillments"); HttpContent content = null; if (orderFulfillment != null) { var body = orderFulfillment.ToDictionary(); content = new JsonContent(body); } return(await ExecuteRequestAsync <Entities.Order>(req, HttpMethod.Post, content)); }
public bool ConfirmOrderShimpmentDetails(MarketplaceOrderFulfillment marketplaceOrder, string submittedBy) { if (!marketplaceOrder.OrderItems.Any()) { return(false); } // create configuratin to use US marketplace var config = new MarketplaceWebServiceConfig { ServiceURL = RequestHelper.ServiceUrl }; config.SetUserAgentHeader(_ApplicationName, _Version, "C#"); _amazonClient = new MarketplaceWebServiceClient(_credential.AccessKeyId, _credential.SecretKey, config); try { // create fulfillment item list from the order items var fulfillmentItems = new List <OrderFulfillmentItem>(); foreach (var item in marketplaceOrder.OrderItems) { fulfillmentItems.Add(new OrderFulfillmentItem { Item = item.OrderItemId, Quantity = item.Quantity.ToString() }); } // create the order fulfillment information var fulfillment = new OrderFulfillment { Item = marketplaceOrder.OrderId, FulfillmentDate = marketplaceOrder.FulfillmentDate, FulfillmentData = new OrderFulfillmentFulfillmentData { Item = marketplaceOrder.Carrier.Code, ShippingMethod = marketplaceOrder.ShippingMethod, ShipperTrackingNumber = marketplaceOrder.ShipperTrackingNumber }, Item1 = fulfillmentItems.ToArray() }; // create Amazon envelope object var amazonEnvelope = new AmazonEnvelope { Header = new Header { DocumentVersion = "1.01", MerchantIdentifier = _credential.MerchantId }, MessageType = AmazonEnvelopeMessageType.OrderFulfillment, Message = new AmazonEnvelopeMessage[] { new AmazonEnvelopeMessage { MessageID = "1", Item = fulfillment } } }; // parse the envelope into file var xmlFullName = XmlParser.WriteXmlToFile(amazonEnvelope, "OrderFulfillment"); var submitController = new SubmitFeedController(_amazonClient, _logger, _credential.MarketplaceId, _credential.MerchantId, submittedBy); var streamResponse = submitController.SubmitFeedAndGetResponse(xmlFullName, AmazonFeedType._POST_ORDER_FULFILLMENT_DATA_); parsedResultStreamAndLogReport(streamResponse, AmazonEnvelopeMessageType.OrderFulfillment, submittedBy); _logger.Add(LogEntrySeverity.Information, LogEntryType.AmazonOrdersProvider, string.Format("{0} - Successfully sent confirming order shipment for Order ID \'{1}\'", ChannelName, marketplaceOrder.OrderId)); return(true); } catch (Exception ex) { _logger.Add(LogEntrySeverity.Error, LogEntryType.AmazonOrdersProvider, string.Format("{0} - Error in confirming order shipment for OrderId: {3}. <br/>Error Message: {1} <br/> Access Key: {2}", ChannelName, EisHelper.GetExceptionMessage(ex), _credential.AccessKeyId, marketplaceOrder.OrderId), ex.StackTrace); return(false); } }
/// A single warehouse fulfilling the complete order should always be more optimal than split orders (In my current understanding) private bool TryFulfillCompleteOrder(Order order, WarehouseNetwork warehouseNetwork, out OrderFulfillment orderFulfillment) { foreach (var warehouse in warehouseNetwork) { var canFulfill = true; foreach (var orderItem in order) { if (!warehouse.Inventory.ContainsKey(orderItem.Key) || warehouse.Inventory[orderItem.Key] < orderItem.Value) { canFulfill = false; break; } } if (canFulfill) { orderFulfillment = new OrderFulfillment { { warehouse.Name, order } }; return(true); } } orderFulfillment = null; return(false); }