﻿<?xml version="1.0" encoding="utf-16"?>
<JiwaDocument xmlns:jiwa="http://www.jiwa.com.au/xml/schemas" Type="JiwaFinancials.Jiwa.JiwaApplication.Plugin.Plugin">
  <RecID>d9644d57-d659-4aaf-b7de-cc38a38000e2</RecID>
  <Name>REST API</Name>
  <Description>Provides a REST HTTP endpoint with some routes.</Description>
  <IsEnabled>true</IsEnabled>
  <IsIsolatedToOwnAppDomain>false</IsIsolatedToOwnAppDomain>
  <ExecutionOrder>0</ExecutionOrder>
  <Author>Jiwa Financials</Author>
  <Version>7.2.1.32</Version>
  <Code>/*
	*** DO NOT MODIFY THIS PLUGIN ***

	This plugin will be updated automatically via upgrades and any modifications made will be lost.

	Copy this plugin instead, and then disable this plugin if the default behaviour is not suited.


*/
using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Windows.Forms;
using System.Security.Cryptography;

using JiwaFinancials.Jiwa;
using JiwaFinancials.Jiwa.JiwaServiceModel.Tables;

using ServiceStack;
using ServiceStack.DataAnnotations;
using ServiceStack.Model;
using ServiceStack.Auth;
using ServiceStack.OrmLite;
using ServiceStack.Host;
using ServiceStack.Configuration;
using ServiceStack.Web;

namespace JiwaFinancials.Jiwa.RESTAPIPlugin
{
#region "BusinessLogicPlugin - Webhooks"
public class BusinessLogicPlugin : System.MarshalByRefObject, JiwaFinancials.Jiwa.JiwaApplication.IJiwaBusinessLogicPlugin
{
	static public string PluginName;
	
    public override object InitializeLifetimeService()
    {
        // returning null here will prevent the lease manager
        // from deleting the Object.
        return null;
    }

    public void Setup(JiwaFinancials.Jiwa.JiwaApplication.IJiwaBusinessLogic JiwaBusinessLogic, JiwaFinancials.Jiwa.JiwaApplication.Plugin.Plugin Plugin)
    {			
		PluginName = Plugin.Name; // webhook needs to know this to read the system setting without using a literal string for the section - DEV-9122
		
		// Add a handler for the Save end
        if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)
        {
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)JiwaBusinessLogic;
            salesOrder.SaveEnd += SalesOrder_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaInventory.Inventory)
        {
            JiwaFinancials.Jiwa.JiwaInventory.Inventory inventory = (JiwaFinancials.Jiwa.JiwaInventory.Inventory)JiwaBusinessLogic;
            inventory.SaveEnd += Inventory_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification)
        {
            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification inventoryClassification = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification)JiwaBusinessLogic;
            inventoryClassification.SaveEnd += InventoryClassification_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories)
        {
            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories inventoryCategories = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories)JiwaBusinessLogic;
            inventoryCategories.SaveEnd += InventoryCategories_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaDebtors.Debtor)
        {
            JiwaFinancials.Jiwa.JiwaDebtors.Debtor debtor = (JiwaFinancials.Jiwa.JiwaDebtors.Debtor)JiwaBusinessLogic;
            debtor.SaveEnd += Debtor_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification)
        {
            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification debtorClassification = (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification)JiwaBusinessLogic;
            debtorClassification.SaveEnd += DebtorClassification_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories)
        {
            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories debtorCategories = (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories)JiwaBusinessLogic;
            debtorCategories.SaveEnd += DebtorCategories_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaCreditors.Creditor)
        {
            JiwaFinancials.Jiwa.JiwaCreditors.Creditor creditor = (JiwaFinancials.Jiwa.JiwaCreditors.Creditor)JiwaBusinessLogic;
            creditor.SaveEnd += Creditor_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification)
        {
            JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification creditorClassification = (JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification)JiwaBusinessLogic;
            creditorClassification.SaveEnd += CreditorClassification_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder)
        {
            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = (JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder)JiwaBusinessLogic;
            purchaseOrder.SaveEnd += PurchaseOrder_SaveEnd;
        }
		else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice)
        {
            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = (JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice)JiwaBusinessLogic;
            purchaseInvoice.SaveEnd += PurchaseInvoice_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates)
        {
            JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates taxRates = (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates)JiwaBusinessLogic;
            taxRates.SaveEnd += TaxRates_SaveEnd;
        }
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn)
        {
           JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn bookIn = (JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn)JiwaBusinessLogic;
           bookIn.SaveEnd += BookIn_SaveEnd;
        }	
        else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment)
        {
           JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = (JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment)JiwaBusinessLogic;
           Shipment.SaveEnd += Shipment_SaveEnd;
        }	
		else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaInvReceival.Receival)
        {
           JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = (JiwaFinancials.Jiwa.JiwaInvReceival.Receival)JiwaBusinessLogic;
           goodsReceivedNote.SaveEnd += GoodsReceivedNote_SaveEnd;
        }
		else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)
        {
           JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)JiwaBusinessLogic;
           salesQuote.SaveEnd += SalesQuote_SaveEnd;
        }
		else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer)
        {
			JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransfer = (JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer)JiwaBusinessLogic;
			warehouseTransfer.SaveEnd += WarehouseTransfer_SaveEnd;
        }				
		else if (JiwaBusinessLogic is JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection)
        {
			JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection paymentTypes = (JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection)JiwaBusinessLogic;
			paymentTypes.SaveEnd += PaymentTypes_SaveEnd;
        }
    }
		
	async public void SalesOrder_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)sender;
        string body = salesOrder.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder&gt;();

        Webhook(salesOrder.Manager, body, (salesOrder.InsertFlag) ? "salesorder.created" : "salesorder.updated", PluginName);
    }

    async public void Inventory_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaInventory.Inventory inventory = (JiwaFinancials.Jiwa.JiwaInventory.Inventory)sender;
        string body = inventory.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryItem&gt;();

        Webhook(inventory.Manager, body, (inventory.InsertFlag) ? "inventory.created" : (inventory.DeleteFlag) ? "inventory.deleted" : "inventory.updated", PluginName);
    }
    
    async public void InventoryClassification_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification inventoryClassification = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification)sender;
        string body = inventoryClassification.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Classification.InventoryClassification&gt;();

        Webhook(inventoryClassification.Manager, body, (inventoryClassification.InsertFlag) ? "inventoryclassification.created" : (inventoryClassification.DeleteFlag) ? "inventoryclassification.deleted" : "inventoryclassification.updated", PluginName);
    }

    async public void InventoryCategories_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories inventoryCategories = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories)sender;

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category1 category in inventoryCategories.Category1Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category1&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "inventorycategory.created" : "inventorycategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category2 category in inventoryCategories.Category2Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category2&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "inventorycategory.created" : "inventorycategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category3 category in inventoryCategories.Category3Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category3&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "inventorycategory.created" : "inventorycategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category4 category in inventoryCategories.Category4Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category4&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "inventorycategory.created" : "inventorycategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category5 category in inventoryCategories.Category5Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category5&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "inventorycategory.created" : "inventorycategory.updated", PluginName);
        }

        // Handle deletes - these will still be in the deleted collections at SaveEnd
        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category1 category in inventoryCategories.Category1Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, "inventorycategory.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category2 category in inventoryCategories.Category2Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, "inventorycategory.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category3 category in inventoryCategories.Category3Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, "inventorycategory.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category4 category in inventoryCategories.Category4Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, "inventorycategory.deleted", PluginName);
        }
        foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Category5 category in inventoryCategories.Category5Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            Webhook(category.Manager, body, "inventorycategory.deleted", PluginName);
        }
    }

    async public void Debtor_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaDebtors.Debtor debtor = (JiwaFinancials.Jiwa.JiwaDebtors.Debtor)sender;
        string body = debtor.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Debtor&gt;();

        Webhook(debtor.Manager, body, (debtor.InsertFlag) ? "debtor.created" : (debtor.DeleteFlag) ? "debtor.deleted" : "debtor.updated", PluginName);
    }
    
    async public void DebtorClassification_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification debtorClassification = (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification)sender;
        string body = debtorClassification.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Classification.DebtorClassification&gt;();

        Webhook(debtorClassification.Manager, body, (debtorClassification.InsertFlag) ? "debtorclassification.created" : (debtorClassification.DeleteFlag) ? "debtorclassification.deleted" : "debtorclassification.updated", PluginName);
    }

    async public void DebtorCategories_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories debtorCategories = (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories)sender;

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category1 category in debtorCategories.Category1Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category1&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "debtorcategory.created" : "debtorcategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category2 category in debtorCategories.Category2Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category2&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "debtorcategory.created" : "debtorcategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category3 category in debtorCategories.Category3Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category3&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "debtorcategory.created" : "debtorcategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category4 category in debtorCategories.Category4Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category4&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "debtorcategory.created" : "debtorcategory.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category5 category in debtorCategories.Category5Collection.Cast&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category5&gt;().Where(cat =&gt; cat.ChangeFlag || cat.InsertFlag))
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, (category.InsertFlag) ? "debtorcategory.created" : "debtorcategory.updated", PluginName);
        }

        // Handle deletes - these will still be in the deleted collections at SaveEnd
        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category1 category in debtorCategories.Category1Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, "debtorcategory.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category2 category in debtorCategories.Category2Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, "debtorcategory.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category3 category in debtorCategories.Category3Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, "debtorcategory.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category4 category in debtorCategories.Category4Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, "debtorcategory.deleted", PluginName);
        }
        foreach (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Category5 category in debtorCategories.Category5Collection)
        {
            string body = category.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            Webhook(category.Manager, body, "debtorcategory.deleted", PluginName);
        }
    }

    async public void Creditor_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaCreditors.Creditor creditor = (JiwaFinancials.Jiwa.JiwaCreditors.Creditor)sender;
        string body = creditor.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Creditor&gt;();

        Webhook(creditor.Manager, body, (creditor.InsertFlag) ? "creditor.created" : (creditor.DeleteFlag) ? "creditor.deleted" : "creditor.updated", PluginName);
    }

    async public void CreditorClassification_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification creditorClassification = (JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification)sender;
        string body = creditorClassification.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Classification.CreditorClassification&gt;();

        Webhook(creditorClassification.Manager, body, (creditorClassification.InsertFlag) ? "creditorclassification.created" : (creditorClassification.DeleteFlag) ? "creditorclassification.deleted" : "creditorclassification.updated", PluginName);
    }

    async public void PurchaseOrder_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = (JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder)sender;
        string body = purchaseOrder.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder&gt;();

        Webhook(purchaseOrder.Manager, body, (purchaseOrder.InsertFlag) ? "purchaseorder.created" : (purchaseOrder.DeleteFlag) ? "purchaseorder.deleted" : "purchaseorder.updated", PluginName);
    }
	
	#region "Purchase Invoices"
    async public void PurchaseInvoice_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = (JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice)sender;
        string body = purchaseInvoice.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice&gt;();

        await Webhook(purchaseInvoice.Manager, body, (purchaseInvoice.InsertFlag) ? "purchaseinvoice.created" : (purchaseInvoice.DeleteFlag) ? "purchaseinvoice.deleted" : "purchaseinvoice.updated", PluginName);
    }
	#endregion	

    async public void TaxRates_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates taxRates = (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates)sender;

        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesOUT.Cast&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate&gt;().Where(tx =&gt; tx.ChangeFlag || tx.InsertFlag) )
        {            
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRate.Manager, body, (taxRate.InsertFlag) ? "taxrate.created" : "taxrate.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesIN.Cast&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate&gt;().Where(tx =&gt; tx.ChangeFlag || tx.InsertFlag))
        {
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRate.Manager, body, (taxRate.InsertFlag) ? "taxrate.created" : "taxrate.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesAdjIN.Cast&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate&gt;().Where(tx =&gt; tx.ChangeFlag || tx.InsertFlag))
        {
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRate.Manager, body, (taxRate.InsertFlag) ? "taxrate.created" : "taxrate.updated", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesAdjOUT.Cast&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate&gt;().Where(tx =&gt; tx.ChangeFlag || tx.InsertFlag))
        {
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRate.Manager, body, (taxRate.InsertFlag) ? "taxrate.created" : "taxrate.updated", PluginName);
        }

        // Handle deletes - these will still be in the deleted collections at SaveEnd
        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesOUT.DeletedCollection)
        {
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRates.Manager, body, "taxrate.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesIN.DeletedCollection)
        {
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRates.Manager, body, "taxrate.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesAdjOUT.DeletedCollection)
        {
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRates.Manager, body, "taxrate.deleted", PluginName);
        }

        foreach (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRate taxRate in taxRates.GSTRatesAdjIN.DeletedCollection)
        {
            string body = taxRate.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;();
            Webhook(taxRates.Manager, body, "taxrate.deleted", PluginName);
        }
    }
		
	async public void BookIn_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn bookIn = (JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn)sender;
        string body = bookIn.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn&gt;();

        Webhook(bookIn.Manager, body, (bookIn.InsertFlag) ? "bookin.created" : "bookin.updated", PluginName);
    }
	
	async public void Shipment_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = (JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment)sender;
        string body = Shipment.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;();

        Webhook(Shipment.Manager, body, (Shipment.InsertFlag) ? "shipment.created" : "shipment.updated", PluginName);
    }
	
    async public void GoodsReceivedNote_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = (JiwaFinancials.Jiwa.JiwaInvReceival.Receival)sender;
        string body = goodsReceivedNote.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;();

        Webhook(goodsReceivedNote.Manager, body, (goodsReceivedNote.InsertFlag) ? "goodsreceivednote.created" : "goodsreceivednote.updated", PluginName);
    }	
	
	async public void SalesQuote_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)sender;
        string body = salesQuote.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote&gt;();

        Webhook(salesQuote.Manager, body, (salesQuote.InsertFlag) ? "salesquote.created" : "salesquote.updated", PluginName);
    }	
	
	async public void WarehouseTransfer_SaveEnd(object sender, System.EventArgs e)
    {
        JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransfer = (JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer)sender;
		
		if(warehouseTransfer.TransferMode == JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward)
		{
	        string body = warehouseTransfer.WarehouseTransferInDTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn&gt;();
	        Webhook(warehouseTransfer.Manager, body, (warehouseTransfer.InsertFlag) ? "warehousetransferin.created" : "warehousetransferin.updated", PluginName);			
		}
		else
		{
	        string body = warehouseTransfer.WarehouseTransferOutDTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut&gt;();
	        Webhook(warehouseTransfer.Manager, body, (warehouseTransfer.InsertFlag) ? "warehousetransferout.created" : "warehousetransferout.updated", PluginName);			
		}
    }	

	#region "Payment Types"
	async public void PaymentTypes_SaveEnd(object sender, System.EventArgs e)
    {
		JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection paymentTypes = (JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection)sender;				
		foreach (JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType paymentType in paymentTypes.Cast&lt;JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType&gt;().Where(x =&gt; x.ChangeFlag || x.InsertFlag))
        {
            string body = paymentType.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt;();
            await Webhook(paymentType.Manager, body, (paymentType.InsertFlag) ? "paymenttype.created" : "paymenttype.updated", PluginName);
        }
		
		 // Handle deletes - these will still be in the deleted collections at SaveEnd
        foreach (JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType paymentType in paymentTypes.DeletedCollection)
        {
            string body = paymentType.DTO_Serialise().ToJson&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt;();
            await Webhook(paymentType.Manager, body, "paymenttype.deleted", PluginName);
        }
	}
	#endregion
	
	static async public System.Threading.Tasks.Task Webhook(JiwaFinancials.Jiwa.JiwaApplication.Manager Manager, string body, string eventName, string PluginName)
	{		
		string url = Manager.Database.ReadSysData(PluginName, "WebhooksHostURL", "").ToString();
		string clientKey = Manager.Database.ReadSysData(PluginName, "WebhooksClientKey", "").ToString();
				
		if (url.Length &gt; 0)
		{
			try
			{				
				ServiceStack.JsonServiceClient client = new ServiceStack.JsonServiceClient(url);								
				client.Headers.Add("ClientKey", clientKey);				
				await client.PostAsync&lt;IReturnVoid&gt;(new JiwaFinancials.Jiwa.JiwaServiceModel.WebhooksEventsPOSTRequest() { EventName = eventName, Body = body });				
			}
			catch (System.Exception ex)
			{				
				// Don't throw if the above fails - we don't want to stop the user continuing on if there was a problem with the REST API, but we do want to try to insert into the message queue table so when the service comes up it knows about these items it missed
				string sql = @"INSERT INTO SY_WebhookMessage(RecID, SY_WebhookSubscription_RecID, Body, ItemNo, Status, LastSavedDateTime, AddedDateTime, Retries)
						SELECT NewID(), SY_WebhookSubscription.RecID, @Body, 
						COALESCE(QueueTable.MaximumItemNo, 0) + ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), 
						0, SYSUTCDATETIME(), SYSUTCDATETIME(), 0
						FROM SY_WebhookSubscription
						CROSS JOIN (SELECT MAX(ItemNo) AS MaximumItemNo FROM SY_WebhookMessage) QueueTable
						WHERE EventName = @EventName
						ORDER BY SY_WebhookSubscription.ItemNo";
				
				var dbFactory = new OrmLiteConnectionFactory(Manager.Database.ConnectionString, ServiceStack.OrmLite.SqlServer2012Dialect.Provider);
				using (var db = dbFactory.Open())
				{				
					db.ExecuteSql(sql, new {Body = body, EventName = eventName} );
				}
				
			}
		}
	}
}
#endregion

#region "ApplicationManagerPlugin - Webhooks"
public class ApplicationManagerPlugin : System.MarshalByRefObject, JiwaFinancials.Jiwa.JiwaApplication.IJiwaApplicationManagerPlugin
{
    public override object InitializeLifetimeService()
    {
        // returning null here will prevent the lease manager
        // from deleting the Object.
        return null;
    }

    public void Setup(JiwaFinancials.Jiwa.JiwaApplication.Plugin.Plugin Plugin)
    {
		Plugin.Manager.StockLevelChanged += delegate(string InventoryID, string IN_LogicalID) 
													   {  
													        StockLevelChanged(Plugin.Manager, InventoryID, IN_LogicalID, Plugin);
													   };
    }
	
	public void StockLevelChanged(JiwaFinancials.Jiwa.JiwaApplication.Manager Manager, string InventoryID, string IN_LogicalID, JiwaFinancials.Jiwa.JiwaApplication.Plugin.Plugin Plugin)
	{
		object dto = new { InventoryID = InventoryID, IN_LogicalID = IN_LogicalID};
		BusinessLogicPlugin.Webhook(Manager, dto.ToJson(), "inventory.stocklevel", Plugin.Name);
	}
}
#endregion
}

namespace JiwaFinancials.Jiwa.JiwaServiceModel
{
    public class RESTAPIPlugin : System.MarshalByRefObject, JiwaFinancials.Jiwa.JiwaApplication.IJiwaRESTAPIPlugin
    {
        public ServiceStack.AutoQueryFeature AutoQueryFeature;

        #region "Static properties"
        private static ConcurrentDictionary&lt;string, JiwaFinancials.Jiwa.JiwaApplication.Manager&gt; _jiwaSessionDictionary = new ConcurrentDictionary&lt;string, JiwaFinancials.Jiwa.JiwaApplication.Manager&gt;();

        public static ConcurrentDictionary&lt;string, JiwaFinancials.Jiwa.JiwaApplication.Manager&gt; JiwaSessionDictionary
        {
            get
            {
                return _jiwaSessionDictionary;
            }
        }
        #endregion

        #region "Static properties for Webhooks functionality"

        private static List&lt;SY_WebhookSubscriber&gt; _webhookSubscribers;
        private static List&lt;SY_WebhookSubscription&gt; _webhookSubscriptions;
        private static List&lt;SY_WebhookSubscriptionRequestHeader&gt; _webhookSubscriptionRequestHeaders;
        private static List&lt;SY_WebhookMessage&gt; _webhookMessages;
        private static List&lt;WebHookEvent&gt; _webHookEvents;
        private static string _hostURL;
        private static int _retryInterval;
        private static int _maxRetries;
        private static string _clientKey;
        private static WebhookMessagesTimer _timer;
        private static ServiceStack.ServiceStackHost _appHost;

        public static List&lt;SY_WebhookSubscriber&gt; WebhookSubscribers
        {
            get
            {
                return _webhookSubscribers;
            }
        }

        public static List&lt;SY_WebhookSubscription&gt; WebhookSubscriptions
        {
            get
            {
                return _webhookSubscriptions;
            }
        }

        public static List&lt;SY_WebhookSubscriptionRequestHeader&gt; WebhookSubscriptionRequestHeaders
        {
            get
            {
                return _webhookSubscriptionRequestHeaders;
            }
        }

        public static List&lt;SY_WebhookMessage&gt; WebhookMessages
        {
            get
            {
                return _webhookMessages;
            }
        }

        public static List&lt;WebHookEvent&gt; WebHookEvents
        {
            get
            {
                return _webHookEvents;
            }
        }

        public static string HostURL
        {
            get
            {
                return _hostURL;
            }
        }

        public static int RetryInterval
        {
            get
            {
                return _retryInterval;
            }
        }

        public static int MaxRetries
        {
            get
            {
                return _maxRetries;
            }
        }

        public static string ClientKey
        {
            get
            {
                return _clientKey;
            }
        }

        public static WebhookMessagesTimer Timer
        {
            get
            {
                return _timer;
            }
        }

        public static ServiceStack.ServiceStackHost AppHost
        {
            get
            {
                return _appHost;
            }
        }
        #endregion

        #region "Configuration"					
        public void Configure(JiwaFinancials.Jiwa.JiwaApplication.Plugin.Plugin Plugin, ServiceStack.ServiceStackHost AppHost, Funq.Container Container, JiwaApplication.Manager JiwaApplicationManager)
        {
            _appHost = AppHost;
            int sessionExpiryInMinutes = int.Parse(JiwaApplicationManager.Database.ReadSysData("REST API", "SessionExpiryInMinutes", "5").ToString());
            bool debugMode = Convert.ToBoolean(JiwaApplicationManager.Database.ReadSysData("REST API", "DebugMode", "0").ToString());
            int autoQueryMaxLimit = int.Parse(JiwaApplicationManager.Database.ReadSysData("REST API", "AutoQueryMaxLimit", "200").ToString());

            #region "Exception Mapping"
            // Map some Jiwa exceptions to the appropriate HTTP status code
            AppHost.Config.MapExceptionToStatusCode.Add(typeof(JiwaApplication.Exceptions.RecordNotFoundException), 404);
            AppHost.Config.MapExceptionToStatusCode.Add(typeof(JiwaApplication.Exceptions.LicencingException), 403);
            AppHost.Config.MapExceptionToStatusCode.Add(typeof(JiwaApplication.Exceptions.PermissionDeniedException), 403);
            AppHost.Config.MapExceptionToStatusCode.Add(typeof(JiwaApplication.Exceptions.ConcurrencyConflictException), 409);
            AppHost.Config.MapExceptionToStatusCode.Add(typeof(JiwaApplication.Exceptions.RecordInUseException), 409);
            AppHost.Config.MapExceptionToStatusCode.Add(typeof(JiwaFinancials.Jiwa.JiwaODBC.Exceptions.BadLoginException), 401);
            #endregion

            #region "Add-ins"
            // Add some swagger
            //AppHost.Plugins.Add(new ServiceStack.Api.Swagger.SwaggerFeature());

            // OpenAPI					
            AppHost.Plugins.Add(new ServiceStack.Api.OpenApi.OpenApiFeature()
            {
                OperationFilter = (verb, operation) =&gt;
                {
                    operation.Consumes = new[] { MimeTypes.FormUrlEncoded, MimeTypes.Json, MimeTypes.Xml }.ToList();
                    operation.Produces = new[] { MimeTypes.Json, MimeTypes.Xml }.ToList();
                },

                ApiDeclarationFilter = api =&gt;
                {
                    api.Consumes = new[] { MimeTypes.FormUrlEncoded, MimeTypes.Json, MimeTypes.Xml }.ToList();
                    api.Produces = new[] { MimeTypes.Json, MimeTypes.Xml }.ToList();

                    // Add a header in each request for the SwaggerUI
                    foreach (var path in api.Paths)
                    {
                        path.Value.Parameters.Add(new ServiceStack.Api.OpenApi.Specification.OpenApiParameter
                        {
                            Type = ServiceStack.Api.OpenApi.Specification.OpenApiType.Boolean,
                            Name = "jiwa-stateful",
                            Description = "Stateful indicator",
                            In = "header",
                            Required = false
                        });
                    }
                }
            });

            // Add AutoQuery plugin
            AppHost.Plugins.Add(new AutoQueryFeature() { EnableAutoQueryViewer = true, MaxLimit = autoQueryMaxLimit });

            AppHost.Plugins.Add(new AutoQueryDataFeature { MaxLimit = autoQueryMaxLimit });

            // Add AutoQuery Viewer plugin
            AppHost.Plugins.Add(new ServiceStack.Admin.AdminFeature());

            // Postman
            AppHost.Plugins.Add(new PostmanFeature());

            // Our custom plugin to add code generation links
            AppHost.Plugins.Add(new CodeGenerationLinksPlugin());

            // Request logging			
            if (debugMode)
                AppHost.Plugins.Add(new RequestLogsFeature() { RequestLogger = new CsvRequestLogger(), LimitToServiceRequests = true });

            // Razor views
            AppHost.Plugins.Add(new ServiceStack.Razor.RazorFormat());

            // Allow Cross Origin Requests
            AppHost.Plugins.Add(new ServiceStack.CorsFeature());
            #endregion

            #region "ServiceStack Config"					
            //When using the API, null or default values should be excluded
            ServiceStack.Text.JsConfig.ExcludeDefaultValues = true;

            //Make guids be hyphenated and lowercase
            //We force to lowercase because any Guid generated in .NET will be lowercase
            ServiceStack.Text.JsConfig&lt;Guid&gt;.SerializeFn = guid =&gt; guid.ToString("D").ToLower();
            ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.DateHandler.ISO8601;

            //Change the default ServiceStack configuration
            Feature disableFeatures = Feature.Jsv | Feature.Soap;
            AppHost.SetConfig(new HostConfig
            {
                EnableFeatures = Feature.All.Remove(disableFeatures), //all formats except for JSV and SOAP
                DebugMode = debugMode, //Show StackTraces in service responses during development
                WriteErrorsToResponse = true, //Disable exception handling
                DefaultContentType = "application/json", //Change default content type
                AllowJsonpRequests = true //Enable JSONP requests                
            });
            #endregion

            #region "Authentication"
            //If we mess with service routes then /auth/logout stops working!
            //The ServiceRoutes are set to "/user/login" and nothing else (by default you also get a "/authenticate" - we don't want messyness).
            var serviceRoutes = new Dictionary&lt;Type, string[]&gt;();
            serviceRoutes.Add(typeof(ServiceStack.Auth.AuthenticateService), new[] { "/auth" });

            //Define the authentication mechanism.  "JiwaAuthProviderSelfHosted" inherits "CredentialsAuthProvider" and overrides TryAuthenticate().
            var authFeature = new AuthFeature(() =&gt; new AuthUserSession(),
							new IAuthProvider[] {
                            new JiwaAuthProvider(AuthenticateService.CredentialsProvider) { SessionExpiry = TimeSpan.FromMinutes(sessionExpiryInMinutes), AppHost = AppHost, StartupManager = JiwaApplicationManager },
							new JiwaApiKeyAuthProvider() { SessionCacheDuration = TimeSpan.FromMinutes(sessionExpiryInMinutes), RequireSecureConnection = false, AppHost = AppHost, AllowInHttpParams = true, StartupManager = JiwaApplicationManager }
                    })
            { IncludeAssignRoleServices = false, ServiceRoutes = serviceRoutes, HtmlRedirect = "/login" };

            AppHost.Plugins.Add(authFeature);
            #endregion

            #region "Global Filters"
            #region "Request Filters"

            // Add a global request filter for permissions
            AppHost.GlobalRequestFilters.Add((req, res, requestDto) =&gt; {                

				AuthUserSession session = (AuthUserSession)req.GetSession();    				
				// Now find the entry in the JiwaSessionDictionary for our session
				JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
                RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

                // if we are authenticated, check permissions
                if (manager != null &amp;&amp; manager.Staff != null)
                {
                    if (req.GetRoute() == null)
                    {
                        throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("Request GetRoute is empty for '{0}' on route '{1}'", manager.Staff.Username, req.Verb));
                    }
                    JiwaFinancials.Jiwa.JiwaApplication.Security.UserGroup.AccessLevels permission = manager.Staff.GetRESTAPIPermission(req.GetRoute().Path, req.Verb);
                    if (permission != JiwaFinancials.Jiwa.JiwaApplication.Security.UserGroup.AccessLevels.Allow)
                    {
                        throw new UnauthorizedAccessException(String.Format("User '{0}' has no permission for '{1}' on route '{2}'. Set permissions in the Jiwa user group.", manager.Staff.Username, req.Verb, req.GetRoute().Path));
                    }                    
                }
            });	

            #region "Register API Key Request filter functions"
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderGETRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderGETRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderPOSTRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderPATCHRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderSAVERequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderSaveRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderABANDONRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderAbandonRequestFilter(req, res, dto); });

            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderLineGETRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderLineGETRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderLinePOSTRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderLinePOSTRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderLinePATCHRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderLinePATCHRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesOrderLineDELETERequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderLineDELETERequestFilter(req, res, dto); });

            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuoteGETRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteGETRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuotePOSTRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuotePATCHRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuoteSAVERequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteSaveRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuoteABANDONRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteAbandonRequestFilter(req, res, dto); });

            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuoteLineGETRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteLineGETRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuoteLinePOSTRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteLinePOSTRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuoteLinePATCHRequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteLinePATCHRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.SalesQuoteLineDELETERequest&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteLineDELETERequestFilter(req, res, dto); });

            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.Tables.SO_MainQuery&gt;((req, res, dto) =&gt; { DebtorAPIKeySO_MainQueryRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.Tables.v_Jiwa_SalesOrder_ListQuery&gt;((req, res, dto) =&gt; { DebtorAPIKeyv_Jiwa_SalesOrder_ListQueryRequestFilter(req, res, dto); });

            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.Tables.QO_MainQuery&gt;((req, res, dto) =&gt; { DebtorAPIKeyQO_MainQueryRequestFilter(req, res, dto); });
            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.Tables.v_Jiwa_SalesQuote_ListQuery&gt;((req, res, dto) =&gt; { DebtorAPIKeyv_Jiwa_SalesQuote_ListQueryRequestFilter(req, res, dto); });

            AppHost.RegisterTypedRequestFilter&lt;JiwaServiceModel.Tables.v_Jiwa_Debtor_Transactions_ListQuery&gt;((req, res, dto) =&gt; { DebtorAPIKeyv_Jiwa_Debtor_Transactions_ListQueryRequestFilter(req, res, dto); });            
            //v_Jiwa_Debtor_Transactions_List
            #endregion

            #endregion

            #region "Response Filters"					            
            // Add a global response filter for extending session each time a response is handled
            AppHost.GlobalResponseFilters.Add((req, res, responseDto) =&gt; {								
                var session = req.GetSession();                
                TimeSpan expiresIn = TimeSpan.FromMinutes(sessionExpiryInMinutes);
				
                if (session != null)
				{
					req.SaveSession(session, expiresIn);
					
					object apiKeyItem = null;
					
					if (req.Items.TryGetValue(Keywords.ApiKey, out apiKeyItem))
					{												
						if (apiKeyItem != null)
						{
							JiwaFinancials.Jiwa.JiwaServiceModel.Tables.v_APIKey apiKey = (JiwaFinancials.Jiwa.JiwaServiceModel.Tables.v_APIKey)apiKeyItem;
							req.GetCacheClient().CacheSet("key:sess:" + apiKey.KeyValue, session, expiresIn);
						}
					}					                    	
				}
            });

            // Add a global response filter for setting the http status codes automatically based on the request type.
            AppHost.GlobalResponseFilters.Add((req, res, responseDto) =&gt; {
                switch (req.Verb)
                {
                    case "GET":
                        res.StatusCode = (int)System.Net.HttpStatusCode.OK;
                        break;
                    case "POST":
                        res.StatusCode = (int)System.Net.HttpStatusCode.Created;
                        break;
                    case "PATCH":
                        res.StatusCode = (int)System.Net.HttpStatusCode.OK;
                        break;
                    case "DELETE":
                        res.StatusCode = (int)System.Net.HttpStatusCode.NoContent;
                        break;
                };
            });
			
			// Add a global reponse filter for session expiry
            AppHost.GlobalResponseFilters.Add((req, res, responseDto) =&gt; {                
				// find all expired and log off																	 				 
                ServiceStack.Caching.ICacheClient cache = HostContext.TryResolve&lt;ServiceStack.Caching.ICacheClient&gt;();
				
				// iterate through each Manager in the JiwaSessionDictionary and see if there is a corresponding session in the session cache
				foreach(System.Collections.Generic.KeyValuePair&lt;string, JiwaFinancials.Jiwa.JiwaApplication.Manager&gt; jiwaSession in RESTAPIPlugin.JiwaSessionDictionary)
				{
					AuthUserSession authSession = cache.Get&lt;AuthUserSession&gt;("urn:iauthsession:" + jiwaSession.Key);
					
					// If there is no match, perform a logoff and then remove the entry from the JiwaSessionDictionary
					if (authSession == null)
					{
						if (debugMode)
						{
							JiwaFinancials.Jiwa.JiwaServiceModel.Helper.EventLog.Log(String.Format("Expired Jiwa Session with id '{0}' is being logged off.", jiwaSession.Key), System.Diagnostics.EventLogEntryType.Information);
						}
						
                        jiwaSession.Value.LogOff();
						JiwaFinancials.Jiwa.JiwaApplication.Manager removedManager = null;
						RESTAPIPlugin.JiwaSessionDictionary.TryRemove(jiwaSession.Key, out removedManager);
					}
				}				
            });				
            
            #region "Register Debtor API Key response filter functions"
            AppHost.RegisterTypedResponseFilter&lt;JiwaServiceModel.Inventory.InventoryItem&gt;((req, res, dto) =&gt; { DebtorAPIKeyInventoryResponseFilter(req, res, dto); });
            AppHost.RegisterTypedResponseFilter&lt;JiwaServiceModel.SalesOrders.SalesOrder&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderResponseFilter(req, res, dto); });
            AppHost.RegisterTypedResponseFilter&lt;JiwaServiceModel.SalesOrders.SalesOrderLine&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesOrderLineResponseFilter(req, res, dto); });
            AppHost.RegisterTypedResponseFilter&lt;JiwaServiceModel.SalesQuotes.SalesQuote&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteResponseFilter(req, res, dto); });
            AppHost.RegisterTypedResponseFilter&lt;JiwaServiceModel.SalesQuotes.SalesQuoteLine&gt;((req, res, dto) =&gt; { DebtorAPIKeySalesQuoteLineResponseFilter(req, res, dto); });
            AppHost.RegisterTypedResponseFilter&lt;JiwaServiceModel.Debtors.Debtor&gt;((req, res, dto) =&gt; { DebtorAPIKeyDebtorResponseFilter(req, res, dto); });            
            #endregion

            #endregion
            #endregion

            #region "OrmLite Config"
            // Configure OrmLite                        
            Container.Register&lt;ServiceStack.Data.IDbConnectionFactory&gt;(new OrmLiteConnectionFactory(JiwaApplicationManager.Database.ConnectionString, ServiceStack.OrmLite.SqlServer2012Dialect.Provider));
            #endregion

            #region "Routes"																		
            #region "Auth"
            AppHost.RegisterService&lt;AuthServices&gt;();
            AppHost.Routes.Add(typeof(LogoutGetRequest), "/auth/logout", "GET", "Logs an authenticated user out.", "");
            #endregion
			
            #region "Bills"
			#region "{Main}"
            AppHost.RegisterService&lt;BillServices&gt;();
            AppHost.Routes.Add(typeof(BillGETRequest), "/Bills/{BillID}", "GET", "Retrieves a bill record.", "");
            AppHost.Routes.Add(typeof(BillPOSTRequest), "/Bills", "POST", "Creates a new bill record.", "");
            AppHost.Routes.Add(typeof(BillPATCHRequest), "/Bills/{BillID}", "PATCH", "Updates a bill record.", "");
			AppHost.Routes.Add(typeof(BillDELETERequest), "/Bills/{BillID}", "DELETE", "Deletes a bill record.", "");
            AppHost.Routes.Add(typeof(BillSAVERequest), "/Bills/{BillID}/Save", "GET", "Saves a stateful bill record.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful bill record exists.");
            AppHost.Routes.Add(typeof(BillABANDONRequest), "/Bills/{BillID}/Abandon", "DELETE", "Abandons a stateful bill record.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful bill record exists.");
			#endregion
			
            #region "Custom Fields"
            AppHost.RegisterService&lt;BillCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(BillCustomFieldsGETManyRequest), "/Bills/CustomFields", "GET", "Retrieves a list of bill custom fields.", "");
            AppHost.Routes.Add(typeof(BillCustomFieldGETRequest), "/Bills/CustomFields/{SettingID}", "GET", "Retrieves a bill custom field.", "");
            AppHost.Routes.Add(typeof(BillCustomFieldValuesGETManyRequest), "/Bills/{BillID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a bill record.", "");
            AppHost.Routes.Add(typeof(BillCustomFieldValueGETRequest), "/Bills/{BillID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a bill record custom field value.", "");
            AppHost.Routes.Add(typeof(BillCustomFieldValuePATCHRequest), "/Bills/{BillID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a bill record custom field value.", "");
            #endregion

            #region "Document Types"
            AppHost.RegisterService&lt;BillDocumentTypeServices&gt;();
            AppHost.Routes.Add(typeof(BillDocumentTypesGETManyRequest), "/Bills/DocumentTypes", "GET", "Retrieves a list of bill document types.", "");
            AppHost.Routes.Add(typeof(BillDocumentTypeGETRequest), "/Bills/DocumentTypes/{DocumentTypeID}", "GET", "Retrieves a bill document type.", "");
            AppHost.Routes.Add(typeof(BillDocumentTypePOSTRequest), "/Bills/DocumentTypes", "POST", "Creates a new bill document type.", "");
            AppHost.Routes.Add(typeof(BillDocumentTypePATCHRequest), "/Bills/DocumentTypes/{DocumentTypeID}", "PATCH", "Updates a bill document type.", "");
            AppHost.Routes.Add(typeof(BillDocumentTypeDELETERequest), "/Bills/DocumentTypes/{DocumentTypeID}", "DELETE", "Deletes a bill document type.", "");
            #endregion	
			
            #region "Documents"
            AppHost.RegisterService&lt;BillDocumentServices&gt;();
            AppHost.Routes.Add(typeof(BillDocumentsGETManyRequest), "/Bills/{BillID}/Documents", "GET", "Retrieves a list of bill record documents.", "");
            AppHost.Routes.Add(typeof(BillDocumentGETRequest), "/Bills/{BillID}/Documents/{DocumentID}", "GET", "Retrieves a bill record document.", "");
            AppHost.Routes.Add(typeof(BillDocumentPOSTRequest), "/Bills/{BillID}/Documents", "POST", "Appends a document to a bill record.", "");
            AppHost.Routes.Add(typeof(BillDocumentPATCHRequest), "/Bills/{BillID}/Documents/{DocumentID}", "PATCH", "Updates a bill record document.", "");
            AppHost.Routes.Add(typeof(BillDocumentDELETERequest), "/Bills/{BillID}/Documents/{DocumentID}", "DELETE", "Deletes a bill record document.", "");
            #endregion
			
            #region "Input Custom Fields"
            AppHost.RegisterService&lt;BillInputCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(BillInputCustomFieldsGETManyRequest), "/Bills/Inputs/CustomFields", "GET", "Retrieves a list of bill input custom fields.", "");
            AppHost.Routes.Add(typeof(BillInputCustomFieldGETRequest), "/Bills/Inputs/CustomFields/{SettingID}", "GET", "Retrieves a bill input custom field.", "");
            AppHost.Routes.Add(typeof(BillInputCustomFieldValuesGETManyRequest), "/Bills/{BillID}/Stages/{StageID}/Inputs/{InputID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a bill input.", "");
            AppHost.Routes.Add(typeof(BillInputCustomFieldValueGETRequest), "/Bills/{BillID}/Stages/{StageID}/Inputs/{InputID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a bill input custom field value.", "");
            AppHost.Routes.Add(typeof(BillInputCustomFieldValuePATCHRequest), "/Bills/{BillID}/Stages/{StageID}/Inputs/{InputID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a bill input custom field value.", "");
            #endregion	

            #region "Inputs"
            AppHost.RegisterService&lt;BillInputServices&gt;();
            AppHost.Routes.Add(typeof(BillInputsGETManyRequest), "/Bills/{BillID}/Stages/{StageID}/Inputs", "GET", "Retrieves inputs for a bill stage.", "");
            AppHost.Routes.Add(typeof(BillInputGETRequest), "/Bills/{BillID}/Stages/{StageID}/Inputs/{InputID}", "GET", "Retrieves an input for a bill stage", "");
            AppHost.Routes.Add(typeof(BillInputPOSTRequest), "/Bills/{BillID}/Stages/{StageID}/Inputs", "POST", "Adds an input to a bill stage", "");
            AppHost.Routes.Add(typeof(BillInputPATCHRequest), "/Bills/{BillID}/Stages/{StageID}/Inputs/{InputID}", "PATCH", "Updates an input for a bill stage", "");
            AppHost.Routes.Add(typeof(BillInputDELETERequest), "/Bills/{BillID}/Stages/{StageID}/Inputs/{InputID}", "DELETE", "Deletes an input from a bill stage", "");
            #endregion

			#region "Instruction Custom Fields"
            AppHost.RegisterService&lt;BillInstructionCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(BillInstructionCustomFieldsGETManyRequest), "/Bills/Instructions/CustomFields", "GET", "Retrieves a list of bill instruction custom fields.", "");
            AppHost.Routes.Add(typeof(BillInstructionCustomFieldGETRequest), "/Bills/Instructions/CustomFields/{SettingID}", "GET", "Retrieves a bill instruction custom field.", "");
            AppHost.Routes.Add(typeof(BillInstructionCustomFieldValuesGETManyRequest), "/Bills/{BillID}/Stages/{StageID}/Instructions/{InstructionID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a bill instruction.", "");
            AppHost.Routes.Add(typeof(BillInstructionCustomFieldValueGETRequest), "/Bills/{BillID}/Stages/{StageID}/Instructions/{InstructionID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a bill instruction custom field value.", "");
            AppHost.Routes.Add(typeof(BillInstructionCustomFieldValuePATCHRequest), "/Bills/{BillID}/Stages/{StageID}/Instructions/{InstructionID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a bill instruction custom field value.", "");
            #endregion	

            #region "Instructions"
            AppHost.RegisterService&lt;BillInstructionServices&gt;();
            AppHost.Routes.Add(typeof(BillInstructionsGETManyRequest), "/Bills/{BillID}/Stages/{StageID}/Instructions", "GET", "Retrieves a list of instructions for a bill stage.", "");
            AppHost.Routes.Add(typeof(BillInstructionGETRequest), "/Bills/{BillID}/Stages/{StageID}/Instructions/{InstructionID}", "GET", "Retrieves an instruction for a bill stage.", "");
            AppHost.Routes.Add(typeof(BillInstructionPOSTRequest), "/Bills/{BillID}/Stages/{StageID}/Instructions", "POST", "Adds an instruction to a bill stage.", "");
            AppHost.Routes.Add(typeof(BillInstructionPATCHRequest), "/Bills/{BillID}/Stages/{StageID}/Instructions/{InstructionID}", "PATCH", "Updates an instruction for a bill stage.", "");
            AppHost.Routes.Add(typeof(BillInstructionDELETERequest), "/Bills/{BillID}/Stages/{StageID}/Instructions/{InstructionID}", "DELETE", "Deletes an instruction from a bill stage.", "");
            #endregion

            #region "Note Types"
            AppHost.RegisterService&lt;BillNoteTypeServices&gt;();
            AppHost.Routes.Add(typeof(BillNoteTypesGETManyRequest), "/Bills/NoteTypes", "GET", "Retrieves a list of bill note types.", "");
            AppHost.Routes.Add(typeof(BillNoteTypeGETRequest), "/Bills/NoteTypes/{NoteTypeID}", "GET", "Retrieves a bill note type.", "");
            AppHost.Routes.Add(typeof(BillNoteTypePOSTRequest), "/Bills/NoteTypes", "POST", "Creates a new bill note type.", "");
            AppHost.Routes.Add(typeof(BillNoteTypePATCHRequest), "/Bills/NoteTypes/{NoteTypeID}", "PATCH", "Updates a bill note type.", "");
            AppHost.Routes.Add(typeof(BillNoteTypeDELETERequest), "/Bills/NoteTypes/{NoteTypeID}", "DELETE", "Deletes a bill note type.", "");
            #endregion

            #region "Notes"
            AppHost.RegisterService&lt;BillNoteServices&gt;();
            AppHost.Routes.Add(typeof(BillNotesGETManyRequest), "/Bills/{BillID}/Notes", "GET", "Retrieves a list of bill record notes.", "");
            AppHost.Routes.Add(typeof(BillNoteGETRequest), "/Bills/{BillID}/Notes/{NoteID}", "GET", "Retrieves a bill record note.", "");
            AppHost.Routes.Add(typeof(BillNotePOSTRequest), "/Bills/{BillID}/Notes", "POST", "Appends a note to a bill record.", "");
            AppHost.Routes.Add(typeof(BillNotePATCHRequest), "/Bills/{BillID}/Notes/{NoteID}", "PATCH", "Updates a bill record note.", "");
            AppHost.Routes.Add(typeof(BillNoteDELETERequest), "/Bills/{BillID}/Notes/{NoteID}", "DELETE", "Deletes a bill record note.", "");
            #endregion			
			
            #region "Output Custom Fields"
            AppHost.RegisterService&lt;BillOutputCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(BillOutputCustomFieldsGETManyRequest), "/Bills/Outputs/CustomFields", "GET", "Retrieves a list of bill output custom fields.", "");
            AppHost.Routes.Add(typeof(BillOutputCustomFieldGETRequest), "/Bills/Outputs/CustomFields/{SettingID}", "GET", "Retrieves a bill output custom field.", "");
            AppHost.Routes.Add(typeof(BillOutputCustomFieldValuesGETManyRequest), "/Bills/{BillID}/Outputs/{OutputID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a bill output.", "");
            AppHost.Routes.Add(typeof(BillOutputCustomFieldValueGETRequest), "/Bills/{BillID}/Outputs/{OutputID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a bill output custom field value.", "");
            AppHost.Routes.Add(typeof(BillOutputCustomFieldValuePATCHRequest), "/Bills/{BillID}/Outputs/{OutputID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a bill output custom field value.", "");
            #endregion	

			#region "Outputs"
            AppHost.RegisterService&lt;BillOutputServices&gt;();
            AppHost.Routes.Add(typeof(BillOutputsGETManyRequest), "/Bills/{BillID}/Outputs", "GET", "Retrieves a list of bill outputs.", "");
            AppHost.Routes.Add(typeof(BillOutputGETRequest), "/Bills/{BillID}/Outputs/{OutputID}", "GET", "Retrieves a bill output.", "");
            AppHost.Routes.Add(typeof(BillOutputPOSTRequest), "/Bills/{BillID}/Outputs", "POST", "Appends a output to a bill record.", "");
            AppHost.Routes.Add(typeof(BillOutputPATCHRequest), "/Bills/{BillID}/Outputs/{OutputID}", "PATCH", "Updates a bill output.", "");
            AppHost.Routes.Add(typeof(BillOutputDELETERequest), "/Bills/{BillID}/Outputs/{OutputID}", "DELETE", "Deletes a bill output.", "");
            #endregion

            #region "Stage Custom Fields"
            AppHost.RegisterService&lt;BillStageCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(BillStageCustomFieldsGETManyRequest), "/Bills/Stages/CustomFields", "GET", "Retrieves a list of bill stage custom fields.", "");
            AppHost.Routes.Add(typeof(BillStageCustomFieldGETRequest), "/Bills/Stages/CustomFields/{SettingID}", "GET", "Retrieves a bill stage custom field.", "");
            AppHost.Routes.Add(typeof(BillStageCustomFieldValuesGETManyRequest), "/Bills/{BillID}/Stages/{StageID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a bill stage.", "");
            AppHost.Routes.Add(typeof(BillStageCustomFieldValueGETRequest), "/Bills/{BillID}/Stages/{StageID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a bill stage custom field value.", "");
            AppHost.Routes.Add(typeof(BillStageCustomFieldValuePATCHRequest), "/Bills/{BillID}/Stages/{StageID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a bill stage custom field value.", "");
            #endregion		
			
            #region "Stages"
            AppHost.RegisterService&lt;BillStageServices&gt;();
            AppHost.Routes.Add(typeof(BillStagesGETManyRequest), "/Bills/{BillID}/Stages", "GET", "Retrieves a list of bill stages.", "");
            AppHost.Routes.Add(typeof(BillStageGETRequest), "/Bills/{BillID}/Stages/{StageID}", "GET", "Retrieves a bill stage.", "");
            AppHost.Routes.Add(typeof(BillStagePOSTRequest), "/Bills/{BillID}/Stages", "POST", "Appends a stage to a bill record.", "");
			AppHost.Routes.Add(typeof(BillStagePATCHRequest), "/Bills/{BillID}/Stages/{StageID}", "PATCH", "Updates a bill stage.", "");
            AppHost.Routes.Add(typeof(BillStageDELETERequest), "/Bills/{BillID}/Stages/{StageID}", "DELETE", "Deletes a bill record stage.", "");			
            #endregion
            #endregion				

            #region "Carriers"
            #region "{Main}"
            AppHost.RegisterService&lt;CarrierServices&gt;();
            AppHost.Routes.Add(typeof(CarrierGETRequest), "/Carriers/{CarrierID}", "GET", "Retrieves a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierPOSTRequest), "/Carriers", "POST", "Creates a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierPATCHRequest), "/Carriers/{CarrierID}", "PATCH", "Updates a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierDELETERequest), "/Carriers/{CarrierID}", "DELETE", "Deletes a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierSAVERequest), "/Carriers/Save", "GET", "Saves a stateful carrier.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful carrier exists.");
            AppHost.Routes.Add(typeof(CarrierABANDONRequest), "/Carriers/Abandon", "DELETE", "Abandons a stateful carrier.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful carrier exists.");
            #endregion

            #region "Carrier Services"
            AppHost.RegisterService&lt;CarrierServiceServices&gt;();
            AppHost.Routes.Add(typeof(CarrierServiceGETRequest), "/Carriers/{CarrierID}/Services/{ServiceID}", "GET", "Retrieves a service from a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierServicesGETManyRequest), "/Carriers/{CarrierID}/Services", "GET", "Retrieves a list of services for a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierServicePOSTRequest), "/Carriers/{CarrierID}/Services", "POST", "Appends a service to a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierServicePATCHRequest), "/Carriers/{CarrierID}/Services/{ServiceID}", "PATCH", "Updates a carrier service.", "");
            AppHost.Routes.Add(typeof(CarrierServiceDELETERequest), "/Carriers/{CarrierID}/Services/{ServiceID}", "DELETE", "Deletes a carrier service.", "");
            #endregion

            #region "Freight Descriptions"
            AppHost.RegisterService&lt;CarrierFreightDescriptionServices&gt;();
            AppHost.Routes.Add(typeof(CarrierFreightDescriptionGETRequest), "/Carriers/{CarrierID}/FreightDescriptions/{FreightDescriptionID}", "GET", "Retrieves a carrier freight description.", "");
            AppHost.Routes.Add(typeof(CarrierFreightDescriptionsGETManyRequest), "/Carriers/{CarrierID}/FreightDescriptions", "GET", "Retrieves a list of carrier freight descriptions.", "");
            AppHost.Routes.Add(typeof(CarrierFreightDescriptionPOSTRequest), "/Carriers/{CarrierID}/FreightDescriptions", "POST", "Appends a freight description to a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierFreightDescriptionPATCHRequest), "/Carriers/{CarrierID}/FreightDescriptions/{FreightDescriptionID}", "PATCH", "Updates a freight description for a carrier.", "");
            AppHost.Routes.Add(typeof(CarrierFreightDescriptionDELETERequest), "/Carriers/{CarrierID}/FreightDescriptions/{FreightDescriptionID}", "DELETE", "Deletes a freight description from a carrier.", "");
            #endregion
            #endregion

            #region "Creditors"
            #region "{Main}"
            AppHost.RegisterService&lt;CreditorServices&gt;();
            AppHost.Routes.Add(typeof(CreditorGETRequest), "/Creditors/{CreditorID}", "GET", "Retrieves a creditor.", "");
            AppHost.Routes.Add(typeof(CreditorPOSTRequest), "/Creditors", "POST", "Creates a creditor.", "");
            AppHost.Routes.Add(typeof(CreditorPATCHRequest), "/Creditors/{CreditorID}", "PATCH", "Updates a creditor.", "");
            AppHost.Routes.Add(typeof(CreditorDELETERequest), "/Creditors/{CreditorID}", "DELETE", "Deletes a creditor.", "");
            AppHost.Routes.Add(typeof(CreditorSAVERequest), "/Creditors/Save", "GET", "Saves a stateful creditor.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful creditor exists.");
            AppHost.Routes.Add(typeof(CreditorABANDONRequest), "/Creditors/Abandon", "DELETE", "Abandons a stateful creditor.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful creditor exists.");
            #endregion

            #region "Classification"
            AppHost.RegisterService&lt;CreditorClassificationServices&gt;();
            AppHost.Routes.Add(typeof(CreditorClassificationGETRequest), "/Creditors/Classifications/{ClassificationID}", "GET", "Retrieves a creditor classification.", "");
            AppHost.Routes.Add(typeof(CreditorClassificationPOSTRequest), "/Creditors/Classifications", "POST", "Creates a creditor classification.", "");
            AppHost.Routes.Add(typeof(CreditorClassificationPATCHRequest), "/Creditors/Classifications/{ClassificationID}", "PATCH", "Updates a creditor classification.", "");
            AppHost.Routes.Add(typeof(CreditorClassificationDELETERequest), "/Creditors/Classifications/{ClassificationID}", "DELETE", "Deletes a creditor classification.", "");
            AppHost.Routes.Add(typeof(CreditorClassificationSAVERequest), "/Creditors/Classifications/Save", "GET", "Saves a stateful creditor classification.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful creditor classification exists.");
            AppHost.Routes.Add(typeof(CreditorClassificationABANDONRequest), "/Creditors/Classifications/Abandon", "DELETE", "Abandons a stateful creditor classification.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful creditor classification exists.");
            #endregion

            #region "Warehouses"
            AppHost.RegisterService&lt;CreditorWarehouseAddressServices&gt;();
            AppHost.Routes.Add(typeof(CreditorWarehouseAddressGETRequest), "/Creditors/{CreditorID}/WarehouseAddress/{WarehouseAddressID}", "GET", "Retrieves a creditor warehouse address.", "");
            AppHost.Routes.Add(typeof(CreditorWarehouseAddressesGETManyRequest), "/Creditors/{CreditorID}/WarehouseAddresses", "GET", "Retrieves a list of creditor warehouse addresses.", "");
            AppHost.Routes.Add(typeof(CreditorWarehouseAddressPOSTRequest), "/Creditors/{CreditorID}/WarehouseAddress", "POST", "Appends a warehouse to a creditor.", "");
            AppHost.Routes.Add(typeof(CreditorWarehouseAddressPATCHRequest), "/Creditors/{CreditorID}/WarehouseAddress/{WarehouseAddressID}", "PATCH", "Updates a warehouse address for a creditor.", "");
            AppHost.Routes.Add(typeof(CreditorWarehouseAddressDELETERequest), "/Creditors/{CreditorID}/WarehouseAddress/{WarehouseAddressID}", "DELETE", "Deletes a warehouse address from a creditor.", "");
            #endregion
            #endregion

            #region "Currencies"
            #region "{Main}"
            AppHost.RegisterService&lt;CurrencyServices&gt;();
            AppHost.Routes.Add(typeof(CurrencyGETRequest), "/Currencies/{CurrencyID}", "GET", "Retrieves a currency.", "");
            AppHost.Routes.Add(typeof(CurrencyPOSTRequest), "/Currencies", "POST", "Creates a currency.", "");
            AppHost.Routes.Add(typeof(CurrencyPATCHRequest), "/Currencies/{CurrencyID}", "PATCH", "Updates a currency.", "");
            AppHost.Routes.Add(typeof(CurrencyDELETERequest), "/Currencies/{CurrencyID}", "DELETE", "Deletes a currency.", "");
            AppHost.Routes.Add(typeof(CurrencySAVERequest), "/Currencies/Save", "GET", "Saves a stateful currency.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful currency exists.");
            AppHost.Routes.Add(typeof(CurrencyABANDONRequest), "/Currencies/Abandon", "DELETE", "Abandons a stateful currency.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful currency exists.");
            #endregion

            #region "Rates"
            AppHost.RegisterService&lt;CurrencyRateServices&gt;();
            AppHost.Routes.Add(typeof(CurrencyRateGETRequest), "/Currencies/{CurrencyID}/Rates/{RateID}", "GET", "Retrieves a currency rate.", "");
            AppHost.Routes.Add(typeof(CurrencyRatePOSTRequest), "/Currencies/{CurrencyID}/Rates", "POST", "Appends a rate to a currency.", "");
            AppHost.Routes.Add(typeof(CurrencyRatePATCHRequest), "/Currencies/{CurrencyID}/Rates/{RateID}", "PATCH", "Updates a rate for a currency.", "");
            AppHost.Routes.Add(typeof(CurrencyRateDELETERequest), "/Currencies/{CurrencyID}/Rates/{RateID}", "DELETE", "Deletes a rate from a currency.", "");
            #endregion
            #endregion

            #region "Debtors"
            #region "{Main}"
            AppHost.RegisterService&lt;DebtorServices&gt;();
			AppHost.Routes.Add(typeof(DebtorAPIKeyDebtorGETRequest), "/Debtors", "GET", "Retrieves a debtor for a API Key authenticated customer.", "");
            AppHost.Routes.Add(typeof(DebtorGETRequest), "/Debtors/{DebtorID}", "GET", "Retrieves a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorPOSTRequest), "/Debtors", "POST", "Creates a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorPATCHRequest), "/Debtors/{DebtorID}", "PATCH", "Updates a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorDELETERequest), "/Debtors/{DebtorID}", "DELETE", "Deletes a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorSAVERequest), "/Debtors/Save", "GET", "Saves a stateful debtor.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful debtor exists.");
            AppHost.Routes.Add(typeof(DebtorABANDONRequest), "/Debtors/Abandon", "DELETE", "Abandons a stateful debtor.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful debtor exists.");
            #endregion

            #region "Backorders"
            AppHost.RegisterService&lt;DebtorBackorderServices&gt;();
            AppHost.Routes.Add(typeof(DebtorBackordersGETRequest), "/Debtors/{DebtorID}/Backorders", "GET", "Retrieves a list of backorders for a debtor.", "");
            #endregion

            #region "Categories"
            AppHost.RegisterService&lt;DebtorCategoryServices&gt;();
            AppHost.Routes.Add(typeof(DebtorCategoryGETRequest), "/Debtors/Categories/{CategoryID}", "GET", "Retrieves a debtor category.", "");
            AppHost.Routes.Add(typeof(DebtorCategoryPOSTRequest), "/Debtors/Categories", "POST", "Creates a debtor category.", "");
            AppHost.Routes.Add(typeof(DebtorCategoryPATCHRequest), "/Debtors/Categories/{CategoryID}", "PATCH", "Updates a debtor category.", "");
            AppHost.Routes.Add(typeof(DebtorCategoryDELETERequest), "/Debtors/Categories/{CategoryID}", "DELETE", "Deletes a debtor category.", "");
            AppHost.Routes.Add(typeof(DebtorCategoriesSAVERequest), "/Debtors/Categories/Save", "GET", "Saves a stateful debtor categories collection.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful debtor categories collection exists.");
            AppHost.Routes.Add(typeof(DebtorCategoriesABANDONRequest), "/Debtors/Categories/Abandon", "DELETE", "Abandons a stateful debtor categories collection.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful debtor categories collection exists.");
            #endregion

            #region "Classification"
            AppHost.RegisterService&lt;DebtorClassificationServices&gt;();
            AppHost.Routes.Add(typeof(DebtorClassificationGETRequest), "/Debtors/Classifications/{ClassificationID}", "GET", "Retrieves a debtor classification.", "");
            AppHost.Routes.Add(typeof(DebtorClassificationPOSTRequest), "/Debtors/Classifications", "POST", "Creates a debtor classification.", "");
            AppHost.Routes.Add(typeof(DebtorClassificationPATCHRequest), "/Debtors/Classifications/{ClassificationID}", "PATCH", "Updates a debtor classification.", "");
            AppHost.Routes.Add(typeof(DebtorClassificationDELETERequest), "/Debtors/Classifications/{ClassificationID}", "DELETE", "Deletes a debtor classification.", "");
            AppHost.Routes.Add(typeof(DebtorClassificationSAVERequest), "/Debtors/Classifications/Save", "GET", "Saves a stateful debtor classification.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful debtor classification exists.");
            AppHost.Routes.Add(typeof(DebtorClassificationABANDONRequest), "/Debtors/Classifications/Abandon", "DELETE", "Abandons a stateful debtor classification.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful debtor classification exists.");
            #endregion

            #region "Contact Names"
            AppHost.RegisterService&lt;DebtorContactNameServices&gt;();
            AppHost.Routes.Add(typeof(DebtorContactNameGETRequest), "/Debtors/{DebtorID}/ContactNames/{ContactNameID}", "GET", "Retrieves a debtor contact name.", "");
            AppHost.Routes.Add(typeof(DebtorContactNamesGETManyRequest), "/Debtors/{DebtorID}/ContactNames", "GET", "Retrieves a list of debtor contact names.", "");
            AppHost.Routes.Add(typeof(DebtorContactNamePOSTRequest), "/Debtors/{DebtorID}/ContactNames", "POST", "Appends a contact name to a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorContactNamePATCHRequest), "/Debtors/{DebtorID}/ContactNames/{ContactNameID}", "PATCH", "Updates a debtor contact name.", "");
            AppHost.Routes.Add(typeof(DebtorContactNameDELETERequest), "/Debtors/{DebtorID}/ContactNames/{ContactNameID}", "DELETE", "Deletes a debtor contact name.", "");
            #endregion

            #region "Custom Fields"
            AppHost.RegisterService&lt;DebtorCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(DebtorCustomFieldValuesGETManyRequest), "/Debtors/{DebtorID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorCustomFieldsGETManyRequest), "/Debtors/CustomFields", "GET", "Retrieves a list of debtor custom fields.", "");
            AppHost.Routes.Add(typeof(DebtorCustomFieldValueGETRequest), "/Debtors/{DebtorID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a debtor custom field value.", "");
            AppHost.Routes.Add(typeof(DebtorCustomFieldValuePATCHRequest), "/Debtors/{DebtorID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a debtor custom field value.", "");
            #endregion

            #region "Debtor Part Numbers"
            AppHost.RegisterService&lt;DebtorPartNumberServices&gt;();
            AppHost.Routes.Add(typeof(DebtorPartNumberGETRequest), "/Debtors/{DebtorID}/DebtorPartNumbers/{PartNumberID}", "GET", "Retrieves a debtor part number.", "");
            AppHost.Routes.Add(typeof(DebtorPartNumbersGETManyRequest), "/Debtors/{DebtorID}/DebtorPartNumbers", "GET", "Retrieves a list of debtor part numbers.", "");
            AppHost.Routes.Add(typeof(DebtorPartNumberPOSTRequest), "/Debtors/{DebtorID}/DebtorPartNumbers", "POST", "Appends a debtor part number to a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorPartNumberPATCHRequest), "/Debtors/{DebtorID}/DebtorPartNumbers/{PartNumberID}", "PATCH", "Updates a debtor part number.", "");
            AppHost.Routes.Add(typeof(DebtorPartNumberDELETERequest), "/Debtors/{DebtorID}/DebtorPartNumbers/{PartNumberID}", "DELETE", "Deletes a debtor part number.", "");
            #endregion

            #region "Delivery Addresses"
            AppHost.RegisterService&lt;DebtorDeliveryAddressServices&gt;();
            AppHost.Routes.Add(typeof(DebtorDeliveryAddressGETRequest), "/Debtors/{DebtorID}/DeliveryAddresses/{DeliveryAddressID}", "GET", "Retrieves a debtor delivery address.", "");
            AppHost.Routes.Add(typeof(DebtorDeliveryAddressesGETManyRequest), "/Debtors/{DebtorID}/DeliveryAddresses", "GET", "Retrieves a list of debtor delivery addresses.", "");
            AppHost.Routes.Add(typeof(DebtorDeliveryAddressPOSTRequest), "/Debtors/{DebtorID}/DeliveryAddresses", "POST", "Appends a delivery address to a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorDeliveryAddressPATCHRequest), "/Debtors/{DebtorID}/DeliveryAddresses/{DeliveryAddressID}", "PATCH", "Updates a debtor delivery address.", "");
            AppHost.Routes.Add(typeof(DebtorDeliveryAddressDELETERequest), "/Debtors/{DebtorID}/DeliveryAddresses/{DeliveryAddressID}", "DELETE", "Deletes a debtor delivery address.", "");
            #endregion

            #region "Document Types"
            AppHost.RegisterService&lt;DebtorDocumentTypeServices&gt;();
            AppHost.Routes.Add(typeof(DebtorDocumentTypeGETRequest), "/Debtors/DocumentTypes/{DocumentTypeID}", "GET", "Retrieves a debtor document type.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentTypesGETManyRequest), "/Debtors/DocumentTypes", "GET", "Retrieves a list of debtor document types.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentTypePOSTRequest), "/Debtors/DocumentTypes", "POST", "Creates a new debtor document type.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentTypePATCHRequest), "/Debtors/DocumentTypes/{DocumentTypeID}", "PATCH", "Updates a debtor document type.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentTypeDELETERequest), "/Debtors/DocumentTypes/{DocumentTypeID}", "DELETE", "Deletes a debtor document type.", "");
            #endregion

            #region "Documents"
            AppHost.RegisterService&lt;DebtorDocumentServices&gt;();
            AppHost.Routes.Add(typeof(DebtorDocumentGETRequest), "/Debtors/{DebtorID}/Documents/{DocumentID}", "GET", "Retrieves a debtor document.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentsGETManyRequest), "/Debtors/{DebtorID}/Documents", "GET", "Retrieves a list of debtor documents.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentPOSTRequest), "/Debtors/{DebtorID}/Documents", "POST", "Appends a document to a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentPATCHRequest), "/Debtors/{DebtorID}/Documents/{DocumentID}", "PATCH", "Updates a debtor document.", "");
            AppHost.Routes.Add(typeof(DebtorDocumentDELETERequest), "/Debtors/{DebtorID}/Documents/{DocumentID}", "DELETE", "Deletes a debtor document.", "");
            #endregion

            #region "Freight Forwarder Addresses"
            AppHost.RegisterService&lt;DebtorFreightForwarderAddressServices&gt;();
            AppHost.Routes.Add(typeof(DebtorFreightForwarderAddressGETRequest), "/Debtors/{DebtorID}/FreightForwarderAddresses/{FreightForwarderAddressID}", "GET", "Retrieves a debtor freight forwarder address.", "");
            AppHost.Routes.Add(typeof(DebtorFreightForwarderAddressesGETManyRequest), "/Debtors/{DebtorID}/FreightForwarderAddresses", "GET", "Retrieves a list of debtor freight forwarder addresses.", "");
            AppHost.Routes.Add(typeof(DebtorFreightForwarderAddressPOSTRequest), "/Debtors/{DebtorID}/FreightForwarderAddresses", "POST", "Appends a freight forwarder address to a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorFreightForwarderAddressPATCHRequest), "/Debtors/{DebtorID}/FreightForwarderAddresses/{FreightForwarderAddressID}", "PATCH", "Updates a debtor freight forwarder address.", "");
            AppHost.Routes.Add(typeof(DebtorFreightForwarderAddressDELETERequest), "/Debtors/{DebtorID}/FreightForwarderAddresses/{FreightForwarderAddressID}", "DELETE", "Deletes a debtor freight forwarder address.", "");
            #endregion

            #region "Groups"
            AppHost.RegisterService&lt;DebtorGroupMembershipServices&gt;();
            AppHost.Routes.Add(typeof(DebtorGroupMembershipGETRequest), "/Debtors/{DebtorID}/GroupMemberships/{GroupMembershipID}", "GET", "Retrieves a debtor group membership.", "");
            AppHost.Routes.Add(typeof(DebtorGroupMembershipsGETManyRequest), "/Debtors/{DebtorID}/GroupMemberships", "GET", "Retrieves a list of debtor group memberships.", "");
            AppHost.Routes.Add(typeof(DebtorGroupMembershipPOSTRequest), "/Debtors/{DebtorID}/GroupMemberships", "POST", "Appends a group membership to a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorGroupMembershipPATCHRequest), "/Debtors/{DebtorID}/GroupMemberships/{GroupMembershipID}", "PATCH", "Updates a debtor group membership.", "");
            AppHost.Routes.Add(typeof(DebtorGroupMembershipDELETERequest), "/Debtors/{DebtorID}/GroupMemberships/{GroupMembershipID}", "DELETE", "Deletes a debtor group membership.", "");
            #endregion

            #region "Note Types"
            AppHost.RegisterService&lt;DebtorNoteTypeServices&gt;();
            AppHost.Routes.Add(typeof(DebtorNoteTypeGETRequest), "/Debtors/NoteTypes/{NoteTypeID}", "GET", "Retrieves a debtor note type.", "");
            AppHost.Routes.Add(typeof(DebtorNoteTypesGETManyRequest), "/Debtors/NoteTypes", "GET", "Retrieves a list of debtor note types.", "");
            AppHost.Routes.Add(typeof(DebtorNoteTypePOSTRequest), "/Debtors/NoteTypes", "POST", "Creates a new debtor note type.", "");
            AppHost.Routes.Add(typeof(DebtorNoteTypePATCHRequest), "/Debtors/NoteTypes/{NoteTypeID}", "PATCH", "Updates a debtor note type.", "");
            AppHost.Routes.Add(typeof(DebtorNoteTypeDELETERequest), "/Debtors/NoteTypes/{NoteTypeID}", "DELETE", "Deletes a debtor note type.", "");
            #endregion

            #region "Notes"
            AppHost.RegisterService&lt;DebtorNoteServices&gt;();
            AppHost.Routes.Add(typeof(DebtorNoteGETRequest), "/Debtors/{DebtorID}/Notes/{NoteID}", "GET", "Retrieves a debtor note.", "");
            AppHost.Routes.Add(typeof(DebtorNotesGETManyRequest), "/Debtors/{DebtorID}/Notes", "GET", "Retrieves a list of debtor notes.", "");
            AppHost.Routes.Add(typeof(DebtorNotePOSTRequest), "/Debtors/{DebtorID}/Notes", "POST", "Appends a note to a debtor.", "");
            AppHost.Routes.Add(typeof(DebtorNotePATCHRequest), "/Debtors/{DebtorID}/Notes/{NoteID}", "PATCH", "Updates a debtor note.", "");
            AppHost.Routes.Add(typeof(DebtorNoteDELETERequest), "/Debtors/{DebtorID}/Notes/{NoteID}", "DELETE", "Deletes a debtor note.", "");
            #endregion

            #region "Pricing Groups"
            AppHost.RegisterService&lt;DebtorPricingGroupServices&gt;();
            AppHost.Routes.Add(typeof(DebtorPricingGroupGETRequest), "/Debtors/PricingGroups/{PricingGroupID}", "GET", "Retrieves a debtor pricing group.", "");
            AppHost.Routes.Add(typeof(DebtorPricingGroupPOSTRequest), "/Debtors/PricingGroups", "POST", "Creates a new debtor pricing group.", "");
            AppHost.Routes.Add(typeof(DebtorPricingGroupPATCHRequest), "/Debtors/PricingGroups/{PricingGroupID}", "PATCH", "Updates a debtor pricing group.", "");
            AppHost.Routes.Add(typeof(DebtorPricingGroupDELETERequest), "/Debtors/PricingGroups/{PricingGroupID}", "DELETE", "Deletes a debtor pricing group.", "");
            #endregion
            #endregion
			
            #region "Goods Received Notes"
            #region "{Main}"
            AppHost.RegisterService&lt;GoodsReceivedNoteServices&gt;();
            AppHost.Routes.Add(typeof(GoodsReceivedNoteGETRequest), "/GoodsReceivedNotes/{GRNID}", "GET", "Retrieves a GRN.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNotePOSTRequest), "/GoodsReceivedNotes", "POST", "Creates a GRN.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNotePATCHRequest), "/GoodsReceivedNotes/{GRNID}", "PATCH", "Updates a GRN.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteDELETERequest), "/GoodsReceivedNotes/{GRNID}", "DELETE", "Deletes a GRN.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteSAVERequest), "/GoodsReceivedNotes/Save", "GET", "Saves a stateful stateful goods received note.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful goods received note item exists.");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteABANDONRequest), "/GoodsReceivedNotes/Abandon", "DELETE", "Abandons a stateful goods received note.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful goods received note item exists.");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteCREATEFromPORequest), "/GoodsReceivedNotes/FromPurchaseOrders/{OrderNos}", "POST", "Creates a GRN from the supplied purchase orders.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteCREATEFromPOLinesRequest), "/GoodsReceivedNotes/FromPurchaseOrderLines", "POST", "Creates a GRN from the supplied list of ReceivedPOLineQuantity.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteACTIVATERequest), "/GoodsReceivedNotes/Activate/{GRNID}", "POST", "Activates a GRN.", "");
            #endregion

            #region "Purchase Orders"
            AppHost.RegisterService&lt;GoodsReceivedNotePurchaseOrderServices&gt;();
            AppHost.Routes.Add(typeof(GoodsReceivedNotePurchaseOrderGETRequest), "/GoodsReceivedNotes/{GRNID}/PurchaseOrders/{OrderID}", "GET", "Retrieves a goods received note purchase order.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNotePurchaseOrdersGETManyRequest), "/GoodsReceivedNotes/{GRNID}/PurchaseOrders", "GET", "Retrieves a list of goods received note purchase orders.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNotePurchaseOrderPOSTRequest), "/GoodsReceivedNotes/{GRNID}/PurchaseOrders", "POST", "Appends a purchase order to a goods received note.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNotePurchaseOrderDELETERequest), "/GoodsReceivedNotes/{GRNID}/PurchaseOrders/{OrderID}", "DELETE", "Deletes a purchase order from a goods received note.", "");
            #endregion

            #region "Lines"
            AppHost.RegisterService&lt;GoodsReceivedNoteLineServices&gt;();
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLineGETRequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}", "GET", "Retrieves a goods received note line.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLinesGETManyRequest), "/GoodsReceivedNotes/{GRNID}/Lines", "GET", "Retrieves a list of goods received note lines.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLinePOSTRequest), "/GoodsReceivedNotes/{GRNID}/Lines", "POST", "Appends a line to a goods received note.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLinePATCHRequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}", "PATCH", "Updates a line for a goods received note.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLineDELETERequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}", "DELETE", "Deletes a line from a goods received note.", "");
            #endregion
			
            #region "Line Detail"
            AppHost.RegisterService&lt;GoodsReceivedNoteLineDetailServices&gt;();
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLineDetailsGETManyRequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}/LineDetails", "GET", "Retrieves a list of line details for a goods received note line.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLineDetailGETRequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}/LineDetails/{LineDetailID}", "GET", "Retrieves a goods received note line detail.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLineDetailPOSTRequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}/LineDetails", "POST", "Appends a line detail to a goods received note line.", "");
			AppHost.Routes.Add(typeof(GoodsReceivedNoteLineDetailPUTRequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}/LineDetails", "PUT", "Sets the line details for a goods received note line. Existing line details for that line will be replaced.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLineDetailPATCHRequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}/LineDetails/{LineDetailID}", "PATCH", "Updates a goods received note line detail.", "");
            AppHost.Routes.Add(typeof(GoodsReceivedNoteLineDetailDELETERequest), "/GoodsReceivedNotes/{GRNID}/Lines/{LineID}/LineDetails/{LineDetailID}", "DELETE", "Deletes a goods received note line detail.", "");
            #endregion			
            #endregion

            #region "Inventory"
            #region "{Main}"
            AppHost.RegisterService&lt;InventoryServices&gt;();
            AppHost.Routes.Add(typeof(InventoryGETRequest), "/Inventory/{InventoryID}", "GET", "Retrieves an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryPOSTRequest), "/Inventory", "POST", "Creates an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryPATCHRequest), "/Inventory/{InventoryID}", "PATCH", "Updates an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDELETERequest), "/Inventory/{InventoryID}", "DELETE", "Deletes an inventory item.", "");
            AppHost.Routes.Add(typeof(InventorySAVERequest), "/Inventory/Save", "GET", "Saves a stateful inventory item.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory item exists.");
            AppHost.Routes.Add(typeof(InventoryABANDONRequest), "/Inventory/Abandon", "DELETE", "Abandons a stateful inventory item.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory item exists.");
            #endregion

            #region "Alternate Children"
            AppHost.RegisterService&lt;InventoryAlternateChildServices&gt;();
            AppHost.Routes.Add(typeof(InventoryAlternateChildrenGETManyRequest), "/Inventory/{InventoryID}/AlternateChildren", "GET", "Retrieves a list of inventory alternate children.", "");
            AppHost.Routes.Add(typeof(InventoryAlternateChildGETRequest), "/Inventory/{InventoryID}/AlternateChildren/{AlternateChildID}", "GET", "Retrieves an inventory alternate child.", "");
            AppHost.Routes.Add(typeof(InventoryAlternateChildPOSTRequest), "/Inventory/{InventoryID}/AlternateChildren", "POST", "Appends an alternate child to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryAlternateChildPATCHRequest), "/Inventory/{InventoryID}/AlternateChildren/{AlternateChildID}", "PATCH", "Updates a inventory alternate child.", "");
            AppHost.Routes.Add(typeof(InventoryAlternateChildDELETERequest), "/Inventory/{InventoryID}/AlternateChildren/{AlternateChildID}", "DELETE", "Deletes a inventory alternate child.", "");
            #endregion

            #region "Alternate Parents"
            AppHost.RegisterService&lt;InventoryAlternateParentServices&gt;();
            AppHost.Routes.Add(typeof(InventoryAlternateParentsGETManyRequest), "/Inventory/{InventoryID}/AlternateParents", "GET", "Retrieves a list of inventory alternate parents.", "");
            AppHost.Routes.Add(typeof(InventoryAlternateParentGETRequest), "/Inventory/{InventoryID}/AlternateParents/{LinkedInventoryID}", "GET", "Retrieves an inventory alternate parent.", "");
            #endregion

            #region "Attribute Group Template Attributes"
            AppHost.RegisterService&lt;InventoryAttributeGroupTemplateAttributeServices&gt;();
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateAttributesGETManyRequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}/Attributes", "GET", "Retrieves a list of inventory attribute group template attributes.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateAttributeGETRequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}/Attributes/{TemplateAttributeID}", "GET", "Retrieves an inventory attribute group template attribute.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateAttributePOSTRequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}/Attribute", "POST", "Appends an inventory attribute group template attribute to an inventory attribute group template.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateAttributePATCHRequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}/Attributes/{TemplateAttributeID}", "PATCH", "Updates an inventory attribute group template attribute.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateAttributeDELETERequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}/Attributes/{TemplateAttributeID}", "DELETE", "Deletes an inventory attribute group template attribute.", "");
            #endregion

            #region "Attribute Group Templates"
            AppHost.RegisterService&lt;InventoryAttributeGroupTemplateServices&gt;();
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateGETRequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}", "GET", "Retrieves an inventory attribute group template.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplatePOSTRequest), "/Inventory/AttributeGroupTemplates", "POST", "Creates a new inventory attribute group template.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplatePATCHRequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}", "PATCH", "Updates an inventory attribute group template.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateDELETERequest), "/Inventory/AttributeGroupTemplates/{AttributeGroupTemplateID}", "DELETE", "Deletes an inventory attribute group template.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateSAVERequest), "/Inventory/AttributeGroupTemplates/Save", "GET", "Saves a stateful inventory attribute group template.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory attribute group template exists.");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupTemplateABANDONRequest), "/Inventory/AttributeGroupTemplates/Abandon", "DELETE", "Abandons a stateful inventory attribute group template.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory attribute group template exists.");
            #endregion

            #region "Attribute Groups"
            AppHost.RegisterService&lt;InventoryAttributeGroupServices&gt;();
            AppHost.Routes.Add(typeof(InventoryAttributeGroupsGETManyRequest), "/Inventory/{InventoryID}/AttributeGroups", "GET", "Retrieves a list of inventory attribute groups.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupGETRequest), "/Inventory/{InventoryID}/AttributeGroups/{AttributeGroupID}", "GET", "Retrieves an inventory attribute group.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupPOSTRequest), "/Inventory/{InventoryID}/AttributeGroups", "POST", "Appends an attribute group to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupPATCHRequest), "/Inventory/{InventoryID}/AttributeGroups/{AttributeGroupID}", "PATCH", "Updates a inventory attribute group.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeGroupDELETERequest), "/Inventory/{InventoryID}/AttributeGroups/{AttributeGroupID}", "DELETE", "Deletes a inventory attribute group.", "");
            #endregion

            #region "Attribute Values"
            AppHost.RegisterService&lt;InventoryAttributeValueServices&gt;();
            AppHost.Routes.Add(typeof(InventoryAttributeValueGETRequest), "/Inventory/{InventoryID}/AttributeGroups/{AttributeGroupID}/AttributeValues/{AttributeID}", "GET", "Retrieves an inventory attribute value.", "");
            AppHost.Routes.Add(typeof(InventoryAttributeValuePATCHRequest), "/Inventory/{InventoryID}/AttributeGroups/{AttributeGroupID}/AttributeValues/{AttributeID}", "PATCH", "Updates an inventory attribute value.", "");
            #endregion

            #region "Budgets"
            AppHost.RegisterService&lt;InventoryBudgetServices&gt;();
            AppHost.Routes.Add(typeof(InventoryBudgetsGETManyRequest), "/Inventory/{InventoryID}/Budgets", "GET", "Retrieves a list of budgets for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryBudgetGETRequest), "/Inventory/{InventoryID}/Budgets/{LogicalWarehouseID}", "GET", "Retrieves a budget from an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryBudgetPATCHRequest), "/Inventory/{InventoryID}/Budgets/{LogicalWarehouseID}", "PATCH", "Updates a budget.", "");
            #endregion

            #region "Categories"
            AppHost.RegisterService&lt;InventoryCategoryServices&gt;();
            AppHost.Routes.Add(typeof(InventoryCategoryGETRequest), "/Inventory/Categories/{CategoryID}", "GET", "Retrieves an inventory category.", "");
            AppHost.Routes.Add(typeof(InventoryCategoryPOSTRequest), "/Inventory/Categories", "POST", "Creates an inventory category.", "");
            AppHost.Routes.Add(typeof(InventoryCategoryPATCHRequest), "/Inventory/Categories/{CategoryID}", "PATCH", "Updates an inventory category.", "");
            AppHost.Routes.Add(typeof(InventoryCategoryDELETERequest), "/Inventory/Categories/{CategoryID}", "DELETE", "Deletes an inventory category.", "");
            AppHost.Routes.Add(typeof(InventoryCategoriesSAVERequest), "/Inventory/Categories/Save", "GET", "Saves a stateful inventory categories collection.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory categories collection exists.");
            AppHost.Routes.Add(typeof(InventoryCategoriesABANDONRequest), "/Inventory/Categories/Abandon", "DELETE", "Abandons a stateful inventory categories collection.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory categories collection exists.");
            #endregion

            #region "Classification"
            AppHost.RegisterService&lt;InventoryClassificationServices&gt;();
            AppHost.Routes.Add(typeof(InventoryClassificationGETRequest), "/Inventory/Classifications/{ClassificationID}", "GET", "Retrieves an inventory classification.", "");
            AppHost.Routes.Add(typeof(InventoryClassificationPOSTRequest), "/Inventory/Classifications", "POST", "Creates an inventory classification.", "");
            AppHost.Routes.Add(typeof(InventoryClassificationPATCHRequest), "/Inventory/Classifications/{ClassificationID}", "PATCH", "Updates an inventory classification.", "");
            AppHost.Routes.Add(typeof(InventoryClassificationDELETERequest), "/Inventory/Classifications/{ClassificationID}", "DELETE", "Deletes an inventory classification.", "");
            AppHost.Routes.Add(typeof(InventoryClassificationSAVERequest), "/Inventory/Classifications/Save", "GET", "Saves a stateful inventory classification.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory classification exists.");
            AppHost.Routes.Add(typeof(InventoryClassificationABANDONRequest), "/Inventory/Classifications/Abandon", "DELETE", "Abandons a stateful inventory classification.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful inventory classification exists.");
            #endregion

            #region "Components"
            AppHost.RegisterService&lt;InventoryComponentServices&gt;();
            AppHost.Routes.Add(typeof(InventoryComponentsGETManyRequest), "/Inventory/{InventoryID}/Components", "GET", "Retrieves a list of components for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryComponentGETRequest), "/Inventory/{InventoryID}/Components/{ComponentID}", "GET", "Retrieves a component from an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryComponentPOSTRequest), "/Inventory/{InventoryID}/Components", "POST", "Appends a component to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryComponentPATCHRequest), "/Inventory/{InventoryID}/Components/{ComponentID}", "PATCH", "Updates a component.", "");
            AppHost.Routes.Add(typeof(InventoryComponentDELETERequest), "/Inventory/{InventoryID}/Components/{ComponentID}", "DELETE", "Deletes a component.", "");
            #endregion

            #region "Custom Fields"
            AppHost.RegisterService&lt;InventoryCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(InventoryCustomFieldsGETManyRequest), "/Inventory/CustomFields", "GET", "Retrieves a list of inventory custom fields.", "");
            AppHost.Routes.Add(typeof(InventoryCustomFieldValuesGETManyRequest), "/Inventory/{InventoryID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryCustomFieldValueGETRequest), "/Inventory/{InventoryID}/CustomFieldValues/{SettingID}", "GET", "Retrieves an inventory custom field value.", "");
            AppHost.Routes.Add(typeof(InventoryCustomFieldValuePATCHRequest), "/Inventory/{InventoryID}/CustomFieldValues/{SettingID}", "PATCH", "Updates an inventory custom field value.", "");
            #endregion

            #region "Document Types"
            AppHost.RegisterService&lt;InventoryDocumentTypeServices&gt;();
            AppHost.Routes.Add(typeof(InventoryDocumentTypesGETManyRequest), "/Inventory/DocumentTypes", "GET", "Retrieves a list of inventory document types.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentTypeGETRequest), "/Inventory/DocumentTypes/{DocumentTypeID}", "GET", "Retrieves an inventory document type.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentTypePOSTRequest), "/Inventory/DocumentTypes", "POST", "Creates a new inventory document type.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentTypePATCHRequest), "/Inventory/DocumentTypes/{DocumentTypeID}", "PATCH", "Updates an inventory document type.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentTypeDELETERequest), "/Inventory/DocumentTypes/{DocumentTypeID}", "DELETE", "Deletes an inventory document type.", "");
            #endregion

            #region "Documents"
            AppHost.RegisterService&lt;InventoryDocumentServices&gt;();
            AppHost.Routes.Add(typeof(InventoryDocumentsGETManyRequest), "/Inventory/{InventoryID}/Documents", "GET", "Retrieves a list of inventory documents.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentGETRequest), "/Inventory/{InventoryID}/Documents/{DocumentID}", "GET", "Retrieves an inventory document.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentPOSTRequest), "/Inventory/{InventoryID}/Documents", "POST", "Appends a document to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentPATCHRequest), "/Inventory/{InventoryID}/Documents/{DocumentID}", "PATCH", "Updates an inventory document.", "");
            AppHost.Routes.Add(typeof(InventoryDocumentDELETERequest), "/Inventory/{InventoryID}/Documents/{DocumentID}", "DELETE", "Deletes an inventory document.", "");
            #endregion

            #region "Ledgers"
            AppHost.RegisterService&lt;InventoryLedgerServices&gt;();
            AppHost.Routes.Add(typeof(InventoryLedgersGETManyRequest), "/Inventory/{InventoryID}/Ledgers", "GET", "Retrieves a list of inventory ledgers.", "");
            AppHost.Routes.Add(typeof(InventoryLedgerGETRequest), "/Inventory/{InventoryID}/Ledgers/{Name}", "GET", "Retrieves an inventory ledger.", "");
            AppHost.Routes.Add(typeof(InventoryLedgerPATCHRequest), "/Inventory/{InventoryID}/Ledgers/{Name}", "PATCH", "Updates a inventory ledger.", "");
            #endregion

            #region "Note Types"
            AppHost.RegisterService&lt;InventoryNoteTypeServices&gt;();
            AppHost.Routes.Add(typeof(InventoryNoteTypesGETManyRequest), "/Inventory/NoteTypes", "GET", "Retrieves a list of inventory note types.", "");
            AppHost.Routes.Add(typeof(InventoryNoteTypeGETRequest), "/Inventory/NoteTypes/{NoteTypeID}", "GET", "Retrieves an inventory note type.", "");
            AppHost.Routes.Add(typeof(InventoryNoteTypePOSTRequest), "/Inventory/NoteTypes", "POST", "Creates a new inventory note type.", "");
            AppHost.Routes.Add(typeof(InventoryNoteTypePATCHRequest), "/Inventory/NoteTypes/{NoteTypeID}", "PATCH", "Updates an inventory note type.", "");
            AppHost.Routes.Add(typeof(InventoryNoteTypeDELETERequest), "/Inventory/NoteTypes/{NoteTypeID}", "DELETE", "Deletes an inventory note type.", "");
            #endregion

            #region "Notes"
            AppHost.RegisterService&lt;InventoryNoteServices&gt;();
            AppHost.Routes.Add(typeof(InventoryNotesGETManyRequest), "/Inventory/{InventoryID}/Notes", "GET", "Retrieves a list of inventory notes.", "");
            AppHost.Routes.Add(typeof(InventoryNoteGETRequest), "/Inventory/{InventoryID}/Notes/{NoteID}", "GET", "Retrieves an inventory note.", "");
            AppHost.Routes.Add(typeof(InventoryNotePOSTRequest), "/Inventory/{InventoryID}/Notes", "POST", "Appends a note to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryNotePATCHRequest), "/Inventory/{InventoryID}/Notes/{NoteID}", "PATCH", "Updates an inventory note.", "");
            AppHost.Routes.Add(typeof(InventoryNoteDELETERequest), "/Inventory/{InventoryID}/Notes/{NoteID}", "DELETE", "Deletes an inventory note.", "");
            #endregion

            #region "Order Levels"
            AppHost.RegisterService&lt;InventoryOrderLevelServices&gt;();
            AppHost.Routes.Add(typeof(InventoryOrderLevelsGETManyRequest), "/Inventory/{InventoryID}/OrderLevels", "GET", "Retrieves a list of order levels for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryOrderLevelGETRequest), "/Inventory/{InventoryID}/OrderLevels/{LogicalWarehouseID}/Periods/{PeriodNo}", "GET", "Retrieves a order level from an inventory item for a particular logical warehouse.", "");
            AppHost.Routes.Add(typeof(InventoryOrderLevelPATCHRequest), "/Inventory/{InventoryID}/OrderLevels/{LogicalWarehouseID}/Periods/{PeriodNo}", "PATCH", "Updates an order level.", "");
            #endregion

            #region "Other Descriptions"
            AppHost.RegisterService&lt;InventoryOtherDescriptionServices&gt;();
            AppHost.Routes.Add(typeof(InventoryOtherDescriptionsGETManyRequest), "/Inventory/{InventoryID}/OtherDescriptions", "GET", "Retrieves a list of inventory other descriptions.", "");
            AppHost.Routes.Add(typeof(InventoryOtherDescriptionGETRequest), "/Inventory/{InventoryID}/OtherDescriptions/{OtherDescriptionID}", "GET", "Retrieves an inventory other description.", "");
            AppHost.Routes.Add(typeof(InventoryOtherDescriptionPOSTRequest), "/Inventory/{InventoryID}/OtherDescriptions", "POST", "Appends an other description to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryOtherDescriptionPATCHRequest), "/Inventory/{InventoryID}/OtherDescriptions/{OtherDescriptionID}", "PATCH", "Updates an inventory other description.", "");
            AppHost.Routes.Add(typeof(InventoryOtherDescriptionDELETERequest), "/Inventory/{InventoryID}/OtherDescriptions/{OtherDescriptionID}", "DELETE", "Deletes an inventory other description.", "");
            #endregion

            #region "Prices"
            #region "{Main}"
            AppHost.RegisterService&lt;InventoryPriceServices&gt;();
            AppHost.Routes.Add(typeof(InventoryPriceGETRequest), "/Inventory/{InventoryID}/Pricing/{DebtorID}/{IN_LogicalID}/{Date}/{Quantity}", "GET", "Retrieves a price for a product, for a debtor, warehouse, date and quantity", "");
            #endregion

            #region "Debtor Specific"
            AppHost.RegisterService&lt;InventoryDebtorSpecificPriceServices&gt;();
            AppHost.Routes.Add(typeof(InventoryDebtorSpecificPricesGETManyRequest), "/Inventory/{InventoryID}/DebtorSpecificPrices", "GET", "Retrieves a list of debtor specific prices for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorSpecificPriceGETRequest), "/Inventory/{InventoryID}/DebtorSpecificPrices/{DebtorSpecificPriceID}", "GET", "Retrieves a debtor specific price from an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorSpecificPricePOSTRequest), "/Inventory/{InventoryID}/DebtorSpecificPrices", "POST", "Adds a debtor specific price to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorSpecificPricePATCHRequest), "/Inventory/{InventoryID}/DebtorSpecificPrices/{DebtorSpecificPriceID}", "PATCH", "Updates a debtor specific price.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorSpecificPriceDELETERequest), "/Inventory/{InventoryID}/DebtorSpecificPrices/{DebtorSpecificPriceID}", "DELETE", "Deletes a debtor specific price.", "");
            #endregion

            #region "Debtor Classification"
            AppHost.RegisterService&lt;InventoryDebtorClassificationPriceServices&gt;();
            AppHost.Routes.Add(typeof(InventoryDebtorClassificationPricesGETManyRequest), "/Inventory/{InventoryID}/DebtorClassificationPrices", "GET", "Retrieves a list of debtor classification prices for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorClassificationPriceGETRequest), "/Inventory/{InventoryID}/DebtorClassificationPrices/{DebtorClassificationPriceID}", "GET", "Retrieves a debtor classification price from an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorClassificationPricePOSTRequest), "/Inventory/{InventoryID}/DebtorClassificationPrices", "POST", "Adds a debtor classification price to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorClassificationPricePATCHRequest), "/Inventory/{InventoryID}/DebtorClassificationPrices/{DebtorClassificationPriceID}", "PATCH", "Updates a debtor classification price.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorClassificationPriceDELETERequest), "/Inventory/{InventoryID}/DebtorClassificationPrices/{DebtorClassificationPriceID}", "DELETE", "Deletes a debtor classification price.", "");
            #endregion

            #region "Debtor Price Group"
            AppHost.RegisterService&lt;InventoryDebtorPriceGroupPriceServices&gt;();
            AppHost.Routes.Add(typeof(InventoryDebtorPriceGroupPricesGETManyRequest), "/Inventory/{InventoryID}/DebtorPriceGroupPrices", "GET", "Retrieves a list of debtor price group prices for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorPriceGroupPriceGETRequest), "/Inventory/{InventoryID}/DebtorPriceGroupPrices/{DebtorPriceGroupInventorySpecificID}", "GET", "Retrieves a debtor price group price from an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorPriceGroupPricePOSTRequest), "/Inventory/{InventoryID}/DebtorPriceGroupPrices", "POST", "Adds a debtor price group price to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorPriceGroupPricePATCHRequest), "/Inventory/{InventoryID}/DebtorPriceGroupPrices/{DebtorPriceGroupInventorySpecificID}", "PATCH", "Updates a debtor price group price.", "");
            AppHost.Routes.Add(typeof(InventoryDebtorPriceGroupPriceDELETERequest), "/Inventory/{InventoryID}/DebtorPriceGroupPrices/{DebtorPriceGroupInventorySpecificID}", "DELETE", "Deletes a debtor price group price.", "");
            #endregion

            #region "Selling Prices"
            AppHost.RegisterService&lt;InventorySellingPriceServices&gt;();
            AppHost.Routes.Add(typeof(InventorySellingPriceGETRequest), "/Inventory/{InventoryID}/SellingPrices", "GET", "Retrieves the selling prices for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventorySellingPricePATCHRequest), "/Inventory/{InventoryID}/SellingPrices", "PATCH", "Updates the selling prices.", "");
            #endregion
            #endregion

            #region "Pricing Groups"
            AppHost.RegisterService&lt;InventoryPricingGroupServices&gt;();
            AppHost.Routes.Add(typeof(InventoryPricingGroupsGETManyRequest), "/Inventory/PricingGroups", "GET", "Retrieves a list of inventory pricing groups.", "");
            AppHost.Routes.Add(typeof(InventoryPricingGroupGETRequest), "/Inventory/PricingGroups/{PricingGroupID}", "GET", "Retrieves an inventory pricing group.", "");
            AppHost.Routes.Add(typeof(InventoryPricingGroupPOSTRequest), "/Inventory/PricingGroups", "POST", "Creates a new inventory pricing group.", "");
            AppHost.Routes.Add(typeof(InventoryPricingGroupPATCHRequest), "/Inventory/PricingGroups/{PricingGroupID}", "PATCH", "Updates an inventory pricing group.", "");
            AppHost.Routes.Add(typeof(InventoryPricingGroupDELETERequest), "/Inventory/PricingGroups/{PricingGroupID}", "DELETE", "Deletes an inventory pricing group.", "");
            #endregion

            #region "Product Availabilities"
            AppHost.RegisterService&lt;InventoryProductAvailabilityServices&gt;();
            AppHost.Routes.Add(typeof(InventoryProductAvailabilitiesGETManyRequest), "/Inventory/{InventoryID}/ProductAvailabilities", "GET", "Retrieves a list of product availabilities for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryProductAvailabilityGETRequest), "/Inventory/{InventoryID}/ProductAvailabilities/{LogicalWarehouseID}", "GET", "Retrieves a product availability from an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryProductAvailabilityPATCHRequest), "/Inventory/{InventoryID}/ProductAvailabilities/{LogicalWarehouseID}", "PATCH", "Updates a product availability.", "");
            #endregion

            #region "Regions"
            #region "{Main}"
            AppHost.RegisterService&lt;InventoryRegionServices&gt;();
            AppHost.Routes.Add(typeof(InventoryRegionGETRequest), "/Inventory/{InventoryID}/Regions/{RegionName}", "GET", "Retrieves an inventory region.", "");
            AppHost.Routes.Add(typeof(InventoryRegionsGETManyRequest), "/Inventory/{InventoryID}/Regions", "GET", "Retrieves a list of inventory regions.", "");
            AppHost.Routes.Add(typeof(InventoryRegionPATCHRequest), "/Inventory/{InventoryID}/Regions/{RegionName}", "PATCH", "Updates a inventory region.", "");
            #endregion

            #region "Suppliers"
            #region "{Main}"
            AppHost.RegisterService&lt;InventorySupplierServices&gt;();
            AppHost.Routes.Add(typeof(InventorySupplierGETRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}", "GET", "Retrieves an inventory item supplier.", "");
            AppHost.Routes.Add(typeof(InventorySuppliersGETManyRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers", "GET", "Retrieves a list of suppliers for a given inventory item in a particular region.", "");
            AppHost.Routes.Add(typeof(InventorySupplierPOSTRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers", "POST", "Appends a supplier to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventorySupplierPATCHRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}", "PATCH", "Updates an inventory item supplier.", "");
            AppHost.Routes.Add(typeof(InventorySupplierDELETERequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}", "DELETE", "Deletes an inventory item supplier.", "");
            #endregion

            #region "Supplier Warehouses"
            AppHost.RegisterService&lt;InventorySupplierWarehouseServices&gt;();
            AppHost.Routes.Add(typeof(InventorySupplierWarehouseGETRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}/SupplierWarehouses/{SupplierWarehouseID}", "GET", "Retrieves an inventory item supplier warehouse.", "");
            AppHost.Routes.Add(typeof(InventorySupplierWarehousesGETManyRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}/SupplierWarehouses", "GET", "Retrieves a list of inventory supplier warehouses.", "");
            AppHost.Routes.Add(typeof(InventorySupplierWarehousePOSTRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}/SupplierWarehouses", "POST", "Appends a supplier warehouse to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventorySupplierWarehousePATCHRequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}/SupplierWarehouses/{SupplierWarehouseID}", "PATCH", "Updates a supplier warehouse for an inventory item.", "");
            AppHost.Routes.Add(typeof(InventorySupplierWarehouseDELETERequest), "/Inventory/{InventoryID}/Regions/{RegionName}/Suppliers/{SupplierID}/SupplierWarehouses/{SupplierWarehouseID}", "DELETE", "Deletes a supplier warehouse from an inventory item.", "");
            #endregion
            #endregion
            #endregion

            #region "Unit Of Measures"
            AppHost.RegisterService&lt;InventoryUnitOfMeasureServices&gt;();
            AppHost.Routes.Add(typeof(InventoryUnitOfMeasuresGETManyRequest), "/Inventory/{InventoryID}/UnitOfMeasures", "GET", "Retrieves a list of inventory unit of measures.", "");
            AppHost.Routes.Add(typeof(InventoryUnitOfMeasureGETRequest), "/Inventory/{InventoryID}/UnitOfMeasures/{UnitOfMeasureID}", "GET", "Retrieves an inventory unit of measure.", "");
            AppHost.Routes.Add(typeof(InventoryUnitOfMeasurePOSTRequest), "/Inventory/{InventoryID}/UnitOfMeasures", "POST", "Appends an alternate child to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryUnitOfMeasurePATCHRequest), "/Inventory/{InventoryID}/UnitOfMeasures/{UnitOfMeasureID}", "PATCH", "Updates a inventory unit of measure.", "");
            AppHost.Routes.Add(typeof(InventoryUnitOfMeasureDELETERequest), "/Inventory/{InventoryID}/UnitOfMeasures/{UnitOfMeasureID}", "DELETE", "Deletes a inventory unit of measure.", "");
            #endregion

            #region "Up Sells"
            AppHost.RegisterService&lt;InventoryUpSellServices&gt;();
            AppHost.Routes.Add(typeof(InventoryUpSellsGETManyRequest), "/Inventory/{InventoryID}/UpSells", "GET", "Retrieves a list of inventory up sells.", "");
            AppHost.Routes.Add(typeof(InventoryUpSellGETRequest), "/Inventory/{InventoryID}/UpSells/{UpSellID}", "GET", "Retrieves an inventory up sell.", "");
            AppHost.Routes.Add(typeof(InventoryUpSellPOSTRequest), "/Inventory/{InventoryID}/UpSells", "POST", "Appends an up sell to an inventory item.", "");
            AppHost.Routes.Add(typeof(InventoryUpSellPATCHRequest), "/Inventory/{InventoryID}/UpSells/{UpSellID}", "PATCH", "Updates a inventory up sell.", "");
            AppHost.Routes.Add(typeof(InventoryUpSellDELETERequest), "/Inventory/{InventoryID}/UpSells/{UpSellID}", "DELETE", "Deletes a inventory up sell.", "");
            #endregion
            #endregion

            #region "Journal Sets"
            #region "{Main}"
            AppHost.RegisterService&lt;JournalSetServices&gt;();
            AppHost.Routes.Add(typeof(JournalSetGETRequest), "/JournalSets/{JournalSetID}", "GET", "Retrieves a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetPOSTRequest), "/JournalSets/", "POST", "Creates a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetPATCHRequest), "/JournalSets/{JournalSetID}", "PATCH", "Updates a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetDELETERequest), "/JournalSets/{JournalSetID}", "DELETE", "Deletes a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetSAVERequest), "/JournalSets/Save", "GET", "Saves a stateful stateful journal set.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful journal set item exists.");
            AppHost.Routes.Add(typeof(JournalSetABANDONRequest), "/JournalSets/Abandon", "DELETE", "Abandons a stateful journal set.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful journal set item exists.");
            #endregion

            #region "Document Types"
            AppHost.RegisterService&lt;JournalSetDocumentTypeServices&gt;();
            AppHost.Routes.Add(typeof(JournalSetDocumentTypesGETManyRequest), "/JournalSets/DocumentTypes", "GET", "Retrieves a list of journal set document types.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentTypeGETRequest), "/JournalSets/DocumentTypes/{DocumentTypeID}", "GET", "Retrieves a journal set document type.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentTypePOSTRequest), "/JournalSets/DocumentTypes", "POST", "Creates a new journal set document type.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentTypePATCHRequest), "/JournalSets/DocumentTypes/{DocumentTypeID}", "PATCH", "Updates a journal set document type.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentTypeDELETERequest), "/JournalSets/DocumentTypes/{DocumentTypeID}", "DELETE", "Deletes a journal set document type.", "");
            #endregion

            #region "Documents"
            AppHost.RegisterService&lt;JournalSetDocumentServices&gt;();
            AppHost.Routes.Add(typeof(JournalSetDocumentsGETManyRequest), "/JournalSets/{JournalSetID}/Documents", "GET", "Retrieves a list of journal set documents.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentGETRequest), "/JournalSets/{JournalSetID}/Documents/{DocumentID}", "GET", "Retrieves a journal set document.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentPOSTRequest), "/JournalSets/{JournalSetID}/Documents", "POST", "Appends a document to a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentPATCHRequest), "/JournalSets/{JournalSetID}/Documents/{DocumentID}", "PATCH", "Updates a journal set document.", "");
            AppHost.Routes.Add(typeof(JournalSetDocumentDELETERequest), "/JournalSets/{JournalSetID}/Documents/{DocumentID}", "DELETE", "Deletes a journal set document.", "");
            #endregion

            #region "Lines"
            AppHost.RegisterService&lt;JournalSetLineServices&gt;();
            AppHost.Routes.Add(typeof(JournalSetLineGETRequest), "/JournalSets/{JournalSetID}/Lines/{JournalSetLineID}", "GET", "Retrieves a journal set line.", "");
            AppHost.Routes.Add(typeof(JournalSetLinesGETManyRequest), "/JournalSets/{JournalSetID}/Lines", "GET", "Retrieves a list of journal set lines.", "");
            AppHost.Routes.Add(typeof(JournalSetLinePOSTRequest), "/JournalSets/{JournalSetID}/Lines", "POST", "Appends a line to a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetLinePATCHRequest), "/JournalSets/{JournalSetID}/Lines/{JournalSetLineID}", "PATCH", "Updates a line for a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetLineDELETERequest), "/JournalSets/{JournalSetID}/Lines/{JournalSetLineID}", "DELETE", "Deletes a line from a journal set.", "");
            #endregion

            #region "Note Type"
            AppHost.RegisterService&lt;JournalSetNoteTypeServices&gt;();
            AppHost.Routes.Add(typeof(JournalSetNoteTypesGETManyRequest), "/JournalSets/NoteTypes", "GET", "Retrieves a list of journal set note types.", "");
            AppHost.Routes.Add(typeof(JournalSetNoteTypeGETRequest), "/JournalSets/NoteTypes/{NoteTypeID}", "GET", "Retrieves a journal set note type.", "");
            AppHost.Routes.Add(typeof(JournalSetNoteTypePOSTRequest), "/JournalSets/NoteTypes", "POST", "Creates a new journal set note type.", "");
            AppHost.Routes.Add(typeof(JournalSetNoteTypePATCHRequest), "/JournalSets/NoteTypes/{NoteTypeID}", "PATCH", "Updates a journal set note type.", "");
            AppHost.Routes.Add(typeof(JournalSetNoteTypeDELETERequest), "/JournalSets/NoteTypes/{NoteTypeID}", "DELETE", "Deletes a journal set note type.", "");
            #endregion

            #region "Note"
            AppHost.RegisterService&lt;JournalSetNoteServices&gt;();
            AppHost.Routes.Add(typeof(JournalSetNotesGETManyRequest), "/JournalSets/{JournalSetID}/Notes", "GET", "Retrieves a list of journal set notes.", "");
            AppHost.Routes.Add(typeof(JournalSetNoteGETRequest), "/JournalSets/{JournalSetID}/Notes/{NoteID}", "GET", "Retrieves a journal set note.", "");
            AppHost.Routes.Add(typeof(JournalSetNotePOSTRequest), "/JournalSets/{JournalSetID}/Notes", "POST", "Appends a note to a journal set.", "");
            AppHost.Routes.Add(typeof(JournalSetNotePATCHRequest), "/JournalSets/{JournalSetID}/Notes/{NoteID}", "PATCH", "Updates a journal set note.", "");
            AppHost.Routes.Add(typeof(JournalSetNoteDELETERequest), "/JournalSets/{JournalSetID}/Notes/{NoteID}", "DELETE", "Deletes a journal set note.", "");
            #endregion
            #endregion

            #region "Keep Alive"
            AppHost.RegisterService&lt;KeepAliveServices&gt;();
            AppHost.Routes.Add(typeof(KeepAliveGETRequest), "/KeepAlive", "GET", "Extends an authenticated users session", "");
            #endregion

            #region "Landed Cost"
            #region "BookIns"
            #region "{Main}"
            AppHost.RegisterService&lt;LandedCostBookInServices&gt;();
            AppHost.Routes.Add(typeof(LandedCostBookInGETRequest), "/BookIns/{BookInID}", "GET", "Retrieves a book in.", "");
            AppHost.Routes.Add(typeof(LandedCostBookInPATCHRequest), "/BookIns/{BookInID}", "PATCH", "Updates a book in.", "");
            AppHost.Routes.Add(typeof(LandedCostBookInSAVERequest), "/BookIns/Save", "GET", "Saves a stateful book in.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful book in item exists.");
            AppHost.Routes.Add(typeof(LandedCostBookInABANDONRequest), "/BookIns/Abandon", "DELETE", "Abandons a stateful book in.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful book in item exists.");
            AppHost.Routes.Add(typeof(LandedCostBookInCREATEFromShipmentIDRequest), "/BookIns/FromShipmentID/{ShipmentID}", "POST", "Creates a book in from the supplied shipment id.", "");
            AppHost.Routes.Add(typeof(LandedCostBookInCREATEFromShipmentNoRequest), "/BookIns/FromShipmentNo/{ShipmentNo}", "POST", "Creates a book in from the supplied shipment no.", "");
            AppHost.Routes.Add(typeof(LandedCostBookInACTIVATERequest), "/BookIns/Activate/{BookInID}", "POST", "Activates a book in.", "");
            #endregion

            #region "Lines"
            AppHost.RegisterService&lt;LandedCostBookInLineServices&gt;();
            AppHost.Routes.Add(typeof(LandedCostBookInLineGETRequest), "/BookIns/{BookInID}/Lines/{LineID}", "GET", "Retrieves a book in line.", "");
            AppHost.Routes.Add(typeof(LandedCostBookInLinesGETManyRequest), "/BookIns/{BookInID}/Lines", "GET", "Retrieves a list of book in lines.", "");
            AppHost.Routes.Add(typeof(LandedCostBookInLinePATCHRequest), "/BookIns/{BookInID}/Lines/{LineID}", "PATCH", "Updates a line for a book in.", "");
            AppHost.Routes.Add(typeof(LandedCostBookInLineDELETERequest), "/BookIns/{BookInID}/Lines/{LineID}", "DELETE", "Deletes a line from a book in.", "");
            #endregion
            #endregion

            #region "Shipments"
            #region "{Main}"
            AppHost.RegisterService&lt;LandedCostShipmentServices&gt;();
            AppHost.Routes.Add(typeof(LandedCostShipmentGETRequest), "/Shipments/{ShipmentID}", "GET", "Retrieves a shipment.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentPOSTRequest), "/Shipments", "POST", "Creates a shipment.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentPATCHRequest), "/Shipments/{ShipmentID}", "PATCH", "Updates a shipment.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentDELETERequest), "/Shipments/{ShipmentID}", "DELETE", "Deletes a shipment.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentSAVERequest), "/Shipments/Save", "GET", "Saves a stateful stateful shipment.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful shipment item exists.");
            AppHost.Routes.Add(typeof(LandedCostShipmentABANDONRequest), "/Shipments/Abandon", "DELETE", "Abandons a stateful shipment.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful shipment item exists.");
            AppHost.Routes.Add(typeof(LandedCostShipmentCREATEFromPORequest), "/Shipments/FromPurchaseOrders/{OrderNos}", "POST", "Creates a shipment from the supplied purchase orders.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentACTIVATERequest), "/Shipments/Activate/{ShipmentID}", "POST", "Activates a shipment.", "");
            #endregion

            #region "Purchase Orders"
            AppHost.RegisterService&lt;LandedCostShipmentPurchaseOrderServices&gt;();
            AppHost.Routes.Add(typeof(LandedCostShipmentPurchaseOrderGETRequest), "/Shipments/{ShipmentID}/PurchaseOrders/{OrderID}", "GET", "Retrieves a shipment purchase order.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentPurchaseOrdersGETManyRequest), "/Shipments/{ShipmentID}/PurchaseOrders", "GET", "Retrieves a list of shipment purchase orders.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentPurchaseOrderPOSTRequest), "/Shipments/{ShipmentID}/PurchaseOrders", "POST", "Appends a purchase order to a shipment.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentPurchaseOrderDELETERequest), "/Shipments/{ShipmentID}/PurchaseOrders/{OrderID}", "DELETE", "Deletes a purchase order from a shipment.", "");
            #endregion

            #region "Lines"
            AppHost.RegisterService&lt;LandedCostShipmentLineServices&gt;();
            AppHost.Routes.Add(typeof(LandedCostShipmentLineGETRequest), "/Shipments/{ShipmentID}/Lines/{LineID}", "GET", "Retrieves a shipment line.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentLinesGETManyRequest), "/Shipments/{ShipmentID}/Lines", "GET", "Retrieves a list of shipment lines.", "");
            AppHost.Routes.Add(typeof(LandedCostShipmentLinePATCHRequest), "/Shipments/{ShipmentID}/Lines/{LineID}", "PATCH", "Updates a line for a shipment.", "");
            #endregion
            #endregion
            #endregion

            #region "Languages"
            AppHost.RegisterService&lt;LanguageServices&gt;();
            AppHost.Routes.Add(typeof(LanguagesGETManyRequest), "/Languages", "GET", "Retrieves a list of languages.", "");
            AppHost.Routes.Add(typeof(LanguageGETRequest), "/Languages/{LanguageID}", "GET", "Retrieves a language.", "");
            AppHost.Routes.Add(typeof(LanguagePOSTRequest), "/Languages", "POST", "Creates a new language.", "");
            AppHost.Routes.Add(typeof(LanguagePATCHRequest), "/Languages/{LanguageID}", "PATCH", "Updates a language.", "");
            AppHost.Routes.Add(typeof(LanguageDELETERequest), "/Languages/{LanguageID}", "DELETE", "Deletes a language.", "");
            #endregion

            #region "Logging"
            if (debugMode)
            {
                AppHost.RegisterService&lt;RequestLogEntryQueryDataServices&gt;();
                AppHost.Routes.Add(typeof(TodayLogsGETManyRequest), "/Logs/Today", "GET", "Retrieves a list of log entries for today.", "");
                AppHost.Routes.Add(typeof(TodayErrorLogsGETManyRequest), "/Logs/Today/Errors", "GET", "Retrieves a list of error log entries for today.", "");
                AppHost.Routes.Add(typeof(YesterdayLogsGETManyRequest), "/Logs/Yesterday", "GET", "Retrieves a list of log entries for yesterday.", "");
                AppHost.Routes.Add(typeof(YesterdayErrorLogsGETManyRequest), "/Logs/Yesterday/Errors", "GET", "Retrieves a list of error log entries for yesterday.", "");
                AppHost.Routes.Add(typeof(QueryRequestLogsGETManyRequest), "/Logs", "GET", "Retrieves a list of log entries.", "");
                AppHost.Routes.Add(typeof(QueryRequestLogsGETManyRequest), "/Logs/{Date}", "GET", "Retrieves a list of log entries for a given date.", "");
            }
            #endregion

            #region "Logical Warehouse"
            AppHost.RegisterService&lt;LogicalWarehouseServices&gt;();
            AppHost.Routes.Add(typeof(LogicalWarehousesCurrentGETRequest), "/LogicalWarehouses/Current", "GET", "Retrieves the current logical warehouse.", "");
            AppHost.Routes.Add(typeof(LogicalWarehousesCurrentPATCHRequest), "/LogicalWarehouses/Current", "PATCH", "Sets the current logical warehouse.", "");
            #endregion
			
            #region "Purchase Order"
            #region "{Main}"
            AppHost.RegisterService&lt;PurchaseOrderServices&gt;();
            AppHost.Routes.Add(typeof(PurchaseOrderGETRequest), "/PurchaseOrders/{PurchaseOrderID}", "GET", "Retrieves a purchase order.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderPOSTRequest), "/PurchaseOrders/", "POST", "Creates a purchase order.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderPATCHRequest), "/PurchaseOrders/{PurchaseOrderID}", "PATCH", "Updates a purchase order.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderDELETERequest), "/PurchaseOrders/{PurchaseOrderID}", "DELETE", "Deletes a purchase order.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderSAVERequest), "/PurchaseOrders/Save", "GET", "Saves a stateful stateful purchase order.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful purchase order item exists.");
            AppHost.Routes.Add(typeof(PurchaseOrderABANDONRequest), "/PurchaseOrders/Abandon", "DELETE", "Abandons a stateful purchase order.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful purchase order item exists.");
            AppHost.Routes.Add(typeof(PurchaseOrderReceiveStockCREATEFromPOLinesRequest), "/PurchaseOrders/FromPurchaseOrderLines", "POST", "Creates a landed cost book in if the purchase order is on a shipment, otherwise creates a goods received note from the supplied list of ReceivedPOLineQuantity.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderACTIVATERequest), "/PurchaseOrders/Activate/{PurchaseOrderID}", "POST", "Sets the status of a purchase order to 'Sent'.", "");
            #endregion

            #region "Lines"
            AppHost.RegisterService&lt;PurchaseOrderLineServices&gt;();
            AppHost.Routes.Add(typeof(PurchaseOrderLineGETRequest), "/PurchaseOrders/{PurchaseOrderID}/Lines/{PurchaseOrderLineID}", "GET", "Retrieves a purchase order line.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderLinesGETManyRequest), "/PurchaseOrders/{PurchaseOrderID}/Lines", "GET", "Retrieves a list of purchase order lines.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderLinePOSTRequest), "/PurchaseOrders/{PurchaseOrderID}/Lines", "POST", "Appends a line to a purchase order.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderLinePATCHRequest), "/PurchaseOrders/{PurchaseOrderID}/Lines/{PurchaseOrderLineID}", "PATCH", "Updates a line for a purchase order.", "");
            AppHost.Routes.Add(typeof(PurchaseOrderLineDELETERequest), "/PurchaseOrders/{PurchaseOrderID}/Lines/{PurchaseOrderLineID}", "DELETE", "Deletes a line from a purchase order.", "");
            #endregion
            #endregion
			
			#region "Purchase Invoice"
			#region "{Main}"
			AppHost.RegisterService&lt;PurchaseInvoiceServices&gt;();
			AppHost.Routes.Add(typeof(PurchaseInvoiceGETRequest), "/PurchaseInvoices/{PurchaseInvoiceID}", "GET", "Retrieves a purchase invoice.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoicePOSTRequest), "/PurchaseInvoices", "POST", "Creates a purchase invoice.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoicePATCHRequest), "/PurchaseInvoices/{PurchaseInvoiceID}", "PATCH", "Updates a purchase invoice.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceDELETERequest), "/PurchaseInvoices/{PurchaseInvoiceID}", "DELETE", "Deletes a purchase invoice.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceSAVERequest), "/PurchaseInvoices/Save", "GET", "Saves a stateful stateful purchase invoice.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful purchase invoice item exists.");
			AppHost.Routes.Add(typeof(PurchaseInvoiceABANDONRequest), "/PurchaseInvoices/Abandon", "DELETE", "Abandons a stateful purchase invoice.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful purchase invoice item exists.");
			AppHost.Routes.Add(typeof(PurchaseInvoiceCREATEFromGRNRequest), "/PurchaseInvoices/FromGoodsReceivedNotes/{GRNNos}", "POST", "Creates a purchase invoice from the supplied goods received notes.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceACTIVATERequest), "/PurchaseInvoices/Activate/{PurchaseInvoiceID}", "POST", "Activates a purchase invoice.", "");
			#endregion

			#region "Goods Received Note"
			AppHost.RegisterService&lt;PurchaseInvoicePurchaseOrderServices&gt;();
			AppHost.Routes.Add(typeof(PurchaseInvoiceGoodsReceivedNoteGETRequest), "/PurchaseInvoices/{PurchaseInvoiceID}/GoodsReceivedNotes/{GRNID}", "GET", "Retrieves a purchase invoice goods received note.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceGoodsReceivedNotesGETManyRequest), "/PurchaseInvoices/{PurchaseInvoiceID}/GoodsReceivedNotes", "GET", "Retrieves a list of purchase invoice goods received notes.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceGoodsReceivedNotePOSTRequest), "/PurchaseInvoices/{PurchaseInvoiceID}/GoodsReceivedNotes", "POST", "Appends a goods received note to a purchase invoice.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceGoodsReceivedNoteDELETERequest), "/PurchaseInvoices/{PurchaseInvoiceID}/GoodsReceivedNotes/{GRNID}", "DELETE", "Deletes a goods received note from a purchase invoice.", "");
			#endregion

			#region "Lines"
			AppHost.RegisterService&lt;PurchaseInvoiceLineServices&gt;();
			AppHost.Routes.Add(typeof(PurchaseInvoiceLineGETRequest), "/PurchaseInvoices/{PurchaseInvoiceID}/Lines/{PurchaseInvoiceLineID}", "GET", "Retrieves a purchase invoice line.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceLinesGETManyRequest), "/PurchaseInvoices/{PurchaseInvoiceID}/PurchaseInvoiceLineID", "GET", "Retrieves a list of purchase invoice lines.", "");
			AppHost.Routes.Add(typeof(PurchaseInvoiceLinePATCHRequest), "/PurchaseInvoices/{PurchaseInvoiceID}/Lines/{PurchaseInvoiceLineID}", "PATCH", "Updates a line for a purchase invoice.", "");
			#endregion
			#endregion				

            #region "Queries - AutoQueries for Tables and Views in JiwaFinancials.Jiwa.JiwaServiceModel.Tables"
            // ServiceStack will automatically create the services for the routes added below - Any DTO which implements IQuery with a route added with no service
            // will have an AutoQuery service created automatically

			AppHost.Routes.Add(typeof(BM_MainQuery), "/Queries/BM_Main", "GET", "Retrieves a list of bills.", "");
			AppHost.Routes.Add(typeof(BM_WorkOrderQuery), "/Queries/BM_WorkOrder", "GET", "Retrieves a list of work orders.", "");
			
            AppHost.Routes.Add(typeof(CR_MainQuery), "/Queries/CR_Main", "GET", "Retrieves a list of creditors.", "");
            AppHost.Routes.Add(typeof(CR_WarehouseQuery), "/Queries/CR_Warehouse", "GET", "Retrieves a list of creditor warehouses.", "");

            AppHost.Routes.Add(typeof(DB_MainQuery), "/Queries/DB_Main", "GET", "Retrieves a list of debtors.", "");
            AppHost.Routes.Add(typeof(DB_CategoriesQuery), "/Queries/DB_Categories", "GET", "Retrieves a list of debtor categories.", "");
            AppHost.Routes.Add(typeof(DB_ClassificationQuery), "/Queries/DB_Classification", "GET", "Retrieves a list of debtor classifications.", "");
            AppHost.Routes.Add(typeof(DB_PricingGroupsQuery), "/Queries/DB_PricingGroups", "GET", "Retrieves a list of debtor pricing groups.", "");

            AppHost.Routes.Add(typeof(FR_CarriersQuery), "/Queries/FR_Carriers", "GET", "Retrieves a list of carriers.", "");

            AppHost.Routes.Add(typeof(FX_CurrencyQuery), "/Queries/FX_Currency", "GET", "Retrieves a list of currencies.", "");
            AppHost.Routes.Add(typeof(FX_CurrencyRatesQuery), "/Queries/FX_CurrencyRates", "GET", "Retrieves a list of currency rates.", "");

            AppHost.Routes.Add(typeof(GL_LedgerQuery), "/Queries/GL_Ledger", "GET", "Retrieves a list of general ledger accounts.", "");
            AppHost.Routes.Add(typeof(GL_CategoryQuery), "/Queries/GL_Category", "GET", "Retrieves a list of general ledger categories.", "");
            AppHost.Routes.Add(typeof(GL_SetsQuery), "/Queries/GL_Sets", "GET", "Retrieves a list of journal sets.", "");

            AppHost.Routes.Add(typeof(HR_DepartmentsQuery), "/Queries/HR_Departments", "GET", "Retrieves a list of departments.", "");
            AppHost.Routes.Add(typeof(HR_StaffQuery), "/Queries/HR_Staff", "GET", "Retrieves a list of staff members.", "");

            AppHost.Routes.Add(typeof(IN_AttributeGroupTemplateQuery), "/Queries/IN_AttributeGroupTemplate", "GET", "Retrieves a list of inventory attribute group templates.", "");
            AppHost.Routes.Add(typeof(IN_BinLocationLookupQuery), "/Queries/IN_BinLocationLookup", "GET", "Retrieves a list of bin locations.", "");
            AppHost.Routes.Add(typeof(IN_CategoriesQuery), "/Queries/IN_Categories", "GET", "Retrieves a list of inventory categories.", "");
            AppHost.Routes.Add(typeof(IN_ClassificationQuery), "/Queries/IN_Classification", "GET", "Retrieves a list of inventory classifications.", "");
            AppHost.Routes.Add(typeof(IN_LogicalQuery), "/Queries/IN_Logical", "GET", "Retrieves a list of logical warehouses.", "");
            AppHost.Routes.Add(typeof(IN_RegionQuery), "/Queries/IN_Region", "GET", "Retrieves a list of regions.", "");
            AppHost.Routes.Add(typeof(IN_MainQuery), "/Queries/IN_Main", "GET", "Retrieves a list of inventory items.", "");
            AppHost.Routes.Add(typeof(IN_SOHQuery), "/Queries/IN_SOH", "GET", "Retrieves a list of inventory stock transactionrecords.", "");
            AppHost.Routes.Add(typeof(IN_PhysicalQuery), "/Queries/IN_Physical", "GET", "Retrieves a list of physical warehouses.", "");
            AppHost.Routes.Add(typeof(IN_TransferQuery), "/Queries/IN_Transfer", "GET", "Retrieves a list of stock transfers.", "");

            AppHost.Routes.Add(typeof(PI_MainQuery), "/Queries/PI_Main", "GET", "Retrieves a list of purchase invoices.", "");
            AppHost.Routes.Add(typeof(PO_MainQuery), "/Queries/PO_Main", "GET", "Retrieves a list of purchase orders.", "");

            AppHost.Routes.Add(typeof(RE_MainQuery), "/Queries/RE_Main", "GET", "Retrieves a list of goods receipt notes.", "");
            AppHost.Routes.Add(typeof(SH_BookInMainQuery), "/Queries/SH_BookInMain", "GET", "Retrieves a list of shipment book ins.", "");

            AppHost.Routes.Add(typeof(SO_MainQuery), "/Queries/SO_Main", "GET", "Retrieves a list of sales orders.", "");
            AppHost.Routes.Add(typeof(QO_MainQuery), "/Queries/QO_Main", "GET", "Retrieves a list of sales quotes.", "");

            AppHost.Routes.Add(typeof(TX_MainQuery), "/Queries/TX_Main", "GET", "Retrieves a list of tax rates.", "");

            AppHost.Routes.Add(typeof(SY_BranchQuery), "/Queries/SY_Branch", "GET", "Retrieves a list of sales branches.", "");
            AppHost.Routes.Add(typeof(SY_PluginQuery), "/Queries/SY_Plugin", "GET", "Retrieves a list of plugins.", "");
            AppHost.Routes.Add(typeof(SY_ReportQuery), "/Queries/SY_Report", "GET", "Retrieves a list of reports.", "");
            AppHost.Routes.Add(typeof(SY_ReportSectionQuery), "/Queries/SY_ReportSection", "GET", "Retrieves a list of report sections.", "");

            AppHost.Routes.Add(typeof(IN_WarehouseSOHQuery), "/Queries/IN_WarehouseSOH", "GET", "Retrieves a list of inventory stock levels per warehouse.", "");

			AppHost.Routes.Add(typeof(SY_SysValuesQuery), "/Queries/SY_SysValues", "GET", "Retrieves a list of system settings.", "");
			
            AppHost.Routes.Add(typeof(SY_WebhookSubscriberQuery), "/Queries/SY_WebhookSubscriber", "GET", "Retrieves a list of webhook subscribers.", "");
            AppHost.Routes.Add(typeof(SY_WebhookSubscription), "/Queries/SY_WebhookSubscription", "GET", "Retrieves a list of webhook subscriptions.", "");
            AppHost.Routes.Add(typeof(SY_WebhookSubscriptionRequestHeader), "/Queries/SY_WebhookSubscriptionRequestHeader", "GET", "Retrieves a list of request headers for webhook subscriptions.", "");
            AppHost.Routes.Add(typeof(SY_WebhookMessage), "/Queries/SY_WebhookMessage", "GET", "Retrieves a list of webhook messages.", "");
            AppHost.Routes.Add(typeof(SY_WebhookMessageResponse), "/Queries/SY_WebhookMessageResponse", "GET", "Retrieves a list of webhook message responses.", "");

            AppHost.Routes.Add(typeof(v_Jiwa_Inventory_Item_ListQuery), "/Queries/InventoryItemList", "GET", "Retrieves a list of inventory items", "");
            AppHost.Routes.Add(typeof(v_Jiwa_SalesOrder_ListQuery), "/Queries/SalesOrderList", "GET", "Retrieves a list of sales orders", "");
			AppHost.Routes.Add(typeof(v_Jiwa_SalesQuote_ListQuery), "/Queries/SalesQuoteList", "GET", "Retrieves a list of sales quotes", "");
            AppHost.Routes.Add(typeof(v_Jiwa_Debtor_ListQuery), "/Queries/DebtorList", "GET", "Retrieves a list of debtors", "");

            AppHost.Routes.Add(typeof(WH_TransferQuery), "/Queries/WH_Transfer", "GET", "Retrieves a list of warehouse transfers.", "");
            #endregion

            #region "Region"
            AppHost.RegisterService&lt;RegionServices&gt;();
            AppHost.Routes.Add(typeof(RegionGETRequest), "/Regions/{RegionID}", "GET", "Retrieves a region.", "");
            AppHost.Routes.Add(typeof(RegionPOSTRequest), "/Regions", "POST", "Creates a region.", "");
            AppHost.Routes.Add(typeof(RegionPATCHRequest), "/Regions/{RegionID}", "PATCH", "Updates a region.", "");
            AppHost.Routes.Add(typeof(RegionDELETERequest), "/Regions/{RegionID}", "DELETE", "Deletes a region.", "");
            AppHost.Routes.Add(typeof(RegionSAVERequest), "/Regions/Save", "GET", "Saves a stateful region.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful region exists.");
            AppHost.Routes.Add(typeof(RegionABANDONRequest), "/Regions/Abandon", "DELETE", "Abandons a stateful region.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful region exists.");
            #endregion

            #region "Reports"
            AppHost.RegisterService&lt;ReportsServices&gt;();
            AppHost.Routes.Add(typeof(ReportsPDFGETRequest), "/Reports/{ReportID}/PDF/Download", "GET", "Retrieves PDF of the selected report.", "");
            #endregion

            #region "Rest Paths"
            AppHost.RegisterService&lt;RestPathServices&gt;();
            AppHost.Routes.Add(typeof(RestPathsGETManyRequest), "/RestPaths", "GET", "Retrieves a list of routes.", "");
            #endregion

            #region "Sales Order"
            AppHost.RegisterService&lt;SalesOrderServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderGETRequest), "/SalesOrders/{InvoiceID}", "GET", "Retrieves a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderPOSTRequest), "/SalesOrders", "POST", "Creates a new sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderPATCHRequest), "/SalesOrders/{InvoiceID}", "PATCH", "Updates a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderSAVERequest), "/SalesOrders/{InvoiceID}/Save", "GET", "Saves a stateful sales order.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful sales order exists.");
            AppHost.Routes.Add(typeof(SalesOrderPROCESSRequest), "/SalesOrders/{InvoiceID}/Process", "GET", "Processes a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderABANDONRequest), "/SalesOrders/{InvoiceID}/Abandon", "DELETE", "Abandons a stateful sales order.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful sales order exists.");

            #region "Custom Field"
            AppHost.RegisterService&lt;SalesOrderCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderCustomFieldsGETManyRequest), "/SalesOrders/CustomFields", "GET", "Retrieves a list of sales order custom fields.", "");
            AppHost.Routes.Add(typeof(SalesOrderCustomFieldGETRequest), "/SalesOrders/CustomFields/{SettingID}", "GET", "Retrieves a sales order custom field.", "");
            AppHost.Routes.Add(typeof(SalesOrderCustomFieldValuesGETManyRequest), "/SalesOrders/{InvoiceID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderCustomFieldValueGETRequest), "/SalesOrders/{InvoiceID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a sales order custom field value.", "");
            AppHost.Routes.Add(typeof(SalesOrderCustomFieldValuePATCHRequest), "/SalesOrders/{InvoiceID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a sales order custom field value.", "");
            #endregion

            #region "Document Types"
            AppHost.RegisterService&lt;SalesOrderDocumentTypeServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderDocumentTypesGETManyRequest), "/SalesOrders/DocumentTypes", "GET", "Retrieves a list of sales order document types.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentTypeGETRequest), "/SalesOrders/DocumentTypes/{DocumentTypeID}", "GET", "Retrieves a sales order document type.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentTypePOSTRequest), "/SalesOrders/DocumentTypes", "POST", "Creates a new sales order document type.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentTypePATCHRequest), "/SalesOrders/DocumentTypes/{DocumentTypeID}", "PATCH", "Updates a sales order document type.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentTypeDELETERequest), "/SalesOrders/DocumentTypes/{DocumentTypeID}", "DELETE", "Deletes a sales order document type.", "");
            #endregion

            #region "Documents"
            AppHost.RegisterService&lt;SalesOrderDocumentServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderDocumentsGETManyRequest), "/SalesOrders/{InvoiceID}/Documents", "GET", "Retrieves a list of sales order documents.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentGETRequest), "/SalesOrders/{InvoiceID}/Documents/{DocumentID}", "GET", "Retrieves a sales order document.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentPOSTRequest), "/SalesOrders/{InvoiceID}/Documents", "POST", "Appends a document to a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentPATCHRequest), "/SalesOrders/{InvoiceID}/Documents/{DocumentID}", "PATCH", "Updates a sales order document.", "");
            AppHost.Routes.Add(typeof(SalesOrderDocumentDELETERequest), "/SalesOrders/{InvoiceID}/Documents/{DocumentID}", "DELETE", "Deletes a sales order document.", "");
            #endregion

            #region "History"
            AppHost.RegisterService&lt;SalesOrderHistoryServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderHistorysGETManyRequest), "/SalesOrders/{InvoiceID}/Historys", "GET", "Retrieves a list of sales order histories.", "");
            AppHost.Routes.Add(typeof(SalesOrderHistorysGETRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}", "GET", "Retrieves a sales order history.", "");
            AppHost.Routes.Add(typeof(SalesOrderHistorysPATCHRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}", "PATCH", "Updates a sales order history.", "");
            #endregion

            #region "History Carrier Consignment Notes"
            AppHost.RegisterService&lt;SalesOrderHistoryCarrierConsignmentNoteServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderHistoryConsignmentNotesGETManyRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/ConsignmentNotes", "GET", "Retrieves consignment notes for a sales order history.", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryConsignmentNotesGETRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/ConsignmentNotes/{ConsignmentNoteID}", "GET", "Retrieves a consignment note for a sales order history", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryConsignmentNotesPOSTRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/ConsignmentNotes", "POST", "Adds a consignment note to a sales order history", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryConsignmentNotesPATCHRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/ConsignmentNotes/{ConsignmentNoteID}", "PATCH", "Updates a consignment note for a sales order history", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryConsignmentNotesDELETERequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/ConsignmentNotes/{ConsignmentNoteID}", "DELETE", "Deletes a consignment note from a sales order history", "");
            #endregion

            #region "History Carrier Freight Items"
            AppHost.RegisterService&lt;SalesOrderHistoryCarrierFreightItemServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderHistoryFreightItemsGETManyRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/FreightItems", "GET", "Retrieves freight items for a sales order history.", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryFreightItemsGETRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/FreightItems/{FreightItemID}", "GET", "Retrieves a freight item for a sales order history", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryFreightItemsPOSTRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/FreightItems", "POST", "Adds a freight item to a sales order history", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryFreightItemsPATCHRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/FreightItems/{FreightItemID}", "PATCH", "Updates a freight item for a sales order history", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryFreightItemsDELETERequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Carrier/FreightItems/{FreightItemID}", "DELETE", "Deletes a freight item from a sales order history", "");
            #endregion

            #region "History Custom Fields"
            AppHost.RegisterService&lt;SalesOrderHistoryCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderHistoryCustomFieldsGETManyRequest), "/SalesOrders/Historys/CustomFields", "GET", "Retrieves a list of sales order history custom fields.", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryCustomFieldValuesGETManyRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a sales order history.", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryCustomFieldValuesGETRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a sales order history custom field value.", "");
            AppHost.Routes.Add(typeof(SalesOrderHistoryCustomFieldValuesPATCHRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a sales order history custom field value.", "");
            #endregion

            #region "Line Custom Field"
            AppHost.RegisterService&lt;SalesOrderLineCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderLineCustomFieldsGETManyRequest), "/SalesOrders/Lines/CustomFields", "GET", "Retrieves a list of sales order line custom fields.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineCustomFieldGETRequest), "/SalesOrders/Lines/CustomFields/{SettingID}", "GET", "Retrieves a sales order line custom field.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineCustomFieldValuesGETManyRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a sales order line.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineCustomFieldValueGETRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a sales order line custom field value.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineCustomFieldValuePATCHRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a sales order line custom field value.", "");
            #endregion

            #region "Line"
            AppHost.RegisterService&lt;SalesOrderLineServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderLinesGETManyRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines", "GET", "Retrieves a list of sales order lines.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineGETRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}", "GET", "Retrieves a sales order line.", "");
            AppHost.Routes.Add(typeof(SalesOrderLinePOSTRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines", "POST", "Appends a line to a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderLinePATCHRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}", "PATCH", "Updates a sales order line.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineDELETERequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}", "DELETE", "Deletes a sales order line.", "");
            #endregion

            #region "Line Detail"
            AppHost.RegisterService&lt;SalesOrderLineDetailServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderLineDetailsGETManyRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/LineDetails", "GET", "Retrieves a list of line details for a sales order line.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineDetailGETRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/LineDetails/{DetailsLineID}", "GET", "Retrieves a sales order line detail.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineDetailPOSTRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/LineDetails", "POST", "Appends a line detail to a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineDetailPATCHRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/LineDetails/{DetailsLineID}", "PATCH", "Updates a sales order line detail.", "");
            AppHost.Routes.Add(typeof(SalesOrderLineDetailDELETERequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Lines/{InvoiceLineID}/LineDetails/{DetailsLineID}", "DELETE", "Deletes a sales order line detail.", "");
            #endregion

            #region "Note Type"
            AppHost.RegisterService&lt;SalesOrderNoteTypeServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderNoteTypesGETManyRequest), "/SalesOrders/NoteTypes", "GET", "Retrieves a list of sales order note types.", "");
            AppHost.Routes.Add(typeof(SalesOrderNoteTypeGETRequest), "/SalesOrders/NoteTypes/{NoteTypeID}", "GET", "Retrieves a sales order note type.", "");
            AppHost.Routes.Add(typeof(SalesOrderNoteTypePOSTRequest), "/SalesOrders/NoteTypes", "POST", "Creates a new sales order note type.", "");
            AppHost.Routes.Add(typeof(SalesOrderNoteTypePATCHRequest), "/SalesOrders/NoteTypes/{NoteTypeID}", "PATCH", "Updates a sales order note type.", "");
            AppHost.Routes.Add(typeof(SalesOrderNoteTypeDELETERequest), "/SalesOrders/NoteTypes/{NoteTypeID}", "DELETE", "Deletes a sales order note type.", "");
            #endregion

            #region "Note"
            AppHost.RegisterService&lt;SalesOrderNoteServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderNotesGETManyRequest), "/SalesOrders/{InvoiceID}/Notes", "GET", "Retrieves a list of sales order notes.", "");
            AppHost.Routes.Add(typeof(SalesOrderNoteGETRequest), "/SalesOrders/{InvoiceID}/Notes/{NoteID}", "GET", "Retrieves a sales order note.", "");
            AppHost.Routes.Add(typeof(SalesOrderNotePOSTRequest), "/SalesOrders/{InvoiceID}/Notes", "POST", "Appends a note to a sales order.", "");
            AppHost.Routes.Add(typeof(SalesOrderNotePATCHRequest), "/SalesOrders/{InvoiceID}/Notes/{NoteID}", "PATCH", "Updates a sales order note.", "");
            AppHost.Routes.Add(typeof(SalesOrderNoteDELETERequest), "/SalesOrders/{InvoiceID}/Notes/{NoteID}", "DELETE", "Deletes a sales order note.", "");
            #endregion

            #region "Payment Types"
            AppHost.RegisterService&lt;SalesOrderPaymentTypeServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderPaymentTypesGETManyRequest), "/SalesOrders/PaymentTypes", "GET", "Retrieves a list of payment types", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentTypesGETRequest), "/SalesOrders/PaymentTypes/{PaymentTypeID}", "GET", "Retrieves a payment type", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentTypesPOSTRequest), "/SalesOrders/PaymentTypes", "POST", "Adds a payment type", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentTypesPATCHRequest), "/SalesOrders/PaymentTypes/{PaymentTypeID}", "PATCH", "Updates a payment type", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentTypesDELETERequest), "/SalesOrders/PaymentTypes/{PaymentTypeID}", "DELETE", "Deletes a payment type", "");
            #endregion

            #region "Payments"
            AppHost.RegisterService&lt;SalesOrderPaymentServices&gt;();
            AppHost.Routes.Add(typeof(SalesOrderPaymentsGETManyRequest), "/SalesOrders/{InvoiceID}/Payments", "GET", "Retrieves a list of payments for a sales order", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentsGETRequest), "/SalesOrders/{InvoiceID}/Payments/{PaymentID}", "GET", "Retrieves a payment for a sales order", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentsPOSTRequest), "/SalesOrders/{InvoiceID}/Historys/{InvoiceHistoryID}/Payments", "POST", "Adds a payment to a sales order", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentsPATCHRequest), "/SalesOrders/{InvoiceID}/Payments/{PaymentID}", "PATCH", "Updates a payment for a sales order", "");
            AppHost.Routes.Add(typeof(SalesOrderPaymentsDELETERequest), "/SalesOrders/{InvoiceID}/Payments/{PaymentID}", "DELETE", "Deletes a payment for a sales order", "");
            #endregion
            #endregion

            #region "Sales Quote"
            AppHost.RegisterService&lt;SalesQuoteServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteGETRequest), "/SalesQuotes/{QuoteID}", "GET", "Retrieves a sales Quote.", "");
            AppHost.Routes.Add(typeof(SalesQuotePOSTRequest), "/SalesQuotes", "POST", "Creates a new sales Quote.", "");
            AppHost.Routes.Add(typeof(SalesQuotePATCHRequest), "/SalesQuotes/{QuoteID}", "PATCH", "Updates a sales Quote.", "");
            AppHost.Routes.Add(typeof(SalesQuoteSAVERequest), "/SalesQuotes/{QuoteID}/Save", "GET", "Saves a stateful sales Quote.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful sales Quote exists.");
            AppHost.Routes.Add(typeof(SalesQuoteMAKEORDERRequest), "/SalesQuotes/{QuoteID}/MakeOrder", "POST", "Makes a sales order from a quote.", "");
            AppHost.Routes.Add(typeof(SalesQuoteMAKEORDERB2BRequest), "/SalesQuotes/{QuoteID}/MakeOrderB2B", "POST", "Makes a back to back sales order from a quote.", "");
            AppHost.Routes.Add(typeof(SalesQuoteABANDONRequest), "/SalesQuotes/{QuoteID}/Abandon", "DELETE", "Abandons a stateful sales Quote.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful sales Quote exists.");

            #region "Custom Field"
            AppHost.RegisterService&lt;SalesQuoteCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteCustomFieldsGETManyRequest), "/SalesQuotes/CustomFields", "GET", "Retrieves a list of sales Quote custom fields.", "");
            AppHost.Routes.Add(typeof(SalesQuoteCustomFieldGETRequest), "/SalesQuotes/CustomFields/{SettingID}", "GET", "Retrieves a sales Quote custom field.", "");
            AppHost.Routes.Add(typeof(SalesQuoteCustomFieldValuesGETManyRequest), "/SalesQuotes/{QuoteID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a sales Quote.", "");
            AppHost.Routes.Add(typeof(SalesQuoteCustomFieldValueGETRequest), "/SalesQuotes/{QuoteID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a sales Quote custom field value.", "");
            AppHost.Routes.Add(typeof(SalesQuoteCustomFieldValuePATCHRequest), "/SalesQuotes/{QuoteID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a sales Quote custom field value.", "");
            #endregion

            #region "Document Types"
            AppHost.RegisterService&lt;SalesQuoteDocumentTypeServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteDocumentTypesGETManyRequest), "/SalesQuotes/DocumentTypes", "GET", "Retrieves a list of sales Quote document types.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentTypeGETRequest), "/SalesQuotes/DocumentTypes/{DocumentTypeID}", "GET", "Retrieves a sales Quote document type.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentTypePOSTRequest), "/SalesQuotes/DocumentTypes", "POST", "Creates a new sales Quote document type.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentTypePATCHRequest), "/SalesQuotes/DocumentTypes/{DocumentTypeID}", "PATCH", "Updates a sales Quote document type.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentTypeDELETERequest), "/SalesQuotes/DocumentTypes/{DocumentTypeID}", "DELETE", "Deletes a sales Quote document type.", "");
            #endregion

            #region "Documents"
            AppHost.RegisterService&lt;SalesQuoteDocumentServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteDocumentsGETManyRequest), "/SalesQuotes/{QuoteID}/Documents", "GET", "Retrieves a list of sales Quote documents.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentGETRequest), "/SalesQuotes/{QuoteID}/Documents/{DocumentID}", "GET", "Retrieves a sales Quote document.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentPOSTRequest), "/SalesQuotes/{QuoteID}/Documents", "POST", "Appends a document to a sales Quote.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentPATCHRequest), "/SalesQuotes/{QuoteID}/Documents/{DocumentID}", "PATCH", "Updates a sales Quote document.", "");
            AppHost.Routes.Add(typeof(SalesQuoteDocumentDELETERequest), "/SalesQuotes/{QuoteID}/Documents/{DocumentID}", "DELETE", "Deletes a sales Quote document.", "");
            #endregion

            #region "History"
            AppHost.RegisterService&lt;SalesQuoteHistoryServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteHistorysGETManyRequest), "/SalesQuotes/{QuoteID}/Historys", "GET", "Retrieves a list of sales Quote histories.", "");
            AppHost.Routes.Add(typeof(SalesQuoteHistorysGETRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}", "GET", "Retrieves a sales Quote history.", "");
            AppHost.Routes.Add(typeof(SalesQuoteHistorysPATCHRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}", "PATCH", "Updates a sales Quote history.", "");
            #endregion

            #region "Line Custom Field"
            AppHost.RegisterService&lt;SalesQuoteLineCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteLineCustomFieldsGETManyRequest), "/SalesQuotes/Lines/CustomFields", "GET", "Retrieves a list of sales Quote line custom fields.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLineCustomFieldGETRequest), "/SalesQuotes/Lines/CustomFields/{SettingID}", "GET", "Retrieves a sales Quote line custom field.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLineCustomFieldValuesGETManyRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines/{QuoteLineID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a sales Quote line.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLineCustomFieldValueGETRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines/{QuoteLineID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a sales Quote line custom field value.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLineCustomFieldValuePATCHRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines/{QuoteLineID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a sales Quote line custom field value.", "");
            #endregion

            #region "Line"
            AppHost.RegisterService&lt;SalesQuoteLineServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteLinesGETManyRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines", "GET", "Retrieves a list of sales Quote lines.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLineGETRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines/{QuoteLineID}", "GET", "Retrieves a sales Quote line.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLinePOSTRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines", "POST", "Appends a line to a sales Quote.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLinePATCHRequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines/{QuoteLineID}", "PATCH", "Updates a sales Quote line.", "");
            AppHost.Routes.Add(typeof(SalesQuoteLineDELETERequest), "/SalesQuotes/{QuoteID}/Historys/{QuoteHistoryID}/Lines/{QuoteLineID}", "DELETE", "Deletes a sales Quote line.", "");
            #endregion

            #region "Note Type"
            AppHost.RegisterService&lt;SalesQuoteNoteTypeServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteNoteTypesGETManyRequest), "/SalesQuotes/NoteTypes", "GET", "Retrieves a list of sales Quote note types.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNoteTypeGETRequest), "/SalesQuotes/NoteTypes/{NoteTypeID}", "GET", "Retrieves a sales Quote note type.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNoteTypePOSTRequest), "/SalesQuotes/NoteTypes", "POST", "Creates a new sales Quote note type.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNoteTypePATCHRequest), "/SalesQuotes/NoteTypes/{NoteTypeID}", "PATCH", "Updates a sales Quote note type.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNoteTypeDELETERequest), "/SalesQuotes/NoteTypes/{NoteTypeID}", "DELETE", "Deletes a sales Quote note type.", "");
            #endregion

            #region "Note"
            AppHost.RegisterService&lt;SalesQuoteNoteServices&gt;();
            AppHost.Routes.Add(typeof(SalesQuoteNotesGETManyRequest), "/SalesQuotes/{QuoteID}/Notes", "GET", "Retrieves a list of sales Quote notes.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNoteGETRequest), "/SalesQuotes/{QuoteID}/Notes/{NoteID}", "GET", "Retrieves a sales Quote note.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNotePOSTRequest), "/SalesQuotes/{QuoteID}/Notes", "POST", "Appends a note to a sales Quote.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNotePATCHRequest), "/SalesQuotes/{QuoteID}/Notes/{NoteID}", "PATCH", "Updates a sales Quote note.", "");
            AppHost.Routes.Add(typeof(SalesQuoteNoteDELETERequest), "/SalesQuotes/{QuoteID}/Notes/{NoteID}", "DELETE", "Deletes a sales Quote note.", "");
            #endregion

            #endregion

            #region "Service Control"
            // Add service control to allow service stops via the API (can't restart self hosted, but you can stop and use the service properties restart on failure restart it)
            AppHost.RegisterService&lt;ServiceControlServices&gt;();
            AppHost.Routes.Add(typeof(RestartRequest), "/Services/Restart", "GET", "Restarts the API site.", "");
            AppHost.Routes.Add(typeof(StopRequest), "/Services/Stop", "GET", "Stops the API Service.", "");
            #endregion

            #region "Staff"
            AppHost.RegisterService&lt;StaffServices&gt;();
			if (debugMode)
			{				
				AppHost.Routes.Add(typeof(AuthUserSessionsGETRequest), "/Sessions", "GET", "Retrieves a list of session information.", "");
				AppHost.Routes.Add(typeof(ManagerInstancesGETRequest), "/ManagerInstances", "GET", "Retrieves a list of JiwaApplication.Manager instance information.", "");
			}
			
            AppHost.Routes.Add(typeof(StaffCurrentUserGETRequest), "/Staff/Current", "GET", "Retrieves the current user.", "");
            AppHost.Routes.Add(typeof(StaffCurrentUserListGETRequest), "/Staff/Current/List", "GET", "Retrieves a list of all REST API session users.", "");
            #endregion
			
			#region "Startup Diagnostics"
            AppHost.RegisterService&lt;StartupDiagnosticsServices&gt;();
            AppHost.Routes.Add(typeof(StartupLogEntryQuery), "/Queries/StartupLog", "GET", "Retrieves a list of logon diagnostics (populated when authenticating).", "");
            AppHost.Routes.Add(typeof(PluginExceptionQuery), "/Queries/PluginExceptions", "GET", "Retrieves a list of plugin exceptions (populated when authenticating).", "");
            #endregion

            #region "Stock Transfer"
            AppHost.RegisterService&lt;StockTransferServices&gt;();
            AppHost.Routes.Add(typeof(StockTransferPOSTRequest), "/StockTransfers/", "POST", "Creates a stock transfer.", "");
            AppHost.Routes.Add(typeof(StockTransferGETRequest), "/StockTransfers/{TransferID}", "GET", "Retrieves a stock transfer.", "");
            AppHost.Routes.Add(typeof(StockTransferDELETERequest), "/StockTransfers/{TransferID}", "DELETE", "Deletes a stock transfer.", "");
            #endregion
			
			#region "Supplier Returns"
				AppHost.RegisterService&lt;SupplierReturnCreditServices&gt;();
				AppHost.Routes.Add(typeof(SupplierReturnCreditGETRequest), "/SupplierReturns/Credit/{CreditID}", "GET", "Retrieves a supplier return credit.", "");
				AppHost.Routes.Add(typeof(SupplierReturnCreditCreateFromShipmentsRequest), "/SupplierReturns/Credit/FromShipments", "POST", "Creates a supplier return credit from one or more shipments.", "");
				AppHost.Routes.Add(typeof(SupplierReturnCreditACTIVATERequest), "/SupplierReturns/Credit/Activate/{CreditID}", "POST", "Activates a supplier return credit.", "");
			
				AppHost.RegisterService&lt;SupplierReturnShippingServices&gt;();				
				AppHost.Routes.Add(typeof(SupplierReturnShippingGETRequest), "/SupplierReturns/Shipping/{ShippingID}", "GET", "Retrieves a supplier return shipping.", "");
			#endregion

            #region "System Information"
            AppHost.RegisterService&lt;SystemInformationServices&gt;();
            AppHost.Routes.Add(typeof(SystemInformationGETRequest), "/SystemInfo/", "GET", "Retrieves system information.", "");
            #endregion

            #region "Tax Rates"				
            AppHost.RegisterService&lt;TaxRateServices&gt;();
            AppHost.Routes.Add(typeof(TaxRateGETRequest), "/TaxRates/{TaxID}", "GET", "Retrieves a tax rate.", "");
            AppHost.Routes.Add(typeof(TaxRatePOSTRequest), "/TaxRates", "POST", "Creates a tax rate.", "");
            AppHost.Routes.Add(typeof(TaxRatePATCHRequest), "/TaxRates/{TaxID}", "PATCH", "Updates a tax rate.", "");
            AppHost.Routes.Add(typeof(TaxRateDELETERequest), "/TaxRates/{TaxID}", "DELETE", "Deletes a tax rate.", "");
            AppHost.Routes.Add(typeof(TaxRateSAVERequest), "/TaxRates/Save", "GET", "Saves a stateful TaxRate collection.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful TaxRate collection exists.");
            AppHost.Routes.Add(typeof(TaxRateABANDONRequest), "/TaxRates/Abandon", "DELETE", "Abandons a stateful TaxRate collection.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful TaxRate collection exists.");
            #endregion

            #region "User Setting"
            AppHost.RegisterService&lt;UserSettingServices&gt;();
            AppHost.Routes.Add(typeof(UserSettingsGETManyRequest), "/UserSettings", "GET", "Retreives a list of user settings for the currently logged in user.", "");
            AppHost.Routes.Add(typeof(UserSettingPOSTRequest), "/UserSettings", "POST", "Creates or updates a user setting for the currently logged in user.", "");
            #endregion

            #region "Warehouse Transfer Out"
            #region "{Main}"
            AppHost.RegisterService&lt;WarehouseTransferOutServices&gt;();
            AppHost.Routes.Add(typeof(WarehouseTransferOutGETRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}", "GET", "Retrieves a warehouse transfer out.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutPOSTRequest), "/WarehouseTransfersOut", "POST", "Creates a warehouse transfer out.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutPATCHRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}", "PATCH", "Updates a warehouse transfer out.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutCANCELRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}", "DELETE", "Cancels a warehouse transfer out.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutSAVERequest), "/WarehouseTransfersOut/Save", "GET", "Saves a stateful stateful warehouse transfer out.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful warehouse transfer out item exists.");
            AppHost.Routes.Add(typeof(WarehouseTransferOutABANDONRequest), "/WarehouseTransfersOut/Abandon", "DELETE", "Abandons a stateful warehouse transfer out.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful warehouse transfer out item exists.");
            AppHost.Routes.Add(typeof(WarehouseTransferOutACTIVATERequest), "/WarehouseTransfersOut/Activate/{WarehouseTransferOutID}", "POST", "Activates a warehouse transfer out.", "");
            #endregion

            #region "Receive Ins"
            AppHost.RegisterService&lt;WarehouseTransferOutReceiveInServices&gt;();
            AppHost.Routes.Add(typeof(WarehouseTransferOutReceiveInsGETManyRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}/ReceiveIns", "GET", "Retrieves a list of warehouse transfer out receive ins.", "");
            #endregion

            #region "Lines"
            AppHost.RegisterService&lt;WarehouseTransferOutLineServices&gt;();
            AppHost.Routes.Add(typeof(WarehouseTransferOutLineGETRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}/Lines/{WarehouseTransferOutLineID}", "GET", "Retrieves a warehouse transfer out line.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutLinesGETManyRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}/Lines", "GET", "Retrieves a list of warehouse transfer out lines.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutLinePOSTRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}/Lines", "POST", "Appends a line to a warehouse transfer out.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutLinePATCHRequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}/Lines/{WarehouseTransferOutLineID}", "PATCH", "Updates a line for a warehouse transfer out.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferOutLineDELETERequest), "/WarehouseTransfersOut/{WarehouseTransferOutID}/Lines/{WarehouseTransferOutLineID}", "DELETE", "Deletes a line from a warehouse transfer out.", "");
            #endregion
            #endregion

            #region "Warehouse Transfer In"
            #region "{Main}"
            AppHost.RegisterService&lt;WarehouseTransferInServices&gt;();
            AppHost.Routes.Add(typeof(WarehouseTransferInGETRequest), "/WarehouseTransfersIn/{WarehouseTransferInID}", "GET", "Retrieves a warehouse transfer in.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferInPOSTRequest), "/WarehouseTransfersIn", "POST", "Creates a warehouse transfer in.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferInPATCHRequest), "/WarehouseTransfersIn/{WarehouseTransferInID}", "PATCH", "Updates a warehouse transfer in.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferInSAVERequest), "/WarehouseTransfersIn/Save", "GET", "Saves a stateful stateful warehouse transfer in.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful warehouse transfer in item exists.");
            AppHost.Routes.Add(typeof(WarehouseTransferInABANDONRequest), "/WarehouseTransfersIn/Abandon", "DELETE", "Abandons a stateful warehouse transfer in.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful stateful warehouse transfer in item exists.");
            AppHost.Routes.Add(typeof(WarehouseTransferInACTIVATERequest), "/WarehouseTransfersIn/Activate/{WarehouseTransferInID}", "POST", "Activates a warehouse transfer in.", "");
            #endregion

            #region "Receive Ins"
            AppHost.RegisterService&lt;WarehouseTransferInReceiveInServices&gt;();
            AppHost.Routes.Add(typeof(WarehouseTransferInReceiveInsGETManyRequest), "/WarehouseTransfersIn/{WarehouseTransferInID}/ReceiveIns", "GET", "Retrieves a list of warehouse transfer in receive ins.", "");
            #endregion

            #region "Lines"
            AppHost.RegisterService&lt;WarehouseTransferInLineServices&gt;();
            AppHost.Routes.Add(typeof(WarehouseTransferInLineGETRequest), "/WarehouseTransfersIn/{WarehouseTransferInID}/Lines/{WarehouseTransferInLineID}", "GET", "Retrieves a warehouse transfer in line.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferInLinesGETManyRequest), "/WarehouseTransfersIn/{WarehouseTransferInID}/Lines", "GET", "Retrieves a list of warehouse transfer in lines.", "");
            AppHost.Routes.Add(typeof(WarehouseTransferInLinePATCHRequest), "/WarehouseTransfersIn/{WarehouseTransferInID}/Lines/{WarehouseTransferInLineID}", "PATCH", "Updates a line for a warehouse transfer in.", "");
            #endregion
            #endregion

            #region "Webhooks"
            AppHost.RegisterService&lt;WebhookServices&gt;();
            AppHost.Routes.Add(typeof(WebhooksSubscribersGETManyRequest), "/Webhooks/Subscribers/", "GET", "Retrieves a list of Webhook subscribers.", "");
            AppHost.Routes.Add(typeof(WebhooksSubscribersGETRequest), "/Webhooks/Subscribers/{SubscriberID}", "GET", "Retrieves a Webhook subscriber.", "");
            AppHost.Routes.Add(typeof(WebhooksSubscribersPOSTRequest), "/Webhooks/Subscribers/", "POST", "Adds a Webhook subscriber.", "");
            AppHost.Routes.Add(typeof(WebhooksSubscribersPATCHRequest), "/Webhooks/Subscribers/{SubscriberID}/", "PATCH", "Updates a Webhook subscriber.", "");
            AppHost.Routes.Add(typeof(WebhooksSubscribersDELETERequest), "/Webhooks/Subscribers/{SubscriberID}/", "DELETE", "Removes a Webhook subscriber.", "");

            /* These routes require no athentication, as providing the SubscriberID in the route / DTO acts as a API Key */
            AppHost.Routes.Add(typeof(WebhooksSubscriptionsGETRequest), "/Webhooks/Subscribers/{SubscriberID}/Subscriptions/", "GET", "Retrieves a list of all Webhook subscriptions for a subscriber.", "");
            AppHost.Routes.Add(typeof(WebhooksSubscriptionsPOSTRequest), "/Webhooks/Subscribers/{SubscriberID}/Subscriptions/", "POST", "Adds a Webhook subscription for a subscriber.", "");
            AppHost.Routes.Add(typeof(WebhooksSubscriptionsPATCHRequest), "/Webhooks/Subscribers/{SubscriberID}/Subscriptions/", "PATCH", "Updates a Webhook subscription for a subscriber.", "");
            AppHost.Routes.Add(typeof(WebhooksSubscriptionsDELETERequest), "/Webhooks/Subscribers/{SubscriberID}/Subscriptions/{SubscriptionID}/", "DELETE", "Removes a Webhook subscription for a subscriber.", "");

            AppHost.Routes.Add(typeof(WebhooksMessagesGETRequest), "/Webhooks/Subscribers/{SubscriberID}/Messages", "GET", "Retrieves a list of all Webhook messages for a subscriber.", "");
            AppHost.Routes.Add(typeof(WebhooksMessagesDELETERequest), "/Webhooks/Subscribers/{SubscriberID}/Subscriptions/{SubscriptionID}/Messages/{MessageID}", "DELETE", "Removes a Webhook message for a subscription.", "");

            AppHost.Routes.Add(typeof(WebhooksMessageResponsesGETRequest), "/Webhooks/Subscribers/{SubscriberID}/Messages/Responses", "GET", "Retrieves a list of all Webhook messages responses for a subscriber.", "");

            AppHost.Routes.Add(typeof(WebhooksEventsGETRequest), "/Webhooks/Events/", "GET", "Lists available events", "");
            AppHost.Routes.Add(typeof(WebhooksEventsPOSTRequest), "/Webhooks/Events/", "POST", "Adds an event occurance.  Used by Jiwa clients to cause webhooks to be sent to subscribers. Not intended to be invoked externally", "");

            AppHost.Routes.Add(typeof(WebhooksTestPOSTRequest), "/Webhooks/Test/", "POST", "Test route for sending webhooks to. Use this as the URL to direct a webhook subscription to.", "");
            #endregion
			
			#region "Work Orders"
			#region "{Main}"
            AppHost.RegisterService&lt;WorkOrderServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderGETRequest), "/WorkOrders/{WorkOrderID}", "GET", "Retrieves a work order record.", "");
            AppHost.Routes.Add(typeof(WorkOrderPOSTRequest), "/WorkOrders", "POST", "Creates a new work order record.", "");
            AppHost.Routes.Add(typeof(WorkOrderPATCHRequest), "/WorkOrders/{WorkOrderID}", "PATCH", "Updates a work order record.", "");
			AppHost.Routes.Add(typeof(WorkOrderDELETERequest), "/WorkOrders/{WorkOrderID}", "DELETE", "Deletes a work order record.", "");
            AppHost.Routes.Add(typeof(WorkOrderSAVERequest), "/WorkOrders/{WorkOrderID}/Save", "GET", "Saves a stateful work order record.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful work order record exists.");
            AppHost.Routes.Add(typeof(WorkOrderABANDONRequest), "/WorkOrders/{WorkOrderID}/Abandon", "DELETE", "Abandons a stateful work order record.", "Requires a request header of 'jiwa-stateful' be set to 'true', and also that a stateful work order record exists.");
			#endregion	
			
			#region "Allocations"
			AppHost.RegisterService&lt;WorkOrderAllocationServices&gt;();
			AppHost.Routes.Add(typeof(WorkOrderAllocationsGETManyRequest), "/WorkOrders/{WorkOrderID}/Allocations", "GET", "Retrieves a list of allocations for a work order record.", "");
			AppHost.Routes.Add(typeof(WorkOrderAllocationGETRequest), "/WorkOrders/{WorkOrderID}/Allocations/{AllocationID}", "GET", "Retrieves a work order allocation.", "");
			AppHost.Routes.Add(typeof(WorkOrderAllocationPOSTRequest), "/WorkOrders/{WorkOrderID}/Allocations", "POST", "Appends an allocation to a work order record.", "");
			AppHost.Routes.Add(typeof(WorkOrderAllocationDELETERequest), "/WorkOrders/{WorkOrderID}/Allocations/{AllocationID}", "DELETE", "Deletes a work order record allocation.", "");
			#endregion
			
            #region "Custom Fields"
            AppHost.RegisterService&lt;WorkOrderCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderCustomFieldsGETManyRequest), "/WorkOrders/CustomFields", "GET", "Retrieves a list of work order custom fields.", "");
            AppHost.Routes.Add(typeof(WorkOrderCustomFieldGETRequest), "/WorkOrders/CustomFields/{SettingID}", "GET", "Retrieves a work order custom field.", "");
            AppHost.Routes.Add(typeof(WorkOrderCustomFieldValuesGETManyRequest), "/WorkOrders/{WorkOrderID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a work order record.", "");
            AppHost.Routes.Add(typeof(WorkOrderCustomFieldValueGETRequest), "/WorkOrders/{WorkOrderID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a work order record custom field value.", "");
            AppHost.Routes.Add(typeof(WorkOrderCustomFieldValuePATCHRequest), "/WorkOrders/{WorkOrderID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a work order record custom field value.", "");
            #endregion			
			
            #region "Document Types"
            AppHost.RegisterService&lt;WorkOrderDocumentTypeServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderDocumentTypesGETManyRequest), "/WorkOrders/DocumentTypes", "GET", "Retrieves a list of work order document types.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentTypeGETRequest), "/WorkOrders/DocumentTypes/{DocumentTypeID}", "GET", "Retrieves a work order document type.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentTypePOSTRequest), "/WorkOrders/DocumentTypes", "POST", "Creates a new work order document type.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentTypePATCHRequest), "/WorkOrders/DocumentTypes/{DocumentTypeID}", "PATCH", "Updates a work order document type.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentTypeDELETERequest), "/WorkOrders/DocumentTypes/{DocumentTypeID}", "DELETE", "Deletes a work order document type.", "");
            #endregion	
			
            #region "Documents"
            AppHost.RegisterService&lt;WorkOrderDocumentServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderDocumentsGETManyRequest), "/WorkOrders/{WorkOrderID}/Documents", "GET", "Retrieves a list of work order record documents.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentGETRequest), "/WorkOrders/{WorkOrderID}/Documents/{DocumentID}", "GET", "Retrieves a work order record document.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentPOSTRequest), "/WorkOrders/{WorkOrderID}/Documents", "POST", "Appends a document to a work order record.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentPATCHRequest), "/WorkOrders/{WorkOrderID}/Documents/{DocumentID}", "PATCH", "Updates a work order record document.", "");
            AppHost.Routes.Add(typeof(WorkOrderDocumentDELETERequest), "/WorkOrders/{WorkOrderID}/Documents/{DocumentID}", "DELETE", "Deletes a work order record document.", "");
            #endregion			
			
            #region "Input Custom Fields"
            AppHost.RegisterService&lt;WorkOrderInputCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderInputCustomFieldsGETManyRequest), "/WorkOrders/Inputs/CustomFields", "GET", "Retrieves a list of work order input custom fields.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputCustomFieldGETRequest), "/WorkOrders/Inputs/CustomFields/{SettingID}", "GET", "Retrieves a work order input custom field.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputCustomFieldValuesGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a work order input.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputCustomFieldValueGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a work order input custom field value.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputCustomFieldValuePATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a work order input custom field value.", "");
            #endregion	
			
            #region "Input Line Details"
            AppHost.RegisterService&lt;WorkOrderInputLineDetailServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderInputLineDetailsGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/LineDetails", "GET", "Retrieves a list of line details for a work order stage input.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputLineDetailGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/LineDetails/{LineDetailID}", "GET", "Retrieves a work order stage input line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputLineDetailPOSTRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/LineDetails", "POST", "Appends a line detail to a work order stage input.", "");
			AppHost.Routes.Add(typeof(WorkOrderInputLineDetailPUTRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/LineDetails", "PUT", "Sets the line details for a work order stage input line. Existing line details for that line will be replaced.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputLineDetailPATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/LineDetails/{LineDetailID}", "PATCH", "Updates a work order stage input line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputLineDetailDELETERequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/LineDetails/{LineDetailID}", "DELETE", "Deletes a work order stage input line detail.", "");
            #endregion
			
            #region "Input Wastage Line Details"
            AppHost.RegisterService&lt;WorkOrderInputWastageLineDetailServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderInputWastageLineDetailsGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/WastageLineDetails", "GET", "Retrieves a list of wastage line details for a work order stage input.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputWastageLineDetailGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/WastageLineDetails/{LineDetailID}", "GET", "Retrieves a work order stage input wastage line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputWastageLineDetailPOSTRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/WastageLineDetails", "POST", "Appends a wastage line detail to a work order stage input.", "");
			AppHost.Routes.Add(typeof(WorkOrderInputWastageLineDetailPUTRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/WastageLineDetails", "PUT", "Sets the wastage line details for a work order stage input line. Existing wastage line details for that line will be replaced.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputWastageLineDetailPATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/WastageLineDetails/{LineDetailID}", "PATCH", "Updates a work order stage input wastage line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputWastageLineDetailDELETERequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}/WastageLineDetails/{LineDetailID}", "DELETE", "Deletes a work order stage input wastage line detail.", "");
            #endregion			
			
            #region "Inputs"
            AppHost.RegisterService&lt;WorkOrderInputServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderInputsGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs", "GET", "Retrieves inputs for a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderInputGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}", "GET", "Retrieves an input for a work order stage", "");
            AppHost.Routes.Add(typeof(WorkOrderInputPOSTRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs", "POST", "Adds an input to a work order stage", "");
            AppHost.Routes.Add(typeof(WorkOrderInputPATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}", "PATCH", "Updates an input for a work order stage", "");
            AppHost.Routes.Add(typeof(WorkOrderInputDELETERequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Inputs/{InputID}", "DELETE", "Deletes an input from a work order stage", "");
            #endregion			
			
			#region "Instruction Custom Fields"
            AppHost.RegisterService&lt;WorkOrderInstructionCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderInstructionCustomFieldsGETManyRequest), "/WorkOrders/Instructions/CustomFields", "GET", "Retrieves a list of work order instruction custom fields.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionCustomFieldGETRequest), "/WorkOrders/Instructions/CustomFields/{SettingID}", "GET", "Retrieves a work order instruction custom field.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionCustomFieldValuesGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions/{InstructionID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a work order instruction.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionCustomFieldValueGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions/{InstructionID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a work order instruction custom field value.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionCustomFieldValuePATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions/{InstructionID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a work order instruction custom field value.", "");
            #endregion	

            #region "Instructions"
            AppHost.RegisterService&lt;WorkOrderInstructionServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderInstructionsGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions", "GET", "Retrieves a list of instructions for a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions/{InstructionID}", "GET", "Retrieves an instruction for a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionPOSTRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions", "POST", "Adds an instruction to a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionPATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions/{InstructionID}", "PATCH", "Updates an instruction for a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderInstructionDELETERequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/Instructions/{InstructionID}", "DELETE", "Deletes an instruction from a work order stage.", "");
            #endregion			
			
            #region "Note Types"
            AppHost.RegisterService&lt;WorkOrderNoteTypeServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderNoteTypesGETManyRequest), "/WorkOrders/NoteTypes", "GET", "Retrieves a list of work order note types.", "");
            AppHost.Routes.Add(typeof(WorkOrderNoteTypeGETRequest), "/WorkOrders/NoteTypes/{NoteTypeID}", "GET", "Retrieves a work order note type.", "");
            AppHost.Routes.Add(typeof(WorkOrderNoteTypePOSTRequest), "/WorkOrders/NoteTypes", "POST", "Creates a new work order note type.", "");
            AppHost.Routes.Add(typeof(WorkOrderNoteTypePATCHRequest), "/WorkOrders/NoteTypes/{NoteTypeID}", "PATCH", "Updates a work order note type.", "");
            AppHost.Routes.Add(typeof(WorkOrderNoteTypeDELETERequest), "/WorkOrders/NoteTypes/{NoteTypeID}", "DELETE", "Deletes a work order note type.", "");
            #endregion

            #region "Notes"
            AppHost.RegisterService&lt;WorkOrderNoteServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderNotesGETManyRequest), "/WorkOrders/{WorkOrderID}/Notes", "GET", "Retrieves a list of work order record notes.", "");
            AppHost.Routes.Add(typeof(WorkOrderNoteGETRequest), "/WorkOrders/{WorkOrderID}/Notes/{NoteID}", "GET", "Retrieves a work order record note.", "");
            AppHost.Routes.Add(typeof(WorkOrderNotePOSTRequest), "/WorkOrders/{WorkOrderID}/Notes", "POST", "Appends a note to a work order record.", "");
            AppHost.Routes.Add(typeof(WorkOrderNotePATCHRequest), "/WorkOrders/{WorkOrderID}/Notes/{NoteID}", "PATCH", "Updates a work order record note.", "");
            AppHost.Routes.Add(typeof(WorkOrderNoteDELETERequest), "/WorkOrders/{WorkOrderID}/Notes/{NoteID}", "DELETE", "Deletes a work order record note.", "");
            #endregion						
			
            #region "Output Custom Fields"
            AppHost.RegisterService&lt;WorkOrderOutputCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderOutputCustomFieldsGETManyRequest), "/WorkOrders/Outputs/CustomFields", "GET", "Retrieves a list of work order output custom fields.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputCustomFieldGETRequest), "/WorkOrders/Outputs/CustomFields/{SettingID}", "GET", "Retrieves a work order output custom field.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputCustomFieldValuesGETManyRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a work order output.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputCustomFieldValueGETRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a work order output custom field value.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputCustomFieldValuePATCHRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a work order output custom field value.", "");
            #endregion	
			
            #region "Output Line Details"
            AppHost.RegisterService&lt;WorkOrderOutputLineDetailServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderOutputLineDetailsGETManyRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/LineDetails", "GET", "Retrieves a list of line details for a work order stage output.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputLineDetailGETRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/LineDetails/{LineDetailID}", "GET", "Retrieves a work order stage output line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputLineDetailPOSTRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/LineDetails", "POST", "Appends a line detail to a work order stage output.", "");
			AppHost.Routes.Add(typeof(WorkOrderOutputLineDetailPUTRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/LineDetails", "PUT", "Sets the line details for a work order output line. Existing line details for that line will be replaced.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputLineDetailPATCHRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/LineDetails/{LineDetailID}", "PATCH", "Updates a work order stage output line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputLineDetailDELETERequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/LineDetails/{LineDetailID}", "DELETE", "Deletes a work order stage output line detail.", "");
            #endregion
			
            #region "Output Wastage Line Details"
            AppHost.RegisterService&lt;WorkOrderOutputWastageLineDetailServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderOutputWastageLineDetailsGETManyRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/WastageLineDetails", "GET", "Retrieves a list of wastage line details for a work order stage output.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputWastageLineDetailGETRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/WastageLineDetails/{LineDetailID}", "GET", "Retrieves a work order stage output wastage line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputWastageLineDetailPOSTRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/WastageLineDetails", "POST", "Appends a wastage line detail to a work order stage output.", "");
			AppHost.Routes.Add(typeof(WorkOrderOutputWastageLineDetailPUTRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/WastageLineDetails", "PUT", "Sets the wastage line details for a work order output line. Existing wastage line details for that line will be replaced.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputWastageLineDetailPATCHRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/WastageLineDetails/{LineDetailID}", "PATCH", "Updates a work order stage output wastage line detail.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputWastageLineDetailDELETERequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}/WastageLineDetails/{LineDetailID}", "DELETE", "Deletes a work order stage output wastage line detail.", "");
            #endregion						

			#region "Outputs"
            AppHost.RegisterService&lt;WorkOrderOutputServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderOutputsGETManyRequest), "/WorkOrders/{WorkOrderID}/Outputs", "GET", "Retrieves a list of work order outputs.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputGETRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}", "GET", "Retrieves a work order output.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputPOSTRequest), "/WorkOrders/{WorkOrderID}/Outputs", "POST", "Appends a output to a work order record.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputPATCHRequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}", "PATCH", "Updates a work order output.", "");
            AppHost.Routes.Add(typeof(WorkOrderOutputDELETERequest), "/WorkOrders/{WorkOrderID}/Outputs/{OutputID}", "DELETE", "Deletes a work order output.", "");
            #endregion			
			
            #region "Stage Custom Fields"
            AppHost.RegisterService&lt;WorkOrderStageCustomFieldServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderStageCustomFieldsGETManyRequest), "/WorkOrders/Stages/CustomFields", "GET", "Retrieves a list of work order stage custom fields.", "");
            AppHost.Routes.Add(typeof(WorkOrderStageCustomFieldGETRequest), "/WorkOrders/Stages/CustomFields/{SettingID}", "GET", "Retrieves a work order stage custom field.", "");
            AppHost.Routes.Add(typeof(WorkOrderStageCustomFieldValuesGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/CustomFieldValues", "GET", "Retrieves a list of custom field values for a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderStageCustomFieldValueGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/CustomFieldValues/{SettingID}", "GET", "Retrieves a work order stage custom field value.", "");
            AppHost.Routes.Add(typeof(WorkOrderStageCustomFieldValuePATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}/CustomFieldValues/{SettingID}", "PATCH", "Updates a work order stage custom field value.", "");
            #endregion		
			
            #region "Stages"
            AppHost.RegisterService&lt;WorkOrderStageServices&gt;();
            AppHost.Routes.Add(typeof(WorkOrderStagesGETManyRequest), "/WorkOrders/{WorkOrderID}/Stages", "GET", "Retrieves a list of work order stages.", "");
            AppHost.Routes.Add(typeof(WorkOrderStageGETRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}", "GET", "Retrieves a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderStagePOSTRequest), "/WorkOrders/{WorkOrderID}/Stages", "POST", "Appends a stage to a work order record.", "");
			AppHost.Routes.Add(typeof(WorkOrderStagePATCHRequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}", "PATCH", "Updates a work order stage.", "");
            AppHost.Routes.Add(typeof(WorkOrderStageDELETERequest), "/WorkOrders/{WorkOrderID}/Stages/{StageID}", "DELETE", "Deletes a work order record stage.", "");			
            #endregion			
			#endregion
            #endregion

            #region "Webhooks startup tasks"
            #region "Initial Read of Subscribers, Subscriptions, Message Queue and Events"            
			using(var db = AppHost.GetDbConnection())
			{
				// Read all the subscribers	
				_webhookSubscribers = db.Select&lt;SY_WebhookSubscriber&gt;();
				// Read all the web hook subscriptions
	            _webhookSubscriptions = db.Select&lt;SY_WebhookSubscription&gt;();
	            _webhookSubscriptionRequestHeaders = db.Select&lt;SY_WebhookSubscriptionRequestHeader&gt;();
				
				// Read the web hook message queue
            	var q = db.From&lt;SY_WebhookMessage&gt;().Where(x =&gt; x.Status == 0 || x.Status == 2).OrderBy(x =&gt; x.LastSavedDateTime);
            	_webhookMessages = db.Select&lt;SY_WebhookMessage&gt;(q);
				
				 #region "System Settings"
	            // Need to store the URL each Jiwa client is going to call in a static
	            JiwaServiceModel.Tables.SY_SysValues hostURLSetting = db.Single&lt;JiwaServiceModel.Tables.SY_SysValues&gt;(x =&gt; x.Section == "REST API" &amp;&amp; x.IDKey == "WebhooksHostURL");
	            _hostURL = hostURLSetting.Contents;

	            JiwaServiceModel.Tables.SY_SysValues retryIntervalSetting = db.Single&lt;JiwaServiceModel.Tables.SY_SysValues&gt;(x =&gt; x.Section == "REST API" &amp;&amp; x.IDKey == "WebhooksRetryInterval");
	            if (!int.TryParse(retryIntervalSetting.Contents, out _retryInterval))
	                throw new Exception("Webhooks Retry Interval setting for plugin REST API is not a valid value");

	            if (_retryInterval &lt;= 0)
	                _retryInterval = 1;

	            JiwaServiceModel.Tables.SY_SysValues maxRetriesSetting = db.Single&lt;JiwaServiceModel.Tables.SY_SysValues&gt;(x =&gt; x.Section == "REST API" &amp;&amp; x.IDKey == "WebhooksMaxRetries");
	            if (!int.TryParse(maxRetriesSetting.Contents, out _maxRetries))
	                throw new Exception("Webhooks Max Retries setting for plugin REST API is not a valid value");

	            if (_maxRetries &lt;= 0)
	                _maxRetries = 1;

	            JiwaServiceModel.Tables.SY_SysValues clientKeySetting = db.Single&lt;JiwaServiceModel.Tables.SY_SysValues&gt;(x =&gt; x.Section == "REST API" &amp;&amp; x.IDKey == "WebhooksClientKey");
	            if (clientKeySetting.Contents.Trim().Length == 0)
	            {
	                // Generate new key
	                using (var hash = MD5.Create())
	                {
	                    clientKeySetting.Contents = Convert.ToBase64String(hash.ComputeHash(Guid.NewGuid().ToByteArray()));
	                }
	                // Save to database							
	                db.Save(clientKeySetting);
	            }
	            _clientKey = clientKeySetting.Contents;

	            #endregion
				
				db.Close();
			}
            
            _webHookEvents = new List&lt;WebHookEvent&gt;();
			
			_webHookEvents.Add(new WebHookEvent { Name = "creditor.created", Description = "Occurs when a new creditor (supplier) is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "creditor.updated", Description = "Occurs when a creditor (supplier) is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "creditor.deleted", Description = "Occurs when a creditor (supplier) is deleted" });
			
			_webHookEvents.Add(new WebHookEvent { Name = "creditorclassification.created", Description = "Occurs when a new creditor classification is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "creditorclassification.updated", Description = "Occurs when a creditor classification is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "creditorclassification.deleted", Description = "Occurs when a creditor classification is deleted" });
			
            _webHookEvents.Add(new WebHookEvent { Name = "debtor.created", Description = "Occurs when a new debtor (customer) is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "debtor.updated", Description = "Occurs when a debtor (customer) is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "debtor.deleted", Description = "Occurs when a debtor (customer) is deleted" });
			
			_webHookEvents.Add(new WebHookEvent { Name = "debtorclassification.created", Description = "Occurs when a new debtor classification is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "debtorclassification.updated", Description = "Occurs when a debtor classification is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "debtorclassification.deleted", Description = "Occurs when a debtor classification is deleted" });
			
			_webHookEvents.Add(new WebHookEvent { Name = "debtorcategory.created", Description = "Occurs when a new debtor category is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "debtorcategory.updated", Description = "Occurs when a debtor category is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "debtorcategory.deleted", Description = "Occurs when a debtor category is deleted" });

            _webHookEvents.Add(new WebHookEvent { Name = "inventory.created", Description = "Occurs when a new inventory item (product) is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "inventory.updated", Description = "Occurs when an inventory item (product) is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "inventory.deleted", Description = "Occurs when an inventory item (product) is deleted" });
			
			_webHookEvents.Add(new WebHookEvent { Name = "inventoryclassification.created", Description = "Occurs when a new inventory classification is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "inventoryclassification.updated", Description = "Occurs when an inventory classification is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "inventoryclassification.deleted", Description = "Occurs when an inventory classification is deleted" });
			
			_webHookEvents.Add(new WebHookEvent { Name = "inventorycategory.created", Description = "Occurs when a new inventory category is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "inventorycategory.updated", Description = "Occurs when an inventory category is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "inventorycategory.deleted", Description = "Occurs when an inventory category is deleted" });
			
            _webHookEvents.Add(new WebHookEvent { Name = "inventory.stocklevel", Description = "Occurs when an inventory item stock level changes" });

            _webHookEvents.Add(new WebHookEvent { Name = "purchaseorder.created", Description = "Occurs when a new purchase order is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "purchaseorder.updated", Description = "Occurs when a purchase order is modified" });
            _webHookEvents.Add(new WebHookEvent { Name = "purchaseorder.deleted", Description = "Occurs when a purchase order is deleted" });

            _webHookEvents.Add(new WebHookEvent { Name = "salesorder.created", Description = "Occurs when a new sales order is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "salesorder.updated", Description = "Occurs when a sales order is modified" });
			
            _webHookEvents.Add(new WebHookEvent { Name = "bookin.created", Description = "Occurs when a new book in is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "bookin.updated", Description = "Occurs when a book in is modified" });		
			
            _webHookEvents.Add(new WebHookEvent { Name = "shipment.created", Description = "Occurs when a new shipment is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "shipment.updated", Description = "Occurs when a shipment is modified" });
			
            _webHookEvents.Add(new WebHookEvent { Name = "goodsreceivednote.created", Description = "Occurs when a new goods received note is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "goodsreceivednote.updated", Description = "Occurs when a goods received note is modified" });
			
            _webHookEvents.Add(new WebHookEvent { Name = "salesquote.created", Description = "Occurs when a new sales quote is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "salesquote.updated", Description = "Occurs when a sales quote is modified" });	
			
            _webHookEvents.Add(new WebHookEvent { Name = "warehousetransferout.created", Description = "Occurs when a new warehouse transfer out is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "warehousetransferout.updated", Description = "Occurs when a warehouse transfer out is modified" });
			
            _webHookEvents.Add(new WebHookEvent { Name = "warehousetransferin.created", Description = "Occurs when a new warehouse transfer in is created" });
            _webHookEvents.Add(new WebHookEvent { Name = "warehousetransferin.updated", Description = "Occurs when a warehouse transfer in is modified" });			
            #endregion

			_timer = new WebhookMessagesTimer(_retryInterval * 1000);
            #endregion
        }
		
        #region "API Key Request filter functions"
        #region "Sales Orders"
        public void DebtorAPIKeySalesOrderGETRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrderGETRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are retrieving an order.
            // We want to make sure only orders belonging to the customer are able to be retrieved
           	AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;
            
            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.InvoiceID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales order belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
                    if (salesOrder.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using(var db = AppHost.GetDbConnection())
				{
                	SO_Main salesOrder = db.Single(db.From&lt;SO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.InvoiceID).Take(1));
					db.Close();
					
                	if (salesOrder != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesOrder.DebtorID)
                    	throw new JiwaApplication.Exceptions.RecordNotFoundException();									
				}
            }            
        }

        public void DebtorAPIKeySalesOrderRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrders.SalesOrder dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are placing orders or updating orders.
            // We don't want the customer to specify the debtor - we already know that by looking at the debtor linked to the APIKey.
            // We also don't want them telling us the price and other fields - so we null the fields in the DTO that we want to ignore.

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            // don't let customers control the system settings
            dto.SystemSettings = null;
            // don't let customers create credit notes
            dto.CreditNote = null;
            
            // Set the debtorID to be the debtorID associated with the API Key
            dto.DebtorID = manager.Database.APIKey_PrincipalID;
            dto.DebtorAccountNo = null;
            dto.DebtorName = null;

            // when creating a sales order, we don't allow them to provide the InvoiceID, InvoiceNo or InvoiceDate
            dto.InvoiceID = null;
            dto.InvoiceNo = null;
            dto.InvoiceInitDate = null;

            // remove payments
            dto.Payments = null;

            // we don't want the customer telling us the price or backorder qty or anything like that
            foreach (JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine salesOrderLine in dto.Lines)
            {
                salesOrderLine.DiscountedPrice = null;
                salesOrderLine.DiscountedPercentage = null;
                salesOrderLine.DiscountGiven = null;
                salesOrderLine.FixPrice = null;
                salesOrderLine.FixSellPrice = null;
                salesOrderLine.LineDetails = null;
                salesOrderLine.LineTotal = null;
                salesOrderLine.Picked = null;
                salesOrderLine.PriceExGst = null;
                salesOrderLine.PriceIncGst = null;
                salesOrderLine.QuantityBackOrd = null;
                salesOrderLine.QuantityDemand = null;
                salesOrderLine.QuantityThisDel = null;
                salesOrderLine.TaxRate = null;
                salesOrderLine.TaxToCharge = null;
                salesOrderLine.UnitCost = null;
            }                
        }

        public void DebtorAPIKeySalesOrderSaveRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrderSAVERequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to save a stateful order.
            // We want to make sure only orders belonging to the customer are able to be saved

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.InvoiceID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales order belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
                    if (salesOrder.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else            
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            
        }

        public void DebtorAPIKeySalesOrderAbandonRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrderABANDONRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to abandon a stateful order.
            // We want to make sure only orders belonging to the customer are able to be abandoned

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.InvoiceID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales order belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
                    if (salesOrder.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
        }
        #endregion

        #region "Sales Order Lines"
        public void DebtorAPIKeySalesOrderLineGETRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrderLineGETRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to retrieve a line from sales order.
            // We want to make sure only orders belonging to the customer are able to be retrieved

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.InvoiceID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales order belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
                    if (salesOrder.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
				using(var db = AppHost.GetDbConnection())
				{
                	SO_Main salesOrder = db.Single(db.From&lt;SO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.InvoiceID).Take(1));
					db.Close();
					
                	if (salesOrder != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesOrder.DebtorID)
                    	throw new JiwaApplication.Exceptions.RecordNotFoundException();									
				}				
            }
        }

        public void DebtorAPIKeySalesOrderLinePOSTRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrderLinePOSTRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to add a line to a sales order.
            // We want to make sure only orders belonging to the customer are able to have lines added

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.InvoiceID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales order belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
                    if (salesOrder.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using (var db = AppHost.GetDbConnection())
				{
                	SO_Main salesOrder = db.Single(db.From&lt;SO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.InvoiceID).Take(1));
                	db.Close();
					
					if (salesOrder != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesOrder.DebtorID)
                    	throw new JiwaApplication.Exceptions.RecordNotFoundException();										
				}
            }

            dto.DiscountedPrice = null;
            dto.DiscountedPercentage = null;
            dto.DiscountGiven = null;
            dto.FixPrice = null;
            dto.FixSellPrice = null;
            dto.LineDetails = null;
            dto.LineTotal = null;
            dto.Picked = null;
            dto.PriceExGst = null;
            dto.PriceIncGst = null;
            dto.QuantityBackOrd = null;
            dto.QuantityDemand = null;
            dto.QuantityThisDel = null;
            dto.TaxRate = null;
            dto.TaxToCharge = null;
            dto.UnitCost = null;
        }

        public void DebtorAPIKeySalesOrderLinePATCHRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrderLinePATCHRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to modify a line on a sales order.
            // We want to make sure only orders belonging to the customer are able to have lines modified

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;				

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.InvoiceID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales order belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
                    if (salesOrder.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using (var db = AppHost.GetDbConnection())
				{
	                SO_Main salesOrder = db.Single(db.From&lt;SO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.InvoiceID).Take(1));
					db.Close();
					
	                if (salesOrder != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesOrder.DebtorID)
	                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
				}
            }

            dto.DiscountedPrice = null;
            dto.DiscountedPercentage = null;
            dto.DiscountGiven = null;
            dto.FixPrice = null;
            dto.FixSellPrice = null;
            dto.LineDetails = null;
            dto.LineTotal = null;
            dto.Picked = null;
            dto.PriceExGst = null;
            dto.PriceIncGst = null;
            dto.QuantityBackOrd = null;
            dto.QuantityDemand = null;
            dto.QuantityThisDel = null;
            dto.TaxRate = null;
            dto.TaxToCharge = null;
            dto.UnitCost = null;
        }

        public void DebtorAPIKeySalesOrderLineDELETERequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrderLineDELETERequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to delete a line on a sales order.
            // We want to make sure only orders belonging to the customer are able to have lines deleted

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.InvoiceID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales order belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = (JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
                    if (salesOrder.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using (var db = AppHost.GetDbConnection())
				{
                	SO_Main salesOrder = db.Single(db.From&lt;SO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.InvoiceID).Take(1));                
					db.Close();
					
					if (salesOrder != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesOrder.DebtorID)
                    	throw new JiwaApplication.Exceptions.RecordNotFoundException();
				}
            }
        }
        #endregion

        #region "Sales Quotes"
        public void DebtorAPIKeySalesQuoteGETRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuoteGETRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are retrieving a quote.
            // We want to make sure only quotes belonging to the customer are able to be retrieved
            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.QuoteID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales quote belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
                    if (salesQuote.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using (var db = AppHost.GetDbConnection())
				{
                	SO_Main quote = db.Single(db.From&lt;SO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.QuoteID).Take(1));
                	db.Close();
					
					if (quote != null &amp;&amp; manager.Database.APIKey_PrincipalID != quote.DebtorID)
                    	throw new JiwaApplication.Exceptions.RecordNotFoundException();
				}
            }
        }

        public void DebtorAPIKeySalesQuoteRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuotes.SalesQuote dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are creating quotes or updating quotes.
            // We don't want the customer to specify the debtor - we already know that by looking at the debtor linked to the APIKey.
            // We also don't want them telling us the price and other fields - so we null the fields in the DTO that we want to ignore.

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            // don't let customers control the system settings
            dto.SystemSettings = null;

            // Set the debtorID to be the debtorID associated with the API Key
            dto.DebtorID = manager.Database.APIKey_PrincipalID;
            dto.DebtorAccountNo = null;
            dto.DebtorName = null;

            // when creating a sales quote, we don't allow them to provide the QuoteID, QuoteNo or InvoiceDate
            dto.QuoteID = null;
            dto.QuoteNo = null;
            dto.InvoiceInitDate = null;

            // we don't want the customer telling us the price or anything like that
            foreach (JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine salesQuoteLine in dto.Lines)
            {
                salesQuoteLine.DiscountedPrice = null;
                salesQuoteLine.DiscountedPercentage = null;
                salesQuoteLine.DiscountGiven = null;                
                salesQuoteLine.FixSellPrice = null;
                salesQuoteLine.LineTotal = null;
                salesQuoteLine.PriceExGst = null;
                salesQuoteLine.PriceIncGst = null;
                salesQuoteLine.TaxRate = null;
                salesQuoteLine.TaxToCharge = null;
                salesQuoteLine.UnitCost = null;
            }
        }

        public void DebtorAPIKeySalesQuoteSaveRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuoteSAVERequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to save a stateful quote.
            // We want to make sure only orders belonging to the customer are able to be saved

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.QuoteID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales quote belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
                    if (salesQuote.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
        }

        public void DebtorAPIKeySalesQuoteAbandonRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuoteABANDONRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to abandon a stateful quote.
            // We want to make sure only quotes belonging to the customer are able to be abandoned

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.QuoteID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales quote belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
                    if (salesQuote.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
        }
        #endregion

        #region "Sales Quote Lines"
        public void DebtorAPIKeySalesQuoteLineGETRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuoteLineGETRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to retrieve a line from sales quote.
            // We want to make sure only quotes belonging to the customer are able to be retrieved

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.QuoteID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales quote belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
                    if (salesQuote.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using(var db = AppHost.GetDbConnection())
				{
	                QO_Main salesQuote = db.Single(db.From&lt;QO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.QuoteID).Take(1));
					db.Close();
					
	                if (salesQuote != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesQuote.DebtorID)
	                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
				}
            }
        }

        public void DebtorAPIKeySalesQuoteLinePOSTRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuoteLinePOSTRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to add a line to a sales quote.
            // We want to make sure only quotes belonging to the customer are able to have lines added

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.QuoteID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales quote belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
                    if (salesQuote.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using(var db = AppHost.GetDbConnection())
				{
	                QO_Main salesQuote = db.Single(db.From&lt;QO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.QuoteID).Take(1));
					db.Close();
					
	                if (salesQuote != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesQuote.DebtorID)
	                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
				}
            }

            dto.DiscountedPrice = null;
            dto.DiscountedPercentage = null;
            dto.DiscountGiven = null;
            dto.FixSellPrice = null;
            dto.LineTotal = null;
            dto.PriceExGst = null;
            dto.PriceIncGst = null;            
            dto.TaxRate = null;
            dto.TaxToCharge = null;
            dto.UnitCost = null;
        }

        public void DebtorAPIKeySalesQuoteLinePATCHRequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuoteLinePATCHRequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to modify a line on a sales quote.
            // We want to make sure only quotes belonging to the customer are able to have lines modified

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.QuoteID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales quote belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
                    if (salesQuote.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using(var db = AppHost.GetDbConnection())
				{
	                QO_Main salesQuote = db.Single(db.From&lt;QO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.QuoteID).Take(1));
					db.Close();
					
	                if (salesQuote != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesQuote.DebtorID)
	                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
				}
            }

            dto.DiscountedPrice = null;
            dto.DiscountedPercentage = null;
            dto.DiscountGiven = null;            
            dto.FixSellPrice = null;
            dto.LineTotal = null;
            dto.PriceExGst = null;
            dto.PriceIncGst = null;
            dto.TaxRate = null;
            dto.TaxToCharge = null;
            dto.UnitCost = null;
        }

        public void DebtorAPIKeySalesQuoteLineDELETERequestFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuoteLineDELETERequest dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are wanting to delete a line on a sales quote.
            // We want to make sure only quotes belonging to the customer are able to have lines deleted

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            if (Helper.Service.IsStateful(req))
            {
                // a stateful request should always fetch from the in-memory ObjectDictionary instead of the database
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue(dto.QuoteID, out objectDictionaryValue))
                    throw new JiwaApplication.Exceptions.RecordNotFoundException();
                else
                {
                    // Check the debtor this sales quote belongs to is the same as the one associated with the Debtor API Key
                    JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = (JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
                    if (salesQuote.Debtor.DebtorID != manager.Database.APIKey_PrincipalID)
                        throw new JiwaApplication.Exceptions.RecordNotFoundException();
                }
            }
            else
            {
                using(var db = AppHost.GetDbConnection())
				{
                	QO_Main salesQuote = db.Single(db.From&lt;QO_Main&gt;().Where(x =&gt; x.InvoiceID == dto.QuoteID).Take(1));
					db.Close();
					
                	if (salesQuote != null &amp;&amp; manager.Database.APIKey_PrincipalID != salesQuote.DebtorID)
                    	throw new JiwaApplication.Exceptions.RecordNotFoundException();
				}
            }
        }
        #endregion

        #region "Queries"
        public void DebtorAPIKeySO_MainQueryRequestFilter(IRequest req, IResponse res, JiwaServiceModel.Tables.SO_MainQuery dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are querying the SO_Main table.
            // We don't want the customer to specify the debtor - we already know that by looking at the debtor linked to the APIKey, 
            // but we want to inject their known debtorid as a filter so the only orders they see are their own.            

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.DebtorID = manager.Database.APIKey_PrincipalID;
        }

        public void DebtorAPIKeyv_Jiwa_SalesOrder_ListQueryRequestFilter(IRequest req, IResponse res, JiwaServiceModel.Tables.v_Jiwa_SalesOrder_ListQuery dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are querying the sales order list view.
            // We don't want the customer to specify the debtor - we already know that by looking at the debtor linked to the APIKey, 
            // but we want to inject their known debtorid as a filter so the only orders they see are their own.            

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.DebtorID = manager.Database.APIKey_PrincipalID;
        }

        public void DebtorAPIKeyQO_MainQueryRequestFilter(IRequest req, IResponse res, JiwaServiceModel.Tables.QO_MainQuery dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are querying the QO_Main table.
            // We don't want the customer to specify the debtor - we already know that by looking at the debtor linked to the APIKey, 
            // but we want to inject their known debtorid as a filter so the only quotes they see are their own.            

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.DebtorID = manager.Database.APIKey_PrincipalID;
        }
        
        public void DebtorAPIKeyv_Jiwa_SalesQuote_ListQueryRequestFilter(IRequest req, IResponse res, JiwaServiceModel.Tables.v_Jiwa_SalesQuote_ListQuery dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are querying the sales quote list view.
            // We don't want the customer to specify the debtor - we already know that by looking at the debtor linked to the APIKey, 
            // but we want to inject their known debtorid as a filter so the only quotes they see are their own.            

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.DebtorID = manager.Database.APIKey_PrincipalID;
        }
        
        public void DebtorAPIKeyv_Jiwa_Debtor_Transactions_ListQueryRequestFilter(IRequest req, IResponse res, JiwaServiceModel.Tables.v_Jiwa_Debtor_Transactions_ListQuery dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are querying the debtor transactions list view.
            // We don't want the customer to specify the debtor - we already know that by looking at the debtor linked to the APIKey, 
            // but we want to inject their known debtorid as a filter so the only transactions they see are their own.            

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.DebtorID = manager.Database.APIKey_PrincipalID;
        }
        #endregion
        #endregion

        #region "API Key Response Filter functions"
        public void DebtorAPIKeyInventoryResponseFilter(IRequest req, IResponse res, JiwaServiceModel.Inventory.InventoryItem dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are getting product information.
            // We don't want the customer to see any prices not associated with them, cost prices and so on - so we null the fields in the DTO that we want to ignore.

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.Budgets = null;
            dto.Classification.InventoryLedgers = null;

            dto.DebtorPrices.RemoveAll(x =&gt; x.DebtorID != manager.Database.APIKey_PrincipalID); // Remove debtor specific prices not belonging to this debtor
            dto.DebtorPrices.Select(x =&gt; {
                                            x.Mode = null;
                                            x.Source = null;
                                            x.Amount = 0;
                                            return x;
                                            }).ToList(); // Remove source, mode and amount values - they should only see the price.

			using(var db = AppHost.GetDbConnection())
			{
	            DB_Main debtor = db.Single(db.From&lt;DB_Main&gt;().Where(x =&gt; x.DebtorID == manager.Database.APIKey_PrincipalID).Take(1));
				db.Close();
				
	            dto.DebtorClassPrices.RemoveAll(x =&gt; x.DebtorClassificationID != debtor.ClassificationID); ; // Remove debtor classification prices not belonging to this debtor
			}
			
            dto.DebtorClassPrices.Select(x =&gt; {
                                                x.Mode = null;
                                                x.Source = null;
                                                x.Amount = 0;
                                                return x;
                                                }).ToList(); // Remove source, mode and amount values - they should only see the price.

            dto.InventoryLedgers = null;
            dto.LCost = null;
            dto.SalesManCost = null;
            dto.SCost = null;
            dto.StandardCost = null;
            dto.OrderLevels = null;
        }
        
        public void DebtorAPIKeySalesOrderResponseFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrders.SalesOrder dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are retrieving a sales order
            // We remove sensitve information such as cost prices by nulling the fields

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.SystemSettings = null;            

            foreach (JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine salesOrderLine in dto.Lines)
            {
                salesOrderLine.DiscountedPercentage = null;
                salesOrderLine.DiscountGiven = null;
                salesOrderLine.PriceExGst = null;  // salesOrderLine.DiscountedPrice is the actual price we're selling to them at, not PriceExGST
                salesOrderLine.PriceIncGst = null;
                salesOrderLine.TaxRate.LedgerAccount = null;
                salesOrderLine.UnitCost = null;

                foreach (JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLineDetail lineDetail in salesOrderLine.LineDetails)
                {
                    lineDetail.Cost = null;
                    lineDetail.SOHID = null;
                    lineDetail.SpecialPrice = null;
                }
            }
        }
        
        public void DebtorAPIKeySalesOrderLineResponseFilter(IRequest req, IResponse res, JiwaServiceModel.SalesOrders.SalesOrderLine dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are retrieving a sales order line
            // We remove sensitve information such as cost prices by nulling the fields

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.DiscountedPercentage = null;
            dto.DiscountGiven = null;
            dto.PriceExGst = null;  // salesOrderLine.DiscountedPrice is the actual price we're selling to them at, not PriceExGST
            dto.PriceIncGst = null;
            dto.TaxRate.LedgerAccount = null;
            dto.UnitCost = null;

            foreach (JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLineDetail lineDetail in dto.LineDetails)
            {
                lineDetail.Cost = null;
                lineDetail.SOHID = null;
                lineDetail.SpecialPrice = null;
            }            
        }

        public void DebtorAPIKeySalesQuoteResponseFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuotes.SalesQuote dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are retrieving a sales quote
            // We remove sensitve information such as cost prices by nulling the fields

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.SystemSettings = null;

            foreach (JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine salesQuoteLine in dto.Lines)
            {
                salesQuoteLine.DiscountedPercentage = null;
                salesQuoteLine.DiscountGiven = null;
                salesQuoteLine.PriceExGst = null;  // salesOrderLine.DiscountedPrice is the actual price we're selling to them at, not PriceExGST                
                salesQuoteLine.PriceIncGst = null;
                salesQuoteLine.UnitCost = null;                
            }
        }

        public void DebtorAPIKeySalesQuoteLineResponseFilter(IRequest req, IResponse res, JiwaServiceModel.SalesQuotes.SalesQuoteLine dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are retrieving a sales quote line
            // We remove sensitve information such as cost prices by nulling the fields

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.DiscountedPercentage = null;
            dto.DiscountGiven = null;
            dto.PriceExGst = null;  // DiscountedPrice is the actual price we're selling to them at, not PriceExGST            
            dto.PriceIncGst = null;
            dto.UnitCost = null;
        }

        public void DebtorAPIKeyDebtorResponseFilter(IRequest req, IResponse res, JiwaServiceModel.Debtors.Debtor dto)
        {
            // This filter is designed to be used when customers authenticated via Debtor API Key are retrieving their account information
            // We remove sensitve information by nulling the fields

            AuthUserSession session = (AuthUserSession)req.GetSession();			
			if (session == null)
				return;
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
            RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null || manager.Database.APIKey_Type != "Debtor")
                return;

            dto.Budgets = null;
            dto.DebtorLedgers = null;
            dto.Classification.DebtorLedgers = null;
            dto.LastPaymentDate = null; // this isn't used, so remove it otherwise it's just confusing
            dto.LastPaymentDate = null; // this isn't used, so remove it otherwise it's just confusing            
        }
        #endregion
		
        #endregion
    }

    #region "Authentication"	
	#region "Credentials Authentication"
    public class JiwaAuthProvider : CredentialsAuthProvider
    {
        public ServiceStack.ServiceStackHost AppHost;
        public JiwaApplication.Manager StartupManager; // Used only so we know the server name, database name, et cetera.

        public JiwaAuthProvider(string providerType)
        {
            Provider = providerType;
        }

        public override bool TryAuthenticate(IServiceBase authService, string userName, string password)        
		{ 															   		
	        //Return true if credentials are valid, otherwise false  
	        JiwaApplication.Manager manager = new JiwaApplication.Manager(); 
			//JiwaApplication.Manager.Instance = manager;
	        AuthUserSession session = (AuthUserSession)authService.GetSession(); 
	        manager.SessionID = session.Id; 
	        //manager.LogEvents = false; // if the service doesn't have permissions to write to the EventLog, set this to false to prevent failure to start
	        manager.Logon(StartupManager.Database.ServerName, StartupManager.Database.DatabaseName, JiwaFinancials.Jiwa.JiwaODBC.database.AuthenticationModes.JiwaAuthentication, userName, password);  
			
			foreach (JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.PluginException exception in manager.PluginExceptions)	            
                manager.LogEvent(String.Format("Plugin '{0}' encountered an exception when compiling or loading during logon. Exception Message: '{1}'", exception.Name, exception.Exception.ToString()), EventLogEntryType.Error, 0, 0);	            
			
			Exception[] abortExceptions = manager.PluginExceptions.Where(x =&gt; x.ExceptionPolicy == JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.ExceptionPolicies.Abort).Select(x =&gt; x.Exception).ToArray&lt;Exception&gt;();
			if (abortExceptions.Length &gt; 0)                
			    throw new AggregateException("One ore more plugins with an abort policy encountered exceptions when compiling or loading during the logon process.", abortExceptions);
						
	        // Because we are actually holding state per session with a Manager object, we need to store the session id and manager in a dict 
	        // so we can figure out in the global request filter which sessions have transparently been expired and get to the manager and log it off 
	        // If we don't do this, we may exhaust SQL connection pools. 
	        RESTAPIPlugin.JiwaSessionDictionary.TryAdd(session.Id, manager);  
	        return true; 		    		  
		}
    }
	#endregion
	
	#region "API Key Authentication"
    public class JiwaApiKeyAuthProvider : AuthProvider, IAuthWithRequest, IAuthPlugin
    {
        public ServiceStack.ServiceStackHost AppHost;
        public JiwaApplication.Manager StartupManager; // Used only so we know the server name, database name, et cetera.

        public const string Name = AuthenticateService.ApiKeyProvider;
        public const string Realm = "/auth/" + AuthenticateService.ApiKeyProvider;

        /// &lt;summary&gt;
        /// Whether to only allow access via API Key from a secure connection. (default true)
        /// &lt;/summary&gt;
        public bool RequireSecureConnection { get; set; }

        /// &lt;summary&gt;
        /// Cache the User Session so it can be reused between subsequent API Key Requests
        /// &lt;/summary&gt;
        public TimeSpan? SessionCacheDuration { get; set; }

        /// &lt;summary&gt;
        /// Whether to allow API Keys in 'apikey' QueryString or FormData
        /// &lt;/summary&gt;
        public bool AllowInHttpParams { get; set; }

        public JiwaApiKeyAuthProvider()
            : base(null, Realm, Name)
        {
            Init();
        }

        public JiwaApiKeyAuthProvider(IAppSettings appSettings)
            : base(appSettings, Realm, Name)
        {
            Init(appSettings);
        }

        protected virtual void Init(IAppSettings appSettings = null)
        {
            RequireSecureConnection = true;
        }

        public override bool IsAuthorized(IAuthSession session, IAuthTokens tokens, Authenticate request = null)
        {
            return session != null &amp;&amp; session.IsAuthenticated &amp;&amp; !session.UserAuthName.IsNullOrEmpty();
        }

        public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request)
        {
            var apiKey = GetApiKey(authService.Request, request.Password);
            ValidateApiKey(apiKey);

            // **********************************************************************************************************************
			AuthUserSession jiwaSession = (AuthUserSession)session; //authService.GetSession();
						
			JiwaApplication.Manager manager = null;
			RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);

            if (manager == null)
			{
				manager = new JiwaApplication.Manager();									            
	            manager.SessionID = session.Id;
	            //manager.LogEvents = false; // if the service doesn't have permissions to write to the EventLog, set this to false to prevent failure to start
	            manager.Logon(StartupManager.Database.ServerName, StartupManager.Database.DatabaseName, apiKey.KeyValue);
				
				foreach (JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.PluginException exception in manager.PluginExceptions)	            
	            	manager.LogEvent(String.Format("Plugin '{0}' encountered an exception when compiling or loading during logon. Exception Message: '{1}'", exception.Name, exception.Exception.ToString()), EventLogEntryType.Error, 0, 0);	            
				
				Exception[] abortExceptions = manager.PluginExceptions.Where(x =&gt; x.ExceptionPolicy == JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.ExceptionPolicies.Abort).Select(x =&gt; x.Exception).ToArray&lt;Exception&gt;();
				if (abortExceptions.Length &gt; 0)                
				    throw new AggregateException("One ore more plugins with an abort policy encountered exceptions when compiling or loading during the logon process.", abortExceptions);
								
				// Because we are actually holding state per session with a Manager object, we need to store the session id and manager in a dict 
		        // so we can figure out in the global request filter which sessions have transparently been expired and get to the manager and log it off 
		        // If we don't do this, we may exhaust SQL connection pools. 
		        RESTAPIPlugin.JiwaSessionDictionary.TryAdd(session.Id, manager);
			}
			
            // **********************************************************************************************************************

            session.IsAuthenticated = true;
            session.UserAuthId = apiKey.KeyValue.ToString(System.Globalization.CultureInfo.InvariantCulture);

            if (session.UserAuthName == null)
                session.UserAuthName = manager.Staff.Username;

            var response = OnAuthenticated(authService, session, null, null);

            if (response != null)
                return response;

            authService.Request.Items[Keywords.ApiKey] = apiKey;

            return new AuthenticateResponse
            {
                UserId = session.UserAuthId,
                UserName = session.UserName,
                SessionId = session.Id,
                DisplayName = session.DisplayName
                    ?? session.UserName
					?? String.Format("{0} {1}", session.FirstName, session.LastName).Trim(),
                ReferrerUrl = request.Continue
            };
        }

        public void PreAuthenticate(IRequest req, IResponse res)
        {
            //The API Key is sent in the Basic Auth Username and Password is Empty
            var userPass = req.GetBasicAuthUserAndPassword();
            if (userPass != null &amp;&amp; string.IsNullOrEmpty(userPass.Value.Value))
            {
                var apiKey = GetApiKey(req, userPass.Value.Key);
                PreAuthenticateWithApiKey(req, res, apiKey);
            }
            var bearerToken = req.GetBearerToken();
            if (bearerToken != null)
            {
                var apiKey = GetApiKey(req, bearerToken);
                if (apiKey != null)
                {
                    PreAuthenticateWithApiKey(req, res, apiKey);
                }
            }

            if (AllowInHttpParams)
            {
                var apiKey = req.QueryString[Keywords.ApiKeyParam] ?? req.FormData[Keywords.ApiKeyParam];
                if (apiKey != null)
                {
                    PreAuthenticateWithApiKey(req, res, GetApiKey(req, apiKey));
                }
            }
        }

        protected virtual JiwaServiceModel.Tables.v_APIKey GetApiKey(IRequest req, string apiKey)
        {
			using (var db = AppHost.GetDbConnection())
			{
				return db.Single(db.From&lt;JiwaServiceModel.Tables.v_APIKey&gt;().Where(x =&gt; x.KeyValue == apiKey));	
			}
            
        }

        public virtual void ValidateApiKey(JiwaServiceModel.Tables.v_APIKey apiKey)
        {
            if (apiKey == null)
                throw HttpError.NotFound("ApiKey does not exist");

            if (apiKey.CancelledDateTime != null)
                throw HttpError.Forbidden("ApiKey has been cancelled");

            if (apiKey.ExpiryDateTime != null &amp;&amp; DateTime.UtcNow &gt; apiKey.ExpiryDateTime.Value)
                throw HttpError.Forbidden("ApiKey has expired");

            if (!apiKey.IsEnabled)
                throw HttpError.Forbidden("ApiKey has been disabled");
        }

        public void PreAuthenticateWithApiKey(IRequest req, IResponse res, JiwaServiceModel.Tables.v_APIKey apiKey)
        {
            if (RequireSecureConnection &amp;&amp; !req.IsSecureConnection)
                throw HttpError.Forbidden(ErrorMessages.ApiKeyRequiresSecureConnection.Localize(req));

            ValidateApiKey(apiKey); // We do this in here because the key may have expired or been cancelled since our first auth, so we need to check every time

            var apiSessionKey = GetSessionKey(apiKey.KeyValue);
            if (SessionCacheDuration != null)
            {
                var session = req.GetCacheClient().Get&lt;IAuthSession&gt;(apiSessionKey);

                if (session != null)
                    session = HostContext.AppHost.OnSessionFilter(req, session, session.Id);

                if (session != null)
                {
                    req.Items[Keywords.ApiKey] = apiKey;
                    req.Items[Keywords.Session] = session;
                    return;
                }
            }

            //Need to run SessionFeature filter since its not executed before this attribute (Priority -100)			
            SessionFeature.AddSessionIdToRequestFilter(req, res, null); //Required to get req.GetSessionId()

            using (var authService = HostContext.ResolveService&lt;AuthenticateService&gt;(req))
            {
                var response = authService.Post(new Authenticate
                {
                    provider = Name,
                    UserName = "ApiKey",
                    Password = apiKey.KeyValue,
                });
            }

            if (SessionCacheDuration != null)
            {
                var session = req.GetSession();
                req.GetCacheClient().Set(apiSessionKey, session, SessionCacheDuration);
            }
        }

        public static string GetSessionKey(string apiKey) 
		{
			return "key:sess:" + apiKey;
		}

        public void Register(IAppHost appHost, AuthFeature feature)
        {
        }

        public override System.Threading.Tasks.Task OnFailedAuthentication(IAuthSession session, IRequest httpReq, IResponse httpRes)
        {
            httpRes.StatusCode = (int)System.Net.HttpStatusCode.Unauthorized;
            //Needs to be 'Basic ' in order for HttpWebRequest to accept challenge and send NetworkCredentials            
			httpRes.AddHeader(HttpHeaders.WwwAuthenticate, String.Format("Basic realm=\"{{0}}\"", this.AuthRealm));
            return HostContext.AppHost.HandleShortCircuitedErrors(httpReq, httpRes, httpReq.Dto);
        }
    }
    #endregion
    #endregion

    #region "Login / Logout"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "logged out OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class LogoutGetRequest : IReturn&lt;LogoutGetResponse&gt;
    {
    }

	[Serializable()]
    [Route("/login")]
    public class LoginGetRequest
    {
        public string redirect { get; set; }
    }

    #endregion

    #region "Responses"
	[Serializable()]
    public class LogoutGetResponse
    {
        public string Username { get; set; }
        public DateTime LoginDateTime { get; set; }
        public DateTime LogoutDateTime { get; set; }
    }

	[Serializable()]
    public class LoginGetResponse
    {
        public string redirect { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class AuthServices : ServiceStack.Service
    {
        [CompressResponse]
        [Authenticate]
        public LogoutGetResponse Get(LogoutGetRequest request)
        {
			AuthUserSession session = (AuthUserSession)this.GetSession();
			
			JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;
			
			if (session != null)
				RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);
			
           	string userName = "";

            if (manager != null)
            {
                if (manager.Staff != null)
                    userName = manager.Staff.Username;

                manager.LogOff();
                manager = null;
				
				JiwaFinancials.Jiwa.JiwaApplication.Manager removedManager = null;
				RESTAPIPlugin.JiwaSessionDictionary.TryRemove(session.Id, out removedManager);
            }

            var createdAt = session.CreatedAt;
            this.RemoveSession();

            return new LogoutGetResponse() { Username = userName, LoginDateTime = createdAt, LogoutDateTime = DateTime.Now };
        }

        public LoginGetResponse Get(LoginGetRequest request)
        {
            return new LoginGetResponse { redirect = request.redirect };
        }
    }
    #endregion
    #endregion

    #region "Backorders"
    #region "Models"
	[Serializable()]
    public class DebtorBackOrder
    {
        public string InvoiceID { get; set; }
        public string InvoiceNo { get; set; }
        public string CustomerOrderNo { get; set; }
        public DateTime Date { get; set; }
        public decimal Quantity { get; set; }
        public int QuantityDecimalPlaces { get; set; }
        public string Warehouse { get; set; }
        public string InventoryID { get; set; }
        public string PartNo { get; set; }
        public string Description { get; set; }
        public string CreditorID { get; set; }
        public string SupplierName { get; set; }
        public string OrderNo { get; set; }
        public DateTime ExpectedDeliveryDate { get; set; }
        public string HistoryTextComment { get; set; }
        public decimal QuantityConsumed { get; set; }
    }
    #endregion
    #endregion
	
	#region "Bills"
    #region "{Main}"
    #region"Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill&gt;
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill&gt;
    {
        public override string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillDELETERequest
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill&gt;
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillABANDONRequest
    {
        public string BillID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill Get(BillGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (j, m, s) =&gt;
                {
                    j.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });
            return billMaintenance.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.Bill Post(BillPOSTRequest Bill)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(null);
            billMaintenance.DTO_Deserialise(Bill);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(billMaintenance.RecID, Bill);
            else
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], billMaintenance.RecID));
            return billMaintenance.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Bills.Bill Patch(BillPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (j, m, s) =&gt;
                {
                    j.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            billMaintenance.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
               	billMaintenance.Save();
                billMaintenance.Read(request.BillID);
            }

            return billMaintenance.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(null);
            billMaintenance.Read(request.BillID);

            billMaintenance.Delete();
        }

        [Authenticate]
        public JiwaServiceModel.Bills.Bill Get(BillSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.BillID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful bill record exists with BillID '{0}'", request.BillID));
            }

            var billMaintenance = (JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance)objectDictionaryValue;
			
			billMaintenance.Save();
            billMaintenance.Read(billMaintenance.RecID);

            return billMaintenance.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.BillID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful bill record exists with BillID '{0}'", request.BillID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.BillID);
        }
    }
    #endregion
    #endregion	
	
    #region "Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No custom field with the SettingID provided was found")]
    public class BillCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill custom field value with the BillID or SettingID provided was found")]
    public class BillCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill custom field value with the BillID or SettingID provided was found")]
    public class BillCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(BillCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            return billMaintenance.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(BillCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            var BillCustomFieldValue = billMaintenance.CustomFieldValues.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (BillCustomFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return BillCustomFieldValue;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(BillCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = billMaintenance.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            customFieldValue = billMaintenance.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(BillCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);

            return billMaintenance.CustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(BillCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);

            var BillCustomField = billMaintenance.CustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (BillCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return BillCustomField;
        }		
    }
    #endregion
    #endregion	
	
    #region "Document Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill document type with the DocumentTypeID provided was found")]
    public class BillDocumentTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillDocumentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillDocumentTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill document type with the DocumentTypeID provided was found")]
    public class BillDocumentTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill document type with the DocumentTypeID provided was found")]
    public class BillDocumentTypeDELETERequest
    {
        public string DocumentTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillDocumentTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Get(BillDocumentTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.DocumentTableNames.Add("BM_Documents");
                    d.Read();
                });

            JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt; Get(BillDocumentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.DocumentTableNames.Add("BM_Documents");					
                    d.Read();
                });

            return documentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Post(BillDocumentTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.DocumentTableNames.Add("BM_Documents");					
                    d.Read();
                });

            // Add the document type. Need to jump through a few hoops as we want to know the DocumentTypeID so we can return that in the response header.	
            var dtoDocumentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;();
            dtoDocumentTypes.Add(request);
            string documentTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaDocumentTypes.DocumentType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentTypeID = item.RecID;
                documentTypes.Added -= addedHandler; // remove handler						
            };

            documentTypes.Added += addedHandler;
            documentTypes.DTO_Deserialise(dtoDocumentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", documentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document type with DocumentTypeID '{0}' was found.", documentTypeID));

            // Add the location to the response header						
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0].Split(new[] { '?' })[0], documentType.RecID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Patch(BillDocumentTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.DocumentTableNames.Add("BM_Documents");
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillDocumentTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.DocumentTableNames.Add("BM_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentTypes.Remove(documentType);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Documents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill document with the BillID or DocumentID provided was found")]
    public class BillDocumentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string BillID { get; set; }
        public string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillDocumentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;&gt;
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillDocumentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string BillID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillDocumentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string BillID { get; set; }
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillDocumentDELETERequest
    {
        public string BillID { get; set; }
        public string DocumentID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillDocumentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Get(BillDocumentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = billMaintenance.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt; Get(BillDocumentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            return billMaintenance.Documents.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Post(BillDocumentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the document. Need to jump through a few hoops as we want to know the DocumentID so we can return that in the response header.	
            var documents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;();
            documents.Add(request);
            string documentID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Documents.Document&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentID = item.RecID;
                billMaintenance.Documents.Added -= addedHandler; // remove handler						
            };

            billMaintenance.Documents.Added += addedHandler;
            billMaintenance.Documents.DTO_Deserialise(documents);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = billMaintenance.Documents.GetItem("RecID", documentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document with DocumentID '{0}' was found.", documentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], document.RecID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Patch(BillDocumentPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaApplication.Documents.Document document = billMaintenance.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document with DocumentID '{0}' was found.", request.DocumentID));

            document.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            document = billMaintenance.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillDocumentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = billMaintenance.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill document with DocumentID '{0}' was found.", request.DocumentID));

            billMaintenance.Documents.Remove(document);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }
        }
    }
    #endregion
    #endregion	
	
    #region "Input Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillInputCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage input BillID, StageID or InputID provided was found")]
    public class BillInputCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillInputCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage input custom field Value with the BillID, StageID, InputID or SettingID provided was found")]
    public class BillInputCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage input custom field Value with the BillID, StageID, InputID or SettingID provided was found")]
    public class BillInputCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillInputCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(BillInputCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem BillInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (BillInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

            return BillInput.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(BillInputCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem BillInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (BillInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in BillInput.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(BillInputCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem inputItem = stage.InputItems.GetItem("RecID", request.InputID);

            if (inputItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = inputItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
				
				stage = billMaintenance.Stages.GetItem("RecID", request.StageID);
				
	            if (stage == null)
	                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage with StageID '{0}' was found.", request.StageID));				

                inputItem = stage.InputItems.GetItem("RecID", request.InputID);
				
	            if (inputItem == null)
	                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

                customFieldValue = inputItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(BillInputCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);
            return billMaintenance.InputCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(BillInputCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);

            var BillInputCustomField = billMaintenance.InputCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (BillInputCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return BillInputCustomField;
        }		
    }
    #endregion
    #endregion	
	
    #region "Inputs"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage input with the BillID, StageID, or InputID provided was found")]
    public class BillInputGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage inputs with the BillID or StageID provided was found")]
    public class BillInputsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput&gt;&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage input with the BillID, StageID or InputID provided was found")]
    public class BillInputPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage input with the BillID, StageID, or InputID provided was found")]
    public class BillInputPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public override string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage input with the BillID, StageID, or InputID provided was found")]
    public class BillInputDELETERequest
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillInputServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput Get(BillInputGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem BillInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (BillInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

            return BillInput.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput&gt; Get(BillInputsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.InputItems.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput Post(BillInputPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            // Add the input. Need to jump through a few hoops as we want to know the InputID so we can return that in the response header.	
            var inputs = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput&gt;();
            inputs.Add(request);
            string InputID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                InputID = item.RecID;
                stage.InputItems.Added -= addedHandler; // remove handler						
            };

            stage.InputItems.Added += addedHandler;
            stage.InputItems.DTO_Deserialise(inputs);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem BillInput = stage.InputItems.GetItem("RecID", InputID);

            if (BillInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", InputID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], BillInput.RecID));

            return BillInput.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInput Patch(BillInputPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem BillInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (BillInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

            BillInput.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            BillInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (BillInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

            return BillInput.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillInputDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.InputItem BillInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (BillInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage input with InputID '{0}' was found.", request.InputID));

            stage.InputItems.Remove(BillInput);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
            }
        }
    }
    #endregion
    #endregion	
	
    #region "Instructions"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instruction with the BillID, StageID, or InstructionID provided was found")]
    public class BillInstructionGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instructions with the BillID or StageID provided was found")]
    public class BillInstructionsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction&gt;&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instruction with the BillID, StageID or InstructionID provided was found")]
    public class BillInstructionPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instruction with the BillID, StageID, or InstructionID provided was found")]
    public class BillInstructionPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public override string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instruction with the BillID, StageID, or InstructionID provided was found")]
    public class BillInstructionDELETERequest
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillInstructionServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction Get(BillInstructionGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction BillInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (BillInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            return BillInstruction.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction&gt; Get(BillInstructionsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.Instructions.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction Post(BillInstructionPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            // Add the instruction. Need to jump through a few hoops as we want to know the InstructionID so we can return that in the response header.	
            var instructions = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction&gt;();
            instructions.Add(request);
            string InstructionID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                InstructionID = item.RecID;
                stage.Instructions.Added -= addedHandler; // remove handler						
            };

            stage.Instructions.Added += addedHandler;
            stage.Instructions.DTO_Deserialise(instructions);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction BillInstruction = stage.Instructions.GetItem("RecID", InstructionID);

            if (BillInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", InstructionID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], BillInstruction.RecID));

            return BillInstruction.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillInstruction Patch(BillInstructionPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction BillInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (BillInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            BillInstruction.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            BillInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (BillInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            return BillInstruction.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillInstructionDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction BillInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (BillInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            stage.Instructions.Remove(BillInstruction);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
            }
        }
    }
    #endregion
    #endregion	
	
    #region "Instruction Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillInstructionCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instruction BillID, StageID or InstructionID provided was found")]
    public class BillInstructionCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillInstructionCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instruction custom field Value with the BillID, StageID, InstructionID or SettingID provided was found")]
    public class BillInstructionCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage instruction custom field Value with the BillID, StageID, InstructionID or SettingID provided was found")]
    public class BillInstructionCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillInstructionCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(BillInstructionCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction BillInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (BillInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            return BillInstruction.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(BillInstructionCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction BillInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (BillInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in BillInstruction.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(BillInstructionCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Instruction instructionItem = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (instructionItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = instructionItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);

                instructionItem = stage.Instructions.GetItem("RecID", request.InstructionID);
                customFieldValue = instructionItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(BillInstructionCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);
            return billMaintenance.InstructionCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(BillInstructionCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);

            var BillInstructionCustomField = billMaintenance.InstructionCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (BillInstructionCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage instruction custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return BillInstructionCustomField;
        }		
    }
    #endregion
    #endregion		
	
    #region "Note Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill note type with the NoteTypeID provided was found")]
    public class BillNoteTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillNoteTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillNoteTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill note type with the NoteTypeID provided was found")]
    public class BillNoteTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill note type with the NoteTypeID provided was found")]
    public class BillNoteTypeDELETERequest
    {
        public string NoteTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillNoteTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Get(BillNoteTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.NoteTableNames.Add("BM_Notes");
                    d.Read();
                });

            JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt; Get(BillNoteTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.NoteTableNames.Add("BM_Notes");
                    d.Read();
                });

            return noteTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Post(BillNoteTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.NoteTableNames.Add("BM_Notes");
                    d.Read();
                });

            // Add the note type. Need to jump through a few hoops as we want to know the NoteTypeID so we can return that in the response header.	
            var dtoNoteTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;();
            dtoNoteTypes.Add(request);
            string noteTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaNoteTypes.NoteType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteTypeID = item.RecID;
                noteTypes.Added -= addedHandler; // remove handler						
            };

            noteTypes.Added += addedHandler;
            noteTypes.DTO_Deserialise(dtoNoteTypes);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", noteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note type with NoteTypeID '{0}' was found.", noteTypeID));

            // Add the location to the response header						
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0].Split(new[] { '?' })[0], noteType.RecID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Patch(BillNoteTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.NoteTableNames.Add("BM_Notes");
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillNoteTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Bill.Bill",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance";
					d.NoteTableNames.Add("BM_Notes");
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteTypes.Remove(noteType);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill note with the BillID or NoteID provided was found")]
    public class BillNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string BillID { get; set; }
        public string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;&gt;
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string BillID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string BillID { get; set; }
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillNoteDELETERequest
    {
        public string BillID { get; set; }
        public string NoteID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Get(BillNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = billMaintenance.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt; Get(BillNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            return billMaintenance.Notes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Post(BillNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the note. Need to jump through a few hoops as we want to know the NoteID so we can return that in the response header.	
            var notes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;();
            notes.Add(request);
            string noteID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Notes.Note&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteID = item.RecID;
                billMaintenance.Notes.Added -= addedHandler; // remove handler						
            };

            billMaintenance.Notes.Added += addedHandler;
            billMaintenance.Notes.DTO_Deserialise(notes);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = billMaintenance.Notes.GetItem("RecID", noteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note with NoteID '{0}' was found.", noteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], note.RecID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Patch(BillNotePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaApplication.Notes.Note note = billMaintenance.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note with NoteID '{0}' was found.", request.NoteID));

            note.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            note = billMaintenance.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(BillNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = billMaintenance.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill note with NoteID '{0}' was found.", request.NoteID));

            billMaintenance.Notes.Remove(note);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }
        }
    }
    #endregion
    #endregion		
	
    #region "Output Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillOutputCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill output output BillID or OutputID provided was found")]
    public class BillOutputCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string BillID { get; set; }
        public string OutputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillOutputCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill output output custom field Value with the BillID, OutputID or SettingID provided was found")]
    public class BillOutputCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string OutputID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill output custom field value with the BillID, OutputID or SettingID provided was found")]
    public class BillOutputCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string OutputID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillOutputCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(BillOutputCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            return output.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(BillOutputCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in output.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill output custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(BillOutputCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = output.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill output custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);

                output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);
                customFieldValue = output.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill output custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(BillOutputCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);
            return billMaintenance.OutputCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(BillOutputCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);

            var BillOutputCustomField = billMaintenance.OutputCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (BillOutputCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill output custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return BillOutputCustomField;
        }		
    }
    #endregion
    #endregion		
	
    #region "Outputs"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill output with the BillID or OutputID provided was found")]
    public class BillOutputGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput&gt;
    {
        public string BillID { get; set; }
        public string OutputID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillOutputsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput&gt;&gt;
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillOutputPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput&gt;
    {
        public string BillID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string OutputID { get; set; }
    }	
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID, or OutputID provided was found")]
    public class BillOutputPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput&gt;
    {
        public string BillID { get; set; }
        override public string OutputID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillOutputDELETERequest
    {
        public string BillID { get; set; }
        public string OutputID { get; set; }
    }	
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillOutputServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput Get(BillOutputGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (i, m, s) =&gt;
                {
                    i.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            return output.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput&gt; Get(BillOutputsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (i, m, s) =&gt;
                {
                    i.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            return billMaintenance.OutputItems.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput Post(BillOutputPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the output. Need to jump through a few hoops as we want to know the OutputID so we can return that in the response header.	
            var outputs = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput&gt;();
            outputs.Add(request);
            string outputID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                outputID = item.RecID;
                billMaintenance.OutputItems.Added -= addedHandler; // remove handler						
            };

            billMaintenance.OutputItems.Added += addedHandler;
            billMaintenance.OutputItems.DTO_Deserialise(outputs);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem output = billMaintenance.OutputItems.GetItem("RecID", outputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill output with OutputID '{0}' was found.", outputID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], output.RecID));

            return output.DTO_Serialise();
        }		

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillOutput Patch(BillOutputPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (i, m, s) =&gt;
                {
                    i.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            output.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);

                output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);

                if (output == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));
            }

            return output.DTO_Serialise();
        }
		
        [Authenticate]
        public void Delete(BillOutputDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.OutputItem output = billMaintenance.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill output with OutputID '{0}' was found.", request.OutputID));

            billMaintenance.OutputItems.Remove(output);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }
        }		
    }
    #endregion
    #endregion		
	
    #region "Stage Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillStageCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage stage BillID or StageID provided was found")]
    public class BillStageCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class BillStageCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage stage custom field Value with the BillID, StageID or SettingID provided was found")]
    public class BillStageCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage custom field value with the BillID, StageID or SettingID provided was found")]
    public class BillStageCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillStageCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(BillStageCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(BillStageCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in stage.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(BillStageCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (o, m, s) =&gt;
                {
                    o.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = stage.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);

                stage = billMaintenance.Stages.GetItem("RecID", request.StageID);
                customFieldValue = stage.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(BillStageCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);
            return billMaintenance.StageCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(BillStageCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, null, null);

            var BillStageCustomField = billMaintenance.StageCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (BillStageCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return BillStageCustomField;
        }		
    }
    #endregion
    #endregion	
	
    #region "Stages"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill stage with the BillID or StageID provided was found")]
    public class BillStageGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage&gt;
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID provided was found")]
    public class BillStagesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage&gt;&gt;
    {
        public string BillID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillStagePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage&gt;
    {
        public string BillID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string StageID { get; set; }
    }	
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill record with the BillID, or StageID provided was found")]
    public class BillStagePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage&gt;
    {
        public string BillID { get; set; }
        override public string StageID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No bill with the BillID provided was found")]
    public class BillStageDELETERequest
    {
        public string BillID { get; set; }
        public string StageID { get; set; }
    }	
    #endregion

    #region "Services"				
    [CompressResponse]
    public class BillStageServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage Get(BillStageGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (i, m, s) =&gt;
                {
                    i.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage&gt; Get(BillStagesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (i, m, s) =&gt;
                {
                    i.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            return billMaintenance.Stages.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage Post(BillStagePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the stage. Need to jump through a few hoops as we want to know the StageID so we can return that in the response header.	
            var stages = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage&gt;();
            stages.Add(request);
            string stageID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                stageID = item.RecID;
                billMaintenance.Stages.Added -= addedHandler; // remove handler						
            };

            billMaintenance.Stages.Added += addedHandler;
            billMaintenance.Stages.DTO_Deserialise(stages);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", stageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage with StageID '{0}' was found.", stageID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], stage.RecID));

            return stage.DTO_Serialise();
        }		

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Bills.BillStage Patch(BillStagePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (i, m, s) =&gt;
                {
                    i.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            stage.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);

                stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

                if (stage == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));
            }

            return stage.DTO_Serialise();
        }
		
        [Authenticate]
        public void Delete(BillStageDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance billMaintenance = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance&gt;(manager, this, request.BillID,
                (d, m, s) =&gt;
                {
                    d.Read(request.BillID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.Stage stage = billMaintenance.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No bill stage with StageID '{0}' was found.", request.StageID));

            billMaintenance.Stages.Remove(stage);

            if (!Helper.Service.IsStateful(this))
            {
                billMaintenance.Save();
                billMaintenance.Read(billMaintenance.RecID);
            }
        }		
    }
    #endregion
    #endregion	
	#endregion

    #region "Carriers"			
    #region"{Main}"
    #region "Requests"		
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Carrier with the CarrierID provided was found")]
    public class CarrierGETRequest : IReturn&lt;JiwaServiceModel.Carriers.Carrier&gt;
    {
        public string CarrierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class CarrierPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.Carrier, IReturn&lt;JiwaServiceModel.Carriers.Carrier&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string CarrierID { get; set; }

        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No carrier with the CarrierID provided was found")]
    public class CarrierPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.Carrier, IReturn&lt;JiwaServiceModel.Carriers.Carrier&gt;
    {
        public override string CarrierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No carrier with the CarrierID provided was found")]
    public class CarrierDELETERequest
    {
        public string CarrierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No carrier with the CarrierID provided was found")]
    public class CarrierSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.Carrier&gt;
    {
        public string CarrierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No carrier with the CarrierID provided was found")]
    public class CarrierABANDONRequest
    {
        public string CarrierID { get; set; }
    }


    #endregion

    #region "Services"		
    [CompressResponse]
    public class CarrierServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.Carrier Get(CarrierGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            return Carrier.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Carriers.Carrier Post(CarrierPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier&gt;(null);

            Carrier.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Carrier.RecID, Carrier);
            else
            {
                Carrier.Save();
                Carrier.Read(Carrier.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.CarrierID));

            return Carrier.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Carriers.Carrier Patch(CarrierPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            Carrier.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Carrier.Save();
                Carrier.Read(request.CarrierID);
            }

            return Carrier.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Carriers.Carrier Get(CarrierSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.CarrierID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful carrier exists with CarrierID '{0}'", request.CarrierID));
            }

            var Carrier = (JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier)objectDictionaryValue;

            Carrier.Save();
            Carrier.Read(Carrier.RecID);

            return Carrier.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CarrierABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.CarrierID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful carrier exists with CarrierID '{0}'", request.CarrierID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.CarrierID);
        }

        [Authenticate]
        public void Delete(CarrierDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID, (d, m, s) =&gt; d.Read(request.CarrierID));
            Carrier.Delete();
        }
    }
    #endregion
    #endregion

    #region "Carrier Services"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No service with the CarrierID or ServiceID provided was found")]
    public class CarrierServiceGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService&gt;
    {
        public string CarrierID { get; set; }
        public string ServiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No service with the CarrierID provided was found")]
    public class CarrierServicesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService&gt;&gt;
    {
        public string CarrierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No service with the CarrierID or ServiceID provided was found")]
    public class CarrierServicePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService&gt;
    {
        public string CarrierID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ServiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No service with the CarrierID or ServiceID provided was found")]
    public class CarrierServicePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService&gt;
    {
        public string CarrierID { get; set; }
        public override string ServiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No service with the CarrierID or ServiceID provided was found")]
    public class CarrierServiceDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService
    {
        public string CarrierID { get; set; }
        public override string ServiceID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class CarrierServiceServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService Get(CarrierServiceGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Service carrierService = Carrier.Services.GetItem("RecID", request.ServiceID);

            if (carrierService == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No carrier service with ServiceID '{0}' was found.", request.ServiceID));

            return carrierService.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService&gt; Get(CarrierServicesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });
            return Carrier.Services.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService Post(CarrierServicePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            var carrierServices = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService&gt;();
            carrierServices.Add(request);

            Carrier.Services.DTO_Deserialise(carrierServices);

            if (!Helper.Service.IsStateful(this))
            {
                Carrier.Save();
                Carrier.Read(Carrier.RecID);
            }

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Service carrierService = Carrier.Services.GetItem("RecID", request.ServiceID);

            if (carrierService == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No carrier service with ServiceID '{0}' was found.", request.ServiceID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], carrierService.RecID));

            return carrierService.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierService Patch(CarrierServicePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Service carrierService = Carrier.Services.GetItem("RecID", request.ServiceID);

            if (carrierService == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No carrier service with ServiceID '{0}' was found.", request.ServiceID));

            carrierService.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Carrier.Save();
                Carrier.Read(Carrier.RecID);
            }

            carrierService = Carrier.Services.GetItem("RecID", request.ServiceID);

            if (carrierService == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No carrier service with ServiceID '{0}' was found.", request.ServiceID));

            return carrierService.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CarrierServiceDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Service carrierService = Carrier.Services.GetItem("RecID", request.ServiceID);

            if (carrierService == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No carrier service with ServiceID '{0}' was found.", request.ServiceID));

            Carrier.Services.Remove(carrierService);

            if (!Helper.Service.IsStateful(this))
            {
                Carrier.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Freight Descriptions"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No freight description with the CarrierID or FreightDescriptionID provided was found")]
    public class CarrierFreightDescriptionGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription&gt;
    {
        public string CarrierID { get; set; }
        public string FreightDescriptionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No freight description with the CarrierID provided was found")]
    public class CarrierFreightDescriptionsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription&gt;&gt;
    {
        public string CarrierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No freight description with the CarrierID or FreightDescriptionID provided was found")]
    public class CarrierFreightDescriptionPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription&gt;
    {
        public string CarrierID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string FreightDescriptionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No freight description with the CarrierID or FreightDescriptionID provided was found")]
    public class CarrierFreightDescriptionPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription&gt;
    {
        public string CarrierID { get; set; }
        public override string FreightDescriptionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No freight description with the CarrierID or FreightDescriptionID provided was found")]
    public class CarrierFreightDescriptionDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription
    {
        public string CarrierID { get; set; }
        public override string FreightDescriptionID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class CarrierFreightDescriptionServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription Get(CarrierFreightDescriptionGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCarrierMaint.FreightDescription freightDescription = Carrier.FreightDescriptions.GetItem("RecID", request.FreightDescriptionID);

            if (freightDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No freight description with FreightDescriptionID '{0}' was found.", request.FreightDescriptionID));

            return freightDescription.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription&gt; Get(CarrierFreightDescriptionsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });
            return Carrier.FreightDescriptions.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription Post(CarrierFreightDescriptionPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            var freightDescriptions = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription&gt;();
            freightDescriptions.Add(request);

            Carrier.FreightDescriptions.DTO_Deserialise(freightDescriptions);

            if (!Helper.Service.IsStateful(this))
            {
                Carrier.Save();
                Carrier.Read(Carrier.RecID);
            }

            JiwaFinancials.Jiwa.JiwaCarrierMaint.FreightDescription freightDescription = Carrier.FreightDescriptions.GetItem("RecID", request.FreightDescriptionID);

            if (freightDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No freight description with FreightDescriptionID '{0}' was found.", request.FreightDescriptionID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], freightDescription.RecID));

            return freightDescription.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Carriers.CarrierFreightDescription Patch(CarrierFreightDescriptionPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCarrierMaint.FreightDescription freightDescription = Carrier.FreightDescriptions.GetItem("RecID", request.FreightDescriptionID);

            if (freightDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No freight description with FreightDescriptionID '{0}' was found.", request.FreightDescriptionID));

            freightDescription.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Carrier.Save();
                Carrier.Read(Carrier.RecID);
            }

            freightDescription = Carrier.FreightDescriptions.GetItem("RecID", request.FreightDescriptionID);

            if (freightDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No freight description with FreightDescriptionID '{0}' was found.", request.FreightDescriptionID));

            return freightDescription.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CarrierFreightDescriptionDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCarrierMaint.Carrier Carrier = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCarrierMaint.Carrier&gt;(manager, this, request.CarrierID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CarrierID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCarrierMaint.FreightDescription freightDescription = Carrier.FreightDescriptions.GetItem("RecID", request.FreightDescriptionID);

            if (freightDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No freight description with FreightDescriptionID '{0}' was found.", request.FreightDescriptionID));

            Carrier.FreightDescriptions.Remove(freightDescription);

            if (!Helper.Service.IsStateful(this))
            {
                Carrier.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Creditors"
    #region "{Main}"
    #region "Requests"	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Creditor with the CreditorID provided was found")]
    public class CreditorGETRequest : IReturn&lt;JiwaServiceModel.Creditors.Creditor&gt;
    {
        public string CreditorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class CreditorPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Creditor, IReturn&lt;JiwaServiceModel.Creditors.Creditor&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string CreditorID { get; set; }

        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No creditor with the CreditorID provided was found")]
    public class CreditorPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Creditor, IReturn&lt;JiwaServiceModel.Creditors.Creditor&gt;
    {
        public override string CreditorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No creditor with the CreditorID provided was found")]
    public class CreditorDELETERequest
    {
        public string CreditorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No creditor with the CreditorID provided was found")]
    public class CreditorSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Creditor&gt;
    {
        public string CreditorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No creditor with the CreditorID provided was found")]
    public class CreditorABANDONRequest
    {
        public string CreditorID { get; set; }
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class CreditorServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Creditor Get(CreditorGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CreditorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            return Creditor.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Creditors.Creditor Post(CreditorPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Creditor&gt;(null);

            Creditor.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Creditor.RecID, Creditor);
            else
            {
                Creditor.Save();
                Creditor.Read(Creditor.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.CreditorID));

            return Creditor.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Creditors.Creditor Patch(CreditorPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CreditorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            Creditor.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Creditor.Save();
                Creditor.Read(request.CreditorID);
            }

            return Creditor.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Creditors.Creditor Get(CreditorSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.CreditorID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful creditor exists with CreditorID '{0}'", request.CreditorID));
            }

            var Creditor = (JiwaFinancials.Jiwa.JiwaCreditors.Creditor)objectDictionaryValue;

            Creditor.Save();
            Creditor.Read(Creditor.RecID);

            return Creditor.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CreditorABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.CreditorID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful creditor exists with CreditorID '{0}'", request.CreditorID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.CreditorID);
        }

        [Authenticate]
        public void Delete(CreditorDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID, (d, m, s) =&gt; d.Read(request.CreditorID));
            Creditor.Delete();
        }
    }
    #endregion
    #endregion

    #region "Classifications"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Creditor classification with the ClassificationID provided was found")]
    public class CreditorClassificationGETRequest : IReturn&lt;JiwaServiceModel.Creditors.Classification.CreditorClassification&gt;
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class CreditorClassificationPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Classification.CreditorClassification, IReturn&lt;JiwaServiceModel.Creditors.Classification.CreditorClassification&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ClassificationID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Creditor classification with the ClassificationID provided was found")]
    public class CreditorClassificationPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Classification.CreditorClassification, IReturn&lt;JiwaServiceModel.Creditors.Classification.CreditorClassification&gt;
    {
        public override string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Insufficient permission to update Creditor classifications")]
    [ApiResponse(404, "No Creditor classification with the ClassificationID provided was found")]
    public class CreditorClassificationDELETERequest
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Creditor classification with the ClassificationID provided was found")]
    public class CreditorClassificationSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Classification.CreditorClassification&gt;
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Creditor classification with the ClassificationID provided was found")]
    public class CreditorClassificationABANDONRequest
    {
        public string ClassificationID { get; set; }
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class CreditorClassificationServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.Classification.CreditorClassification Get(CreditorClassificationGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification CreditorClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID,
                (c, m, s) =&gt;
                {
                    c.Read(request.ClassificationID);
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add(c.RecID, c);
                });
            return CreditorClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Creditors.Classification.CreditorClassification Post(CreditorClassificationPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification CreditorClassification = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification&gt;(null);

            CreditorClassification.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(CreditorClassification.RecID, CreditorClassification);
            else
            {
                CreditorClassification.Save();
                CreditorClassification.Read(CreditorClassification.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.ClassificationID));

            return CreditorClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Creditors.Classification.CreditorClassification Patch(CreditorClassificationPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification CreditorClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID,
                (c, m, s) =&gt;
                {
                    c.Read(request.ClassificationID);
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add(c.RecID, c);
                });

            CreditorClassification.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                CreditorClassification.Save();
                CreditorClassification.Read(request.ClassificationID);
            }

            return CreditorClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Creditors.Classification.CreditorClassification Get(CreditorClassificationSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.ClassificationID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful Creditor classification exists with RecID '{0}'", request.ClassificationID));
            }

            var CreditorClassification = (JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification)objectDictionaryValue;
            CreditorClassification.Save();
            CreditorClassification.Read(CreditorClassification.RecID);

            return CreditorClassification.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CreditorClassificationABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.ClassificationID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful Creditor classification exists with RecID '{0}'", request.ClassificationID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.ClassificationID);
        }

        [Authenticate]
        public void Delete(CreditorClassificationDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification CreditorClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaCreditors.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID, (c, m, s) =&gt; c.Read(request.ClassificationID));

            if (CreditorClassification == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No Creditor classification with a RecID of '{0}' was found.", request.ClassificationID));

            CreditorClassification.Delete();
        }
    }
    #endregion
    #endregion

    #region "Warehouse Addresses"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse address with the CreditorID or WarehouseAddressID provided was found")]
    public class CreditorWarehouseAddressGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress&gt;
    {
        public string CreditorID { get; set; }
        public string WarehouseAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse address with the CreditorID provided was found")]
    public class CreditorWarehouseAddressesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress&gt;&gt;
    {
        public string CreditorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse address with the CreditorID or WarehouseAddressID provided was found")]
    public class CreditorWarehouseAddressPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress&gt;
    {
        public string CreditorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string WarehouseAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse address with the CreditorID or WarehouseAddressID provided was found")]
    public class CreditorWarehouseAddressPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress&gt;
    {
        public string CreditorID { get; set; }
        public override string WarehouseAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse address with the CreditorID or WarehouseAddressID provided was found")]
    public class CreditorWarehouseAddressDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress
    {
        public string CreditorID { get; set; }
        public override string WarehouseAddressID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class CreditorWarehouseAddressServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress Get(CreditorWarehouseAddressGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CreditorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCreditors.WarehouseAddress warehouseAddress = Creditor.WarehouseAddresses.GetItem("RecID", request.WarehouseAddressID);

            if (warehouseAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse address with WarehouseAddressID '{0}' was found.", request.WarehouseAddressID));

            return warehouseAddress.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress&gt; Get(CreditorWarehouseAddressesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CreditorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });
            return Creditor.WarehouseAddresses.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress Post(CreditorWarehouseAddressPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CreditorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            var Warehouses = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress&gt;();
            Warehouses.Add(request);

            Creditor.WarehouseAddresses.DTO_Deserialise(Warehouses);

            if (!Helper.Service.IsStateful(this))
            {
                Creditor.Save();
                Creditor.Read(Creditor.RecID);
            }

            JiwaFinancials.Jiwa.JiwaCreditors.WarehouseAddress warehouseAddress = Creditor.WarehouseAddresses.GetItem("RecID", request.WarehouseAddressID);

            if (warehouseAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse address with WarehouseAddressID '{0}' was found.", request.WarehouseAddressID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], warehouseAddress.RecID));

            return warehouseAddress.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Creditors.CreditorWarehouseAddress Patch(CreditorWarehouseAddressPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CreditorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCreditors.WarehouseAddress warehouseAddress = Creditor.WarehouseAddresses.GetItem("RecID", request.WarehouseAddressID);

            if (warehouseAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse address with WarehouseAddressID '{0}' was found.", request.WarehouseAddressID));

            warehouseAddress.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Creditor.Save();
                Creditor.Read(Creditor.RecID);
            }

            warehouseAddress = Creditor.WarehouseAddresses.GetItem("RecID", request.WarehouseAddressID);

            if (warehouseAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse address with WarehouseAddressID '{0}' was found.", request.WarehouseAddressID));

            return warehouseAddress.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CreditorWarehouseAddressDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaCreditors.Creditor Creditor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaCreditors.Creditor&gt;(manager, this, request.CreditorID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CreditorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaCreditors.WarehouseAddress warehouseAddress = Creditor.WarehouseAddresses.GetItem("RecID", request.WarehouseAddressID);

            if (warehouseAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse address with WarehouseAddressID '{0}' was found.", request.WarehouseAddressID));

            Creditor.WarehouseAddresses.Remove(warehouseAddress);

            if (!Helper.Service.IsStateful(this))
            {
                Creditor.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Currencies"
    #region "{Main}"
    #region "Requests"	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Currency with the CurrencyID provided was found")]
    public class CurrencyGETRequest : IReturn&lt;JiwaServiceModel.Currencies.Currency&gt;
    {
        public string CurrencyID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class CurrencyPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.Currency, IReturn&lt;JiwaServiceModel.Currencies.Currency&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string CurrencyID { get; set; }

        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No currency with the CurrencyID provided was found")]
    public class CurrencyPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.Currency, IReturn&lt;JiwaServiceModel.Currencies.Currency&gt;
    {
        public override string CurrencyID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No currency with the CurrencyID provided was found")]
    public class CurrencyDELETERequest
    {
        public string CurrencyID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No currency with the CurrencyID provided was found")]
    public class CurrencySAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.Currency&gt;
    {
        public string CurrencyID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No currency with the CurrencyID provided was found")]
    public class CurrencyABANDONRequest
    {
        public string CurrencyID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class CurrencyServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.Currency Get(CurrencyGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange&gt;(manager, this, request.CurrencyID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CurrencyID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            return Currency.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Currencies.Currency Post(CurrencyPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange&gt;(null);

            Currency.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Currency.RecID, Currency);
            else
            {
                Currency.Save();
                Currency.Read(Currency.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.CurrencyID));

            return Currency.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Currencies.Currency Patch(CurrencyPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange&gt;(manager, this, request.CurrencyID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CurrencyID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            Currency.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Currency.Save();
                Currency.Read(request.CurrencyID);
            }

            return Currency.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Currencies.Currency Get(CurrencySAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.CurrencyID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful currency exists with CurrencyID '{0}'", request.CurrencyID));
            }

            var Currency = (JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange)objectDictionaryValue;

            Currency.Save();
            Currency.Read(Currency.RecID);

            return Currency.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CurrencyABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.CurrencyID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful currency exists with CurrencyID '{0}'", request.CurrencyID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.CurrencyID);
        }

        [Authenticate]
        public void Delete(CurrencyDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange&gt;(manager, this, request.CurrencyID, (d, m, s) =&gt; d.Read(request.CurrencyID));
            Currency.Delete();
        }
    }
    #endregion
    #endregion

    #region "Rates"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No rate with the CurrencyID or RateID provided was found")]
    public class CurrencyRateGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate&gt;
    {
        public string CurrencyID { get; set; }
        public string RateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No rate with the CurrencyID provided was found")]
    public class CurrencyRatesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate&gt;&gt;
    {
        public string CurrencyID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No description with the CurrencyID or RateID provided was found")]
    public class CurrencyRatePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate&gt;
    {
        public string CurrencyID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string RateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No rate with the CurrencyID or RateID provided was found")]
    public class CurrencyRatePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate&gt;
    {
        public string CurrencyID { get; set; }
        public override string RateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No rate with the CurrencyID or RateID provided was found")]
    public class CurrencyRateDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate
    {
        public string CurrencyID { get; set; }
        public override string RateID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class CurrencyRateServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate Get(CurrencyRateGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaForeignExchange.ForeignExchange&gt;(manager, this, request.CurrencyID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CurrencyID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaForeignExchange.Rate Rate = Currency.Rates.GetItem("RecID", request.RateID);

            if (Rate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No rate with RateID '{0}' was found.", request.RateID));

            return Rate.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate Post(CurrencyRatePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaForeignExchange.ForeignExchange&gt;(manager, this, request.CurrencyID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CurrencyID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            var Rates = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate&gt;();
            Rates.Add(request);

            Currency.Rates.DTO_Deserialise(Rates);

            if (!Helper.Service.IsStateful(this))
            {
                Currency.Save();
                Currency.Read(Currency.RecID);
            }

            JiwaFinancials.Jiwa.JiwaForeignExchange.Rate Rate = Currency.Rates.GetItem("RecID", request.RateID);

            if (Rate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No rate with RateID '{0}' was found.", request.RateID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Rate.RecID));

            return Rate.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Currencies.CurrencyRate Patch(CurrencyRatePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaForeignExchange.ForeignExchange&gt;(manager, this, request.CurrencyID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CurrencyID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaForeignExchange.Rate Rate = Currency.Rates.GetItem("RecID", request.RateID);

            if (Rate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No rate with RateID '{0}' was found.", request.RateID));

            Rate.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Currency.Save();
                Currency.Read(Currency.RecID);
            }

            Rate = Currency.Rates.GetItem("RecID", request.RateID);

            if (Rate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No rate with RateID '{0}' was found.", request.RateID));

            return Rate.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(CurrencyRateDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaForeignExchange.ForeignExchange Currency = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaForeignExchange.ForeignExchange&gt;(manager, this, request.CurrencyID,
                (c, m, s) =&gt;
                {
                    c.Read(request.CurrencyID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(c.RecID, c);
                    }
                });

            JiwaFinancials.Jiwa.JiwaForeignExchange.Rate Rate = Currency.Rates.GetItem("RecID", request.RateID);

            if (Rate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No rate with RateID '{0}' was found.", request.RateID));

            Currency.Rates.Remove(Rate);

            if (!Helper.Service.IsStateful(this))
            {
                Currency.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Debtors"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
	[ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]    
    public class DebtorAPIKeyDebtorGETRequest : IReturn&lt;JiwaServiceModel.Debtors.Debtor&gt;
    {        
        // Empty request - we'll determine the debtor by looking at the API Key and seeing which debtor the Key was for.
    }
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorGETRequest : IReturn&lt;JiwaServiceModel.Debtors.Debtor&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Debtor, IReturn&lt;JiwaServiceModel.Debtors.Debtor&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Debtor, IReturn&lt;JiwaServiceModel.Debtors.Debtor&gt;
    {
        public override string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorDELETERequest
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Debtor&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorABANDONRequest
    {
        public string DebtorID { get; set; }
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class DebtorServices : Service
    {
		[Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Debtor Get(DebtorAPIKeyDebtorGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (manager.Database.APIKey_Type != "Debtor")
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.PermissionDeniedException("This service is only intended for use by Debtor API Key authenticated requests.");

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Debtor&gt;(manager, this, manager.Database.APIKey_PrincipalID,
                (d, m, s) =&gt;
                {
                    d.Read(manager.Database.APIKey_PrincipalID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            return Debtor.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Debtor Get(DebtorGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            return Debtor.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Debtor Post(DebtorPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Debtor&gt;(null);

            Debtor.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Debtor.DebtorID, Debtor);
            else
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.DebtorID));

            return Debtor.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Debtor Patch(DebtorPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            Debtor.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(request.DebtorID);
            }

            return Debtor.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Debtor Get(DebtorSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.DebtorID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful debtor exists with DebtorID '{0}'", request.DebtorID));
            }

            var Debtor = (JiwaFinancials.Jiwa.JiwaDebtors.Debtor)objectDictionaryValue;
            Debtor.Save();
            Debtor.Read(Debtor.DebtorID);

            return Debtor.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.DebtorID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful debtor exists with DebtorID '{0}'", request.DebtorID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.DebtorID);
        }

        [Authenticate]
        public void Delete(DebtorDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID, (d, m, s) =&gt; d.Read(request.DebtorID));
            Debtor.Delete();
        }
    }
    #endregion
    #endregion

    #region "Backorders"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Rread OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorBackordersGETRequest : IReturn&lt;List&lt;DebtorBackOrder&gt;&gt;
    {
        public string DebtorID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorBackorderServices : Service
    {
        [Authenticate]
        public List&lt;DebtorBackOrder&gt; Get(DebtorBackordersGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            // Call the stored procedure and return the results, as the stored procedure returns 2 result sets and this is not supported by ormlite
            // Can't use ormlite unfortunately
            //var results = Db.SqlList&lt;object&gt;("EXEC usp_Jiwa_Debtor_BackOrderFulfillments @RecID, @IN_LogicalID, @HR_Staff_StaffID", new { RecID = debtor.Id, IN_LogicalID = "", HR_Staff_StaffID = "" });
            //return results;	

            // So we do it the long way
            var db = manager.Database;
            SqlDataReader SQLReader = null;
            SqlParameter SQLParam = null;

            try
            {
                using (SqlCommand SQLCmd = new SqlCommand("usp_Jiwa_Debtor_BackOrderFulfillments", db.SQLConnection, db.SQLTransaction))
                {
                    SQLCmd.CommandType = System.Data.CommandType.StoredProcedure;

                    SQLParam = new SqlParameter("@RecID", System.Data.SqlDbType.Char);
                    SQLParam.Value = request.DebtorID;
                    SQLParam.Direction = ParameterDirection.Input;
                    SQLCmd.Parameters.Add(SQLParam);

                    SQLParam = new SqlParameter("@IN_LogicalID", System.Data.SqlDbType.Char);
                    SQLParam.Value = System.DBNull.Value;
                    SQLParam.Direction = ParameterDirection.Input;
                    SQLCmd.Parameters.Add(SQLParam);

                    SQLParam = new SqlParameter("@HR_Staff_StaffID", System.Data.SqlDbType.Char);
                    SQLParam.Value = System.DBNull.Value;
                    SQLParam.Direction = ParameterDirection.Input;
                    SQLCmd.Parameters.Add(SQLParam);

                    SQLReader = db.ExecuteReader(SQLCmd);

                    SQLReader.NextResult(); // Skip the first result set, as that's column schema info.

                    List&lt;DebtorBackOrder&gt; backOrders = Helper.Serialisation.SqlDataReaderToList&lt;DebtorBackOrder&gt;(SQLReader);
                    return backOrders;
                }
            }
            finally
            {
                if (SQLReader != null)
                    SQLReader.Close();
            }
        }
    }
    #endregion
    #endregion

    #region "Categories"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor category with the CategoryID provided was found")]
    public class DebtorCategoryGETRequest : IReturn&lt;JiwaServiceModel.Debtors.Category.DebtorCategory&gt;
    {
        public string CategoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorCategoryPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory, IReturn&lt;JiwaServiceModel.Debtors.Category.DebtorCategory&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string CategoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor category with the CategoryID provided was found")]
    public class DebtorCategoryPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory, IReturn&lt;JiwaServiceModel.Debtors.Category.DebtorCategory&gt;
    {
        public override string CategoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No category with the CategoryID provided was found")]
    public class DebtorCategoryDELETERequest
    {
        public string CategoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor category with the CategoryID provided was found")]
    public class DebtorCategoriesSAVERequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor category with the CategoryID provided was found")]
    public class DebtorCategoriesABANDONRequest
    {
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorCategoryServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Category.DebtorCategory Get(DebtorCategoryGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories",
                (c, m, s) =&gt;
                {
                    c.Read();
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories", c);
                });

            var category = cats.DTO_Serialise().Find(x =&gt; x.CategoryID.Trim() == request.CategoryID.Trim());

            if (category == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No debtor category with a RecID of '{0}' was found.", request.CategoryID));
            else
                return category;
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Category.DebtorCategory Post(DebtorCategoryPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories",
                (c, m, s) =&gt;
                {
                    c.Read();
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories", c);
                });

            var listCats = new List&lt;JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            listCats.Add(request);
            cats.DTO_Deserialise(listCats);

            string categoryID = listCats[0].CategoryID;

            if (!Helper.Service.IsStateful(this))
            {
                cats.Save();
                cats.Read();
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], categoryID));

            var categories = cats.DTO_Serialise();
            var category = categories.Find(x =&gt; x.CategoryID.Trim() == categoryID.Trim());

            return category;
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Category.DebtorCategory Patch(DebtorCategoryPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories",
                (c, m, s) =&gt;
                {
                    c.Read();
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories", c);
                });

            var listCats = new List&lt;JiwaServiceModel.Debtors.Category.DebtorCategory&gt;();
            listCats.Add(request);
            cats.DTO_Deserialise(listCats);

            if (!Helper.Service.IsStateful(this))
            {
                cats.Save();
                cats.Read();
            }

            var categories = cats.DTO_Serialise();
            var category = categories.Find(x =&gt; x.CategoryID.Trim() == request.CategoryID.Trim());

            return category;
        }

        [Authenticate]
        public List&lt;JiwaServiceModel.Debtors.Category.DebtorCategory&gt; Get(DebtorCategoriesSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories cats = null;

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful debtor categories exist.");
            }

            cats = (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories)objectDictionaryValue;
            cats.Save();
            cats.Read();

            return cats.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorCategoriesABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful debtor categories exist.");
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove("JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories");
        }

        [Authenticate]
        public void Delete(DebtorCategoryDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            var cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories",
                (c, m, s) =&gt;
                {
                    c.Read();
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Category.Categories", c);
                });

            var categories = cats.DTO_Serialise();
            var category = categories.Find(x =&gt; x.CategoryID.Trim() == request.CategoryID.Trim());

            if (category == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No debtor category with a CategoryID of '{0}' was found.", request.CategoryID));

            switch (category.CategoryNo)
            {
                case 1:
                    cats.Category1Collection.Remove(cats.Category1Collection[request.CategoryID]);
                    break;
                case 2:
                    cats.Category2Collection.Remove(cats.Category2Collection[request.CategoryID]);
                    break;
                case 3:
                    cats.Category3Collection.Remove(cats.Category3Collection[request.CategoryID]);
                    break;
                case 4:
                    cats.Category4Collection.Remove(cats.Category4Collection[request.CategoryID]);
                    break;
                case 5:
                    cats.Category5Collection.Remove(cats.Category5Collection[request.CategoryID]);
                    break;
            }

            if (!Helper.Service.IsStateful(this))
            {
                cats.Save();
                cats.Read();
            }
        }
    }

    #endregion
    #endregion

    #region "Classifications"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor classification with the ClassificationID provided was found")]
    public class DebtorClassificationGETRequest : IReturn&lt;JiwaServiceModel.Debtors.Classification.DebtorClassification&gt;
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorClassificationPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Classification.DebtorClassification, IReturn&lt;JiwaServiceModel.Debtors.Classification.DebtorClassification&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ClassificationID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor classification with the ClassificationID provided was found")]
    public class DebtorClassificationPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Classification.DebtorClassification, IReturn&lt;JiwaServiceModel.Debtors.Classification.DebtorClassification&gt;
    {
        public override string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Insufficient permission to update debtor classifications")]
    [ApiResponse(404, "No debtor classification with the ClassificationID provided was found")]
    public class DebtorClassificationDELETERequest
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor classification with the ClassificationID provided was found")]
    public class DebtorClassificationSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Classification.DebtorClassification&gt;
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor classification with the ClassificationID provided was found")]
    public class DebtorClassificationABANDONRequest
    {
        public string ClassificationID { get; set; }
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class DebtorClassificationServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.Classification.DebtorClassification Get(DebtorClassificationGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification debtorClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID,
                (c, m, s) =&gt;
                {
                    c.Read(request.ClassificationID);
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add(c.RecID, c);
                });
            return debtorClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Classification.DebtorClassification Post(DebtorClassificationPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification debtorClassification = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification&gt;(null);

            debtorClassification.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(debtorClassification.RecID, debtorClassification);
            else
            {
                debtorClassification.Save();
                debtorClassification.Read(debtorClassification.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.ClassificationID));

            return debtorClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Classification.DebtorClassification Patch(DebtorClassificationPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification debtorClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID,
                (c, m, s) =&gt;
                {
                    c.Read(request.ClassificationID);
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add(c.RecID, c);
                });

            debtorClassification.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                debtorClassification.Save();
                debtorClassification.Read(request.ClassificationID);
            }

            return debtorClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Debtors.Classification.DebtorClassification Get(DebtorClassificationSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.ClassificationID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful debtor classification exists with RecID '{0}'", request.ClassificationID));
            }

            var debtorClassification = (JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification)objectDictionaryValue;
            debtorClassification.Save();
            debtorClassification.Read(debtorClassification.RecID);

            return debtorClassification.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorClassificationABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.ClassificationID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful debtor classification exists with RecID '{0}'", request.ClassificationID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.ClassificationID);
        }

        [Authenticate]
        public void Delete(DebtorClassificationDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification debtorClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID, (c, m, s) =&gt; c.Read(request.ClassificationID));

            if (debtorClassification == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No debtor classification with a RecID of '{0}' was found.", request.ClassificationID));

            debtorClassification.Delete();
        }
    }
    #endregion
    #endregion

    #region "Contact Names"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor contact name with the DebtorID or ContactNameID provided was found")]
    public class DebtorContactNameGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName&gt;
    {
        public string DebtorID { get; set; }
        public string ContactNameID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor contact name with the DebtorID or ContactNameID provided was found")]
    public class DebtorContactNamesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor contact name with the DebtorID or ContactNameID provided was found")]
    public class DebtorContactNamePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName&gt;
    {
        public string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ContactNameID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor contact name with the DebtorID or ContactNameID provided was found")]
    public class DebtorContactNamePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName&gt;
    {
        public string DebtorID { get; set; }
        public override string ContactNameID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor contact name with the DebtorID or ContactNameID provided was found")]
    public class DebtorContactNameDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName
    {
        public string DebtorID { get; set; }
        public override string ContactNameID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorContactNameServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName Get(DebtorContactNameGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.ContactName debtorContactName = Debtor.ContactNames.GetItem("RecID", request.ContactNameID);

            if (debtorContactName == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor contact name with RecID '{0}' was found.", request.ContactNameID));

            return debtorContactName.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName&gt; Get(DebtorContactNamesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });
            return Debtor.ContactNames.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName Post(DebtorContactNamePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            // Add the debtor contact name. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var debtorContactNames = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName&gt;();
            debtorContactNames.Add(request);

            Debtor.ContactNames.DTO_Deserialise(debtorContactNames);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            JiwaFinancials.Jiwa.JiwaDebtors.ContactName debtorContactName = Debtor.ContactNames.GetItem("RecID", request.ContactNameID);

            if (debtorContactName == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor contact name with RecID '{0}' was found.", request.ContactNameID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorContactName.RecID));

            return debtorContactName.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorContactName Patch(DebtorContactNamePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.ContactName debtorContactName = Debtor.ContactNames.GetItem("RecID", request.ContactNameID);

            if (debtorContactName == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor contact name with RecID '{0}' was found.", request.ContactNameID));

            debtorContactName.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            debtorContactName = Debtor.ContactNames.GetItem("RecID", request.ContactNameID);

            if (debtorContactName == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor contact name with RecID '{0}' was found.", request.ContactNameID));

            return debtorContactName.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorContactNameDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.ContactName debtorContactName = Debtor.ContactNames.GetItem("RecID", request.ContactNameID);

            if (debtorContactName == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor contact name with RecID '{0}' was found.", request.ContactNameID));

            Debtor.ContactNames.Remove(debtorContactName);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Custom Fields"
    #region "Requests"			
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor custom field value with the DebtorID or SettingID provided was found")]
    public class DebtorCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string DebtorID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor custom field value with the DebtorID or SettingID provided was found")]
    public class DebtorCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string DebtorID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorCustomFieldServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(DebtorCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            var debtorCustomField = debtor.CustomFieldValues.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (debtorCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return debtorCustomField;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(DebtorCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = debtor.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                debtor.Save();
                debtor.Read(debtor.DebtorID);
                customFieldValue = debtor.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(DebtorCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaDebtors.Debtor debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, null, null);
            return debtor.CustomFields.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(DebtorCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            return debtor.CustomFieldValues.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Debtor Part Numbers"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor part number with the DebtorID or PartNumberID provided was found")]
    public class DebtorPartNumberGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber&gt;
    {
        public string DebtorID { get; set; }
        public string PartNumberID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor part number with the DebtorID or PartNumberID provided was found")]
    public class DebtorPartNumbersGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor part number with the DebtorID or PartNumberID provided was found")]
    public class DebtorPartNumberPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber&gt;
    {
        public string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PartNumberID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor part number with the DebtorID or PartNumberID provided was found")]
    public class DebtorPartNumberPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber&gt;
    {
        public string DebtorID { get; set; }
        public override string PartNumberID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor part number with the DebtorID or PartNumberID provided was found")]
    public class DebtorPartNumberDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber
    {
        public string DebtorID { get; set; }
        public override string PartNumberID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorPartNumberServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber Get(DebtorPartNumberGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.DebtorPartNumber debtorPartNumber = Debtor.DebtorPartNumbers.GetItem("RecID", request.PartNumberID);

            if (debtorPartNumber == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor part number with PartNumberID '{0}' was found.", request.PartNumberID));

            return debtorPartNumber.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber&gt; Get(DebtorPartNumbersGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });
            return Debtor.DebtorPartNumbers.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber Post(DebtorPartNumberPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            // Add the debtor part no. Need to jump through a few hoops as we want to know the PartNumberID so we can return that in the response header.	
            var debtorPartNumbers = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber&gt;();
            debtorPartNumbers.Add(request);

            Debtor.DebtorPartNumbers.DTO_Deserialise(debtorPartNumbers);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            JiwaFinancials.Jiwa.JiwaDebtors.DebtorPartNumber debtorPartNumber = Debtor.DebtorPartNumbers.GetItem("RecID", request.PartNumberID);

            if (debtorPartNumber == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor part number with PartNumberID '{0}' was found.", request.PartNumberID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorPartNumber.RecID));

            return debtorPartNumber.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorPartNumber Patch(DebtorPartNumberPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.DebtorPartNumber debtorPartNumber = Debtor.DebtorPartNumbers.GetItem("RecID", request.PartNumberID);

            if (debtorPartNumber == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor part number with PartNumberID '{0}' was found.", request.PartNumberID));

            debtorPartNumber.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            debtorPartNumber = Debtor.DebtorPartNumbers.GetItem("RecID", request.PartNumberID);

            if (debtorPartNumber == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor part number with PartNumberID '{0}' was found.", request.PartNumberID));

            return debtorPartNumber.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorPartNumberDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.DebtorPartNumber debtorPartNumber = Debtor.DebtorPartNumbers.GetItem("RecID", request.PartNumberID);

            if (debtorPartNumber == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor part number with PartNumberID '{0}' was found.", request.PartNumberID));

            Debtor.DebtorPartNumbers.Remove(debtorPartNumber);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Delivery Addresses"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor delivery address with the DebtorID or DeliveryAddressID provided was found")]
    public class DebtorDeliveryAddressGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress&gt;
    {
        public string DebtorID { get; set; }
        public string DeliveryAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor delivery address with the DebtorID or DeliveryAddressID provided was found")]
    public class DebtorDeliveryAddressesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor delivery address with the DebtorID or DeliveryAddressID provided was found")]
    public class DebtorDeliveryAddressPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress&gt;
    {
        public string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DeliveryAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Insufficient permission to update debtor delivery addresses")]
    [ApiResponse(404, "No debtor delivery address with the DebtorID or DeliveryAddressID provided was found")]
    public class DebtorDeliveryAddressPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress&gt;
    {
        public string DebtorID { get; set; }
        public override string DeliveryAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Insufficient permission to update debtor delivery addresses")]
    [ApiResponse(404, "No debtor delivery address with the DebtorID or DeliveryAddressID provided was found")]
    public class DebtorDeliveryAddressDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress
    {
        public string DebtorID { get; set; }
        public override string DeliveryAddressID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class DebtorDeliveryAddressServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress Get(DebtorDeliveryAddressGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.DeliveryAddress debtorDeliveryAddress = Debtor.DeliveryAddresses.GetItem("RecID", request.DeliveryAddressID);

            if (debtorDeliveryAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor delivery address with DeliveryAddressID '{0}' was found.", request.DeliveryAddressID));

            return debtorDeliveryAddress.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress&gt; Get(DebtorDeliveryAddressesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });
            return Debtor.DeliveryAddresses.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress Post(DebtorDeliveryAddressPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            // Add the debtor delivery address. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var debtorDeliveryAddresses = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress&gt;();
            debtorDeliveryAddresses.Add(request);

            Debtor.DeliveryAddresses.DTO_Deserialise(debtorDeliveryAddresses);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            JiwaFinancials.Jiwa.JiwaDebtors.DeliveryAddress debtorDeliveryAddress = Debtor.DeliveryAddresses.GetItem("RecID", request.DeliveryAddressID);

            if (debtorDeliveryAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor delivery address with DeliveryAddressID '{0}' was found.", debtorDeliveryAddress.RecID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorDeliveryAddress.RecID));

            return debtorDeliveryAddress.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorDeliveryAddress Patch(DebtorDeliveryAddressPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.DeliveryAddress debtorDeliveryAddress = Debtor.DeliveryAddresses.GetItem("RecID", request.DeliveryAddressID);

            if (debtorDeliveryAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor delivery address with DeliveryAddressID '{0}' was found.", request.DeliveryAddressID));

            debtorDeliveryAddress.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            debtorDeliveryAddress = Debtor.DeliveryAddresses.GetItem("RecID", request.DeliveryAddressID);

            if (debtorDeliveryAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor delivery address with DeliveryAddressID '{0}' was found.", request.DeliveryAddressID));

            return debtorDeliveryAddress.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorDeliveryAddressDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.DeliveryAddress debtorDeliveryAddress = Debtor.DeliveryAddresses.GetItem("RecID", request.DeliveryAddressID);

            if (debtorDeliveryAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor delivery address with DeliveryAddressID '{0}' was found.", request.DeliveryAddressID));

            Debtor.DeliveryAddresses.Remove(debtorDeliveryAddress);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Document Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor document type with the DocumentTypeID provided was found")]
    public class DebtorDocumentTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorDocumentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorDocumentTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor document type with the DocumentTypeID provided was found")]
    public class DebtorDocumentTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor document type with the DocumentTypeID provided was found")]
    public class DebtorDocumentTypeDELETERequest
    {
        public string DocumentTypeID { get; set; }
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class DebtorDocumentTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Get(DebtorDocumentTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
					d.DocumentTableNames.Add("DB_Documents");					
                    d.Read();
                });

            JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt; Get(DebtorDocumentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
					d.DocumentTableNames.Add("DB_Documents");					
                    d.Read();
                });

            return documentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Post(DebtorDocumentTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
					d.DocumentTableNames.Add("DB_Documents");					
                    d.Read();
                });

            // Add the document type. Need to jump through a few hoops as we want to know the DocumentTypeID so we can return that in the response header.	
            var dtoDocumentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;();
            dtoDocumentTypes.Add(request);

            documentTypes.DTO_Deserialise(dtoDocumentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], documentType.RecID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Patch(DebtorDocumentTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
					d.DocumentTableNames.Add("DB_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorDocumentTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
					d.DocumentTableNames.Add("DB_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentTypes.Remove(documentType);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Documents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor Document with the DebtorID or DocumentID provided was found")]
    public class DebtorDocumentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string DebtorID { get; set; }
        public string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorDocumentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorDocumentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorDocumentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string DebtorID { get; set; }
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorDocumentDELETERequest
    {
        public string DebtorID { get; set; }
        public string DocumentID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorDocumentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Get(DebtorDocumentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = Debtor.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt; Get(DebtorDocumentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            return Debtor.Documents.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Post(DebtorDocumentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            // Add the document. Need to jump through a few hoops as we want to know the DocumentID so we can return that in the response header.	
            var documents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;();
            documents.Add(request);

            Debtor.Documents.DTO_Deserialise(documents);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = Debtor.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document with DocumentID '{0}' was found.", request.DocumentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], document.RecID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Patch(DebtorDocumentPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaApplication.Documents.Document document = Debtor.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document with DocumentID '{0}' was found.", request.DocumentID));

            document.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            document = Debtor.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorDocumentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = Debtor.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor document with DocumentID '{0}' was found.", request.DocumentID));

            Debtor.Documents.Remove(document);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Freight Forwarder Addresses"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor freight forwarder address with the DebtorID or FreightForwarderAddressID provided was found")]
    public class DebtorFreightForwarderAddressGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress&gt;
    {
        public string DebtorID { get; set; }
        public string FreightForwarderAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor freight forwarder address with the DebtorID or FreightForwarderAddressID provided was found")]
    public class DebtorFreightForwarderAddressesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor freight forwarder address with the DebtorID or FreightForwarderAddressID provided was found")]
    public class DebtorFreightForwarderAddressPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress&gt;
    {
        public string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string FreightForwarderAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor freight forwarder address with the DebtorID or FreightForwarderAddressID provided was found")]
    public class DebtorFreightForwarderAddressPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress&gt;
    {
        public string DebtorID { get; set; }
        public override string FreightForwarderAddressID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor freight forwarder address with the DebtorID or FreightForwarderAddressID provided was found")]
    public class DebtorFreightForwarderAddressDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress
    {
        public string DebtorID { get; set; }
        public override string FreightForwarderAddressID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorFreightForwarderAddressServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress Get(DebtorFreightForwarderAddressGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.FreightForwarderAddress debtorFreightForwarderAddress = Debtor.FreightForwarderAddresses.GetItem("RecID", request.FreightForwarderAddressID);

            if (debtorFreightForwarderAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor freight forwarder address with FreightForwarderAddressID '{0}' was found.", request.FreightForwarderAddressID));

            return debtorFreightForwarderAddress.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress&gt; Get(DebtorFreightForwarderAddressesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });
            return Debtor.FreightForwarderAddresses.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress Post(DebtorFreightForwarderAddressPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            // Add the debtor freight forwarder address. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var debtorFreightForwarderAddresses = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress&gt;();
            debtorFreightForwarderAddresses.Add(request);

            Debtor.FreightForwarderAddresses.DTO_Deserialise(debtorFreightForwarderAddresses);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            JiwaFinancials.Jiwa.JiwaDebtors.FreightForwarderAddress debtorFreightForwarderAddress = Debtor.FreightForwarderAddresses.GetItem("RecID", request.FreightForwarderAddressID);

            if (debtorFreightForwarderAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor freight forwarder address with FreightForwarderAddressID '{0}' was found.", request.FreightForwarderAddressID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorFreightForwarderAddress.RecID));

            return debtorFreightForwarderAddress.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorFreightForwarderAddress Patch(DebtorFreightForwarderAddressPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.FreightForwarderAddress debtorFreightForwarderAddress = Debtor.FreightForwarderAddresses.GetItem("RecID", request.FreightForwarderAddressID);

            if (debtorFreightForwarderAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor freight forwarder address with FreightForwarderAddressID '{0}' was found.", request.FreightForwarderAddressID));

            debtorFreightForwarderAddress.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            debtorFreightForwarderAddress = Debtor.FreightForwarderAddresses.GetItem("RecID", request.FreightForwarderAddressID);

            if (debtorFreightForwarderAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor freight forwarder address with FreightForwarderAddressID '{0}' was found.", request.FreightForwarderAddressID));

            return debtorFreightForwarderAddress.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorFreightForwarderAddressDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.FreightForwarderAddress debtorFreightForwarderAddress = Debtor.FreightForwarderAddresses.GetItem("RecID", request.FreightForwarderAddressID);

            if (debtorFreightForwarderAddress == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor freight forwarder address with FreightForwarderAddressID '{0}' was found.", request.FreightForwarderAddressID));

            Debtor.FreightForwarderAddresses.Remove(debtorFreightForwarderAddress);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Groups"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor group membership with the DebtorID or GroupMembershipID provided was found")]
    public class DebtorGroupMembershipGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership&gt;
    {
        public string DebtorID { get; set; }
        public string GroupMembershipID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor group membership with the DebtorID or GroupMembershipID provided was found")]
    public class DebtorGroupMembershipsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor group membership with the DebtorID or GroupMembershipID provided was found")]
    public class DebtorGroupMembershipPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership&gt;
    {
        public string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string GroupMembershipID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor group membership with the DebtorID or GroupMembershipID provided was found")]
    public class DebtorGroupMembershipPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership&gt;
    {
        public string DebtorID { get; set; }
        public override string GroupMembershipID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor group membership with the DebtorID or GroupMembershipID provided was found")]
    public class DebtorGroupMembershipDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership
    {
        public string DebtorID { get; set; }
        public override string GroupMembershipID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorGroupMembershipServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership Get(DebtorGroupMembershipGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.Group debtorGroupMembership = Debtor.Groups.GetItem("RecID", request.GroupMembershipID);

            if (debtorGroupMembership == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor group membership with RecID '{0}' was found.", request.GroupMembershipID));

            return debtorGroupMembership.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership&gt; Get(DebtorGroupMembershipsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });
            return Debtor.Groups.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership Post(DebtorGroupMembershipPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            // Add the debtor group membership. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var debtorGroupMemberships = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership&gt;();
            debtorGroupMemberships.Add(request);

            Debtor.Groups.DTO_Deserialise(debtorGroupMemberships);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            JiwaFinancials.Jiwa.JiwaDebtors.Group debtorGroupMembership = Debtor.Groups.GetItem("RecID", request.GroupMembershipID);

            if (debtorGroupMembership == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor group membership with RecID '{0}' was found.", request.GroupMembershipID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorGroupMembership.RecID));

            return debtorGroupMembership.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.DebtorGroupMembership Patch(DebtorGroupMembershipPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.Group debtorGroupMembership = Debtor.Groups.GetItem("RecID", request.GroupMembershipID);

            if (debtorGroupMembership == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor group membership with RecID '{0}' was found.", request.GroupMembershipID));

            debtorGroupMembership.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            debtorGroupMembership = Debtor.Groups.GetItem("RecID", request.GroupMembershipID);

            if (debtorGroupMembership == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor group membership with RecID '{0}' was found.", request.GroupMembershipID));

            return debtorGroupMembership.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorGroupMembershipDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaDebtors.Group debtorGroupMembership = Debtor.Groups.GetItem("RecID", request.GroupMembershipID);

            if (debtorGroupMembership == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor group membership with RecID '{0}' was found.", request.GroupMembershipID));

            Debtor.Groups.Remove(debtorGroupMembership);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Note Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor note type with the NoteTypeID provided was found")]
    public class DebtorNoteTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorNoteTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorNoteTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor note type with the NoteTypeID provided was found")]
    public class DebtorNoteTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor note type with the NoteTypeID provided was found")]
    public class DebtorNoteTypeDELETERequest
    {
        public string NoteTypeID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class DebtorNoteTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Get(DebtorNoteTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
                    n.Read();
                });

            JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt; Get(DebtorNoteTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
                    n.Read();
                });

            return noteTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Post(DebtorNoteTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
                    n.Read();
                });

            // Add the note type. Need to jump through a few hoops as we want to know the NoteTypeID so we can return that in the response header.	
            var dtoNoteTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;();
            dtoNoteTypes.Add(request);

            noteTypes.DTO_Deserialise(dtoNoteTypes);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], noteType.RecID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Patch(DebtorNoteTypePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorNoteTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDebtors.Debtor",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaDebtors.Debtor";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteTypes.Remove(noteType);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor Note with the DebtorID or NoteID provided was found")]
    public class DebtorNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string DebtorID { get; set; }
        public string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;&gt;
    {
        public string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string DebtorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string DebtorID { get; set; }
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor with the DebtorID provided was found")]
    public class DebtorNoteDELETERequest
    {
        public string DebtorID { get; set; }
        public string NoteID { get; set; }
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class DebtorNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Get(DebtorNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = Debtor.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt; Get(DebtorNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            return Debtor.Notes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Post(DebtorNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            // Add the note. Need to jump through a few hoops as we want to know the NoteID so we can return that in the response header.	
            var notes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;();
            notes.Add(request);

            Debtor.Notes.DTO_Deserialise(notes);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = Debtor.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note with NoteID '{0}' was found.", request.NoteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], note.RecID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Patch(DebtorNotePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaApplication.Notes.Note note = Debtor.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note with NoteID '{0}' was found.", request.NoteID));

            note.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
                Debtor.Read(Debtor.DebtorID);
            }

            note = Debtor.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaDebtors.Debtor Debtor = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaDebtors.Debtor&gt;(manager, this, request.DebtorID,
                (d, m, s) =&gt;
                {
                    d.Read(request.DebtorID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.DebtorID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = Debtor.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor note with NoteID '{0}' was found.", request.NoteID));

            Debtor.Notes.Remove(note);

            if (!Helper.Service.IsStateful(this))
            {
                Debtor.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Pricing Groups"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor pricing group with the PricingGroupID provided was found")]
    public class DebtorPricingGroupGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup&gt;
    {
        public string PricingGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class DebtorPricingGroupPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PricingGroupID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor pricing group with the PricingGroupID provided was found")]
    public class DebtorPricingGroupPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup&gt;
    {
        public override string PricingGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor pricing group with the PricingGroupID provided was found")]
    public class DebtorPricingGroupDELETERequest
    {
        public string PricingGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor pricing groups were found")]
    public class DebtorPricingGroupsSAVERequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor pricing groups were found")]
    public class DebtorPricingGroupsABANDONRequest
    {
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class DebtorPricingGroupServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup Get(DebtorPricingGroupGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDBPricingGroups.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDBPricingGroups.PricingGroup, JiwaDBPricingGroups.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            JiwaDBPricingGroups.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor pricing group with PricingGroupID '{0}' was found.", request.PricingGroupID));

            return pricingGroup.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup Post(DebtorPricingGroupPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDBPricingGroups.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDBPricingGroups.PricingGroup, JiwaDBPricingGroups.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            var dtoPricingGroups = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup&gt;();
            dtoPricingGroups.Add(request);

            pricingGroups.DTO_Deserialise(dtoPricingGroups);

            if (!Helper.Service.IsStateful(this))
            {
                pricingGroups.Save();
                pricingGroups.Read();
            }

            JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor pricing group with PricingGroupID '{0}' was found.", request.PricingGroupID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], pricingGroup.RecID));

            return pricingGroup.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup Patch(DebtorPricingGroupPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDBPricingGroups.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDBPricingGroups.PricingGroup, JiwaDBPricingGroups.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor pricing group with PricingGroupID '{0}' was found.", request.PricingGroupID));

            pricingGroup.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                pricingGroups.Save();
                pricingGroups.Read();
            }

            pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor pricing group with PricingGroupID '{0}' was found.", request.PricingGroupID));

            return pricingGroup.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorPricingGroupDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDBPricingGroups.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDBPricingGroups.PricingGroup, JiwaDBPricingGroups.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor pricing group with PricingGroupID '{0}' was found.", request.PricingGroupID));

            pricingGroups.Remove(pricingGroup);

            if (!Helper.Service.IsStateful(this))
            {
                pricingGroups.Save();
                pricingGroups.Read();
            }
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Debtors.PricingGroup.DebtorPricingGroup&gt; Get(DebtorPricingGroupsSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection pricingGroups = null;

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful debtor pricing groups exist.");
            }

            pricingGroups = (JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection)objectDictionaryValue;
            pricingGroups.Save();
            pricingGroups.Read();

            return pricingGroups.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(DebtorPricingGroupsABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful debtor pricing groups exist.");
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove("JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection");
        }

    }
    #endregion
    #endregion
    #endregion

    #region "Goods Received Notes"
    #region "{Main}"
    #region "Models"
	[Serializable()]
    public class ReceivedPOLineQuantity
    {
        public string OrderLineID { get; set; }
        public decimal? Quantity { get; set; }
    }
    #endregion

    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID provided was found")]
    public class GoodsReceivedNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;
    {
        public string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class GoodsReceivedNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;
    {
        public override string CreditorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string GRNID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID provided was found")]
    public class GoodsReceivedNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote, IReturn&lt;JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;
    {
        public override string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID provided was found")]
    public class GoodsReceivedNoteDELETERequest
    {
        public string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID provided was found")]
    public class GoodsReceivedNoteSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;
    {
        public string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID provided was found")]
    public class GoodsReceivedNoteABANDONRequest
    {
        public string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Purchase Order(s) with the PO No. provided was found")]
    public class GoodsReceivedNoteCREATEFromPORequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;
    {
        public string[] OrderNos { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Purchase Order Line(s) with the OrderLineID provided was found")]
    public class GoodsReceivedNoteCREATEFromPOLinesRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;
    {
        public GoodsReceivedNoteCREATEFromPOLinesRequest()
        {
            ReceivedPOLineQuantities = new System.Collections.Generic.List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity&gt;();
        }

        public System.Collections.Generic.List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity&gt; ReceivedPOLineQuantities { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No GRN with the GRNID provided was found")]
    public class GoodsReceivedNoteACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote&gt;
    {
        public string GRNID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class GoodsReceivedNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote Get(GoodsReceivedNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            return goodsReceivedNote.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote Post(GoodsReceivedNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(null);

            goodsReceivedNote.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(goodsReceivedNote.RecID, goodsReceivedNote);
            else
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.GRNID));

            return goodsReceivedNote.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote Patch(GoodsReceivedNotePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            goodsReceivedNote.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(request.GRNID);
            }

            return goodsReceivedNote.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(GoodsReceivedNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID, (g, m, s) =&gt; g.Read(request.GRNID));
            goodsReceivedNote.Delete();
        }

        [Authenticate]
        public JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote Get(GoodsReceivedNoteSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.GRNID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful goods received note exists with GRNID '{0}'", request.GRNID));
            }

            var goodsReceivedNote = (JiwaFinancials.Jiwa.JiwaInvReceival.Receival)objectDictionaryValue;

            goodsReceivedNote.Save();
            goodsReceivedNote.Read(goodsReceivedNote.RecID);

            return goodsReceivedNote.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(GoodsReceivedNoteABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.GRNID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful goods received note exists with GRNID '{0}'", request.GRNID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.GRNID);
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote Post(GoodsReceivedNoteCREATEFromPORequest request)
        {
            // find creditor
            if (request.OrderNos.Length == 0)
            {
                throw new Exception("No Order No's provided - array empty");
            }

            PO_Main firstPO = Db.Single(Db.From&lt;PO_Main&gt;().Where(x =&gt; x.OrderNo == request.OrderNos[0]).Take(1));

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival grn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(null);
            grn.CreateNew(firstPO.CreditorID);

            foreach (string orderNo in request.OrderNos)
            {
                PO_Main po = Db.Single(Db.From&lt;PO_Main&gt;().Where(pl =&gt; pl.OrderNo == orderNo).Take(1));

                if (po == null)
                {
                    throw new Exception(string.Format("PO with Order No. '{0}' was not found", orderNo));
                }

                string newOrderKey = "";
                string OrderID = po.OrderID;
                grn.PurchaseOrders.AddPO(OrderID, ref newOrderKey);
            }

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(grn.RecID, grn);
            else
            {
                grn.Save();
                grn.Read(grn.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], grn.RecID));

            return grn.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote Post(GoodsReceivedNoteCREATEFromPOLinesRequest request)
        {
            // find creditor
            if (request.ReceivedPOLineQuantities.Count == 0)
                throw new Exception("No purchase order lines provided - array empty");

            var OrderIDs = new System.Collections.Generic.List&lt;string&gt;();
            string creditorID = "";
            foreach (ReceivedPOLineQuantity existingReceivedPOLineQuantity in request.ReceivedPOLineQuantities)
            {
                PO_Main purchaseOrder = Db.Single(Db.From&lt;PO_Main&gt;()
                                .Join&lt;PO_Main, PO_Lines&gt;()
                                .Where&lt;PO_Lines&gt;(x =&gt; x.OrderLineID == existingReceivedPOLineQuantity.OrderLineID)
                                .Take(1));

                OrderIDs.Add(purchaseOrder.OrderID);
                creditorID = purchaseOrder.CreditorID; //Should all be the same.
            }

            var distinctOrderIDs = OrderIDs.Distinct();

            if (creditorID.Trim().Length == 0)
                throw new Exception("No valid creditor found for order lines provided");

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInvReceival.Receival grn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(null);
            grn.CreateNew(creditorID);

            string newKey = "";
            foreach (string orderID in distinctOrderIDs)
                grn.PurchaseOrders.AddPO(orderID, ref newKey);

            JiwaFinancials.Jiwa.JiwaInvReceival.Line grnLine;
            for (int myLoop = grn.Lines.Count; myLoop &gt; 0; myLoop--)
            {
                grnLine = grn.Lines[myLoop];

                if (request.ReceivedPOLineQuantities.FirstOrDefault(item =&gt; item.OrderLineID.Trim() == grnLine.PurchaseOrderLine.RecID.Trim()) != null)
                    grnLine.Quantity = (decimal)request.ReceivedPOLineQuantities.First(item =&gt; item.OrderLineID.Trim() == grnLine.PurchaseOrderLine.RecID.Trim()).Quantity;
                else
                    grn.Lines.Remove(grnLine);
            }

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(grn.RecID, grn);
            else
            {
                grn.Save();
                grn.Read(grn.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], grn.RecID));

            return grn.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNote Post(GoodsReceivedNoteACTIVATERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival grn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(null);
            grn.Read(request.GRNID);

            grn.ActivateRecord();
            grn.Read(request.GRNID);
            return grn.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Purchase Orders"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the GRNID or OrderID provided was found")]
    public class GoodsReceivedNotePurchaseOrderGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived&gt;
    {
        public string GRNID { get; set; }
        public string OrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the GRNID provided was found")]
    public class GoodsReceivedNotePurchaseOrdersGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived&gt;&gt;
    {
        public string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the GRNID or OrderID provided was found")]
    public class GoodsReceivedNotePurchaseOrderPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived&gt;
    {
        public string GRNID { get; set; }
        public override string OrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the GRNID or OrderID provided was found")]
    public class GoodsReceivedNotePurchaseOrderDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived
    {
        public string GRNID { get; set; }
        public override string OrderID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class GoodsReceivedNotePurchaseOrderServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived Get(GoodsReceivedNotePurchaseOrderGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.PurchaseOrder purchaseOrder = goodsReceivedNote.PurchaseOrders.GetItem("OrderID", request.OrderID);

            if (purchaseOrder == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No purchase order with OrderID '{0}' was found.", request.OrderID));

            return purchaseOrder.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived&gt; Get(GoodsReceivedNotePurchaseOrdersGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });
            return goodsReceivedNote.PurchaseOrders.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived Post(GoodsReceivedNotePurchaseOrderPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            var purchaseOrders = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNotePurchaseOrderReceived&gt;();
            purchaseOrders.Add(request);

            goodsReceivedNote.PurchaseOrders.DTO_Deserialise(purchaseOrders);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }

            JiwaFinancials.Jiwa.JiwaInvReceival.PurchaseOrder purchaseOrder = goodsReceivedNote.PurchaseOrders.GetItem("OrderID", request.OrderID);

            if (purchaseOrder == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No purchase order with OrderID '{0}' was found.", request.OrderID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], purchaseOrder.OrderID));

            return purchaseOrder.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(GoodsReceivedNotePurchaseOrderDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.PurchaseOrder purchaseOrder = goodsReceivedNote.PurchaseOrders.GetItem("OrderID", request.OrderID);

            if (purchaseOrder == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No purchase order with OrderID '{0}' was found.", request.OrderID));

            goodsReceivedNote.PurchaseOrders.Remove(purchaseOrder);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the GRNID or LineID provided was found")]
    public class GoodsReceivedNoteLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine&gt;
    {
        public string GRNID { get; set; }
        public string LineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the GRNID provided was found")]
    public class GoodsReceivedNoteLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine&gt;&gt;
    {
        public string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the GRNID or LineID provided was found")]
    public class GoodsReceivedNoteLinePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine&gt;
    {
        public string GRNID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the GRNID or LineID provided was found")]
    public class GoodsReceivedNoteLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine&gt;
    {
        public string GRNID { get; set; }
        public override string LineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the GRNID or LineID provided was found")]
    public class GoodsReceivedNoteLineDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine
    {
        public string GRNID { get; set; }
        public override string LineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class GoodsReceivedNoteLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine Get(GoodsReceivedNoteLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line Line = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine&gt; Get(GoodsReceivedNoteLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });
            return goodsReceivedNote.Lines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine Post(GoodsReceivedNoteLinePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            var Lines = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine&gt;();
            Lines.Add(request);

            goodsReceivedNote.Lines.DTO_Deserialise(Lines);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }

            JiwaFinancials.Jiwa.JiwaInvReceival.Line Line = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Line.RecID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLine Patch(GoodsReceivedNoteLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line Line = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            Line.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }

            Line = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(GoodsReceivedNoteLineDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (g, m, s) =&gt;
                {
                    g.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line Line = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            goodsReceivedNote.Lines.Remove(Line);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
            }
        }
    }
    #endregion
    #endregion
	
    #region "Line Details"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID or LineID provided was found")]
    public class GoodsReceivedNoteLineDetailsGETManyRequest : IReturn&lt;List&lt;JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt;&gt;
    {
        public string GRNID { get; set; }
        public string LineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID or LineID or LineDetailID provided was found")]
    public class GoodsReceivedNoteLineDetailGETRequest : IReturn&lt;JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt;
    {
        public string GRNID { get; set; }
        public string LineID { get; set; }
        public string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID or  LineID provided was found")]
    public class GoodsReceivedNoteLineDetailPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt;
    {
        public string GRNID { get; set; }
        public string LineID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LineDetailID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]    
    public class GoodsReceivedNoteLineDetailPUTRequest : List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt;, IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt;&gt;
    {	
		public string GRNID { get; set; }
		public string LineID { get; set; }
    }		

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID or LineID provided was found")]
    public class GoodsReceivedNoteLineDetailPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt;
    {
        public string GRNID { get; set; }
        public string LineID { get; set; }
        public override string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the GRNID or  LineID or LineDetailID provided was found")]
    public class GoodsReceivedNoteLineDetailDELETERequest
    {
        public string GRNID { get; set; }
        public string LineID { get; set; }
        public string LineDetailID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class GoodsReceivedNoteLineDetailServices : Service
    {
        [Authenticate]
        public List&lt;JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt; Get(GoodsReceivedNoteLineDetailsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (o, m, s) =&gt;
                {
                    o.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });


            JiwaFinancials.Jiwa.JiwaInvReceival.Line goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            return goodsReceivedNoteLine.LineDetails.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail Get(GoodsReceivedNoteLineDetailGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (o, m, s) =&gt;
                {
                    o.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            JiwaFinancials.Jiwa.JiwaInvReceival.LineDetail goodsReceivedNoteLineDetail = goodsReceivedNoteLine.LineDetails.GetItem("RecID", request.LineDetailID);

            if (goodsReceivedNoteLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return goodsReceivedNoteLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail Post(GoodsReceivedNoteLineDetailPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (o, m, s) =&gt;
                {
                    o.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            // Add the line detail. Need to jump through a few hoops as we want to know the LineDetailID so we can return that in the response header.	
            var lineDetails = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt;();
            lineDetails.Add(request);
            string lineDetailID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaInvReceival.LineDetail&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                lineDetailID = item.RecID;
                goodsReceivedNoteLine.LineDetails.Added -= addedHandler; // remove handler						
            };

            goodsReceivedNoteLine.LineDetails.Added += addedHandler;
            goodsReceivedNoteLine.LineDetails.DTO_Deserialise(lineDetails);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }

            goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            JiwaFinancials.Jiwa.JiwaInvReceival.LineDetail goodsReceivedNoteLineDetail = goodsReceivedNoteLine.LineDetails.GetItem("RecID", lineDetailID);

            if (goodsReceivedNoteLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line detail with LineDetailID '{0}' was found.", lineDetailID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], goodsReceivedNoteLineDetail.RecID));

            return goodsReceivedNoteLineDetail.DTO_Serialise();
        }
		
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail&gt; Put(GoodsReceivedNoteLineDetailPUTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (o, m, s) =&gt;
                {
                    o.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));
					
			// remove any existing line details
			goodsReceivedNoteLine.LineDetails.RemoveAll();
			
			goodsReceivedNoteLine.setQuantityWithoutGeneratingLineDetails(goodsReceivedNoteLine.CalculateTotalLineDetailsQuantity());
			
			// Now add new line details as provided
			goodsReceivedNoteLine.LineDetails.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }

            goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            return goodsReceivedNoteLine.LineDetails.DTO_Serialise();		
        }		

        [Authenticate]
        public JiwaServiceModel.GoodsReceivedNotes.GoodsReceivedNoteLineDetail Patch(GoodsReceivedNoteLineDetailPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (o, m, s) =&gt;
                {
                    o.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            JiwaFinancials.Jiwa.JiwaInvReceival.LineDetail goodsReceivedNoteLineDetail = goodsReceivedNoteLine.LineDetails.GetItem("RecID", request.LineDetailID);

            if (goodsReceivedNoteLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            goodsReceivedNoteLineDetail.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }

            goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            goodsReceivedNoteLineDetail = goodsReceivedNoteLine.LineDetails.GetItem("RecID", request.LineDetailID);

            if (goodsReceivedNoteLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return goodsReceivedNoteLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(GoodsReceivedNoteLineDetailDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(manager, this, request.GRNID,
                (o, m, s) =&gt;
                {
                    o.Read(request.GRNID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInvReceival.Line goodsReceivedNoteLine = goodsReceivedNote.Lines.GetItem("RecID", request.LineID);

            if (goodsReceivedNoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line with LineID '{0}' was found.", request.LineID));

            JiwaFinancials.Jiwa.JiwaInvReceival.LineDetail goodsReceivedNoteLineDetail = goodsReceivedNoteLine.LineDetails.GetItem("RecID", request.LineDetailID);

            if (goodsReceivedNoteLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            goodsReceivedNoteLine.LineDetails.Remove(goodsReceivedNoteLineDetail);
			goodsReceivedNoteLine.setQuantityWithoutGeneratingLineDetails(goodsReceivedNoteLine.CalculateTotalLineDetailsQuantity());

            if (!Helper.Service.IsStateful(this))
            {
                goodsReceivedNote.Save();
                goodsReceivedNote.Read(goodsReceivedNote.RecID);
            }
        }
    }
    #endregion
    #endregion	
    #endregion

    #region "Inventory"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryGETRequest : IReturn&lt;JiwaServiceModel.Inventory.InventoryItem&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryItem, IReturn&lt;JiwaServiceModel.Inventory.InventoryItem&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryItem, IReturn&lt;JiwaServiceModel.Inventory.InventoryItem&gt;
    {
        public override string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryDELETERequest
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventorySAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryItem&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryABANDONRequest
    {
        public string InventoryID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryItem Get(InventoryGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            return Inventory.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryItem Post(InventoryPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Inventory&gt;(null);

            Inventory.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Inventory.InventoryID, Inventory);
            else
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.InventoryID));

            return Inventory.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryItem Patch(InventoryPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            Inventory.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(request.InventoryID);
            }

            return Inventory.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryItem Get(InventorySAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.InventoryID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful inventory exists with InventoryID '{0}'", request.InventoryID));
            }

            var Inventory = (JiwaFinancials.Jiwa.JiwaInventory.Inventory)objectDictionaryValue;

            Inventory.Save();
            Inventory.Read(Inventory.RecID);

            return Inventory.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.InventoryID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful inventory exists with InventoryID '{0}'", request.InventoryID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.InventoryID);
        }

        [Authenticate]
        public void Delete(InventoryDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Inventory&gt;(manager, this, request.InventoryID, (d, m, s) =&gt; d.Read(request.InventoryID));
            Inventory.Delete();
        }
    }
    #endregion
    #endregion

    #region "Alternate Children"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory alternate child with the InventoryID or RecID provided was found")]
    public class InventoryAlternateChildGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild&gt;
    {
        public string InventoryID { get; set; }
        public string AlternateChildID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory alternate child with the InventoryID or RecID provided was found")]
    public class InventoryAlternateChildrenGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory alternate child with the InventoryID or RecID provided was found")]
    public class InventoryAlternateChildPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string AlternateChildID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory alternate child with the InventoryID or RecID provided was found")]
    public class InventoryAlternateChildPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild&gt;
    {
        public string InventoryID { get; set; }
        public override string AlternateChildID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory alternate child with the InventoryID or RecID provided was found")]
    public class InventoryAlternateChildDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild
    {
        public string InventoryID { get; set; }
        public override string AlternateChildID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryAlternateChildServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild Get(InventoryAlternateChildGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AlternateChild inventoryAlternateChild = Inventory.AlternateChildren.GetItem("RecID", request.AlternateChildID);

            if (inventoryAlternateChild == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory alternate child with RecID '{0}' was found.", request.AlternateChildID));

            return inventoryAlternateChild.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild&gt; Get(InventoryAlternateChildrenGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.AlternateChildren.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild Post(InventoryAlternateChildPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory alternate child. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var inventoryAlternateChildren = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild&gt;();
            inventoryAlternateChildren.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.AlternateChild&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.AlternateChildren.Added -= addedHandler; // remove handler						
            };

            Inventory.AlternateChildren.Added += addedHandler;
            Inventory.AlternateChildren.DTO_Deserialise(inventoryAlternateChildren);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.AlternateChild inventoryAlternateChild = Inventory.AlternateChildren.GetItem("RecID", recID);

            if (inventoryAlternateChild == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory alternate child with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventoryAlternateChild.RecID));

            return inventoryAlternateChild.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateChild Patch(InventoryAlternateChildPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AlternateChild inventoryAlternateChild = Inventory.AlternateChildren.GetItem("RecID", request.AlternateChildID);

            if (inventoryAlternateChild == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory alternate child with RecID '{0}' was found.", request.AlternateChildID));

            inventoryAlternateChild.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryAlternateChild = Inventory.AlternateChildren.GetItem("RecID", request.AlternateChildID);

            if (inventoryAlternateChild == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory alternate child with RecID '{0}' was found.", request.AlternateChildID));

            return inventoryAlternateChild.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryAlternateChildDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AlternateChild inventoryAlternateChild = Inventory.AlternateChildren.GetItem("RecID", request.AlternateChildID);

            if (inventoryAlternateChild == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory alternate child with RecID '{0}' was found.", request.AlternateChildID));

            Inventory.AlternateChildren.Remove(inventoryAlternateChild);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Alternate Parents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory alternate parent with the InventoryID or RecID provided was found")]
    public class InventoryAlternateParentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateParent&gt;
    {
        public string InventoryID { get; set; }
        public string LinkedInventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory alternate parent with the InventoryID or RecID provided was found")]
    public class InventoryAlternateParentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateParent&gt;&gt;
    {
        public string InventoryID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class InventoryAlternateParentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateParent Get(InventoryAlternateParentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AlternateParent inventoryAlternateParent = null;
            foreach (JiwaFinancials.Jiwa.JiwaInventory.AlternateParent existingAlternateParent in Inventory.AlternateParents)
                if (existingAlternateParent.LinkedInventory.InventoryID == request.LinkedInventoryID)
                {
                    inventoryAlternateParent = Inventory.AlternateParents.GetItem("RecID", existingAlternateParent.RecID);
                    break;
                }

            if (inventoryAlternateParent == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory alternate parent with LinkedInventoryID '{0}' was found.", request.LinkedInventoryID));

            return inventoryAlternateParent.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAlternateParent&gt; Get(InventoryAlternateParentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });
            return Inventory.AlternateParents.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Attribute Group Template Attributes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group template attribute with the AttributeGroupTemplateAttributeID provided was found")]
    public class InventoryAttributeGroupTemplateAttributeGETRequest : IReturn&lt;JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute&gt;
    {
        public string AttributeGroupTemplateID { get; set; }
        public string TemplateAttributeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group template with the AttributeTemplateID provided was found")]
    public class InventoryAttributeGroupTemplateAttributesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute&gt;&gt;
    {
        public string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group template with the AttributeTemplateID provided was found")]
    public class InventoryAttributeGroupTemplateAttributePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute&gt;
    {
        public override string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group template attribute with the AttributeTemplateID or AttributeGroupTemplateAttributeID provided was found")]
    public class InventoryAttributeGroupTemplateAttributePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute&gt;
    {
        public override string TemplateAttributeID { get; set; }
        public override string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group template attribute with the AttributeGroupTemplateAttributeID provided was found")]
    public class InventoryAttributeGroupTemplateAttributeDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute
    {
        public override string TemplateAttributeID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class InventoryAttributeGroupTemplateAttributeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute Get(InventoryAttributeGroupTemplateAttributeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID, (a, m, s) =&gt; a.Read(request.AttributeGroupTemplateID));
            foreach (JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Attribute existingAttribute in inventoryAttributeGroupTemplate.AttributeCollection)
                if (existingAttribute.RecID == request.TemplateAttributeID)
                    return existingAttribute.DTO_Serialise();

            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group template attribute with RecID '{0}' was found.", request.TemplateAttributeID));
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute&gt; Get(InventoryAttributeGroupTemplateAttributesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();			

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID, (a, m, s) =&gt; a.Read(request.AttributeGroupTemplateID));
            return inventoryAttributeGroupTemplate.AttributeCollection.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute Post(InventoryAttributeGroupTemplateAttributePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID,
                (a, m, s) =&gt;
                {
                    a.Read(request.AttributeGroupTemplateID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(a.RecID, a);
                    }
                });

            // Add the inventory attribute group template attribute. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var inventoryAttributeGroupTemplateAttributes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute&gt;();
            inventoryAttributeGroupTemplateAttributes.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.Configuration.AttributeGroupTemplate.Attribute&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                inventoryAttributeGroupTemplate.AttributeCollection.Added -= addedHandler; // remove handler						
            };

            inventoryAttributeGroupTemplate.AttributeCollection.Added += addedHandler;
            inventoryAttributeGroupTemplate.AttributeCollection.DTO_Deserialise(inventoryAttributeGroupTemplateAttributes);

            if (!Helper.Service.IsStateful(this))
            {
                inventoryAttributeGroupTemplate.Save();
                inventoryAttributeGroupTemplate.Read(inventoryAttributeGroupTemplate.RecID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Attribute inventoryAttributeGroupTemplateAttribute = inventoryAttributeGroupTemplate.AttributeCollection.GetItem("RecID", recID);

            if (inventoryAttributeGroupTemplateAttribute == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group template attribute with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventoryAttributeGroupTemplateAttribute.RecID));

            return inventoryAttributeGroupTemplateAttribute.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryAttributeGroupTemplateAttribute Patch(InventoryAttributeGroupTemplateAttributePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID,
                (a, m, s) =&gt;
                {
                    a.Read(request.AttributeGroupTemplateID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(a.RecID, a);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Attribute inventoryAttributeGroupTemplateAttribute = inventoryAttributeGroupTemplate.AttributeCollection.GetItem("RecID", request.AttributeGroupTemplateID);

            if (inventoryAttributeGroupTemplateAttribute == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group template attribute with AttributeGroupTemplateAttributeID '{0}' was found.", request.AttributeGroupTemplateID));

            inventoryAttributeGroupTemplateAttribute.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                inventoryAttributeGroupTemplate.Save();
                inventoryAttributeGroupTemplate.Read(inventoryAttributeGroupTemplate.RecID);
            }

            inventoryAttributeGroupTemplateAttribute = inventoryAttributeGroupTemplate.AttributeCollection.GetItem("RecID", request.AttributeGroupTemplateID);

            if (inventoryAttributeGroupTemplateAttribute == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group template attribute with RecID '{0}' was found.", request.AttributeGroupTemplateID));

            return inventoryAttributeGroupTemplateAttribute.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryAttributeGroupTemplateAttributeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID,
                (a, m, s) =&gt;
                {
                    a.Read(request.AttributeGroupTemplateID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(a.RecID, a);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Attribute inventoryAttributeGroupTemplateAttribute = inventoryAttributeGroupTemplate.AttributeCollection.GetItem("RecID", request.AttributeGroupTemplateID);

            if (inventoryAttributeGroupTemplateAttribute == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group template attribute with AttributeGroupTemplateAttributeID '{0}' was found.", request.AttributeGroupTemplateID));

            inventoryAttributeGroupTemplate.AttributeCollection.Remove(inventoryAttributeGroupTemplateAttribute);

            if (!Helper.Service.IsStateful(this))
            {
                inventoryAttributeGroupTemplate.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Attribute Group Templates"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group template with the AttributeGroupTemplateID provided was found")]
    public class InventoryAttributeGroupTemplateGETRequest : IReturn&lt;JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate&gt;
    {
        public string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryAttributeGroupTemplatePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate, IReturn&lt;JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group template with the AttributeGroupTemplateID provided was found")]
    public class InventoryAttributeGroupTemplatePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate, IReturn&lt;JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate&gt;
    {
        public override string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No classification with the AttributeGroupTemplateID provided was found")]
    public class InventoryAttributeGroupTemplateDELETERequest
    {
        public string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory classification with the AttributeGroupTemplateID provided was found")]
    public class InventoryAttributeGroupTemplateSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate&gt;
    {
        public string AttributeGroupTemplateID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory classification with the AttributeGroupTemplateID provided was found")]
    public class InventoryAttributeGroupTemplateABANDONRequest
    {
        public string AttributeGroupTemplateID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class InventoryAttributeGroupTemplateServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate Get(InventoryAttributeGroupTemplateGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID, (a, m, s) =&gt; a.Read(request.AttributeGroupTemplateID));
            return inventoryAttributeGroupTemplate.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate Post(InventoryAttributeGroupTemplatePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(null);

            inventoryAttributeGroupTemplate.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(inventoryAttributeGroupTemplate.RecID, inventoryAttributeGroupTemplate);
            else
            {
                inventoryAttributeGroupTemplate.Save();
                inventoryAttributeGroupTemplate.Read(inventoryAttributeGroupTemplate.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.AttributeGroupTemplateID));

            return inventoryAttributeGroupTemplate.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate Patch(InventoryAttributeGroupTemplatePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID, (a, m, s) =&gt; a.Read(request.AttributeGroupTemplateID));

            inventoryAttributeGroupTemplate.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                inventoryAttributeGroupTemplate.Save();
                inventoryAttributeGroupTemplate.Read(request.AttributeGroupTemplateID);
            }

            return inventoryAttributeGroupTemplate.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.InventoryAttributeGroupTemplate Get(InventoryAttributeGroupTemplateSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.AttributeGroupTemplateID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful inventory attribute group template exists with RecID '{0}'", request.AttributeGroupTemplateID));
            }

            var inventoryAttributeGroupTemplate = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template)objectDictionaryValue;
            inventoryAttributeGroupTemplate.Save();

            return inventoryAttributeGroupTemplate.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryAttributeGroupTemplateABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.AttributeGroupTemplateID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful inventory attribute group template exists with AttributeGroupTemplateID '{0}'", request.AttributeGroupTemplateID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.AttributeGroupTemplateID);
        }

        [Authenticate]
        public void Delete(InventoryAttributeGroupTemplateDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template inventoryAttributeGroupTemplate = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.AttributeGroupTemplate.Template&gt;(manager, this, request.AttributeGroupTemplateID, (a, m, s) =&gt; a.Read(request.AttributeGroupTemplateID));

            if (inventoryAttributeGroupTemplate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No inventory attribute group template with a AttributeGroupTemplateID of '{0}' was found.", request.AttributeGroupTemplateID));

            inventoryAttributeGroupTemplate.Delete();
        }
    }
    #endregion
    #endregion

    #region "Attribute Groups"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group with the InventoryID or RecID provided was found")]
    public class InventoryAttributeGroupGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup&gt;
    {
        public string InventoryID { get; set; }
        public string AttributeGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group with the InventoryID or RecID provided was found")]
    public class InventoryAttributeGroupsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group with the InventoryID or RecID provided was found")]
    public class InventoryAttributeGroupPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string AttributeGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group with the InventoryID or RecID provided was found")]
    public class InventoryAttributeGroupPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup&gt;
    {
        public string InventoryID { get; set; }
        public override string AttributeGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute group with the InventoryID or RecID provided was found")]
    public class InventoryAttributeGroupDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup
    {
        public string InventoryID { get; set; }
        public override string AttributeGroupID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryAttributeGroupServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup Get(InventoryAttributeGroupGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AttributeGroup inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group with RecID '{0}' was found.", request.AttributeGroupID));

            return inventoryAttributeGroup.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup&gt; Get(InventoryAttributeGroupsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.AttributeGroups.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup Post(InventoryAttributeGroupPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory attribute group. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var inventoryAttributeGroups = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup&gt;();
            inventoryAttributeGroups.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.AttributeGroup&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.AttributeGroups.Added -= addedHandler; // remove handler						
            };

            Inventory.AttributeGroups.Added += addedHandler;
            Inventory.AttributeGroups.DTO_Deserialise(inventoryAttributeGroups);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.AttributeGroup inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", recID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventoryAttributeGroup.RecID));

            return inventoryAttributeGroup.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroup Patch(InventoryAttributeGroupPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AttributeGroup inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group with RecID '{0}' was found.", request.AttributeGroupID));

            inventoryAttributeGroup.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group with RecID '{0}' was found.", request.AttributeGroupID));

            return inventoryAttributeGroup.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryAttributeGroupDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AttributeGroup inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute group with RecID '{0}' was found.", request.AttributeGroupID));

            Inventory.AttributeGroups.Remove(inventoryAttributeGroup);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Attribute Values"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute value with the InventoryID or RecID provided was found")]
    public class InventoryAttributeValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupAttribute&gt;
    {
        public string InventoryID { get; set; }
        public string AttributeGroupID { get; set; }
        public string AttributeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory attribute value with the InventoryID or RecID provided was found")]
    public class InventoryAttributeValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupAttribute, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupAttribute&gt;
    {
        public string InventoryID { get; set; }
        public override string AttributeGroupID { get; set; }
        public override string AttributeID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryAttributeValueServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupAttribute Get(InventoryAttributeValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AttributeGroup inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Group with RecID '{0}' was found.", request.AttributeGroupID));


            JiwaFinancials.Jiwa.JiwaInventory.AttributeValue inventoryAttributeValue = inventoryAttributeGroup.AttributeValueCollection.GetItem("RecID", request.AttributeID);

            if (inventoryAttributeValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Value with RecID '{0}' was found.", request.AttributeID));

            return inventoryAttributeValue.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryAttributeGroupAttribute Patch(InventoryAttributeValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.AttributeGroup inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Group with RecID '{0}' was found.", request.AttributeGroupID));


            JiwaFinancials.Jiwa.JiwaInventory.AttributeValue inventoryAttributeValue = inventoryAttributeGroup.AttributeValueCollection.GetItem("RecID", request.AttributeID);

            if (inventoryAttributeValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Value with RecID '{0}' was found.", request.AttributeID));

            inventoryAttributeValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Group with RecID '{0}' was found.", request.AttributeGroupID));


            inventoryAttributeValue = inventoryAttributeGroup.AttributeValueCollection.GetItem("RecID", request.AttributeID);

            if (inventoryAttributeValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Value with RecID '{0}' was found.", request.AttributeID));

            return inventoryAttributeValue.DTO_Serialise();
        }

        /*
        [Authenticate]
        public void Delete(InventoryAttributeValueDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();			        

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID, 
                (i, m, s) =&gt; 
                { 
                    i.Read(request.InventoryID); 
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });


            JiwaFinancials.Jiwa.JiwaInventory.AttributeGroup inventoryAttributeGroup = Inventory.AttributeGroups.GetItem("RecID", request.AttributeGroupID);

            if (inventoryAttributeGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Group with RecID '{0}' was found.", request.AttributeGroupID));


            JiwaFinancials.Jiwa.JiwaInventory.AttributeValue inventoryAttributeValue = inventoryAttributeGroup.AttributeValueCollection.GetItem("RecID", request.AttributeID);

            if (inventoryAttributeValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory attribute Value with RecID '{0}' was found.", request.AttributeID));

            //System.Diagnostics.Debugger.Launch();
            inventoryAttributeGroup.AttributeValueCollection.Remove(inventoryAttributeValue);

            if (! Helper.Service.IsStateful(this))
            {
                Inventory.Save();						
            }
        }	
        */
    }
    #endregion
    #endregion

    #region "Budgets"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No budget with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryBudgetGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryBudget&gt;
    {
        public int? MonthIndex { get; set; }
        public string InventoryID { get; set; }
        public string LogicalWarehouseID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No budgets with the InventoryID provided was found")]
    public class InventoryBudgetsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryBudget&gt;&gt;
    {
        public string InventoryID { get; set; }
        public string LogicalWarehouseID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No budget with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryBudgetPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryBudget, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryBudget&gt;
    {
        public override int? MonthIndex { get; set; }
        public string InventoryID { get; set; }
        public override string LogicalWarehouseID { get; set; }
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class InventoryBudgetServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryBudget Get(InventoryBudgetGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    i.Budgets.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            if (!Inventory.Budgets.HasBeenRead)
                Inventory.Budgets.Read();

            JiwaFinancials.Jiwa.JiwaInventory.Month Month = Inventory.Months[(int)request.MonthIndex];

            if (Month == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No month '{0}' for inventory item with an InventoryID of {1} was found.", request.MonthIndex, request.InventoryID));

            bool warehouseFound = false;
            JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.LogicalWarehouse logicalWarehouse = null;

            foreach (JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.PhysicalWarehouse existingPhysicalWarehouse in manager.PhysicalWarehouseCollection)
            {
                foreach (JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.LogicalWarehouse existingLogicalWarehouse in existingPhysicalWarehouse.LogicalWarehouseCollection)
                    if (existingLogicalWarehouse.IN_LogicalID == request.LogicalWarehouseID)
                    {
                        logicalWarehouse = existingLogicalWarehouse;
                        warehouseFound = true;
                        break;
                    }

                if (warehouseFound)
                    break;
            }
            if (logicalWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            JiwaFinancials.Jiwa.JiwaInventory.Budget inventoryBudget = Inventory.Budgets.RetrieveBudget(Month, logicalWarehouse);

            if (inventoryBudget == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No budget with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            return inventoryBudget.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryBudget&gt; Get(InventoryBudgetsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    i.Budgets.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            if (!Inventory.Budgets.HasBeenRead)
                Inventory.Budgets.Read();

            return Inventory.Budgets.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryBudget Patch(InventoryBudgetPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    i.Budgets.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            if (!Inventory.Budgets.HasBeenRead)
                Inventory.Budgets.Read();

            JiwaFinancials.Jiwa.JiwaInventory.Month Month = Inventory.Months[(int)request.MonthIndex];

            if (Month == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No month '{0}' for inventory item with an InventoryID of {1} was found.", request.MonthIndex, request.InventoryID));

            bool warehouseFound = false;
            JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.LogicalWarehouse logicalWarehouse = null;

            foreach (JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.PhysicalWarehouse existingPhysicalWarehouse in manager.PhysicalWarehouseCollection)
            {
                foreach (JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.LogicalWarehouse existingLogicalWarehouse in existingPhysicalWarehouse.LogicalWarehouseCollection)
                    if (existingLogicalWarehouse.IN_LogicalID == request.LogicalWarehouseID)
                    {
                        logicalWarehouse = existingLogicalWarehouse;
                        warehouseFound = true;
                        break;
                    }

                if (warehouseFound)
                    break;
            }
            if (logicalWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            JiwaFinancials.Jiwa.JiwaInventory.Budget inventoryBudget = Inventory.Budgets.RetrieveBudget(Month, logicalWarehouse);

            if (inventoryBudget == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No budget with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            inventoryBudget.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
                Inventory.Budgets.Read();
            }

            inventoryBudget = Inventory.Budgets.RetrieveBudget(Month, logicalWarehouse);

            if (inventoryBudget == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No budget with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            return inventoryBudget.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Categories"
    #region "Requests"		
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory category with the CategoryID provided was found")]
    public class InventoryCategoryGETRequest : IReturn&lt;JiwaServiceModel.Inventory.Category.InventoryCategory&gt;
    {
        public string CategoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryCategoryPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory, IReturn&lt;JiwaServiceModel.Inventory.Category.InventoryCategory&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string CategoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory category with the CategoryID provided was found")]
    public class InventoryCategoryPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory, IReturn&lt;JiwaServiceModel.Inventory.Category.InventoryCategory&gt;
    {
        public override string CategoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No category with the CategoryID provided was found")]
    public class InventoryCategoryDELETERequest
    {
        public string CategoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory category with the CategoryID provided was found")]
    public class InventoryCategoriesSAVERequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory category with the CategoryID provided was found")]
    public class InventoryCategoriesABANDONRequest
    {
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryCategoryServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Category.InventoryCategory Get(InventoryCategoryGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories",
            (c, m, s) =&gt;
            {
                c.Read();
                if (Helper.Service.IsStateful(s))
                    m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", c);
            });

            var category = cats.DTO_Serialise().Find(x =&gt; x.CategoryID == request.CategoryID);

            if (category == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No inventory category with a RecID of '{0}' was found.", request.CategoryID));
            else
                return category;
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.Category.InventoryCategory Post(InventoryCategoryPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories",
            (c, m, s) =&gt;
            {
                c.Read();
                if (Helper.Service.IsStateful(s))
                    m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", c);
            });

            var listCats = new List&lt;JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            listCats.Add(request);
            cats.DTO_Deserialise(listCats);
            string categoryID = listCats[0].CategoryID;

            if (Helper.Service.IsStateful(this))
            {
                object objectDictionaryValue = null;
                if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", out objectDictionaryValue)) //Add if not already there
                    manager.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", cats);
            }
            else
            {
                cats.Save();
                cats.Read();
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], categoryID));

            var categories = cats.DTO_Serialise();
            var category = categories.Find(x =&gt; x.CategoryID == categoryID);

            return category;
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.Category.InventoryCategory Patch(InventoryCategoryPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", (c, m, s) =&gt; c.Read());
            var listCats = new List&lt;JiwaServiceModel.Inventory.Category.InventoryCategory&gt;();
            listCats.Add(request);
            cats.DTO_Deserialise(listCats);

            if (!Helper.Service.IsStateful(this))
            {
                cats.Save();
                cats.Read();
            }

            var categories = cats.DTO_Serialise();
            var category = categories.Find(x =&gt; x.CategoryID == request.CategoryID);

            return category;
        }

        [Authenticate]
        public List&lt;JiwaServiceModel.Inventory.Category.InventoryCategory&gt; Get(InventoryCategoriesSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories cats = null;

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful inventory categories exist.");
            }

            cats = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories)objectDictionaryValue;
            cats.Save();
            cats.Read();

            return cats.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryCategoriesABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful inventory categories exist.");
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories");
        }

        [Authenticate]
        public void Delete(InventoryCategoryDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            var cats = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories",
                (c, m, s) =&gt;
                {
                    c.Read();
                    if (Helper.Service.IsStateful(s))
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories", c);
                });
            var categories = cats.DTO_Serialise();
            var category = categories.Find(x =&gt; x.CategoryID.Trim() == request.CategoryID.Trim());

            if (category == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No inventory category with a CategoryID of '{0}' was found.", request.CategoryID));

            switch (category.CategoryNo)
            {
                case 1:
                    cats.Category1Collection.Remove(cats.Category1Collection[request.CategoryID]);
                    break;
                case 2:
                    cats.Category2Collection.Remove(cats.Category2Collection[request.CategoryID]);
                    break;
                case 3:
                    cats.Category3Collection.Remove(cats.Category3Collection[request.CategoryID]);
                    break;
                case 4:
                    cats.Category4Collection.Remove(cats.Category4Collection[request.CategoryID]);
                    break;
                case 5:
                    cats.Category5Collection.Remove(cats.Category5Collection[request.CategoryID]);
                    break;
            }

            if (!Helper.Service.IsStateful(this))
            {
                cats.Save();
                cats.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Classifications"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory classification with the ClassificationID provided was found")]
    public class InventoryClassificationGETRequest : IReturn&lt;JiwaServiceModel.Inventory.Classification.InventoryClassification&gt;
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryClassificationPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Classification.InventoryClassification, IReturn&lt;JiwaServiceModel.Inventory.Classification.InventoryClassification&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ClassificationID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory classification with the ClassificationID provided was found")]
    public class InventoryClassificationPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Classification.InventoryClassification, IReturn&lt;JiwaServiceModel.Inventory.Classification.InventoryClassification&gt;
    {
        public override string ClassificationID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No classification with the ClassificationID provided was found")]
    public class InventoryClassificationDELETERequest
    {
        public string ClassificationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory classification with the ClassificationID provided was found")]
    public class InventoryClassificationSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Classification.InventoryClassification&gt;
    {
        public string RecID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory classification with the ClassificationID provided was found")]
    public class InventoryClassificationABANDONRequest
    {
        public string RecID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryClassificationServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.Classification.InventoryClassification Get(InventoryClassificationGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification inventoryClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID, (c, m, s) =&gt; c.Read(request.ClassificationID));
            return inventoryClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.Classification.InventoryClassification Post(InventoryClassificationPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification inventoryClassification = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification&gt;(null);

            inventoryClassification.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(inventoryClassification.RecID, inventoryClassification);
            else
            {
                inventoryClassification.Save();
                inventoryClassification.Read(inventoryClassification.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.ClassificationID));

            return inventoryClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.Classification.InventoryClassification Patch(InventoryClassificationPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification inventoryClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID, (c, m, s) =&gt; c.Read(request.ClassificationID));

            inventoryClassification.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                inventoryClassification.Save();
                inventoryClassification.Read(request.ClassificationID);
            }

            return inventoryClassification.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Inventory.Classification.InventoryClassification Get(InventoryClassificationSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.RecID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful inventory classification exists with RecID '{0}'", request.RecID));
            }

            var inventoryClassification = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification)objectDictionaryValue;
            inventoryClassification.Save();

            return inventoryClassification.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryClassificationABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.RecID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful inventory classification exists with RecID '{0}'", request.RecID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.RecID);
        }

        [Authenticate]
        public void Delete(InventoryClassificationDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification inventoryClassification = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification&gt;(manager, this, request.ClassificationID, (c, m, s) =&gt; c.Read(request.ClassificationID));

            if (inventoryClassification == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No inventory classification with a RecID of '{0}' was found.", request.ClassificationID));

            inventoryClassification.Delete();
        }
    }
    #endregion
    #endregion

    #region "Components"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No component with the InventoryID or RecID provided was found")]
    public class InventoryComponentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent&gt;
    {
        public string InventoryID { get; set; }
        public string ComponentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No component with the InventoryID or RecID provided was found")]
    public class InventoryComponentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No component with the InventoryID or RecID provided was found")]
    public class InventoryComponentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ComponentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No component with the InventoryID or RecID provided was found")]
    public class InventoryComponentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent&gt;
    {
        public string InventoryID { get; set; }
        public override string ComponentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No component with the InventoryID or RecID provided was found")]
    public class InventoryComponentDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent
    {
        public string InventoryID { get; set; }
        public override string ComponentID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class InventoryComponentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent Get(InventoryComponentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Component inventoryComponent = Inventory.Components.GetItem("RecID", request.ComponentID);

            if (inventoryComponent == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No component with RecID '{0}' was found.", request.ComponentID));

            return inventoryComponent.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent&gt; Get(InventoryComponentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.Components.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent Post(InventoryComponentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            var inventoryComponents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent&gt;();
            inventoryComponents.Add(request);

            Inventory.Components.DTO_Deserialise(inventoryComponents);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.Component inventoryComponent = Inventory.Components.GetItem("RecID", request.ComponentID);

            if (inventoryComponent == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No component with RecID '{0}' was found.", request.ComponentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventoryComponent.RecID));

            return inventoryComponent.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryComponent Patch(InventoryComponentPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Component inventoryComponent = Inventory.Components.GetItem("RecID", request.ComponentID);

            if (inventoryComponent == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No component with RecID '{0}' was found.", request.ComponentID));

            inventoryComponent.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryComponent = Inventory.Components.GetItem("RecID", request.ComponentID);

            if (inventoryComponent == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No component with RecID '{0}' was found.", request.ComponentID));

            return inventoryComponent.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryComponentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Component inventoryComponent = Inventory.Components.GetItem("RecID", request.ComponentID);

            if (inventoryComponent == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No component with RecID '{0}' was found.", request.ComponentID));

            Inventory.Components.Remove(inventoryComponent);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Custom Fields"
    #region "Requests"	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory custom field value with the InventoryID or SettingID provided was found")]
    public class InventoryCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InventoryID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory custom field value with the InventoryID or SettingID provided was found")]
    public class InventoryCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InventoryID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory item with the InventoryID provided was found")]
    public class InventoryCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string InventoryID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryCustomFieldServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(InventoryCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            var inventoryCustomField = Inventory.CustomFieldValues.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (inventoryCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return inventoryCustomField;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(InventoryCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = inventory.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                inventory.Save();
                inventory.Read(inventory.InventoryID);
                customFieldValue = inventory.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(InventoryCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInventory.Inventory inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, null, null);
            return inventory.CustomFields.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(InventoryCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInventory.Inventory inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });
            return inventory.CustomFieldValues.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Document Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory document type with the DocumentTypeID provided was found")]
    public class InventoryDocumentTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryDocumentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryDocumentTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory document type with the DocumentTypeID provided was found")]
    public class InventoryDocumentTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory document type with the DocumentTypeID provided was found")]
    public class InventoryDocumentTypeDELETERequest
    {
        public string DocumentTypeID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class InventoryDocumentTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Get(InventoryDocumentTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.DocumentType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt; Get(InventoryDocumentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.DocumentType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            return documentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Post(InventoryDocumentTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.DocumentType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            // Add the document type. Need to jump through a few hoops as we want to know the DocumentTypeID so we can return that in the response header.	
            var dtoDocumentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;();
            dtoDocumentTypes.Add(request);
            string documentTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaDocumentTypes.DocumentType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentTypeID = item.RecID;
                documentTypes.Added -= addedHandler; // remove handler						
            };

            documentTypes.Added += addedHandler;
            documentTypes.DTO_Deserialise(dtoDocumentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", documentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", documentTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], documentType.RecID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Patch(InventoryDocumentTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.DocumentType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryDocumentTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.DocumentType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentTypes.Remove(documentType);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Documents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory Document with the InventoryID or DocumentID provided was found")]
    public class InventoryDocumentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string InventoryID { get; set; }
        public string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read Ok")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryDocumentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryDocumentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryDocumentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string InventoryID { get; set; }
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryDocumentDELETERequest
    {
        public string InventoryID { get; set; }
        public string DocumentID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class InventoryDocumentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Get(InventoryDocumentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = Inventory.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt; Get(InventoryDocumentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            return Inventory.Documents.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Post(InventoryDocumentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            // Add the document. Need to jump through a few hoops as we want to know the DocumentID so we can return that in the response header.	
            var documents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;();
            documents.Add(request);
            string documentID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Documents.Document&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentID = item.RecID;
                Inventory.Documents.Added -= addedHandler; // remove handler						
            };

            Inventory.Documents.Added += addedHandler;
            Inventory.Documents.DTO_Deserialise(documents);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = Inventory.Documents.GetItem("RecID", documentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", documentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], document.RecID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Patch(InventoryDocumentPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            JiwaApplication.Documents.Document document = Inventory.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document with DocumentID '{0}' was found.", request.DocumentID));

            document.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            document = Inventory.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryDocumentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = Inventory.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document with DocumentID '{0}' was found.", request.DocumentID));

            Inventory.Documents.Remove(document);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }
        }
    }
    #endregion
    #endregion

    #region "Ledgers"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory ledger with the InventoryID or Name provided was found")]
    public class InventoryLedgerGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryLedger&gt;
    {
        public string InventoryID { get; set; }
        public string Name { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory ledger with the InventoryID provided was found")]
    public class InventoryLedgersGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryLedger&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory ledger with the InventoryID or Name provided was found")]
    public class InventoryLedgerPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryLedger, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryLedger&gt;
    {
        public string InventoryID { get; set; }
        public override string Name { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryLedgerServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryLedger Get(InventoryLedgerGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.InventoryLedger inventoryLedger = null;
            foreach (JiwaFinancials.Jiwa.JiwaInventory.InventoryLedger existingInventoryLedger in Inventory.InventoryLedgers)
                if (existingInventoryLedger.LedgerName == request.Name)
                {
                    inventoryLedger = existingInventoryLedger;
                    break;
                }


            if (inventoryLedger == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory ledger with Name '{0}' was found.", request.Name));

            return inventoryLedger.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryLedger&gt; Get(InventoryLedgersGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.InventoryLedgers.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryLedger Patch(InventoryLedgerPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.InventoryLedger inventoryLedger = null;
            foreach (JiwaFinancials.Jiwa.JiwaInventory.InventoryLedger existingInventoryLedger in Inventory.InventoryLedgers)
                if (existingInventoryLedger.LedgerName == request.Name)
                {
                    inventoryLedger = existingInventoryLedger;
                    break;
                }

            if (inventoryLedger == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory ledger with Name '{0}' was found.", request.Name));

            inventoryLedger.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryLedger = null;
            foreach (JiwaFinancials.Jiwa.JiwaInventory.InventoryLedger existingInventoryLedger in Inventory.InventoryLedgers)
                if (existingInventoryLedger.LedgerName == request.Name)
                {
                    inventoryLedger = existingInventoryLedger;
                    break;
                }

            if (inventoryLedger == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory ledger with Name '{0}' was found.", request.Name));

            return inventoryLedger.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Note Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory note type with the NoteTypeID provided was found")]
    public class InventoryNoteTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryNoteTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryNoteTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory note type with the NoteTypeID provided was found")]
    public class InventoryNoteTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory note type with the NoteTypeID provided was found")]
    public class InventoryNoteTypeDELETERequest
    {
        public string NoteTypeID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class InventoryNoteTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Get(InventoryNoteTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt; Get(InventoryNoteTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            return noteTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Post(InventoryNoteTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            // Add the note type. Need to jump through a few hoops as we want to know the NoteTypeID so we can return that in the response header.	
            var dtoNoteTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;();
            dtoNoteTypes.Add(request);
            string noteTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaNoteTypes.NoteType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteTypeID = item.RecID;
                noteTypes.Added -= addedHandler; // remove handler						
            };

            noteTypes.Added += addedHandler;
            noteTypes.DTO_Deserialise(dtoNoteTypes);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", noteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", noteTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], noteType.RecID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Patch(InventoryNoteTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryNoteTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Inventory",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaInventory.Inventory";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteTypes.Remove(noteType);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory Note with the InventoryID or NoteID provided was found")]
    public class InventoryNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string InventoryID { get; set; }
        public string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string InventoryID { get; set; }
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory with the InventoryID provided was found")]
    public class InventoryNoteDELETERequest
    {
        public string InventoryID { get; set; }
        public string NoteID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Get(InventoryNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = Inventory.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt; Get(InventoryNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            return Inventory.Notes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Post(InventoryNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            // Add the note. Need to jump through a few hoops as we want to know the NoteID so we can return that in the response header.	
            var notes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;();
            notes.Add(request);
            string noteID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Notes.Note&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteID = item.RecID;
                Inventory.Notes.Added -= addedHandler; // remove handler						
            };

            Inventory.Notes.Added += addedHandler;
            Inventory.Notes.DTO_Deserialise(notes);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = Inventory.Notes.GetItem("RecID", noteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", noteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], note.RecID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Patch(InventoryNotePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            JiwaApplication.Notes.Note note = Inventory.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note with NoteID '{0}' was found.", request.NoteID));

            note.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            note = Inventory.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InventoryID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = Inventory.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note with NoteID '{0}' was found.", request.NoteID));

            Inventory.Notes.Remove(note);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }
        }
    }
    #endregion
    #endregion

    #region "Order Levels"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No order level with the OrderLevelID provided was found")]
    public class InventoryOrderLevelGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOrderLevel&gt;
    {
        public string LogicalWarehouseID { get; set; }
        public string InventoryID { get; set; }
        public int PeriodNo { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No order levels with the InventoryID provided was found")]
    public class InventoryOrderLevelsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOrderLevel&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No order level with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryOrderLevelPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOrderLevel, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOrderLevel&gt;
    {
        public override string LogicalWarehouseID { get; set; }
        public string InventoryID { get; set; }
        public override int PeriodNo { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryOrderLevelServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOrderLevel Get(InventoryOrderLevelGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    i.OrderLevels.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.LogicalWarehouse logicalWarehouse = manager.PhysicalWarehouseCollection.FindLogicalWarehouse(request.LogicalWarehouseID);

            if (logicalWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse with IN_LogicalID '{0}' was found.", request.LogicalWarehouseID));

            JiwaFinancials.Jiwa.JiwaInventory.OrderLevel inventoryOrderLevel = Inventory.OrderLevels.RetrieveOrderLevel(Inventory.Months[request.PeriodNo], logicalWarehouse);

            if (inventoryOrderLevel == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No order level with IN_LogicalID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            return inventoryOrderLevel.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOrderLevel&gt; Get(InventoryOrderLevelsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    i.OrderLevels.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            return Inventory.OrderLevels.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOrderLevel Patch(InventoryOrderLevelPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    i.OrderLevels.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.Warehouse.LogicalWarehouse logicalWarehouse = manager.PhysicalWarehouseCollection.FindLogicalWarehouse(request.LogicalWarehouseID);

            if (logicalWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse with IN_LogicalID '{0}' was found.", request.LogicalWarehouseID));

            JiwaFinancials.Jiwa.JiwaInventory.OrderLevel inventoryOrderLevel = Inventory.OrderLevels.RetrieveOrderLevel(Inventory.Months[request.PeriodNo], logicalWarehouse);

            if (inventoryOrderLevel == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No order level with IN_LogicalID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            inventoryOrderLevel.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
                Inventory.OrderLevels.Read();
            }

            inventoryOrderLevel = Inventory.OrderLevels.RetrieveOrderLevel(Inventory.Months[request.PeriodNo], logicalWarehouse);

            if (inventoryOrderLevel == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No order level with IN_LogicalID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            return inventoryOrderLevel.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Other Descriptions"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory other description with the InventoryID or OtherDescriptionID provided was found")]
    public class InventoryOtherDescriptionGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription&gt;
    {
        public string InventoryID { get; set; }
        public string OtherDescriptionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory other descriptions with the InventoryID provided was found")]
    public class InventoryOtherDescriptionsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory other description with the InventoryID provided was found")]
    public class InventoryOtherDescriptionPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string OtherDescriptionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory other description with the InventoryID or OtherDescriptionID provided was found")]
    public class InventoryOtherDescriptionPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription&gt;
    {
        public string InventoryID { get; set; }
        public override string OtherDescriptionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory other description with the InventoryID or OtherDescriptionID provided was found")]
    public class InventoryOtherDescriptionDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription
    {
        public string InventoryID { get; set; }
        public override string OtherDescriptionID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryOtherDescriptionServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription Get(InventoryOtherDescriptionGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.OtherDescription inventoryOtherDescription = Inventory.OtherDescriptions.GetItem("RecID", request.OtherDescriptionID);

            if (inventoryOtherDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory other description with RecID '{0}' was found.", request.OtherDescriptionID));

            return inventoryOtherDescription.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription&gt; Get(InventoryOtherDescriptionsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.OtherDescriptions.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription Post(InventoryOtherDescriptionPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory other description. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var inventoryOtherDescriptions = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription&gt;();
            inventoryOtherDescriptions.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.OtherDescription&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.OtherDescriptions.Added -= addedHandler; // remove handler						
            };

            Inventory.OtherDescriptions.Added += addedHandler;
            Inventory.OtherDescriptions.DTO_Deserialise(inventoryOtherDescriptions);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.OtherDescription inventoryOtherDescription = Inventory.OtherDescriptions.GetItem("RecID", recID);

            if (inventoryOtherDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory other description with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventoryOtherDescription.RecID));

            return inventoryOtherDescription.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryOtherDescription Patch(InventoryOtherDescriptionPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.OtherDescription inventoryOtherDescription = Inventory.OtherDescriptions.GetItem("RecID", request.OtherDescriptionID);

            if (inventoryOtherDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory other description with RecID '{0}' was found.", request.OtherDescriptionID));

            inventoryOtherDescription.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryOtherDescription = Inventory.OtherDescriptions.GetItem("RecID", request.OtherDescriptionID);

            if (inventoryOtherDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory other description with RecID '{0}' was found.", request.OtherDescriptionID));

            return inventoryOtherDescription.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryOtherDescriptionDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.OtherDescription inventoryOtherDescription = Inventory.OtherDescriptions.GetItem("RecID", request.OtherDescriptionID);

            if (inventoryOtherDescription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory other description with RecID '{0}' was found.", request.OtherDescriptionID));

            Inventory.OtherDescriptions.Remove(inventoryOtherDescription);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Prices"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryPriceGETRequest : IReturn&lt;InventoryPriceGETResponse&gt;
    {
        public string InventoryID { get; set; }
        public string DebtorID { get; set; }
        public string IN_LogicalID { get; set; }
        public System.DateTime Date { get; set; }
        public decimal Quantity { get; set; }
    }
    #endregion

    #region "Responses"
	[Serializable()]
    public class InventoryPriceGETResponse
    {
        virtual public Nullable&lt;decimal&gt; Price { get; set; }
        virtual public Nullable&lt;bool&gt; IncludesTax { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class InventoryPriceServices : Service
    {
        [Authenticate]
        public InventoryPriceGETResponse Get(InventoryPriceGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            // Need to find the price scheme ID associated with the debtor						
            DB_Main debtor = Db.Single&lt;DB_Main&gt;(x =&gt; x.DebtorID == request.DebtorID);

            JiwaFinancials.Jiwa.JiwaPriceSchemes.PriceScheme priceScheme = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPriceSchemes.PriceScheme&gt;(manager, this, debtor.PriceSchemeID,
                (o, m, s) =&gt;
                {
                    o.Read(debtor.PriceSchemeID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(debtor.PriceSchemeID, o);
                    }
                });

            decimal price = 0;
            bool priceIsIncTax = false;

            priceScheme.GetPrice(JiwaFinancials.Jiwa.JiwaPriceSchemes.PriceScheme.PriceSchemePriceChangeOrigin.e_PriceSchemePriceChangeOriginSalesOrder, null, request.InventoryID, request.DebtorID, request.Date, request.IN_LogicalID, request.Quantity, ref price, ref priceIsIncTax);

            return new InventoryPriceGETResponse() { Price = price, IncludesTax = priceIsIncTax };
        }
    }
    #endregion
    #endregion

    #region "Debtor Specific"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor specific price with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryDebtorSpecificPriceGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice&gt;
    {
        public string InventoryID { get; set; }
        public string DebtorSpecificPriceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor specific prices with the InventoryID provided was found")]
    public class InventoryDebtorSpecificPricesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory item with the InventoryID provided was found")]
    public class InventoryDebtorSpecificPricePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice&gt;
    {
        public string InventoryID { get; set; }
        public override string DebtorID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor specific price with the InventoryID or DebtorSpecificPriceID provided was found")]
    public class InventoryDebtorSpecificPricePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice&gt;
    {
        public string InventoryID { get; set; }
        public override string DebtorSpecificPriceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor specific price with the InventoryID or InventoryID DebtorSpecificPriceID was found")]
    public class InventoryDebtorSpecificPriceDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice
    {
        public string InventoryID { get; set; }
        public override string DebtorSpecificPriceID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryDebtorSpecificPriceServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice Get(InventoryDebtorSpecificPriceGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorSpecificInventorySpecific inventoryDebtorSpecificPrice = Inventory.DebtorPrices[request.DebtorSpecificPriceID];

            if (inventoryDebtorSpecificPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor specific price with DebtorSpecificPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorSpecificPriceID, request.InventoryID));

            return inventoryDebtorSpecificPrice.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice&gt; Get(InventoryDebtorSpecificPricesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.DebtorPrices.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice Post(InventoryDebtorSpecificPricePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory supplier. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var debtorSpecificPrices = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice&gt;();
            debtorSpecificPrices.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.DebtorSpecificInventorySpecific&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.DebtorPrices.Added -= addedHandler; // remove handler						
            };

            Inventory.DebtorPrices.Added += addedHandler;
            Inventory.DebtorPrices.DTO_Deserialise(debtorSpecificPrices);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.DebtorSpecificInventorySpecific debtorSpecificPrice = Inventory.DebtorPrices.GetItem("RecID", recID);

            if (debtorSpecificPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor specific price with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorSpecificPrice.RecID));

            return debtorSpecificPrice.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPrice Patch(InventoryDebtorSpecificPricePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorSpecificInventorySpecific inventoryDebtorSpecificPrice = Inventory.DebtorPrices[request.DebtorSpecificPriceID];

            if (inventoryDebtorSpecificPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor specific price with DebtorSpecificPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorSpecificPriceID, request.InventoryID));

            inventoryDebtorSpecificPrice.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryDebtorSpecificPrice = Inventory.DebtorPrices[request.DebtorSpecificPriceID];

            if (inventoryDebtorSpecificPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor specific price with DebtorSpecificPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorSpecificPriceID, request.InventoryID));

            return inventoryDebtorSpecificPrice.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryDebtorSpecificPriceDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorSpecificInventorySpecific inventoryDebtorSpecificPrice = Inventory.DebtorPrices[request.DebtorSpecificPriceID];

            if (inventoryDebtorSpecificPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor specific price with DebtorSpecificPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorSpecificPriceID, request.InventoryID));

            Inventory.DebtorPrices.Remove(inventoryDebtorSpecificPrice);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }
        }
    }
    #endregion
    #endregion

    #region "Debtor Classification"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor classification price with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryDebtorClassificationPriceGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice&gt;
    {
        public string InventoryID { get; set; }
        public string DebtorClassificationPriceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor classification prices with the InventoryID provided was found")]
    public class InventoryDebtorClassificationPricesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory item with the InventoryID provided was found")]
    public class InventoryDebtorClassificationPricePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice&gt;
    {
        public string InventoryID { get; set; }
        public override string DebtorClassificationPriceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor classification price with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryDebtorClassificationPricePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice&gt;
    {
        public string InventoryID { get; set; }
        public override string DebtorClassificationPriceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No DebtorClassificationPrice with the DebtorClassificationPriceID or InventoryID provided was found")]
    public class InventoryDebtorClassificationPriceDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice
    {
        public string InventoryID { get; set; }
        public override string DebtorClassificationPriceID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryDebtorClassificationPriceServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice Get(InventoryDebtorClassificationPriceGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorClassificationInventorySpecific inventoryDebtorClassificationPrice = Inventory.DebtorClassPrices[request.DebtorClassificationPriceID];

            if (inventoryDebtorClassificationPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor classification price with DebtorClassificationPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorClassificationPriceID, request.InventoryID));

            return inventoryDebtorClassificationPrice.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice&gt; Get(InventoryDebtorClassificationPricesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.DebtorClassPrices.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice Post(InventoryDebtorClassificationPricePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory supplier. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var debtorClassificationPrices = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice&gt;();
            debtorClassificationPrices.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.DebtorClassificationInventorySpecific&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.DebtorClassPrices.Added -= addedHandler; // remove handler						
            };

            Inventory.DebtorClassPrices.Added += addedHandler;
            Inventory.DebtorClassPrices.DTO_Deserialise(debtorClassificationPrices);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.DebtorClassificationInventorySpecific debtorClassificationPrice = Inventory.DebtorClassPrices.GetItem("RecID", recID);

            if (debtorClassificationPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor classification price with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorClassificationPrice.RecID));

            return debtorClassificationPrice.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorClassificationPrice Patch(InventoryDebtorClassificationPricePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorClassificationInventorySpecific inventoryDebtorClassificationPrice = Inventory.DebtorClassPrices[request.DebtorClassificationPriceID];

            if (inventoryDebtorClassificationPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor classification price with DebtorClassificationPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorClassificationPriceID, request.InventoryID));

            inventoryDebtorClassificationPrice.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryDebtorClassificationPrice = Inventory.DebtorClassPrices[request.DebtorClassificationPriceID];

            if (inventoryDebtorClassificationPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor classification price with DebtorClassificationPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorClassificationPriceID, request.InventoryID));

            return inventoryDebtorClassificationPrice.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryDebtorClassificationPriceDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorClassificationInventorySpecific inventoryDebtorClassificationPrice = Inventory.DebtorClassPrices[request.DebtorClassificationPriceID];

            if (inventoryDebtorClassificationPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor classification price with DebtorClassificationPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorClassificationPriceID, request.InventoryID));

            Inventory.DebtorClassPrices.Remove(inventoryDebtorClassificationPrice);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }
        }
    }
    #endregion
    #endregion

    #region "Debtor Price Group"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor price group price with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryDebtorPriceGroupPriceGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific&gt;
    {
        public string InventoryID { get; set; }
        public string DebtorPriceGroupInventorySpecificID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor price group prices with the InventoryID provided was found")]
    public class InventoryDebtorPriceGroupPricesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory item with the InventoryID provided was found")]
    public class InventoryDebtorPriceGroupPricePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific&gt;
    {
        public string InventoryID { get; set; }
        public override string DebtorPriceGroupInventorySpecificID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor price group price with the InventoryID or DebtorPriceGroupInventorySpecificID provided was found")]
    public class InventoryDebtorPriceGroupPricePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific&gt;
    {
        public string InventoryID { get; set; }
        public override string DebtorPriceGroupInventorySpecificID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No debtor price group price with the InventoryID or DebtorPriceGroupInventorySpecificID provided was found")]
    public class InventoryDebtorPriceGroupPriceDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific
    {
        public string InventoryID { get; set; }
        public override string DebtorPriceGroupInventorySpecificID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryDebtorPriceGroupPriceServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific Get(InventoryDebtorPriceGroupPriceGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorPriceGroupInventorySpecific inventoryDebtorPriceGroupPrice = Inventory.DebtorPriceGroupInventorySpecificPrices[request.DebtorPriceGroupInventorySpecificID];

            if (inventoryDebtorPriceGroupPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor price group price with DebtorPriceGroupPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorPriceGroupInventorySpecificID, request.InventoryID));

            return inventoryDebtorPriceGroupPrice.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific&gt; Get(InventoryDebtorPriceGroupPricesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.DebtorPriceGroupInventorySpecificPrices.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific Post(InventoryDebtorPriceGroupPricePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory supplier. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var debtorPriceGroupPrices = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific&gt;();
            debtorPriceGroupPrices.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.DebtorPriceGroupInventorySpecific&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.DebtorPriceGroupInventorySpecificPrices.Added -= addedHandler; // remove handler						
            };

            Inventory.DebtorPriceGroupInventorySpecificPrices.Added += addedHandler;
            Inventory.DebtorPriceGroupInventorySpecificPrices.DTO_Deserialise(debtorPriceGroupPrices);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.DebtorPriceGroupInventorySpecific debtorPriceGroupPrice = Inventory.DebtorPriceGroupInventorySpecificPrices.GetItem("RecID", recID);

            if (debtorPriceGroupPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor price group price with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], debtorPriceGroupPrice.RecID));

            return debtorPriceGroupPrice.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryDebtorPriceGroupInventorySpecific Patch(InventoryDebtorPriceGroupPricePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorPriceGroupInventorySpecific inventoryDebtorPriceGroupPrice = Inventory.DebtorPriceGroupInventorySpecificPrices[request.DebtorPriceGroupInventorySpecificID];

            if (inventoryDebtorPriceGroupPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor price group price with DebtorPriceGroupPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorPriceGroupInventorySpecificID, request.InventoryID));

            inventoryDebtorPriceGroupPrice.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryDebtorPriceGroupPrice = Inventory.DebtorPriceGroupInventorySpecificPrices[request.DebtorPriceGroupInventorySpecificID];

            if (inventoryDebtorPriceGroupPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor price group price with DebtorPriceGroupPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorPriceGroupInventorySpecificID, request.InventoryID));

            return inventoryDebtorPriceGroupPrice.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryDebtorPriceGroupPriceDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.DebtorPriceGroupInventorySpecific inventoryDebtorPriceGroupPrice = Inventory.DebtorPriceGroupInventorySpecificPrices[request.DebtorPriceGroupInventorySpecificID];

            if (inventoryDebtorPriceGroupPrice == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No debtor price group price with DebtorPriceGroupPriceID '{0}' for inventory item with an InventoryID of {1} was found.", request.DebtorPriceGroupInventorySpecificID, request.InventoryID));

            Inventory.DebtorPriceGroupInventorySpecificPrices.Remove(inventoryDebtorPriceGroupPrice);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }
        }
    }
    #endregion
    #endregion

    #region "Selling Prices"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No selling price with the InventoryID provided was found")]
    public class InventorySellingPriceGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySellingPrices&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No selling price with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventorySellingPricePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySellingPrices, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySellingPrices&gt;
    {
        public string InventoryID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventorySellingPriceServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySellingPrices Get(InventorySellingPriceGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            return Inventory.SellingPrices.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySellingPrices Patch(InventorySellingPricePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            Inventory.SellingPrices.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            return Inventory.SellingPrices.DTO_Serialise();
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Pricing Groups"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory pricing group with the RecID provided was found")]
    public class InventoryPricingGroupGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup&gt;
    {
        public string PricingGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryPricingGroupsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class InventoryPricingGroupPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PricingGroupID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory pricing group with the RecID provided was found")]
    public class InventoryPricingGroupPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup&gt;
    {
        public override string PricingGroupID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory pricing group with the RecID provided was found")]
    public class InventoryPricingGroupDELETERequest
    {
        public string PricingGroupID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryPricingGroupServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup Get(InventoryPricingGroupGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaInventory.Configuration.PricingGroup.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaInventory.Configuration.PricingGroup.PricingGroup, JiwaInventory.Configuration.PricingGroup.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            JiwaInventory.Configuration.PricingGroup.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory pricing group with RecID '{0}' was found.", request.PricingGroupID));

            return pricingGroup.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup&gt; Get(InventoryPricingGroupsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaInventory.Configuration.PricingGroup.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaInventory.Configuration.PricingGroup.PricingGroup, JiwaInventory.Configuration.PricingGroup.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            return pricingGroups.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup Post(InventoryPricingGroupPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaInventory.Configuration.PricingGroup.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaInventory.Configuration.PricingGroup.PricingGroup, JiwaInventory.Configuration.PricingGroup.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            // Add the pricing group. Need to jump through a few hoops as we want to know the PricingGroupID so we can return that in the response header.	
            var dtoPricingGroups = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup&gt;();
            dtoPricingGroups.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.Configuration.PricingGroup.PricingGroup&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                pricingGroups.Added -= addedHandler; // remove handler						
            };

            pricingGroups.Added += addedHandler;
            pricingGroups.DTO_Deserialise(dtoPricingGroups);

            if (!Helper.Service.IsStateful(this))
            {
                pricingGroups.Save();
                pricingGroups.Read();
            }

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", recID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory pricing group with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], pricingGroup.RecID));

            return pricingGroup.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.PricingGroup.InventoryPricingGroup Patch(InventoryPricingGroupPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaInventory.Configuration.PricingGroup.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaInventory.Configuration.PricingGroup.PricingGroup, JiwaInventory.Configuration.PricingGroup.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory pricing group with RecID '{0}' was found.", request.PricingGroupID));

            pricingGroup.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                pricingGroups.Save();
                pricingGroups.Read();
            }

            pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory pricing group with RecID '{0}' was found.", request.PricingGroupID));

            return pricingGroup.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryPricingGroupDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaInventory.Configuration.PricingGroup.PricingGroupCollection pricingGroups = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaInventory.Configuration.PricingGroup.PricingGroup, JiwaInventory.Configuration.PricingGroup.PricingGroupCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroupCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                });

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroup pricingGroup = pricingGroups.GetItem("RecID", request.PricingGroupID);

            if (pricingGroup == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory pricing group with RecID '{0}' was found.", request.PricingGroupID));

            pricingGroups.Remove(pricingGroup);

            if (!Helper.Service.IsStateful(this))
            {
                pricingGroups.Save();
                pricingGroups.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Product Availabilities"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No product availability with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryProductAvailabilityGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability&gt;
    {
        public string InventoryID { get; set; }
        public string LogicalWarehouseID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No product availabilities with the InventoryID provided was found")]
    public class InventoryProductAvailabilitiesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No product availability with the InventoryID or LogicalWarehouseID provided was found")]
    public class InventoryProductAvailabilityPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability&gt;
    {
        public string InventoryID { get; set; }
        public override string LogicalWarehouseID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryProductAvailabilityServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability Get(InventoryProductAvailabilityGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability dtoInventoryProductAvailability = Inventory.ProductAvailabilities.DTO_Serialise().FirstOrDefault(x =&gt; x.LogicalWarehouseID == request.LogicalWarehouseID);

            if (dtoInventoryProductAvailability == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No product availability with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            JiwaFinancials.Jiwa.JiwaInventory.ProductAvailability inventoryProductAvailability = Inventory.ProductAvailabilities[dtoInventoryProductAvailability.ProductAvailabilityID];

            if (inventoryProductAvailability == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No product availability with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            return inventoryProductAvailability.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability&gt; Get(InventoryProductAvailabilitiesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.ProductAvailabilities.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability Patch(InventoryProductAvailabilityPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryProductAvailability dtoInventoryProductAvailability = Inventory.ProductAvailabilities.DTO_Serialise().FirstOrDefault(x =&gt; x.LogicalWarehouseID == request.LogicalWarehouseID);

            if (dtoInventoryProductAvailability == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No product availability with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            JiwaFinancials.Jiwa.JiwaInventory.ProductAvailability inventoryProductAvailability = Inventory.ProductAvailabilities[dtoInventoryProductAvailability.ProductAvailabilityID];

            if (inventoryProductAvailability == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No product availability with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            inventoryProductAvailability.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            dtoInventoryProductAvailability = Inventory.ProductAvailabilities.DTO_Serialise().FirstOrDefault(x =&gt; x.LogicalWarehouseID == request.LogicalWarehouseID);

            if (dtoInventoryProductAvailability == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No product availability with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            inventoryProductAvailability = Inventory.ProductAvailabilities[dtoInventoryProductAvailability.ProductAvailabilityID];

            if (inventoryProductAvailability == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No product availability with LogicalWarehouseID '{0}' for inventory item with an InventoryID of {1} was found.", request.LogicalWarehouseID, request.InventoryID));

            return inventoryProductAvailability.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Regions"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory region with the InventoryID or RegionName provided was found")]
    public class InventoryRegionGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryRegion&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory region with the InventoryID provided was found")]
    public class InventoryRegionsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryRegion&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory region with the InventoryID or RegionName provided was found")]
    public class InventoryRegionPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryRegion, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryRegion&gt;
    {
        public string InventoryID { get; set; }
        public override string RegionName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventoryRegionServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryRegion Get(InventoryRegionGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with name '{0}' was found.", request.RegionName));

            return inventoryRegion.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryRegion&gt; Get(InventoryRegionsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.Regions.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryRegion Patch(InventoryRegionPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with name '{0}' was found.", request.RegionName));

            inventoryRegion.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with name '{0}' was found.", request.RegionName));

            return inventoryRegion.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Suppliers"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory supplier with the InventoryID, RegionName or SupplierID provided was found")]
    public class InventorySupplierGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public string SupplierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory suppliers with the InventoryID or RegionName provided was found")]
    public class InventorySuppliersGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier&gt;&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory supplier with the InventoryID or RegionName provided was found")]
    public class InventorySupplierPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SupplierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory supplier with the InventoryID, RegionName or SupplierID provided was found")]
    public class InventorySupplierPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public override string SupplierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory supplier with the InventoryID, RegionName or SupplierID provided was found")]
    public class InventorySupplierDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public override string SupplierID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class InventorySupplierServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier Get(InventorySupplierGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            return inventorySupplier.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier&gt; Get(InventorySuppliersGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            return inventoryRegion.Suppliers.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier Post(InventorySupplierPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            // Add the inventory supplier. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var inventorySuppliers = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier&gt;();
            inventorySuppliers.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.Supplier&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                inventoryRegion.Suppliers.Added -= addedHandler; // remove handler						
            };

            inventoryRegion.Suppliers.Added += addedHandler;
            inventoryRegion.Suppliers.DTO_Deserialise(inventorySuppliers);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", recID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventorySupplier.RecID));

            return inventorySupplier.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplier Patch(InventorySupplierPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            inventorySupplier.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            return inventorySupplier.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventorySupplierDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            inventoryRegion.Suppliers.Remove(inventorySupplier);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Supplier Warehouses"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No supplier warehouse with the InventoryID, SupplierID, or SupplierWarehouseID provided was found")]
    public class InventorySupplierWarehouseGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public string SupplierID { get; set; }
        public string SupplierWarehouseID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No supplier warehouse with the InventoryID or SupplierID provided was found")]
    public class InventorySupplierWarehousesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse&gt;&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public string SupplierID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No description with the InventoryID, SupplierID or SupplierWarehouseID provided was found")]
    public class InventorySupplierWarehousePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public string SupplierID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SupplierWarehouseID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No supplier warehouse with the InventoryID, SupplierID or SupplierWarehouseID provided was found")]
    public class InventorySupplierWarehousePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse&gt;
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public string SupplierID { get; set; }
        public override string SupplierWarehouseID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No supplier warehouse with the InventoryID, SupplierID or SupplierWarehouseID provided was found")]
    public class InventorySupplierWarehouseDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse
    {
        public string InventoryID { get; set; }
        public string RegionName { get; set; }
        public string SupplierID { get; set; }
        public override string SupplierWarehouseID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class InventorySupplierWarehouseServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse Get(InventorySupplierWarehouseGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            JiwaFinancials.Jiwa.JiwaInventory.SupplierWarehouse inventorySupplierWarehouse = inventorySupplier.SupplierWarehouses.GetItem("RecID", request.SupplierWarehouseID);

            if (inventorySupplierWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier warehouse with RecID '{0}' was found.", request.SupplierWarehouseID));

            return inventorySupplierWarehouse.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse&gt; Get(InventorySupplierWarehousesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            return inventorySupplier.SupplierWarehouses.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse Post(InventorySupplierWarehousePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            // Add the inventory supplier warehouse.
            var inventorySupplierWarehoues = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse&gt;();
            inventorySupplierWarehoues.Add(request);

            inventorySupplier.SupplierWarehouses.DTO_Deserialise(inventorySupplierWarehoues);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            JiwaFinancials.Jiwa.JiwaInventory.SupplierWarehouse inventorySupplierWarehouse = inventorySupplier.SupplierWarehouses.GetItem("RecID", request.SupplierWarehouseID);

            if (inventorySupplierWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier warehouse with RecID '{0}' was found.", request.SupplierWarehouseID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventorySupplierWarehouse.RecID));

            return inventorySupplierWarehouse.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventorySupplierWarehouse Patch(InventorySupplierWarehousePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            JiwaFinancials.Jiwa.JiwaInventory.SupplierWarehouse inventorySupplierWarehouse = inventorySupplier.SupplierWarehouses.GetItem("RecID", request.SupplierWarehouseID);

            if (inventorySupplierWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier warehouse with RecID '{0}' was found.", request.SupplierWarehouseID));

            inventorySupplierWarehouse.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            inventorySupplierWarehouse = inventorySupplier.SupplierWarehouses.GetItem("RecID", request.SupplierWarehouseID);

            if (inventorySupplierWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier warehouse with RecID '{0}' was found.", request.SupplierWarehouseID));

            return inventorySupplierWarehouse.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventorySupplierWarehouseDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Region inventoryRegion = Inventory.Regions.GetItem("Name", request.RegionName);

            if (inventoryRegion == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory region with Name '{0}' was found.", request.RegionName));

            JiwaFinancials.Jiwa.JiwaInventory.Supplier inventorySupplier = inventoryRegion.Suppliers.GetItem("RecID", request.SupplierID);

            if (inventorySupplier == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier with RecID '{0}' was found.", request.SupplierID));

            JiwaFinancials.Jiwa.JiwaInventory.SupplierWarehouse inventorySupplierWarehouse = inventorySupplier.SupplierWarehouses.GetItem("RecID", request.SupplierWarehouseID);

            if (inventorySupplierWarehouse == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory supplier warehouse with RecID '{0}' was found.", request.SupplierWarehouseID));

            inventorySupplier.SupplierWarehouses.Remove(inventorySupplierWarehouse);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion
    #endregion

    #region "Unit Of Measures"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory unit of measure with the InventoryID or UnitOfMeasureID provided was found")]
    public class InventoryUnitOfMeasureGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure&gt;
    {
        public string InventoryID { get; set; }
        public string UnitOfMeasureID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory unit of measure with the InventoryID provided was found")]
    public class InventoryUnitOfMeasuresGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory unit of measure with the InventoryID or UnitOfMeasureID provided was found")]
    public class InventoryUnitOfMeasurePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string UnitOfMeasureID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory unit of measure with the InventoryID or UnitOfMeasureID provided was found")]
    public class InventoryUnitOfMeasurePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure&gt;
    {
        public string InventoryID { get; set; }
        public override string UnitOfMeasureID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory unit of measure with the InventoryID or UnitOfMeasureID provided was found")]
    public class InventoryUnitOfMeasureDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure
    {
        public string InventoryID { get; set; }
        public override string UnitOfMeasureID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class InventoryUnitOfMeasureServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure Get(InventoryUnitOfMeasureGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.UnitOfMeasure inventoryUnitOfMeasure = Inventory.UnitOfMeasures.GetItem("RecID", request.UnitOfMeasureID);

            if (inventoryUnitOfMeasure == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory unit of measure with RecID '{0}' was found.", request.UnitOfMeasureID));

            return inventoryUnitOfMeasure.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure&gt; Get(InventoryUnitOfMeasuresGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.UnitOfMeasures.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure Post(InventoryUnitOfMeasurePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory attribute group. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var inventoryUnitOfMeasures = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure&gt;();
            inventoryUnitOfMeasures.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.UnitOfMeasure&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.UnitOfMeasures.Added -= addedHandler; // remove handler						
            };

            Inventory.UnitOfMeasures.Added += addedHandler;
            Inventory.UnitOfMeasures.DTO_Deserialise(inventoryUnitOfMeasures);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.UnitOfMeasure inventoryUnitOfMeasure = Inventory.UnitOfMeasures.GetItem("RecID", recID);

            if (inventoryUnitOfMeasure == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory unit of measure with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventoryUnitOfMeasure.RecID));

            return inventoryUnitOfMeasure.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUnitOfMeasure Patch(InventoryUnitOfMeasurePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.UnitOfMeasure inventoryUnitOfMeasure = Inventory.UnitOfMeasures.GetItem("RecID", request.UnitOfMeasureID);

            if (inventoryUnitOfMeasure == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory unit of measure with RecID '{0}' was found.", request.UnitOfMeasureID));

            inventoryUnitOfMeasure.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryUnitOfMeasure = Inventory.UnitOfMeasures.GetItem("RecID", request.UnitOfMeasureID);

            if (inventoryUnitOfMeasure == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory unit of measure with RecID '{0}' was found.", request.UnitOfMeasureID));

            return inventoryUnitOfMeasure.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryUnitOfMeasureDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.UnitOfMeasure inventoryUnitOfMeasure = Inventory.UnitOfMeasures.GetItem("RecID", request.UnitOfMeasureID);

            if (inventoryUnitOfMeasure == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory unit of measure with RecID '{0}' was found.", request.UnitOfMeasureID));

            Inventory.UnitOfMeasures.Remove(inventoryUnitOfMeasure);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Up Sells"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory up sell with the InventoryID or RecID provided was found")]
    public class InventoryUpSellGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell&gt;
    {
        public string InventoryID { get; set; }
        public string UpSellID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory up sell with the InventoryID or RecID provided was found")]
    public class InventoryUpSellsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell&gt;&gt;
    {
        public string InventoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory up sell with the InventoryID or RecID provided was found")]
    public class InventoryUpSellPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell&gt;
    {
        public string InventoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string UpSellID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory up sell with the InventoryID or RecID provided was found")]
    public class InventoryUpSellPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell&gt;
    {
        public string InventoryID { get; set; }
        public override string UpSellID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No inventory up sell with the InventoryID or RecID provided was found")]
    public class InventoryUpSellDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell
    {
        public string InventoryID { get; set; }
        public override string UpSellID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class InventoryUpSellServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell Get(InventoryUpSellGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Upsell inventoryUpSell = Inventory.UpSells.GetItem("RecID", request.UpSellID);

            if (inventoryUpSell == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory up sell with RecID '{0}' was found.", request.UpSellID));

            return inventoryUpSell.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell&gt; Get(InventoryUpSellsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });
            return Inventory.UpSells.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell Post(InventoryUpSellPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            // Add the inventory up sell. Need to jump through a few hoops as we want to know the RecID so we can return that in the response header.	
            var inventoryUpSells = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell&gt;();
            inventoryUpSells.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaInventory.Upsell&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Inventory.UpSells.Added -= addedHandler; // remove handler						
            };

            Inventory.UpSells.Added += addedHandler;
            Inventory.UpSells.DTO_Deserialise(inventoryUpSells);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            JiwaFinancials.Jiwa.JiwaInventory.Upsell inventoryUpSell = Inventory.UpSells.GetItem("RecID", recID);

            if (inventoryUpSell == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory up sell with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], inventoryUpSell.RecID));

            return inventoryUpSell.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.InventoryUpSell Patch(InventoryUpSellPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Upsell inventoryUpSell = Inventory.UpSells.GetItem("RecID", request.UpSellID);

            if (inventoryUpSell == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory up sell with RecID '{0}' was found.", request.UpSellID));

            inventoryUpSell.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
                Inventory.Read(Inventory.InventoryID);
            }

            inventoryUpSell = Inventory.UpSells.GetItem("RecID", request.UpSellID);

            if (inventoryUpSell == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory up sell with RecID '{0}' was found.", request.UpSellID));

            return inventoryUpSell.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(InventoryUpSellDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Inventory Inventory = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaInventory.Inventory&gt;(manager, this, request.InventoryID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InventoryID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InventoryID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaInventory.Upsell inventoryUpSell = Inventory.UpSells.GetItem("RecID", request.UpSellID);

            if (inventoryUpSell == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No inventory up sell with RecID '{0}' was found.", request.UpSellID));

            Inventory.UpSells.Remove(inventoryUpSell);

            if (!Helper.Service.IsStateful(this))
            {
                Inventory.Save();
            }
        }
    }
    #endregion
    #endregion

    #endregion

    #region "Journal Set"
    #region "{Main}"
    #region"Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet&gt;
    {
        public string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class JournalSetPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet&gt;
    {
        public override string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetDELETERequest
    {
        public string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet&gt;
    {
        public string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetABANDONRequest
    {
        public string JournalSetID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class JournalSetServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet Get(JournalSetGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });
            return journalSet.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSet Post(JournalSetPOSTRequest JournalSet)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(null);
            journalSet.DTO_Deserialise(JournalSet);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(journalSet.RecID, journalSet);
            else
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }

                journalSet.Read(journalSet.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], journalSet.RecID));
            return journalSet.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.JournalSets.JournalSet Patch(JournalSetPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            journalSet.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }
                journalSet.Read(request.JournalSetID);
            }

            return journalSet.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(JournalSetDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet JournalSet = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(null);
            JournalSet.Read(request.JournalSetID);

            JournalSet.Delete();
        }

        [Authenticate]
        public JiwaServiceModel.JournalSets.JournalSet Get(JournalSetSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.JournalSetID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful journal set exists with JournalSetID '{0}'", request.JournalSetID));
            }

            var journalSet = (JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet)objectDictionaryValue;

            bool oldIsLocalJournal = journalSet.IsLocalJournal;
            try
            {
                journalSet.IsLocalJournal = true;
                journalSet.Save();
            }
            finally
            {
                journalSet.IsLocalJournal = oldIsLocalJournal;
            }
            journalSet.Read(journalSet.RecID);

            return journalSet.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(JournalSetABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.JournalSetID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful journal set exists with JournalSetID '{0}'", request.JournalSetID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.JournalSetID);
        }
    }
    #endregion
    #endregion

    #region "Document Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set document type with the DocumentTypeID provided was found")]
    public class JournalSetDocumentTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class JournalSetDocumentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class JournalSetDocumentTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set document type with the DocumentTypeID provided was found")]
    public class JournalSetDocumentTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set document type with the DocumentTypeID provided was found")]
    public class JournalSetDocumentTypeDELETERequest
    {
        public string DocumentTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class JournalSetDocumentTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Get(JournalSetDocumentTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
					d.DocumentTableNames.Add("GL_Documents");
                    d.Read();
                });

            JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt; Get(JournalSetDocumentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
					d.DocumentTableNames.Add("GL_Documents");					
                    d.Read();
                });

            return documentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Post(JournalSetDocumentTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
					d.DocumentTableNames.Add("GL_Documents");					
                    d.Read();
                });

            // Add the document type. Need to jump through a few hoops as we want to know the DocumentTypeID so we can return that in the response header.	
            var dtoDocumentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;();
            dtoDocumentTypes.Add(request);
            string documentTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaDocumentTypes.DocumentType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentTypeID = item.RecID;
                documentTypes.Added -= addedHandler; // remove handler						
            };

            documentTypes.Added += addedHandler;
            documentTypes.DTO_Deserialise(dtoDocumentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", documentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", documentTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], documentType.RecID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Patch(JournalSetDocumentTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
					d.DocumentTableNames.Add("GL_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(JournalSetDocumentTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
					d.DocumentTableNames.Add("GL_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentTypes.Remove(documentType);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Documents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set document with the JournalSetID or DocumentID provided was found")]
    public class JournalSetDocumentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string JournalSetID { get; set; }
        public string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetDocumentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;&gt;
    {
        public string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetDocumentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string JournalSetID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetDocumentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string JournalSetID { get; set; }
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set with the JournalSetID provided was found")]
    public class JournalSetDocumentDELETERequest
    {
        public string JournalSetID { get; set; }
        public string DocumentID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class JournalSetDocumentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Get(JournalSetDocumentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = journalSet.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt; Get(JournalSetDocumentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet JournalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            return JournalSet.Documents.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Post(JournalSetDocumentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet JournalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            // Add the document. Need to jump through a few hoops as we want to know the DocumentID so we can return that in the response header.	
            var documents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;();
            documents.Add(request);
            string documentID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Documents.Document&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentID = item.RecID;
                JournalSet.Documents.Added -= addedHandler; // remove handler						
            };

            JournalSet.Documents.Added += addedHandler;
            JournalSet.Documents.DTO_Deserialise(documents);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = JournalSet.IsLocalJournal;
                try
                {
                    JournalSet.IsLocalJournal = true;
                    JournalSet.Save();
                }
                finally
                {
                    JournalSet.IsLocalJournal = oldIsLocalJournal;
                }
                JournalSet.Read(JournalSet.RecID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = JournalSet.Documents.GetItem("RecID", documentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", documentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], document.RecID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Patch(JournalSetDocumentPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet JournalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaApplication.Documents.Document document = JournalSet.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set document with DocumentID '{0}' was found.", request.DocumentID));

            document.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = JournalSet.IsLocalJournal;
                try
                {
                    JournalSet.IsLocalJournal = true;
                    JournalSet.Save();
                }
                finally
                {
                    JournalSet.IsLocalJournal = oldIsLocalJournal;
                }
                JournalSet.Read(JournalSet.RecID);
            }

            document = JournalSet.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(JournalSetDocumentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet JournalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = JournalSet.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set document with DocumentID '{0}' was found.", request.DocumentID));

            JournalSet.Documents.Remove(document);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = JournalSet.IsLocalJournal;
                try
                {
                    JournalSet.IsLocalJournal = true;
                    JournalSet.Save();
                }
                finally
                {
                    JournalSet.IsLocalJournal = oldIsLocalJournal;
                }
                JournalSet.Read(JournalSet.RecID);
            }
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the JournalSetID or JournalSetLineID provided was found")]
    public class JournalSetLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine&gt;
    {
        public string JournalSetID { get; set; }
        public string JournalSetLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the JournalSetID provided was found")]
    public class JournalSetLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine&gt;&gt;
    {
        public string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the JournalSetID or JournalSetLineID provided was found")]
    public class JournalSetLinePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine&gt;
    {
        public string JournalSetID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string JournalSetLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the JournalSetID or JournalSetLineID provided was found")]
    public class JournalSetLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine&gt;
    {
        public string JournalSetID { get; set; }
        public override string JournalSetLineID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the JournalSetID or JournalSetLineID provided was found")]
    public class JournalSetLineDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine
    {
        public string JournalSetID { get; set; }
        public override string JournalSetLineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class JournalSetLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine Get(JournalSetLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaFinancials.Jiwa.JiwaJournalSets.Line Line = journalSet.Lines.GetItem("RecID", request.JournalSetLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with JournalSetLineID '{0}' was found.", request.JournalSetLineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine&gt; Get(JournalSetLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });
            return journalSet.Lines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine Post(JournalSetLinePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            var Lines = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine&gt;();
            Lines.Add(request);

            journalSet.Lines.DTO_Deserialise(Lines);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }
                journalSet.Read(journalSet.RecID);
            }

            JiwaFinancials.Jiwa.JiwaJournalSets.Line Line = journalSet.Lines.GetItem("RecID", request.JournalSetLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with JournalSetLineID '{0}' was found.", request.JournalSetLineID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Line.RecID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.JournalSets.JournalSetLine Patch(JournalSetLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaFinancials.Jiwa.JiwaJournalSets.Line Line = journalSet.Lines.GetItem("RecID", request.JournalSetLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with JournalSetLineID '{0}' was found.", request.JournalSetLineID));

            Line.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }
                journalSet.Read(journalSet.RecID);
            }

            Line = journalSet.Lines.GetItem("RecID", request.JournalSetLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with JournalSetLineID '{0}' was found.", request.JournalSetLineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(JournalSetLineDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (p, m, s) =&gt;
                {
                    p.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(p.RecID, p);
                    }
                });

            JiwaFinancials.Jiwa.JiwaJournalSets.Line Line = journalSet.Lines.GetItem("RecID", request.JournalSetLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with JournalSetLineID '{0}' was found.", request.JournalSetLineID));

            journalSet.Lines.Remove(Line);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }
            }
        }
    }
    #endregion
    #endregion

    #region "Note Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set note type with the NoteTypeID provided was found")]
    public class JournalSetNoteTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class JournalSetNoteTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class JournalSetNoteTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set note type with the NoteTypeID provided was found")]
    public class JournalSetNoteTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No journal set note type with the NoteTypeID provided was found")]
    public class JournalSetNoteTypeDELETERequest
    {
        public string NoteTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class JournalSetNoteTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Get(JournalSetNoteTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
                    n.Read();
                });

            JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt; Get(JournalSetNoteTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
                    n.Read();
                });

            return noteTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Post(JournalSetNoteTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
                    n.Read();
                });

            // Add the note type. Need to jump through a few hoops as we want to know the NoteTypeID so we can return that in the response header.	
            var dtoNoteTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;();
            dtoNoteTypes.Add(request);
            string noteTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaNoteTypes.NoteType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteTypeID = item.RecID;
                noteTypes.Added -= addedHandler; // remove handler						
            };

            noteTypes.Added += addedHandler;
            noteTypes.DTO_Deserialise(dtoNoteTypes);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", noteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", noteTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], noteType.RecID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Patch(JournalSetNoteTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(JournalSetNoteTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteTypes.Remove(noteType);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Note with the JournalSetID or NoteID provided was found")]
    public class JournalSetNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string JournalSetID { get; set; }
        public string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the JournalSetID provided was found")]
    public class JournalSetNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;&gt;
    {
        public string JournalSetID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the JournalSetID provided was found")]
    public class JournalSetNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string JournalSetID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the JournalSetID provided was found")]
    public class JournalSetNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string JournalSetID { get; set; }
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the JournalSetID provided was found")]
    public class JournalSetNoteDELETERequest
    {
        public string JournalSetID { get; set; }
        public string NoteID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class JournalSetNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Get(JournalSetNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = journalSet.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt; Get(JournalSetNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            return journalSet.Notes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Post(JournalSetNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            // Add the note. Need to jump through a few hoops as we want to know the NoteID so we can return that in the response header.	
            var notes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;();
            notes.Add(request);
            string noteID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Notes.Note&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteID = item.RecID;
                journalSet.Notes.Added -= addedHandler; // remove handler						
            };

            journalSet.Notes.Added += addedHandler;
            journalSet.Notes.DTO_Deserialise(notes);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }
                journalSet.Read(journalSet.RecID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = journalSet.Notes.GetItem("RecID", noteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", noteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], note.RecID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Patch(JournalSetNotePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaApplication.Notes.Note note = journalSet.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set note with NoteID '{0}' was found.", request.NoteID));

            note.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }
                journalSet.Read(journalSet.RecID);
            }

            note = journalSet.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(JournalSetNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaJournalSets.JournalSet journalSet = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaJournalSets.JournalSet&gt;(manager, this, request.JournalSetID,
                (j, m, s) =&gt;
                {
                    j.Read(request.JournalSetID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = journalSet.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No journal set note with NoteID '{0}' was found.", request.NoteID));

            journalSet.Notes.Remove(note);

            if (!Helper.Service.IsStateful(this))
            {
                bool oldIsLocalJournal = journalSet.IsLocalJournal;
                try
                {
                    journalSet.IsLocalJournal = true;
                    journalSet.Save();
                }
                finally
                {
                    journalSet.IsLocalJournal = oldIsLocalJournal;
                }
                journalSet.Read(journalSet.RecID);
            }
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Keep Alive"
    #region "Requests"
	[Serializable()]
    [ApiResponse(204, "OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class KeepAliveGETRequest
    {
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class KeepAliveServices : Service
    {
        [Authenticate]
        public void Get(KeepAliveGETRequest request)
        {
        }
    }
    #endregion
    #endregion

    #region "Landed Cost"
    #region "BookIns"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No book in with the book in no. provided was found")]
    public class LandedCostBookInGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn&gt;
    {
        public string BookInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No book in with the book in no. provided was found")]
    public class LandedCostBookInPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn&gt;
    {
        public override string BookInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No book in with the BookInID provided was found")]
    public class LandedCostBookInSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn&gt;
    {
        public string BookInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No book in with the BookInID provided was found")]
    public class LandedCostBookInABANDONRequest
    {
        public string BookInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the shipment no. provided was found")]
    public class LandedCostBookInCREATEFromShipmentIDRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn&gt;
    {
        public string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the shipment no. provided was found")]
    public class LandedCostBookInCREATEFromShipmentNoRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn&gt;
    {
        public string ShipmentNo { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No book in with the book in no. provided was found")]
    public class LandedCostBookInACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn&gt;
    {
        public string BookInID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class LandedCostBookInServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn Get(LandedCostBookInGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn ShipmentBookIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(manager, this, request.BookInID,
                (g, m, s) =&gt;
                {
                    g.Read(request.BookInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            return ShipmentBookIn.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn Patch(LandedCostBookInPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn ShipmentBookIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(manager, this, request.BookInID,
                (g, m, s) =&gt;
                {
                    g.Read(request.BookInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            ShipmentBookIn.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                ShipmentBookIn.Save();
                ShipmentBookIn.Read(request.BookInID);
            }

            return ShipmentBookIn.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn Get(LandedCostBookInSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.BookInID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful book in with BookInID '{0}'", request.BookInID));
            }

            var ShipmentBookIn = (JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn)objectDictionaryValue;

            ShipmentBookIn.Save();
            ShipmentBookIn.Read(ShipmentBookIn.RecID);

            return ShipmentBookIn.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(LandedCostBookInABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.BookInID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful book in exists with BookInID '{0}'", request.BookInID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.BookInID);
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn Post(LandedCostBookInCREATEFromShipmentIDRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn shipmentBookIn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(null);
            shipmentBookIn.CreateNew(request.ShipmentID);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(shipmentBookIn.RecID, shipmentBookIn);
            else
            {
                shipmentBookIn.Save();
                shipmentBookIn.Read(shipmentBookIn.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], shipmentBookIn.RecID));

            return shipmentBookIn.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn Post(LandedCostBookInCREATEFromShipmentNoRequest request)
        {

            SH_Main firstShipment = Db.Single(Db.From&lt;SH_Main&gt;().Where(x =&gt; x.ShipmentNo == request.ShipmentNo).Take(1));

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn shipmentBookIn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(null);
            shipmentBookIn.CreateNew(firstShipment.ShipmentID);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(shipmentBookIn.RecID, shipmentBookIn);
            else
            {
                shipmentBookIn.Save();
                shipmentBookIn.Read(shipmentBookIn.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], shipmentBookIn.RecID));

            return shipmentBookIn.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookIn Post(LandedCostBookInACTIVATERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn shipmentBookIn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(null);
            shipmentBookIn.Read(request.BookInID);

            shipmentBookIn.ActivateRecord();
            shipmentBookIn.Read(request.BookInID);
            return shipmentBookIn.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the BookInID or LineID provided was found")]
    public class LandedCostBookInLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine&gt;
    {
        public string BookInID { get; set; }
        public string LineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the BookInID provided was found")]
    public class LandedCostBookInLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine&gt;&gt;
    {
        public string BookInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the BookInID or LineID provided was found")]
    public class LandedCostBookInLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine&gt;
    {
        public string BookInID { get; set; }
        public override string LineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the BookInID or LineID provided was found")]
    public class LandedCostBookInLineDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine
    {
        public string BookInID { get; set; }
        public override string LineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class LandedCostBookInLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine Get(LandedCostBookInLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn shipmentBookIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(manager, this, request.BookInID,
            (b, m, s) =&gt;
            {
                b.Read(request.BookInID);
                if (Helper.Service.IsStateful(s))
                {
                    m.ObjectDictionary.Add(b.RecID, b);
                }
            });

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.Line Line = shipmentBookIn.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine&gt; Get(LandedCostBookInLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn shipmentBookIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(manager, this, request.BookInID,
                (b, m, s) =&gt;
                {
                    b.Read(request.BookInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(b.RecID, b);
                    }
                });
            return shipmentBookIn.Lines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.BookIns.BookInLine Patch(LandedCostBookInLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn shipmentBookIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(manager, this, request.BookInID,
                (b, m, s) =&gt;
                {
                    b.Read(request.BookInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(b.RecID, b);
                    }
                });

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.Line Line = shipmentBookIn.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            Line.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                shipmentBookIn.Save();
                shipmentBookIn.Read(shipmentBookIn.RecID);
            }

            Line = shipmentBookIn.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(LandedCostBookInLineDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn shipmentBookIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(manager, this, request.BookInID,
                (b, m, s) =&gt;
                {
                    b.Read(request.BookInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(b.RecID, b);
                    }
                });

            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.Line Line = shipmentBookIn.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            shipmentBookIn.Lines.Remove(Line);

            if (!Helper.Service.IsStateful(this))
            {
                shipmentBookIn.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Shipments"			
    #region "{Main}"			
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the ShipmentID provided was found")]
    public class LandedCostShipmentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;
    {
        public string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class LandedCostShipmentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the ShipmentID provided was found")]
    public class LandedCostShipmentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;
    {
        public override string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the ShipmentID provided was found")]
    public class LandedCostShipmentDELETERequest
    {
        public string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the ShipmentID provided was found")]
    public class LandedCostShipmentSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;
    {
        public string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the ShipmentID provided was found")]
    public class LandedCostShipmentABANDONRequest
    {
        public string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order(s) with the order nos. provided were found")]
    public class LandedCostShipmentCREATEFromPORequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;
    {
        public string[] OrderNos { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Purchase Order Line(s) with the OrderLineID provided was found")]
    public class LandedCostShipmentCREATEFromPOLinesRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;
    {
        public LandedCostShipmentCREATEFromPOLinesRequest()
        {
            ReceivedPOLineQuantities = new System.Collections.Generic.List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity&gt;();
        }

        public System.Collections.Generic.List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity&gt; ReceivedPOLineQuantities { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No shipment with the ShipmentID provided was found")]
    public class LandedCostShipmentACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment&gt;
    {
        public string ShipmentID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class LandedCostShipmentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment Get(LandedCostShipmentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            return Shipment.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment Post(LandedCostShipmentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(null);

            Shipment.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Shipment.RecID, Shipment);
            else
            {
                Shipment.Save();
                Shipment.Read(Shipment.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.ShipmentID));

            return Shipment.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment Patch(LandedCostShipmentPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            Shipment.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Shipment.Save();
                Shipment.Read(request.ShipmentID);
            }

            return Shipment.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(LandedCostShipmentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID, (g, m, s) =&gt; g.Read(request.ShipmentID));
            Shipment.Delete();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment Get(LandedCostShipmentSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.ShipmentID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful shipment exists with ShipmentID '{0}'", request.ShipmentID));
            }

            var Shipment = (JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment)objectDictionaryValue;

            Shipment.Save();
            Shipment.Read(Shipment.RecID);

            return Shipment.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(LandedCostShipmentABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.ShipmentID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful shipment exists with ShipmentID '{0}'", request.ShipmentID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.ShipmentID);
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment Post(LandedCostShipmentCREATEFromPORequest request)
        {
            if (request.OrderNos.Length == 0)
                throw new Exception("No Order No's provided - array empty");

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(null);
            Shipment.CreateNew();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder newPurchaseOrder;
            foreach (string orderNo in request.OrderNos)
            {
                PO_Main po = Db.Single(Db.From&lt;PO_Main&gt;().Where(pl =&gt; pl.OrderNo == orderNo).Take(1));

                if (po == null)
                {
                    throw new Exception(string.Format("PO with Order No. '{0}' was not found", orderNo));
                }
                newPurchaseOrder = manager.CollectionItemFactory.CreateCollectionItem&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder&gt;();
                newPurchaseOrder.PurchaseOrder.ReadRecord(po.OrderID);
                Shipment.PurchaseOrders.Add(newPurchaseOrder);
                foreach (JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrderLine purchaseOrderLine in newPurchaseOrder.PurchaseOrderLines)
                    purchaseOrderLine.AddToShipmentLines();
            }

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Shipment.RecID, Shipment);
            else
            {
                Shipment.Save();
                Shipment.Read(Shipment.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Shipment.RecID));

            return Shipment.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment Post(LandedCostShipmentCREATEFromPOLinesRequest request)
        {
            // find creditor
            if (request.ReceivedPOLineQuantities.Count == 0)
                throw new Exception("No purchase order lines provided - array empty");

            var OrderIDs = new System.Collections.Generic.List&lt;string&gt;();
            foreach (ReceivedPOLineQuantity existingReceivedPOLineQuantity in request.ReceivedPOLineQuantities)
            {
                PO_Main purchaseOrder = Db.Single(Db.From&lt;PO_Main&gt;()
                                .Join&lt;PO_Main, PO_Lines&gt;()
                                .Where&lt;PO_Lines&gt;(x =&gt; x.OrderLineID == existingReceivedPOLineQuantity.OrderLineID)
                                .Take(1));

                OrderIDs.Add(purchaseOrder.OrderID);
            }

            var distinctOrderIDs = OrderIDs.Distinct();

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(null);
            Shipment.CreateNew();
            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder newPurchaseOrder;
            foreach (string orderID in OrderIDs)
            {
                newPurchaseOrder = manager.CollectionItemFactory.CreateCollectionItem&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder&gt;();
                newPurchaseOrder.PurchaseOrder.ReadRecord(orderID);
                Shipment.PurchaseOrders.Add(newPurchaseOrder);
                foreach (JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrderLine purchaseOrderLine in newPurchaseOrder.PurchaseOrderLines)
                    foreach (ReceivedPOLineQuantity receivedPOLineQuantity in request.ReceivedPOLineQuantities)
                        if (receivedPOLineQuantity.OrderLineID == purchaseOrderLine.RecID &amp;&amp; purchaseOrderLine.Include)
                        {
                            purchaseOrderLine.AddToShipmentLines();
                            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Line newShipmentLine = Shipment.Lines[Shipment.Lines.Count - 1];
                            newShipmentLine.QuantityThisShipment = (decimal)receivedPOLineQuantity.Quantity;
                        }

            }

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Shipment.RecID, Shipment);
            else
            {
                Shipment.Save();
                Shipment.Read(Shipment.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Shipment.RecID));

            return Shipment.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.Shipment Post(LandedCostShipmentACTIVATERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(null);
            Shipment.Read(request.ShipmentID);

            Shipment.ActivateRecord();
            Shipment.Read(request.ShipmentID);
            return Shipment.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Purchase Orders"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the ShipmentID or OrderID provided was found")]
    public class LandedCostShipmentPurchaseOrderGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived&gt;
    {
        public string ShipmentID { get; set; }
        public string OrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the ShipmentID provided was found")]
    public class LandedCostShipmentPurchaseOrdersGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived&gt;&gt;
    {
        public string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the ShipmentID or OrderID provided was found")]
    public class LandedCostShipmentPurchaseOrderPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived&gt;
    {
        public string ShipmentID { get; set; }
        public override string OrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the ShipmentID or OrderID provided was found")]
    public class LandedCostShipmentPurchaseOrderDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived
    {
        public string ShipmentID { get; set; }
        public override string OrderID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class LandedCostShipmentPurchaseOrderServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived Get(LandedCostShipmentPurchaseOrderGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder purchaseOrder = Shipment.PurchaseOrders.Cast&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder&gt;().FirstOrDefault(x =&gt; x.PurchaseOrder.RecID == request.OrderID);

            if (purchaseOrder == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No purchase order with OrderID '{0}' was found.", request.OrderID));

            return purchaseOrder.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived&gt; Get(LandedCostShipmentPurchaseOrdersGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });
            return Shipment.PurchaseOrders.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived Post(LandedCostShipmentPurchaseOrderPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            var purchaseOrders = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentPurchaseOrderReceived&gt;();
            purchaseOrders.Add(request);

            Shipment.PurchaseOrders.DTO_Deserialise(purchaseOrders);

            if (!Helper.Service.IsStateful(this))
            {
                Shipment.Save();
                Shipment.Read(Shipment.RecID);
            }

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder purchaseOrder = Shipment.PurchaseOrders.Cast&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder&gt;().FirstOrDefault(x =&gt; x.PurchaseOrder.RecID == request.OrderID);

            if (purchaseOrder == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No purchase order with OrderID '{0}' was found.", request.OrderID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], purchaseOrder.PurchaseOrder.RecID));

            return purchaseOrder.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(LandedCostShipmentPurchaseOrderDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder purchaseOrder = Shipment.PurchaseOrders.Cast&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.PurchaseOrder&gt;().FirstOrDefault(x =&gt; x.PurchaseOrder.RecID == request.OrderID);

            if (purchaseOrder == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No purchase order with OrderID '{0}' was found.", request.OrderID));

            Shipment.PurchaseOrders.Remove(purchaseOrder);

            if (!Helper.Service.IsStateful(this))
            {
                Shipment.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the ShipmentID or LineID provided was found")]
    public class LandedCostShipmentLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentLine&gt;
    {
        public string ShipmentID { get; set; }
        public string LineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the ShipmentID provided was found")]
    public class LandedCostShipmentLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentLine&gt;&gt;
    {
        public string ShipmentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the ShipmentID or LineID provided was found")]
    public class LandedCostShipmentLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentLine&gt;
    {
        public string ShipmentID { get; set; }
        public override string LineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class LandedCostShipmentLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentLine Get(LandedCostShipmentLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaLandedCost.Shipment.Line Line = Shipment.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentLine&gt; Get(LandedCostShipmentLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });
            return Shipment.Lines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.LandedCost.Shipments.ShipmentLine Patch(LandedCostShipmentLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment Shipment = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment&gt;(manager, this, request.ShipmentID,
                (g, m, s) =&gt;
                {
                    g.Read(request.ShipmentID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(g.RecID, g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Line Line = Shipment.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            Line.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Shipment.Save();
                Shipment.Read(Shipment.RecID);
            }

            Line = Shipment.Lines.GetItem("RecID", request.LineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with LineID '{0}' was found.", request.LineID));

            return Line.DTO_Serialise();
        }
    }
    #endregion
    #endregion
    #endregion
    #endregion

    #region "Languages"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No language with the RecID provided was found")]
    public class LanguageGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language&gt;
    {
        public string LanguageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class LanguagesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class LanguagePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LanguageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No language with the RecID provided was found")]
    public class LanguagePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language&gt;
    {
        public override string LanguageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No language with the RecID provided was found")]
    public class LanguageDELETERequest
    {
        public string LanguageID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class LanguageServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language Get(LanguageGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection Languages = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaApplication.Language.Language, JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection",
                (l, m, s) =&gt;
                {
                    l.Read();
                });

            JiwaFinancials.Jiwa.JiwaApplication.Language.Language Language = Languages.GetItem("RecID", request.LanguageID);

            if (Language == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No language with RecID '{0}' was found.", request.LanguageID));

            return Language.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language&gt; Get(LanguagesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection Languages = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaApplication.Language.Language, JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection",
                (l, m, s) =&gt;
                {
                    l.Read();
                });

            return Languages.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language Post(LanguagePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection Languages = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaApplication.Language.Language, JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection",
                (l, m, s) =&gt;
                {
                    l.Read();
                });

            // Add the language. Need to jump through a few hoops as we want to know the LanguageID so we can return that in the response header.	
            var dtoLanguages = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language&gt;();
            dtoLanguages.Add(request);
            string recID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaApplication.Language.Language&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                recID = item.RecID;
                Languages.Added -= addedHandler; // remove handler						
            };

            Languages.Added += addedHandler;
            Languages.DTO_Deserialise(dtoLanguages);

            if (!Helper.Service.IsStateful(this))
            {
                Languages.Save();
                Languages.Read();
            }

            JiwaFinancials.Jiwa.JiwaApplication.Language.Language Language = Languages.GetItem("RecID", recID);

            if (Language == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No language with RecID '{0}' was found.", recID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Language.RecID));

            return Language.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Languages.Language Patch(LanguagePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection Languages = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaApplication.Language.Language, JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection",
                (l, m, s) =&gt;
                {
                    l.Read();
                });

            JiwaFinancials.Jiwa.JiwaApplication.Language.Language Language = Languages.GetItem("RecID", request.LanguageID);

            if (Language == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No language with RecID '{0}' was found.", request.LanguageID));

            Language.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Languages.Save();
                Languages.Read();
            }

            Language = Languages.GetItem("RecID", request.LanguageID);

            if (Language == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No language with RecID '{0}' was found.", request.LanguageID));

            return Language.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(LanguageDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection Languages = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaApplication.Language.Language, JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.Language.LanguageCollection",
                (l, m, s) =&gt;
                {
                    l.Read();
                });

            JiwaFinancials.Jiwa.JiwaApplication.Language.Language Language = Languages.GetItem("RecID", request.LanguageID);

            if (Language == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No language with RecID '{0}' was found.", request.LanguageID));

            Languages.Remove(Language);

            if (!Helper.Service.IsStateful(this))
            {
                Languages.Save();
                Languages.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Logging"		
    #region "Requests"	
    public class TodayLogsGETManyRequest : QueryData&lt;RequestLogEntry&gt; { }	
    public class TodayErrorLogsGETManyRequest : QueryData&lt;RequestLogEntry&gt; { }	
    public class YesterdayLogsGETManyRequest : QueryData&lt;RequestLogEntry&gt; { }	
    public class YesterdayErrorLogsGETManyRequest : QueryData&lt;RequestLogEntry&gt; { }	
    public class QueryRequestLogsGETManyRequest : QueryData&lt;RequestLogEntry&gt;
    {
        public DateTime? Date { get; set; }
        public bool ViewErrors { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class RequestLogEntryQueryDataServices : Service
    {
        public IAutoQueryData AutoQueryData { get; set; }

		[Authenticate]
        public object Any(QueryRequestLogsGETManyRequest query)
        {
            var date = query.Date.GetValueOrDefault(DateTime.UtcNow);
            var logSuffix = query.ViewErrors ? "-errors" : "";
            var csvLogsFile = VirtualFileSources.GetFile(
                "requestlogs/{0}-{1}/{0}-{1}-{2}{3}.csv".Fmt(
                    date.Year.ToString("0000"),
                    date.Month.ToString("00"),
                    date.Day.ToString("00"),
                    logSuffix));

            if (csvLogsFile == null)
                throw HttpError.NotFound("No logs found on " + date.ToShortDateString());

            var logs = csvLogsFile.ReadAllText().FromCsv&lt;List&lt;RequestLogEntry&gt;&gt;();

            var q = AutoQueryData.CreateQuery(query, Request,
                db: new MemoryDataSource&lt;RequestLogEntry&gt;(logs, query, Request));

            return AutoQueryData.Execute(query, q);
        }

		[Authenticate]
        public object Any(TodayLogsGETManyRequest request)
        {
            return Any(new QueryRequestLogsGETManyRequest { Date = DateTime.UtcNow });
        }

		[Authenticate]
        public object Any(TodayErrorLogsGETManyRequest request)
        {
            return Any(new QueryRequestLogsGETManyRequest { Date = DateTime.UtcNow, ViewErrors = true });
        }

		[Authenticate]
        public object Any(YesterdayLogsGETManyRequest request)
        {
            return Any(new QueryRequestLogsGETManyRequest { Date = DateTime.UtcNow.AddDays(-1) });
        }

		[Authenticate]
        public object Any(YesterdayErrorLogsGETManyRequest request)
        {
            return Any(new QueryRequestLogsGETManyRequest { Date = DateTime.UtcNow.AddDays(-1), ViewErrors = true });
        }
    }
    #endregion
    #endregion

    #region "Logical Warehouse"
    #region "Requests"			
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class LogicalWarehousesCurrentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Warehouse changed OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class LogicalWarehousesCurrentPATCHRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical&gt;
    {
        public string IN_LogicalID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class LogicalWarehouseServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical Get(LogicalWarehousesCurrentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical logicalWarehouse = Db.Single&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical&gt;(x =&gt; x.IN_LogicalID == manager.CurrentLogicalWarehouse.IN_LogicalID);
            return logicalWarehouse;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical Patch(LogicalWarehousesCurrentPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            manager.CurrentLogicalWarehouse.IN_LogicalID = request.IN_LogicalID;

            JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical logicalWarehouse = Db.Single&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tables.IN_Logical&gt;(x =&gt; x.IN_LogicalID == manager.CurrentLogicalWarehouse.IN_LogicalID);
            return logicalWarehouse;
        }

    }
    #endregion
    #endregion

    #region "Purchase Order"
    #region "{Main}"
    #region"Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the PurchaseOrderID provided was found")]
    public class PurchaseOrderGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder&gt;
    {
        public string PurchaseOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class PurchaseOrderPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder&gt;
    {
        public override string CreditorRecID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PurchaseOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the PurchaseOrderID provided was found")]
    public class PurchaseOrderPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder&gt;
    {
        public override string PurchaseOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the PurchaseOrderID provided was found")]
    public class PurchaseOrderDELETERequest
    {
        public string PurchaseOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the PurchaseOrderID provided was found")]
    public class PurchaseOrderSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder&gt;
    {
        public string PurchaseOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the PurchaseOrderID provided was found")]
    public class PurchaseOrderABANDONRequest
    {
        public string PurchaseOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order line(s) with the OrderLineID provided was found")]
    public class PurchaseOrderReceiveStockCREATEFromPOLinesRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.ReceivalDocument&gt;&gt;
    {
        public PurchaseOrderReceiveStockCREATEFromPOLinesRequest()
        {
            ReceivedPOLineQuantities = new System.Collections.Generic.List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity&gt;();
        }

        public System.Collections.Generic.List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity&gt; ReceivedPOLineQuantities { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the PurchaseOrderID provided was found")]
    public class PurchaseOrderACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder&gt;
    {
        public string PurchaseOrderID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class PurchaseOrderServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder Get(PurchaseOrderGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(manager, this, request.PurchaseOrderID,
                (po, m, s) =&gt;
                {
                    po.Read(request.PurchaseOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(po.OrderID, po);
                    }
                });
            return purchaseOrder.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder Post(PurchaseOrderPOSTRequest PurchaseOrder)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder PurchaseOrderObject = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(null);
            PurchaseOrderObject.DTO_Deserialise(PurchaseOrder);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(PurchaseOrderObject.OrderID, PurchaseOrderObject);
            else
            {
                PurchaseOrderObject.Save();
                PurchaseOrderObject.Read(PurchaseOrderObject.OrderID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], PurchaseOrderObject.OrderID));
            return PurchaseOrderObject.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.PurchaseOrders.PurchaseOrder Patch(PurchaseOrderPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(manager, this, request.PurchaseOrderID,
                (p, m, s) =&gt;
                {
                    p.Read(request.PurchaseOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(p.OrderID, p);
                    }
                });

            purchaseOrder.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseOrder.Save();
                purchaseOrder.Read(request.PurchaseOrderID);
            }

            return purchaseOrder.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(PurchaseOrderDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder PurchaseOrder = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(null);
            PurchaseOrder.Read(request.PurchaseOrderID);

            PurchaseOrder.Delete();
        }

        [Authenticate]
        public JiwaServiceModel.PurchaseOrders.PurchaseOrder Get(PurchaseOrderSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.PurchaseOrderID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful purchase order exists with PurchaseOrderID '{0}'", request.PurchaseOrderID));
            }

            var purchaseOrder = (JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder)objectDictionaryValue;

            purchaseOrder.Save();
            purchaseOrder.Read(purchaseOrder.RecID);

            return purchaseOrder.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(PurchaseOrderABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.PurchaseOrderID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful purchase order exists with PurchaseOrderID '{0}'", request.PurchaseOrderID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.PurchaseOrderID);
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.ReceivalDocument&gt; Post(PurchaseOrderReceiveStockCREATEFromPOLinesRequest request)
        {
            List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.ReceivalDocument&gt; receivalDocuments = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.ReceivalDocument&gt;();
            // Sanity check
            if (request.ReceivedPOLineQuantities.Count == 0)
                throw new Exception("No purchase order lines provided - array empty");

            var Orders = new System.Collections.Generic.List&lt;PO_Main&gt;();

            foreach (ReceivedPOLineQuantity existingReceivedPOLineQuantity in request.ReceivedPOLineQuantities)
            {
                PO_Main purchaseOrder = Db.Single(Db.From&lt;PO_Main&gt;()
                                .Join&lt;PO_Main, PO_Lines&gt;()
                                .Where&lt;PO_Lines&gt;(x =&gt; x.OrderLineID == existingReceivedPOLineQuantity.OrderLineID)
                                .Take(1));

                bool found = false;
                foreach (PO_Main addedPurchaseOrder in Orders)
                {
                    if (addedPurchaseOrder.OrderID == purchaseOrder.OrderID)
                    {
                        found = true;
                        break;
                    }
                }
                if (found == false)
                    Orders.Add(purchaseOrder);
            }

            //More sanity checks
            foreach (PO_Main purchaseOrder in Orders)
            {
                if (purchaseOrder.Status &gt;= 3 &amp;&amp; purchaseOrder.Status != 10 &amp;&amp; purchaseOrder.Status != 7)
                {
                    //Purchase order has a status that allows receival of stock
                }
                else
                {
                    //Purchase order is in an invalid state for receiving.
                    string purchaseOrderStatus = "";
                    switch (purchaseOrder.Status)
                    {
                        case 0:
                            purchaseOrderStatus = "Not Sent";
                            break;
                        case 1:
                            purchaseOrderStatus = "Awaiting Order Approval";
                            break;
                        case 2:
                            purchaseOrderStatus = "Awaiting EDI Processing";
                            break;
                        case 3:
                            purchaseOrderStatus = "Sent";
                            break;
                        case 4:
                            purchaseOrderStatus = "Receipt Acknowledged";
                            break;
                        case 5:
                            purchaseOrderStatus = "Accepted";
                            break;
                        case 6:
                            purchaseOrderStatus = "Accepted With Updates";
                            break;
                        case 7:
                            purchaseOrderStatus = "Rejected";
                            break;
                        case 8:
                            purchaseOrderStatus = "Awaiting Invoice Approval";
                            break;
                        case 9:
                            purchaseOrderStatus = "Invoicing";
                            break;
                        case 10:
                            purchaseOrderStatus = "Closed";
                            break;
                        default:
                            purchaseOrderStatus = "Unknown";
                            break;
                    }

                    throw new Exception(string.Format("Cannot receive against purchase order {0}, because it has a status of {1}", purchaseOrder.OrderNo, purchaseOrderStatus));
                }
            }

            var shipmentIDs = new System.Collections.Generic.List&lt;string&gt;();
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInvReceival.Receival goodsReceivedNoteObject = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInvReceival.Receival&gt;(null);
            foreach (PO_Main purchaseOrder in Orders)
            {
                //Is this purchase order on a shipment?
                SH_Main Shipment = Db.Single(Db.From&lt;SH_Main&gt;()
                                   .Join&lt;RE_OrdersUsed&gt;((x, y) =&gt; x.ShipmentID == y.PackSlipID)
                                   .Where&lt;RE_OrdersUsed&gt;(x =&gt; x.OrderID == purchaseOrder.OrderID)
                                   .Take(1));
                if (Shipment != null)
                    shipmentIDs.Add(Shipment.ShipmentID); //Add to a list of shipments for which we will create bookins later
                else
                {
                    if (purchaseOrder.OrderSupplierType == Convert.ToInt32(JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder.SupplierType.Creditor))
                    {
                        //Does an un-activated goods received note already exist for this purchase order?
                        RE_Main goodsReceivedNoteForThisPurchaseOrder = Db.Single(Db.From&lt;RE_Main&gt;()
                                           .Join&lt;RE_OrdersUsed&gt;((x, y) =&gt; x.PackSlipID == y.PackSlipID)
                                           .Where&lt;RE_OrdersUsed&gt;(x =&gt; x.OrderID == purchaseOrder.OrderID)
                                           .And&lt;RE_Main&gt;(x =&gt; x.Status == 1)
                                           .Take(1));
                        if (goodsReceivedNoteForThisPurchaseOrder != null)
                            goodsReceivedNoteObject.Read(goodsReceivedNoteForThisPurchaseOrder.PackSlipID); //Use the existing goods received note
                        else
                        {
                            //Does an un-activated goods received note already exist for this creditor?
                            RE_Main goodsReceivedNoteForThisCreditor = Db.Single(Db.From&lt;RE_Main&gt;()
                                               .Where&lt;RE_Main&gt;(x =&gt; x.CreditorID == purchaseOrder.CreditorID)
                                               .And&lt;RE_Main&gt;(x =&gt; x.Status == 1)
                                               .Take(1));

                            if (goodsReceivedNoteForThisCreditor != null)
                            {
                                //Add the purchase order to this goods received note
                                goodsReceivedNoteObject.Read(goodsReceivedNoteForThisCreditor.PackSlipID);
                                string newKey = "";
                                goodsReceivedNoteObject.PurchaseOrders.AddPO(purchaseOrder.OrderID, ref newKey);
                            }
                            else
                            {
                                //Create a new goods received note and add this purchase order to it
                                goodsReceivedNoteObject.CreateNew(purchaseOrder.CreditorID);
                                string newKey = "";
                                goodsReceivedNoteObject.PurchaseOrders.AddPO(purchaseOrder.OrderID, ref newKey);
                            }
                        }

                        //Set the quantities and save
                        foreach (JiwaFinancials.Jiwa.JiwaInvReceival.Line existingLine in goodsReceivedNoteObject.Lines)
                        {
                            foreach (JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity receivedPOLineQuantity in request.ReceivedPOLineQuantities)
                            {
                                if (receivedPOLineQuantity.OrderLineID == existingLine.RecID)
                                    existingLine.Quantity += (decimal)receivedPOLineQuantity.Quantity;
                            }
                        }
                        goodsReceivedNoteObject.Save();
                        receivalDocuments.Add(new JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.ReceivalDocument { DocumentNo = goodsReceivedNoteObject.GRNNo, DocumentID = goodsReceivedNoteObject.RecID, IsGoodsReceivedNote = true, IsLandedCostBookIn = false });
                    }
                    else
                    {
                        //Warehouse purchase order
                        //With the current Jiwa design, it actually makes no sense to be told to "receive" some quantity of stock for a warehouse purchase order. 
                        //As soon as a purchase order is set to sent, a warehouse transfer is created with all stock set to be received in full.
                    }
                }
            }

            //Now deal with purchase orders that are on a shipment(s)
            JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn bookIn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn&gt;(null);
            foreach (string shipmentID in shipmentIDs)
            {
                //See if an un-activated book in already exists
                SH_BookInMain existingBookIn = Db.Single(Db.From&lt;SH_BookInMain&gt;()
                                   .Where&lt;SH_BookInMain&gt;(x =&gt; x.ShipmentID == shipmentID)
                                   .And&lt;SH_BookInMain&gt;(x =&gt; x.Status == false)
                                   .Take(1));

                if (existingBookIn != null)
                {
                    bookIn.Read(existingBookIn.BookInID);
                    foreach (JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.Line bookInLine in bookIn.Lines)
                        foreach (JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity receivedPOLineQuantity in request.ReceivedPOLineQuantities)
                            if (receivedPOLineQuantity.OrderLineID == bookInLine.ShipmentLine.PurchaseOrderLine.RecID)
                                bookInLine.Quantity += (decimal)receivedPOLineQuantity.Quantity;
                }
                else
                {
                    //Create a new bookin and set quantities
                    bookIn.CreateNew(shipmentID);
                    foreach (JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.Line bookInLine in bookIn.Lines)
                    {
                        foreach (JiwaFinancials.Jiwa.JiwaServiceModel.ReceivedPOLineQuantity receivedPOLineQuantity in request.ReceivedPOLineQuantities)
                        {
                            if (receivedPOLineQuantity.OrderLineID == bookInLine.ShipmentLine.PurchaseOrderLine.RecID)
                                bookInLine.Quantity += (decimal)receivedPOLineQuantity.Quantity;
                        }
                    }
                }
                bookIn.Save();
                receivalDocuments.Add(new JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.ReceivalDocument { DocumentNo = bookIn.BookInNo, DocumentID = bookIn.RecID, IsGoodsReceivedNote = false, IsLandedCostBookIn = true });
            }

            return receivalDocuments;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrder Post(PurchaseOrderACTIVATERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(null);
            purchaseOrder.Read(request.PurchaseOrderID);

            purchaseOrder.MoveToWorkflowStep(JiwaFinancials.Jiwa.JiwaApplication.Entities.PurchaseOrder.Workflow.Status.Sent);
            purchaseOrder.Read(request.PurchaseOrderID);
            return purchaseOrder.DTO_Serialise();
        }

    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseOrderID or PurchaseOrderLineID provided was found")]
    public class PurchaseOrderLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine&gt;
    {
        public string PurchaseOrderID { get; set; }
        public string PurchaseOrderLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseOrderID provided was found")]
    public class PurchaseOrderLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine&gt;&gt;
    {
        public string PurchaseOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseOrderID or PurchaseOrderLineID provided was found")]
    public class PurchaseOrderLinePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine&gt;
    {
        public string PurchaseOrderID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PurchaseOrderLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseOrderID or PurchaseOrderLineID provided was found")]
    public class PurchaseOrderLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine&gt;
    {
        public string PurchaseOrderID { get; set; }
        public override string PurchaseOrderLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseOrderID or PurchaseOrderLineID provided was found")]
    public class PurchaseOrderLineDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine
    {
        public string PurchaseOrderID { get; set; }
        public override string PurchaseOrderLineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class PurchaseOrderLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine Get(PurchaseOrderLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(manager, this, request.PurchaseOrderID,
                (p, m, s) =&gt;
                {
                    p.Read(request.PurchaseOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(p.RecID, p);
                    }
                });

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.Line Line = purchaseOrder.Lines.GetItem("RecID", request.PurchaseOrderLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseOrderLineID '{0}' was found.", request.PurchaseOrderLineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine&gt; Get(PurchaseOrderLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(manager, this, request.PurchaseOrderID,
                (p, m, s) =&gt;
                {
                    p.Read(request.PurchaseOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(p.RecID, p);
                    }
                });
            return purchaseOrder.Lines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine Post(PurchaseOrderLinePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(manager, this, request.PurchaseOrderID,
                (p, m, s) =&gt;
                {
                    p.Read(request.PurchaseOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(p.RecID, p);
                    }
                });

            var Lines = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine&gt;();
            Lines.Add(request);

            purchaseOrder.Lines.DTO_Deserialise(Lines);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseOrder.Save();
                purchaseOrder.Read(purchaseOrder.RecID);
            }

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.Line Line = purchaseOrder.Lines.GetItem("RecID", request.PurchaseOrderLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseOrderLineID '{0}' was found.", request.PurchaseOrderLineID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Line.RecID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseOrders.PurchaseOrderLine Patch(PurchaseOrderLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(manager, this, request.PurchaseOrderID,
                (p, m, s) =&gt;
                {
                    p.Read(request.PurchaseOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(p.RecID, p);
                    }
                });

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.Line Line = purchaseOrder.Lines.GetItem("RecID", request.PurchaseOrderLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseOrderLineID '{0}' was found.", request.PurchaseOrderLineID));

            Line.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseOrder.Save();
                purchaseOrder.Read(purchaseOrder.RecID);
            }

            Line = purchaseOrder.Lines.GetItem("RecID", request.PurchaseOrderLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseOrderLineID '{0}' was found.", request.PurchaseOrderLineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(PurchaseOrderLineDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder purchaseOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder&gt;(manager, this, request.PurchaseOrderID,
                (p, m, s) =&gt;
                {
                    p.Read(request.PurchaseOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(p.RecID, p);
                    }
                });

            JiwaFinancials.Jiwa.JiwaPurchaseOrders.Line Line = purchaseOrder.Lines.GetItem("RecID", request.PurchaseOrderLineID);

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseOrderLineID '{0}' was found.", request.PurchaseOrderLineID));

            purchaseOrder.Lines.Remove(Line);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseOrder.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion
	
    #region "Purchase Invoices"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase invoice with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoiceGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice&gt;
    {
        public string PurchaseInvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class PurchaseInvoicePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice&gt;
    {
        public override string CreditorID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PurchaseInvoiceID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase invoice with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoicePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice, IReturn&lt;JiwaServiceModel.PurchaseInvoices.PurchaseInvoice&gt;
    {
        public override string PurchaseInvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase invoice with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoiceDELETERequest
    {
        public string PurchaseInvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase invoice with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoiceSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice&gt;
    {
        public string PurchaseInvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase invoice with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoiceABANDONRequest
    {
        public string PurchaseInvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Goods Received Note(s) with the GRN No(s). provided was/were found")]
    public class PurchaseInvoiceCREATEFromGRNRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice&gt;
    {
        public string[] GRNNos { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase invoice with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoiceACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice&gt;
    {
        public string PurchaseInvoiceID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class PurchaseInvoiceServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice Get(PurchaseInvoiceGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });

            return purchaseInvoice.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice Post(PurchaseInvoicePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice&gt;(null);

            purchaseInvoice.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(purchaseInvoice.RecID, purchaseInvoice);
            else
            {
                purchaseInvoice.Save();
                purchaseInvoice.Read(purchaseInvoice.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.PurchaseInvoiceID));

            return purchaseInvoice.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.PurchaseInvoices.PurchaseInvoice Patch(PurchaseInvoicePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });

            purchaseInvoice.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseInvoice.Save();
                purchaseInvoice.Read(request.PurchaseInvoiceID);
            }

            return purchaseInvoice.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(PurchaseInvoiceDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID, (g, m, s) =&gt; g.Read(request.PurchaseInvoiceID));
            purchaseInvoice.Delete();
        }

        [Authenticate]
        public JiwaServiceModel.PurchaseInvoices.PurchaseInvoice Get(PurchaseInvoiceSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful purchase invoice exists with PurchaseInvoiceID '{0}'", request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaInvReceival.Receival&gt;()));
            }

            var purchaseInvoice = (JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice)objectDictionaryValue;

            purchaseInvoice.Save();
            purchaseInvoice.Read(purchaseInvoice.RecID);

            return purchaseInvoice.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(PurchaseInvoiceABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful purchase invoice exists with PurchaseInvoiceID '{0}'", request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;()));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;());
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice Post(PurchaseInvoiceCREATEFromGRNRequest request)
        {
            if (request.GRNNos.Length == 0)
            {
                throw new Exception("No GRN No's provided - array empty");
            }

            RE_Main firstGRN = Db.Single(Db.From&lt;RE_Main&gt;().Where(x =&gt; x.SlipNo == request.GRNNos[0]).Take(1));

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice&gt;(null);
            purchaseInvoice.CreateNew(firstGRN.CreditorID);

            foreach (string GRNNo in request.GRNNos)
            {
                RE_Main grn = Db.Single(Db.From&lt;RE_Main&gt;().Where(pl =&gt; pl.SlipNo == GRNNo).Take(1));

                if (grn == null)
                {
                    throw new Exception(string.Format("GRN with Slip No. '{0}' was not found", GRNNo));
                }

                string newInvoiceKey = "";
                string packSlipID = grn.PackSlipID;
                purchaseInvoice.InventoryReceivals.AddInventoryReceival(packSlipID, ref newInvoiceKey);
            }

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(purchaseInvoice.RecID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), purchaseInvoice);
            else
            {
                purchaseInvoice.Save();
                purchaseInvoice.Read(purchaseInvoice.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], purchaseInvoice.RecID));

            return purchaseInvoice.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoice Post(PurchaseInvoiceACTIVATERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice&gt;(null);
            purchaseInvoice.Read(request.PurchaseInvoiceID);

            purchaseInvoice.ActivateRecord();
            purchaseInvoice.Read(request.PurchaseInvoiceID);
            return purchaseInvoice.DTO_Serialise();
        }
    }
    #endregion
    #endregion
	
    #region "Goods Received Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the PurchaseInvoiceID or OrderID provided was found")]
    public class PurchaseInvoiceGoodsReceivedNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced&gt;
    {
        public string PurchaseInvoiceID { get; set; }
        public string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoiceGoodsReceivedNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced&gt;&gt;
    {
        public string PurchaseInvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the PurchaseInvoiceID or GRNID provided was found")]
    public class PurchaseInvoiceGoodsReceivedNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced&gt;
    {
        public string PurchaseInvoiceID { get; set; }
        public override string GRNID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No goods received note with the PurchaseInvoiceID or GRNID provided was found")]
    public class PurchaseInvoiceGoodsReceivedNoteDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced
    {
        public string PurchaseInvoiceID { get; set; }
        public override string GRNID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class PurchaseInvoicePurchaseOrderServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced Get(PurchaseInvoiceGoodsReceivedNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.InventoryReceival grn = purchaseInvoice.InventoryReceivals.GetItem("PackSlipID", request.GRNID);

            if (grn == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note with GRNID '{0}' was found.", request.GRNID));

            return grn.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced&gt; Get(PurchaseInvoiceGoodsReceivedNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });
            return purchaseInvoice.InventoryReceivals.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced Post(PurchaseInvoiceGoodsReceivedNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });

            var goodsReceivedNotes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceGoodsReceivedNoteInvoiced&gt;();
            goodsReceivedNotes.Add(request);

            purchaseInvoice.InventoryReceivals.DTO_Deserialise(goodsReceivedNotes);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseInvoice.Save();
                purchaseInvoice.Read(purchaseInvoice.RecID);
            }

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.InventoryReceival grn = purchaseInvoice.InventoryReceivals.GetItem("PackSlipID", request.GRNID);

            if (grn == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note with GRNID '{0}' was found.", request.GRNID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], grn.RecID));

            return grn.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(PurchaseInvoiceGoodsReceivedNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.InventoryReceival grn = purchaseInvoice.InventoryReceivals.GetItem("PackSlipID", request.GRNID);

            if (grn == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No goods received note with GRNID '{0}' was found.", request.GRNID));

            purchaseInvoice.InventoryReceivals.Remove(grn);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseInvoice.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseInvoiceID or PurchaseInvoiceLineID provided was found")]
    public class PurchaseInvoiceLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceLine&gt;
    {
        public string PurchaseInvoiceID { get; set; }
        public string PurchaseInvoiceLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseInvoiceID provided was found")]
    public class PurchaseInvoiceLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceLine&gt;&gt;
    {
        public string PurchaseInvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No line with the PurchaseInvoiceID or PurchaseInvoiceLineID provided was found")]
    public class PurchaseInvoiceLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceLine&gt;
    {
        public string PurchaseInvoiceID { get; set; }
        public override string PurchaseInvoiceLineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class PurchaseInvoiceLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceLine Get(PurchaseInvoiceLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.Line Line = purchaseInvoice.Lines[request.PurchaseInvoiceLineID];

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseInvoiceLineID '{0}' was found.", request.PurchaseInvoiceLineID));

            return Line.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceLine&gt; Get(PurchaseInvoiceLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });
            return purchaseInvoice.Lines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.PurchaseInvoices.PurchaseInvoiceLine Patch(PurchaseInvoiceLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice purchaseInvoice = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(manager, this, request.PurchaseInvoiceID,
                (g, m, s) =&gt;
                {
                    g.Read(request.PurchaseInvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(request.PurchaseInvoiceID.CreateObjectDictionaryKey&lt;JiwaPurchaseInvoices.PurchaseInvoice&gt;(), g);
                    }
                });

            JiwaFinancials.Jiwa.JiwaPurchaseInvoices.Line Line = purchaseInvoice.Lines[request.PurchaseInvoiceLineID];

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseInvoiceLineID '{0}' was found.", request.PurchaseInvoiceLineID));

            Line.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                purchaseInvoice.Save();
                purchaseInvoice.Read(purchaseInvoice.RecID);
            }

            Line = purchaseInvoice.Lines[request.PurchaseInvoiceLineID];

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No line with PurchaseInvoiceLineID '{0}' was found.", request.PurchaseInvoiceLineID));

            return Line.DTO_Serialise();
        }
    }
    #endregion
    #endregion
    #endregion	

    #region "Regions"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No region with the RegionID provided was found")]
    public class RegionGETRequest : IReturn&lt;JiwaServiceModel.Regions.Region&gt;
    {
        public string RegionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class RegionPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Regions.Region, IReturn&lt;JiwaServiceModel.Regions.Region&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string RegionID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No region with the RegionID provided was found")]
    public class RegionPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Regions.Region, IReturn&lt;JiwaServiceModel.Regions.Region&gt;
    {
        public override string RegionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No region with the RegionID provided was found")]
    public class RegionDELETERequest
    {
        public string RegionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No region with the RegionID provided was found")]
    public class RegionSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Regions.Region&gt;
    {
        public string RegionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No region with the RegionID provided was found")]
    public class RegionABANDONRequest
    {
        public string RegionID { get; set; }
    }

    #endregion

    #region "Services"				
    [CompressResponse]
    public class RegionServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Regions.Region Get(RegionGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region Region = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region&gt;(manager, this, request.RegionID,
                (r, m, s) =&gt;
                {
                    r.Read(request.RegionID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(r.RecID, r);
                    }
                });

            return Region.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Regions.Region Post(RegionPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region Region = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region&gt;(null);

            Region.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(Region.RecID, Region);
            else
            {
                Region.Save();
                Region.Read(Region.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.RegionID));

            return Region.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.Regions.Region Patch(RegionPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region Region = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region&gt;(manager, this, request.RegionID,
                (r, m, s) =&gt;
                {
                    r.Read(request.RegionID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(r.RecID, r);
                    }
                });

            Region.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                Region.Save();
                Region.Read(request.RegionID);
            }

            return Region.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(RegionDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region Region = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region&gt;(manager, this, request.RegionID, (d, m, s) =&gt; d.Read(request.RegionID));
            Region.Delete();
        }

        [Authenticate]
        public JiwaServiceModel.Regions.Region Get(RegionSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.RegionID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful region exists with RegionID '{0}'", request.RegionID));
            }

            var Region = (JiwaFinancials.Jiwa.JiwaInventory.Configuration.Regions.Region)objectDictionaryValue;
            Region.Save();

            return Region.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(RegionABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.RegionID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful region exists with RegionID '{0}'", request.RegionID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.RegionID);
        }
    }
    #endregion
    #endregion

    #region "Reports"			
    #region "Requests"		
	[Serializable()]
    [ApiResponse(200, "OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No report with the ReportID provided was found")]
    public class ReportsPDFGETRequest : IReturn&lt;ServiceStack.Web.IHttpResult&gt;
    {
        public string ReportID { get; set; }
        public List&lt;ReportParameter&gt; ReportParameters { get; set; }
        public bool AsAttachment { get; set; }
    }

	[Serializable()]
    public class ReportParameter
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }
    #endregion

    #region "Services"							
    [CompressResponse]
    public class ReportsServices : Service
    {
        [Authenticate]
        public ServiceStack.Web.IHttpResult Get(ReportsPDFGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaApplication.Report.Configuration.ReportCollection m_Reports = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaApplication.Report.Configuration.ReportCollection&gt;(null);
            m_Reports.Read();

            // find report with request.ReportID
            JiwaApplication.Report.Configuration.Report report = m_Reports[request.ReportID];

            if (report == null)
                throw new JiwaApplication.Exceptions.RecordNotFoundException("Report not found");

            JiwaApplication.JiwaPrintReport.JiwaPrintReport printReportObject = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaApplication.JiwaPrintReport.JiwaPrintReport&gt;(null);
            printReportObject.Setup();

            printReportObject.LoadReport(report);

            if (request.ReportParameters != null)
            {
                foreach (ReportParameter reportParameter in request.ReportParameters)
                {
                    foreach (JiwaApplication.JiwaPrintReport.JiwaReportRange jiwaReportRange in printReportObject.JiwaReportRangeCollection)
                    {
                        if (printReportObject.JiwaPrintFormulaCollection[jiwaReportRange.FormulaKey].Name.Replace("{", "").Replace("}", "").Replace("@", "").Trim().ToUpper() == reportParameter.Name.Replace("{", "").Replace("}", "").Replace("@", "").Trim().ToUpper())
                        {
                            jiwaReportRange.Value = reportParameter.Value;
                            break;
                        }
                    }
                }
            }

            printReportObject.UpdateReport();

            // export report to PDF
            string tempFolderPath = System.IO.Path.GetTempPath();
            string fileName = report.Title;

            // Make filename safe
            foreach (char c in System.IO.Path.GetInvalidFileNameChars())
            {
                fileName = fileName.Replace(c.ToString(), "");
            }

            string fullFileName = System.IO.Path.Combine(tempFolderPath, fileName) + ".pdf";
            printReportObject.CrystalReportObject.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, fullFileName);

            // Return the file
            System.IO.FileInfo fileInfo = new System.IO.FileInfo(fullFileName);
            return new HttpResult(fileInfo, asAttachment: request.AsAttachment);
        }
    }
    #endregion
    #endregion

    #region "Rest Paths"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read")]
    public class RestPathsGETManyRequest : IReturn&lt;List&lt;RestPath&gt;&gt;
    {
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class RestPathServices : Service
    {
        public List&lt;RestPath&gt; Get(RestPathsGETManyRequest request)
        {
            List&lt;RestPath&gt; restPaths = new List&lt;RestPath&gt;();

            foreach (ServiceStack.Host.RestPath restPath in AppHostBase.Instance.RestPaths)
            {
                var dtoRestPath = new RestPath();
                dtoRestPath.Path = restPath.Path;
                dtoRestPath.Summary = restPath.Summary;
                dtoRestPath.AllowedVerbs = restPath.AllowedVerbs;

                restPaths.Add(dtoRestPath);
            }

            return restPaths;
        }
    }
    #endregion
    #endregion

    #region "Sales Orders"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string InvoiceID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder&gt;
    {
        override public string InvoiceID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Processed OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderPROCESSRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderABANDONRequest
    {
        public string InvoiceID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder Get(SalesOrderGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });
            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder Post(SalesOrderPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(null);
            so.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(so.InvoiceID, so);
            else
            {
                so.Save();
                so.Read(so.InvoiceID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], so.InvoiceID));

            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder Patch(SalesOrderPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            so.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.InvoiceID);
            }

            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder Get(SalesOrderSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.InvoiceID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful sales order exists with InvoiceID '{0}'", request.InvoiceID));
            }

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = (JiwaSales.SalesOrder.SalesOrder)objectDictionaryValue;
            so.Save();

            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrder Get(SalesOrderPROCESSRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(null);
            so.Read(request.InvoiceID);

            so.Process();
            so.Read(so.InvoiceID);
            return so.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.InvoiceID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful sales order exists with InvoiceID '{0}'", request.InvoiceID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.InvoiceID);
        }
    }
    #endregion
    #endregion

    #region "Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No custom field with the SettingID provided was found")]
    public class SalesOrderCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Custom Field Value with the InvoiceID or SettingID provided was found")]
    public class SalesOrderCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InvoiceID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Custom Field Value with the InvoiceID or SettingID provided was found")]
    public class SalesOrderCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InvoiceID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(SalesOrderCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            return salesOrder.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(SalesOrderCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            var salesOrderCustomFieldValue = so.CustomFieldValues.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (salesOrderCustomFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return salesOrderCustomFieldValue;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(SalesOrderCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = salesOrder.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            customFieldValue = salesOrder.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(SalesOrderCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, null, null);

            return salesOrder.CustomSettings.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Document Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder document type with the DocumentTypeID provided was found")]
    public class SalesOrderDocumentTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderDocumentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderDocumentTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder document type with the DocumentTypeID provided was found")]
    public class SalesOrderDocumentTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder document type with the DocumentTypeID provided was found")]
    public class SalesOrderDocumentTypeDELETERequest
    {
        public string DocumentTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderDocumentTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Get(SalesOrderDocumentTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
					d.DocumentTableNames.Add("SO_Documents");					
                    d.Read();
                });

            JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt; Get(SalesOrderDocumentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
					d.DocumentTableNames.Add("SO_Documents");					
                    d.Read();
                });

            return documentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Post(SalesOrderDocumentTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
					d.DocumentTableNames.Add("SO_Documents");					
                    d.Read();
                });

            // Add the document type. Need to jump through a few hoops as we want to know the DocumentTypeID so we can return that in the response header.	
            var dtoDocumentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;();
            dtoDocumentTypes.Add(request);
            string documentTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaDocumentTypes.DocumentType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentTypeID = item.RecID;
                documentTypes.Added -= addedHandler; // remove handler						
            };

            documentTypes.Added += addedHandler;
            documentTypes.DTO_Deserialise(dtoDocumentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", documentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", documentTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], documentType.RecID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Patch(SalesOrderDocumentTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
					d.DocumentTableNames.Add("SO_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderDocumentTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
					d.DocumentTableNames.Add("SO_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentTypes.Remove(documentType);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Documents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder Document with the InvoiceID or DocumentID provided was found")]
    public class SalesOrderDocumentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string InvoiceID { get; set; }
        public string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder with the InvoiceID provided was found")]
    public class SalesOrderDocumentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder with the InvoiceID provided was found")]
    public class SalesOrderDocumentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string InvoiceID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder with the InvoiceID provided was found")]
    public class SalesOrderDocumentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string InvoiceID { get; set; }
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder with the InvoiceID provided was found")]
    public class SalesOrderDocumentDELETERequest
    {
        public string InvoiceID { get; set; }
        public string DocumentID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderDocumentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Get(SalesOrderDocumentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InvoiceID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = salesOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt; Get(SalesOrderDocumentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder SalesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InvoiceID, d);
                    }
                });

            return SalesOrder.Documents.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Post(SalesOrderDocumentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder SalesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InvoiceID, d);
                    }
                });

            // Add the document. Need to jump through a few hoops as we want to know the DocumentID so we can return that in the response header.	
            var documents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;();
            documents.Add(request);
            string documentID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Documents.Document&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentID = item.RecID;
                SalesOrder.Documents.Added -= addedHandler; // remove handler						
            };

            SalesOrder.Documents.Added += addedHandler;
            SalesOrder.Documents.DTO_Deserialise(documents);

            if (!Helper.Service.IsStateful(this))
            {
                SalesOrder.Save();
                SalesOrder.Read(SalesOrder.InvoiceID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = SalesOrder.Documents.GetItem("RecID", documentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", documentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], document.RecID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Patch(SalesOrderDocumentPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder SalesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InvoiceID, d);
                    }
                });

            JiwaApplication.Documents.Document document = SalesOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document with DocumentID '{0}' was found.", request.DocumentID));

            document.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                SalesOrder.Save();
                SalesOrder.Read(SalesOrder.InvoiceID);
            }

            document = SalesOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderDocumentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder SalesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (d, m, s) =&gt;
                {
                    d.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.InvoiceID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = SalesOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order document with DocumentID '{0}' was found.", request.DocumentID));

            SalesOrder.Documents.Remove(document);

            if (!Helper.Service.IsStateful(this))
            {
                SalesOrder.Save();
                SalesOrder.Read(SalesOrder.InvoiceID);
            }
        }
    }
    #endregion
    #endregion

    #region "History"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistorysGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderHistory&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder with the InvoiceID provided was found")]
    public class SalesOrderHistorysGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderHistory&gt;&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder with the InvoiceID, Or InvoiceHistoryID provided was found")]
    public class SalesOrderHistorysPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderHistory, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderHistory&gt;
    {
        public string InvoiceID { get; set; }
        override public string InvoiceHistoryID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderHistoryServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderHistory Get(SalesOrderHistorysGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            return history.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderHistory&gt; Get(SalesOrderHistorysGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            return salesOrder.SalesOrderHistorys.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderHistory Patch(SalesOrderHistorysPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            history.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);

                history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

                if (history == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));
            }

            return history.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "History Carrier Consignment Notes"
    #region "Requests"	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryConsignmentNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote&gt;&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder consignment note with ConsignmentNoteID, InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryConsignmentNotesGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string ConsignmentNoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryConsignmentNotesPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string ConsignmentNoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder consignment note with ConsignmentNoteID, InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryConsignmentNotesPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public override string ConsignmentNoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder consignment note with ConsignmentNoteID, InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryConsignmentNotesDELETERequest
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string ConsignmentNoteID { get; set; }
    }

    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderHistoryCarrierConsignmentNoteServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote&gt; Get(SalesOrderHistoryConsignmentNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            return history.Carrier.ConsignmentNoteCollection.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote Get(SalesOrderHistoryConsignmentNotesGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.ConsignmentNote ConsignmentNote = history.Carrier.ConsignmentNoteCollection[request.ConsignmentNoteID];

            if (ConsignmentNote == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No ConsignmentNote with ConsignmentNoteID '{0}' was found.", request.ConsignmentNoteID));

            return ConsignmentNote.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote Post(SalesOrderHistoryConsignmentNotesPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            // Add the consignment note. Need to jump through a few hoops as we want to know the ConsignmentNoteid so we can return that in the response header.	
            var ConsignmentNotes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote&gt;();
            ConsignmentNotes.Add(request);
            string ConsignmentNoteID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaSales.SalesOrder.ConsignmentNote&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                ConsignmentNoteID = item.RecID;
                history.Carrier.ConsignmentNoteCollection.Added -= addedHandler; // remove handler						
            };

            history.Carrier.ConsignmentNoteCollection.Added += addedHandler;
            history.Carrier.ConsignmentNoteCollection.DTO_Deserialise(ConsignmentNotes);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.ConsignmentNote ConsignmentNote = history.Carrier.ConsignmentNoteCollection.GetItem("RecID", ConsignmentNoteID);

            if (ConsignmentNote == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No ConsignmentNote with ConsignmentNoteID '{0}' was found.", ConsignmentNoteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], ConsignmentNote.RecID));

            return ConsignmentNote.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderConsignmentNote Patch(SalesOrderHistoryConsignmentNotesPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.ConsignmentNote ConsignmentNote = history.Carrier.ConsignmentNoteCollection[request.ConsignmentNoteID];

            if (ConsignmentNote == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No ConsignmentNote with ConsignmentNoteID '{0}' was found.", request.ConsignmentNoteID));

            ConsignmentNote.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);

                history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

                if (history == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

                ConsignmentNote = history.Carrier.ConsignmentNoteCollection[request.ConsignmentNoteID];

                if (ConsignmentNote == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No ConsignmentNote with ConsignmentNoteID '{0}' was found.", request.ConsignmentNoteID));
            }

            return ConsignmentNote.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderHistoryConsignmentNotesDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.ConsignmentNote ConsignmentNote = history.Carrier.ConsignmentNoteCollection[request.ConsignmentNoteID];

            if (ConsignmentNote == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No ConsignmentNote with ConsignmentNoteID '{0}' was found.", request.ConsignmentNoteID));

            history.Carrier.ConsignmentNoteCollection.Remove(ConsignmentNote);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "History Carrier FreightItems"
    #region "Requests"		
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryFreightItemsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem&gt;&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder Freight Item with FreightItemID, InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryFreightItemsGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string FreightItemID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryFreightItemsPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string FreightItemID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder Freight Item with FreightItemID, InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryFreightItemsPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public override string FreightItemID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder Freight Item with FreightItemID, InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryFreightItemsDELETERequest
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string FreightItemID { get; set; }
    }

    #endregion

    #region "Services"					
    [CompressResponse]
    public class SalesOrderHistoryCarrierFreightItemServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem&gt; Get(SalesOrderHistoryFreightItemsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            return history.Carrier.FreightItemCollection.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem Get(SalesOrderHistoryFreightItemsGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.FreightItem freightItem = history.Carrier.FreightItemCollection[request.FreightItemID];

            if (freightItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No FreightItem with FreightItemID '{0}' was found.", request.FreightItemID));

            return freightItem.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem Post(SalesOrderHistoryFreightItemsPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            // Add the freight item. Need to jump through a few hoops as we want to know the Freightitemid so we can return that in the response header.	
            var freightItems = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem&gt;();
            freightItems.Add(request);
            string freightItemID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaSales.SalesOrder.FreightItem&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                freightItemID = item.RecID;
                history.Carrier.FreightItemCollection.Added -= addedHandler; // remove handler						
            };

            history.Carrier.FreightItemCollection.Added += addedHandler;
            history.Carrier.FreightItemCollection.DTO_Deserialise(freightItems);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.FreightItem freightItem = history.Carrier.FreightItemCollection.GetItem("RecID", freightItemID);

            if (freightItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No freightItem with freightItemID '{0}' was found.", freightItemID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], freightItem.RecID));

            return freightItem.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderFreightItem Patch(SalesOrderHistoryFreightItemsPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.FreightItem freightItem = history.Carrier.FreightItemCollection.GetItem("RecID", request.FreightItemID);

            if (freightItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No FreightItem with FreightItemID '{0}' was found.", request.FreightItemID));

            freightItem.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);

                history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

                if (history == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

                freightItem = history.Carrier.FreightItemCollection.GetItem("RecID", request.FreightItemID);

                if (freightItem == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No FreightItem with FreightItemID '{0}' was found.", request.FreightItemID));
            }

            return freightItem.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderHistoryFreightItemsDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.FreightItem freightItem = history.Carrier.FreightItemCollection.GetItem("RecID", request.FreightItemID);

            if (freightItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No FreightItem with FreightItemID '{0}' was found.", request.FreightItemID));

            history.Carrier.FreightItemCollection.Remove(freightItem);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "History Custom Fields"
    #region "Requests"	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderHistoryCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryCustomFieldValuesGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesOrder History with the InvoiceID or HistoryID provided was found")]
    public class SalesOrderHistoryCustomFieldValuesPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }

    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderHistoryCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(SalesOrderHistoryCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, null, null);
            return salesOrder.HistoryCustomSettings.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(SalesOrderHistoryCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            return history.CustomSettingValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(SalesOrderHistoryCustomFieldValuesGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = history.CustomSettingValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(SalesOrderHistoryCustomFieldValuesPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (i, m, s) =&gt;
                {
                    i.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.InvoiceID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = history.CustomSettingValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);

                history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

                if (history == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

                customFieldValue = history.CustomSettingValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Line Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderLineCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line InvoiceID, InvoiceHistoryID or InvoiceLineID provided was found")]
    public class SalesOrderLineCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderLineCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string FieldID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line Custom Field Value with the InvoiceID, InvoiceHistoryID, InvoiceLineID or SettingID provided was found")]
    public class SalesOrderLineCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line Custom Field Value with the InvoiceID, InvoiceHistoryID, InvoiceLineID or SettingID provided was found")]
    public class SalesOrderLineCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderLineCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(SalesOrderLineCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            return salesOrderLine.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(SalesOrderLineCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in salesOrderLine.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(SalesOrderLineCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine soLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (soLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = soLine.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);

                soLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);
                customFieldValue = soLine.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(SalesOrderLineCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, null, null);
            return salesOrder.LineCustomFields.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Line Details"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID or InvoiceLineID provided was found")]
    public class SalesOrderLineDetailsGETManyRequest : IReturn&lt;List&lt;JiwaServiceModel.SalesOrders.SalesOrderLineDetail&gt;&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID or InvoiceLineID or DetailsLineID provided was found")]
    public class SalesOrderLineDetailGETRequest : IReturn&lt;JiwaServiceModel.SalesOrders.SalesOrderLineDetail&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
        public string DetailsLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID or  InvoiceLineID provided was found")]
    public class SalesOrderLineDetailPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLineDetail&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID or  InvoiceLineID provided was found")]
    public class SalesOrderLineDetailPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLineDetail&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
        public string DetailsLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID or  InvoiceLineID or DetailsLineID provided was found")]
    public class SalesOrderLineDetailDELETERequest
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
        public string DetailsLineID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderLineDetailServices : Service
    {
        [Authenticate]
        public List&lt;JiwaServiceModel.SalesOrders.SalesOrderLineDetail&gt; Get(SalesOrderLineDetailsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            return salesOrderLine.LineDetails.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.SalesOrders.SalesOrderLineDetail Get(SalesOrderLineDetailGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.LineDetail salesOrderLineDetail = salesOrderLine.LineDetails.GetItem("RecID", request.DetailsLineID);

            if (salesOrderLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line detail with DetailsLineID '{0}' was found.", request.DetailsLineID));

            return salesOrderLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.SalesOrders.SalesOrderLineDetail Post(SalesOrderLineDetailPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            // Add the line detail. Need to jump through a few hoops as we want to know the DetailsLineID so we can return that in the response header.	
            var lineDetails = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLineDetail&gt;();
            lineDetails.Add(request);
            string lineDetailID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaSales.SalesOrder.LineDetail&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                lineDetailID = item.RecID;
                salesOrderLine.LineDetails.Added -= addedHandler; // remove handler						
            };

            salesOrderLine.LineDetails.Added += addedHandler;
            salesOrderLine.LineDetails.DTO_Deserialise(lineDetails);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.LineDetail salesOrderLineDetail = salesOrderLine.LineDetails.GetItem("RecID", lineDetailID);

            if (salesOrderLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line detail with DetailsLineID '{0}' was found.", lineDetailID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], salesOrderLineDetail.RecID));

            return salesOrderLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.SalesOrders.SalesOrderLineDetail Patch(SalesOrderLineDetailPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.LineDetail salesOrderLineDetail = salesOrderLine.LineDetails.GetItem("RecID", request.DetailsLineID);

            if (salesOrderLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line detail with DetailsLineID '{0}' was found.", request.DetailsLineID));

            salesOrderLineDetail.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            salesOrderLineDetail = salesOrderLine.LineDetails.GetItem("RecID", request.DetailsLineID);

            if (salesOrderLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line detail with DetailsLineID '{0}' was found.", request.DetailsLineID));

            return salesOrderLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderLineDetailDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.LineDetail salesOrderLineDetail = salesOrderLine.LineDetails.GetItem("RecID", request.DetailsLineID);

            if (salesOrderLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line detail with DetailsLineID '{0}' was found.", request.DetailsLineID));

            salesOrderLine.LineDetails.Remove(salesOrderLineDetail);
            salesOrderLine.ReAdjustDelivered(salesOrderLine.QuantityThisDelivery);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line with the InvoiceID or InvoiceLineID provided was found")]
    public class SalesOrderLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line with the InvoiceID or InvoiceLineID provided was found")]
    public class SalesOrderLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine&gt;&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line with the InvoiceID or InvoiceLineID provided was found")]
    public class SalesOrderLinePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string InvoiceLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line with the InvoiceID or InvoiceLineID provided was found")]
    public class SalesOrderLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public override string InvoiceLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Line with the InvoiceID or InvoiceLineID provided was found")]
    public class SalesOrderLineDELETERequest
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        public string InvoiceLineID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine Get(SalesOrderLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            return salesOrderLine.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine&gt; Get(SalesOrderLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            return salesOrder.SalesOrderLines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine Post(SalesOrderLinePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            // Add the line. Need to jump through a few hoops as we want to know the invoicelineid so we can return that in the response header.	
            var lines = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine&gt;();
            lines.Add(request);
            string invoiceLineID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaSales.SalesOrder.SalesOrderLine&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                invoiceLineID = item.RecID;
                salesOrder.SalesOrderLines.Added -= addedHandler; // remove handler						
            };

            salesOrder.SalesOrderLines.Added += addedHandler;
            salesOrder.SalesOrderLines.DTO_Deserialise(lines);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", invoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", invoiceLineID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], salesOrderLine.RecID));

            return salesOrderLine.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderLine Patch(SalesOrderLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            salesOrderLine.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            return salesOrderLine.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderLineDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            if (salesOrder.SalesOrderHistorys[salesOrder.SelectedHistoryNo].RecID != request.InvoiceHistoryID)
                salesOrder.SelectedHistoryNo = history.HistoryNo;

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderLine salesOrderLine = salesOrder.SalesOrderLines.GetItem("RecID", request.InvoiceLineID);

            if (salesOrderLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order line with InvoiceLineID '{0}' was found.", request.InvoiceLineID));

            salesOrder.SalesOrderLines.Remove(salesOrderLine);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Note Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Note Type with the NoteTypeID provided was found")]
    public class SalesOrderNoteTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderNoteTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderNoteTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Note Type with the NoteTypeID provided was found")]
    public class SalesOrderNoteTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Note Type with the NoteTypeID provided was found")]
    public class SalesOrderNoteTypeDELETERequest
    {
        public string NoteTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderNoteTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Get(SalesOrderNoteTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
                    n.Read();
                });

            JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt; Get(SalesOrderNoteTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
                    n.Read();
                });

            return noteTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Post(SalesOrderNoteTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
                    n.Read();
                });

            // Add the note type. Need to jump through a few hoops as we want to know the NoteTypeID so we can return that in the response header.	
            var dtoNoteTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;();
            dtoNoteTypes.Add(request);
            string noteTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaNoteTypes.NoteType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteTypeID = item.RecID;
                noteTypes.Added -= addedHandler; // remove handler						
            };

            noteTypes.Added += addedHandler;
            noteTypes.DTO_Deserialise(dtoNoteTypes);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", noteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", noteTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], noteType.RecID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Patch(SalesOrderNoteTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderNoteTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteTypes.Remove(noteType);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order Note with the InvoiceID or NoteID provided was found")]
    public class SalesOrderNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string InvoiceID { get; set; }
        public string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string InvoiceID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string InvoiceID { get; set; }
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Order with the InvoiceID provided was found")]
    public class SalesOrderNoteDELETERequest
    {
        public string InvoiceID { get; set; }
        public string NoteID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Get(SalesOrderNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt; Get(SalesOrderNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            return so.Notes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Post(SalesOrderNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            // Add the note. Need to jump through a few hoops as we want to know the NoteID so we can return that in the response header.	
            var notes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;();
            notes.Add(request);
            string noteID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Notes.Note&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteID = item.RecID;
                so.Notes.Added -= addedHandler; // remove handler						
            };

            so.Notes.Added += addedHandler;
            so.Notes.DTO_Deserialise(notes);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.InvoiceID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", noteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", noteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], note.RecID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Patch(SalesOrderNotePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note with NoteID '{0}' was found.", request.NoteID));

            note.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.InvoiceID);
            }

            note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales order note with NoteID '{0}' was found.", request.NoteID));

            so.Notes.Remove(note);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.InvoiceID);
            }
        }
    }
    #endregion
    #endregion

    #region "Payment Types"
    #region "Requests"		
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderPaymentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No payment type with PaymentTypeID provided was found")]
    public class SalesOrderPaymentTypesGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt;
    {
        public string PaymentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderPaymentTypesPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PaymentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No payment type with PaymentTypeID provided was found")]
    public class SalesOrderPaymentTypesPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt;
    {
        public override string PaymentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No payment type with PaymentTypeID provided was found")]
    public class SalesOrderPaymentTypesDELETERequest
    {
        public string PaymentTypeID { get; set; }
    }

    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderPaymentTypeServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt; Get(SalesOrderPaymentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection paymentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType, JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection", p);
                    }
                });

            return paymentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType Get(SalesOrderPaymentTypesGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection paymentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType, JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection", p);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType paymentType = paymentTypes.GetItem("RecID", request.PaymentTypeID);

            if (paymentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment type with PaymentTypeID '{0}' was found.", request.PaymentTypeID));

            return paymentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType Post(SalesOrderPaymentTypesPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection paymentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType, JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection", p);
                    }
                });

            // Add the payment type. Need to jump through a few hoops as we want to know the PaymentTypeID so we can return that in the response header.	
            var dtoPaymentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType&gt;();
            dtoPaymentTypes.Add(request);
            string paymentTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaSales.Configuration.PaymentTypes.PaymentType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                paymentTypeID = item.RecID;
                paymentTypes.Added -= addedHandler; // remove handler						
            };

            paymentTypes.Added += addedHandler;
            paymentTypes.DTO_Deserialise(dtoPaymentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                paymentTypes.Save();
                paymentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType paymentType = paymentTypes.GetItem("RecID", paymentTypeID);

            if (paymentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment type with PaymentTypeID '{0}' was found.", request.PaymentTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], paymentType.RecID));

            return paymentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.PaymentType Patch(SalesOrderPaymentTypesPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection paymentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType, JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection", p);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType paymentType = paymentTypes.GetItem("RecID", request.PaymentTypeID);

            if (paymentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment type with PaymentTypeID '{0}' was found.", request.PaymentTypeID));

            paymentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                paymentTypes.Save();
                paymentTypes.Read();

                paymentType = paymentTypes.GetItem("RecID", request.PaymentTypeID);

                if (paymentType == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment type with PaymentTypeID '{0}' was found.", request.PaymentTypeID));
            }

            return paymentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderPaymentTypesDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection paymentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType, JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection",
                (p, m, s) =&gt;
                {
                    p.Read();
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection", p);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentType paymentType = paymentTypes.GetItem("RecID", request.PaymentTypeID);

            if (paymentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment type with PaymentTypeID '{0}' was found.", request.PaymentTypeID));

            paymentTypes.Remove(paymentType);

            if (!Helper.Service.IsStateful(this))
            {
                paymentTypes.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Payments"
    #region "Requests"		
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderPaymentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment&gt;&gt;
    {
        public string InvoiceID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No payment with PaymentID or InvoiceID provided was found")]
    public class SalesOrderPaymentsGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment&gt;
    {
        public string InvoiceID { get; set; }
        public string PaymentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesOrderPaymentsPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment&gt;
    {
        public string InvoiceID { get; set; }
        public string InvoiceHistoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PaymentID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override int? HistoryNo { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No payment with PaymentID or InvoiceID provided was found")]
    public class SalesOrderPaymentsPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment&gt;
    {
        public string InvoiceID { get; set; }
        public override string PaymentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No payment with PaymentID or InvoiceID  provided was found")]
    public class SalesOrderPaymentsDELETERequest
    {
        public string InvoiceID { get; set; }
        public string PaymentID { get; set; }
    }

    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesOrderPaymentServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment&gt; Get(SalesOrderPaymentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            return salesOrder.SalesOrderPayments.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment Get(SalesOrderPaymentsGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.Payment payment = salesOrder.SalesOrderPayments.GetItem("RecID", request.PaymentID);

            if (payment == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment with PaymentID '{0}' was found.", request.PaymentID));

            return payment.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment Post(SalesOrderPaymentsPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            // Set the History no based on the provided InvoiceHistoryID
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrderHistory history = salesOrder.SalesOrderHistorys.GetItem("RecID", request.InvoiceHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.InvoiceHistoryID));

            request.HistoryNo = history.HistoryNo;

            // Add the payment. Need to jump through a few hoops as we want to know the PaymentID so we can return that in the response header.	
            var dtoPayments = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment&gt;();
            dtoPayments.Add(request);
            string paymentID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaSales.SalesOrder.Payment&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                paymentID = item.RecID;
                salesOrder.SalesOrderPayments.Added -= addedHandler; // remove handler						
            };

            salesOrder.SalesOrderPayments.Added += addedHandler;
            salesOrder.SalesOrderPayments.DTO_Deserialise(dtoPayments);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);
            }

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.Payment payment = salesOrder.SalesOrderPayments.GetItem("RecID", paymentID);

            if (payment == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment with PaymentType '{0}' was found.", paymentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], payment.RecID));

            return payment.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesOrders.SalesOrderPayment Patch(SalesOrderPaymentsPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.Payment payment = salesOrder.SalesOrderPayments.GetItem("RecID", request.PaymentID);

            if (payment == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment with PaymentType '{0}' was found.", request.PaymentID));

            payment.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
                salesOrder.Read(salesOrder.InvoiceID);

                payment = salesOrder.SalesOrderPayments.GetItem("RecID", request.PaymentID);

                if (payment == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment with PaymentType '{0}' was found.", request.PaymentID));
            }

            return payment.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesOrderPaymentsDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesOrder.SalesOrder&gt;(manager, this, request.InvoiceID,
                (o, m, s) =&gt;
                {
                    o.Read(request.InvoiceID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.InvoiceID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.Payment payment = salesOrder.SalesOrderPayments.GetItem("RecID", request.PaymentID);

            if (payment == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No payment with PaymentType '{0}' was found.", request.PaymentID));

            salesOrder.SalesOrderPayments.Remove(payment);

            if (!Helper.Service.IsStateful(this))
            {
                salesOrder.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Sales Quotes"
    #region "{main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string QuoteID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote&gt;
    {
        override public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteMAKEORDERRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteMAKEORDERB2BRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteABANDONRequest
    {
        public string QuoteID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote Get(SalesQuoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });
            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote Post(SalesQuotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(null);
            so.DTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(so.QuoteID, so);
            else
            {
                so.Save();
                so.Read(so.QuoteID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], so.QuoteID));

            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote Patch(SalesQuotePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            so.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.QuoteID);
            }

            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote Get(SalesQuoteSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.QuoteID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful sales Quote exists with QuoteID '{0}'", request.QuoteID));
            }

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = (JiwaSales.SalesQuote.SalesQuote)objectDictionaryValue;
            so.Save();

            return so.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote Post(SalesQuoteMAKEORDERRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote qo = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(null);
            qo.Read(request.QuoteID);

            //make order
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = qo.MakeOrder(JiwaSales.SalesOrder.SalesOrder.SalesOrderTypes.e_SalesOrderNormalSalesOrder);

            qo.Read(qo.QuoteID);

            // Add the location to the response header												
            base.Response.AddHeader("Location", String.Format("{0}/{1}/{2}", HostContext.AppHost.Config.WebHostUrl, "SalesOrders", salesOrder.RecID));
            return qo.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuote Post(SalesQuoteMAKEORDERB2BRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote qo = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(null);
            qo.Read(request.QuoteID);

            //make order
            JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder salesOrder = qo.MakeOrder(JiwaSales.SalesOrder.SalesOrder.SalesOrderTypes.e_SalesOrderBackToBack);

            qo.Read(qo.QuoteID);

            // Add the location to the response header						
            base.Response.AddHeader("Location", String.Format("{0}/{1}/{2}", HostContext.AppHost.Config.WebHostUrl, "SalesOrders", salesOrder.RecID));
            return qo.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesQuoteABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.QuoteID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful sales Quote exists with QuoteID '{0}'", request.QuoteID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.QuoteID);
        }
    }
    #endregion
    #endregion

    #region "Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuoteCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No custom field with the SettingID provided was found")]
    public class SalesQuoteCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }

    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Custom Field Value with the QuoteID or SettingID provided was found")]
    public class SalesQuoteCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string QuoteID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Custom Field Value with the QuoteID or SettingID provided was found")]
    public class SalesQuoteCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string QuoteID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(SalesQuoteCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            return salesQuote.CustomSettingValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(SalesQuoteCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            var salesQuoteCustomFieldValue = so.CustomSettingValues.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (salesQuoteCustomFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return salesQuoteCustomFieldValue;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(SalesQuoteCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = salesQuote.CustomSettingValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesQuote.Save();
                salesQuote.Read(salesQuote.QuoteID);
            }

            customFieldValue = salesQuote.CustomSettingValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(SalesQuoteCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, null, null);

            return salesQuote.CustomSettings.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Document Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote document type with the DocumentTypeID provided was found")]
    public class SalesQuoteDocumentTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuoteDocumentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuoteDocumentTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote document type with the DocumentTypeID provided was found")]
    public class SalesQuoteDocumentTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote document type with the DocumentTypeID provided was found")]
    public class SalesQuoteDocumentTypeDELETERequest
    {
        public string DocumentTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteDocumentTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Get(SalesQuoteDocumentTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
					d.DocumentTableNames.Add("QO_Documents");					
                    d.Read();
                });

            JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt; Get(SalesQuoteDocumentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
					d.DocumentTableNames.Add("QO_Documents");					
                    d.Read();
                });

            return documentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Post(SalesQuoteDocumentTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
					d.DocumentTableNames.Add("QO_Documents");					
                    d.Read();
                });

            // Add the document type. Need to jump through a few hoops as we want to know the DocumentTypeID so we can return that in the response header.	
            var dtoDocumentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;();
            dtoDocumentTypes.Add(request);
            string documentTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaDocumentTypes.DocumentType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentTypeID = item.RecID;
                documentTypes.Added -= addedHandler; // remove handler						
            };

            documentTypes.Added += addedHandler;
            documentTypes.DTO_Deserialise(dtoDocumentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", documentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", documentTypeID));

            // Add the location to the response header						
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0].Split(new[] { '?' })[0], documentType.RecID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Patch(SalesQuoteDocumentTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
					d.DocumentTableNames.Add("QO_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesQuoteDocumentTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
					d.DocumentTableNames.Add("QO_Documents");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentTypes.Remove(documentType);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Documents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote Document with the QuoteID or DocumentID provided was found")]
    public class SalesQuoteDocumentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string QuoteID { get; set; }
        public string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote with the QuoteID provided was found")]
    public class SalesQuoteDocumentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote with the QuoteID provided was found")]
    public class SalesQuoteDocumentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string QuoteID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote with the QuoteID provided was found")]
    public class SalesQuoteDocumentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string QuoteID { get; set; }
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote with the QuoteID provided was found")]
    public class SalesQuoteDocumentDELETERequest
    {
        public string QuoteID { get; set; }
        public string DocumentID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteDocumentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Get(SalesQuoteDocumentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (d, m, s) =&gt;
                {
                    d.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.QuoteID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = salesQuote.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt; Get(SalesQuoteDocumentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote SalesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (d, m, s) =&gt;
                {
                    d.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.QuoteID, d);
                    }
                });

            return SalesQuote.Documents.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Post(SalesQuoteDocumentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote SalesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (d, m, s) =&gt;
                {
                    d.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.QuoteID, d);
                    }
                });

            // Add the document. Need to jump through a few hoops as we want to know the DocumentID so we can return that in the response header.	
            var documents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;();
            documents.Add(request);
            string documentID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Documents.Document&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentID = item.RecID;
                SalesQuote.Documents.Added -= addedHandler; // remove handler						
            };

            SalesQuote.Documents.Added += addedHandler;
            SalesQuote.Documents.DTO_Deserialise(documents);

            if (!Helper.Service.IsStateful(this))
            {
                SalesQuote.Save();
                SalesQuote.Read(SalesQuote.QuoteID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = SalesQuote.Documents.GetItem("RecID", documentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", documentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], document.RecID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Patch(SalesQuoteDocumentPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote SalesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (d, m, s) =&gt;
                {
                    d.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.QuoteID, d);
                    }
                });

            JiwaApplication.Documents.Document document = SalesQuote.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote document with DocumentID '{0}' was found.", request.DocumentID));

            document.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                SalesQuote.Save();
                SalesQuote.Read(SalesQuote.QuoteID);
            }

            document = SalesQuote.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesQuoteDocumentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote SalesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (d, m, s) =&gt;
                {
                    d.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.QuoteID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = SalesQuote.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote document with DocumentID '{0}' was found.", request.DocumentID));

            SalesQuote.Documents.Remove(document);

            if (!Helper.Service.IsStateful(this))
            {
                SalesQuote.Save();
                SalesQuote.Read(SalesQuote.QuoteID);
            }
        }
    }
    #endregion
    #endregion

    #region "History"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote History with the QuoteID or HistoryID provided was found")]
    public class SalesQuoteHistorysGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteHistory&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote with the QuoteID provided was found")]
    public class SalesQuoteHistorysGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteHistory&gt;&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No SalesQuote with the QuoteID, Or QuoteHistoryID provided was found")]
    public class SalesQuoteHistorysPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteHistory, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteHistory&gt;
    {
        public string QuoteID { get; set; }
        override public string QuoteHistoryID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteHistoryServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteHistory Get(SalesQuoteHistorysGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (i, m, s) =&gt;
                {
                    i.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.QuoteID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            return history.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteHistory&gt; Get(SalesQuoteHistorysGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (i, m, s) =&gt;
                {
                    i.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.QuoteID, i);
                    }
                });

            return salesQuote.SalesQuoteHistorys.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteHistory Patch(SalesQuoteHistorysPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (i, m, s) =&gt;
                {
                    i.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.QuoteID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            history.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesQuote.Save();
                salesQuote.Read(salesQuote.QuoteID);

                history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

                if (history == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));
            }

            return history.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Line Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuoteLineCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line QuoteID, QuoteHistoryID or QuoteLineID provided was found")]
    public class SalesQuoteLineCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
        public string QuoteLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuoteLineCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string FieldID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line Custom Field Value with the QuoteID, QuoteHistoryID, QuoteLineID or SettingID provided was found")]
    public class SalesQuoteLineCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
        public string QuoteLineID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line Custom Field Value with the QuoteID, QuoteHistoryID, QuoteLineID or SettingID provided was found")]
    public class SalesQuoteLineCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
        public string QuoteLineID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteLineCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(SalesQuoteLineCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteLine salesQuoteLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);

            if (salesQuoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", request.QuoteLineID));

            return salesQuoteLine.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(SalesQuoteLineCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteLine salesQuoteLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);

            if (salesQuoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", request.QuoteLineID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in salesQuoteLine.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(SalesQuoteLineCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteLine soLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);

            if (soLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", request.QuoteLineID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = soLine.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesQuote.Save();
                salesQuote.Read(salesQuote.QuoteID);

                soLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);
                customFieldValue = soLine.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No CustomFieldValue with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(SalesQuoteLineCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, null, null);
            return salesQuote.LineCustomFields.DTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line with the QuoteID or QuoteLineID provided was found")]
    public class SalesQuoteLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
        public string QuoteLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line with the QuoteID or QuoteLineID provided was found")]
    public class SalesQuoteLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine&gt;&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line with the QuoteID or QuoteLineID provided was found")]
    public class SalesQuoteLinePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string QuoteLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line with the QuoteID or QuoteLineID provided was found")]
    public class SalesQuoteLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine&gt;
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
        public override string QuoteLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Line with the QuoteID or QuoteLineID provided was found")]
    public class SalesQuoteLineDELETERequest
    {
        public string QuoteID { get; set; }
        public string QuoteHistoryID { get; set; }
        public string QuoteLineID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine Get(SalesQuoteLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteLine salesQuoteLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);

            if (salesQuoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", request.QuoteLineID));

            return salesQuoteLine.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine&gt; Get(SalesQuoteLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            return salesQuote.SalesQuoteLines.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine Post(SalesQuoteLinePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            // Add the line. Need to jump through a few hoops as we want to know the Quotelineid so we can return that in the response header.	
            var lines = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine&gt;();
            lines.Add(request);
            string QuoteLineID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaSales.SalesQuote.SalesQuoteLine&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                QuoteLineID = item.RecID;
                salesQuote.SalesQuoteLines.Added -= addedHandler; // remove handler						
            };

            salesQuote.SalesQuoteLines.Added += addedHandler;
            salesQuote.SalesQuoteLines.DTO_Deserialise(lines);

            if (!Helper.Service.IsStateful(this))
            {
                salesQuote.Save();
                salesQuote.Read(salesQuote.QuoteID);
            }

            history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteLine salesQuoteLine = salesQuote.SalesQuoteLines.GetItem("RecID", QuoteLineID);

            if (salesQuoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", QuoteLineID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], salesQuoteLine.RecID));

            return salesQuoteLine.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.SalesQuotes.SalesQuoteLine Patch(SalesQuoteLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteLine salesQuoteLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);

            if (salesQuoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", request.QuoteLineID));

            salesQuoteLine.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                salesQuote.Save();
                salesQuote.Read(salesQuote.QuoteID);
            }

            history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            salesQuoteLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);

            if (salesQuoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", request.QuoteLineID));

            return salesQuoteLine.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesQuoteLineDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote salesQuote = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteHistory history = salesQuote.SalesQuoteHistorys.GetItem("RecID", request.QuoteHistoryID);

            if (history == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No history with HistoryID '{0}' was found.", request.QuoteHistoryID));

            if (salesQuote.SalesQuoteHistorys[salesQuote.SelectedHistoryNo].RecID != request.QuoteHistoryID)
                salesQuote.SelectedHistoryNo = (short)(history.HistoryNo);

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuoteLine salesQuoteLine = salesQuote.SalesQuoteLines.GetItem("RecID", request.QuoteLineID);

            if (salesQuoteLine == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote line with QuoteLineID '{0}' was found.", request.QuoteLineID));

            salesQuote.SalesQuoteLines.Remove(salesQuoteLine);

            if (!Helper.Service.IsStateful(this))
            {
                salesQuote.Save();
            }
        }
    }
    #endregion
    #endregion

    #region "Note Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Note Type with the NoteTypeID provided was found")]
    public class SalesQuoteNoteTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuoteNoteTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SalesQuoteNoteTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Note Type with the NoteTypeID provided was found")]
    public class SalesQuoteNoteTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Note Type with the NoteTypeID provided was found")]
    public class SalesQuoteNoteTypeDELETERequest
    {
        public string NoteTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteNoteTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Get(SalesQuoteNoteTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
                    n.Read();
                });

            JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt; Get(SalesQuoteNoteTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
                    n.Read();
                });

            return noteTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Post(SalesQuoteNoteTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
                    n.Read();
                });

            // Add the note type. Need to jump through a few hoops as we want to know the NoteTypeID so we can return that in the response header.	
            var dtoNoteTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;();
            dtoNoteTypes.Add(request);
            string noteTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaNoteTypes.NoteType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteTypeID = item.RecID;
                noteTypes.Added -= addedHandler; // remove handler						
            };

            noteTypes.Added += addedHandler;
            noteTypes.DTO_Deserialise(dtoNoteTypes);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", noteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", noteTypeID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], noteType.RecID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Patch(SalesQuoteNoteTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesQuoteNoteTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote",
                (n, m, s) =&gt;
                {
                    n.NoteType = "JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote";
                    n.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteTypes.Remove(noteType);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote Note with the QuoteID or NoteID provided was found")]
    public class SalesQuoteNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string QuoteID { get; set; }
        public string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;&gt;
    {
        public string QuoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string QuoteID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string QuoteID { get; set; }
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Sales Quote with the QuoteID provided was found")]
    public class SalesQuoteNoteDELETERequest
    {
        public string QuoteID { get; set; }
        public string NoteID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SalesQuoteNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Get(SalesQuoteNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt; Get(SalesQuoteNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            return so.Notes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Post(SalesQuoteNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            // Add the note. Need to jump through a few hoops as we want to know the NoteID so we can return that in the response header.	
            var notes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;();
            notes.Add(request);
            string noteID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Notes.Note&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteID = item.RecID;
                so.Notes.Added -= addedHandler; // remove handler						
            };

            so.Notes.Added += addedHandler;
            so.Notes.DTO_Deserialise(notes);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.QuoteID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", noteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", noteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], note.RecID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Patch(SalesQuoteNotePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote note with NoteID '{0}' was found.", request.NoteID));

            note.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.QuoteID);
            }

            note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(SalesQuoteNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote so = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaSales.SalesQuote.SalesQuote&gt;(manager, this, request.QuoteID,
                (o, m, s) =&gt;
                {
                    o.Read(request.QuoteID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.QuoteID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = so.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No sales Quote note with NoteID '{0}' was found.", request.NoteID));

            so.Notes.Remove(note);

            if (!Helper.Service.IsStateful(this))
            {
                so.Save();
                so.Read(so.QuoteID);
            }
        }
    }
    #endregion
    #endregion

    #endregion

    #region "Service Control"
    #region "Requests"
	[Serializable()]
    [ApiResponse(204, "Stop request sent OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class StopRequest
    {
    }

	[Serializable()]
    [ApiResponse(204, "Restart request sent OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class RestartRequest
    {
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class ServiceControlServices : Service
    {
        [Authenticate]
        public void Get(StopRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.Security.UserGroup.AccessLevels permission = manager.Staff.GetAbstractPermission("JiwaFinancials.Jiwa.JiwaPluginMaintenanceUI.frmMain", "APIRestart");
            if (permission != JiwaFinancials.Jiwa.JiwaApplication.Security.UserGroup.AccessLevels.Allow)
            {
                throw new UnauthorizedAccessException();
            }
            // because we can't restart a service inside itself, we simply do a STOP instead.
            // If you configure the service to restart after failure, then once we exit, the OS will restart the service for you.
            Environment.Exit(1);
        }

        [Authenticate]
        public void Get(RestartRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.Security.UserGroup.AccessLevels permission = manager.Staff.GetAbstractPermission("JiwaFinancials.Jiwa.JiwaPluginMaintenanceUI.frmMain", "APIRestart");
            if (permission != JiwaFinancials.Jiwa.JiwaApplication.Security.UserGroup.AccessLevels.Allow)
            {
                throw new UnauthorizedAccessException();
            }
            System.Web.HttpRuntime.UnloadAppDomain();
        }
    }
    #endregion
    #endregion

    #region "Staff"	
    #region "Requests"
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    public class AuthUserSessionsGETRequest : IReturn&lt;List&lt;AuthUserSession&gt;&gt;
    {
    }		
	
	public class ManagerInstance
	{
		virtual public string SessionId { get; set; }
		virtual public string StaffUsername { get; set; }
	}
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    public class ManagerInstancesGETRequest : IReturn&lt;List&lt;ManagerInstance&gt;&gt;
    {
    }	
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class StaffCurrentUserGETRequest : IReturn&lt;StaffCurrentUserGETResponse&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class StaffCurrentUserListGETRequest : IReturn&lt;List&lt;StaffCurrentUserGETResponse&gt;&gt;
    {
    }
    #endregion

    #region "Responses"
	[Serializable()]
    public class StaffCurrentUserGETResponse
    {
        public string SessionID { get; set; }
        public string IPAddress { get; set; }
        public string StaffID { get; set; }
        public string Username { get; set; }
        public DateTime LoginDateTime { get; set; }
        public int DurationDays { get; set; }
        public int DurationHours { get; set; }
        public int DurationMinutes { get; set; }
        public int DurationSeconds { get; set; }
        public long RequestCount { get; set; }
        public long ConcurrentRequestCount { get; set; }
        public long MaxConcurrentRequestCount { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class StaffServices : Service
    {
		public List&lt;AuthUserSession&gt; Get (AuthUserSessionsGETRequest request)
		{
			List&lt;AuthUserSession&gt; sessions = new List&lt;AuthUserSession&gt;();
			
			ServiceStack.Caching.ICacheClient cache = HostContext.TryResolve&lt;ServiceStack.Caching.ICacheClient&gt;();
			
            var sessionKeys = cache.GetKeysStartingWith("urn:iauthsession:").ToList();		// Credential auth cached sessionIds
			sessionKeys.AddRange(cache.GetKeysStartingWith("key:sess:").ToList());			// API Key auth cached sessionIds
			
			var allSessions = cache.GetAll&lt;AuthUserSession&gt;(sessionKeys);
			
			foreach(string sessionKey in sessionKeys)
			{
				sessions.Add(cache.Get&lt;AuthUserSession&gt;(sessionKey));
			}
			
			return sessions;			
		}
		
		public List&lt;ManagerInstance&gt; Get (ManagerInstancesGETRequest request)
		{
			List&lt;ManagerInstance&gt; managerInstances = new List&lt;ManagerInstance&gt;();
			
			List&lt;string&gt; keys = RESTAPIPlugin.JiwaSessionDictionary.Keys.ToList();
			
			foreach(string key in keys)
			{
				ManagerInstance managerInstance = new ManagerInstance();
				managerInstance.SessionId = key;
				
				JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;			
				RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(key, out manager);
				
				if (manager != null)
				{
					if (manager.Staff != null)
					{						
						managerInstance.StaffUsername = manager.Staff.Username;
					}					
				}
				
				managerInstances.Add(managerInstance);
			}			
			
			return managerInstances;			
		}
			
        [Authenticate]
        public StaffCurrentUserGETResponse Get(StaffCurrentUserGETRequest request)
        {			
			AuthUserSession session = (AuthUserSession)this.GetSession();
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;			
			RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);
			
            TimeSpan span = DateTime.UtcNow - session.CreatedAt;
            return new StaffCurrentUserGETResponse { SessionID = session.Id, StaffID = manager.Staff.RecID, Username = manager.Staff.Username, LoginDateTime = session.CreatedAt, DurationDays = span.Days, DurationHours = span.Hours, DurationMinutes = span.Minutes, DurationSeconds = span.Seconds };
        }

        [Authenticate]
        public List&lt;StaffCurrentUserGETResponse&gt; Get(StaffCurrentUserListGETRequest request)
        {
            ServiceStack.Caching.ICacheClient cache = HostContext.TryResolve&lt;ServiceStack.Caching.ICacheClient&gt;();
            var sessionKeys = cache.GetKeysStartingWith("urn:iauthsession:").ToList();		// Credential auth cached sessionIds
			sessionKeys.AddRange(cache.GetKeysStartingWith("key:sess:").ToList());			// API Key auth cached sessionIds
			
			List&lt;StaffCurrentUserGETResponse&gt; users = new List&lt;StaffCurrentUserGETResponse&gt;();
			
			if (sessionKeys != null &amp;&amp; sessionKeys.Count &gt; 0)
			{
	            var allSessions = cache.GetAll&lt;AuthUserSession&gt;(sessionKeys);
	            
	            foreach (var sessionEntry in allSessions)
	            {
	                AuthUserSession session = sessionEntry.Value;
	                if (session != null)
	                {
						JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;			
					    RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(session.Id, out manager);
						
	                    StaffCurrentUserGETResponse staffSessionInfo = new StaffCurrentUserGETResponse();
	                    staffSessionInfo.SessionID = session.Id;                    

	                    if (manager != null &amp;&amp; manager.Staff != null)
	                    {
	                        staffSessionInfo.StaffID = manager.Staff.RecID;
	                        staffSessionInfo.Username = manager.Staff.Username;
	                    }

	                    staffSessionInfo.LoginDateTime = session.CreatedAt;

	                    TimeSpan span = DateTime.UtcNow - session.CreatedAt.ToUniversalTime();
	                    staffSessionInfo.DurationDays = span.Days;
	                    staffSessionInfo.DurationHours = span.Hours;
	                    staffSessionInfo.DurationMinutes = span.Minutes;
	                    staffSessionInfo.DurationSeconds = span.Seconds;
	                                       
	                    users.Add(staffSessionInfo);
	                }
	            }
			}
            return users.OrderBy(user =&gt; user.LoginDateTime).ToList();
        }
    }

    #endregion
    #endregion
	
	#region "Startup Diagnostics"        
    #region "Requests"    
    public class StartupLogEntryQuery : QueryData&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.StartupLogEntry&gt; { }
    public class PluginExceptionQuery : QueryData&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.PluginException&gt; { }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class StartupDiagnosticsServices : Service
    {
        public IAutoQueryData AutoQuery { get; set; }

        [Authenticate]
        public object Get(StartupLogEntryQuery query)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            var q = AutoQuery.CreateQuery(query, Request, db: new MemoryDataSource&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.StartupLogEntry&gt;(manager.StartupLog, query, Request));
            return AutoQuery.Execute(query, q);
        }

        [Authenticate]
        public object Get(PluginExceptionQuery query)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            var q = AutoQuery.CreateQuery(query, Request, db: new MemoryDataSource&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Startup.Diagnostics.PluginException&gt;(manager.PluginExceptions, query, Request));
            return AutoQuery.Execute(query, q);
        }
    }
    #endregion

    #endregion

    #region "Stock Transfer"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Stock Transfer with the TransferID provided was found")]
    public class StockTransferGETRequest : IReturn&lt;JiwaServiceModel.StockTransfers.StockTransfer&gt;
    {
        public string TransferID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Stock Transfer with the Transfer No. provided was found")]
    public class StockTransferDELETERequest
    {
        public string TransferID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class StockTransferPOSTRequest : JiwaServiceModel.StockTransfers.StockTransfer, IReturn&lt;JiwaServiceModel.StockTransfers.StockTransfer&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string TransferID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class StockTransferServices : Service
    {
        [Authenticate]
        public JiwaServiceModel.StockTransfers.StockTransfer Get(StockTransferGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaStockTransfer.StockTransfer StockTransfer = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaStockTransfer.StockTransfer&gt;(null);
            StockTransfer.Read(request.TransferID);

            return StockTransfer.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.StockTransfers.StockTransfer Post(StockTransferPOSTRequest StockTransfer)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaStockTransfer.StockTransfer StockTransferObject = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaStockTransfer.StockTransfer&gt;(null);
            StockTransferObject.DTO_Deserialise(StockTransfer);
            StockTransferObject.Save();
            StockTransferObject.Read(StockTransferObject.RecID);

            return StockTransferObject.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(StockTransferDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaStockTransfer.StockTransfer StockTransfer = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaStockTransfer.StockTransfer&gt;(null);
            StockTransfer.Read(request.TransferID);

            StockTransfer.Delete();
        }
    }
    #endregion
    #endregion
    #endregion
	
	#region "Supplier Returns"
	#region "Shipping"
	#region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Supplier Return Credit with the RecID provided was found")]
    public class SupplierReturnShippingGETRequest : IReturn&lt;JiwaServiceModel.SupplierReturns.Shippings.Shipping&gt;
    {
        public string ShippingID { get; set; }
    }
	#endregion
	
	#region "Services"	
	[CompressResponse]
    public class SupplierReturnShippingServices : Service
    {
        [Authenticate]
        public JiwaServiceModel.SupplierReturns.Shippings.Shipping Get(SupplierReturnShippingGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSupplierReturns.Shipping.Shipping supplierReturnShipping = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSupplierReturns.Shipping.Shipping&gt;(null);
            supplierReturnShipping.Read(request.ShippingID);

            return supplierReturnShipping.DTO_Serialise();
        }
	}
	#endregion
	#endregion
	
	#region "Credits"
	
	#region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Supplier Return Credit with the RecID provided was found")]
    public class SupplierReturnCreditGETRequest : IReturn&lt;JiwaServiceModel.SupplierReturns.Credits.Credit&gt;
    {
        public string CreditID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SupplierReturnCreditCreateFromShipmentsRequest : IReturn&lt;JiwaServiceModel.SupplierReturns.Credits.Credit&gt;
    {        
        public string[] ShipmentIDs { get; set; }
		public string[] ShipmentNos { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No supplier return credit with the CreditID provided was found")]
    public class SupplierReturnCreditACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.SupplierReturns.Credits.Credit&gt;
    {
        public string CreditID { get; set; }
    }
	#endregion
	
	#region "Services"	
	[CompressResponse]
    public class SupplierReturnCreditServices : Service
    {
        [Authenticate]
        public JiwaServiceModel.SupplierReturns.Credits.Credit Get(SupplierReturnCreditGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaSupplierReturns.Credit.Credit supplierReturnCredit = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSupplierReturns.Credit.Credit&gt;(null);
            supplierReturnCredit.Read(request.CreditID);

            return supplierReturnCredit.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.SupplierReturns.Credits.Credit Post(SupplierReturnCreditCreateFromShipmentsRequest request)
        {			
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();            
			
			JiwaFinancials.Jiwa.JiwaSupplierReturns.Credit.Credit supplierReturnCredit = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSupplierReturns.Credit.Credit&gt;(null);			
			supplierReturnCredit.CreateNew();				
			JiwaFinancials.Jiwa.JiwaSupplierReturns.Entities.Shipping.Shipping shipment = manager.CollectionItemFactory.CreateCollectionItem&lt;JiwaFinancials.Jiwa.JiwaSupplierReturns.Entities.Shipping.Shipping&gt;();
						
			if (request.ShipmentIDs != null)
			{
				foreach(string shipmentID in request.ShipmentIDs)
				{
					try
					{
						shipment.ReadRecord(shipmentID);
					}
					catch (JiwaApplication.Exceptions.RecordNotFoundException ex)
					{
						throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No supplier return shipment with ID of '{0}' was found", shipmentID), ex);
					}
					
					if (supplierReturnCredit.Creditor.RecID.Trim().Length == 0)
					{
						supplierReturnCredit.Creditor.ReadRecord(shipment.Creditor.RecID);
					}
					
					supplierReturnCredit.Shippings.Add(shipment);
				}
			}
						
			if (request.ShipmentNos != null)
			{
				foreach(string shipmentNo in request.ShipmentNos)
				{
					try
					{
						shipment.ReadRecordFromShipmentNo(shipmentNo);
					}
					catch (JiwaApplication.Exceptions.RecordNotFoundException ex)
					{
						throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No supplier return shipment with shipment No. of '{0}' was found", shipmentNo), ex);
					}
					
					if (supplierReturnCredit.Creditor.RecID.Trim().Length == 0)
					{
						supplierReturnCredit.Creditor.ReadRecord(shipment.Creditor.RecID);
					}
					
					supplierReturnCredit.Shippings.Add(shipment);
				}
			}
			
			supplierReturnCredit.Save();
			supplierReturnCredit.Read(supplierReturnCredit.RecID);

            return supplierReturnCredit.DTO_Serialise();
        }
		
		[Authenticate]
        public JiwaServiceModel.SupplierReturns.Credits.Credit Post(SupplierReturnCreditACTIVATERequest request)
        {			
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();            
			
			JiwaFinancials.Jiwa.JiwaSupplierReturns.Credit.Credit supplierReturnCredit = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaSupplierReturns.Credit.Credit&gt;(null);			
			
			supplierReturnCredit.Read(request.CreditID);
			supplierReturnCredit.Status = JiwaFinancials.Jiwa.JiwaSupplierReturns.Credit.Credit.Statuses.Activated;
			supplierReturnCredit.Save();
			supplierReturnCredit.Read(supplierReturnCredit.RecID);
			
			return supplierReturnCredit.DTO_Serialise();
		}
	}
	#endregion
	
	#endregion
	#endregion

    #region "System Information"		
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class SystemInformationGETRequest : IReturn&lt;SystemInformationGETResponse&gt;
    {
    }
    #endregion

    #region "Responses"
	[Serializable()]
    public class SystemInformationGETResponse
    {
        public string JiwaVersion { get; set; }
        public DateTime SQLServerDateTime { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class SystemInformationServices : Service
    {
        [Authenticate]
        public SystemInformationGETResponse Get(SystemInformationGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            SystemInformationGETResponse response = new SystemInformationGETResponse();
            response.JiwaVersion = String.Format("{0}.{1}.{2}", manager.Database.JiwaVerMajor.ToString("D2"), manager.Database.JiwaVerMinor.ToString("D2"), manager.Database.JiwaVerRelease.ToString("D2"));
            response.SQLServerDateTime = Db.SqlScalar&lt;DateTime&gt;("SELECT GETDATE()");

            return response;
        }
    }
    #endregion
    #endregion

    #region "User Settings"
    #region "Models"
	[Serializable()]
    public class UserSetting : JiwaFinancials.Jiwa.JiwaServiceModel.Tables.SY_UserProfile
    {
        public string HR_StaffUsername { get; set; }
    }
    #endregion

    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class UserSettingPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.UserSettings.UserSetting
    {
    }
	
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class UserSettingsGETManyRequest : QueryDb&lt;SY_UserProfile&gt;
    {
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class UserSettingServices : Service
    {
        [Authenticate]
        public void Post(UserSettingPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            manager.JLib.SetProfileKey(manager.Staff.RecID, request.Section, request.IDKey, request.Contents);
        }

        public IAutoQueryDb AutoQuery { get; set; }

        [Authenticate]
        public object Get(UserSettingsGETManyRequest query)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            var q = AutoQuery.CreateQuery(query, base.Request).Where(String.Format("UserID = '{0}'", manager.Staff.RecID));

            return AutoQuery.Execute(query, q);
        }
    }
    #endregion
    #endregion

    #region "ServiceStack Plugins"
    public class CodeGenerationLinksPlugin : ServiceStack.IPlugin
    {
        public void Register(IAppHost appHost)
        {
            appHost.GetPlugin&lt;MetadataFeature&gt;().AddPluginLink("types/csharp", "Generate C#");
            appHost.GetPlugin&lt;MetadataFeature&gt;().AddPluginLink("types/vbnet", "Generate VB.NET");
            appHost.GetPlugin&lt;MetadataFeature&gt;().AddPluginLink("types/fsharp", "Generate F#");
            appHost.GetPlugin&lt;MetadataFeature&gt;().AddPluginLink("types/typescript", "Generate Typescript");
            appHost.GetPlugin&lt;MetadataFeature&gt;().AddPluginLink("types/java", "Generate Java");
            appHost.GetPlugin&lt;MetadataFeature&gt;().AddPluginLink("types/kotlin", "Generate Kotlin");
            appHost.GetPlugin&lt;MetadataFeature&gt;().AddPluginLink("types/swift", "Generate Swift");
        }
    }
    #endregion

    #region "Tax Rates"	
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No tax rate with the RecID provided was found")]
    public class TaxRateGETRequest : IReturn&lt;JiwaServiceModel.Tax.TaxRate&gt;
    {
        public string TaxID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class TaxRatePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string TaxID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No tax rate with the RecID provided was found")]
    public class TaxRatePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;
    {
        public override string TaxID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No tax rate with the RecID provided was found")]
    public class TaxRateDELETERequest
    {
        public string TaxID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No tax rate with the RecID provided was found")]
    public class TaxRateSAVERequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No tax rate with the RecID provided was found")]
    public class TaxRateABANDONRequest
    {
    }
    #endregion

    #region "Services"	
    [CompressResponse]
    public class TaxRateServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRate Get(TaxRateGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates taxRates = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates",
            (c, m, s) =&gt;
            {
                c.Read();
                if (Helper.Service.IsStateful(s))
                    m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates", c);
            });

            var taxRate = taxRates.DTO_Serialise().Find(x =&gt; x.TaxID.Trim() == request.TaxID.Trim());

            if (taxRate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No tax rate with TaxID of '{0}' was found.", request.TaxID));
            else
                return taxRate;
        }

        [Authenticate]
        public JiwaServiceModel.Tax.TaxRate Post(TaxRatePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates taxRates = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates",
            (c, m, s) =&gt;
            {
                c.Read();
                if (Helper.Service.IsStateful(s))
                    m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates", c);
            });

            var listRates = new List&lt;JiwaServiceModel.Tax.TaxRate&gt;();
            listRates.Add(request);
            taxRates.DTO_Deserialise(listRates);

            string taxRateID = listRates[0].TaxID;

            if (!Helper.Service.IsStateful(this))
            {
                taxRates.Save();
                taxRates.Read();
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], taxRateID));

            var taxRatesDTO = taxRates.DTO_Serialise();
            var taxRate = taxRatesDTO.Find(x =&gt; x.TaxID.Trim() == taxRateID.Trim());

            return taxRate;
        }

        [Authenticate]
        public JiwaServiceModel.Tax.TaxRate Patch(TaxRatePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates taxRates = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates",
            (c, m, s) =&gt;
            {
                c.Read();
                if (Helper.Service.IsStateful(s))
                    m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates", c);
            });

            var listRates = new List&lt;JiwaServiceModel.Tax.TaxRate&gt;();
            listRates.Add(request);
            taxRates.DTO_Deserialise(listRates);

            if (!Helper.Service.IsStateful(this))
            {
                taxRates.Save();
                taxRates.Read();
            }

            var taxRatesDTO = taxRates.DTO_Serialise();
            var taxRate = taxRatesDTO.Find(x =&gt; x.TaxID.Trim() == request.TaxID.Trim());

            return taxRate;
        }

        [Authenticate]
        public List&lt;JiwaServiceModel.Tax.TaxRate&gt; Get(TaxRateSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates taxRates = null;

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful tax rates exist.");
            }

            taxRates = (JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates)objectDictionaryValue;
            taxRates.Save();
            taxRates.Read();

            return taxRates.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(TaxRateABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue("JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates", out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException("No stateful tax rates exist.");
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove("JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates");
        }

        [Authenticate]
        public void Delete(TaxRateDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates taxRates = Helper.Service.GetMultiListMaintenance&lt;JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates",
            (c, m, s) =&gt;
            {
                c.Read();
                if (Helper.Service.IsStateful(s))
                    m.ObjectDictionary.Add("JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates", c);
            });

            var taxRate = taxRates.DTO_Serialise().Find(x =&gt; x.TaxID.Trim() == request.TaxID.Trim());

            if (taxRate == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(string.Format("No tax rate with a TaxID of '{0}' was found.", request.TaxID));

            switch (taxRate.GSTTaxGroup)
            {
                case JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRateTypes.GSTOut:
                    taxRates.GSTRatesOUT.Remove(taxRates.GSTRatesOUT[request.TaxID]);
                    break;
                case JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRateTypes.GSTIn:
                    taxRates.GSTRatesIN.Remove(taxRates.GSTRatesIN[request.TaxID]);
                    break;
                case JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRateTypes.GSTAdjustmentsIn:
                    taxRates.GSTRatesAdjIN.Remove(taxRates.GSTRatesAdjIN[request.TaxID]);
                    break;
                case JiwaFinancials.Jiwa.JiwaServiceModel.Tax.TaxRateTypes.GSTAdjustmentsout:
                    taxRates.GSTRatesAdjOUT.Remove(taxRates.GSTRatesAdjOUT[request.TaxID]);
                    break;
            }

            if (!Helper.Service.IsStateful(this))
            {
                taxRates.Save();
                taxRates.Read();
            }
        }
    }
    #endregion

    #endregion

    #region "Warehouse Transfers Out"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut&gt;
    {
        public string WarehouseTransferOutID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WarehouseTransferOutPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string WarehouseTransferOutID { get; set; }
        public override string DestinationWarehouseID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut, IReturn&lt;JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut&gt;
    {
        public override string WarehouseTransferOutID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutCANCELRequest
    {
        public string WarehouseTransferOutID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut&gt;
    {
        public string WarehouseTransferOutID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutABANDONRequest
    {
        public string WarehouseTransferOutID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut&gt;
    {
        public string WarehouseTransferOutID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class WarehouseTransferOutServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut Get(WarehouseTransferOutGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            return warehouseTransferOut.WarehouseTransferOutDTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut Post(WarehouseTransferOutPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(null);

            warehouseTransferOut.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
            warehouseTransferOut.DestinationLogicalWarehouse.ReadRecord(request.DestinationWarehouseID);

            warehouseTransferOut.WarehouseTransferOutDTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(warehouseTransferOut.RecID, warehouseTransferOut);
            else
            {
                warehouseTransferOut.Save();
                warehouseTransferOut.Read(warehouseTransferOut.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.WarehouseTransferOutID));

            return warehouseTransferOut.WarehouseTransferOutDTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut Patch(WarehouseTransferOutPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            warehouseTransferOut.WarehouseTransferOutDTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                warehouseTransferOut.Save();
                warehouseTransferOut.Read(request.WarehouseTransferOutID);
            }

            return warehouseTransferOut.WarehouseTransferOutDTO_Serialise();
        }

        [Authenticate]
        public void Delete(WarehouseTransferOutCANCELRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                });
            warehouseTransferOut.CancelRecord();
        }

        [Authenticate]
        public JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut Get(WarehouseTransferOutSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.WarehouseTransferOutID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful warehouse transfer out exists with WarehouseTransferOutID '{0}'", request.WarehouseTransferOutID));
            }

            var warehouseTransferOut = (JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer)objectDictionaryValue;

            warehouseTransferOut.Save();
            warehouseTransferOut.Read(warehouseTransferOut.RecID);

            return warehouseTransferOut.WarehouseTransferOutDTO_Serialise();
        }

        [Authenticate]
        public void Delete(WarehouseTransferOutABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.WarehouseTransferOutID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful warehouse transfer out exists with WarehouseTransferOutID '{0}'", request.WarehouseTransferOutID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.WarehouseTransferOutID);
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOut Post(WarehouseTransferOutACTIVATERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(null);
            warehouseTransferOut.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
            warehouseTransferOut.Read(request.WarehouseTransferOutID);

            warehouseTransferOut.ActivateRecord(false);
            warehouseTransferOut.Read(request.WarehouseTransferOutID);
            return warehouseTransferOut.WarehouseTransferOutDTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Receive Ins"
    #region "Requests"	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutReceiveInsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutReceiveIn&gt;&gt;
    {
        public string WarehouseTransferOutID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class WarehouseTransferOutReceiveInServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutReceiveIn&gt; Get(WarehouseTransferOutReceiveInsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });
            return warehouseTransferOut.ReceiveIns.WarehouseTransferOutReceiveInsDTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out line with the WarehouseTransferOutID or WarehouseTransferOutLineID provided was found")]
    public class WarehouseTransferOutLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine&gt;
    {
        public string WarehouseTransferOutID { get; set; }
        public string WarehouseTransferOutLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out line with the WarehouseTransferOutID provided was found")]
    public class WarehouseTransferOutLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine&gt;&gt;
    {
        public string WarehouseTransferOutID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out line with the WarehouseTransferOutID or WarehouseTransferOutLineID provided was found")]
    public class WarehouseTransferOutLinePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine&gt;
    {
        public string WarehouseTransferOutID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string WarehouseTransferOutLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out line with the WarehouseTransferOutID or WarehouseTransferOutLineID provided was found")]
    public class WarehouseTransferOutLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine&gt;
    {
        public string WarehouseTransferOutID { get; set; }
        public override string WarehouseTransferOutLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer out line with the WarehouseTransferOutID or WarehouseTransferOutLineID provided was found")]
    public class WarehouseTransferOutLineDELETERequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine
    {
        public string WarehouseTransferOutID { get; set; }
        public override string WarehouseTransferOutLineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class WarehouseTransferOutLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine Get(WarehouseTransferOutLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferOut.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferOutLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer out line with RecID '{0}' was found.", request.WarehouseTransferOutLineID));

            return Line.WarehouseTransferOutLineDTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine&gt; Get(WarehouseTransferOutLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });
            return warehouseTransferOut.Lines.WarehouseTransferOutLinesDTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine Post(WarehouseTransferOutLinePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            var Lines = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine&gt;();
            Lines.Add(request);

            warehouseTransferOut.Lines.WarehouseTransferOutLinesDTO_Deserialise(Lines);

            if (!Helper.Service.IsStateful(this))
            {
                warehouseTransferOut.Save();
                warehouseTransferOut.Read(warehouseTransferOut.RecID);
            }

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferOut.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferOutLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer out line with RecID '{0}' was found.", request.WarehouseTransferOutLineID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], Line.RecID));

            return Line.WarehouseTransferOutLineDTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferOutLine Patch(WarehouseTransferOutLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferOut.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferOutLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer out line with RecID '{0}' was found.", request.WarehouseTransferOutLineID));

            Line.WarehouseTransferOutLineDTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                warehouseTransferOut.Save();
                warehouseTransferOut.Read(warehouseTransferOut.RecID);
            }

            Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferOut.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferOutLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer out line with RecID '{0}' was found.", request.WarehouseTransferOutLineID));

            return Line.WarehouseTransferOutLineDTO_Serialise();
        }

        [Authenticate]
        public void Delete(WarehouseTransferOutLineDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferOut = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferOutID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Outward;
                    w.Read(request.WarehouseTransferOutID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferOut.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferOutLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer out line with RecID '{0}' was found.", request.WarehouseTransferOutLineID));

            warehouseTransferOut.Lines.Remove(Line);

            if (!Helper.Service.IsStateful(this))
            {
                warehouseTransferOut.Save();
            }
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Warehouse Transfers In"
    #region "{Main}"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in with the WarehouseTransferInID provided was found")]
    public class WarehouseTransferInGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn&gt;
    {
        public string WarehouseTransferInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WarehouseTransferInPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string WarehouseTransferInID { get; set; }
        public override string WarehouseTransferOutID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in with the WarehouseTransferInID provided was found")]
    public class WarehouseTransferInPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn, IReturn&lt;JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn&gt;
    {
        public override string WarehouseTransferInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in with the WarehouseTransferInID provided was found")]
    public class WarehouseTransferInSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn&gt;
    {
        public string WarehouseTransferInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in with the WarehouseTransferInID provided was found")]
    public class WarehouseTransferInABANDONRequest
    {
        public string WarehouseTransferInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Activated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in with the WarehouseTransferInID provided was found")]
    public class WarehouseTransferInACTIVATERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn&gt;
    {
        public string WarehouseTransferInID { get; set; }
    }
    #endregion

    #region "Services"			
    [CompressResponse]
    public class WarehouseTransferInServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn Get(WarehouseTransferInGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferInID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
                    w.Read(request.WarehouseTransferInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            return warehouseTransferIn.WarehouseTransferInDTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn Post(WarehouseTransferInPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(null);

            warehouseTransferIn.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
            
            warehouseTransferIn.WarehouseTransferInDTO_Deserialise(request);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(warehouseTransferIn.RecID, warehouseTransferIn);
            else
            {
                warehouseTransferIn.Save();
                warehouseTransferIn.Read(warehouseTransferIn.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], request.WarehouseTransferInID));

            return warehouseTransferIn.WarehouseTransferInDTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn Patch(WarehouseTransferInPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferInID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
                    w.Read(request.WarehouseTransferInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            warehouseTransferIn.WarehouseTransferInDTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                warehouseTransferIn.Save();
                warehouseTransferIn.Read(request.WarehouseTransferInID);
            }

            return warehouseTransferIn.WarehouseTransferInDTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn Get(WarehouseTransferInSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.WarehouseTransferInID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful warehouse transfer in exists with WarehouseTransferInID '{0}'", request.WarehouseTransferInID));
            }

            var warehouseTransferIn = (JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer)objectDictionaryValue;

            warehouseTransferIn.Save();
            warehouseTransferIn.Read(warehouseTransferIn.RecID);

            return warehouseTransferIn.WarehouseTransferInDTO_Serialise();
        }

        [Authenticate]
        public void Delete(WarehouseTransferInABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.WarehouseTransferInID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful warehouse transfer in exists with WarehouseTransferInID '{0}'", request.WarehouseTransferInID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.WarehouseTransferInID);
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferIn Post(WarehouseTransferInACTIVATERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(null);
            warehouseTransferIn.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
            warehouseTransferIn.Read(request.WarehouseTransferInID);

            warehouseTransferIn.ActivateRecord(false);
            warehouseTransferIn.Read(request.WarehouseTransferInID);
            return warehouseTransferIn.WarehouseTransferInDTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Receive Ins"
    #region "Requests"		
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No purchase order with the WarehouseTransferInID provided was found")]
    public class WarehouseTransferInReceiveInsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInReceiveIn&gt;&gt;
    {
        public string WarehouseTransferInID { get; set; }
    }
    #endregion

    #region "Services"
    [CompressResponse]
    public class WarehouseTransferInReceiveInServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInReceiveIn&gt; Get(WarehouseTransferInReceiveInsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferInID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
                    w.Read(request.WarehouseTransferInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });
            return warehouseTransferIn.ReceiveIns.WarehouseTransferInReceiveInsDTO_Serialise();
        }
    }
    #endregion
    #endregion

    #region "Lines"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in line with the WarehouseTransferInID or WarehouseTransferInLineID provided was found")]
    public class WarehouseTransferInLineGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInLine&gt;
    {
        public string WarehouseTransferInID { get; set; }
        public string WarehouseTransferInLineID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in line with the WarehouseTransferInID provided was found")]
    public class WarehouseTransferInLinesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInLine&gt;&gt;
    {
        public string WarehouseTransferInID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No warehouse transfer in line with the WarehouseTransferInID or WarehouseTransferInLineID provided was found")]
    public class WarehouseTransferInLinePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInLine, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInLine&gt;
    {
        public string WarehouseTransferInID { get; set; }
        public override string WarehouseTransferInLineID { get; set; }
    }
    #endregion

    #region "Services"		
    [CompressResponse]
    public class WarehouseTransferInLineServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInLine Get(WarehouseTransferInLineGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferInID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
                    w.Read(request.WarehouseTransferInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferIn.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferInLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer in line with RecID '{0}' was found.", request.WarehouseTransferInLineID));

            return Line.WarehouseTransferInLineDTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInLine&gt; Get(WarehouseTransferInLinesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferInID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
                    w.Read(request.WarehouseTransferInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });
            return warehouseTransferIn.Lines.WarehouseTransferInLinesDTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WarehouseTransfers.WarehouseTransferInLine Patch(WarehouseTransferInLinePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer warehouseTransferIn = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer&gt;(manager, this, request.WarehouseTransferInID,
                (w, m, s) =&gt;
                {
                    w.TransferMode = JiwaFinancials.Jiwa.JiwaWhouseTransfer.WarehouseTransfer.Mode.Inward;
                    w.Read(request.WarehouseTransferInID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(w.RecID, w);
                    }
                });

            JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferIn.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferInLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer in line with RecID '{0}' was found.", request.WarehouseTransferInLineID));

            Line.WarehouseTransferInLineDTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                warehouseTransferIn.Save();
                warehouseTransferIn.Read(warehouseTransferIn.RecID);
            }

            Line = null;

            foreach (JiwaFinancials.Jiwa.JiwaWhouseTransfer.Line existingLine in warehouseTransferIn.Lines)
            {
                if (existingLine.RecID == request.WarehouseTransferInLineID)
                {
                    Line = existingLine;
                    break;
                }
            }

            if (Line == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No warehouse transfer in line with RecID '{0}' was found.", request.WarehouseTransferInLineID));

            return Line.WarehouseTransferInLineDTO_Serialise();
        }
    }
    #endregion
    #endregion
    #endregion

    #region "Webhooks"
    #region "Models"
	[Serializable()]
    public partial class WebHookEvent
    {
        [Required]
        [PrimaryKey]
        public string Name { get; set; }
        public string Description { get; set; }
    }

	[Serializable()]
    public class WebhooksSubscriptionHeader
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }

	[Serializable()]
    public class WebhookSubscriber : JiwaFinancials.Jiwa.JiwaServiceModel.Tables.SY_WebhookSubscriber
    {
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tables.SY_WebhookSubscription&gt; Subscriptions { get; set; }
    }
    #endregion

    #region "Requests"
    #region "Subscribers"	
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WebhooksSubscribersGETManyRequest : QueryDb&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Tables.SY_WebhookSubscriber&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WebhooksSubscribersGETRequest : IReturn&lt;WebhookSubscriber&gt;
    {
        public string SubscriberID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WebhooksSubscribersPOSTRequest : IReturn&lt;SY_WebhookSubscriber&gt;
    {
        public string Name { get; set; }
        public bool? IsEnabled { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Subscriber with the SubscriberID was found.")]
    public class WebhooksSubscribersPATCHRequest : IReturn&lt;SY_WebhookSubscriber&gt;
    {
        public string SubscriberID { get; set; }
        public string Name { get; set; }
        public bool? IsEnabled { get; set; }
        public int? ItemNo { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No Subscriber with the SubscriberID was found.")]
    public class WebhooksSubscribersDELETERequest
    {
        public string SubscriberID { get; set; }
    }
    #endregion

    #region "Subscriptions"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(404, "No Subscriber with the SubscriberID was found.")]
    public class WebhooksSubscriptionsGETRequest : IReturn&lt;List&lt;SY_WebhookSubscription&gt;&gt;
    {
        public string SubscriberID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(404, "No Subscriber with the SubscriberID was found.")]
    public class WebhooksSubscriptionsPOSTRequest : IReturn&lt;SY_WebhookSubscription&gt;
    {
        public string SubscriberID { get; set; }
        public string URL { get; set; }
        public string EventName { get; set; }
        public List&lt;WebhooksSubscriptionHeader&gt; Headers { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(404, "No Subscriber with the SubscriberID was found.")]
    public class WebhooksSubscriptionsPATCHRequest : IReturn&lt;SY_WebhookSubscription&gt;
    {
        public string SubscriberID { get; set; }
        public string SubscriptionID { get; set; }
        public string URL { get; set; }
        public string EventName { get; set; }
        public List&lt;WebhooksSubscriptionHeader&gt; Headers { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(404, "No Subscriber with the SubscriberID or Webhook with the SubscriptionID provided was found")]
    public class WebhooksSubscriptionsDELETERequest
    {
        public string SubscriberID { get; set; }
        public string SubscriptionID { get; set; }
    }
    #endregion

    #region "Messages"	
    public class WebhooksMessagesGETRequest : QueryDb&lt;v_SY_WebhookSubscriber_Messages&gt;
    {
        public string SubscriberID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(404, "No Subscriber with the SubscriberID, Subscription with the SubscriptionID, Or Message with the MessageID provided was found.")]
    public class WebhooksMessagesDELETERequest
    {
        public string SubscriberID { get; set; }
        public string SubscriptionID { get; set; }
        public string MessageID { get; set; }
    }
    #endregion

    #region "Message Responses"	
    public class WebhooksMessageResponsesGETRequest : QueryDb&lt;v_SY_WebhookSubscriber_MessageResponses&gt;
    {
        public string SubscriberID { get; set; }
    }
    #endregion

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    public class WebhooksEventsGETRequest : IReturn&lt;List&lt;WebHookEvent&gt;&gt;
    {
    }

	[Serializable()]
    [Route("/Webhooks/Events/", "POST")] // Needed by client in business logic plugin - it can't infer the route without this attribute
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WebhooksEventsPOSTRequest
    {
        public string EventName { get; set; }
        public string Body { get; set; }
    }

	[Serializable()]
    [Route("/Webhooks/Test/", "POST")]
    [ApiResponse(201, "Created OK")]
    public class WebhooksTestPOSTRequest
    {
        public string Body { get; set; }
    }


    #endregion

    #region "Services"
    [CompressResponse]
    public class WebhookServices : Service
    {
        public IAutoQueryDb AutoQuery { get; set; }

        #region "Subscribers"	

        [Authenticate]
        public object Get(WebhooksSubscribersGETManyRequest query)
        {
            var q = AutoQuery.CreateQuery(query, base.Request);
            return AutoQuery.Execute(query, q);
        }

        [Authenticate]
        public WebhookSubscriber Get(WebhooksSubscribersGETRequest request)
        {
            SY_WebhookSubscriber SY_WebhookSubscriber = RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToString().ToLower()).FirstOrDefault();
            if (SY_WebhookSubscriber == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriberID with ID '{0}'", request.SubscriberID.ToString().ToLower()));

            WebhookSubscriber subscriber = new WebhookSubscriber() { RecID = SY_WebhookSubscriber.RecID, Name = SY_WebhookSubscriber.Name, IsEnabled = SY_WebhookSubscriber.IsEnabled, ItemNo = SY_WebhookSubscriber.ItemNo, LastSavedDateTime = SY_WebhookSubscriber.LastSavedDateTime, RowHash = SY_WebhookSubscriber.RowHash };

            subscriber.Subscriptions = RESTAPIPlugin.WebhookSubscriptions.Where(x =&gt; x.SY_WebhookSubscriber_RecID.ToString().ToLower() == request.SubscriberID.ToLower()).ToList&lt;SY_WebhookSubscription&gt;();

            return subscriber;
        }

        [Authenticate]
        public SY_WebhookSubscriber Post(WebhooksSubscribersPOSTRequest request)
        {
            System.Guid subscriberID = System.Guid.NewGuid();

            Db.ExecuteSql(@"INSERT INTO SY_WebhookSubscriber (RecID, Name, IsEnabled, ItemNo, LastSavedDateTime) 
										VALUES (@RecID, @Name, @IsEnabled, (SELECT COALESCE(MAX(ItemNo), 0) + 1 FROM SY_WebhookSubscriber), SYSUTCDATETIME())",
                          new { RecID = subscriberID, Name = request.Name, IsEnabled = request.IsEnabled });
            // Read back the value, add it to the internal collection and return it
            SY_WebhookSubscriber newSubscriber = Db.SingleById&lt;SY_WebhookSubscriber&gt;(subscriberID);
            RESTAPIPlugin.WebhookSubscribers.Add(newSubscriber);
            return newSubscriber;
        }

        [Authenticate]
        public SY_WebhookSubscriber Patch(WebhooksSubscribersPATCHRequest request)
        {
            SY_WebhookSubscriber subscriber = RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToString().ToLower()).FirstOrDefault();

            if (subscriber == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriber with ID '{0}'", request.SubscriberID.ToString().ToLower()));

            if (request.Name != null)
                subscriber.Name = request.Name;

            if (request.IsEnabled.HasValue)
                subscriber.IsEnabled = request.IsEnabled.Value;

            if (request.ItemNo.HasValue)
                subscriber.ItemNo = request.ItemNo.Value;

            Db.ExecuteSql(@"UPDATE SY_WebhookSubscriber
										SET Name = @Name,
										IsEnabled = @IsEnabled,
										ItemNo = @ItemNo,
										LastSavedDateTime = SYSUTCDATETIME()
										WHERE RecID = @RecID",
                          new { RecID = subscriber.RecID, Name = subscriber.Name, IsEnabled = subscriber.IsEnabled, ItemNo = subscriber.ItemNo });

            // Read back the value, update the internal collection and return it
            SY_WebhookSubscriber updatedSubscriber = Db.SingleById&lt;SY_WebhookSubscriber&gt;(request.SubscriberID);
            subscriber.Name = updatedSubscriber.Name;
            subscriber.IsEnabled = updatedSubscriber.IsEnabled;
            subscriber.ItemNo = updatedSubscriber.ItemNo;
            subscriber.LastSavedDateTime = updatedSubscriber.LastSavedDateTime;

            return updatedSubscriber;
        }

        [Authenticate]
        public void Delete(WebhooksSubscribersDELETERequest request)
        {
            if (RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriber with ID '{0}'", request.SubscriberID.ToLower()));

            Db.Delete&lt;SY_WebhookSubscriber&gt;(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower());
            // Remove from internal collection
            RESTAPIPlugin.WebhookSubscribers.Remove(RESTAPIPlugin.WebhookSubscribers.FirstOrDefault(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower()));
        }
        #endregion

        #region "Subscriptions"
        public List&lt;JiwaServiceModel.Tables.SY_WebhookSubscription&gt; Get(WebhooksSubscriptionsGETRequest request)
        {
            if (RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriber with ID '{0}'", request.SubscriberID.ToLower()));

            return RESTAPIPlugin.WebhookSubscriptions.Where(x =&gt; x.SY_WebhookSubscriber_RecID.ToString().ToLower() == request.SubscriberID.ToLower()).ToList&lt;SY_WebhookSubscription&gt;();
        }

        public SY_WebhookSubscription Post(WebhooksSubscriptionsPOSTRequest request)
        {
            if (RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriber with ID '{0}'", request.SubscriberID.ToLower()));

            SY_WebhookSubscription newSubscription = new SY_WebhookSubscription { RecID = System.Guid.NewGuid(), SY_WebhookSubscriber_RecID = new System.Guid(request.SubscriberID), EventName = request.EventName, URL = request.URL };

            Db.ExecuteSql(@"INSERT INTO SY_WebhookSubscription (RecID, SY_WebhookSubscriber_RecID, EventName, URL, ItemNo, LastSavedDateTime) 
											VALUES (@RecID, @SY_WebhookSubscriber_RecID, @EventName, @URL, (SELECT COALESCE(MAX(ItemNo), 0) + 1 FROM SY_WebhookSubscription WHERE SY_WebhookSubscription.SY_WebhookSubscriber_RecID = @ItemNo_SY_WebhookSubscriber_RecID), SYSUTCDATETIME())",
                              new
                              {
                                  RecID = newSubscription.RecID,
                                  SY_WebhookSubscriber_RecID = newSubscription.SY_WebhookSubscriber_RecID,
                                  EventName = newSubscription.EventName,
                                  URL = newSubscription.URL,
                                  ItemNo_SY_WebhookSubscriber_RecID = newSubscription.RecID
                              });

            // read back and return that as our item no and lastsaved date time is set at the database level and we want to return that.
            newSubscription = Db.SingleById&lt;SY_WebhookSubscription&gt;(newSubscription.RecID);
            RESTAPIPlugin.WebhookSubscriptions.Add(newSubscription);

            // Now do the headers (if any)
            if (request.Headers != null)
            {
                foreach (WebhooksSubscriptionHeader webhooksSubscriptionHeader in request.Headers)
                {
                    string webhooksSubscriptionHeaderRecID = System.Guid.NewGuid().ToString();
                    Db.ExecuteSql(@"INSERT INTO SY_WebhookSubscriptionRequestHeader (RecID, SY_WebhookSubscription_RecID, Name, Value, ItemNo, LastSavedDateTime) 
											VALUES (@RecID, @SY_WebhookSubscription_RecID, @Name, @Value, (SELECT COALESCE(MAX(ItemNo), 0) + 1 FROM SY_WebhookSubscriptionRequestHeader WHERE SY_WebhookSubscriptionRequestHeader.SY_WebhookSubscription_RecID = @ItemNo_SY_WebhookSubscription_RecID), SYSUTCDATETIME())",
                              new
                              {
                                  RecID = webhooksSubscriptionHeaderRecID,
                                  SY_WebhookSubscription_RecID = newSubscription.RecID,
                                  Name = webhooksSubscriptionHeader.Name,
                                  Value = webhooksSubscriptionHeader.Value,
                                  ItemNo_SY_WebhookSubscription_RecID = newSubscription.RecID
                              });
                    SY_WebhookSubscriptionRequestHeader newSubscriptionRequestHeader = Db.SingleById&lt;SY_WebhookSubscriptionRequestHeader&gt;(webhooksSubscriptionHeaderRecID);
                    RESTAPIPlugin.WebhookSubscriptionRequestHeaders.Add(newSubscriptionRequestHeader);
                }
            }

            return newSubscription;
        }

        public SY_WebhookSubscription Patch(WebhooksSubscriptionsPATCHRequest request)
        {
            if (RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriber with ID '{0}'", request.SubscriberID.ToLower()));

            SY_WebhookSubscription subscription = RESTAPIPlugin.WebhookSubscriptions.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriptionID.ToLower()).FirstOrDefault();

            if (subscription == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscription with ID '{0}'", request.SubscriptionID.ToLower()));

            Db.Update&lt;SY_WebhookSubscription&gt;(new { URL = request.URL, EventName = request.EventName }, x =&gt; x.RecID.ToString().ToLower() == request.SubscriptionID.ToLower());
            // read back and return that as our item no and lastsaved date time is set at the database level and we want to return that.
            SY_WebhookSubscription updatedSubscription = Db.SingleById&lt;SY_WebhookSubscription&gt;(subscription.RecID);

            // Update the subscription in the internal collection
            SY_WebhookSubscription internalSubscription = RESTAPIPlugin.WebhookSubscriptions.FirstOrDefault(x =&gt; x.RecID.ToString().ToLower() == request.SubscriptionID.ToLower());
            internalSubscription.URL = updatedSubscription.URL;
            internalSubscription.EventName = updatedSubscription.EventName;

            return updatedSubscription;
        }

        public void Delete(WebhooksSubscriptionsDELETERequest request)
        {
            if (RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriber with ID '{0}'", request.SubscriberID.ToLower()));

            if (RESTAPIPlugin.WebhookSubscriptions.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriptionID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscription with ID '{0}'", request.SubscriptionID.ToLower()));

            Db.Delete&lt;SY_WebhookSubscription&gt;(x =&gt; x.RecID.ToString().ToLower() == request.SubscriptionID.ToLower());
            RESTAPIPlugin.WebhookSubscriptions.Remove(RESTAPIPlugin.WebhookSubscriptions.FirstOrDefault(x =&gt; x.RecID.ToString().ToLower() == request.SubscriptionID.ToLower()));
        }
        #endregion

        #region "Messages"
        public object Get(WebhooksMessagesGETRequest query)
        {
            var q = AutoQuery.CreateQuery(query, base.Request);
            q.And("SubscriberID = {0}", query.SubscriberID.ToLower());
            return AutoQuery.Execute(query, q);
        }

        public void Delete(WebhooksMessagesDELETERequest request)
        {
            if (RESTAPIPlugin.WebhookSubscribers.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriberID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscriber with ID '{0}'", request.SubscriberID.ToLower()));

            if (RESTAPIPlugin.WebhookSubscriptions.Where(x =&gt; x.RecID.ToString().ToLower() == request.SubscriptionID.ToLower()).FirstOrDefault() == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No subscription with ID '{0}'", request.SubscriptionID.ToLower()));

            Db.Delete&lt;SY_WebhookMessage&gt;(x =&gt; x.RecID.ToString().ToLower() == request.MessageID.ToLower());
            RESTAPIPlugin.WebhookMessages.Remove(RESTAPIPlugin.WebhookMessages.FirstOrDefault(x =&gt; x.RecID.ToString().ToLower() == request.MessageID.ToLower()));
        }
        #endregion

        #region "Message Responses"
        public object Get(WebhooksMessageResponsesGETRequest query)
        {
            var q = AutoQuery.CreateQuery(query, base.Request);
            q.And("SubscriberID = {0}", query.SubscriberID.ToLower());
            return AutoQuery.Execute(query, q);
        }
        #endregion

        public List&lt;JiwaServiceModel.WebHookEvent&gt; Get(WebhooksEventsGETRequest request)
        {
            return RESTAPIPlugin.WebHookEvents.OrderBy(x =&gt; x.Name).ToList&lt;WebHookEvent&gt;();
        }

        public void Post(WebhooksEventsPOSTRequest request)
        {
            // This is the route invoked by clients to indicate an event has occurred.

            // Check key					
            string clientKey = this.Request.GetHeader("ClientKey");
            if (clientKey == null || clientKey != RESTAPIPlugin.ClientKey)
                throw new JiwaApplication.Exceptions.PermissionDeniedException("Invalid ClientKey provided.");

            // Add items to the message queue with status 0 (not sent)
            List&lt;SY_WebhookSubscription&gt; subscriptions = RESTAPIPlugin.WebhookSubscriptions.Where(x =&gt; x.EventName == request.EventName).ToList&lt;SY_WebhookSubscription&gt;();
            foreach (SY_WebhookSubscription subscription in subscriptions)
            {
                SY_WebhookMessage newMessage = new SY_WebhookMessage { RecID = System.Guid.NewGuid(), SY_WebhookSubscription_RecID = subscription.RecID, Body = request.Body, Status = 0, Retries = 0 };
                Db.ExecuteSql(@"INSERT INTO SY_WebhookMessage (RecID, SY_WebhookSubscription_RecID, Body, ItemNo, Status, LastSavedDateTime, AddedDateTime, Retries) 
										VALUES (@RecID, @SY_WebhookSubscription_RecID, @Body, (SELECT COALESCE(MAX(ItemNo), 0) + 1 FROM SY_WebhookMessage), @Status, SYSUTCDATETIME(), SYSUTCDATETIME(), @Retries)",
                              new { RecID = newMessage.RecID, SY_WebhookSubscription_RecID = newMessage.SY_WebhookSubscription_RecID, Body = newMessage.Body, Status = newMessage.Status, Retries = newMessage.Retries });

                // read back and keep that in our internal list as our item no and lastsaved date time is set at the database level.
                newMessage = Db.SingleById&lt;SY_WebhookMessage&gt;(newMessage.RecID);

                RESTAPIPlugin.WebhookMessages.Add(newMessage);
                // send to url			
                WebHookController.CallWebhook(newMessage);
            }
        }

        public void Post(WebhooksTestPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaServiceModel.Helper.EventLog.Log("WebhooksTestPOSTRequest received", System.Diagnostics.EventLogEntryType.Information);
        }
    }
    #endregion

    #region "Callback logic"
    public class WebHookController
    {
        static public void CallWebhook(SY_WebhookMessage message)
        {			
			byte originalStatus = message.Status;
			message.Status = 100;	// immediately flag status to 100 to signal to the retry timer to not attempt to process this message whilst we are - prevents double-sending
			
            if (originalStatus == 1)
                return;

            SY_WebhookSubscription subscription = RESTAPIPlugin.WebhookSubscriptions.Where(x =&gt; x.RecID == message.SY_WebhookSubscription_RecID).FirstOrDefault();
            List&lt;SY_WebhookSubscriptionRequestHeader&gt; subscriptionRequestHeaders = RESTAPIPlugin.WebhookSubscriptionRequestHeaders.Where(x =&gt; x.SY_WebhookSubscription_RecID == message.SY_WebhookSubscription_RecID).OrderBy(x =&gt; x.ItemNo).ToList&lt;SY_WebhookSubscriptionRequestHeader&gt;();

            int retries = message.Retries;

            if (originalStatus != 0)
            {
                // Calculate the UTC time we need to be older than to continue
                int seconds = (int)((RESTAPIPlugin.RetryInterval) * Math.Pow(10, message.Retries));
                int differenceMilliseconds = (int)((TimeSpan)(DateTime.UtcNow - message.LastSavedDateTime)).TotalMilliseconds;

                if (differenceMilliseconds &lt; (seconds * 1000))
                {
					message.Status = originalStatus;
                    return;
                }

                retries++;
            }

            int newStatus = originalStatus;
            SY_WebhookMessageResponse messageResponse = new SY_WebhookMessageResponse { RecID = System.Guid.NewGuid(), SY_WebhookMessage_RecID = message.RecID };

            try
            {
                // This is the actual POST to the webhook
                subscription.URL.PostStringToUrl(message.Body,
                                                 requestFilter: webRequest =&gt;
                                                 {
                                                     foreach (SY_WebhookSubscriptionRequestHeader subscriptionRequestHeader in subscriptionRequestHeaders)
                                                     {
														if(subscriptionRequestHeader.Name.ToUpper() == "CONTENT-TYPE")
														{
															webRequest.ContentType = subscriptionRequestHeader.Value;
														}
														else
														{
															webRequest.Headers[subscriptionRequestHeader.Name] = subscriptionRequestHeader.Value;
														}
                                                     }
                                                 });
                messageResponse.HTTPCode = 200;
                newStatus = 1;
            }
            catch (System.Exception ex)
            {
                while (ex.InnerException != null) ex = ex.InnerException;

                newStatus = 2;
                messageResponse.Message = ex.Message;
                int statusCode = 0;

                if (ex.GetStatus() != null)
                    statusCode = (int)ex.GetStatus();

                messageResponse.HTTPCode = statusCode;

                if ((statusCode &gt;= 200 &amp;&amp; statusCode &lt; 300) || ex.IsAny300() || statusCode == 410)
                    newStatus = 3;  // Permanent fail - we do not attempt to retry these							
            }
            finally
            {
                if (message.Retries &gt;= RESTAPIPlugin.MaxRetries)
                    newStatus = 3;

                message.Status = (byte)newStatus;
                message.LastSavedDateTime = DateTime.UtcNow;
                message.Retries = retries;

				using(var db = RESTAPIPlugin.AppHost.GetDbConnection())
				{
	                db.ExecuteSql(@"UPDATE SY_WebhookMessage 
											SET Status = @Status,
											Retries = @Retries,
											LastSavedDateTime = @LastSavedDateTime
											WHERE RecID = @RecID",
	                                  new { RecID = message.RecID, Status = message.Status, Retries = message.Retries, LastSavedDateTime = message.LastSavedDateTime });

	                db.ExecuteSql(@"INSERT INTO SY_WebhookMessageResponse (RecID, SY_WebhookMessage_RecID, HTTPCode, Message, ItemNo, LastSavedDateTime) 
											VALUES (@RecID, @SY_WebhookMessage_RecID, @HTTPCode, @Message, (SELECT COALESCE(MAX(ItemNo), 0) + 1 FROM SY_WebhookMessageResponse WHERE SY_WebhookMessage_RecID = @SY_WebhookMessage_RecID), SYSUTCDATETIME())",
	                              new { RecID = messageResponse.RecID, SY_WebhookMessage_RecID = message.RecID, HTTPCode = messageResponse.HTTPCode, Message = messageResponse.Message });
					
					db.Close();
				}
                if (message.Status == 1 || message.Status == 3)
                {
                    // remove from internal in-memory list
                    SY_WebhookMessage existingItem = RESTAPIPlugin.WebhookMessages.FirstOrDefault(x =&gt; x.RecID.ToString().ToLower() == message.RecID.ToString().ToLower());
                    if (existingItem != null)
					{
                        RESTAPIPlugin.WebhookMessages.Remove(existingItem);
					}
                }
            }
        }
    }
    #endregion

    #region "Retry Message Queue Logic"

    public class WebhookMessagesTimer : IDisposable
    {
        // This is essentially a timer class which is non-reentrant				
        private readonly System.Timers.Timer _timer;

        public WebhookMessagesTimer(int TimerInterval)
        {
            _timer = new System.Timers.Timer { AutoReset = false, Interval = TimerInterval };

            _timer.Elapsed += delegate
            {
                _timer.Stop();

                // Process the message queue
                List&lt;SY_WebhookMessage&gt; messages = RESTAPIPlugin.WebhookMessages.Where(x =&gt; x.Status == 0 || x.Status == 2).OrderBy(x =&gt; x.ItemNo).ToList&lt;SY_WebhookMessage&gt;();
                foreach (SY_WebhookMessage message in messages)
                {
                    // 0 = not sent, never been tried
					// 1 = successfully sent already
					// 2 = failed to send, retry pending
					// 3 = failed permanently
					// 100 = currently being sent
					if (message.Status == 0 || message.Status == 2)
					{						
	                	WebHookController.CallWebhook(message);
					}
                }

                _timer.Start(); // restart the timer
            };

            _timer.Start();
        }

        public void Dispose()
        {
            if (_timer != null)
            {
                _timer.Dispose();
            }
        }
    }
    #endregion
    #endregion
	
	#region "Work Orders"
    #region "{Main}"
    #region"Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder&gt;
    {
        public override string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderDELETERequest
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Saved OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderSAVERequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Abandoned OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderABANDONRequest
    {
        public string WorkOrderID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder Get(WorkOrderGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (j, m, s) =&gt;
                {
                    j.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });
            return workOrder.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrder Post(WorkOrderPOSTRequest WorkOrder)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(null);
            workOrder.DTO_Deserialise(WorkOrder);

            if (Helper.Service.IsStateful(this))
                manager.ObjectDictionary.Add(workOrder.RecID, WorkOrder);
            else
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], workOrder.RecID));
            return workOrder.DTO_Serialise();
        }

        [Authenticate]
        public JiwaServiceModel.WorkOrders.WorkOrder Patch(WorkOrderPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (j, m, s) =&gt;
                {
                    j.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(j.RecID, j);
                    }
                });

            workOrder.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
               	workOrder.Save();
                workOrder.Read(request.WorkOrderID);
            }

            return workOrder.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = manager.BusinessLogicFactory.CreateBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(null);
            workOrder.Read(request.WorkOrderID);

            workOrder.Delete();
        }

        [Authenticate]
        public JiwaServiceModel.WorkOrders.WorkOrder Get(WorkOrderSAVERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.WorkOrderID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful work order record exists with WorkOrderID '{0}'", request.WorkOrderID));
            }

            var workOrder = (JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder)objectDictionaryValue;
			
			workOrder.Save();
            workOrder.Read(workOrder.RecID);

            return workOrder.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderABANDONRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            if (!Helper.Service.IsStateful(this))
            {
                throw new ArgumentException("Request header jiwa-stateful must be provided and be 'true' for this request to be valid.");
            }

            object objectDictionaryValue = null;
            if (!manager.ObjectDictionary.TryGetValue(request.WorkOrderID, out objectDictionaryValue))
            {
                throw new JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stateful work order record exists with WorkOrderID '{0}'", request.WorkOrderID));
            }

            // Remove the object from the dictionary
            manager.ObjectDictionary.Remove(request.WorkOrderID);
        }
    }
    #endregion
    #endregion		
	
    #region "Allocations"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order allocation with the WorkOrderID or AllocationID provided was found")]
    public class WorkOrderAllocationGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation&gt;
    {
        public string WorkOrderID { get; set; }
        public string AllocationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order allocations with the WorkOrderID provided was found")]
    public class WorkOrderAllocationsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation&gt;&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order allocation with the WorkOrderID or AllocationID provided was found")]
    public class WorkOrderAllocationPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation&gt;
    {
        public string WorkOrderID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string AllocationID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order allocation with the WorkOrderID or AllocationID provided was found")]
    public class WorkOrderAllocationDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string AllocationID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderAllocationServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation Get(WorkOrderAllocationGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.LineDetailsAllocation allocation = workOrder.Allocations.GetItem("RecID", request.AllocationID);

            if (allocation == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order allocation with AllocationID '{0}' was found.", request.AllocationID));

            return allocation.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation&gt; Get(WorkOrderAllocationsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            return workOrder.Allocations.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation Post(WorkOrderAllocationPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });


            // Add the allocation. Need to jump through a few hoops as we want to know the AllocationID so we can return that in the response header.	
            var allocations = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.Allocation&gt;();
            allocations.Add(request);
            string AllocationID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.LineDetailsAllocation&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                AllocationID = item.RecID;
                workOrder.Allocations.Added -= addedHandler; // remove handler						
            };

            workOrder.Allocations.Added += addedHandler;
            workOrder.Allocations.DTO_Deserialise(allocations);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.LineDetailsAllocation allocation = workOrder.Allocations.GetItem("RecID", AllocationID);

            if (allocation == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order allocation with AllocationID '{0}' was found.", AllocationID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], allocation.RecID));

            return allocation.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderAllocationDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.LineDetailsAllocation allocation = workOrder.Allocations.GetItem("RecID", request.AllocationID);

            if (allocation == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order allocation with AllocationID '{0}' was found.", request.AllocationID));

            workOrder.Allocations.Remove(allocation);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
            }
        }
    }
    #endregion
    #endregion		
	
    #region "Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No custom field with the SettingID provided was found")]
    public class WorkOrderCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order custom field value with the WorkOrderID or SettingID provided was found")]
    public class WorkOrderCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order custom field value with the WorkOrderID or SettingID provided was found")]
    public class WorkOrderCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(WorkOrderCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            return workOrder.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(WorkOrderCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            var WorkOrderCustomFieldValue = workOrder.CustomFieldValues.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (WorkOrderCustomFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return WorkOrderCustomFieldValue;
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(WorkOrderCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = workOrder.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            customFieldValue = workOrder.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(WorkOrderCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);

            return workOrder.CustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(WorkOrderCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);

            var WorkOrderCustomField = workOrder.CustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (WorkOrderCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return WorkOrderCustomField;
        }		
    }
    #endregion
    #endregion		
	
    #region "Document Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order document type with the DocumentTypeID provided was found")]
    public class WorkOrderDocumentTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderDocumentTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderDocumentTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order document type with the DocumentTypeID provided was found")]
    public class WorkOrderDocumentTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;
    {
        public override string DocumentTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order document type with the DocumentTypeID provided was found")]
    public class WorkOrderDocumentTypeDELETERequest
    {
        public string DocumentTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderDocumentTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Get(WorkOrderDocumentTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.DocumentTableNames.Add("BM_WorkOrderDocuments");					
                    d.Read();
                });

            JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt; Get(WorkOrderDocumentTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.DocumentTableNames.Add("BM_WorkOrderDocuments");					
                    d.Read();
                });

            return documentTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Post(WorkOrderDocumentTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.DocumentTableNames.Add("BM_WorkOrderDocuments");					
                    d.Read();
                });

            // Add the document type. Need to jump through a few hoops as we want to know the DocumentTypeID so we can return that in the response header.	
            var dtoDocumentTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType&gt;();
            dtoDocumentTypes.Add(request);
            string documentTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaDocumentTypes.DocumentType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentTypeID = item.RecID;
                documentTypes.Added -= addedHandler; // remove handler						
            };

            documentTypes.Added += addedHandler;
            documentTypes.DTO_Deserialise(dtoDocumentTypes);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", documentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document type with DocumentTypeID '{0}' was found.", documentTypeID));

            // Add the location to the response header						
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0].Split(new[] { '?' })[0], documentType.RecID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.DocumentType Patch(WorkOrderDocumentTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.DocumentTableNames.Add("BM_WorkOrderDocuments");					
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }

            documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            return documentType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderDocumentTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaDocumentTypes.DocumentTypeCollection documentTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaDocumentTypes.DocumentType, JiwaDocumentTypes.DocumentTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.DocumentType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.DocumentTableNames.Add("BM_WorkOrderDocuments");
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentType documentType = documentTypes.GetItem("RecID", request.DocumentTypeID);

            if (documentType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document type with DocumentTypeID '{0}' was found.", request.DocumentTypeID));

            documentTypes.Remove(documentType);

            if (!Helper.Service.IsStateful(this))
            {
                documentTypes.Save();
                documentTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Documents"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order document with the WorkOrderID or DocumentID provided was found")]
    public class WorkOrderDocumentGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string WorkOrderID { get; set; }
        public string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderDocumentsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderDocumentPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string WorkOrderID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string DocumentID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderDocumentPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;
    {
        public string WorkOrderID { get; set; }
        public override string DocumentID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderDocumentDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string DocumentID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderDocumentServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Get(WorkOrderDocumentGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = workOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt; Get(WorkOrderDocumentsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            return workOrder.Documents.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Post(WorkOrderDocumentPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the document. Need to jump through a few hoops as we want to know the DocumentID so we can return that in the response header.	
            var documents = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document&gt;();
            documents.Add(request);
            string documentID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Documents.Document&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                documentID = item.RecID;
                workOrder.Documents.Added -= addedHandler; // remove handler						
            };

            workOrder.Documents.Added += addedHandler;
            workOrder.Documents.DTO_Deserialise(documents);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = workOrder.Documents.GetItem("RecID", documentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document with DocumentID '{0}' was found.", documentID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], document.RecID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Documents.Document Patch(WorkOrderDocumentPATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaApplication.Documents.Document document = workOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document with DocumentID '{0}' was found.", request.DocumentID));

            document.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            document = workOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document with DocumentID '{0}' was found.", request.DocumentID));

            return document.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderDocumentDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Documents.Document document = workOrder.Documents.GetItem("RecID", request.DocumentID);

            if (document == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order document with DocumentID '{0}' was found.", request.DocumentID));

            workOrder.Documents.Remove(document);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }
    }
    #endregion
    #endregion		
	
    #region "Input Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderInputCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input WorkOrderID, StageID or InputID provided was found")]
    public class WorkOrderInputCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderInputCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input custom field Value with the WorkOrderID, StageID, InputID or SettingID provided was found")]
    public class WorkOrderInputCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input custom field Value with the WorkOrderID, StageID, InputID or SettingID provided was found")]
    public class WorkOrderInputCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderInputCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(WorkOrderInputCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem WorkOrderInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (WorkOrderInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            return WorkOrderInput.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(WorkOrderInputCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem WorkOrderInput = stage.InputItems.GetItem("RecID", request.InputID);

            if (WorkOrderInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in WorkOrderInput.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(WorkOrderInputCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem inputItem = stage.InputItems.GetItem("RecID", request.InputID);

            if (inputItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = inputItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
				
				stage = workOrder.Stages.GetItem("RecID", request.StageID);
				
	            if (stage == null)
	                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));				

                inputItem = stage.InputItems.GetItem("RecID", request.InputID);
				
	            if (inputItem == null)
	                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));
				
                customFieldValue = inputItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(WorkOrderInputCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);
            return workOrder.InputCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(WorkOrderInputCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);

            var WorkOrderInputCustomField = workOrder.InputCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (WorkOrderInputCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return WorkOrderInputCustomField;
        }		
    }
    #endregion
    #endregion		
	
    #region "Input Line Details"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID, or InputID provided was found")]
    public class WorkOrderInputLineDetailsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input line detail with the WorkOrderID, StageID, InputID, or LineDetailID provided was found")]
    public class WorkOrderInputLineDetailGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID, or InputID provided was found")]
    public class WorkOrderInputLineDetailPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LineDetailID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]    
    public class WorkOrderInputLineDetailPUTRequest : List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;, IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {	
		public string WorkOrderID { get; set; }
		public string StageID { get; set; }
		public string InputID { get; set; }
    }		

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input line detail with the WorkOrderID, StageID, InputID, or LineDetailID provided was found")]
    public class WorkOrderInputLineDetailPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public override string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input line detail with the WorkOrderID, StageID, InputID, or LineDetailID provided was found")]
    public class WorkOrderInputLineDetailDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public string LineDetailID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderInputLineDetailServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Get(WorkOrderInputLineDetailsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            return input.LineDetails.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Get(WorkOrderInputLineDetailGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; lineDetail = input.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return lineDetail.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Post(WorkOrderInputLineDetailPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            // Add the line detail. Need to jump through a few hoops as we want to know the DetailsLineID so we can return that in the response header.	
            var lineDetails = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;();
            lineDetails.Add(request);
            string lineDetailID = "";
            JiwaFinancials.Jiwa.JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt;&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                lineDetailID = item.RecID;
                input.LineDetails.Added -= addedHandler; // remove handler						
            };

            input.LineDetails.Added += addedHandler;
            input.LineDetails.DTO_Deserialise(lineDetails);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; lineDetail = input.LineDetails.GetItem("RecID", lineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input line detail with LineDetailID '{0}' was found.", lineDetailID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], lineDetail.RecID));

            return lineDetail.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Put(WorkOrderInputLineDetailPUTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

			// remove any existing line details
			input.LineDetails.RemoveAll();
			
			// Now add new line details as provided
			input.LineDetails.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            return input.LineDetails.DTO_Serialise();		
        }				
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Patch(WorkOrderInputLineDetailPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; lineDetail = input.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            lineDetail.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            lineDetail = input.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return lineDetail.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderInputLineDetailDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; lineDetail = input.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            input.LineDetails.Remove(lineDetail);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }
    }
    #endregion
    #endregion	
	
    #region "Input Wastage Line Details"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID, or InputID provided was found")]
    public class WorkOrderInputWastageLineDetailsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input wastage line detail with the WorkOrderID, StageID, InputID, or LineDetailID provided was found")]
    public class WorkOrderInputWastageLineDetailGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID, or InputID provided was found")]
    public class WorkOrderInputWastageLineDetailPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]    
    public class WorkOrderInputWastageLineDetailPUTRequest : List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;, IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {	
		public string WorkOrderID { get; set; }
		public string StageID { get; set; }
		public string InputID { get; set; }
    }	
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input wastage line detail with the WorkOrderID, StageID, InputID, or LineDetailID provided was found")]
    public class WorkOrderInputWastageLineDetailPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public override string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input wastage line detail with the WorkOrderID, StageID, InputID, or LineDetailID provided was found")]
    public class WorkOrderInputWastageLineDetailDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
        public string LineDetailID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderInputWastageLineDetailServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Get(WorkOrderInputWastageLineDetailsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            return input.WastageLineDetails.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Get(WorkOrderInputWastageLineDetailGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; wastageLineDetail = input.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return wastageLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Post(WorkOrderInputWastageLineDetailPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            // Add the line detail. Need to jump through a few hoops as we want to know the DetailsLineID so we can return that in the response header.	
            var wastageLineDetails = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;();
            wastageLineDetails.Add(request);
            string LineDetailID = "";
            JiwaFinancials.Jiwa.JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt;&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                LineDetailID = item.RecID;
                input.WastageLineDetails.Added -= addedHandler; // remove handler						
            };

            input.WastageLineDetails.Added += addedHandler;
            input.WastageLineDetails.DTO_Deserialise(wastageLineDetails);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; wastageLineDetail = input.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], wastageLineDetail.RecID));

            return wastageLineDetail.DTO_Serialise();
        }
		
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Put(WorkOrderInputWastageLineDetailPUTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

			// remove any existing line details
			input.WastageLineDetails.RemoveAll();
			
			// Now add new line details as provided
			input.WastageLineDetails.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            return input.WastageLineDetails.DTO_Serialise();		
        }			

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Patch(WorkOrderInputWastageLineDetailPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; wastageLineDetail = input.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            wastageLineDetail.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            wastageLineDetail = input.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return wastageLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderInputWastageLineDetailDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt; wastageLineDetail = input.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            input.WastageLineDetails.Remove(wastageLineDetail);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }
    }
    #endregion
    #endregion		
	
    #region "Inputs"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID, or InputID provided was found")]
    public class WorkOrderInputGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage inputs with the WorkOrderID or StageID provided was found")]
    public class WorkOrderInputsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID or InputID provided was found")]
    public class WorkOrderInputPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID, or InputID provided was found")]
    public class WorkOrderInputPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public override string InputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage input with the WorkOrderID, StageID, or InputID provided was found")]
    public class WorkOrderInputDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InputID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderInputServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput Get(WorkOrderInputGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            return input.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput&gt; Get(WorkOrderInputsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.InputItems.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput Post(WorkOrderInputPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            // Add the input. Need to jump through a few hoops as we want to know the InputID so we can return that in the response header.	
            var inputs = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput&gt;();
            inputs.Add(request);
            string InputID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                InputID = item.RecID;
                stage.InputItems.Added -= addedHandler; // remove handler						
            };

            stage.InputItems.Added += addedHandler;
            stage.InputItems.DTO_Deserialise(inputs);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem WorkOrderInput = stage.InputItems.GetItem("RecID", InputID);

            if (WorkOrderInput == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", InputID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], WorkOrderInput.RecID));

            return WorkOrderInput.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInput Patch(WorkOrderInputPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            input.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            return input.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderInputDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.InputItem input = stage.InputItems.GetItem("RecID", request.InputID);

            if (input == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage input with InputID '{0}' was found.", request.InputID));

            stage.InputItems.Remove(input);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
            }
        }
    }
    #endregion
    #endregion		
	
    #region "Instructions"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instruction with the WorkOrderID, StageID, or InstructionID provided was found")]
    public class WorkOrderInstructionGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instructions with the WorkOrderID or StageID provided was found")]
    public class WorkOrderInstructionsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instruction with the WorkOrderID, StageID or InstructionID provided was found")]
    public class WorkOrderInstructionPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instruction with the WorkOrderID, StageID, or InstructionID provided was found")]
    public class WorkOrderInstructionPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public override string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instruction with the WorkOrderID, StageID, or InstructionID provided was found")]
    public class WorkOrderInstructionDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderInstructionServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction Get(WorkOrderInstructionGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction WorkOrderInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (WorkOrderInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            return WorkOrderInstruction.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction&gt; Get(WorkOrderInstructionsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.Instructions.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction Post(WorkOrderInstructionPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            // Add the instruction. Need to jump through a few hoops as we want to know the InstructionID so we can return that in the response header.	
            var instructions = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction&gt;();
            instructions.Add(request);
            string InstructionID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                InstructionID = item.RecID;
                stage.Instructions.Added -= addedHandler; // remove handler						
            };

            stage.Instructions.Added += addedHandler;
            stage.Instructions.DTO_Deserialise(instructions);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction WorkOrderInstruction = stage.Instructions.GetItem("RecID", InstructionID);

            if (WorkOrderInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", InstructionID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], WorkOrderInstruction.RecID));

            return WorkOrderInstruction.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderInstruction Patch(WorkOrderInstructionPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction WorkOrderInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (WorkOrderInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            WorkOrderInstruction.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            WorkOrderInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (WorkOrderInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            return WorkOrderInstruction.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderInstructionDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction WorkOrderInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (WorkOrderInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            stage.Instructions.Remove(WorkOrderInstruction);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
            }
        }
    }
    #endregion
    #endregion	
	
    #region "Instruction Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderInstructionCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instruction WorkOrderID, StageID or InstructionID provided was found")]
    public class WorkOrderInstructionCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderInstructionCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instruction custom field Value with the WorkOrderID, StageID, InstructionID or SettingID provided was found")]
    public class WorkOrderInstructionCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage instruction custom field Value with the WorkOrderID, StageID, InstructionID or SettingID provided was found")]
    public class WorkOrderInstructionCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string InstructionID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderInstructionCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(WorkOrderInstructionCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction WorkOrderInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (WorkOrderInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            return WorkOrderInstruction.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(WorkOrderInstructionCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction WorkOrderInstruction = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (WorkOrderInstruction == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in WorkOrderInstruction.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(WorkOrderInstructionCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Instruction instructionItem = stage.Instructions.GetItem("RecID", request.InstructionID);

            if (instructionItem == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction with InstructionID '{0}' was found.", request.InstructionID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = instructionItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);

                instructionItem = stage.Instructions.GetItem("RecID", request.InstructionID);
                customFieldValue = instructionItem.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(WorkOrderInstructionCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);
            return workOrder.InstructionCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(WorkOrderInstructionCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);

            var WorkOrderInstructionCustomField = workOrder.InstructionCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (WorkOrderInstructionCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage instruction custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return WorkOrderInstructionCustomField;
        }		
    }
    #endregion
    #endregion			
	
    #region "Note Types"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order note type with the NoteTypeID provided was found")]
    public class WorkOrderNoteTypeGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderNoteTypesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderNoteTypePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order note type with the NoteTypeID provided was found")]
    public class WorkOrderNoteTypePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;
    {
        public override string NoteTypeID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order note type with the NoteTypeID provided was found")]
    public class WorkOrderNoteTypeDELETERequest
    {
        public string NoteTypeID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderNoteTypeServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Get(WorkOrderNoteTypeGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.NoteTableNames.Add("BM_WorkOrderNotes");
                    d.Read();
                });

            JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt; Get(WorkOrderNoteTypesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.NoteTableNames.Add("BM_WorkOrderNotes");
                    d.Read();
                });

            return noteTypes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Post(WorkOrderNoteTypePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.NoteTableNames.Add("BM_WorkOrderNotes");
                    d.Read();
                });

            // Add the note type. Need to jump through a few hoops as we want to know the NoteTypeID so we can return that in the response header.	
            var dtoNoteTypes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType&gt;();
            dtoNoteTypes.Add(request);
            string noteTypeID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaNoteTypes.NoteType&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteTypeID = item.RecID;
                noteTypes.Added -= addedHandler; // remove handler						
            };

            noteTypes.Added += addedHandler;
            noteTypes.DTO_Deserialise(dtoNoteTypes);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", noteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note type with NoteTypeID '{0}' was found.", noteTypeID));

            // Add the location to the response header						
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0].Split(new[] { '?' })[0], noteType.RecID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.NoteType Patch(WorkOrderNoteTypePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.NoteTableNames.Add("BM_WorkOrderNotes");
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteType.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }

            noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            return noteType.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderNoteTypeDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaNoteTypes.NoteTypeCollection noteTypes = Helper.Service.GetListMaintenanceBusinessLogic&lt;JiwaNoteTypes.NoteType, JiwaNoteTypes.NoteTypeCollection&gt;(manager, this, "JiwaFinancials.Jiwa.JiwaSales.WorkOrder.WorkOrder",
                (d, m, s) =&gt;
                {
                    d.NoteType = "JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder";
					d.NoteTableNames.Add("BM_WorkOrderNotes");
                    d.Read();
                });

            JiwaFinancials.Jiwa.JiwaNoteTypes.NoteType noteType = noteTypes.GetItem("RecID", request.NoteTypeID);

            if (noteType == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note type with NoteTypeID '{0}' was found.", request.NoteTypeID));

            noteTypes.Remove(noteType);

            if (!Helper.Service.IsStateful(this))
            {
                noteTypes.Save();
                noteTypes.Read();
            }
        }
    }
    #endregion
    #endregion

    #region "Notes"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order note with the WorkOrderID or NoteID provided was found")]
    public class WorkOrderNoteGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string WorkOrderID { get; set; }
        public string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderNotesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderNotePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string WorkOrderID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string NoteID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override DateTime? LastSavedDateTime { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderNotePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;
    {
        public string WorkOrderID { get; set; }
        public override string NoteID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderNoteDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string NoteID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderNoteServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Get(WorkOrderNoteGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = workOrder.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt; Get(WorkOrderNotesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            return workOrder.Notes.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Post(WorkOrderNotePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the note. Need to jump through a few hoops as we want to know the NoteID so we can return that in the response header.	
            var notes = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note&gt;();
            notes.Add(request);
            string noteID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaApplication.Notes.Note&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                noteID = item.RecID;
                workOrder.Notes.Added -= addedHandler; // remove handler						
            };

            workOrder.Notes.Added += addedHandler;
            workOrder.Notes.DTO_Deserialise(notes);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = workOrder.Notes.GetItem("RecID", noteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note with NoteID '{0}' was found.", noteID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], note.RecID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Notes.Note Patch(WorkOrderNotePATCHRequest request)
        {

            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaApplication.Notes.Note note = workOrder.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note with NoteID '{0}' was found.", request.NoteID));

            note.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            note = workOrder.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note with NoteID '{0}' was found.", request.NoteID));

            return note.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderNoteDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaApplication.Notes.Note note = workOrder.Notes.GetItem("RecID", request.NoteID);

            if (note == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order note with NoteID '{0}' was found.", request.NoteID));

            workOrder.Notes.Remove(note);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }
    }
    #endregion
    #endregion			
	
    #region "Output Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderOutputCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output output WorkOrderID or OutputID provided was found")]
    public class WorkOrderOutputCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderOutputCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output output custom field Value with the WorkOrderID, OutputID or SettingID provided was found")]
    public class WorkOrderOutputCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output custom field value with the WorkOrderID, OutputID or SettingID provided was found")]
    public class WorkOrderOutputCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderOutputCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(WorkOrderOutputCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            return output.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(WorkOrderOutputCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in output.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(WorkOrderOutputCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = output.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);

                output = workOrder.OutputItems.GetItem("RecID", request.OutputID);
                customFieldValue = output.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(WorkOrderOutputCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);
            return workOrder.OutputCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(WorkOrderOutputCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);

            var WorkOrderOutputCustomField = workOrder.OutputCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (WorkOrderOutputCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return WorkOrderOutputCustomField;
        }		
    }
    #endregion
    #endregion		
	
    #region "Output Line Details"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output with the WorkOrderID or OutputID provided was found")]
    public class WorkOrderOutputLineDetailsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output line detail with the WorkOrderID, OutputID, or LineDetailID provided was found")]
    public class WorkOrderOutputLineDetailGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output with the WorkOrderID or OutputID provided was found")]
    public class WorkOrderOutputLineDetailPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LineDetailID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]    
    public class WorkOrderOutputLineDetailPUTRequest : List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;, IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {	
		public string WorkOrderID { get; set; }
		public string OutputID { get; set; }
    }			

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output line detail with the WorkOrderID, OutputID, or LineDetailID provided was found")]
    public class WorkOrderOutputLineDetailPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output line detail with the WorkOrderID, OutputID, or LineDetailID provided was found")]
    public class WorkOrderOutputLineDetailDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public string LineDetailID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderOutputLineDetailServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Get(WorkOrderOutputLineDetailsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            return output.LineDetails.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Get(WorkOrderOutputLineDetailGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; lineDetail = output.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return lineDetail.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Post(WorkOrderOutputLineDetailPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            // Add the line detail. Need to jump through a few hoops as we want to know the DetailsLineID so we can return that in the response header.	
            var lineDetails = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;();
            lineDetails.Add(request);
            string lineDetailID = "";
            JiwaFinancials.Jiwa.JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt;&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                lineDetailID = item.RecID;
                output.LineDetails.Added -= addedHandler; // remove handler						
            };

            output.LineDetails.Added += addedHandler;
            output.LineDetails.DTO_Deserialise(lineDetails);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; lineDetail = output.LineDetails.GetItem("RecID", lineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output line detail with LineDetailID '{0}' was found.", lineDetailID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], lineDetail.RecID));

            return lineDetail.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Put(WorkOrderOutputLineDetailPUTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });


            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

			// remove any existing line details
			output.LineDetails.RemoveAll();
			
			// Now add new line details as provided
			output.LineDetails.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            return output.LineDetails.DTO_Serialise();		
        }				
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Patch(WorkOrderOutputLineDetailPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; lineDetail = output.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            lineDetail.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            lineDetail = output.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return lineDetail.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderOutputLineDetailDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; lineDetail = output.LineDetails.GetItem("RecID", request.LineDetailID);

            if (lineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            output.LineDetails.Remove(lineDetail);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }
    }
    #endregion
    #endregion	
	
    #region "Output Wastage Line Details"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output with the WorkOrderID or OutputID provided was found")]
    public class WorkOrderOutputWastageLineDetailsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output wastage line detail with the WorkOrderID, OutputID, or LineDetailID provided was found")]
    public class WorkOrderOutputWastageLineDetailGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output with the WorkOrderID or OutputID provided was found")]
    public class WorkOrderOutputWastageLineDetailPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string LineDetailID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]    
    public class WorkOrderOutputWastageLineDetailPUTRequest : List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;, IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;&gt;
    {	
		public string WorkOrderID { get; set; }
		public string OutputID { get; set; }
    }	

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output wastage line detail with the WorkOrderID, OutputID, or LineDetailID provided was found")]
    public class WorkOrderOutputWastageLineDetailPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public string LineDetailID { get; set; }
    }

	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output wastage line detail with the WorkOrderID, OutputID, or LineDetailID provided was found")]
    public class WorkOrderOutputWastageLineDetailDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
        public string LineDetailID { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderOutputWastageLineDetailServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Get(WorkOrderOutputWastageLineDetailsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            return output.WastageLineDetails.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Get(WorkOrderOutputWastageLineDetailGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

			JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; wastageLineDetail = output.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return wastageLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Post(WorkOrderOutputWastageLineDetailPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            // Add the line detail. Need to jump through a few hoops as we want to know the DetailsLineID so we can return that in the response header.	
            var wastageLineDetails = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt;();
            wastageLineDetails.Add(request);
            string LineDetailID = "";
            JiwaFinancials.Jiwa.JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt;&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                LineDetailID = item.RecID;
                output.WastageLineDetails.Added -= addedHandler; // remove handler						
            };

            output.WastageLineDetails.Added += addedHandler;
            output.WastageLineDetails.DTO_Deserialise(wastageLineDetails);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; wastageLineDetail = output.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], wastageLineDetail.RecID));

            return wastageLineDetail.DTO_Serialise();
        }
		
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail&gt; Put(WorkOrderOutputWastageLineDetailPUTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });


            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

			// remove any existing line details
			output.WastageLineDetails.RemoveAll();
			
			// Now add new line details as provided
			output.WastageLineDetails.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            return output.WastageLineDetails.DTO_Serialise();		
        }				

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.Inventory.SOH.InventorySOHLineDetail Patch(WorkOrderOutputWastageLineDetailPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; wastageLineDetail = output.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            wastageLineDetail.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

			output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            wastageLineDetail = output.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            return wastageLineDetail.DTO_Serialise();
        }

        [Authenticate]
        public void Delete(WorkOrderOutputWastageLineDetailDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            JiwaFinancials.Jiwa.JiwaApplication.Inventory.SOH.LineDetail&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt; wastageLineDetail = output.WastageLineDetails.GetItem("RecID", request.LineDetailID);

            if (wastageLineDetail == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output wastage line detail with LineDetailID '{0}' was found.", request.LineDetailID));

            output.WastageLineDetails.Remove(wastageLineDetail);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }
    }
    #endregion
    #endregion			
	
    #region "Outputs"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order output with the WorkOrderID or OutputID provided was found")]
    public class WorkOrderOutputGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput&gt;
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderOutputsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput&gt;&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderOutputPOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput&gt;
    {
        public string WorkOrderID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string OutputID { get; set; }
    }	
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID, or OutputID provided was found")]
    public class WorkOrderOutputPATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput&gt;
    {
        public string WorkOrderID { get; set; }
        override public string OutputID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderOutputDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string OutputID { get; set; }
    }	
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderOutputServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput Get(WorkOrderOutputGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (i, m, s) =&gt;
                {
                    i.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            return output.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput&gt; Get(WorkOrderOutputsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (i, m, s) =&gt;
                {
                    i.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            return workOrder.OutputItems.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput Post(WorkOrderOutputPOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the output. Need to jump through a few hoops as we want to know the OutputID so we can return that in the response header.	
            var outputs = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput&gt;();
            outputs.Add(request);
            string outputID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                outputID = item.RecID;
                workOrder.OutputItems.Added -= addedHandler; // remove handler						
            };

            workOrder.OutputItems.Added += addedHandler;
            workOrder.OutputItems.DTO_Deserialise(outputs);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", outputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", outputID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], output.RecID));

            return output.DTO_Serialise();
        }		

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderOutput Patch(WorkOrderOutputPATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (i, m, s) =&gt;
                {
                    i.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));

            output.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);

                output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

                if (output == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No output with OutputID '{0}' was found.", request.OutputID));
            }

            return output.DTO_Serialise();
        }
		
        [Authenticate]
        public void Delete(WorkOrderOutputDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.OutputItem output = workOrder.OutputItems.GetItem("RecID", request.OutputID);

            if (output == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order output with OutputID '{0}' was found.", request.OutputID));

            workOrder.OutputItems.Remove(output);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }		
    }
    #endregion
    #endregion			
	
    #region "Stage Custom Fields"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderStageCustomFieldsGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;&gt;
    {
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage stage WorkOrderID or StageID provided was found")]
    public class WorkOrderStageCustomFieldValuesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    public class WorkOrderStageCustomFieldGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt;
    {
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage stage custom field Value with the WorkOrderID, StageID or SettingID provided was found")]
    public class WorkOrderStageCustomFieldValueGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public string SettingID { get; set; }
    }

	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage custom field value with the WorkOrderID, StageID or SettingID provided was found")]
    public class WorkOrderStageCustomFieldValuePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
        public override string SettingID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string SettingName { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string PluginName { get; set; }
    }
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderStageCustomFieldServices : Service
    {
        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue&gt; Get(WorkOrderStageCustomFieldValuesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.CustomFieldValues.DTO_Serialise();
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Get(WorkOrderStageCustomFieldValueGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            foreach (JiwaApplication.CustomFields.CustomFieldValue customFieldValue in stage.CustomFieldValues)
            {
                if (customFieldValue.CustomField.RecID.Trim() == request.SettingID.Trim())
                {
                    return customFieldValue.DTO_Serialise();
                }
            }

            // if we got to here, it means we didn't find a custom field value with that settingID
            throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));
        }

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomFieldValue Patch(WorkOrderStageCustomFieldValuePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (o, m, s) =&gt;
                {
                    o.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(o.RecID, o);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            JiwaFinancials.Jiwa.JiwaApplication.CustomFields.CustomFieldValue customFieldValue = stage.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

            if (customFieldValue == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage custom field value with SettingID '{0}' was found.", request.SettingID));

            customFieldValue.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);

                stage = workOrder.Stages.GetItem("RecID", request.StageID);
                customFieldValue = stage.CustomFieldValues.get_ItemFromSettingID(request.SettingID);

                if (customFieldValue == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage custom field value with SettingID '{0}' was found.", request.SettingID));
            }

            return customFieldValue.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField&gt; Get(WorkOrderStageCustomFieldsGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();
            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);
            return workOrder.StageCustomFields.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.CustomFields.CustomField Get(WorkOrderStageCustomFieldGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, null, null);

            var WorkOrderStageCustomField = workOrder.StageCustomFields.DTO_Serialise().Find(x =&gt; x.SettingID.Trim() == request.SettingID.Trim());

            if (WorkOrderStageCustomField == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage custom field with SettingID '{0}' was found. Make sure the plugin it is defined in is enabled.", request.SettingID));

            return WorkOrderStageCustomField;
        }		
    }
    #endregion
    #endregion	
	
    #region "Stages"
    #region "Requests"
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order stage with the WorkOrderID or StageID provided was found")]
    public class WorkOrderStageGETRequest : IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage&gt;
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(200, "Read OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID provided was found")]
    public class WorkOrderStagesGETManyRequest : IReturn&lt;List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage&gt;&gt;
    {
        public string WorkOrderID { get; set; }
    }

	[Serializable()]
    [ApiResponse(201, "Created OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderStagePOSTRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage&gt;
    {
        public string WorkOrderID { get; set; }
        [System.Runtime.Serialization.IgnoreDataMember]
        public override string StageID { get; set; }
    }	
	
	[Serializable()]
    [ApiResponse(200, "Updated OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order record with the WorkOrderID, or StageID provided was found")]
    public class WorkOrderStagePATCHRequest : JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage, IReturn&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage&gt;
    {
        public string WorkOrderID { get; set; }
        override public string StageID { get; set; }
    }
	
	[Serializable()]
    [ApiResponse(204, "Deleted OK")]
    [ApiResponse(401, "Not authenticated")]
    [ApiResponse(403, "Not authorised")]
    [ApiResponse(404, "No work order with the WorkOrderID provided was found")]
    public class WorkOrderStageDELETERequest
    {
        public string WorkOrderID { get; set; }
        public string StageID { get; set; }
    }	
    #endregion

    #region "Services"				
    [CompressResponse]
    public class WorkOrderStageServices : Service
    {
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage Get(WorkOrderStageGETRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (i, m, s) =&gt;
                {
                    i.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            return stage.DTO_Serialise();
        }

        [Authenticate]
        public List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage&gt; Get(WorkOrderStagesGETManyRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (i, m, s) =&gt;
                {
                    i.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            return workOrder.Stages.DTO_Serialise();
        }
		
        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage Post(WorkOrderStagePOSTRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            // Add the stage. Need to jump through a few hoops as we want to know the StageID so we can return that in the response header.	
            var stages = new List&lt;JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage&gt;();
            stages.Add(request);
            string stageID = "";
            JiwaApplication.IJiwaCollection&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage&gt;.AddedEventHandler addedHandler = null;
            addedHandler = (item) =&gt;
            {
                stageID = item.RecID;
                workOrder.Stages.Added -= addedHandler; // remove handler						
            };

            workOrder.Stages.Added += addedHandler;
            workOrder.Stages.DTO_Deserialise(stages);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", stageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage with StageID '{0}' was found.", stageID));

            // Add the location to the response header
            base.Response.AddHeader("Location", String.Format("{0}/{1}", base.Request.AbsoluteUri.Split(new[] { '?' })[0], stage.RecID));

            return stage.DTO_Serialise();
        }		

        [Authenticate]
        public JiwaFinancials.Jiwa.JiwaServiceModel.WorkOrders.WorkOrderStage Patch(WorkOrderStagePATCHRequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (i, m, s) =&gt;
                {
                    i.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(i.RecID, i);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));

            stage.DTO_Deserialise(request);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);

                stage = workOrder.Stages.GetItem("RecID", request.StageID);

                if (stage == null)
                    throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No stage with StageID '{0}' was found.", request.StageID));
            }

            return stage.DTO_Serialise();
        }
		
        [Authenticate]
        public void Delete(WorkOrderStageDELETERequest request)
        {
            JiwaFinancials.Jiwa.JiwaApplication.Manager manager = this.GetManager();

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder workOrder = Helper.Service.GetMaintenanceBusinessLogic&lt;JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder&gt;(manager, this, request.WorkOrderID,
                (d, m, s) =&gt;
                {
                    d.Read(request.WorkOrderID);
                    if (Helper.Service.IsStateful(s))
                    {
                        m.ObjectDictionary.Add(d.RecID, d);
                    }
                });

            JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.Stage stage = workOrder.Stages.GetItem("RecID", request.StageID);

            if (stage == null)
                throw new JiwaFinancials.Jiwa.JiwaApplication.Exceptions.RecordNotFoundException(String.Format("No work order stage with StageID '{0}' was found.", request.StageID));

            workOrder.Stages.Remove(stage);

            if (!Helper.Service.IsStateful(this))
            {
                workOrder.Save();
                workOrder.Read(workOrder.RecID);
            }
        }		
    }
    #endregion
    #endregion		
	#endregion
}

#region "Helpers"
namespace JiwaFinancials.Jiwa.JiwaServiceModel.Helper
{
	#region "Serialise"
	public static class Serialisation
	{
		public static List&lt;T&gt; SqlDataReaderToList&lt;T&gt;(SqlDataReader reader) where T : new()
		{
			// returns a List of &lt;T&gt;, given a reader
			List&lt;T&gt; list = new List&lt;T&gt;();
			var columns = new List&lt;string&gt;();
		    for (var i = 0; i &lt; reader.FieldCount; i++) 
		        columns.Add(reader.GetName(i));
			
			while (reader.Read()) 
			{
				T item = new T();
				foreach(string columnName in columns)
				{
					//JiwaApplication.Manager.SetPropertyValue(item, columnName, JiwaApplication.Manager.Instance.Database.Sanitise(reader, columnName) , null);						
					PropertyInfo property = item.GetType().GetProperty(columnName, BindingFlags.Public | BindingFlags.Instance);
					if(null != property &amp;&amp; property.CanWrite)
					{
						property.SetValue(item, reader[columnName], null);
					}
				}
				
				list.Add(item);
			}								
			
			return list;
		}
			
		public static IEnumerable&lt;Dictionary&lt;string, object&gt;&gt; Serialise(SqlDataReader reader)
		{
		    var results = new List&lt;Dictionary&lt;string, object&gt;&gt;();
		    var columns = new List&lt;string&gt;();
		    for (var i = 0; i &lt; reader.FieldCount; i++) 
		        columns.Add(reader.GetName(i));

		    while (reader.Read()) 
		        results.Add(SerialiseRow(columns, reader));

		    return results;
		}
		
		private static Dictionary&lt;string, object&gt; SerialiseRow(IEnumerable&lt;string&gt; columns, SqlDataReader reader) 
		{
		    var result = new Dictionary&lt;string, object&gt;();
		    foreach (var column in columns) 
		        result.Add(column, reader[column]);
		    return result;
		}
	}		
	#endregion
	
	#region "Service"
	public static class Service
	{						
		public static T GetMaintenanceBusinessLogic&lt;T&gt;(JiwaApplication.Manager Manager, ServiceStack.Service Service, string ObjectDictionaryKey, Action&lt;T, JiwaApplication.Manager, ServiceStack.Service&gt; PostFactoryCreateAction) where T:JiwaFinancials.Jiwa.JiwaApplication.BusinessLogic.Maintenance, new()
		{
			T businessLogic = null;
			if (IsStateful(Service) &amp;&amp; ObjectDictionaryKey != null)
			{
				object objectDictionaryValue = null;
				if (! Manager.ObjectDictionary.TryGetValue(ObjectDictionaryKey, out objectDictionaryValue))				
				{
					businessLogic = Manager.BusinessLogicFactory.CreateBusinessLogic&lt;T&gt;(null);	
					if (PostFactoryCreateAction != null)
						PostFactoryCreateAction(businessLogic, Manager, Service);
				}
				else
					businessLogic = (T)objectDictionaryValue;
			}
			else
			{
				businessLogic = Manager.BusinessLogicFactory.CreateBusinessLogic&lt;T&gt;(null);
				
				if (PostFactoryCreateAction != null)
					PostFactoryCreateAction(businessLogic, Manager, Service);
			}
			
			return businessLogic;
		}
		
		public static T GetMultiListMaintenance&lt;T&gt;(JiwaApplication.Manager Manager, ServiceStack.Service Service, string ObjectDictionaryKey, Action&lt;T, JiwaApplication.Manager, ServiceStack.Service&gt; PostFactoryCreateAction) where T:JiwaFinancials.Jiwa.JiwaApplication.BusinessLogic.MultiListMaintenance, new()
		{
			T businessLogic = null;
			if (IsStateful(Service) &amp;&amp; ObjectDictionaryKey != null)
			{
				object objectDictionaryValue = null;
				if (! Manager.ObjectDictionary.TryGetValue(ObjectDictionaryKey, out objectDictionaryValue))
				{
					businessLogic = Manager.BusinessLogicFactory.CreateBusinessLogic&lt;T&gt;(null);
					if (PostFactoryCreateAction != null)
						PostFactoryCreateAction(businessLogic, Manager, Service);
					
					objectDictionaryValue = businessLogic;					
				}						
				businessLogic = (T)objectDictionaryValue;
			}
			else
			{
				businessLogic = Manager.BusinessLogicFactory.CreateBusinessLogic&lt;T&gt;(null);
				if (PostFactoryCreateAction != null)
					PostFactoryCreateAction(businessLogic, Manager, Service);				
			}
			
			return businessLogic;			
		}
		
		public static ListType GetListMaintenanceBusinessLogic&lt;ListItemType, ListType&gt;(JiwaApplication.Manager Manager, ServiceStack.Service Service, string ObjectDictionaryKey, Action&lt;ListType, JiwaApplication.Manager, ServiceStack.Service&gt; PostFactoryCreateAction) 
			where ListType: JiwaFinancials.Jiwa.JiwaApplication.BusinessLogic.ListMaintenance&lt;ListItemType&gt;, new()
			where ListItemType: JiwaFinancials.Jiwa.JiwaApplication.JiwaCollectionItem&lt;ListItemType&gt;, new()			
		{
			ListType businessLogic = null;
			if (IsStateful(Service) &amp;&amp; ObjectDictionaryKey != null)
			{
				object objectDictionaryValue = null;
				if (! Manager.ObjectDictionary.TryGetValue(ObjectDictionaryKey, out objectDictionaryValue))
				{
					businessLogic = Manager.BusinessLogicFactory.CreateBusinessLogic&lt;ListType&gt;(null);
					
					if (PostFactoryCreateAction != null)
						PostFactoryCreateAction(businessLogic, Manager, Service);
					
					Manager.ObjectDictionary.Add(ObjectDictionaryKey, businessLogic);
					objectDictionaryValue = businessLogic;
				}						
				businessLogic = (ListType)objectDictionaryValue;
			}
			else
			{				
				businessLogic = Manager.BusinessLogicFactory.CreateBusinessLogic&lt;ListType&gt;(null);	
				
				if (PostFactoryCreateAction != null)
					PostFactoryCreateAction(businessLogic, Manager, Service);
				
			}
			
			return businessLogic;
		}
		
		public static bool IsStateful(ServiceStack.Service Service)
        {
            return IsStateful(Service.Request);
        }

        public static Boolean IsStateful(IRequest request)
        {
            string statefulHeaderValue = request.GetHeader("jiwa-stateful");

            if (statefulHeaderValue != null &amp;&amp; statefulHeaderValue == "true")
                return true;

            return false;
        }				
	}	
	#endregion
	
	#region "EventLog"
	public static class EventLog
	{
		// NOTE: If this is running in an Azure App service, then you cannot log to the event log.
		static public void Log(string Message, System.Diagnostics.EventLogEntryType EventLogEntryType)
		{
			string source = "REST API";
			var Log = new System.Diagnostics.EventLog("Application");
			if (! System.Diagnostics.EventLog.SourceExists(source))
				System.Diagnostics.EventLog.CreateEventSource(source, "Application");
			
			Log.Source = source;
			Log.WriteEntry(Message, EventLogEntryType);
			Log.Close();
		}
	}
	#endregion
}

public static class JiwaExtensions
{
	// Extension method for ServiceStack.Service to get the manager (or null) for the session.
	public static JiwaFinancials.Jiwa.JiwaApplication.Manager GetManager(this ServiceStack.Service Service)
	{
		JiwaFinancials.Jiwa.JiwaApplication.Manager manager = null;			
		JiwaFinancials.Jiwa.JiwaServiceModel.RESTAPIPlugin.JiwaSessionDictionary.TryGetValue(Service.GetSession().Id, out manager);
		return manager;
	}		
	
	public static string CreateObjectDictionaryKey&lt;T&gt;(this string RecID)
	{
		return String.Format("{0}:{1}", typeof(T).ToString(), RecID == null ? "" : RecID);
	}
	
	public static IEnumerable&lt;T&gt; FlattenChildren&lt;T&gt;(this IEnumerable&lt;T&gt; List, Func&lt;T, IEnumerable&lt;T&gt;&gt; Selector)
    {
        var result = List.SelectMany(Selector);
        if (!result.Any())
        {
            return result;
        }
        return result.Concat(result.FlattenChildren(Selector));
    }
}
#endregion</Code>
  <ExceptionPolicy>Report</ExceptionPolicy>
  <Language>CSharp</Language>
  <BusinessLogicCollection>
    <BusinessLogic>
      <RecID>86828ac0-0fb4-4e29-9ba5-dbc14bd01dd6</RecID>
      <Description>Sales Order Entry</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaSales.SalesOrder.SalesOrder</ClassName>
      <Assembly>JiwaSales, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>986c958f-a36e-4573-bda0-c0634e064398</RecID>
      <Description>Inventory Maintenance</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaInventory.Inventory</ClassName>
      <Assembly>JiwaInventory, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>cd35bfbc-fa67-4fba-a8cb-67aa71155681</RecID>
      <Description>Debtors</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaDebtors.Debtor</ClassName>
      <Assembly>JiwaDebtors, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>cc09ceb8-3128-410b-b964-d08384fd94ff</RecID>
      <Description>Purchase Orders</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaPurchaseOrders.PurchaseOrder</ClassName>
      <Assembly>JiwaPurchaseOrders, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>b2c77edf-d3fb-4672-841b-e48ae3f19c74</RecID>
      <Description>Purchase Invoices</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaPurchaseInvoices.PurchaseInvoice</ClassName>
      <Assembly>JiwaPurchaseInvoices, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>bebfabf8-36bd-4bdd-9b80-52afd18a8382</RecID>
      <Description>Creditors</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaCreditors.Creditor</ClassName>
      <Assembly>JiwaCreditors, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>86e79239-4d33-47a6-a995-a9c0801f40bd</RecID>
      <Description>Debtor Classifications</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaDebtors.Configuration.Classification.Classification</ClassName>
      <Assembly>JiwaDebtors, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>ddc14c2b-2a11-4aa1-ab3e-77c521300b61</RecID>
      <Description>Debtor Pricing Groups</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaDBPricingGroups.PricingGroupCollection</ClassName>
      <Assembly>JiwaDBPricingGroups, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>3f9bc1b6-958f-4602-ab00-9269dc71ea30</RecID>
      <Description>Inventory Receival</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaInvReceival.Receival</ClassName>
      <Assembly>JiwaInvReceival, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>109fda1c-7fcb-43fd-ac23-cc48bd18343d</RecID>
      <Description>Landed Cost BookIn</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaLandedCost.BookIn.BookIn</ClassName>
      <Assembly>JiwaLandedCost, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>7766bdeb-938d-4df4-ad39-9389bd140437</RecID>
      <Description>Landed Cost Shipment</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaLandedCost.Shipment.Shipment</ClassName>
      <Assembly>JiwaLandedCost, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>fa59ef6a-0a59-40a4-815b-48b5dd499da7</RecID>
      <Description>Note Types</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaNoteTypes.NoteTypeCollection</ClassName>
      <Assembly>JiwaNoteTypes, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>b10edcb8-bebb-49d5-a04e-fca49f7f1cc9</RecID>
      <Description>Document Types</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaDocumentTypes.DocumentTypeCollection</ClassName>
      <Assembly>JiwaDocumentTypes, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>c0baf6ba-01b9-4794-ad39-6fc28229f663</RecID>
      <Description>Sales Quote Entry</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaSales.SalesQuote.SalesQuote</ClassName>
      <Assembly>JiwaSales, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>00a12ae5-8ed1-4ebe-a397-ca43ad1fb661</RecID>
      <Description>Warehouse Maintenance</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaWarehouses.PhysicalWarehouse</ClassName>
      <Assembly>JiwaWarehouses, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>fc07ef7e-49a9-4652-a9e5-0f6e3c8304f1</RecID>
      <Description>Payment Types Configuration</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaSales.Configuration.PaymentTypes.PaymentTypeCollection</ClassName>
      <Assembly>JiwaSales, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>4485904a-60cc-413a-a83a-92db3cb52a45</RecID>
      <Description>Inventory Categories</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaInventory.Configuration.Category.Categories</ClassName>
      <Assembly>JiwaInventory, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>d27f9d5c-efc8-44ce-af3d-ebb2eaeff073</RecID>
      <Description>Inventory Classifications</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaInventory.Configuration.Classification.Classification</ClassName>
      <Assembly>JiwaInventory, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>cb064a18-7cd5-47b8-bbeb-f31181916e23</RecID>
      <Description>Inventory Pricing Groups</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaInventory.Configuration.PricingGroup.PricingGroupCollection</ClassName>
      <Assembly>JiwaInventory, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>c39dec90-f22c-4445-839a-152c1f1a0efe</RecID>
      <Description>Tax Rates</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaApplication.JiwaTaxSystemRates.TaxRates</ClassName>
      <Assembly>JiwaApplication, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>cde5defe-0740-411d-9583-fc2cd7748422</RecID>
      <Description>Bill Maintenance</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaBillOfMaterials.BillMaintenance.BillMaintenance</ClassName>
      <Assembly>JiwaBillOfMaterials, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
    <BusinessLogic>
      <RecID>19df9cc8-cf84-4908-acce-892581cee2e5</RecID>
      <Description>Work Order</Description>
      <ClassName>JiwaFinancials.Jiwa.JiwaBillOfMaterials.WorkOrder.WorkOrder</ClassName>
      <Assembly>JiwaBillOfMaterials, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</Assembly>
    </BusinessLogic>
  </BusinessLogicCollection>
  <ReferenceCollection>
    <Reference>
      <RecID>a05f39d5-8330-4da6-a558-3b3a01f9f8aa</RecID>
      <AssemblyFullName>JiwaApplication, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaApplication.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaApplication.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>21bce669-3cbc-45a6-8d5f-d157b55250bd</RecID>
      <AssemblyFullName>mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>mscorlib.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>5acb9ffa-0355-4ae1-a5f6-2db1fd2bbc1f</RecID>
      <AssemblyFullName>System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>System.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>4b1937d3-813e-479b-8d59-7b203d4e1828</RecID>
      <AssemblyFullName>Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</AssemblyFullName>
      <AssemblyName>Microsoft.VisualBasic.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>e2a9b5c5-a6ff-4a2f-ab95-d03e9914663b</RecID>
      <AssemblyFullName>System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</AssemblyFullName>
      <AssemblyName>System.Drawing.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Drawing\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>e5267ada-47e1-4041-b1c9-9619fd9154c5</RecID>
      <AssemblyFullName>JiwaODBC, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaODBC.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaODBC.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>cd365329-33fb-4ca9-919f-bd3883eb53b8</RecID>
      <AssemblyFullName>System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>System.Data.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>f894b250-193a-4d85-af64-809651895525</RecID>
      <AssemblyFullName>System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>System.Xml.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>ebaf007c-74ef-4f45-933a-762670440847</RecID>
      <AssemblyFullName>System.Runtime.Serialization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>System.Runtime.Serialization.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Runtime.Serialization\v4.0_4.0.0.0__b77a5c561934e089\System.Runtime.Serialization.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>17272b09-57bf-4266-be5d-ce95515433d3</RecID>
      <AssemblyFullName>Microsoft.SqlServer.Smo, Version=14.100.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91</AssemblyFullName>
      <AssemblyName>Microsoft.SqlServer.Smo.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\Microsoft.SqlServer.Smo.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>fed006aa-96cc-41b1-8f2b-d111c7de74d6</RecID>
      <AssemblyFullName>Microsoft.SqlServer.ConnectionInfo, Version=14.100.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91</AssemblyFullName>
      <AssemblyName>Microsoft.SqlServer.ConnectionInfo.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\Microsoft.SqlServer.ConnectionInfo.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>6f3791f2-1dc9-41c8-b502-bafd1d3b2418</RecID>
      <AssemblyFullName>System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>System.Windows.Forms.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>de9f406d-6584-4f2b-ab87-b76f9955b464</RecID>
      <AssemblyFullName>Infragistics4.Win.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>d155eb48-6bec-4104-97fd-b4cbf023493e</RecID>
      <AssemblyFullName>Infragistics4.Win.Misc.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.Misc.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.Misc.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.Misc.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>03232213-35d0-4eec-9623-9707c90f60c2</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinEditors.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinEditors.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinEditors.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinEditors.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>4aa17801-7f54-4ecb-9a86-9ab230821726</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinExplorerBar.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinExplorerBar.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinExplorerBar.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinExplorerBar.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>8846598c-7a79-434f-9196-ef004ae498c8</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinTree.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinTree.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinTree.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinTree.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>b8b491e7-245f-4a8c-9b28-3e297869446a</RecID>
      <AssemblyFullName>FarPoint.Win.Spread, Version=8.35.20151.0, Culture=neutral, PublicKeyToken=327c3516b1b18457</AssemblyFullName>
      <AssemblyName>FarPoint.Win.Spread.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\FarPoint.Win.Spread\8.35.20151.0__327c3516b1b18457\FarPoint.Win.Spread.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>44480b09-0b82-4414-8b67-07d289a6922f</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinTabControl.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinTabControl.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinTabControl.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinTabControl.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>ef2f272d-592b-4b2b-9251-1f5096f1db9c</RecID>
      <AssemblyFullName>Infragistics4.Shared.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Shared.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Shared.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Shared.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>edffc9c9-2329-44b7-8636-5517aeafe1e1</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinToolbars.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinToolbars.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinToolbars.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinToolbars.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>c2d2f59b-52e2-4e95-aa51-1d7d89dfe1d2</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinStatusBar.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinStatusBar.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinStatusBar.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinStatusBar.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>65d5ee7a-953b-4de6-8895-cb176a2e3a3e</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinSchedule.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinSchedule.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinSchedule.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinSchedule.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>2e5d6948-b1ab-4b1e-ab49-158f77c91628</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinListView.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinListView.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinListView.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinListView.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>2a50e698-7bcc-4d8f-acd2-9d62e9294a6c</RecID>
      <AssemblyFullName>ServiceStack, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>2bdd83b2-c9a1-4569-bc1f-38e59d9576ef</RecID>
      <AssemblyFullName>ActiproSoftware.SyntaxEditor.WinForms, Version=16.1.330.0, Culture=neutral, PublicKeyToken=c27e062d3c1a4763</AssemblyFullName>
      <AssemblyName>ActiproSoftware.SyntaxEditor.WinForms.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\ActiproSoftware.SyntaxEditor.WinForms\16.1.330.0__c27e062d3c1a4763\ActiproSoftware.SyntaxEditor.WinForms.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>6d091343-f632-4535-8502-a3f8f45663e7</RecID>
      <AssemblyFullName>ZetaHtmlEditControl, Version=1.1.0.3, Culture=neutral, PublicKeyToken=2e2e5ba5da72b6c0</AssemblyFullName>
      <AssemblyName>ZetaHtmlEditControl.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ZetaHtmlEditControl.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>bb4efa49-4595-41d1-bb69-b0a6d66dd8a7</RecID>
      <AssemblyFullName>ActiproSoftware.SyntaxEditor.Addons.DotNet.WinForms, Version=16.1.330.0, Culture=neutral, PublicKeyToken=c27e062d3c1a4763</AssemblyFullName>
      <AssemblyName>ActiproSoftware.SyntaxEditor.Addons.DotNet.WinForms.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\ActiproSoftware.SyntaxEditor.Addons.DotNet.WinForms\16.1.330.0__c27e062d3c1a4763\ActiproSoftware.SyntaxEditor.Addons.DotNet.WinForms.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>798edcbe-7fb2-4c62-975e-34db16e9951b</RecID>
      <AssemblyFullName>System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</AssemblyFullName>
      <AssemblyName>System.Security.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Security\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Security.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>4ad75f83-5fb0-4830-be55-18502affa998</RecID>
      <AssemblyFullName>JiwaEncryption, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaEncryption.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaEncryption.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>4a2837cd-86df-4cf9-b566-0bb2f0dc84be</RecID>
      <AssemblyFullName>Microsoft.SqlServer.Dac, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</AssemblyFullName>
      <AssemblyName>Microsoft.SqlServer.Dac.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\Microsoft.SqlServer.Dac.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>524f0d15-493b-4c8b-8d25-d78bd5cf90eb</RecID>
      <AssemblyFullName>CrystalDecisions.CrystalReports.Engine, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304</AssemblyFullName>
      <AssemblyName>CrystalDecisions.CrystalReports.Engine.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\CrystalDecisions.CrystalReports.Engine\13.0.3500.0__692fbea5521e1304\CrystalDecisions.CrystalReports.Engine.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>f7c10ed3-96ab-4f9b-8da1-5465621da7d6</RecID>
      <AssemblyFullName>CrystalDecisions.Shared, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304</AssemblyFullName>
      <AssemblyName>CrystalDecisions.Shared.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\CrystalDecisions.Shared\13.0.3500.0__692fbea5521e1304\CrystalDecisions.Shared.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>160b3bfd-9b45-4dfc-a084-8245d8e16717</RecID>
      <AssemblyFullName>CrystalDecisions.ReportAppServer.ClientDoc, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304</AssemblyFullName>
      <AssemblyName>CrystalDecisions.ReportAppServer.ClientDoc.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\CrystalDecisions.ReportAppServer.ClientDoc\13.0.3500.0__692fbea5521e1304\CrystalDecisions.ReportAppServer.ClientDoc.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>7bf1569a-4631-4f29-937b-65e2484dfb13</RecID>
      <AssemblyFullName>CrystalDecisions.ReportAppServer.Controllers, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304</AssemblyFullName>
      <AssemblyName>CrystalDecisions.ReportAppServer.Controllers.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\CrystalDecisions.ReportAppServer.Controllers\13.0.3500.0__692fbea5521e1304\CrystalDecisions.ReportAppServer.Controllers.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>da65b5b3-6b32-41d5-9904-ed5dd1defc6c</RecID>
      <AssemblyFullName>System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>System.Core.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Core\v4.0_4.0.0.0__b77a5c561934e089\System.Core.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>bba13623-110a-4a99-a79c-47daa4cf20b2</RecID>
      <AssemblyFullName>Infragistics4.Win.AppStylistSupport.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.AppStylistSupport.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.AppStylistSupport.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.AppStylistSupport.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>b87de0b4-182c-4435-98b3-49229e008913</RecID>
      <AssemblyFullName>JiwaLib, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaLib.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaLib.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>417f7d8b-a346-49db-8de5-ec8744f70281</RecID>
      <AssemblyFullName>Microsoft.ApplicationInsights, Version=2.4.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</AssemblyFullName>
      <AssemblyName>Microsoft.ApplicationInsights.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\Microsoft.ApplicationInsights.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>774c78d5-99bc-4f2d-a1b0-42d60ab267d7</RecID>
      <AssemblyFullName>CrystalDecisions.Windows.Forms, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304</AssemblyFullName>
      <AssemblyName>CrystalDecisions.Windows.Forms.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\CrystalDecisions.Windows.Forms\13.0.3500.0__692fbea5521e1304\CrystalDecisions.Windows.Forms.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>80dced67-db2f-480c-acef-f5efc380bb17</RecID>
      <AssemblyFullName>Infragistics4.Win.UltraWinGrid.v13.1, Version=13.1.20131.2060, Culture=neutral, PublicKeyToken=7dd5c3163f2cd0cb</AssemblyFullName>
      <AssemblyName>Infragistics4.Win.UltraWinGrid.v13.1.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\Infragistics4.Win.UltraWinGrid.v13.1\v4.0_13.1.20131.2060__7dd5c3163f2cd0cb\Infragistics4.Win.UltraWinGrid.v13.1.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>90132719-80b1-49de-b707-c8ae863a0181</RecID>
      <AssemblyFullName>ActiproSoftware.Shared.WinForms, Version=16.1.330.0, Culture=neutral, PublicKeyToken=c27e062d3c1a4763</AssemblyFullName>
      <AssemblyName>ActiproSoftware.Shared.WinForms.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\ActiproSoftware.Shared.WinForms\16.1.330.0__c27e062d3c1a4763\ActiproSoftware.Shared.WinForms.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>505f0447-ddbd-4fad-8c9f-934244d2724c</RecID>
      <AssemblyFullName>FarPoint.Win, Version=8.35.20151.0, Culture=neutral, PublicKeyToken=327c3516b1b18457</AssemblyFullName>
      <AssemblyName>FarPoint.Win.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\FarPoint.Win\8.35.20151.0__327c3516b1b18457\FarPoint.Win.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>fd8fea9b-6882-4126-b4d8-a68f16366623</RecID>
      <AssemblyFullName>CrystalDecisions.ReportAppServer.ReportDefModel, Version=13.0.3500.0, Culture=neutral, PublicKeyToken=692fbea5521e1304</AssemblyFullName>
      <AssemblyName>CrystalDecisions.ReportAppServer.ReportDefModel.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\assembly\GAC_MSIL\CrystalDecisions.ReportAppServer.ReportDefModel\13.0.3500.0__692fbea5521e1304\CrystalDecisions.ReportAppServer.ReportDefModel.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>81a93bd8-7996-4332-8156-e0c1b0e07e3f</RecID>
      <AssemblyFullName>ServiceStack.Interfaces, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Interfaces.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Interfaces.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>9f8edf37-3f03-4873-ab4e-1183ce08c619</RecID>
      <AssemblyFullName>ServiceStack.Server, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Server.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Server.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>4f0a425a-1c9c-4892-b9c0-7d2a3a2d3337</RecID>
      <AssemblyFullName>ServiceStack.OrmLite, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.OrmLite.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.OrmLite.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>cc2e7171-ffe2-43f6-9116-2ddc1d89c796</RecID>
      <AssemblyFullName>JiwaServiceModel, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaServiceModel.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaServiceModel.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>101669c3-93cc-4741-a7a7-253d43a988d4</RecID>
      <AssemblyFullName>JiwaSales, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaSales.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaSales.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>63912df1-c1dd-49a6-a863-bd8a5f201d60</RecID>
      <AssemblyFullName>JiwaDebtors, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaDebtors.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaDebtors.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>2ceafa8e-9382-4ea5-96fd-0bd363fdf1f3</RecID>
      <AssemblyFullName>JiwaInvReceival, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaInvReceival.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaInvReceival.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>83a18c35-9957-47d8-9128-ade36d73263b</RecID>
      <AssemblyFullName>JiwaPurchaseOrders, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaPurchaseOrders.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaPurchaseOrders.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>a74b014e-196c-419f-868e-0688b3faf8f7</RecID>
      <AssemblyFullName>JiwaInventory, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaInventory.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaInventory.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>49222be9-667e-44cb-aca1-69e54cfffeac</RecID>
      <AssemblyFullName>JiwaStockTransfer, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaStockTransfer.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaStockTransfer.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>ea3c5f1a-4e62-4f09-b405-159738c13e09</RecID>
      <AssemblyFullName>ServiceStack.Common, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Common.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Common.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>81c767d0-d496-421e-917f-218ef534edae</RecID>
      <AssemblyFullName>ServiceStack.Client, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Client.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Client.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>9b70fcfb-e45e-440c-904d-c29c07cc7ef2</RecID>
      <AssemblyFullName>ServiceStack.OrmLite.SqlServer, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.OrmLite.SqlServer.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.OrmLite.SqlServer.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>3e95e826-982f-4ded-b2bf-b95270681a3f</RecID>
      <AssemblyFullName>ServiceStack.Api.Swagger, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Api.Swagger.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Api.Swagger.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>8eb05834-2997-45d4-ab79-02e8795eb3cc</RecID>
      <AssemblyFullName>ServiceStack.Admin, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Admin.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Admin.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>f9a80262-9280-42f7-a5ec-2cb0fb522c88</RecID>
      <AssemblyFullName>ServiceStack.Text, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Text.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Text.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>165c99be-c782-470a-992b-8b5aa0d54984</RecID>
      <AssemblyFullName>JiwaCarrierMaint, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaCarrierMaint.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaCarrierMaint.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>2c305fbe-1f45-4620-b7c2-f583a4dde12d</RecID>
      <AssemblyFullName>System.Net, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</AssemblyFullName>
      <AssemblyName>System.Net.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Net\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Net.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>1e1088ef-5508-4468-8e02-b669fd428959</RecID>
      <AssemblyFullName>System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</AssemblyFullName>
      <AssemblyName>System.Web.dll</AssemblyName>
      <AssemblyLocation>C:\Windows\Microsoft.Net\assembly\GAC_32\System.Web\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Web.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>2956318b-9842-45be-9943-a04ae1eea3b1</RecID>
      <AssemblyFullName>ServiceStack.Razor, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Razor.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Razor.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>ac5bac3d-f1cd-49f2-a71b-2ca2548094de</RecID>
      <AssemblyFullName>JiwaNoteTypes, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaNoteTypes.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaNoteTypes.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>38852e8e-17b3-4274-8901-36900bb8ffbc</RecID>
      <AssemblyFullName>ServiceStack.Api.OpenApi, Version=5.0.0.0, Culture=neutral, PublicKeyToken=02c12cbda47e6587</AssemblyFullName>
      <AssemblyName>ServiceStack.Api.OpenApi.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\ServiceStack.Api.OpenApi.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>424d9715-1999-487d-8c0a-54a86520f18f</RecID>
      <AssemblyFullName>JiwaDBPricingGroups, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaDBPricingGroups.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaDBPricingGroups.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>3af2a40e-a264-480a-86f7-7cd23debcfbf</RecID>
      <AssemblyFullName>JiwaDocumentTypes, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaDocumentTypes.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaDocumentTypes.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>90d13198-d9e0-4cce-afca-a8a45dfe9eca</RecID>
      <AssemblyFullName>JiwaCreditors, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaCreditors.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaCreditors.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>7bb6376d-7323-4f8a-b566-47e1793e1566</RecID>
      <AssemblyFullName>JiwaForeignExchange, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaForeignExchange.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaForeignExchange.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>1bc3e6c9-0362-4db1-b5ce-c5783c76a60b</RecID>
      <AssemblyFullName>JiwaPriceSchemes, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaPriceSchemes.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaPriceSchemes.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>631b133d-2cc7-4b26-b6d7-9d1d500d4279</RecID>
      <AssemblyFullName>JiwaLandedCost, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaLandedCost.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaLandedCost.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>03681fd2-3d49-4d37-bfe0-9eb21fbb8b73</RecID>
      <AssemblyFullName>JiwaJournalSets, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaJournalSets.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaJournalSets.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>b604b648-a89e-4be5-81a8-7df801d255a6</RecID>
      <AssemblyFullName>JiwaWhouseTransfer, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaWhouseTransfer.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaWhouseTransfer.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>453720a5-821b-4ced-b4d3-8dc5b4f0e369</RecID>
      <AssemblyFullName>JiwaPurchaseInvoices, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaPurchaseInvoices.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaPurchaseInvoices.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>33027689-8141-443d-8ab4-611730582ee1</RecID>
      <AssemblyFullName>LumenWorks.Framework.IO, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>LumenWorks.Framework.IO.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\LumenWorks.Framework.IO.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>2a2d2196-474b-476d-a801-40ed15eb2864</RecID>
      <AssemblyFullName>JiwaDebtorInvoices, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaDebtorInvoices.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaDebtorInvoices.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>4926886f-4c89-46c6-a597-8603eaa245d9</RecID>
      <AssemblyFullName>JiwaJobCosting, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaJobCosting.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaJobCosting.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>109dbd23-0de5-460f-8a3d-196856919667</RecID>
      <AssemblyFullName>JiwaForwardCover, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaForwardCover.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaForwardCover.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>58e9be28-8ab7-4d9f-a98b-20ca8bcee2be</RecID>
      <AssemblyFullName>JiwaLock, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaLock.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaLock.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>ede065bc-8e78-4cbb-8219-afe62d3e6a59</RecID>
      <AssemblyFullName>JiwaCashBook, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaCashBook.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaCashBook.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>9b03d217-1a45-4b32-be7c-179c8950063f</RecID>
      <AssemblyFullName>JiwaWarehouses, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaWarehouses.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaWarehouses.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>d311746d-549c-412f-9318-72d91e4833c6</RecID>
      <AssemblyFullName>JiwaBillOfMaterials, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaBillOfMaterials.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaBillOfMaterials.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>f5ef9318-6f79-4957-b0e8-25de836f6061</RecID>
      <AssemblyFullName>EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>EntityFramework.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\EntityFramework.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>b6228853-5e91-4380-a602-85d7585a5186</RecID>
      <AssemblyFullName>EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</AssemblyFullName>
      <AssemblyName>EntityFramework.SqlServer.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\EntityFramework.SqlServer.dll</AssemblyLocation>
    </Reference>
    <Reference>
      <RecID>d9a5370c-3305-4e6f-8858-fdd92a43b978</RecID>
      <AssemblyFullName>JiwaSupplierReturns, Version=7.2.1.0, Culture=neutral, PublicKeyToken=e30ce81e37f29c8c</AssemblyFullName>
      <AssemblyName>JiwaSupplierReturns.dll</AssemblyName>
      <AssemblyLocation>C:\VSTS\Jiwa 7\07.02.00\Built Files\JiwaSupplierReturns.dll</AssemblyLocation>
    </Reference>
  </ReferenceCollection>
  <SystemSettingCollection>
    <SystemSetting>
      <RecID>1ffbb7a6d39849b5a16a</RecID>
      <IDKey>SessionExpiryInMinutes</IDKey>
      <Description>How many minutes of idle time before the users session expires</Description>
      <DisplayOrder>2</DisplayOrder>
      <CellType>Integer</CellType>
      <Contents>5</Contents>
      <DisplayContents>5</DisplayContents>
    </SystemSetting>
    <SystemSetting>
      <RecID>72E30F4B347C4B8F99C2</RecID>
      <IDKey>AutoQueryMaxLimit</IDKey>
      <Description>The default maximum number of rows to return from AutoQuery queries</Description>
      <DisplayOrder>3</DisplayOrder>
      <CellType>Integer</CellType>
      <Contents>100</Contents>
      <DisplayContents>100</DisplayContents>
    </SystemSetting>
    <SystemSetting>
      <RecID>7d746d4d91024cd3a201</RecID>
      <IDKey>DebugMode</IDKey>
      <Description>Indicates if the API is running in debug mode (requests logged, stack traces shown in service responses)</Description>
      <DisplayOrder>3</DisplayOrder>
      <CellType>Checkbox</CellType>
      <Contents>False</Contents>
      <DisplayContents>False</DisplayContents>
    </SystemSetting>
    <SystemSetting>
      <RecID>d41df9cba56543b5989c</RecID>
      <IDKey>WebhooksHostURL</IDKey>
      <Description>URL of the REST API Site - used for clients to use internally</Description>
      <DisplayOrder>4</DisplayOrder>
      <CellType>Text</CellType>
      <Contents />
      <DisplayContents />
    </SystemSetting>
    <SystemSetting>
      <RecID>bcd588a4f29942fdb022</RecID>
      <IDKey>WebhooksRetryInterval</IDKey>
      <Description>Base number of seconds to wait until retrying a failed subscription - (10 ^ (RetryNo * interval))</Description>
      <DisplayOrder>5</DisplayOrder>
      <CellType>Integer</CellType>
      <Contents>1</Contents>
      <DisplayContents>1</DisplayContents>
    </SystemSetting>
    <SystemSetting>
      <RecID>fc6dad008cf244c5a40d</RecID>
      <IDKey>WebhooksMaxRetries</IDKey>
      <Description>Maximum number of retries to attempt to send subscription</Description>
      <DisplayOrder>6</DisplayOrder>
      <CellType>Integer</CellType>
      <Contents>6</Contents>
      <DisplayContents>6</DisplayContents>
    </SystemSetting>
    <SystemSetting>
      <RecID>6066a73ba7a94ff3bbc6</RecID>
      <IDKey>WebhooksClientKey</IDKey>
      <Description>Key used by internal Jiwa clients - when blank will be generated at service start</Description>
      <DisplayOrder>7</DisplayOrder>
      <CellType>Text</CellType>
      <Contents />
      <DisplayContents />
    </SystemSetting>
  </SystemSettingCollection>
</JiwaDocument>