Fix merge conflict.
authorBen Thompson <ben@xtuple.com>
Tue, 13 May 2014 17:58:41 +0000 (13:58 -0400)
committerBen Thompson <ben@xtuple.com>
Tue, 13 May 2014 17:58:41 +0000 (13:58 -0400)
1  2 
enyo-client/database/source/xm/javascript/item_site.sql
lib/orm/source/xm/javascript/model.sql

@@@ -2,7 -2,7 +2,7 @@@
  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);
    };
  
  }());
@@@ -319,20 -319,29 +319,20 @@@ select xt.install_js('XM','Model','xtup
    };
  
    /**
 -   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;
    };