Skip to content

Instantly share code, notes, and snippets.

@rustyswayne
Created October 27, 2014 16:54
Show Gist options
  • Save rustyswayne/598049064a02fce1597c to your computer and use it in GitHub Desktop.
Save rustyswayne/598049064a02fce1597c to your computer and use it in GitHub Desktop.
Manually generating an order in Merchello
// 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
@rustyswayne
Copy link
Author

I've added this code to Merchello.Tests.IntegrationTests.Invoices.InvoiceTests in the repository so you can step through it if you want.

@kikores
Copy link

kikores commented Aug 9, 2017

Perfect example, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment