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 :"This email address is being protected from spambots. You need JavaScript enabled to view it."
subject :"DEBUG: eBay Order: " + p_eBayOrderRef + " :: SO Order: " + v_BooksSoReference
message :v_DebugMessages
]
*/
}
return "";
- /*
- 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+This email address is being protected from spambots. You need JavaScript enabled to view it."
- 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."}