31f25a53426ee5798fcd9e05b27140d80c0044a3
[xtuple] / enyo-client / database / source / xm / javascript / item_site.sql
1 /* Delete previously misnamed record */
2 delete from xt.js where js_context='xtuple' and js_type = 'item_site';
3
4 select xt.install_js('XM','ItemSite','xtuple', $$
5   /* Copyright (c) 1999-2014 by OpenMFG LLC, d/b/a xTuple.
6      See www.xm.ple.com/CPAL for the full text of the software license. */
7
8 (function () {
9
10   if (!XM.ItemSite) { XM.ItemSite = {}; }
11
12   XM.ItemSite.isDispatchable = true;
13
14   /**
15     Return the current cost for a particular item site.
16   */
17   XM.ItemSite.cost = function (itemsiteId) {
18     if (!XT.Data.checkPrivilege('ViewCosts')) { return null; }
19     return plv8.execute('select itemcost(itemsite_id) as cost from itemsite where obj_uuid = $1;', [itemsiteId])[0].cost;
20   };
21
22   /** @private */
23   var _fetch = function (recordType, backingType, query) {
24     query = query || {};
25     var data = Object.create(XT.Data),
26       namespace = recordType.beforeDot(),
27       type = recordType.afterDot(),
28       tableNamespace = backingType.beforeDot(),
29       table = backingType.afterDot(),
30       customerId = null,
31       accountId = -1,
32       shiptoId,
33       effectiveDate = new Date(),
34       vendorId = null,
35       limit = query.rowLimit ? 'limit ' + Number(query.rowLimit) : '',
36       offset = query.rowOffset ? 'offset ' + Number(query.rowOffset) : '',
37       clause,
38       keySearch = false,
39       extra = "",
40       qry,
41       counter = 1,
42       ids = [],
43       idParams = [],
44       sql1 = 'select t1.itemsite_id as id ' +
45             'from %1$I.%2$I t1 {joins} ' +
46             'where {conditions} {extra}',
47       sql2 = 'select * from %1$I.%2$I where id in ({ids}) {orderBy}';
48
49     /* Handle special parameters */
50     if (query.parameters) {
51       query.parameters = query.parameters.filter(function (param) {
52         var result = false;
53
54         /* Over-ride usual search behavior */
55         if (param.keySearch) {
56           keySearch = param.value;
57           sql1 += ' and itemsite_item_id in (select item_id from item where item_number ~^ ${p1} or item_upccode ~^ ${p1}) ' +
58             'union ' +
59             'select t1.itemsite_id ' +
60             'from %1$I.%2$I t1 {joins} ' +
61             ' join itemalias on itemsite_item_id=itemalias_item_id ' +
62             '   and itemalias_crmacct_id is null ' +
63             'where {conditions} {extra} ' +
64             ' and (itemalias_number ~^ ${p1}) ' +
65             'union ' +
66             'select t1.itemsite_id ' +
67             'from %1$I.%2$I t1 {joins} ' +
68             ' join itemalias on itemsite_item_id=itemalias_item_id ' +
69             '   and itemalias_crmacct_id={accountId} ' +
70             'where {conditions} {extra} ' +
71             ' and (itemalias_number ~^ ${p1}) ';
72           return false;
73         }
74
75         switch (param.attribute)
76         {
77         case "customer":
78           customerNumber = param.value;
79           customerId = data.getId(data.fetchOrm('XM', 'CustomerProspectRelation'), param.value);
80           accountId = data.getId(data.fetchOrm('XM', 'AccountRelation'), param.value);
81           break;
82         case "shipto":
83           shiptoId = data.getId(data.fetchOrm('XM', 'CustomerShipto'), param.value);
84           break;
85         case "effectiveDate":
86           effectiveDate = param.value;
87           break;
88         case "vendor":
89           vendorId = data.getId(data.fetchOrm('XM', 'VendorRelation'), param.value);
90           break;
91         default:
92           result = true;
93         }
94         return result;
95       });
96     }
97
98     clause = data.buildClause(namespace, type, query.parameters, query.orderByColumns);
99
100     /* If customer passed, restrict results to item sites allowed to be sold to that customer */
101     if (customerId) {
102       extra += ' and jt0.item_id in (' + /* XXX jt0 is a dangerous assumption */
103              'select item_id from item where item_sold and not item_exclusive ' +
104              'union ' +
105              'select item_id from xt.custitem where cust_id=${p2} ' +
106              '  and ${p4}::date between effective and (expires - 1) ';
107
108       if (shiptoId) {
109         extra += 'union ' +
110                'select item_id from xt.shiptoitem where shipto_id=${p3}::integer ' +
111                '  and ${p4}::date between effective and (expires - 1) ';
112       }
113
114       extra += ") ";
115     }
116
117     /* If vendor passed, and vendor can only supply against defined item sources, then restrict results */
118     if (vendorId) {
119       extra +=  ' and jt0.item_id in (' + /* XXX jt0 is a dangerous assumption */
120               '  select itemsrc_item_id ' +
121               '  from itemsrc ' +
122               '  where itemsrc_active ' +
123               '    and itemsrc_vend_id=' + vendorId + ')';
124     }
125
126     sql1 = XT.format(
127       sql1 += '{orderBy} %3$s %4$s;',
128       [tableNamespace, table, limit, offset]
129     );
130
131     /* Query the model */
132     sql1 = sql1.replace(/{conditions}/g, clause.conditions)
133              .replace(/{extra}/g, extra)
134              .replace(/{joins}/g, clause.joins)
135              .replace('{orderBy}', clause.orderBy)
136              .replace('{limit}', limit)
137              .replace('{offset}', offset)
138              .replace('{accountId}', accountId)
139              .replace(/{p1}/g, clause.parameters.length + 1)
140              .replace(/{p2}/g, clause.parameters.length + (keySearch ? 2 : 1))
141              .replace(/{p3}/g, clause.parameters.length + (keySearch ? 3 : 2))
142              .replace(/{p4}/g, clause.parameters.length + (keySearch ? 4 : 3));
143
144     if (keySearch) {
145       clause.parameters.push(keySearch);
146     }
147     if (customerId) {
148       clause.parameters = clause.parameters.concat([customerId, shiptoId, effectiveDate]);
149     }
150     if (DEBUG) {
151       XT.debug('ItemSiteListItem sql1 = ', sql1.slice(0,500));
152       XT.debug(sql1.slice(500, 1000));
153       XT.debug(sql1.slice(1000, 1500));
154       XT.debug(sql1.slice(1500, 2000));
155       XT.debug(sql1.slice(2000, 2500));
156       XT.debug('ItemSiteListItem parameters = ', clause.parameters);
157     }
158     qry = plv8.execute(sql1, clause.parameters);
159
160     if (!qry.length) { return []; }
161     qry.forEach(function (row) {
162       ids.push(row.id);
163       idParams.push("$" + counter);
164       counter++;
165     });
166
167     sql2 = XT.format(sql2, [namespace.decamelize(), type.decamelize()]);
168     sql2 = sql2.replace(/{orderBy}/g, clause.orderBy)
169                .replace('{ids}', idParams.join());
170
171     if (DEBUG) {
172       XT.debug('fetch sql2 = ', sql2);
173       XT.debug('fetch values = ', JSON.stringify(ids));
174     }
175     return plv8.execute(sql2, ids);
176
177   };
178
179   if (!XM.ItemSiteListItem) { XM.ItemSiteListItem = {}; }
180
181   XM.ItemSiteListItem.isDispatchable = true;
182
183   /**
184     Returns item site list items using usual query means with additional special support for:
185       * Attributes `customer`,`shipto`, and `effectiveDate` for exclusive item rules.
186       * Attribute `vendor` to filter on only items with associated item sources.
187       * Cross check on `alias` and `barcode` attributes for item numbers.
188
189     @param {String} Record type. Must have `itemsite` or related view as its orm source table.
190     @param {Object} Additional query filter (Optional)
191     @returns {Array}
192   */
193   XM.ItemSiteListItem.fetch = function (query) {
194     return _fetch("XM.ItemSiteListItem", "public.itemsite", query);
195   };
196
197   /**
198    Wrapper for XM.ItemSiteListItem.fetch with support for REST query formatting.
199    Sample usage:
200     select xt.post('{
201       "nameSpace":"XM",
202       "type":"ItemSiteListItem",
203       "dispatch":{
204         "functionName":"restFetch",
205         "parameters":[
206           {
207             "query":[
208               {"customer":{"EQUALS":"TTOYS"}},
209               {"shipto":{"EQUALS":"1d103cb0-dac6-11e3-9c1a-0800200c9a66"}},
210               {"effectiveDate":{"EQUALS":"2014-05-01"}}
211             ]
212           }
213         ]
214       },
215       "username":"admin",
216       "encryptionKey":"hm6gnf3xsov9rudi"
217     }');
218
219    @param {Object} options: query
220    @returns Object
221   */
222   XM.ItemSiteListItem.restFetch = function (options) {
223     options = options || {};
224
225     var items = {},
226       query = {},
227       result = {};
228
229     if (options) {
230       /* Convert from rest_query to XM.Model.query structure. */
231       query = XM.Model.restQueryFormat(options);
232
233       /* Perform the query. */
234       items = XM.ItemSiteListItem.fetch(query);
235     }
236
237     result = {items: items};
238
239     return items;
240   };
241   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.";
242   XM.ItemSiteListItem.restFetch.request = {
243     "$ref": "ItemSiteListItemQuery"
244   };
245   XM.ItemSiteListItem.restFetch.parameterOrder = ["options"];
246   // For JSON-Schema deff, see:
247   // https://github.com/fge/json-schema-validator/issues/46#issuecomment-14681103
248   XM.ItemSiteListItem.restFetch.schema = {
249     ItemSiteListItemQuery: {
250       properties: {
251         attributes: {
252           title: "ItemSiteListItem Service request attributes",
253           description: "An array of attributes needed to perform a ItemSiteListItem query.",
254           type: "array",
255           items: [
256             {
257               title: "Options",
258               type: "object",
259               "$ref": "ItemSiteListItemOptions"
260             }
261           ],
262           "minItems": 1,
263           "maxItems": 1,
264           required: true
265         }
266       }
267     },
268     ItemSiteListItemOptions: {
269       properties: {
270         query: {
271           title: "query",
272           description: "The query to perform.",
273           type: "array",
274           items: [
275             {
276               title: "column",
277               type: "object"
278             }
279           ],
280           "minItems": 1
281         },
282         orderby: {
283           title: "Order By",
284           description: "The query order by.",
285           type: "array",
286           items: [
287             {
288               title: "column",
289               type: "object"
290             }
291           ]
292         },
293         rowlimit: {
294           title: "Row Limit",
295           description: "The query for paged results.",
296           type: "integer"
297         },
298         maxresults: {
299           title: "Max Results",
300           description: "The query limit for total results.",
301           type: "integer"
302         },
303         pagetoken: {
304           title: "Page Token",
305           description: "The query offset page token.",
306           type: "integer"
307         },
308         count: {
309           title: "Count",
310           description: "Set to true to return only the count of results for this query.",
311           type: "boolean"
312         }
313       }
314     }
315   };
316
317   if (!XM.ItemSiteRelation) { XM.ItemSiteRelation = {}; }
318
319   XM.ItemSiteRelation.isDispatchable = true;
320
321   /**
322     Returns item site relatinos using usual query means with additional special support for:
323       * Attributes `customer`,`shipto`, and `effectiveDate` for exclusive item rules.
324       * Attribute `vendor` to filter on only items with associated item sources.
325       * Cross check on `alias` and `barcode` attributes for item numbers.
326
327     @param {String} Record type. Must have `itemsite` or related view as its orm source table.
328     @param {Object} Additional query filter (Optional)
329     @returns {Array}
330   */
331   XM.ItemSiteRelation.fetch = function (query) {
332     return _fetch("XM.ItemSiteRelation", "xt.itemsiteinfo", query);
333   };
334
335 }());
336
337 $$ );
338