private List <ShipmentAction> BuildShipmentInvoiceActions(ShopifyOrder orderRecord) { var output = new List <ShipmentAction>(); foreach (var soShipment in orderRecord.SoShipments()) { var action = new ShipmentAction(); action.ShipmentNbr = soShipment.AcumaticaShipmentNbr; action.ShipmentHref = _acumaticaUrlService.AcumaticaShipmentUrl(soShipment.AcumaticaShipmentNbr); action.InvoiceNbr = soShipment.AcumaticaInvoiceNbr; action.InvoiceAmount = soShipment.AcumaticaInvoiceAmount.Value; action.InvoiceTax = soShipment.AcumaticaInvoiceTax.Value; if (soShipment.ShopifyFulfillment == null) { action.ActionCode = ActionCode.CreateInShopify; } else { action.ActionCode = ActionCode.None; action.ShopifyFulfillmentId = soShipment.ShopifyFulfillment.ShopifyFulfillmentId; } output.Add(action); } return(output); }
public void ValidatePayment(ShopifyOrder order, PaymentAction action) { action.Validation = new ValidationResult(); var transaction = order .ShopifyTransactions.FirstOrDefault(x => x.ShopifyTransactionId == action.ShopifyTransactionId); //if (transaction == null) //{ // return; //} if (action.ActionCode == ActionCode.CreateInAcumatica) { action.Validation = ReadyToCreatePayment(transaction); return; } if (action.ActionCode == ActionCode.UpdateInAcumatica) { action.Validation = ReadyToUpdatePayment(transaction); return; } if (action.ActionCode == ActionCode.ReleaseInAcumatica) { action.Validation = ReadyToRelease(transaction); return; } }
private OrderAction BuildOrderPendingAction(ShopifyOrder record) { var output = new OrderAction(); var order = _shopifyJsonService.RetrieveOrder(record.ShopifyOrderId); output.ShopifyOrderId = record.ShopifyOrderId; output.ShopifyOrderHref = _shopifyUrlService.ShopifyOrderUrl(record.ShopifyOrderId); output.ShopifyOrderName = order.name; output.Validation = new ValidationResult(); output.ActionCode = ActionCode.None; if (!record.ExistsInAcumatica()) { output.ActionCode = order.IsCancelled || order.AreAllLineItemsRefunded ? ActionCode.CreateBlankSyncRecord : ActionCode.CreateInAcumatica; } else // Exists in Acumatica { output.AcumaticaSalesOrderNbr = record.AcumaticaSalesOrder.AcumaticaOrderNbr; output.AcumaticaSalesOrderHref = _acumaticaUrlService.AcumaticaSalesOrderUrl( SalesOrderType.SO, record.AcumaticaSalesOrder.AcumaticaOrderNbr); if (record.NeedsOrderPut || record.ShopifyTotalQuantity != record.SyncedSalesOrder().AcumaticaQtyTotal) { output.ActionCode = ActionCode.UpdateInAcumatica; } } return(output); }
public static bool IsPaid(this ShopifyOrder order) { return (order.ShopifyFinancialStatus == FinancialStatus.Paid || order.ShopifyFinancialStatus == FinancialStatus.PartiallyRefunded || order.ShopifyFinancialStatus == FinancialStatus.Refunded); }
private void PullTransactionsFromShopify(ShopifyOrder orderRecord) { var transactionsJson = _orderApi.RetrieveTransactions(orderRecord.ShopifyOrderId); var transactions = transactionsJson.DeserializeFromJson <TransactionList>(); var order = _shopifyJsonService.RetrieveOrder(orderRecord.ShopifyOrderId); foreach (var transaction in transactions.transactions) { var transactionRecord = _orderRepository.RetrieveTransaction(transaction.id); if (transactionRecord != null) { transactionRecord.LastUpdated = DateTime.UtcNow; _orderRepository.SaveChanges(); continue; } using (var dbTransaction = _orderRepository.BeginTransaction()) { var record = new ShopifyTransaction(); if (transaction.kind == TransactionKind.Refund) { record.IsSyncableToPayment = true; var refund = order.RefundByTransaction(transaction.id); if (refund != null) { record.ShopifyRefundId = refund.id; record.IsPureCancel = refund.IsPureCancel; } } if (transaction.kind == TransactionKind.Capture || transaction.kind == TransactionKind.Sale) { record.IsSyncableToPayment = true; } record.ShopifyOrderId = transaction.order_id; record.ShopifyTransactionId = transaction.id; record.ShopifyStatus = transaction.status; record.ShopifyKind = transaction.kind; record.ShopifyGateway = transaction.gateway; record.ShopifyAmount = transaction.amount; record.ShopifyOrderMonsterId = orderRecord.MonsterId; record.DateCreated = DateTime.UtcNow; record.LastUpdated = DateTime.UtcNow; _logService.Log(LogBuilder.DetectedNewShopifyTransaction(record)); _orderRepository.InsertTransaction(record); _shopifyJsonService.Upsert( ShopifyJsonType.Transaction, transaction.id, transaction.SerializeToJson()); dbTransaction.Commit(); } } orderRecord.NeedsTransactionGet = false; _orderRepository.SaveChanges(); }
public void Validate(ShopifyOrder orderRecord, ShipmentAction action) { var soShipment = orderRecord.SoShipments() .First(x => x.AcumaticaShipmentNbr == action.ShipmentNbr && x.AcumaticaInvoiceNbr == action.InvoiceNbr); action.Validation = Validate(soShipment); }
private List <AdjustmentAction> BuildRefundAdjustmentActions(ShopifyOrder orderRecord) { var output = new List <AdjustmentAction>(); foreach (var creditAdj in orderRecord.CreditAdustmentRefunds()) { var action = new AdjustmentAction(); action.ActionCode = ActionCode.None; action.ShopifyOrderId = orderRecord.ShopifyOrderId; action.ShopifyRefundId = creditAdj.ShopifyRefundId; action.MemoType = AdjustmentMemoType.CreditMemo; action.MemoAmount = creditAdj.CreditAdjustment; if (creditAdj.AcumaticaMemo == null) { action.ActionCode = ActionCode.CreateInAcumatica; } if (creditAdj.AcumaticaMemo != null) { action.AcumaticaRefNbr = creditAdj.AcumaticaMemo.AcumaticaRefNbr; action.AcumaticaDocType = creditAdj.AcumaticaMemo.AcumaticaDocType; action.AcumaticaHref = _acumaticaUrlService.AcumaticaInvoiceUrl( SalesInvoiceType.Credit_Memo, creditAdj.AcumaticaMemo.AcumaticaRefNbr); } if (creditAdj.AcumaticaMemo != null && !creditAdj.AcumaticaMemo.NeedManualApply && creditAdj.AcumaticaMemo.NeedRelease) { action.ActionCode = ActionCode.ReleaseInAcumatica; } if (creditAdj.AcumaticaMemo != null && creditAdj.AcumaticaMemo.NeedManualApply) { action.ActionCode = ActionCode.NeedManualApply; } output.Add(action); } foreach (var debitAdj in orderRecord.DebitAdustmentRefunds()) { var action = new AdjustmentAction(); action.ActionCode = ActionCode.CreateInAcumatica; action.MemoType = AdjustmentMemoType.DebitMemo; action.MemoAmount = debitAdj.DebitAdjustment; output.Add(action); } return(output); }
private void UpsertOrderAndCustomer(Order order) { var monsterCustomerRecord = _shopifyCustomerPull.UpsertCustomer(order.customer); using (var transaction = _orderRepository.BeginTransaction()) { var existingOrder = _orderRepository.RetrieveOrder(order.id); if (existingOrder == null) { var newOrder = new ShopifyOrder(); newOrder.ShopifyOrderId = order.id; newOrder.ShopifyOrderNumber = order.name; newOrder.ShopifyTotalPrice = order.total_price; newOrder.ShopifyFinancialStatus = order.financial_status; newOrder.ShopifyFulfillmentStatus = order.fulfillment_status; newOrder.ShopifyIsCancelled = order.IsCancelled; newOrder.ShopifyAreAllItemsRefunded = order.AreAllLineItemsRefunded; newOrder.ShopifyTotalQuantity = order.NetOrderedQuantity; newOrder.NeedsOrderPut = false; newOrder.NeedsTransactionGet = true; newOrder.ErrorCount = 0; newOrder.Ignore = false; newOrder.CustomerMonsterId = monsterCustomerRecord.MonsterId; newOrder.DateCreated = DateTime.UtcNow; newOrder.LastUpdated = DateTime.UtcNow; _executionLogService.Log(LogBuilder.DetectedNewShopifyOrder(newOrder)); _orderRepository.InsertOrder(newOrder); } else { existingOrder.ShopifyTotalPrice = order.total_price; existingOrder.ShopifyFinancialStatus = order.financial_status; existingOrder.ShopifyFulfillmentStatus = order.fulfillment_status; existingOrder.ShopifyIsCancelled = order.IsCancelled; existingOrder.ShopifyAreAllItemsRefunded = order.AreAllLineItemsRefunded; existingOrder.ShopifyTotalQuantity = order.NetOrderedQuantity; if (existingOrder.StatusChangeDetected(order)) { existingOrder.NeedsOrderPut = true; } existingOrder.NeedsTransactionGet = true; existingOrder.LastUpdated = DateTime.UtcNow; _executionLogService.Log(LogBuilder.DetectedUpdateShopifyOrder(existingOrder)); _orderRepository.SaveChanges(); } _shopifyJsonService.Upsert(ShopifyJsonType.Order, order.id, order.SerializeToJson()); transaction.Commit(); } }
public void ParseShopifyEmail() { var sut = new ShopifyOrder(shopifyEmail); Assert.Equal("1130", sut.OrderID); Assert.Equal(114.05, sut.OrderTotal); Assert.Equal("https://liftergifts.myshopify.com/admin/orders/1853957537907", sut.OrderUrl); Assert.Equal(2.04, sut.ShippingCharge); Assert.Equal(3, sut.Transactions.Count); }
// *** IMPORTANT => Shopify is the single source of truth (SSoT) for Payment Transactions // ... whereas Acumatica is the SSoT for goods issued to Customer via Shipments // public static decimal TheoreticalPaymentRemaining(this ShopifyOrder order) { // UPDATE => We'll play conservatively for system stability and clarity. // ... This is computed figure is inclusive of Cancels, Returns and InStock // ... aka indeterminate. If a Return is received before the Order is Complete, // ... the user will bear the responsibility of manually applying Payments and Refunds. // var output = order.ShopifyNetPayment() - order.AcumaticaInvoiceTotal(); return(output <= 0.00m ? 0.00m : output); }
private List <PaymentAction> BuildRefundPaymentActions(ShopifyOrder orderRecord) { var output = new List <PaymentAction>(); foreach (var refundTrans in orderRecord.RefundTransactions()) { var refundAction = new PaymentAction(); refundAction.ShopifyTransactionId = refundTrans.ShopifyTransactionId; refundAction.TransDesc = $"Shopify Refund ({refundTrans.ShopifyTransactionId})"; refundAction.PaymentGateway = refundTrans.ShopifyGateway; refundAction.Amount = refundTrans.ShopifyAmount; var refund = orderRecord.Refund(refundTrans.ShopifyRefundId.Value); refundAction.HasShipping = refund.HasShipping(); refundAction.Shipping = refund.Shipping; refundAction.ShippingTax = refund.ShippingTax; refundAction.ActionCode = ActionCode.None; if (!refundTrans.ExistsInAcumatica()) { refundAction.ActionCode = ActionCode.CreateInAcumatica; } if (refundTrans.ExistsInAcumatica()) { refundAction.AcumaticaPaymentRef = refundTrans.AcumaticaPayment.AcumaticaRefNbr; refundAction.AcumaticaHref = _acumaticaUrlService.AcumaticaPaymentUrl( PaymentType.CustomerRefund, refundTrans.AcumaticaPayment.AcumaticaRefNbr); } if (refundTrans.ExistsInAcumatica() && !refundTrans.AcumaticaPayment.NeedManualApply && !refundTrans.IsReleased()) { refundAction.ActionCode = ActionCode.ReleaseInAcumatica; } if (refundTrans.ExistsInAcumatica() && refundTrans.AcumaticaPayment.NeedManualApply) { refundAction.ActionCode = ActionCode.NeedManualApply; } output.Add(refundAction); } return(output); }
private OrderAnalyzerResultsRow MakeOrderAnalyzerResults(ShopifyOrder order) { var output = new OrderAnalyzerResultsRow(); output.ShopifyOrderId = order.ShopifyOrderId; output.ShopifyOrderNbr = order.ShopifyOrderNumber.ToString(); output.ShopifyOrderHref = _shopifyUrlService.ShopifyOrderUrl(order.ShopifyOrderId); // TODO - need to add a flag that indicates this Order has been archived // var shopifyOrder = _shopifyJsonService.RetrieveOrder(order.ShopifyOrderId); output.ShopifyOrderTotal = shopifyOrder.NetOrderTotal; output.ShopifyNetPayment = order.ShopifyNetPayment(); output.ShopifyFinancialStatus = order.ShopifyFinancialStatus; output.ShopifyFulfillmentStatus = order.ShopifyFulfillmentStatus; output.ShopifyIsCancelled = order.ShopifyIsCancelled; output.ShopifyAreAllItemsRefunded = order.ShopifyAreAllItemsRefunded; var acumaticaSalesOrder = order.AcumaticaSalesOrder; if (acumaticaSalesOrder != null && acumaticaSalesOrder.AcumaticaOrderNbr != AcumaticaSyncConstants.BlankRefNbr) { output.AcumaticaSalesOrderNbr = acumaticaSalesOrder.AcumaticaOrderNbr; output.AcumaticaSalesOrderHref = _acumaticaUrlService .AcumaticaSalesOrderUrl(SalesOrderType.SO, acumaticaSalesOrder.AcumaticaOrderNbr); output.AcumaticaStatus = acumaticaSalesOrder.AcumaticaStatus; output.AcumaticaOrderTotal = acumaticaSalesOrder.AcumaticaOrderTotal; } if (order.IsPaymentSynced()) { output.AcumaticaOrderPayment = order.AcumaticaPaymentAmount(); output.AcumaticaNetPayment = order.AcumaticaNetPaymentAmount(); } else { output.AcumaticaOrderPayment = 0.00m; output.AcumaticaNetPayment = 0.00m; } output.AcumaticaInvoiceTotal = order.AcumaticaInvoiceTotal(); output.Ignore = order.Ignore; output.HasError = order.ExceedsErrorLimit(); output.HasPendingActions = _pendingActionService.Create(order, false).HasPendingActions; return(output); }
// Invoke the Acumatica Customer Sync // public AcumaticaCustomer PushNonExistentCustomer(ShopifyOrder shopifyOrder) { var customer = _syncOrderRepository .RetrieveCustomer(shopifyOrder.ShopifyCustomer.ShopifyCustomerId); if (customer.HasMatch()) { return(customer.Match()); } else { return(_acumaticaCustomerSync.PushCustomer(customer)); } }
private PaymentAction BuildPaymentActions(ShopifyOrder orderRecord) { var paymentAction = new PaymentAction(); paymentAction.ActionCode = ActionCode.None; paymentAction.Validation = new ValidationResult(); if (orderRecord.HasPayment()) { var payment = orderRecord.PaymentTransaction(); paymentAction.ShopifyTransactionId = payment.ShopifyTransactionId; paymentAction.TransDesc = $"Shopify Payment ({payment.ShopifyTransactionId})"; paymentAction.PaymentGateway = payment.ShopifyGateway; paymentAction.Amount = payment.ShopifyAmount; paymentAction.ActionCode = ActionCode.None; if (!payment.ExistsInAcumatica()) { paymentAction.ActionCode = ActionCode.CreateInAcumatica; } if (payment.ExistsInAcumatica()) { paymentAction.AcumaticaPaymentRef = payment.AcumaticaPayment.AcumaticaRefNbr; paymentAction.AcumaticaHref = _acumaticaUrlService.AcumaticaPaymentUrl( PaymentType.Payment, payment.AcumaticaPayment.AcumaticaRefNbr); if (orderRecord.OriginalPaymentNeedsUpdateForRefund()) { paymentAction.ActionCode = ActionCode.UpdateInAcumatica; } else if (payment.ExistsInAcumatica() && payment.AcumaticaPayment.NeedRelease) { paymentAction.ActionCode = ActionCode.ReleaseInAcumatica; } } } else { paymentAction.ShopifyTransactionId = -1; paymentAction.TransDesc = $"Shopify Payment not found yet"; paymentAction.PaymentGateway = "No Gateway"; paymentAction.Amount = 0.00m; paymentAction.ActionCode = ActionCode.None; } return(paymentAction); }
private void UpsertOrderFulfillment(ShopifyOrder orderRecord, Fulfillment fulfillment) { var fulfillmentRecord = orderRecord .ShopifyFulfillments .FirstOrDefault(x => x.ShopifyFulfillmentId == fulfillment.id); if (fulfillmentRecord != null) { // Existing Fulfillment Record // fulfillmentRecord.ShopifyStatus = fulfillment.status; fulfillmentRecord.LastUpdated = DateTime.UtcNow; _orderRepository.SaveChanges(); return; } var matchedRecord = orderRecord .ShopifyFulfillments .FirstOrDefault(x => x.ShopifyTrackingNumber == fulfillment.tracking_number); if (matchedRecord != null) { // Matched via Tracking Number in Shopify // _executionLogService.Log( LogBuilder.FillingUnknownShopifyFulfillmentRefByTracking(matchedRecord)); matchedRecord.ShopifyFulfillmentId = fulfillment.id; matchedRecord.LastUpdated = DateTime.UtcNow; _orderRepository.SaveChanges(); } else { // Creating new Fulfillment Record // var newRecord = new ShopifyFulfillment(); newRecord.ShopifyOrderMonsterId = orderRecord.MonsterId; newRecord.ShopifyFulfillmentId = fulfillment.id; newRecord.ShopifyOrderId = orderRecord.ShopifyOrderId; newRecord.ShopifyStatus = fulfillment.status; newRecord.DateCreated = DateTime.UtcNow; newRecord.LastUpdated = DateTime.UtcNow; _orderRepository.InsertFulfillment(newRecord); } }
// Create new Sales Order // private SalesOrder BuildNewSalesOrder(ShopifyOrder shopifyOrderRecord, AcumaticaCustomer customer) { // Get the Shopify Order // var shopifyOrder = _shopifyJsonService.RetrieveOrder(shopifyOrderRecord.ShopifyOrderId); // Header // var salesOrder = BuildNewSalesOrderHeader(shopifyOrderRecord, shopifyOrder, customer); // Detail // salesOrder.Details = BuildSalesOrderDetail(shopifyOrder); // Billing Address & Contact // salesOrder.BillToContactOverride = true.ToValue(); salesOrder.BillToContact = BuildContact(shopifyOrder, shopifyOrder.billing_address); salesOrder.BillToAddressOverride = true.ToValue(); salesOrder.BillToAddress = BuildAddress(shopifyOrder.billing_address); // Shipping Address & Contact // salesOrder.ShipToContactOverride = true.ToValue(); salesOrder.ShipToContact = BuildContact(shopifyOrder, shopifyOrder.shipping_address); salesOrder.ShipToAddressOverride = true.ToValue(); salesOrder.ShipToAddress = BuildAddress(shopifyOrder.shipping_address); if (!shopifyOrder.MaybeShippingRateTitle.IsNullOrEmpty()) { var carrierToShipVia = _settingsRepository.RetrieveRateToShipVia(shopifyOrder.MaybeShippingRateTitle); if (carrierToShipVia != null) { salesOrder.ShipVia = carrierToShipVia.AcumaticaShipViaId.ToValue(); } } // Payment optimization *** FAIL - PENDING ACUMATICA SUPPORT *** // //var payment = _acumaticaOrderPaymentPut.BuildPaymentForCreate(shopifyOrderRecord.PaymentTransaction()); //salesOrder.Payments = new List<object> { payment }; salesOrder.PaymentRef = shopifyOrderRecord.PaymentTransaction().ShopifyTransactionId.ToString().ToValue(); return(salesOrder); }
private void InjectTotalsFromAcumatica(ShopifyOrder shopifyOrderRecord, OrderAnalysisTotals output) { SalesOrder acumaticaOrder = null; var acumaticaOrderNbr = shopifyOrderRecord.AcumaticaSalesOrder.AcumaticaOrderNbr; _acumaticaHttpContext.SessionRun(() => { var json = _salesOrderClient .RetrieveSalesOrder(acumaticaOrderNbr, SalesOrderType.SO, Expand.Totals); acumaticaOrder = json.ToSalesOrderObj(); }); output.AcumaticaOrderLineTotal = (decimal)acumaticaOrder.Totals.LineTotalAmount.value; output.AcumaticaOrderFreight = (decimal)acumaticaOrder.Totals.Freight.value; output.AcumaticaTaxTotal = (decimal)acumaticaOrder.Totals.TaxTotal.value; output.AcumaticaOrderTotal = (decimal)acumaticaOrder.OrderTotal.value; }
public static FinAnalyzer ToFinAnalyzer(this ShopifyOrder orderRecord, Order shopifyOrder) { var FinAnalyzer = new FinAnalyzer(); FinAnalyzer.ExternalRefNbr = shopifyOrder.id.ToString(); FinAnalyzer.Freight.Price = shopifyOrder.ShippingTotal; FinAnalyzer.Freight.TaxableAmount = shopifyOrder.IsShippingTaxable ? shopifyOrder.ShippingTotal : 0m; FinAnalyzer.Freight.TaxLines = shopifyOrder.shipping_lines.ToFinAnalyzerTaxLines(); FinAnalyzer.Freight.TaxAmount = shopifyOrder.ShippingTax; foreach (var line_item in shopifyOrder.line_items) { var xferLineItem = new FinAnalyzerLineItem(); xferLineItem.ExternalRefNbr = line_item.id.ToString(); xferLineItem.InventoryID = line_item.sku; xferLineItem.Quantity = line_item.quantity; xferLineItem.UnitPrice = line_item.UnitPriceAfterDiscount; xferLineItem.TaxableAmount = line_item.TaxableAmount; xferLineItem.TaxAmount = line_item.Tax; xferLineItem.TaxLines = line_item.tax_lines.ToFinAnalyzerTaxLines(); FinAnalyzer.LineItems.Add(xferLineItem); } foreach (var refund in shopifyOrder.refunds) { var xferRefund = new FinAnalyzerRefund(); if (refund.transactions.Any()) { xferRefund.ExternalRefNbr = refund.transactions.First().id.ToString(); } xferRefund.TaxableAmount = refund.TotalTaxableLineAndShippingAmount; xferRefund.LineItemTotal = refund.LineItemTotal; xferRefund.LineItemsTax = refund.TotalLineItemTax; xferRefund.Freight = refund.TotalShippingAdjustment; xferRefund.FreightTax = refund.TotalShippingAdjustmentTax; xferRefund.Credit = refund.CreditMemoTotal; xferRefund.Debit = refund.DebitMemoTotal; xferRefund.RefundAmount = refund.PaymentTotal; FinAnalyzer.Refunds.Add(xferRefund); } FinAnalyzer.Payment = orderRecord.ShopifyPaymentAmount(); return(FinAnalyzer); }
public void ValidateRefundPayment(ShopifyOrder order, PaymentAction action) { var transaction = order .ShopifyTransactions .First(x => x.ShopifyTransactionId == action.ShopifyTransactionId); action.Validation = new ValidationResult(); if (action.ActionCode == ActionCode.CreateInAcumatica) { action.Validation = ReadyToCreateRefundPayment(transaction); } if (action.ActionCode == ActionCode.ReleaseInAcumatica) { action.Validation = ReadyToReleaseRefundPayment(transaction); } }
// Update existing Sales Order // public SalesOrderUpdate BuildSalesOrderUpdate(ShopifyOrder shopifyOrderRecord) { var shopifyOrder = _shopifyJsonService.RetrieveOrder(shopifyOrderRecord.ShopifyOrderId); var salesOrderRecord = shopifyOrderRecord.SyncedSalesOrder(); var existingSalesOrder = _salesOrderClient .RetrieveSalesOrder( salesOrderRecord.AcumaticaOrderNbr, SalesOrderType.SO, SalesOrderExpand.Details) .ToSalesOrderObj(); var salesOrderUpdate = new SalesOrderUpdate(); salesOrderUpdate.OrderType = existingSalesOrder.OrderType.Copy(); salesOrderUpdate.OrderNbr = existingSalesOrder.OrderNbr.Copy(); salesOrderUpdate.Hold = false.ToValue(); // Update the Shipping Cost // salesOrderUpdate.FreightPrice = ((double)shopifyOrder.NetShippingPrice).ToValue(); salesOrderUpdate.OverrideFreightPrice = true.ToValue(); foreach (var line_item in shopifyOrder.line_items) { var variant = _syncInventoryRepository.RetrieveVariant(line_item.variant_id.Value, line_item.sku); var stockItemId = variant.MatchedStockItem().ItemId; var salesOrderDetail = existingSalesOrder.DetailByInventoryId(stockItemId); var detail = new SalesOrderUpdateDetail(); detail.id = salesOrderDetail.id; detail.OrderQty = ((double)line_item.NetOrderedQuantity).ToValue(); detail.InventoryID = variant.MatchedStockItem().ItemId.ToValue(); salesOrderUpdate.Details.Add(detail); } var taxTransfer = shopifyOrder.ToSerializedAndZippedTaxTransfer(); salesOrderUpdate.custom = new SalesOrderUsrTaxSnapshot(taxTransfer); return(salesOrderUpdate); }
/// <summary> /// A method that will throw an exception which looks like { errors: { "order" : [ "some error message" ] } } /// </summary> /// <returns></returns> public async Task ThrowArrayException() { var request = RequestEngine.CreateRequest("orders.json", Method.POST); //Creating an order with tax lines on both line items and the order will return an error var order = new ShopifyOrder() { CreatedAt = DateTime.UtcNow, LineItems = new List <ShopifyLineItem>() { new ShopifyLineItem() { Title = "Click Keyboard", Price = 99.99, Grams = 600, Quantity = 1, TaxLines = new List <ShopifyTaxLine>() { new ShopifyTaxLine() { Price = 1.0, Rate = 0.01, Title = "Keyboard tax" } } } }, TaxLines = new List <ShopifyTaxLine>() { new ShopifyTaxLine() { Price = 6.0, Rate = 0.06, Title = "State tax" } } }; request.AddJsonBody(new { order }); //Make request await RequestEngine.ExecuteRequestAsync <ShopifyOrder>(_RestClient, request); }
public RootAction Create(ShopifyOrder orderRecord, bool validate = true) { var output = new RootAction(); output.OrderAction = BuildOrderPendingAction(orderRecord); output.PaymentAction = BuildPaymentActions(orderRecord); output.RefundPaymentActions = BuildRefundPaymentActions(orderRecord); output.AdjustmentMemoActions = BuildRefundAdjustmentActions(orderRecord); output.ShipmentInvoiceActions = BuildShipmentInvoiceActions(orderRecord); output.ErrorCount = orderRecord.ErrorCount; output.ExceedsErrorLimit = orderRecord.ExceedsErrorLimit(); output.Ignore = orderRecord.Ignore; if (validate) { _orderValidation.Validate(output.OrderAction); _paymentValidation.ValidatePayment(orderRecord, output.PaymentAction); foreach (var action in output.RefundPaymentActions) { _paymentValidation.ValidateRefundPayment(orderRecord, action); } foreach (var action in output.ShipmentInvoiceActions) { _fulfillmentStatusService.Validate(orderRecord, action); } foreach (var action in output.AdjustmentMemoActions) { _memoValidationService.Validate(output, action); } } return(output); }
public static string LogDescriptor(this ShopifyOrder shopifyOrder) { return($"Shopify Order {shopifyOrder.ShopifyOrderNumber} " + $"({shopifyOrder.ShopifyOrderId})"); }
public async Task <IActionResult> ShopifyInvoiceEndpoint( [FromServices] InvoiceRepository invoiceRepository, [FromServices] InvoiceController invoiceController, [FromServices] IHttpClientFactory httpClientFactory, string storeId, string orderId, decimal amount, bool checkOnly = false) { var invoiceOrderId = $"{ShopifyOrderMarkerHostedService.SHOPIFY_ORDER_ID_PREFIX}{orderId}"; var matchedExistingInvoices = await invoiceRepository.GetInvoices(new InvoiceQuery() { OrderId = new[] { invoiceOrderId }, StoreId = new[] { storeId } }); matchedExistingInvoices = matchedExistingInvoices.Where(entity => entity.GetInternalTags(ShopifyOrderMarkerHostedService.SHOPIFY_ORDER_ID_PREFIX) .Any(s => s == orderId)) .ToArray(); var firstInvoiceStillPending = matchedExistingInvoices.FirstOrDefault(entity => entity.GetInvoiceState().Status == InvoiceStatus.New); if (firstInvoiceStillPending != null) { return(Ok(new { invoiceId = firstInvoiceStillPending.Id, status = firstInvoiceStillPending.Status.ToString().ToLowerInvariant() })); } var firstInvoiceSettled = matchedExistingInvoices.LastOrDefault(entity => new[] { InvoiceStatus.Paid, InvoiceStatus.Complete, InvoiceStatus.Confirmed }.Contains( entity.GetInvoiceState().Status)); var store = await _Repo.FindStore(storeId); var shopify = store?.GetStoreBlob()?.Shopify; ShopifyApiClient client = null; ShopifyOrder order = null; if (shopify?.IntegratedAt.HasValue is true) { client = new ShopifyApiClient(httpClientFactory, shopify.CreateShopifyApiCredentials()); order = await client.GetOrder(orderId); if (string.IsNullOrEmpty(order?.Id)) { return(NotFound()); } } if (firstInvoiceSettled != null) { //if BTCPay was shut down before the tx managed to get registered on shopify, this will fix it on the next UI load in shopify if (client != null && order?.FinancialStatus == "pending" && firstInvoiceSettled.Status != InvoiceStatus.Paid) { await new OrderTransactionRegisterLogic(client).Process(orderId, firstInvoiceSettled.Id, firstInvoiceSettled.Currency, firstInvoiceSettled.Price.ToString(CultureInfo.InvariantCulture), true); order = await client.GetOrder(orderId); } if (order?.FinancialStatus != "pending" && order?.FinancialStatus != "partially_paid") { return(Ok(new { invoiceId = firstInvoiceSettled.Id, status = firstInvoiceSettled.Status.ToString().ToLowerInvariant() })); } } if (checkOnly) { return(Ok()); } if (shopify?.IntegratedAt.HasValue is true) { if (string.IsNullOrEmpty(order?.Id) || !new[] { "pending", "partially_paid" }.Contains(order.FinancialStatus)) { return(NotFound()); } //we create the invoice at due amount provided from order page or full amount if due amount is bigger than order amount var invoice = await invoiceController.CreateInvoiceCoreRaw( new CreateInvoiceRequest() { Amount = amount < order.TotalPrice ? amount : order.TotalPrice, Currency = order.Currency, Metadata = new JObject { ["orderId"] = invoiceOrderId } }, store, Request.GetAbsoluteUri(""), new List <string>() { invoiceOrderId }); return(Ok(new { invoiceId = invoice.Id, status = invoice.Status.ToString().ToLowerInvariant() })); } return(NotFound()); }
public static bool HasUnsyncedFulfillments(this ShopifyOrder order) { return(order.SoShipments().Any(x => x.ShopifyFulfillment == null)); }
/// <summary> /// A method that will throw an exception which looks like { errors: { "order" : [ "some error message" ] } } /// </summary> /// <returns></returns> public async Task ThrowArrayException() { var request = RequestEngine.CreateRequest("orders.json", Method.POST); //Creating an order with tax lines on both line items and the order will return an error var order = new ShopifyOrder() { CreatedAt = DateTime.UtcNow, LineItems = new List<ShopifyLineItem>() { new ShopifyLineItem() { Title = "Click Keyboard", Price = 99.99, Grams = 600, Quantity = 1, TaxLines = new List<ShopifyTaxLine>() { new ShopifyTaxLine() { Price = 1.0, Rate = 0.01, Title = "Keyboard tax" } } } }, TaxLines = new List<ShopifyTaxLine>() { new ShopifyTaxLine() { Price = 6.0, Rate = 0.06, Title = "State tax" } } }; request.AddJsonBody(new { order }); //Make request await RequestEngine.ExecuteRequestAsync<ShopifyOrder>(_RestClient, request); }
public static bool DoesNotExceedErrorLimit(this ShopifyOrder order) { return(!order.ExceedsErrorLimit()); }
public static bool ExceedsErrorLimit(this ShopifyOrder order) { return(order.ErrorCount >= SystemConsts.ErrorThreshold); }
public static decimal AcumaticaDebitMemosTotal(this ShopifyOrder order) { return(order.ShopifyRefunds .Where(x => x.DebitAdjustment > 0 && x.AcumaticaMemo != null) .Sum(x => x.AcumaticaMemo.AcumaticaAmount)); }
public static string AcumaticaCustomerId(this ShopifyOrder order) { return(order.ExistsInAcumatica() ? order.SyncedSalesOrder().AcumaticaCustomer.AcumaticaCustomerId : null); }
public static bool HasInvoicedShipments(this ShopifyOrder order) { return(order.SoShipments().Any()); }