/// <summary> /// Deletes a product option /// </summary> /// <param name="option"> /// The option to be deleted /// </param> /// <param name="raiseEvents"> /// Optional boolean indicating whether or not to raise events. /// </param> /// <remarks> /// This performs a check to ensure the option is valid to be deleted /// </remarks> public void Delete(IProductOption option, bool raiseEvents = true) { if (!EnsureSafeOptionDelete(option)) { MultiLogHelper.Warn <ProductOptionService>("A ProductOption delete attempt was aborted. The option cannot be deleted due to it being shared with one or more products."); return; } if (raiseEvents) { if (Deleting.IsRaisedEventCancelled(new DeleteEventArgs <IProductOption>(option), this)) { ((ProductOption)option).WasCancelled = true; return; } } using (new WriteLock(Locker)) { var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateProductOptionRepository(uow)) { repository.Delete(option); uow.Commit(); } } if (raiseEvents) { Deleted.RaiseEvent(new DeleteEventArgs <IProductOption>(option), this); } }
public HttpResponseMessage PutInvoiceShippingAddress(InvoiceShippingUpdateData data) { var response = Request.CreateResponse(HttpStatusCode.OK); try { var invoice = _invoiceService.GetByKey(data.InvoiceKey); var shippingLineItems = invoice.ShippingLineItems().ToArray(); if (shippingLineItems.Any()) { foreach (var lineItem in shippingLineItems) { lineItem.ExtendedData.AddAddress(data.Address.ToAddress(), Constants.ExtendedDataKeys.ShippingDestinationAddress); } } else { // Problem. There is no shipping line item when there should be! Needs more investigating as this does very, very occasionally happen MultiLogHelper.Warn <InvoiceApiController>(string.Format("No shipping address line item when trying to save shipping address for {0}", invoice.PrefixedInvoiceNumber())); } _invoiceService.Save(invoice); } catch (Exception ex) { MultiLogHelper.Error <InvoiceApiController>("Failed to save shipping address", ex); response = Request.CreateResponse(HttpStatusCode.NotFound, string.Format("{0}", ex.Message)); } return(response); }
/// <summary> /// Maps a <see cref="Page{Guid}"/> to <see cref="PagedCollection{TContent}"/>. /// </summary> /// <param name="page"> /// The page. /// </param> /// <param name="sortBy"> /// The sort by. /// </param> /// <returns> /// The <see cref="PagedCollection"/>. /// </returns> public virtual PagedCollection <TContent> MapPagedCollection(Page <Guid> page, string sortBy) { var items = page.Items.Select(GetByKey).Where(x => x != null).ToArray(); if (items.Count() != page.ItemsPerPage) { MultiLogHelper.Warn <VirtualContentCache <TContent, TEntity> >("Could not map all items to virtual content"); } return(new PagedCollection <TContent> { CurrentPage = page.CurrentPage, PageSize = items.Count(), TotalPages = page.TotalPages, TotalItems = page.TotalItems, Items = items, SortField = sortBy }); }
/// <summary> /// Itemizes the invoice. /// </summary> /// <returns> /// The <see cref="InvoiceItemItemization"/>. /// </returns> public InvoiceItemItemization Itemize() { var itemization = this.ItemizeInvoice(); itemization.Reconciles = true; if (!this.Reconcile(itemization)) { itemization.Reconciles = false; MultiLogHelper.Warn <InvoiceItemizationStrategyBase>("Reconciliation of invoice total failed in the itemization strategy"); } itemization.ItemizationTotal = itemization.CalculateTotal(); itemization.InvoiceTotal = Invoice.Total; itemization.ProductTotal = itemization.CalculateProductTotal(); itemization.ShippingTotal = itemization.CalculateShippingTotal(); itemization.TaxTotal = itemization.CalculateTaxTotal(); itemization.AdjustmentTotal = itemization.CalculateAdjustmentTotal(); itemization.DiscountTotal = itemization.CalculateDiscountTotal(); itemization.CustomTotal = itemization.CalculateCustomTotal(); return(itemization); }
/// <summary> /// Performs the setup for an express checkout. /// </summary> /// <param name="invoice"> /// The <see cref="IInvoice"/>. /// </param> /// <param name="payment"> /// The <see cref="IPayment"/> /// </param> /// <param name="returnUrl"> /// The return URL. /// </param> /// <param name="cancelUrl"> /// The cancel URL. /// </param> /// <returns> /// The <see cref="ExpressCheckoutResponse"/>. /// </returns> protected virtual PayPalExpressTransactionRecord SetExpressCheckout(IInvoice invoice, IPayment payment, string returnUrl, string cancelUrl) { var record = new PayPalExpressTransactionRecord { Success = true, Data = { Authorized = false, CurrencyCode = invoice.CurrencyCode } }; var factory = new PayPalPaymentDetailsTypeFactory(new PayPalFactorySettings { WebsiteUrl = _websiteUrl }); var paymentDetailsType = factory.Build(invoice, PaymentActionCodeType.ORDER); // The API requires this be in a list var paymentDetailsList = new List <PaymentDetailsType>() { paymentDetailsType }; // ExpressCheckout details var ecDetails = new SetExpressCheckoutRequestDetailsType() { ReturnURL = returnUrl, CancelURL = cancelUrl, PaymentDetails = paymentDetailsList, AddressOverride = "1" }; // Trigger the event to allow for overriding ecDetails var ecdOverride = new PayPalExpressCheckoutRequestDetailsOverride(invoice, payment, ecDetails); SettingCheckoutRequestDetails.RaiseEvent(new ObjectEventArgs <PayPalExpressCheckoutRequestDetailsOverride>(ecdOverride), this); // The ExpressCheckoutRequest var request = new SetExpressCheckoutRequestType { Version = Version, SetExpressCheckoutRequestDetails = ecdOverride.ExpressCheckoutDetails }; // Crete the wrapper for Express Checkout var wrapper = new SetExpressCheckoutReq { SetExpressCheckoutRequest = request }; try { var service = GetPayPalService(); var response = service.SetExpressCheckout(wrapper); record.SetExpressCheckout = _responseFactory.Build(response, response.Token); if (record.SetExpressCheckout.Success()) { record.Data.Token = response.Token; record.SetExpressCheckout.RedirectUrl = GetRedirectUrl(response.Token); } else { foreach (var et in record.SetExpressCheckout.ErrorTypes) { var code = et.ErrorCode; var sm = et.ShortMessage; var lm = et.LongMessage; MultiLogHelper.Warn <PayPalExpressCheckoutService>(string.Format("{0} {1} {2}", code, lm, sm)); } record.Success = false; } } catch (Exception ex) { record.Success = false; record.SetExpressCheckout = _responseFactory.Build(ex); } return(record); }
/// <summary> /// Delete products from an existing invoice /// </summary> /// <param name="invoiceOrderShipment"></param> /// <param name="invoiceAddItems"></param> /// <param name="invoiceAdjustmentResult"></param> public virtual InvoiceAdjustmentResult DeleteLineItemsFromInvoice(InvoiceOrderShipment invoiceOrderShipment, IEnumerable <InvoiceAddItem> invoiceAddItems, InvoiceAdjustmentResult invoiceAdjustmentResult) { // Get the items to be deleted in a dictionary by SKU too var skusToBeDeleted = invoiceAddItems.Where(x => x.Quantity <= 0).Select(x => x.OriginalSku); // Now get the correct items var toBeDeleted = invoiceOrderShipment.LineItems.Where(x => skusToBeDeleted.Contains(x.Sku)).ToArray(); // Can we delete var canDelete = true; // Check if we have an order if (invoiceAdjustmentResult.InvoiceLineItemType == InvoiceLineItemType.Product) { // Order needs saving var saveOrder = false; foreach (var lineItem in toBeDeleted) { if (lineItem.HasShipment) { // Cannot delete as this lineitem is in a shipment canDelete = false; } else { if (invoiceOrderShipment.HasOrders) { var order = invoiceOrderShipment.Orders.FirstOrDefault(x => x.Key == lineItem.OrderId); if (order != null) { // Remove this orderline item invoiceOrderShipment.Orders.FirstOrDefault(x => x.Key == lineItem.OrderId).Items.RemoveItem(lineItem.Sku); // Save the order saveOrder = true; } } // Remove invoice line item too invoiceOrderShipment.Invoice.Items.RemoveItem(lineItem.Sku); } // Found a product we can't delete so break if (canDelete == false) { break; } // Finally Save the order? if (saveOrder) { foreach (var order in invoiceOrderShipment.Orders.Where(x => x.Key == lineItem.OrderId)) { _orderService.Save(order); } saveOrder = false; } } } // If we can delete then do it. if (canDelete) { // Now update invoice and save as well as doing the tax ((InvoiceService)_invoiceService).ReSyncInvoiceTotal(invoiceOrderShipment.Invoice, true); // Set to true invoiceAdjustmentResult.Success = true; } else { const string message = "Unable to delete product because there is already an order that has a shipment with one of the products to be deleted. Either delete the shipment or use adjustments to reduce invoice."; MultiLogHelper.Warn <InvoiceApiController>(message); invoiceAdjustmentResult.Success = false; invoiceAdjustmentResult.Message = message; } return(invoiceAdjustmentResult); }
public virtual HttpResponseMessage PutInvoiceNewProducts(InvoiceAddItems invoiceAddItems) { var response = Request.CreateResponse(HttpStatusCode.OK); try { if (invoiceAddItems.Items != null) { // Get the invoice and associated data var invoiceOrderShipment = _invoiceService.GetInvoiceOrderShipment(invoiceAddItems.InvoiceKey); if (invoiceOrderShipment.Invoice != null) { //var currentUser = Umbraco.UmbracoContext.Security.CurrentUser; var invoiceAdjustmentResult = new InvoiceAdjustmentResult(invoiceAddItems.LineItemType); // The adjustment type var invoiceAdjustmentType = SetInvoiceAdjustmentType(invoiceAddItems, invoiceOrderShipment); //// Use the merchello helper to get the prdoucts, so the data modifiers are triggered. var merchelloHelper = new MerchelloHelper(); // Get the product service var productService = merchelloHelper.Query.Product; // See if we can get the products foreach (var invoiceAddItem in invoiceAddItems.Items) { if (invoiceAddItems.IsAddProduct && invoiceAddItem.Key != Guid.Empty) { invoiceAddItem.ProductVariant = productService.GetProductVariantByKey(invoiceAddItem.Key); invoiceAddItem.Product = productService.GetByKey(invoiceAddItem.Key); // Complete the Sku too invoiceAddItem.Sku = invoiceAddItem.Product != null ? invoiceAddItem.Product.Sku : invoiceAddItem.ProductVariant.Sku; } else if (!string.IsNullOrWhiteSpace(invoiceAddItem.Sku)) { invoiceAddItem.ProductVariant = productService.GetProductVariantBySku(invoiceAddItem.Sku); invoiceAddItem.Product = productService.GetBySku(invoiceAddItem.Sku); } } // Work out the type of adjustment switch (invoiceAdjustmentType) { case InvoiceAdjustmentType.AddProducts: invoiceAdjustmentResult = AddNewLineItemsToInvoice(invoiceOrderShipment, invoiceAddItems.Items, invoiceAdjustmentResult); break; case InvoiceAdjustmentType.DeleteProduct: invoiceAdjustmentResult = DeleteLineItemsFromInvoice(invoiceOrderShipment, invoiceAddItems.Items, invoiceAdjustmentResult); break; case InvoiceAdjustmentType.UpdateProductDetails: invoiceAdjustmentResult = UpdateCustomProductsOnInvoice(invoiceOrderShipment, invoiceAddItems.Items, invoiceAdjustmentResult); break; } if (!invoiceAdjustmentResult.Success) { response = Request.CreateResponse(HttpStatusCode.Conflict, invoiceAdjustmentResult.Message); MultiLogHelper.Warn <InvoiceApiController>(invoiceAdjustmentResult.Message); } } else { response = Request.CreateResponse(HttpStatusCode.NotFound, "Invoice not found"); } } else { response = Request.CreateResponse(HttpStatusCode.NotFound, "No items to update"); } } catch (Exception ex) { MultiLogHelper.Error <InvoiceApiController>("Failed to adjust invoice", ex); response = Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); } return(response); }
public QueryResultDisplay SearchInvoices(QueryDisplay query) { var term = query.Parameters.FirstOrDefault(x => x.FieldName == "term"); var invoiceDateStart = query.Parameters.FirstOrDefault(x => x.FieldName == "invoiceDateStart"); var invoiceDateEnd = query.Parameters.FirstOrDefault(x => x.FieldName == "invoiceDateEnd"); var isTermSearch = term != null && !string.IsNullOrEmpty(term.Value); var isDateSearch = invoiceDateStart != null && !string.IsNullOrEmpty(invoiceDateStart.Value); var startDate = DateTime.MinValue; var endDate = DateTime.MaxValue; if (isDateSearch) { var settings = _storeSettingService.GetAll().ToList(); var dateFormat = settings.FirstOrDefault(s => s.Name == "dateFormat"); if (dateFormat == null) { if (!DateTime.TryParse(invoiceDateStart.Value, out startDate)) { MultiLogHelper.Warn <InvoiceApiController>(string.Format("Was unable to parse startDate: {0}", invoiceDateStart.Value)); startDate = DateTime.MinValue; } } else if (!DateTime.TryParseExact(invoiceDateStart.Value, dateFormat.Value, CultureInfo.InvariantCulture, DateTimeStyles.None, out startDate)) { MultiLogHelper.Warn <InvoiceApiController>(string.Format("Was unable to parse startDate: {0}", invoiceDateStart.Value)); startDate = DateTime.MinValue; } endDate = invoiceDateEnd == null || dateFormat == null ? DateTime.MaxValue : DateTime.TryParseExact(invoiceDateEnd.Value, dateFormat.Value, CultureInfo.InvariantCulture, DateTimeStyles.None, out endDate) ? endDate : DateTime.MaxValue; } if (isTermSearch && isDateSearch) { return(_merchello.Query.Invoice.Search( term.Value, startDate, endDate, query.CurrentPage + 1, query.ItemsPerPage, query.SortBy, query.SortDirection)); } if (isTermSearch) { return(this._merchello.Query.Invoice.Search( term.Value, query.CurrentPage + 1, query.ItemsPerPage, query.SortBy, query.SortDirection)); } if (isDateSearch) { return(this._merchello.Query.Invoice.Search( startDate, endDate, query.CurrentPage + 1, query.ItemsPerPage, query.SortBy, query.SortDirection)); } return(this._merchello.Query.Invoice.Search( query.CurrentPage + 1, query.ItemsPerPage, query.SortBy, query.SortDirection)); }