/// <summary> /// Populates the sales transaction. /// </summary> /// <param name="context">The context.</param> /// <param name="cartId">The cart id.</param> /// <param name="email">The email.</param> /// <param name="salesTransaction">The sales transaction.</param> private static void PopulateSalesTransaction(RequestContext context, string cartId, string email, out SalesTransaction salesTransaction) { salesTransaction = CartWorkflowHelper.LoadSalesTransaction(context, cartId); if (salesTransaction == null) { throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotFound, cartId); } salesTransaction.ReceiptEmail = email; salesTransaction.TransactionType = SalesTransactionType.PendingSalesOrder; if (string.IsNullOrEmpty(salesTransaction.ReceiptEmail)) { throw new DataValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_RequiredValueNotFound, "Receipt email must be provided."); } OrderWorkflowHelper.FillTransactionWithContextData(context, salesTransaction); }
/// <summary> /// Creates a sales transaction given the cart. /// </summary> /// <param name="request">The request.</param> /// <returns>The response.</returns> protected override SubmitSalesTransactionResponse Process(SubmitSalesTransactionRequest request) { ThrowIf.Null(request, "request"); ThrowIf.Null(request.CartId, "request.CartId"); // Get the Sales Transaction SalesTransaction salesTransaction = CartWorkflowHelper.LoadSalesTransaction(this.Context, request.CartId); if (salesTransaction == null) { throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotFound, request.CartId); } if (salesTransaction.IsSuspended) { throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotActive, request.CartId); } if (!(salesTransaction.TerminalId ?? string.Empty).Equals(this.Context.GetTerminal().TerminalId ?? string.Empty, StringComparison.OrdinalIgnoreCase)) { // If the terminal id of the cart is not same as the context then it means that the cart is active on another terminal. throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_LoadingActiveCartFromAnotherTerminalNotAllowed, request.CartId); } salesTransaction.ReceiptEmail = request.ReceiptEmail; // Set the transaction type to represent Cash & Carry sales by default, if it's not an IncomeExpense nor AccountDeposit transaction. if (salesTransaction.TransactionType != SalesTransactionType.IncomeExpense && salesTransaction.TransactionType != SalesTransactionType.CustomerAccountDeposit) { salesTransaction.TransactionType = SalesTransactionType.Sales; } // Fill in Store and Terminal information. OrderWorkflowHelper.FillTransactionWithContextData(this.Context, salesTransaction); // Calculate required reason code for end of transaction. ReasonCodesWorkflowHelper.CalculateRequiredReasonCodesOnTransaction(this.Context, salesTransaction, ReasonCodeSourceType.EndOfTransaction); // Validate required reason code lines has been filled. ReasonCodesWorkflowHelper.ValidateRequiredReasonCodeLinesFilled(this.Context, salesTransaction); // Validate return permission. CartWorkflowHelper.ValidateReturnPermission(this.Context, salesTransaction, salesTransaction.CartType); // Fill in variant information. OrderWorkflowHelper.FillVariantInformation(this.Context, salesTransaction); // Fill in Receipt Id. OrderWorkflowHelper.FillInReceiptId(this.Context, salesTransaction, request.ReceiptNumberSequence); // Validate sales order for creation. OrderWorkflowHelper.ValidateContextForCreateOrder(this.Context, salesTransaction); // Validate payments. OrderWorkflowHelper.CalculateAndValidateAmountPaidForCheckout(this.Context, salesTransaction); salesTransaction = OrderWorkflowHelper.ProcessCheckoutPayments(this.Context, salesTransaction); // release/unlock gift cards on sales lines GiftCardWorkflowHelper.UnlockGiftCardsOnActiveSalesLines(this.Context, salesTransaction); // Pay Sales Invoices... OrderWorkflowHelper.SettleInvoiceSalesLines(this.Context, salesTransaction); // Create order var salesOrder = OrderWorkflowHelper.CreateSalesOrder(this.Context, salesTransaction); // We also need to delete the shopping cart. CartWorkflowHelper.TryDeleteCart( this.Context, new SalesTransaction { Id = salesTransaction.Id, TerminalId = salesTransaction.TerminalId, CustomerId = salesTransaction.CustomerId, }); return(new SubmitSalesTransactionResponse(salesOrder)); }
/// <summary> /// Creates a sales transaction given the cart. /// </summary> /// <param name="request">The request.</param> /// <returns>The response.</returns> protected override SaveVoidTransactionResponse Process(SaveVoidTransactionRequest request) { ThrowIf.Null(request, "request"); ThrowIf.Null(request.CartId, "request.CartId"); // Get the Sales Transaction SalesTransaction salesTransaction = CartWorkflowHelper.LoadSalesTransaction(this.Context, request.CartId, ignoreProductDiscontinuedNotification: true); if (salesTransaction == null) { throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotFound, request.CartId); } if (salesTransaction.IsSuspended) { throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_CartNotActive, request.CartId); } // If there are unvoided non-historical Tender lines throw exception that Transaction cannot be voided. if (salesTransaction.TenderLines != null && salesTransaction.TenderLines.Any(l => l.TransactionStatus != TransactionStatus.Voided && l.Status != TenderLineStatus.Historical)) { throw new CartValidationException(DataValidationErrors.Microsoft_Dynamics_Commerce_Runtime_VoidTransactionContainsTenderedLines, request.CartId); } // Add or update any incoming reason codes on the transaction. Cart cartToBeVoided = new Cart { Id = request.CartId }; if (request.ReasonCodeLines != null) { cartToBeVoided.ReasonCodeLines = request.ReasonCodeLines.ToList(); } ReasonCodesWorkflowHelper.AddOrUpdateReasonCodeLinesOnTransaction(salesTransaction, cartToBeVoided); // Calculate the required reason codes on the tender line for voiding transaction. ReasonCodesWorkflowHelper.CalculateRequiredReasonCodesOnTransaction(this.Context, salesTransaction, ReasonCodeSourceType.VoidTransaction); GiftCardWorkflowHelper.VoidGiftCardSalesLines(this.Context, salesTransaction); // Set the Sales Transaction Status to Voided. salesTransaction.EntryStatus = TransactionStatus.Voided; // Set the transaction type to represent Cash & Carry sales. if (salesTransaction.TransactionType != SalesTransactionType.IncomeExpense) { salesTransaction.TransactionType = SalesTransactionType.Sales; } // Fill in Store and Terminal information. OrderWorkflowHelper.FillTransactionWithContextData(this.Context, salesTransaction); // Create order var salesOrder = OrderWorkflowHelper.CreateSalesOrder(this.Context, salesTransaction); // We also need to delete the shopping cart. CartWorkflowHelper.TryDeleteCart( this.Context, new SalesTransaction { Id = request.CartId, TerminalId = salesTransaction.TerminalId, CustomerId = salesTransaction.CustomerId, }); CartWorkflowHelper.LogAuditEntry( this.Context, "SaveVoidTransactionRequestHandler.Process", string.Format("Transaction '{0}' voided.", request.CartId)); return(new SaveVoidTransactionResponse(salesOrder)); }
protected override CreateOrderFromCartResponse Process(CreateOrderFromCartRequest request) { ThrowIf.Null(request, "request"); ThrowIf.Null(request.CartId, "request.CartId"); List <TenderLine> tenderLines = new List <TenderLine>(); // Get the Sales Transaction. SalesTransaction salesTransaction = null; ExecutionHandler( delegate { PopulateSalesTransaction(this.Context, request.CartId, request.ReceiptEmailAddress, out salesTransaction); }, SubmitOrderOperationType.GetSalesTransaction.ToString()); // Validate sales order for creation. ExecutionHandler( delegate { OrderWorkflowHelper.ValidateContextForCreateOrder(this.Context, salesTransaction); }, SubmitOrderOperationType.ValidateContextForCreateOrder.ToString()); // Validate addresses. ExecutionHandler( delegate { ShippingHelper.ValidateAndResolveAddresses(this.Context, salesTransaction); }, SubmitOrderOperationType.ValidateAndResolveAddresses.ToString()); // Add missing dependencies to the sales transaction. ExecutionHandler( delegate { OrderWorkflowHelper.FillMissingRequirementsForOrder(this.Context, salesTransaction); }, SubmitOrderOperationType.FillMissingRequirementsForOrder.ToString()); // Validate addresses for shipping. ExecutionHandler( delegate { ShippingHelper.ValidateShippingInformation(this.Context, salesTransaction); }, SubmitOrderOperationType.ValidateShippingAddresses.ToString()); // Validate required reason code lines has been filled. ExecutionHandler( () => ReasonCodesWorkflowHelper.ValidateRequiredReasonCodeLinesFilled(this.Context, salesTransaction), SubmitOrderOperationType.ValidateReasonCodes.ToString()); // Authorize payments. ExecutionHandler( delegate { tenderLines = OrderWorkflowHelper.ProcessPendingOrderPayments(this.Context, salesTransaction, request.CartTenderLines); }, SubmitOrderOperationType.AuthorizePayments.ToString()); SalesOrder salesOrder = null; try { // Create order and add all authorization payment blobs. ExecutionHandler( delegate { salesOrder = OrderWorkflowHelper.CreateSalesOrder(this.Context, salesTransaction); }, SubmitOrderOperationType.CreateSaleOrderInCrt.ToString()); } catch (Exception ex) { try { // Cancel the payment authorizations OrderWorkflowHelper.CancelPayments(this.Context, salesTransaction, tenderLines, request.CartTenderLines); } catch (PaymentException cancelPaymentsEx) { // Inside of CancelPayments() we always wrap Exception as PaymentException. RetailLogger.Log.CrtWorkflowCancelingPaymentFailure(ex, cancelPaymentsEx); } throw; } // We also need to delete the shopping cart. CartWorkflowHelper.TryDeleteCart( this.Context, new SalesTransaction { Id = request.CartId, TerminalId = salesTransaction.TerminalId, CustomerId = salesTransaction.CustomerId, }); return(new CreateOrderFromCartResponse(salesOrder)); }