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
copyraw
/* 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 :"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."}
Category: Zoho :: Article: 846