我正在使用Netsuite PHP Toolkit来获取客户的发票列表。我可以毫无问题地打电话(使用TransactionSearch),但我很难理解如何获取发票的所有详细信息,即发票"标题"详细信息(如总额、货币、主菜单行等)以及每行项目的详细信息(净值、应纳税额、项目等)。
我尝试了几种方法:
-
TransactionSearchAdvanced,指定了返回列,并将returnSearchColumns首选项设置为"false"。这会返回所有单独的行(哇!),但货币和术语等内容并没有展开——你只需要指定internalId,而不是实际的文本(或符号)。此外,对于TSA,您真的必须指定您想要的每一列吗?即,默认的真的只是一组空字段吗?难道没有一种方法可以说"给我每张发票所有行的所有详细信息吗?
-
TransactionSearch,returnSearchColumns首选项设置为"true"。这提供了一个单一发票类型记录的列表,其中正确填充了所有货币和术语,但令人沮丧的是,没有一个单独的行项目。这更像是一个总结。
因此,我只剩下几个选项,它们都不太令人满意,即:
- 对所有发票执行两个调用并合并数据。这些搜索需要很长时间(性能对我来说是另一个难题,所以我真的不想这么做
或
- 找出一种请求条款、货币等数据的方法,以及获取发票行的方法
我不知道你应该怎么做,在互联网上也找不到任何关于它的信息。这是我用过的最糟糕的接口之一(我用过一些非常糟糕的接口)。
任何帮助都将不胜感激。
就像你一样,我开始尝试使用Web服务API(也称为SuiteTalk)。大多数情况下,这是一次沮丧的锻炼,因为最终我发现,我根本无法和他们一起做我想做的事。这和性能都很糟糕,即使我的项目运行正常,这也会扼杀我的项目。
和Faz一样,我发现使用RESTlets和Saved Searches的组合比使用web服务框架更容易、更快。
基本上将您的问题分解为以下几个部分:
- 保存的搜索,返回您想要的结果(跟踪您稍后需要的内部ID)
- RESTlet它只是一个Javascript文件,定义了用于返回搜索结果的函数
- 调用RESTlet并获取结果的客户端代码
第一部分:因此,保存的搜索非常简单。我假设你可以做到这一点,而且你实际上可以在一个地方获得你想要的所有字段。根据我的经验,情况并非总是如此。
第二部分:RESTlet涉及更多的步骤,尽管它实际上是一件非常简单的事情。让它变得复杂的是将它上传并部署在NetSuite网站上。如果你还没有安装NetSuite IDE,我强烈建议你安装它,哪怕只是为了让部署脚本更容易一点。自动完成和工具提示也非常有用。
例如,这里是我用来从我关心的搜索中获得结果的代码。这是根据某个灵魂在互联网上的帖子改编的,但我忘了在哪里:
function getSearchResults(){
var max_rows = 1000;
var search_id = 1211;
var search = nlapiLoadSearch(null, search_id);
var results = search.runSearch();
var rows = [];
// add starting point for usage
var context = nlapiGetContext();
startingUsage = context.getRemainingUsage();
rows.push(["beginning usage", startingUsage]);
// now create the collection of result rows in 1000 row chunks
var index = 0;
do{
var chunk = results.getResults(index, index+1000);
if( ! chunk ) break;
chunk.forEach( function(row){
rows.push(row);
index++;
});
}while( chunk.length === max_rows);
// add a line that returns the remaining usage for this RESTlet
context = nlapiGetContext();
var remainingUsage = context.getRemainingUsage();
rows.push(["remaining usage",remainingUsage]);
// send back the rows
return rows;
}
这是你通过传递你保存的搜索内部ID:来做好准备的地方
var search = nlapiLoadSearch(null, SEARCH_ID);
var resultSet = search.runSearch();
然后代码重复调用getResults()以获得1000个结果的块,这是NetSuite的限制。一旦你写了这篇文章,你必须将脚本上传到NetSuite并配置和部署它。最重要的部分是告诉它给每个动词分配什么功能。在本例中,我指定GET执行getSearchResults。这里有很多工作要做,我不会把所有的都打出来,因为这部分值得你花时间学习。至少足以让IDE为你做这件事=D。您可以在"RESTlets简介"指南中阅读有关它的全部内容。
第三部分。客户端代码可以是任何你想要的,以你喜欢的方式进行REST。就我个人而言,我喜欢Python,因为请求库非常棒。下面是一些Python代码示例:
import requests
import json
url = 'https://rest.sandbox.netsuite.com/app/site/hosting/restlet.nl?script=123&deploy=1'
headers = {'Content-Type': 'application/json', 'Authorization':'NLAuth nlauth_account=1234567, nlauth_email=someone@somewhere.com, nlauth_signature=somepassword, nlauth_role=3'}
resp = requests.get(url, headers=headers)
data = resp.json()
URL将作为RESTlet部署的一部分显示给您。然后,你就可以对返回的数据做你想做的事情了。
所以我建议你花时间在上
- 设置NetSuite IDE
- 获取和阅读SuiteScript开发人员参考文档
- 找到用您选择的语言创建REST客户端代码的好方法
我希望这能有所帮助。
我在Netsuite中创建了一个保存的搜索,并使用restlet调用该搜索。有了它,它非常轻量级,您可以在保存的搜索中原样调用数据。
性能方面,Restlet比Web服务要好得多。
创建一个新的suitelet脚本并部署
下面的脚本将按客户内部id 给您发票列表
function customSearch(request, response) {
var rows = [];
var result;
var filters = [];
//9989 is customer internal id you can add more
// by pushing additional ids to array
filters.push(new nlobjSearchFilter('entity', null, 'anyOf', [9989] ));
var invoiceList = nlapiSearchRecord('invoice', null, filters, []);
// by default record limit is 1000
// taking 100 records
for (var i = 0; i < Math.min(100, invoiceList.length); i++)
{
if (parseInt(invoiceList[i].getId()) > 0) {
recordid = invoiceList[i].getId();
try {
result= nlapiLoadRecord(invoiceList[i].getRecordType(), recordid);
// pushing in to result
rows.push(result);
} catch (e) {
if (e instanceof nlobjError) {
nlapiLogExecution('DEBUG', 'system error', e.getCode() + ''n' + e.getDetails());
} else {
nlapiLogExecution('DEBUG', 'unexpected error', e.toString());
}
}
}
}
response.setContentType('JSON');
response.write(JSON.stringify({'records' : rows}));
return;
}
}
}
response.setContentType('JSON');
response.write(JSON.stringify({'records' : rows}));
return;
}
以下是我获得客户发票的方法:
public function getCustomerInvoices($customer_id)
{
$service = new NetSuiteService($this->config);
$customerSearchBasic = new CustomerSearchBasic();
$searchValue = new RecordRef();
$searchValue->type = 'customer';
$searchValue->internalId = $customer_id;
$searchMultiSelectField = new SearchMultiSelectField();
setFields($searchMultiSelectField, array('operator' => 'anyOf', 'searchValue' => $searchValue));
$customerSearchBasic->internalId = $searchMultiSelectField;
$transactionSearchBasic = new TransactionSearchBasic();
$searchMultiSelectEnumField = new SearchEnumMultiSelectField();
setFields($searchMultiSelectEnumField, array('operator' => 'anyOf', 'searchValue' => "_invoice"));
$transactionSearchBasic->type = $searchMultiSelectEnumField;
$transactionSearch = new TransactionSearch();
$transactionSearch->basic = $transactionSearchBasic;
$transactionSearch->customerJoin = $customerSearchBasic;
$request = new SearchRequest();
$request->searchRecord = $transactionSearch;
$searchResponse = $service->search($request);
return $searchResponse->searchResult->recordList;
}