I am having a little bit of trouble when creating an Invoice/Order. I can set a billing address using invoice.SetBillingAddress(billingAddress). But I don't see a way of setting the shipping one. Has anyone got any sample code for me to look at?
Also how do I set it so I can change the status of the order from unfulfilled to fulfilled? I Assume this is something to do with the shipments tab, but I can't see anywhere to set this as well.
Authorize/AuthorizeCapture payment will actually save the invoice and set a flag to approve the order creation. Once the payment has been captured the order will be created and allow the order to be fulfilled. This is so warehouse staff don't have to be notified of an order to be fulfilled until the payment has been received.
If you want an order created regardless of payment status, you can set the AlwaysApproveOrderCreation to true in the merchello.config.
<!--
Overrides the Payment Method's IPaymentResponse ApproveOrderCreation indicating an order should always be created no matter
if the payment has been collected or not.
-->
<setting alias="AlwaysApproveOrderCreation" value="false" />
Checkout the Merchello.Bazaar code for an example:
There are methods to set both the ShippingAddress and BillingAddress in the SalesPreparation class. You can think of this class as a temporary stage to collect all of your information while you are building the sale (invoice).
Im not actually using Bazaar. Im doing it in a custom way. Here's the code im using:
//Create Invoice
var invoiceService = MerchelloContext.Current.Services.InvoiceService;
var invoice = invoiceService.CreateInvoice(Merchello.Core.Constants.DefaultKeys.InvoiceStatus.Unpaid);
var extendedData = new ExtendedDataCollection();
//Set Invoice Products
var customerContext = new CustomerContext(UmbracoContext);
var basket = customerContext.CurrentCustomer.Basket();
var basketModel = basket.ToBasketViewModel();
foreach(var basketItem in basketModel.Items)
{
var content = Umbraco.TypedContent(basketItem.ContentId);
decimal itemPrice = basketItem.UnitPrice;
var title = content.Name;
var quantity = basketItem.Quantity;
var sku = basketItem.Sku;
var orderLine = new InvoiceLineItem(LineItemType.Product, title, sku, quantity, itemPrice, extendedData);
invoice.Items.Add(orderLine);
invoice.Total += itemPrice * quantity;
}
//Payment Method
var cashProvider = MerchelloContext.Current.Gateways.Payment.GetProviderByKey(Constants.ProviderKeys.Payment.CashPaymentProviderKey);
var cash = cashProvider.PaymentMethods.FirstOrDefault();
invoice.AuthorizeCapturePayment(cash.Key);
//Set Billing Address
invoice.SetBillingAddress(billingDestination);
//Set Customer
((Invoice)invoice).CustomerKey = customer.Key;
invoiceService.Save(invoice);
As you can see from the code i can set the billing address quite easily with .SetBillingAddress, but there isnt anything to set the shipping address and i cant find anyone that has done it.
OK - if you want to create an invoice manually, you will need to add the shipment line item yourself. A shipment line item is created by getting a shipment rate quote by quoting a shipment (which you'll have to "package" from your items) and then adding that (the quote) to the shipment line items extended data collection. The shipment itself has the shipping address as "destination address".
The reason we do it this way, is there could be times when an order is broken up into multiple shipments that need to be sent to different destinations. In that case there would be multiple shipment line items.
I can't post code at the moment, but there are a few integration tests in the Merchello repo that should give you an idea. Also, if I remember right, there was a thread on this forum a while back where we discussed creating invoices manually.
I have looked into it a bit further, I have see the post before and have tried to work through it and get it to work but I haven't had any luck.
This is what I have so far:
//Set Shipping Address
var warehouse = MerchelloContext.Current.Services.WarehouseService.GetDefaultWarehouse();
var shipmentService = MerchelloContext.Current.Services.ShipmentService;
var shipmentStatus = MerchelloContext.Current.Services.ShipmentService.GetShipmentStatusByKey(Constants.DefaultKeys.ShipmentStatus.Quoted);
var shipment = shipmentService.CreateShipment(shipmentStatus, warehouse.AsAddress(), shippingDestination, invoice.Items);
var key = Constants.ProviderKeys.Shipping.FixedRateShippingProviderKey;
var rateTableProvider = (FixedRateShippingGatewayProvider)MerchelloContext.Current.Gateways.Shipping.GetProviderByKey(key);
var quotes = rateTableProvider.QuoteShippingGatewayMethodsForShipment(shipment);
if (quotes.Any())
{
invoice.Items.Add(quotes.FirstOrDefault().AsLineItemOf<InvoiceLineItem>());
}
Its currently not wokring and doesnt seem to actually be doing anything. Any ideas when you get a sec would be amazing thank you.
//Preparing shipment
var warehouseService = MerchelloContext.Current.Services.WarehouseService;
var shipmentService = MerchelloContext.Current.Services.ShipmentService;
var gatewayproviderService = MerchelloContext.Current.Services.GatewayProviderService;
var warehouse = warehouseService.GetDefaultWarehouse();
var shipmentStatus = shipmentService.GetShipmentStatusByKey(Constants.DefaultKeys.ShipmentStatus.Quoted);
var shipment = shipmentService.CreateShipment(shipmentStatus, warehouse.AsAddress(), billingDestination, invoice.Items);
var country = MerchelloContext.Current.Services.StoreSettingService.GetCountryByCode("GB").Key;
var key = Constants.ProviderKeys.Shipping.FixedRateShippingProviderKey;
var rateTableProvider = (FixedRateShippingGatewayProvider)MerchelloContext.Current.Gateways.Shipping.GetProviderByKey(key);
var shipService = new Merchello.Core.Services.GatewayProviderService();
//IShipCountry shipCountry = shipService.GetShipCountryByKey(country);
var catalog = warehouseService.GetAllWarehouseCatalogs().FirstOrDefault();
var shipCountry = gatewayproviderService.GetShipCountry(catalog.Key, "GB");
var methods = rateTableProvider.ShipMethods.ToArray(); //Gets "GLS", "Post Danmark (Vary by Weigth)", "Ground (Vary by Weight)"
var method = rateTableProvider.ShipMethods.Where(x => x.ShipCountryKey == shipCountry.Key).FirstOrDefault(); //Gets "Post Danmark (Vary by Weight)"
shipment.ShipMethodKey = method.Key;
var quote = rateTableProvider.QuoteShipMethodForShipment(shipment, rateTableProvider.GetShippingGatewayMethod(method.Key, shipCountry.Key));
//Add shipping quotes to invoice
invoice.Items.Add(quote.AsLineItemOf<InvoiceLineItem>());
Im curious to know if you can spot anything just by looking at that bit of code?
Once you have your shipment, you should probably use the ShippingContext as it sort of looks like your trying to do a lot of work that is already done for you ...
var shippingContext = MerchelloContext.Current.Gateways.Shipping;
var quote = shippingContext.GetShipRateQuotesForShipment(shipment);
Alternatively you could use the extension method off of the shipment.
// Quote the shipment
var shipmentRateQuotes = shipment.ShipmentRateQuotes().ToArray();
if (shipmentRateQuotes.Any() && !invoice.ShippingLineItems().Any())
{
//// Assume the first selection. Customer will be able to update this later
//// but this allows for a taxation calculation as well in the event shipping charges
//// are taxable.
preparation.SaveShipmentRateQuote(shipmentRateQuotes.First());
}
shipmentRateQuotes.Any() && !invoice.ShippingLineItems().Any() always is false
Shipping Address and Shipments when creating Invoice/Order
Hi Guys,
I am having a little bit of trouble when creating an Invoice/Order. I can set a billing address using invoice.SetBillingAddress(billingAddress). But I don't see a way of setting the shipping one. Has anyone got any sample code for me to look at?
Also how do I set it so I can change the status of the order from unfulfilled to fulfilled? I Assume this is something to do with the shipments tab, but I can't see anywhere to set this as well.
Many Thanks,
Nathan
Hey Nathan,
You should not have to create an order - that is pretty much done internally.
Typically the process would go:
Basket -> SalesPreparation -> Authorize/AuthorizeCapture payment.
Authorize/AuthorizeCapture payment will actually save the invoice and set a flag to approve the order creation. Once the payment has been captured the order will be created and allow the order to be fulfilled. This is so warehouse staff don't have to be notified of an order to be fulfilled until the payment has been received.
If you want an order created regardless of payment status, you can set the AlwaysApproveOrderCreation to true in the merchello.config.
Checkout the Merchello.Bazaar code for an example:
https://github.com/Merchello/Merchello/blob/merchello-dev/src/Merchello.Bazaar/Controllers/BazaarCheckoutConfirmController.cs
There are methods to set both the ShippingAddress and BillingAddress in the SalesPreparation class. You can think of this class as a temporary stage to collect all of your information while you are building the sale (invoice).
Hi Rusty,
Im not actually using Bazaar. Im doing it in a custom way. Here's the code im using:
As you can see from the code i can set the billing address quite easily with .SetBillingAddress, but there isnt anything to set the shipping address and i cant find anyone that has done it.
Does this make sense?
Nathan
@Nathan,
OK - if you want to create an invoice manually, you will need to add the shipment line item yourself. A shipment line item is created by getting a shipment rate quote by quoting a shipment (which you'll have to "package" from your items) and then adding that (the quote) to the shipment line items extended data collection. The shipment itself has the shipping address as "destination address".
The reason we do it this way, is there could be times when an order is broken up into multiple shipments that need to be sent to different destinations. In that case there would be multiple shipment line items.
I can't post code at the moment, but there are a few integration tests in the Merchello repo that should give you an idea. Also, if I remember right, there was a thread on this forum a while back where we discussed creating invoices manually.
Rusty,
I have looked into it a bit further, I have see the post before and have tried to work through it and get it to work but I haven't had any luck.
This is what I have so far:
Its currently not wokring and doesnt seem to actually be doing anything. Any ideas when you get a sec would be amazing thank you.
Nathan
Hi Rusty,
I have tried to get this working this morning by looking at this post: https://our.umbraco.org/projects/collaboration/merchello/merchello/67640-fulfilling-orders. It seems like in my code it inst finding a shipment country.
Im curious to know if you can spot anything just by looking at that bit of code?
Nathan
@Nathan,
Once you have your shipment, you should probably use the ShippingContext as it sort of looks like your trying to do a lot of work that is already done for you ...
Alternatively you could use the extension method off of the shipment.
Rusty, why shipment rate quote with my shipping address alway set to null? How can I configure this?
shipmentRateQuotes = shipment.ShipmentRateQuotes().ToArray();
if (shipmentRateQuotes.Any() && !invoice.ShippingLineItems().Any()) {
//// Assume the first selection. Customer will be able to update this later //// but this allows for a taxation calculation as well in the event shipping charges
//// are taxable. preparation.SaveShipmentRateQuote(shipmentRateQuotes.First()); }
shipmentRateQuotes.Any() && !invoice.ShippingLineItems().Any() always is false
is working on a reply...