delete from xt.js where js_context='xtuple' and js_type = 'item_site';
select xt.install_js('XM','ItemSite','xtuple', $$
- /* Copyright (c) 1999-2014 by OpenMFG LLC, d/b/a xTuple.
+ /* Copyright (c) 1999-2014 by OpenMFG LLC, d/b/a xTuple.
See www.xm.ple.com/CPAL for the full text of the software license. */
(function () {
Return the current cost for a particular item site.
*/
XM.ItemSite.cost = function (itemsiteId) {
- if (!XT.Data.checkPrivilege('ViewCosts')) { return null };
+ if (!XT.Data.checkPrivilege('ViewCosts')) { return null; }
return plv8.execute('select itemcost(itemsite_id) as cost from itemsite where obj_uuid = $1;', [itemsiteId])[0].cost;
};
/** @private */
- var _fetch = function (recordType, query) {
+ var _fetch = function (recordType, backingType, query) {
query = query || {};
var data = Object.create(XT.Data),
namespace = recordType.beforeDot(),
type = recordType.afterDot(),
+ tableNamespace = backingType.beforeDot(),
+ table = backingType.afterDot(),
customerId = null,
accountId = -1,
shiptoId,
clause,
keySearch = false,
extra = "",
- sql = 'select * ' +
- 'from %1$I.%2$I ' +
- 'where {conditions} {extra}';
+ qry,
+ counter = 1,
+ ids = [],
+ idParams = [],
+ sql1 = 'select t1.itemsite_id as id ' +
+ 'from %1$I.%2$I t1 {joins} ' +
+ 'where {conditions} {extra}',
+ sql2 = 'select * from %1$I.%2$I where id in ({ids}) {orderBy}';
/* Handle special parameters */
if (query.parameters) {
/* Over-ride usual search behavior */
if (param.keySearch) {
keySearch = param.value;
- sql += ' and (number ~^ ${p1} or barcode ~^ ${p1}) ' +
- 'union ' +
- 'select %2$I.* ' +
- 'from %1$I.%2$I ' +
- ' join itemsite on itemsite_id=id ' +
- ' join itemalias on itemsite_item_id=itemalias_item_id ' +
- ' and itemalias_crmacct_id is null ' +
- 'where {conditions} {extra} ' +
- ' and (itemalias_number ~^ ${p1}) ' +
- 'union ' +
- 'select %2$I.* ' +
- 'from %1$I.%2$I ' +
- ' join itemsite on itemsite_id=id ' +
- ' join itemalias on itemsite_item_id=itemalias_item_id ' +
- ' and itemalias_crmacct_id={accountId} ' +
- 'where {conditions} {extra} ' +
- ' and (itemalias_number ~^ ${p1}) ';
+ sql1 += ' and itemsite_item_id in (select item_id from item where item_number ~^ ${p1} or item_upccode ~^ ${p1}) ' +
+ 'union ' +
- 'select t1.itemsite_id ' +
- 'from %1$I.%2$I t1 {joins} ' +
++ 'select t1.itemsite_id ' +
++ 'from %1$I.%2$I t1 {joins} ' +
+ ' join itemalias on itemsite_item_id=itemalias_item_id ' +
+ ' and itemalias_crmacct_id is null ' +
+ 'where {conditions} {extra} ' +
+ ' and (itemalias_number ~^ ${p1}) ' +
+ 'union ' +
- 'select t1.itemsite_id ' +
- 'from %1$I.%2$I t1 {joins} ' +
++ 'select t1.itemsite_id ' +
++ 'from %1$I.%2$I t1 {joins} ' +
+ ' join itemalias on itemsite_item_id=itemalias_item_id ' +
+ ' and itemalias_crmacct_id={accountId} ' +
+ 'where {conditions} {extra} ' +
+ ' and (itemalias_number ~^ ${p1}) ';
return false;
}
result = true;
}
return result;
- })
+ });
}
- clause = data.buildClause(namespace, type, query.parameters, query.orderBy);
+ clause = data.buildClause(namespace, type, query.parameters, query.orderByColumns);
/* If customer passed, restrict results to item sites allowed to be sold to that customer */
if (customerId) {
- extra += ' and (item).id in (' +
+ extra += ' and jt0.item_id in (' + /* XXX jt0 is a dangerous assumption */
'select item_id from item where item_sold and not item_exclusive ' +
'union ' +
'select item_id from xt.custitem where cust_id=${p2} ' +
/* If vendor passed, and vendor can only supply against defined item sources, then restrict results */
if (vendorId) {
- extra += ' and (item).id in (' +
+ extra += ' and jt0.item_id in (' + /* XXX jt0 is a dangerous assumption */
' select itemsrc_item_id ' +
' from itemsrc ' +
' where itemsrc_active ' +
' and itemsrc_vend_id=' + vendorId + ')';
}
- sql = XT.format(
- sql += '{orderBy} %3$s %4$s;',
- [namespace.decamelize(), type.decamelize(), limit, offset]
+ sql1 = XT.format(
+ sql1 += '{orderBy} %3$s %4$s;',
+ [tableNamespace, table, limit, offset]
);
/* Query the model */
- sql = sql.replace(/{conditions}/g, clause.conditions)
+ sql1 = sql1.replace(/{conditions}/g, clause.conditions)
.replace(/{extra}/g, extra)
+ .replace(/{joins}/g, clause.joins)
.replace('{orderBy}', clause.orderBy)
.replace('{limit}', limit)
.replace('{offset}', offset)
clause.parameters = clause.parameters.concat([customerId, shiptoId, effectiveDate]);
}
if (DEBUG) {
- XT.debug('ItemSiteListItem sql = ', sql.slice(0,500));
- XT.debug('ItemSiteListItem sql = ', sql.slice(500, 1000));
- XT.debug('ItemSiteListItem sql = ', sql.slice(1000, 1500));
- XT.debug('ItemSiteListItem sql = ', sql.slice(1500, 2000));
- plv8.elog(NOTICE, 'sql1 = ', sql1.slice(0,500));
- plv8.elog(NOTICE, sql1.slice(500, 1000));
- plv8.elog(NOTICE, sql1.slice(1000, 1500));
- plv8.elog(NOTICE, sql1.slice(1500, 2000));
- plv8.elog(NOTICE, sql1.slice(2000, 2500));
- plv8.elog(NOTICE, 'parameters = ', clause.parameters);
++ XT.debug('ItemSiteListItem sql1 = ', sql1.slice(0,500));
++ XT.debug(sql1.slice(500, 1000));
++ XT.debug(sql1.slice(1000, 1500));
++ XT.debug(sql1.slice(1500, 2000));
++ XT.debug(sql1.slice(2000, 2500));
+ XT.debug('ItemSiteListItem parameters = ', clause.parameters);
}
- return plv8.execute(sql, clause.parameters);
+ qry = plv8.execute(sql1, clause.parameters);
+
+ if (!qry.length) { return [] };
+ qry.forEach(function (row) {
+ ids.push(row.id);
+ idParams.push("$" + counter);
+ counter++;
+ });
+
+ sql2 = XT.format(sql2, [namespace.decamelize(), type.decamelize()]);
+ sql2 = sql2.replace(/{orderBy}/g, clause.orderBy)
+ .replace('{ids}', idParams.join());
+
+ if (DEBUG) {
+ XT.debug('fetch sql2 = ', sql2);
+ XT.debug('fetch values = ', JSON.stringify(ids));
+ }
+ return plv8.execute(sql2, ids);
-
++
};
if (!XM.ItemSiteListItem) { XM.ItemSiteListItem = {}; }
@returns {Array}
*/
XM.ItemSiteListItem.fetch = function (query) {
- return _fetch("XM.ItemSiteListItem", query);
+ return _fetch("XM.ItemSiteListItem", "public.itemsite", query);
};
+ /**
+ Wrapper for XM.ItemSiteListItem.fetch with support for REST query formatting.
+ Sample usage:
+ select xt.post($${
+ "nameSpace":"XM",
+ "type":"ItemSiteListItem",
+ "dispatch":{
+ "functionName":"restFetch",
+ "parameters":[
+ {
+ "query":[
+ {"customer":{"EQUALS":"TTOYS"}},
+ {"shipto":{"EQUALS":"1d103cb0-dac6-11e3-9c1a-0800200c9a66"}},
+ {"effectiveDate":{"EQUALS":"2014-05-01"}}
+ ]
+ }
+ ]
+ },
+ "username":"admin",
+ "encryptionKey":"hm6gnf3xsov9rudi"
+ }$$);
+
+ @param {Object} options: query
+ @returns Object
+ */
+ XM.ItemSiteListItem.restFetch = function (options) {
+ options = options || {};
+
+ var items = {},
+ query = {},
+ result = {};
+
+ if (options) {
+ /* Convert from rest_query to XM.Model.query structure. */
+ query = XM.Model.restQueryFormat(options);
+
+ /* Perform the query. */
+ items = XM.ItemSiteListItem.fetch(query);
+ }
+
+ result = {items: items};
+
+ return items;
+ };
+ XM.ItemSiteListItem.restFetch.description = "Returns ItemSiteListItems with additional special support for exclusive item rules, to filter on only items with associated item sources and Cross check on `alias` and `barcode` attributes for item numbers.";
+ XM.ItemSiteListItem.restFetch.request = {
+ "$ref": "ItemSiteListItemQuery"
+ };
+ XM.ItemSiteListItem.restFetch.parameterOrder = ["options"];
+ // For JSON-Schema deff, see:
+ // https://github.com/fge/json-schema-validator/issues/46#issuecomment-14681103
+ XM.ItemSiteListItem.restFetch.schema = {
+ ItemSiteListItemQuery: {
+ properties: {
+ attributes: {
+ title: "ItemSiteListItem Service request attributes",
+ description: "An array of attributes needed to perform a ItemSiteListItem query.",
+ type: "array",
+ items: [
+ {
+ title: "Options",
+ type: "object",
+ "$ref": "ItemSiteListItemOptions"
+ }
+ ],
+ "minItems": 1,
+ "maxItems": 1,
+ required: true
+ }
+ }
+ },
+ ItemSiteListItemOptions: {
+ properties: {
+ query: {
+ title: "query",
+ description: "The query to perform.",
+ type: "array",
+ items: [
+ {
+ title: "column",
+ type: "object"
+ }
+ ],
+ "minItems": 1
+ },
+ orderby: {
+ title: "Order By",
+ description: "The query order by.",
+ type: "array",
+ items: [
+ {
+ title: "column",
+ type: "object"
+ }
+ ]
+ },
+ rowlimit: {
+ title: "Row Limit",
+ description: "The query for paged results.",
+ type: "integer"
+ },
+ maxresults: {
+ title: "Max Results",
+ description: "The query limit for total results.",
+ type: "integer"
+ },
+ pagetoken: {
+ title: "Page Token",
+ description: "The query offset page token.",
+ type: "integer"
+ },
+ count: {
+ title: "Count",
+ description: "Set to true to return only the count of results for this query.",
+ type: "boolean"
+ }
+ }
+ }
+ };
+
if (!XM.ItemSiteRelation) { XM.ItemSiteRelation = {}; }
XM.ItemSiteRelation.isDispatchable = true;
@returns {Array}
*/
XM.ItemSiteRelation.fetch = function (query) {
- return _fetch("XM.ItemSiteRelation", query);
+ return _fetch("XM.ItemSiteRelation", "xt.itemsiteinfo", query);
};
}());
};
/**
- Returns a complex query's results using the REST query structure. This is a
- wrapper for XM.Model.query that reformats the query structure from a
- rest_query to our XT.Rest structure. This dispatch function can be used by
- a REST API client to query a resource when the query would be too long to
- pass to the API as a GET URL query.
+ Format acomplex query's using the REST query structure into an xTuple's query.
+ This is a helper function that reformats the query structure from a
+ rest_query to our XT.Rest structure. This function should be used by reformat
+ any REST API client queriers.
Sample usage:
- select xt.post('{
- "username": "admin",
- "nameSpace": "XM",
- "type": "Model",
- "dispatch":{
- "functionName":"restQuery",
- "parameters":["Address", {"query": [{"city":{"EQUALS":"Norfolk"}}], "orderby": [{"ASC": "line1"}, {"DESC": "line2"}]}]
- }
- }');
+ XM.Model.restQueryFormat({"query": [{"city":{"EQUALS":"Norfolk"}}], "orderby": [{"ASC": "line1"}, {"DESC": "line2"}]})
- @param {String} recordType to query
@param {Object} options: query
- @returns Object
+ @returns {Object} The formated query
*/
- XM.Model.restQuery = function (recordType, options) {
+ XM.Model.restQueryFormat = function (options) {
options = options || {};
+
var order = {},
param = {},
query = {},
};
/* Convert from rest_query to XM.Model.query structure. */
- if (recordType && options) {
+ if (options) {
if (options.query) {
query.parameters = [];
for (var i = 0; i < options.query.length; i++) {
for (var o = 0; o < options.orderBy.length; o++) {
for (var column in options.orderBy[o]) {
order = {};
- order.attribute = options.orderBy[o][column];
- if (column === 'DESC') {
+ order.attribute = column;
+ if (options.orderBy[o][column] === 'DESC') {
order.descending = true;
}
query.orderBy.push(order);
}
}
- result = XM.Model.query(recordType, {"query": query});
+ return query;
+ };
+
+ /**
+ Returns a complex query's results using the REST query structure. This is a
+ wrapper for XM.Model.query that reformats the query structure from a
+ rest_query to our XT.Rest structure. This dispatch function can be used by
+ a REST API client to query a resource when the query would be too long to
+ pass to the API as a GET URL query.
+
+ Sample usage:
+ select xt.post('{
+ "username": "admin",
+ "nameSpace": "XM",
+ "type": "Model",
+ "dispatch":{
+ "functionName":"restQuery",
+ "parameters":["Address", {"query": [{"city":{"EQUALS":"Norfolk"}}], "orderby": [{"ASC": "line1"}, {"DESC": "line2"}]}]
+ }
+ }');
+
+ @param {String} recordType to query
+ @param {Object} options: query
+ @returns Object
+ */
+ XM.Model.restQuery = function (recordType, options) {
+ options = options || {};
+ var formattedOptions = {};
+
+ /* Convert from rest_query to XM.Model.query structure. */
+ if (recordType && options) {
+ formattedOptions = {
+ "query": XM.Model.restQueryFormat(options)
+ };
+ }
+
+ result = XM.Model.query(recordType, formattedOptions);
return result;
};