This is a not-so-quick article that queries an eBay order and creates the relevant ZohoInventory item, contact, sales order, package slip, shipment order, invoice, payment records...
Why?
I'm storing this here as a reference and taking the bits that I need for the various clients that request an eBay integration. This is a comprehensive snippet which does the whole lot.
How?
Using the method of "mega-functions", here is the code snippet for one function which will accept as parameter the eBay order reference and generate all the respective records in Zoho Inventory. We're using a ZohoCRM webhook, because CRM webhooks run more reliably then the ones we have found in ZohoBooks and other Zoho Apps.
Prerequisites:
- Setup a connection called "joel_books" that has the necessary scopes to view taxes and chart of accounts
- Setup a connection called "joel_inventory" that has the necessary scopes to do everything under the sun
- Setup a function that generates an access token of the Trading API for the eBay store
/*
Function: fn_eBay_GetOrderInfoCreateUpdateZohoSO(string p_eBayOrderRef)
Purpose: Queries eBay for information about an order and then creates item/contact/sales order/package slip/invoice (if not exist)
Date Created: 2022-05-05 (Joel Lipman)
- Initial release
Date Modified: 2023-01-23 (Joel Lipman)
- Revamp of code
- Only generate invoice if payment received
- Distinguish whether composite based on ebay item specific
- Add stock in order to authorize payment creation
Date Modified: 2023-02-02 (Joel Lipman)
- Marked Items as inclusive of VAT so VAT reports in Books will be accurate (eg. £499.95 is correctly £416.62)
Date Modified: 2023-02-23 (Joel Lipman)
- Check if ebay Order ID already exists on system to determine whether to update or create.
- Check if SalesOrder already exists on system to determine whether to update or create.
- Check if Invoice already exists on system to determine whether to update or create.
- Check if Package already exists on system to determine whether to update or create.
- Check if Shipment already exists on system to determine whether to update or create.
- Loop through eBay payments to record all the different payments received.
Date Modified: 2023-03-14 (Joel Lipman)
- Resolved fix of incorrect customer (Use Email rather than StaticAlias)
- Resolved fix of inventory adjustment level (Error:9205:Insufficient Stock)
- Resolved fix of overpaid amount (Include Shipping Cost in SO)
Date Modified: 2023-03-16 (Joel Lipman)
- Resolves issue of SO / Invoice / Package / Shipment / Payment not updating.
- Revamp and debug line by line
- Switched email identifier back to StaticAlias rather than member Email
- Possibly still an issue with delayed payment (check this is not holding status)
Date Modified: 2023-03-17 (Joel Lipman)
- Enhanced debug messages as function not auto-triggering on receipt of Order
- Resolved: SO ID was not being returned when created.
- Forced re-upload of photo for item on any modification
Date Modified: 2023-03-20 (Joel Lipman)
- Check if payment has already been recorded before creating a new one.
- Fixed reference_number being included on customer payment.
Date Modified: 2023-03-21 (Joel Lipman)
- Added if conditions to not adjust stock level if item has enough quantity then that purchased
- Adds tracking number and carrier to shipment record on either creation or modification.
- Only creates shipment order if shipped time is specified.
- Only marks shipment as delivered if DHL API checked and status returned is delivered
Date Modified: 2023-03-22 (Joel Lipman)
- On creation of Sales Order, create map of line items and created SO (fix to invoice only generated on edit)
Date Modified: 2023-03-29 (Joel Lipman)
- If an eBay order comes through as cancelled, then void the sales order, void the invoice, delete the package and shipment.
- Added chart of accounts lookup to set purchase account for an item: now ticks purchase information and track inventory.
- Issue on create that shipment is not created.
More Info:
- API Explorer Test Tool: https://developer.ebay.com/DevZone/build-test/test-tool/default.aspx?index=0&env=production&api=trading
- GetMyeBaySelling Documentation: https://developer.ebay.com/devzone/xml/docs/reference/ebay/getmyebayselling.html
- GetOrderTransactions Documentation: https://developer.ebay.com/devzone/xml/docs/reference/ebay/GetOrderTransactions.html
- DHL API Developer Portal: https://developer.dhl.com/documentation
- DHL API Developer API Reference Shipment Tracking: https://developer.dhl.com/api-reference/shipment-tracking#reference-docs-section
*/
//
// enter your own organization ID here for ZohoBooks and ZohoInventory
v_BooksOrgID = 12345678901;
//
// evaluate
v_currentDate = zoho.currentdate.toString("yyyy-MM-dd");
v_OrderDate = zoho.currentdate.toString("yyyy-MM-dd");
v_Page = 1;
v_PerPage = 10;
m_Output = Map();
l_Costs = {11,13,15,17,20};
b_DebugMode = true;
l_DebugMessages = List();
l_DebugMessages.add("eBay Order ID: " + p_eBayOrderRef);
l_DebugMessages.add("eBay Order Date: " + v_OrderDate);
info p_eBayOrderRef;
//
// get books tax rates
m_Taxes = Map();
r_Taxes = invokeurl
[
url :"https://books.zoho.eu/api/v3/settings/taxes?organization_id=" + v_BooksOrgID
type :GET
connection:"joel_books"
];
if(!isnull(r_Taxes.get("taxes")))
{
for each r_Tax in r_Taxes.get("taxes")
{
m_Taxes.put(r_Tax.get("tax_percentage").toString(),r_Tax.get("tax_id"));
}
}
l_DebugMessages.add("ZB Taxes: " + m_Taxes);
//
// set chart of accounts to use
v_Endpoint = "https://books.zoho.eu/api/v3/chartofaccounts?organization_id=" + v_BooksOrgID;
r_ChartOfAccounts = invokeurl
[
url :v_Endpoint
type :GET
connection:"joel_books"
];
m_Accounts = Map();
if(!isnull(r_ChartOfAccounts.get("chartofaccounts")))
{
for each r_Account in r_ChartOfAccounts.get("chartofaccounts")
{
m_Accounts.put(r_Account.get("account_name"),r_Account.get("account_id"));
}
}
//
// get access token
v_AccessToken = standalone.fn_eBay_GetAccessToken();
l_DebugMessages.add("AccessToken:<br /><br />" + v_AccessToken);
//
v_TradingAPIVersion = 967;
v_Endpoint = "https://api.ebay.com/ws/api.dll";
//
// build header
m_Headers = Map();
m_Headers.put("X-EBAY-API-SITEID",3);
m_Headers.put("X-EBAY-API-COMPATIBILITY-LEVEL",v_TradingAPIVersion);
v_ApiCall = "GetOrderTransactions";
m_Headers.put("X-EBAY-API-CALL-NAME",v_ApiCall);
m_Headers.put("X-EBAY-API-IAF-TOKEN",v_AccessToken);
//
// build params
m_Params = Map();
m_Params.put("WarningLevel","High");
m_Params.put("ErrorLanguage","en_GB");
m_Params.put("DetailLevel","ReturnAll");
//
// send an order array
l_OrderIDs = List();
m_OrderID = Map();
m_OrderID.put("OrderID",p_eBayOrderRef);
l_OrderIDs.add(m_OrderID);
m_Params.put("OrderIDArray",l_OrderIDs);
//
// convert to xml and replace root nodes
x_Params = m_Params.toXML();
x_Params = x_Params.toString().replaceFirst("<root>","<?xml version=\"1.0\" encoding=\"utf-8\"?><" + v_ApiCall + "Request xmlns=\"urn:ebay:apis:eBLBaseComponents\">");
x_Params = x_Params.toString().replaceFirst("</root>","</" + v_ApiCall + "Request>");
//
// send the request XML as a string
r_ResponseXMLOrder = invokeurl
[
url :v_Endpoint
type :POST
parameters:x_Params
headers:m_Headers
];
info "-----------------------";
info "EBAY ORDER XML:";
if(b_DebugMode)
{
l_DebugMessages.add("EBAY ORDER XML:<br /><br />" + r_ResponseXMLOrder.replaceAll(">",">").replaceAll("<","<"));
}
//
// ********************************************************
// loop through order array
v_ArrayNode = "OrderArray";
x_OrderArray = r_ResponseXMLOrder.subString(r_ResponseXMLOrder.indexOf("<" + v_ArrayNode),r_ResponseXMLOrder.lastIndexOf("</" + v_ArrayNode) + v_ArrayNode.length() + 3);
l_Orders = x_OrderArray.executeXPath("//Order").toXmlList();
for each x_Order in l_Orders
{
// initialize
m_BooksContact = Map();
m_BooksShipping = Map();
m_BooksBilling = Map();
l_InventoryLineItems = List();
//
v_OrderID = x_Order.executeXPath("//Order/OrderID/text()");
v_OrderStatus = x_Order.executeXPath("//Order/OrderStatus/text()");
b_OrderCancelled = if(v_OrderStatus.equalsIgnoreCase("Cancelled") || v_OrderStatus.equalsIgnoreCase("Inactive"),true,false);
v_OrderAmountPaid = x_Order.executeXPath("//Order/AmountPaid/text()");
v_OrderCurrency = x_Order.executeXPath("//Order/AmountPaid/@currencyID").executeXPath("/currencyID/text()");
v_OrderSellerID = x_Order.executeXPath("//Order/SellerUserID/text()");
//
v_OrderTaxPercent = x_Order.executeXPath("//Order/ShippingDetails/SalesTax/SalesTaxPercent/text()");
v_OrderShippingIncludesTax = x_Order.executeXPath("//Order/ShippingDetails/SalesTax/ShippingIncludedInTax/text()");
v_OrderTaxCurrency = x_Order.executeXPath("//Order/ShippingDetails/SalesTax/SalesTaxAmount/@currencyID").executeXPath("/currencyID/text()");
v_OrderTaxAmount = x_Order.executeXPath("//Order/ShippingDetails/SalesTax/SalesTaxAmount/text()");
//
v_BuyerShippingName = x_Order.executeXPath("//Order/ShippingAddress/Name/text()");
v_BuyerShippingStreet1 = x_Order.executeXPath("//Order/ShippingAddress/Street1/text()");
v_BuyerShippingStreet1 = if(v_BuyerShippingStreet1.contains(" ebay"),v_BuyerShippingStreet1.getPrefix(" ebay"),v_BuyerShippingStreet1);
v_BuyerShippingStreet2 = x_Order.executeXPath("//Order/ShippingAddress/Street2/text()");
v_BuyerShippingStreet2 = if(v_BuyerShippingStreet2.contains("ebay"),v_BuyerShippingStreet2.getPrefix("ebay"),v_BuyerShippingStreet2);
v_BuyerShippingCity = x_Order.executeXPath("//Order/ShippingAddress/CityName/text()");
v_BuyerShippingPostcode = x_Order.executeXPath("//Order/ShippingAddress/PostalCode/text()");
v_BuyerShippingCounty = x_Order.executeXPath("//Order/ShippingAddress/StateOrProvince/text()");
v_BuyerShippingCountryName = x_Order.executeXPath("//Order/ShippingAddress/CountryName/text()");
v_BuyerShippingPhone = x_Order.executeXPath("//Order/ShippingAddress/Phone/text()");
//
// for Books: Billing Address Map
m_BooksBilling.put("attention",v_BuyerShippingName);
m_BooksBilling.put("address",v_BuyerShippingStreet1);
m_BooksBilling.put("street2",v_BuyerShippingStreet2);
m_BooksBilling.put("city",v_BuyerShippingCity);
m_BooksBilling.put("state",v_BuyerShippingCounty);
m_BooksBilling.put("zip",v_BuyerShippingPostcode);
m_BooksBilling.put("country",v_BuyerShippingCountryName);
// for Books: Shipping Address Map
m_BooksShipping.put("attention",v_BuyerShippingName);
m_BooksShipping.put("address",v_BuyerShippingStreet1);
m_BooksShipping.put("street2",v_BuyerShippingStreet2);
m_BooksShipping.put("city",v_BuyerShippingCity);
m_BooksShipping.put("state",v_BuyerShippingCounty);
m_BooksShipping.put("zip",v_BuyerShippingPostcode);
m_BooksShipping.put("country",v_BuyerShippingCountryName);
//
v_ShippingServiceSelected = x_Order.executeXPath("//Order/ShippingServiceSelected/ShippingService/text()");
v_ShippingServiceCost = x_Order.executeXPath("//Order/ShippingServiceSelected/ShippingServiceCost/text()");
v_OrderSubtotal = x_Order.executeXPath("//Order/Subtotal/text()");
v_OrderTotal = x_Order.executeXPath("//Order/Total/text()");
//
v_Order_DateCreated = x_Order.executeXPath("//Order/CreatedTime/text()");
v_Order_DateCreated = if(!isnull(v_Order_DateCreated),v_Order_DateCreated.getPrefix(".").replaceFirst("T"," ",true).toTime(),zoho.currenttime);
l_DebugMessages.add("Date Order Created: " + v_Order_DateCreated);
v_Order_DateShipped = x_Order.executeXPath("//Order/ShippedTime/text()");
v_Order_DateShipped = if(!isnull(v_Order_DateShipped),v_Order_DateShipped.getPrefix(".").replaceFirst("T"," ",true).toTime(),null);
l_DebugMessages.add("Date Order Shipped: " + v_Order_DateShipped);
//
// loop through transaction array (possibly multiple line items)
l_Transactions = x_Order.executeXPath("//Order/TransactionArray/Transaction").toXmlList();
for each x_Transaction in l_Transactions
{
// initialize
m_BooksItem = Map();
m_BooksLineItem = Map();
//
// get buyer info
v_BuyerUserName = x_Transaction.executeXPath("//Transaction/Buyer/UserID/text()");
v_BuyerUserFName = x_Transaction.executeXPath("//Transaction/Buyer/UserFirstName/text()");
v_BuyerUserSName = x_Transaction.executeXPath("//Transaction/Buyer/UserLastName/text()");
v_BuyerUserEmail = x_Transaction.executeXPath("//Transaction/Buyer/Email/text()");
l_DebugMessages.add("BuyerEmail: " + v_BuyerUserEmail);
info "BuyerEmail: " + v_BuyerUserEmail;
v_BuyerUserStaticEmail = x_Transaction.executeXPath("//Transaction/Buyer/StaticAlias/text()");
l_DebugMessages.add("BuyerStaticEmail: " + v_BuyerUserStaticEmail);
info "BuyerStaticEmail: " + v_BuyerUserStaticEmail;
v_BuyerIDVerified = x_Transaction.executeXPath("//Transaction/Buyer/IDVerified/text()");
v_BuyerSite = x_Transaction.executeXPath("//Transaction/Buyer/Site/text()");
//
// Update Zoho Contact Name
m_BooksContact.put("contact_name",v_BuyerUserFName + " " + v_BuyerUserSName);
m_BooksContact.put("billing_address",m_BooksBilling);
m_BooksContact.put("shipping_address",m_BooksShipping);
m_BooksContact.put("first_name",v_BuyerUserFName);
m_BooksContact.put("last_name",v_BuyerUserSName);
m_BooksContact.put("phone",v_BuyerShippingPhone);
//
v_ItemID = x_Transaction.executeXPath("//Transaction/Item/ItemID/text()").replaceAll("[^0-9]","");
l_DebugMessages.add("Item Number: " + v_ItemID);
info "Item Number: " + v_ItemID;
v_ItemListingType = x_Transaction.executeXPath("//Transaction/Item/ListingType/text()");
v_ItemSKU = x_Transaction.executeXPath("//Transaction/Item/SKU/text()");
l_DebugMessages.add("Item SKU: " + v_ItemSKU);
info "Item SKU: " + v_ItemSKU;
v_ItemConditionID = x_Transaction.executeXPath("//Transaction/Item/ConditionID/text()");
v_ItemConditionName = x_Transaction.executeXPath("//Transaction/Item/ConditionDisplayName/text()");
v_ItemPrice = x_Transaction.executeXPath("//Transaction/Item/SellingStatus/CurrentPrice/text()");
//
v_TransactionID = x_Transaction.executeXPath("//Transaction/TransactionID/text()");
v_TransactionCurrency = x_Transaction.executeXPath("//Transaction/AmountPaid/@currencyID").executeXPath("/currencyID/text()");
v_TransactionAmountPaid = x_Transaction.executeXPath("//Transaction/AmountPaid/text()");
v_TransactionQtyPurchased = x_Transaction.executeXPath("//Transaction/QuantityPurchased/text()");
v_TransactionCheckoutStatus = x_Transaction.executeXPath("//Transaction/Status/CheckoutStatus/text()");
v_TransactionCompleteStatus = x_Transaction.executeXPath("//Transaction/Status/CompleteStatus/text()");
v_TransactionBestOffer = x_Transaction.executeXPath("//Transaction/BestOfferSale/text()");
v_TransactionOrderRef = x_Transaction.executeXPath("//Transaction/ExtendedOrderID/text()");
v_TransactionOrderLineItemRef = x_Transaction.executeXPath("//Transaction/OrderLineItemID/text()");
//
v_Transaction_DateCreated = x_Transaction.executeXPath("//Transaction/CreatedDate/text()");
v_Transaction_DateCreated = if(!isnull(v_Transaction_DateCreated),v_Transaction_DateCreated.getPrefix(".").replaceFirst("T"," ",true).toTime(),zoho.currenttime);
v_Transaction_DateModified = x_Transaction.executeXPath("//Transaction/Status/LastTimeModified/text()");
v_Transaction_DateModified = if(!isnull(v_Transaction_DateModified),v_Transaction_DateModified.getPrefix(".").replaceFirst("T"," ",true).toTime(),zoho.currenttime);
v_Transaction_DatePaid = x_Transaction.executeXPath("//Transaction/PaidTime/text()");
v_Transaction_DatePaid = if(!isnull(v_Transaction_DatePaid),v_Transaction_DatePaid.getPrefix(".").replaceFirst("T"," ",true).toTime(),zoho.currenttime);
v_Transaction_DateShipped = x_Transaction.executeXPath("//Transaction/ShippedTime/text()");
v_Transaction_DateShipped = if(!isnull(v_Transaction_DateShipped),v_Transaction_DateShipped.getPrefix(".").replaceFirst("T"," ",true).toTime(),zoho.currenttime);
//
v_TransactionPaymentMethod = x_Transaction.executeXPath("//Transaction/Status/PaymentMethodUsed/text()");
v_TransactionPaymentStatus = x_Transaction.executeXPath("//Transaction/Status/eBayPaymentStatus/text()");
v_TransactionPaymentHoldStatus = x_Transaction.executeXPath("//Transaction/Status/PaymentHoldStatus/text()");
//
v_ShippingCarrier = x_Transaction.executeXPath("//Transaction/ShippingDetails/ShipmentTrackingDetails/ShippingCarrierUsed/text()");
v_ShippingTrackingNumber = x_Transaction.executeXPath("//Transaction/ShippingDetails/ShipmentTrackingDetails/ShipmentTrackingNumber/text()");
//
// Other Zoho Contact updates
m_BooksContact.put("currency_code",v_TransactionCurrency);
//
// check for the item in books and add to line items for other records
v_BooksItemID = 0;
v_BooksCurrentStock = 0;
m_Criteria = Map();
m_Criteria.put("sku",v_ItemID);
b_Composite = false;
//
// search items
r_SearchItems = zoho.inventory.getRecords("items",v_BooksOrgID,m_Criteria,"joel_inventory");
for each r_FoundItem in r_SearchItems.get("items")
{
if(!isnull(r_FoundItem.get("item_id")) && r_FoundItem.get("sku") == v_ItemID)
{
v_BooksItemID = r_FoundItem.get("item_id").toLong();
v_ItemTitle = r_FoundItem.get("name");
v_ListingDescription = r_FoundItem.get("description");
v_BooksCurrentStock = ifnull(r_FoundItem.get("actual_available_stock"),0).toLong();
}
}
// search composite items
if(v_BooksItemID == 0)
{
r_SearchCompositeItems = zoho.inventory.getRecords("compositeitems",v_BooksOrgID,m_Criteria,"joel_inventory");
for each r_CompositeItem in r_SearchCompositeItems.get("compositeitems")
{
if(!isnull(r_CompositeItem.get("item_id")) && r_CompositeItem.get("sku") == v_ItemID)
{
v_BooksItemID = r_CompositeItem.get("item_id").toLong();
v_ItemTitle = r_CompositeItem.get("name");
v_ListingDescription = r_CompositeItem.get("description");
v_BooksCurrentStock = ifnull(r_CompositeItem.get("actual_available_stock"),0).toLong();
b_Composite = true;
}
}
}
//
l_DebugMessages.add("ZB Item Search: " + v_BooksItemID);
info "ZB Item Search: " + v_BooksItemID;
// ***********************************************
// query eBay for the item listing
//
// build header
m_Headers = Map();
m_Headers.put("X-EBAY-API-SITEID",3);
m_Headers.put("X-EBAY-API-COMPATIBILITY-LEVEL",v_TradingAPIVersion);
v_ApiCall = "GetItem";
m_Headers.put("X-EBAY-API-CALL-NAME",v_ApiCall);
m_Headers.put("X-EBAY-API-IAF-TOKEN",v_AccessToken);
//
// build params
m_Params = Map();
m_Params.put("WarningLevel","High");
m_Params.put("ErrorLanguage","en_GB");
m_Params.put("DetailLevel","ReturnAll");
m_Params.put("IncludeItemSpecifics",true);
//
// include fixed price items
m_ActiveList = Map();
m_ActiveList.put("Include","true");
m_ActiveList.put("ListingType","FixedPriceItem");
m_Pagination = Map();
m_Pagination.put("PageNumber",v_Page);
m_Pagination.put("EntriesPerPage",v_PerPage);
m_ActiveList.put("Pagination",m_Pagination);
m_Params.put("ItemID",v_ItemID);
//
// convert to xml and replace root nodes
x_Params = m_Params.toXML();
x_Params = x_Params.toString().replaceFirst("<root>","<?xml version=\"1.0\" encoding=\"utf-8\"?><" + v_ApiCall + "Request xmlns=\"urn:ebay:apis:eBLBaseComponents\">");
x_Params = x_Params.toString().replaceFirst("</root>","</" + v_ApiCall + "Request>");
//
// send the request XML as a string
r_ResponseXMLItem = invokeurl
[
url :v_Endpoint
type :POST
parameters:x_Params
headers:m_Headers
];
info "-----------------------";
info "EBAY ITEM XML:";
if(b_DebugMode)
{
l_DebugMessages.add("EBAY ITEM XML:<br /><br />" + r_ResponseXMLItem.replaceAll(">",">").replaceAll("<","<"));
}
v_Node = "Item";
x_Item = r_ResponseXMLItem.subString(r_ResponseXMLItem.indexOf("<" + v_Node),r_ResponseXMLItem.lastIndexOf("</" + v_Node) + v_Node.length() + 3);
//
// parse out details of item
v_ItemTitle = x_Item.executeXPath("//Item/Title/text()");
l_DebugMessages.add("Item Title: " + v_ItemTitle);
info "Item Title: " + v_ItemTitle;
v_ItemCustomSKU = x_Item.executeXPath("//Item/SKU/text()");
v_ItemBrand = x_Item.executeXPath("//Item/ProductListingDetails/BrandMPN/Brand/text()");
v_ItemCategoryID = x_Item.executeXPath("//Item/PrimaryCategory/CategoryID/text()");
v_ItemCategoryName = x_Item.executeXPath("//Item/PrimaryCategory/CategoryName/text()");
v_ItemLocation = x_Item.executeXPath("//Item/Location/text()");
v_ListingQuantity = x_Item.executeXPath("//Item/Quantity/text()");
v_ListingConditionName = x_Item.executeXPath("//Item/ConditionDisplayName/text()");
v_ListingConditionDesc = x_Item.executeXPath("//Item/ConditionDescription/text()");
//v_ListingDescription = x_Item.executeXPath("//Item/Description/text()").replaceAll("<","<").replaceAll(">",">");
v_ListingDescription = x_Item.executeXPath("//Item/Description/text()");
l_ListingPictures = x_Item.executeXPath("//Item/PictureDetails/PictureURL").toXmlList();
l_ItemSpecifics = x_Item.executeXPath("//Item/ItemSpecifics/NameValueList").toXmlList();
v_ItemCondition = x_Item.executeXPath("//Item/ConditionID/text()");
b_IsNew = if(v_ItemCondition == "1000",true,false);
//
m_BooksItem.put("name",v_ItemTitle);
m_BooksItem.put("sku",v_ItemID);
m_BooksItem.put("rate",v_ItemPrice.toDecimal());
// cost?
v_NumberOfStars = v_ItemTitle.getOccurenceCount("*") - 1;
v_NumberOfStars = if(v_NumberOfStars < 1,0,v_NumberOfStars);
v_NumberOfStars = if(v_NumberOfStars > 4,4,v_NumberOfStars);
v_PurchaseRate = l_Costs.get(v_NumberOfStars);
m_BooksItem.put("purchase_rate",v_PurchaseRate.toDecimal());
//
v_UnitType = "";
if(v_ItemTitle.containsIgnoreCase("wheel") && v_ItemTitle.containsIgnoreCase("tyre"))
{
v_UnitType = "pcs";
}
else if(v_ItemTitle.containsIgnoreCase("wheel"))
{
v_UnitType = "Wheel";
}
else if(v_ItemTitle.containsIgnoreCase("tyre"))
{
v_UnitType = "Tyre";
}
m_BooksItem.put("unit",v_UnitType);
//
l_CustomFields = list();
m_CustomField = Map();
m_CustomField.put("api_name","cf_ebay_sku");
m_CustomField.put("value",v_ItemCustomSKU);
l_CustomFields.add(m_CustomField);
//
// here are the item specifics, simply specify the Item Specific label and then the Zoho Inventory API name of the field to map to.
m_NameListMappings = Map();
m_NameListMappings.put("Offset (ET)","cf_offset");
m_NameListMappings.put("Centre Bore","cf_centre_bore");
m_NameListMappings.put("Custom Bundle","cf_custom_bundle");
m_NameListMappings.put("Manufacturer Part Number","cf_manufacturer_part_number");
m_NameListMappings.put("Stud Diameter","cf_stud_diameter");
m_NameListMappings.put("Wheel Material","cf_wheel_material");
m_NameListMappings.put("Wheel Construction","cf_wheel_construction");
m_NameListMappings.put("Reference OE/OEM Number","cf_reference_oe_oem_number");
m_NameListMappings.put("Modified Item","cf_modified_item");
m_NameListMappings.put("Offset","cf_offset");
m_NameListMappings.put("Number of Studs","cf_number_of_studs");
m_NameListMappings.put("Type","cf_type");
m_NameListMappings.put("Wheel Diameter","cf_wheel_diameter");
m_NameListMappings.put("Unit Quantity","cf_unit_quantity");
m_NameListMappings.put("Finish","cf_finish");
m_NameListMappings.put("Wheel Width","cf_wheel_width");
//
l_CustomFields = list();
for each x_ItemSpecific in l_ItemSpecifics
{
v_SpecificName = x_ItemSpecific.executeXPath("//NameValueList/Name/text()");
v_SpecificValue = x_ItemSpecific.executeXPath("//NameValueList/Value/text()");
//
if(!isNull(m_NameListMappings.get(v_SpecificName)))
{
m_CustomField = Map();
m_CustomField.put("api_name",m_NameListMappings.get(v_SpecificName));
m_CustomField.put("value",v_SpecificValue);
l_CustomFields.add(m_CustomField);
}
//
if(v_SpecificName.containsIgnoreCase("Unit Quantity"))
{
if(v_SpecificValue.toLong() > 1)
{
b_Composite = true;
}
}
}
//
m_BooksItem.put("custom_fields",l_CustomFields);
//
// do 1 picture as ZohoInventory only supports 1 image upload (at time of print)
v_PictureURL = "";
for each x_Picture in l_ListingPictures
{
v_PictureURL = x_Picture.executeXPath("//PictureURL/text()");
break;
}
//
// update or create with purchase information
m_BooksItem.put("inventory_account_id",m_Accounts.get("Inventory Asset"));
m_BooksItem.put("purchase_rate",v_ItemPrice.toDecimal());
if(v_ItemTitle.containsIgnoreCase("alloy"))
{
m_BooksItem.put("purchase_account_id",m_Accounts.get("Cost of Goods Sold"));
m_BooksItem.put("initial_stock",v_TransactionQtyPurchased.toLong());
}
else
{
if(v_ListingConditionName.containsIgnoreCase("new"))
{
m_BooksItem.put("purchase_account_id",m_Accounts.get("New Tyres Purchase"));
m_BooksItem.put("initial_stock",999);
}
else
{
m_BooksItem.put("initial_stock",v_TransactionQtyPurchased.toLong());
m_BooksItem.put("purchase_account_id",m_Accounts.get("Part Worn Tyres Purchase"));
}
}
m_BooksItem.put("initial_stock_rate",v_ItemPrice.toDecimal());
//
// send request to create item
if(v_BooksItemID == 0)
{
// m_BooksItem.put("initial_stock",v_TransactionQtyPurchased.toLong());
// m_BooksItem.put("initial_stock_rate",v_ItemPrice.toDecimal());
r_CreateItem = zoho.inventory.createRecord("items",v_BooksOrgID,m_BooksItem,"joel_inventory");
info "ITEM CREATE RESPONSE FOR " + v_ItemID;
info r_CreateItem.get("message");
l_DebugMessages.add("ITEM CREATE RESPONSE FOR " + v_ItemID + ": " + r_CreateItem.get("message"));
//
// retrieve the generated item id for generating other records
if(!isnull(r_CreateItem.get("item")))
{
if(!isnull(r_CreateItem.get("item").get("item_id")))
{
v_BooksItemID = r_CreateItem.get("item").get("item_id").toLong();
}
}
}
else
{
//
// ENSURE THAT STOCK LEVEL IS RESTORED TO PURCHASE THIS ITEM
if(v_BooksCurrentStock < 1)
{
// now build stock level adjustment on ZohoInventory for this item
m_UpdateStock = Map();
m_UpdateStock.put("date",v_Order_DateCreated.toString("yyyy-MM-dd"));
m_UpdateStock.put("reason","eBay Order");
m_UpdateStock.put("description","An eBay Order has come in using this item. Re-adjusting inventory level on-the-fly to include it for use in transactions.");
m_UpdateStock.put("adjustment_type","quantity");
//
// need to include line items of adjustment (just this one item)
l_LineItems = List();
m_LineItem = Map();
m_LineItem.put("item_id",v_BooksItemID);
m_LineItem.put("quantity_adjusted",abs(v_TransactionQtyPurchased));
l_LineItems.add(m_LineItem);
m_UpdateStock.put("line_items",l_LineItems);
//
// create this stock level adjustment (need to use Invoke as shortcode wouldn't work)
v_Endpoint = "https://www.zohoapis.eu/inventory/v1/inventoryadjustments?organization_id=" + v_BooksOrgID;
r_CreateAdjustment = invokeurl
[
url :v_Endpoint
type :POST
parameters:m_UpdateStock.toString()
connection:"joel_inventory"
];
info "ADJUSTED INVENTORY LEVEL";
info r_CreateAdjustment.get("message");
l_DebugMessages.add("ADJUSTED INVENTORY LEVEL: " + r_CreateAdjustment.get("message"));
}
//
// update the item to block this function from running until modified by some other method
m_UpdateItem = Map();
l_CustomFields = List();
m_CustomField = Map();
m_CustomField.put("api_name","cf_updated_by");
m_CustomField.put("value","eBay Order");
l_CustomFields.add(m_CustomField);
m_UpdateItem.put("custom_fields",l_CustomFields);
m_UpdateItem.put("status","active");
if(v_BooksCurrentStock < 1)
{
m_UpdateItem.put("initial_stock",abs(v_TransactionQtyPurchased));
m_UpdateItem.put("initial_stock_rate",v_ItemPrice);
}
//info m_UpdateItem;
v_Endpoint = "https://www.zohoapis.eu/inventory/v1/items/" + v_BooksItemID + "?organization_id=" + v_BooksOrgID;
r_UpdateItem = invokeurl
[
url :v_Endpoint
type :PUT
parameters:m_UpdateItem.toString()
connection:"joel_inventory"
];
info "UPDATED ITEM:";
info r_UpdateItem.get("message");
l_DebugMessages.add("UPDATED ITEM: " + r_UpdateItem.get("message"));
}
//
// let's upload the picture for this (only 1 supported in inventory at this time)
if(!isBlank(v_PictureURL))
{
r_DownloadedPhoto = invokeurl
[
url :v_PictureURL
type :GET
];
//
// set the data type
r_DownloadedPhoto.setParamName("image");
//
// build up request to Zoho
m_Params = Map();
m_Params.put("image",r_DownloadedPhoto);
//
// generate endpoint
v_Url = "https://inventory.zoho.eu/api/v1/items/" + v_BooksItemID + "/image";
//
// updload the photo
r_UploadPhoto = invokeurl
[
url :v_Url
type :POST
files:r_DownloadedPhoto
connection:"joel_inventory"
];
// output response to console
info "PHOTO UPLOAD:";
info r_UploadPhoto.get("message");
l_DebugMessages.add("PHOTO UPLOAD OF " + v_PictureURL + ": " + r_UploadPhoto.get("message"));
}
//
// ensure the item is activated
if(v_BooksItemID != 0)
{
v_Endpoint = "https://www.zohoapis.eu/inventory/v1/items/" + v_BooksItemID + "/active?organization_id=" + v_BooksOrgID;
r_ActivateItem = invokeurl
[
url :v_Endpoint
type :POST
connection:"joel_inventory"
];
info "ACTIVATED ITEM:";
info r_ActivateItem.get("message");
l_DebugMessages.add("ACTIVATED ITEM: " + r_ActivateItem.get("message"));
}
//
// add to line items for sales orders or invoices
info "BooksItemID: " + v_BooksItemID;
m_BooksLineItem.put("item_id",v_BooksItemID);
m_BooksLineItem.put("name",v_ItemTitle);
v_ListingDescriptionCleaned = ifnull(v_ListingDescription,"").replaceAll("<br />","\n",true).replaceAll("<br>","\n",true).replaceAll("<(.|\n)*?>","");
m_BooksLineItem.put("description","");
v_OrderTaxFactor = v_OrderTaxPercent.toDecimal() / 100;
v_OrderTaxFactor = v_OrderTaxFactor + 1;
v_ItemPriceExclVAT = v_ItemPrice.toDecimal() / v_OrderTaxFactor;
v_ItemPriceExclVATRounded = floor(v_ItemPriceExclVAT * 100) / 100;
m_BooksLineItem.put("rate",v_ItemPrice);
m_BooksLineItem.put("quantity",v_TransactionQtyPurchased.toLong());
v_UnitType = "";
if(v_ItemTitle.containsIgnoreCase("wheel") && v_ItemTitle.containsIgnoreCase("tyre"))
{
v_UnitType = "pcs";
}
else if(v_ItemTitle.containsIgnoreCase("wheel"))
{
v_UnitType = "Wheel";
}
else if(v_ItemTitle.containsIgnoreCase("tyre"))
{
v_UnitType = "Tyre";
}
m_BooksLineItem.put("unit",v_UnitType);
m_BooksLineItem.put("tax_id",m_Taxes.get(v_OrderTaxPercent.toLong().toString()));
m_BooksLineItem.put("tax_percentage",v_OrderTaxPercent.toLong());
//m_BooksLineItem.put("item_total",v_ItemPriceExclVAT.toDecimal());
l_InventoryLineItems.add(m_BooksLineItem);
l_DebugMessages.add("BooksItemID: " + m_BooksLineItem);
}
//
// now loop through payments for this order
l_Payments = x_Order.executeXPath("//Order/MonetaryDetails/Payments").toXmlList();
v_OrderPayAmountTotal = 0.0;
l_eBayPaymentRefs = List();
for each x_Payment in l_Payments
{
m_eBayPaymentRef = Map();
v_PaymentRef = x_Payment.executeXPath("//Payment/ReferenceID/text()");
m_eBayPaymentRef.put("BooksItemID",v_BooksItemID);
m_eBayPaymentRef.put("ReferenceID",v_PaymentRef);
v_ThisPaymentStatus = x_Payment.executeXPath("//Payment/PaymentStatus/text()");
m_eBayPaymentRef.put("Status",v_ThisPaymentStatus);
v_ThisPaymentTime = x_Payment.executeXPath("//Payment/PaymentTime/text()");
v_ThisPaymentTime = if(!isnull(v_ThisPaymentTime),v_ThisPaymentTime.getPrefix(".").replaceFirst("T"," ",true),zoho.currenttime.toString("yyyy-MM-dd HH:mm:ss"));
m_eBayPaymentRef.put("DateTime",v_ThisPaymentTime);
v_ThisPayee = x_Payment.executeXPath("//Payment/Payee/text()");
m_eBayPaymentRef.put("Payee",v_ThisPayee);
v_ThisPaymentAmount = 0.0;
if(v_ThisPaymentStatus == "Succeeded" && v_ThisPayee == v_OrderSellerID)
{
v_ThisPaymentAmount = x_Payment.executeXPath("//Payment/PaymentAmount/text()");
v_OrderPayAmountTotal = v_OrderPayAmountTotal + v_ThisPaymentAmount.toDecimal();
}
m_eBayPaymentRef.put("Amount",v_ThisPaymentAmount);
l_eBayPaymentRefs.add(m_eBayPaymentRef);
}
info "Payment(s): ";
if(b_DebugMode)
{
info l_eBayPaymentRefs;
}
l_DebugMessages.add("PAYMENT(S): " + l_eBayPaymentRefs);
}
//
// search for this customer in Zoho Inventory
info "-----------------------";
v_BooksCustomerID = 0;
m_SearchCriteria = Map();
m_SearchCriteria.put("email",v_BuyerUserStaticEmail);
r_SearchContacts = zoho.inventory.getRecords("contacts",v_BooksOrgID,m_SearchCriteria,"joel_inventory");
for each r_Contact in r_SearchContacts.get("contacts")
{
if(!isnull(r_Contact.get("contact_id")))
{
if(!isNull(v_BuyerUserStaticEmail) && v_BuyerUserStaticEmail == r_Contact.get("email"))
{
v_BooksCustomerID = r_Contact.get("contact_id").toLong();
}
}
}
info "ZB Contact Search: " + v_BooksCustomerID;
l_DebugMessages.add("ZB Contact Search: " + v_BooksCustomerID);
if(v_BooksCustomerID == 0)
{
// create a contact person
m_ContactPerson = Map();
m_ContactPerson.put("email",v_BuyerUserStaticEmail);
m_ContactPerson.put("first_name",v_BuyerUserFName);
m_ContactPerson.put("last_name",v_BuyerUserSName);
m_ContactPerson.put("phone",v_BuyerShippingPhone);
m_ContactPerson.put("is_primary_contact",true);
l_CreateContactPerson = List();
l_CreateContactPerson.add(m_ContactPerson);
m_BooksContact.put("contact_persons",l_CreateContactPerson);
//
// other fields on creation
m_BooksContact.put("contact_type","customer");
m_BooksContact.put("customer_sub_type","individual");
m_BooksContact.put("payment_terms",0);
m_BooksContact.put("status","active");
//
// send request to create contact
r_CreateContact = zoho.inventory.createRecord("contacts",v_BooksOrgID,m_BooksContact,"joel_inventory");
info "CONTACT CREATE RESPONSE: ";
info r_CreateContact.get("message");
l_DebugMessages.add("CONTACT CREATE RESPONSE: " + r_CreateContact);
//
// retrieve the generated contact id for generating other records
if(!isnull(r_CreateContact.get("contact")))
{
if(!isnull(r_CreateContact.get("contact").get("contact_id")))
{
v_BooksCustomerID = r_CreateContact.get("contact").get("contact_id").toLong();
}
}
}
else
{
//
// send request to modify contact
r_UpdateContact = zoho.inventory.updateRecord("contacts",v_BooksOrgID,v_BooksCustomerID,m_BooksContact,"joel_inventory");
info "CONTACT UPDATE RESPONSE:";
info r_UpdateContact.get("message");
l_DebugMessages.add("CONTACT UPDATE RESPONSE: " + r_UpdateContact.get("message"));
}
info "CustomerID: " + v_BooksCustomerID;
l_DebugMessages.add("CustomerID: " + v_BooksCustomerID);
info "-----------------------";
//
// ********************************************************
// now we have contact ID and item ID, let's create Sales Order
if(v_BooksCustomerID != 0 && v_BooksItemID != 0)
{
m_BooksSalesOrder = Map();
m_BooksSalesOrder.put("customer_id",v_BooksCustomerID);
m_BooksSalesOrder.put("date",v_Transaction_DateCreated.toString("yyyy-MM-dd","Europe/London"));
m_BooksSalesOrder.put("reference_number",p_eBayOrderRef);
m_BooksSalesOrder.put("line_items",l_InventoryLineItems);
m_BooksSalesOrder.put("is_inclusive_tax",true);
m_BooksSalesOrder.put("shipping_charge",ifnull(v_ShippingServiceCost,0.0).toDecimal());
l_CustomFields = list();
m_CustomField = Map();
m_CustomField.put("api_name","cf_source");
m_CustomField.put("value","eBay");
l_CustomFields.add(m_CustomField);
m_CustomField = Map();
m_CustomField.put("api_name","cf_ebay_order_id");
m_CustomField.put("value",p_eBayOrderRef);
l_CustomFields.add(m_CustomField);
m_BooksSalesOrder.put("custom_fields",l_CustomFields);
//
// determine if sales order already exists or to update
v_BooksSoID = 0;
m_SearchCriteria = Map();
m_SearchCriteria.put("reference_number",p_eBayOrderRef);
r_BooksSearch = zoho.inventory.getRecords("salesorders",v_BooksOrgID,m_SearchCriteria,"joel_inventory");
for each r_So in r_BooksSearch.get("salesorders")
{
if(r_So.get("reference_number") == p_eBayOrderRef)
{
v_BooksSoID = r_So.get("salesorder_id");
}
}
info "ZB SalesOrder Search: " + v_BooksSoID;
l_DebugMessages.add("ZB SalesOrder Search: " + v_BooksSoID);
//info m_BooksSalesOrder;
//
// if sales order exists then update it
if(v_BooksSoID != 0)
{
r_UpdateSO = zoho.inventory.updateRecord("salesorders",v_BooksOrgID,v_BooksSoID,m_BooksSalesOrder,"joel_inventory");
info "SALESORDER UPDATE RESPONSE:";
info r_UpdateSO.get("message");
l_DebugMessages.add("SALESORDER UPDATE RESPONSE: " + r_UpdateSO.get("message") + "<br /><br />" + m_BooksSalesOrder);
//
r_BooksSO = zoho.inventory.getRecordsByID("salesorders",v_BooksOrgID,v_BooksSoID,"joel_inventory");
m_BooksSO = if(!isnull(r_BooksSO.get("salesorder")),r_BooksSO.get("salesorder").toMap(),{});
if(!isnull(m_BooksSO.get("salesorder_number")))
{
v_BooksSoReference = m_BooksSO.get("salesorder_number");
}
}
else
{
r_CreateSO = zoho.inventory.createRecord("salesorders",v_BooksOrgID,m_BooksSalesOrder,"joel_inventory");
info "SALESORDER CREATE RESPONSE:";
info r_CreateSO.get("message");
l_DebugMessages.add("SALESORDER CREATE RESPONSE: " + r_CreateSO.get("message") + "<br /><br />" + m_BooksSalesOrder);
//
// if having created the sales order
v_BooksSoReference = "";
if(!isnull(r_CreateSO.get("salesorder")))
{
if(!isnull(r_CreateSO.get("salesorder").get("salesorder_id")))
{
v_BooksSoID = r_CreateSO.get("salesorder").get("salesorder_id");
r_BooksSO = zoho.inventory.getRecordsByID("salesorders",v_BooksOrgID,v_BooksSoID,"joel_inventory");
m_BooksSO = if(!isnull(r_BooksSO.get("salesorder")),r_BooksSO.get("salesorder").toMap(),{});
}
if(!isnull(r_CreateSO.get("salesorder").get("salesorder_number")))
{
v_BooksSoReference = r_CreateSO.get("salesorder").get("salesorder_number");
}
}
}
//
info "SalesOrderID: " + v_BooksSoID;
info "SalesOrderRef: " + v_BooksSoReference;
info "-----------------------";
l_DebugMessages.add("SalesOrderID: " + v_BooksSoID);
l_DebugMessages.add("SalesOrderRef: " + v_BooksSoReference);
//
// in both cases let's confirm the sales order unless cancelled
if(b_OrderCancelled)
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/salesorders/" + v_BooksSoID + "/status/void?organization_id=" + v_BooksOrgID;
r_CancelSO = invokeurl
[
url :v_Endpoint
type :POST
connection:"joel_inventory"
];
info "SALESORDER VOID STATUS:";
info r_CancelSO.get("message");
l_DebugMessages.add("SALESORDER VOID RESPONSE: " + r_CancelSO.get("message"));
}
else
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/salesorders/" + v_BooksSoID + "/status/confirmed?organization_id=" + v_BooksOrgID;
r_ConfirmSO = invokeurl
[
url :v_Endpoint
type :POST
connection:"joel_inventory"
];
info "SALESORDER CONFIRMED STATUS:";
info r_ConfirmSO.get("message");
l_DebugMessages.add("SALESORDER CONFIRMED RESPONSE: " + r_ConfirmSO.get("message"));
}
//
// in both cases let's build up the package slip/delivery note line items
l_PackageLineItems = List();
l_ExistingSoLineItems = m_BooksSO.get("line_items");
for each r_SoLineItem in l_ExistingSoLineItems
{
m_PackageLineItem = Map();
m_PackageLineItem.put("so_line_item_id",r_SoLineItem.get("line_item_id"));
m_PackageLineItem.put("quantity",r_SoLineItem.get("quantity"));
l_PackageLineItems.add(m_PackageLineItem);
}
//
// search to see if invoice already generated
v_BooksInvoiceID = 0;
m_SearchCriteria = Map();
m_SearchCriteria.put("reference_number",v_BooksSoReference);
r_BooksSearch2 = zoho.inventory.getRecords("invoices",v_BooksOrgID,m_SearchCriteria,"joel_inventory");
for each r_Invoice in r_BooksSearch2.get("invoices")
{
if(!isNull(v_BooksSoReference) && r_Invoice.get("reference_number") == v_BooksSoReference)
{
v_BooksInvoiceID = r_Invoice.get("invoice_id").toLong();
v_InvoiceID = v_BooksInvoiceID;
v_InvoiceRef = r_Invoice.get("invoice_number");
}
}
info "ZB Invoice Search: " + v_BooksInvoiceID;
l_DebugMessages.add("ZB Invoice Search: " + v_BooksInvoiceID);
//
// create invoice if not exists
if(v_BooksInvoiceID == 0 && v_BooksSoID != 0)
{
//
v_InvoiceID = 0;
v_InvoiceRef = "";
v_Endpoint = "https://inventory.zoho.eu/api/v1/invoices/fromsalesorder?organization_id=" + v_BooksOrgID + "&salesorder_id=" + v_BooksSoID;
r_CreateInvoice = invokeurl
[
url :v_Endpoint
type :POST
connection:"joel_inventory"
];
info "INVOICE FROM SO RESPONSE: ";
info r_CreateInvoice.get("message");
l_DebugMessages.add("INVOICE FROM SO RESPONSE: " + r_CreateInvoice.get("message"));
//
if(!isnull(r_CreateInvoice.get("invoice")))
{
if(!isnull(r_CreateInvoice.get("invoice").get("invoice_id")))
{
v_InvoiceID = r_CreateInvoice.get("invoice").get("invoice_id").toLong();
v_BooksInvoiceID = v_InvoiceID;
v_InvoiceRef = r_CreateInvoice.get("invoice").get("invoice_number");
}
}
}
else
{
info "INVOICE REUSED:" + v_InvoiceRef;
l_DebugMessages.add("INVOICE REUSED:" + v_InvoiceRef);
}
//
// mark invoice as sent
if(v_BooksInvoiceID != 0)
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/invoices/" + v_BooksInvoiceID + "/status/sent?organization_id=" + v_BooksOrgID;
r_SendInvoice = invokeurl
[
url :v_Endpoint
type :POST
connection:"joel_inventory"
];
info "INVOICE SENT RESPONSE:";
info r_SendInvoice.get("message");
l_DebugMessages.add("INVOICE SENT RESPONSE: " + r_SendInvoice.get("message"));
}
//
// cancel invoice if order cancelled
if(b_OrderCancelled && v_BooksInvoiceID != 0)
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/invoices/" + v_BooksInvoiceID + "/status/void?organization_id=" + v_BooksOrgID;
r_CancelInvoice = invokeurl
[
url :v_Endpoint
type :POST
connection:"joel_inventory"
];
info "INVOICE VOID RESPONSE:";
info r_CancelInvoice.get("message");
l_DebugMessages.add("INVOICE VOID RESPONSE: " + r_CancelInvoice.get("message"));
}
info "InvoiceID: " + v_BooksInvoiceID;
info "InvoiceRef: " + v_InvoiceRef;
info "-----------------------";
l_DebugMessages.add("InvoiceID: " + v_BooksInvoiceID);
l_DebugMessages.add("InvoiceRef: " + v_InvoiceRef);
//
// search to see if package already generated
v_BooksPackageID = 0;
v_BooksShipmentID = 0;
m_SearchCriteria = Map();
m_SearchCriteria.put("salesorder_number",v_BooksSoReference);
r_BooksSearch3 = zoho.inventory.getRecords("packages",v_BooksOrgID,m_SearchCriteria,"joel_inventory");
for each r_Package in r_BooksSearch3.get("packages")
{
if(r_Package.get("salesorder_number") == v_BooksSoReference)
{
v_BooksPackageID = r_Package.get("package_id").toLong();
v_BooksShipmentID = if(isBlank(r_Package.get("shipment_id")),0,r_Package.get("shipment_id")).toLong();
}
}
info "ZB Package Search: " + v_BooksInvoiceID;
info "ZB Shipment Search: " + v_BooksShipmentID;
info "Transaction Hold Status: " + v_TransactionPaymentHoldStatus;
l_DebugMessages.add("ZB Package Search: " + v_BooksInvoiceID);
l_DebugMessages.add("ZB Shipment Search: " + v_BooksShipmentID);
l_DebugMessages.add("Transaction Hold Status: " + v_TransactionPaymentHoldStatus);
//
// create package
v_BooksPackageNumber = "";
if(v_BooksSoID.toLong() != 0 && v_BooksPackageID.toLong() == 0 && v_TransactionPaymentHoldStatus == "None" && !b_OrderCancelled)
{
//
l_PackageIDs = List();
m_BooksPackage = Map();
m_BooksPackage.put("salesorder_id",v_BooksSoID);
m_BooksPackage.put("date",v_Order_DateCreated.toString("yyyy-MM-dd"));
m_BooksPackage.put("line_items",l_PackageLineItems);
r_CreatePackage = zoho.inventory.createRecord("packages",v_BooksOrgID,m_BooksPackage,"joel_inventory");
info "PACKAGE CREATE RESPONSE:";
info r_CreatePackage.get("message");
l_DebugMessages.add("PACKAGE CREATE RESPONSE: " + r_CreatePackage.get("message"));
//
if(!isnull(r_CreatePackage.get("package")))
{
if(!isnull(r_CreatePackage.get("package").get("package_id")))
{
v_BooksPackageID = r_CreatePackage.get("package").get("package_id");
v_BooksPackageNumber = r_CreatePackage.get("package").get("package_number");
}
}
}
//
// delete package if exists and order cancelled
if(b_OrderCancelled && v_BooksPackageID.toLong() != 0)
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/packages/" + v_BooksPackageID + "?organization_id=" + v_BooksOrgID;
r_DeletePackage = invokeurl
[
url :v_Endpoint
type :DELETE
connection:"joel_inventory"
];
info "PACKAGE DELETE RESPONSE:";
info r_DeletePackage.get("message");
l_DebugMessages.add("PACKAGE DELETE RESPONSE: " + r_DeletePackage.get("message"));
}
info "-----------------------";
//
// record this payment
//info l_eBayPaymentRefs;
for each r_eBayPaymentRef in l_eBayPaymentRefs
{
if(v_InvoiceID != 0 && v_TransactionPaymentHoldStatus == "None" && !b_OrderCancelled)
{
//
// search to see if payment already recorded
v_BooksPaymentID = 0;
m_SearchCriteria = Map();
m_SearchCriteria.put("reference_number",r_eBayPaymentRef.get("ReferenceID"));
r_BooksSearch4 = zoho.inventory.getRecords("customerpayments",v_BooksOrgID,m_SearchCriteria,"joel_inventory");
for each r_Payment in r_BooksSearch4.get("customerpayments")
{
if(r_Payment.get("reference_number") == r_eBayPaymentRef.get("ReferenceID"))
{
v_BooksPaymentID = r_Payment.get("payment_id").toLong();
}
}
info "ZB Payment Search: " + v_BooksPaymentID;
l_DebugMessages.add("ZB Payment Search: " + v_BooksPaymentID);
//
// if not found, then create one
if(v_BooksPaymentID == 0)
{
m_BooksPayment = Map();
m_BooksPayment.put("customer_id",v_BooksCustomerID.toString());
m_BooksPayment.put("payment_mode",v_TransactionPaymentMethod);
m_BooksPayment.put("amount",r_eBayPaymentRef.get("Amount"));
m_BooksPayment.put("date",r_eBayPaymentRef.get("DateTime").toTime().toString("yyyy-MM-dd","Europe/London"));
m_BooksPayment.put("reference_number",r_eBayPaymentRef.get("ReferenceID"));
l_Invoices = List();
m_Invoice = Map();
m_Invoice.put("invoice_id",v_BooksInvoiceID);
m_Invoice.put("amount_applied",r_eBayPaymentRef.get("Amount"));
m_Invoice.put("tax_amount_withheld",0);
l_Invoices.add(m_Invoice);
m_BooksPayment.put("invoices",l_Invoices);
//
// create the payment record
r_CreatePayment = zoho.inventory.createRecord("customerpayments",v_BooksOrgID,m_BooksPayment,"joel_inventory");
info "PAYMENT RESPONSE:" + r_eBayPaymentRef.get("ReferenceID");
info r_CreatePayment.get("message");
l_DebugMessages.add("PAYMENT RESPONSE:" + r_eBayPaymentRef.get("ReferenceID") + ": " + r_CreatePayment.get("message"));
}
}
}
//
// check if invoice fully paid now
v_CurrentInvoiceStatus = "";
r_CurrentInvoice = zoho.inventory.getRecordsByID("invoices",v_BooksOrgID,v_InvoiceID,"joel_inventory");
if(!isnull(r_CurrentInvoice.get("invoice")))
{
v_CurrentInvoiceStatus = r_CurrentInvoice.get("invoice").get("status");
}
//
// create/update shipment if date shipped is specified and full payment received
l_DebugMessages.add("SHIPPING CREATE CONDITION: " + v_BooksPackageID + "::" + v_BooksSoID + "::" + v_Order_DateShipped + "::" + v_CurrentInvoiceStatus + "::" + b_OrderCancelled);
if(v_BooksPackageID != 0 && v_BooksSoID != 0 && !isNull(v_Order_DateShipped) && v_CurrentInvoiceStatus == "paid" && !b_OrderCancelled)
{
//
v_ShipmentID = 0;
m_BooksShipment = Map();
m_BooksShipment.put("shipment_number","SH-" + v_BooksSoReference.getSuffix("-"));
m_BooksShipment.put("date",v_Order_DateCreated.toString("yyyy-MM-dd"));
m_BooksShipment.put("reference_number",v_BooksSoReference);
m_BooksShipment.put("delivery_method",v_ShippingCarrier);
m_BooksShipment.put("tracking_number",v_ShippingTrackingNumber);
l_DebugMessages.add("SHIPPING CREATE REQUEST: " + m_BooksShipment);
//
if(v_BooksShipmentID == 0)
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/shipmentorders?organization_id=" + v_BooksOrgID + "&package_ids=" + v_BooksPackageID + "&salesorder_id=" + v_BooksSoID;
r_CreateShipment = invokeurl
[
url :v_Endpoint
type :POST
parameters:m_BooksShipment.toString()
connection:"joel_inventory"
];
info "SHIPPING CREATE RESPONSE:";
info r_CreateShipment.get("message");
l_DebugMessages.add("SHIPPING CREATE RESPONSE: " + r_CreateShipment.get("message"));
//
if(!isnull(r_CreateShipment.get("shipmentorder")))
{
if(!isnull(r_CreateShipment.get("shipmentorder").get("shipment_id")))
{
v_ShipmentID = r_CreateShipment.get("shipmentorder").get("shipment_id").toLong();
}
}
}
else
{
v_ShipmentID = v_BooksShipmentID;
v_Endpoint = "https://inventory.zoho.eu/api/v1/shipmentorders/" + v_BooksShipmentID + "?organization_id=" + v_BooksOrgID + "&package_ids=" + v_BooksPackageID + "&salesorder_id=" + v_BooksSoID;
r_UpdateShipment = invokeurl
[
url :v_Endpoint
type :PUT
parameters:m_BooksShipment.toString()
connection:"joel_inventory"
];
info "SHIPPING UPDATE RESPONSE:";
info r_UpdateShipment.get("message");
l_DebugMessages.add("SHIPPING UPDATE RESPONSE: " + r_UpdateShipment.get("message"));
}
//
// check delivery status based on tracking number
if(!isNull(v_ShippingTrackingNumber))
{
v_DeliveryStatus = standalone.fn_DHL_CheckShipmentStatus(v_ShippingTrackingNumber);
l_DebugMessages.add("DHL API Shipment Status: " + v_DeliveryStatus);
if(v_DeliveryStatus.equalsIgnoreCase("delivered"))
{
//
// mark as delivered
if(v_ShipmentID != 0)
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/shipmentorders/" + v_ShipmentID + "/status/delivered?organization_id=" + v_BooksOrgID;
r_UpdateShipment = invokeurl
[
url :v_Endpoint
type :POST
connection:"joel_inventory"
];
info "SHIPPING DELIVERED RESPONSE:";
info r_UpdateShipment.get("message");
l_DebugMessages.add("SHIPPING DELIVERED RESPONSE: " + r_UpdateShipment.get("message"));
}
}
}
}
//
// delete shipment order if exists and order cancelled
if(b_OrderCancelled && v_BooksShipmentID.toLong() != 0)
{
v_Endpoint = "https://inventory.zoho.eu/api/v1/shipmentorders/" + v_BooksShipmentID + "?organization_id=" + v_BooksOrgID;
r_DeleteShipment = invokeurl
[
url :v_Endpoint
type :DELETE
connection:"joel_inventory"
];
info "SHIPMENT DELETE RESPONSE:";
info r_DeleteShipment.get("message");
l_DebugMessages.add("SHIPMENT DELETE RESPONSE: " + r_DeleteShipment.get("message"));
}
}
//
if(b_DebugMode)
{
/*
l_DebugMessages.add("That's all folks!");
v_DebugMessages = l_DebugMessages.toString("<hr />");
sendmail
[
from :zoho.adminuserid
to :"errors+customer-DEBUG@joellipman.com"
subject :"DEBUG: eBay Order: " + p_eBayOrderRef + " :: SO Order: " + v_BooksSoReference
message :v_DebugMessages
]
*/
}
return "";
Postrequisites:
- Setup a notification on the eBay instance to notify this webhook whenever an order is created or modified.
- Setup a scheduled function in Zoho Inventory to re-query an order as to whether it has been shipped.
- Setup a scheduled function to query DHL (the courier in this case) to check if an item has been delivered.
Error(s) Encountered
- Invalid value passed for package_ids
- Invalid value passed for salesorder_id
- {"code":57,"message":"You are not authorized to perform this operation"}
- {"code":36023,"message":"Sorry, you are not allowed to update or delete a product which is marked as invoiced."}
- {"code":9205,"message":"You do not have sufficient stock to create out-transactions for the item (...). Please restock the item and try again.","error_info":["1234756000001234567"]}
- {"code":2051,"message":"Please enter a positive opening stock rate."}
Discussion
Comments
Questions, corrections and useful additions are reviewed before appearing here.
No comments yet. Start the discussion.