Skip to content

Instantly share code, notes, and snippets.

@rustyswayne
Created October 27, 2014 16:54
Show Gist options
  • Select an option

  • Save rustyswayne/598049064a02fce1597c to your computer and use it in GitHub Desktop.

Select an option

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
Copy Markdown
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
Copy Markdown

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