private PartialShipment PatchShipment(Shipment ocShipment, Misc.Shipment shipment) { PartialShipment newShipment = new PartialShipment(); bool isCreatingNew = false; if (ocShipment == null) { isCreatingNew = true; } else { newShipment.ID = ocShipment?.ID.Trim(); newShipment.xp = ocShipment?.xp; newShipment.FromAddress = ocShipment?.FromAddress; newShipment.ToAddress = ocShipment?.ToAddress; } if (newShipment.xp == null) { newShipment.xp = new ShipmentXp(); } newShipment.BuyerID = shipment.BuyerID; newShipment.Shipper = shipment.Shipper; newShipment.DateShipped = isCreatingNew ? null : shipment.DateShipped; //Must patch to null on new creation due to OC bug newShipment.DateDelivered = shipment.DateDelivered; newShipment.TrackingNumber = shipment.TrackingNumber; newShipment.Cost = Convert.ToDecimal(shipment.Cost); newShipment.Account = shipment.Account; newShipment.FromAddressID = shipment.FromAddressID; newShipment.ToAddressID = shipment.ToAddressID; newShipment.xp.Service = Convert.ToString(shipment.Service); newShipment.xp.Comment = Convert.ToString(shipment.ShipmentComment); return(newShipment); }
private static bool ShouldIgnoreRow(Misc.Shipment value) { string exampleSignifier = "//EXAMPLE//"; //Ignore if the row is empty, or if it's the example row. if (value == null) { return(false); } if (value.OrderID?.ToUpper() == exampleSignifier) { return(true); } PropertyInfo[] props = typeof(Misc.Shipment).GetProperties(); foreach (PropertyInfo prop in props) { if (prop.GetValue(value) != null) { return(false); } } return(true); }
private BatchProcessFailure CreateBatchProcessFailureItem(Misc.Shipment shipment, OrderCloudException ex) { BatchProcessFailure failure = new BatchProcessFailure(); string errorMessage; try { errorMessage = $"{ex.Message}: {((dynamic)ex?.Errors[0]?.Data).ToList()?[0]}"; } catch { errorMessage = $"{ex.Message}"; } if (errorMessage == null) { failure.Error = "Something went wrong"; } else { failure.Error = errorMessage; } failure.Shipment = shipment; return(failure); }
private void ValidateShipmentAmount(Misc.Shipment shipment, LineItem lineItem, Order ocOrder) { if (shipment == null || lineItem == null) { return; } int newAmountShipped = Convert.ToInt32(shipment.QuantityShipped) + lineItem.QuantityShipped; if (newAmountShipped > lineItem.Quantity) { throw new Exception($"Unable to ship {shipment.QuantityShipped} item(s). {lineItem.QuantityShipped} out of {lineItem.Quantity} items are already shipped. LineItemID: {lineItem.ID}"); } }
private async Task <Order> GetOutgoingOrder(Misc.Shipment shipment) { if (shipment == null || shipment.OrderID == null) { throw new Exception("No OrderID provided for shipment"); } try { return(await _oc.Orders.GetAsync(OrderDirection.Outgoing, shipment.OrderID)); } catch (Exception ex) { throw new Exception($"Unable to find Order for OrderID: {shipment.OrderID}", ex.InnerException); } }
private async Task <LineItem> GetOutgoingLineItem(Misc.Shipment shipment) { if (shipment == null || shipment.LineItemID == null) { throw new Exception("No LineItemID provided for shipment"); } try { return(await _oc.LineItems.GetAsync(OrderDirection.Outgoing, shipment.OrderID, shipment.LineItemID)); } catch (Exception ex) { throw new Exception($"Unable to find LineItem for LineItemID: {shipment.LineItemID}", ex.InnerException); } }
private async Task <Shipment> GetShipmentByTrackingNumber(Misc.Shipment shipment, string accessToken) { Shipment shipmentResponse = null; //if dictionary already contains shipment, return that shipment if (shipment != null && _shipmentByTrackingNumber.ContainsKey(shipment.TrackingNumber)) { return(_shipmentByTrackingNumber[shipment.TrackingNumber]); } if (shipment?.ShipmentID != null) { //get shipment if shipmentId is provided try { shipmentResponse = await _oc.Shipments.GetAsync(shipment.ShipmentID, accessToken); } catch (Exception ex) { throw new Exception($"ShipmentID: {shipment.ShipmentID} could not be found. If you are not patching an existing shipment, this field must be blank so that the system can generate a Shipment ID for you. Error Detail: {ex.Message}"); } if (shipmentResponse != null) { //add shipment to dictionary if it's found _shipmentByTrackingNumber.Add(shipmentResponse.TrackingNumber, shipmentResponse); } } else if (shipment?.ShipmentID == null) { PartialShipment newShipment = PatchShipment(null, shipment); //Create shipment for tracking number provided if shipmentId wasn't included shipmentResponse = await _oc.Shipments.CreateAsync(newShipment, accessToken); if (shipmentResponse != null) { _shipmentByTrackingNumber.Add(shipmentResponse.TrackingNumber, shipmentResponse); } } return(shipmentResponse); }
private async Task <LineItem> PatchPartialLineItemComment(Misc.Shipment shipment, string newShipmentId) { PartialLineItem partialLineItem; Dictionary <string, object> commentDictonary = new Dictionary <string, object>(); //Add new comment if (shipment?.ShipmentLineItemComment == null || shipment?.ShipmentLineItemComment == "") { return(null); } commentDictonary.Add(newShipmentId, shipment?.ShipmentLineItemComment); partialLineItem = new PartialLineItem() { xp = new { Comments = commentDictonary } }; return(await _oc.LineItems.PatchAsync(OrderDirection.Outgoing, shipment.OrderID, shipment.LineItemID, partialLineItem)); }
private async Task <bool> ProcessShipment(Misc.Shipment shipment, BatchProcessResult result, VerifiedUserContext userContext) { PartialShipment newShipment = null; Shipment ocShipment; try { if (shipment == null) { throw new Exception("Shipment cannot be null"); } Order ocOrder = await GetOutgoingOrder(shipment); LineItem lineItem = await GetOutgoingLineItem(shipment); //Don't continue if attempting to ship more items than what's in the order. ValidateShipmentAmount(shipment, lineItem, ocOrder); ShipmentItem newShipmentItem = new ShipmentItem() { OrderID = shipment.OrderID, LineItemID = lineItem.ID, QuantityShipped = Convert.ToInt32(shipment.QuantityShipped), UnitPrice = Convert.ToDecimal(shipment.Cost) }; ocShipment = await GetShipmentByTrackingNumber(shipment, userContext?.AccessToken); //If a user included a ShipmentID in the spreadsheet, find that shipment and patch it with the information on that row if (ocShipment != null) { newShipment = PatchShipment(ocShipment, shipment); } if (newShipment != null) { Shipment processedShipment = await _oc.Shipments.PatchAsync(newShipment.ID, newShipment, userContext?.AccessToken); //Before updating shipment item, must post the shipment line item comment to the order line item due to OC bug. await PatchPartialLineItemComment(shipment, newShipment.ID); await PatchLineItemStatus(shipment.OrderID, newShipmentItem, userContext); //POST a shipment item, passing it a Shipment ID parameter, and a request body of Order ID, Line Item ID, and Quantity Shipped await _oc.Shipments.SaveItemAsync(newShipment.ID, newShipmentItem, accessToken : userContext?.AccessToken); //Re-patch the shipment adding the date shipped now due to oc bug var repatchedShipment = PatchShipment(ocShipment, shipment); await _oc.Shipments.PatchAsync(newShipment.ID, repatchedShipment); result.SuccessfulList.Add(processedShipment); } if (lineItem?.ID == null) { //Before updating shipment item, must post the shipment line item comment to the order line item due to OC bug. await PatchPartialLineItemComment(shipment, newShipment.ID); //Create new lineItem await _oc.Shipments.SaveItemAsync(shipment.ShipmentID, newShipmentItem); } return(true); } catch (OrderCloudException ex) { result.ProcessFailureList.Add(CreateBatchProcessFailureItem(shipment, ex)); return(false); } catch (Exception ex) { result.ProcessFailureList.Add(new BatchProcessFailure() { Error = ex.Message, Shipment = shipment }); return(false); } }