Created
October 27, 2014 16:54
-
-
Save rustyswayne/598049064a02fce1597c to your computer and use it in GitHub Desktop.
Manually generating an order in Merchello
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Adding the shipmethod is typically done in the back office through the UI. | |
// Interested in the use case to dynamically add theses? | |
var key = Constants.ProviderKeys.Shipping.FixedRateShippingProviderKey; | |
var defaultCatalogKey = Constants.DefaultKeys.Warehouse.DefaultWarehouseCatalogKey; | |
// this would have to be done through the back office as it uses an internal service | |
var us = MerchelloContext.Current.Services.StoreSettingService.GetCountryByCode("US"); | |
var usCountry = new ShipCountry(defaultCatalogKey, us); | |
((ServiceContext)MerchelloContext.Current.Services).ShipCountryService.Save(usCountry); | |
// we can use this later. | |
var rateTableProvider = (FixedRateShippingGatewayProvider)MerchelloContext.Current.Gateways.Shipping.GetProviderByKey(key); | |
// again usually done in the back office | |
if (!rateTableProvider.ShipMethods.Any()) | |
{ | |
// creates the rate table for ship rate quotes | |
var gwShipmeMethod = (FixedRateShippingGatewayMethod)rateTableProvider.CreateShipMethod(FixedRateShippingGatewayMethod.QuoteType.VaryByWeight, usCountry, "Ground (Vary by Weight)"); | |
gwShipmeMethod.RateTable.AddRow(0, 10, 5); | |
gwShipmeMethod.RateTable.AddRow(10, 15, 10); // total weight should be 10M so we should hit this tier | |
gwShipmeMethod.RateTable.AddRow(15, 25, 25); | |
gwShipmeMethod.RateTable.AddRow(25, 10000, 100); | |
rateTableProvider.SaveShippingGatewayMethod(gwShipmeMethod); | |
} | |
// Get the persisted customer | |
const string loginName = "rusty"; | |
var customerService = MerchelloContext.Current.Services.CustomerService; | |
var customer = customerService.GetByLoginName(loginName) | |
?? customerService.CreateCustomerWithKey(loginName, "Rusty", "Swayne", "rusty@mindfly.com"); | |
// I'll use this for billing and shipping | |
var billingAddress = new Address() | |
{ | |
Name = "Mindfly Web Design Studio", | |
Address1 = "114 W. Magnolia St. Suite 300", | |
Locality = "Bellingham", | |
Region = "WA", | |
PostalCode = "98225", | |
CountryCode = "US" | |
}; | |
// Most of the time this information is brought in from the IProductVariant - but the idea is you can | |
// describe things on the fly | |
var extendedData = new ExtendedDataCollection(); | |
// this is used to determine where a shipment originates | |
extendedData.SetValue(Constants.ExtendedDataKeys.WarehouseCatalogKey, defaultCatalogKey.ToString()); | |
// items set to shippable | |
extendedData.SetValue(Constants.ExtendedDataKeys.TrackInventory, "false"); | |
extendedData.SetValue(Constants.ExtendedDataKeys.Shippable, "true"); | |
extendedData.SetValue(Constants.ExtendedDataKeys.Weight, "1.25"); | |
extendedData.SetValue(Constants.ExtendedDataKeys.CurrencyCode, "USD"); | |
var item = new InvoiceLineItem(LineItemType.Product, "My product", "mySku", 2, 10M, extendedData); | |
var invoiceService = MerchelloContext.Current.Services.InvoiceService; | |
var invoice = invoiceService.CreateInvoice(Constants.DefaultKeys.InvoiceStatus.Unpaid); | |
// I'd say we need to add a parameter to the service so we don't have to do this | |
// http://issues.merchello.com/youtrack/issue/M-434 | |
((Invoice)invoice).CustomerKey = customer.Key; | |
// The version key is useful in some cases to invalidate shipping quotes or taxation calculations | |
invoice.VersionKey = Guid.NewGuid(); | |
invoice.Items.Add(item); | |
// at this point the invoice is not saved and we don't have an invoice number | |
// however, we may want to quote shipping so we need a shipment | |
// Shipment Statuses are new in 1.5.0 | |
var warehouse = MerchelloContext.Current.Services.WarehouseService.GetDefaultWarehouse(); | |
var shipmentStatus = | |
MerchelloContext.Current.Services.ShipmentService.GetShipmentStatusByKey( | |
Constants.DefaultKeys.ShipmentStatus.Quoted); | |
// since we know all the items in the invoice will be shipped we don't need to filter | |
var shipment = new Shipment(shipmentStatus, warehouse.AsAddress(), billingAddress, invoice.Items); | |
// since we already know the shipping provider we want from above we can do | |
var quotes = rateTableProvider.QuoteShippingGatewayMethodsForShipment(shipment); | |
// if we wanted Merchello to get quotes from all shipping providers we'd do the following | |
// var quotes = shipment.ShipmentRateQuotes(); | |
if (quotes.Any()) | |
{ | |
// this check makes certain a quote was returned. For example if the collection of items was outside the allowable | |
// weight range, the provider would not return a quote. | |
// Add the first quote to the invoice. | |
invoice.Items.Add(quotes.FirstOrDefault().AsLineItemOf<InvoiceLineItem>()); | |
} | |
// you do need to update the total ... this is usually done in the InvoiceBuilder in | |
// instantiated by a SalesPreparation sub class | |
var charges = invoice.Items.Where(x => x.LineItemType != LineItemType.Discount).Sum(x => x.TotalPrice); | |
var discounts = invoice.Items.Where(x => x.LineItemType == LineItemType.Discount).Sum(x => x.TotalPrice); | |
// total the invoice | |
decimal converted; | |
invoice.Total = decimal.TryParse((charges - discounts).ToString(CultureInfo.InvariantCulture), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture.NumberFormat, out converted) ? converted : 0; | |
// Now we save the invoice since we have to have a real record of something to collect a payment against | |
// This also generates the invoice number | |
invoiceService.Save(invoice); | |
Console.WriteLine(invoice.InvoiceNumber); | |
// cash payment method | |
var cashProvider = MerchelloContext.Current.Gateways.Payment.GetProviderByKey(Constants.ProviderKeys.Payment.CashPaymentProviderKey); | |
if (cashProvider != null) | |
{ | |
var cash = cashProvider.PaymentMethods.FirstOrDefault(); // default install has a single payment method "Cash" | |
// I usually Authorize a cash payment if taken online since we don't really see the money. Capture is used | |
// when the money comes in. In your inquiry, it looks like you are assuming the money is in hand at the | |
// time of the purchase, so we'll use AuthorizeCapture straight away. | |
var attempt = invoice.AuthorizeCapturePayment(cash.Key); | |
if (! attempt.Payment.Success) | |
{ | |
// handle the error | |
} | |
// otherwise you'll notice | |
var approved = attempt.ApproveOrderCreation; // equals true | |
// the order will be automatically created by the event handler in Merchello.Core.Gateways.GatewayEvents | |
// however in this test I don't have the event wired up so I have to do it manuall | |
if (approved) | |
{ | |
var order = invoice.PrepareOrder(); | |
MerchelloContext.Current.Services.OrderService.Save(order); | |
} | |
} | |
// Cash provider is not active |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've added this code to Merchello.Tests.IntegrationTests.Invoices.InvoiceTests in the repository so you can step through it if you want.