LP#1350371 PO name on create w/ dupe detect
[working/Evergreen.git] / Open-ILS / web / js / ui / default / acq / financial / list_funds.js
1 dojo.require("dijit.Dialog");
2 dojo.require("dijit.form.FilteringSelect");
3 dojo.require('dijit.form.Button');
4 dojo.require('dijit.TooltipDialog');
5 dojo.require('dijit.form.DropDownButton');
6 dojo.require('dijit.form.CheckBox');
7 dojo.require('dojox.grid.DataGrid');
8 dojo.require('dojo.data.ItemFileWriteStore');
9 dojo.require('openils.widget.OrgUnitFilteringSelect');
10 dojo.require('openils.acq.CurrencyType');
11 dojo.require('openils.Event');
12 dojo.require('openils.Util');
13 dojo.require('openils.User');
14 dojo.require('openils.CGI');
15 dojo.require('openils.PermaCrud');
16 dojo.require('openils.widget.AutoGrid');
17 dojo.require('openils.widget.ProgressDialog');
18 dojo.require('fieldmapper.OrgUtils');
19 dojo.requireLocalization('openils.acq', 'acq');
20 var localeStrings = dojo.i18n.getLocalization('openils.acq', 'acq');
21
22 var contextOrg;
23 var rolloverResponses;
24 var rolloverMode = false;
25 var fundFleshFields = [
26     'spent_balance', 
27     'combined_balance', 
28     'spent_total', 
29     'encumbrance_total', 
30     'debit_total', 
31     'allocation_total'
32 ];
33
34 var adminPermOrgs = [];
35 var cachedFunds = [];
36
37 function initPage() {
38     contextOrg = openils.User.user.ws_ou();
39
40     /* Reveal controls for rollover without money if org units say ok.
41      * Actual ability to do the operation is controlled in the database, of
42      * course. */
43     var ouSettings = fieldmapper.aou.fetchOrgSettingBatch(
44         openils.User.user.ws_ou(), ["acq.fund.allow_rollover_without_money"]
45     );
46     if (
47         ouSettings["acq.fund.allow_rollover_without_money"] &&
48         ouSettings["acq.fund.allow_rollover_without_money"].value
49     ) {
50         dojo.query(".encumb_only").forEach(
51             function(o) { openils.Util.show(o, "table-row"); }
52         );
53     }
54
55     var connect = function() {
56         dojo.connect(contextOrgSelector, 'onChange',
57             function() {
58                 contextOrg = this.attr('value');
59                 dojo.byId('oils-acq-rollover-ctxt-org').innerHTML = 
60                     fieldmapper.aou.findOrgUnit(contextOrg).shortname();
61                 rolloverMode = false;
62                 gridDataLoader();
63             }
64         );
65     };
66
67     dojo.connect(refreshButton, 'onClick', 
68         function() { rolloverMode = false; gridDataLoader(); });
69
70     new openils.User().buildPermOrgSelector(
71         ['ADMIN_ACQ_FUND', 'VIEW_FUND'], 
72         contextOrgSelector, contextOrg, connect);
73
74     dojo.byId('oils-acq-rollover-ctxt-org').innerHTML = 
75         fieldmapper.aou.findOrgUnit(contextOrg).shortname();
76
77     loadYearSelector();
78     lfGrid.onItemReceived = function(item) {cachedFunds.push(item)};
79
80     new openils.User().getPermOrgList(
81         'ADMIN_ACQ_FUND',
82         function(list) {
83             adminPermOrgs = list;
84             loadFundGrid(
85                 new openils.CGI().param('year') 
86                     || new Date().getFullYear().toString());
87         },
88         true, true
89     );
90 }
91
92 function gridDataLoader() {
93     lfGrid.resetStore();
94     if(rolloverMode) {
95         var offset = lfGrid.displayOffset;
96         for(var i = offset; i < (offset + lfGrid.displayLimit - 1); i++) {
97             var fund = rolloverResponses[i];
98             if(!fund) break;
99             lfGrid.store.newItem(fieldmapper.acqf.toStoreItem(fund));
100         }
101     } else {
102         loadFundGrid();
103     }
104 }
105
106 function getBalanceInfo(rowIdx, item) {
107     if (!item) return '';
108     var fundId = this.grid.store.getValue(item, 'id');
109     var fund = cachedFunds.filter(function(f) { return f.id() == fundId })[0];
110     var cb = fund.combined_balance();
111     return cb ? cb.amount() : '0';
112 }
113
114 function loadFundGrid(year) {
115     openils.Util.hide('acq-fund-list-rollover-summary');
116     year = year || fundFilterYearSelect.attr('value');
117     cachedFunds = [];
118
119     var order_by = [{'class' : 'acqf', field : 'name'}];
120
121     if (adminPermOrgs.length) {
122         // sort funds I can edit to the front
123         order_by.unshift({   
124             'class' : 'acqf',
125             field : 'org',
126             compare : {'in' : adminPermOrgs},
127             direction : 'desc'
128         });
129     }
130
131     lfGrid.loadAll(
132         {   
133             flesh : 1,  
134             flesh_fields : {acqf : fundFleshFields},
135             order_by : order_by,
136         }, {   
137             year : year, 
138             org : fieldmapper.aou.descendantNodeList(contextOrg, true) 
139         } 
140     );
141 }
142
143 function loadYearSelector() {
144
145     fieldmapper.standardRequest(
146         ['open-ils.acq', 'open-ils.acq.fund.org.years.retrieve'],
147         {   async : true,
148             params : [openils.User.authtoken, {}, {limit_perm : 'VIEW_FUND'}],
149             oncomplete : function(r) {
150
151                 var yearList = openils.Util.readResponse(r);
152                 if(!yearList) return;
153                 yearList = yearList.map(function(year){return {year:year+''};}); // dojo wants strings
154
155                 var yearStore = {identifier:'year', name:'year', items:yearList};
156                 yearStore.items = yearStore.items.sort().reverse();
157                 fundFilterYearSelect.store = new dojo.data.ItemFileWriteStore({data:yearStore});
158
159                 // default to this year
160                 fundFilterYearSelect.setValue(new Date().getFullYear().toString());
161
162                 dojo.connect(
163                     fundFilterYearSelect, 
164                     'onChange', 
165                     function() { 
166                         rolloverMode = false;
167                         gridDataLoader();
168                     }
169                 );
170             }
171         }
172     );
173 }
174
175 function performRollover(args) {
176
177     rolloverMode = true;
178     progressDialog.show(true, "Processing...");
179     rolloverResponses = [];
180
181     var method = 'open-ils.acq.fiscal_rollover';
182
183     if(args.rollover[0] == 'on') {
184         method += '.combined';
185     } else {
186         method += '.propagate';
187     }
188         
189     var dryRun = args.dry_run[0] == 'on';
190     if(dryRun) method += '.dry_run';
191
192     var encumbOnly = args.encumb_only[0] == 'on';
193
194     var count = 0;
195     var amount_rolled = 0;
196     var year = fundFilterYearSelect.attr('value'); // TODO alternate selector?
197     
198     fieldmapper.standardRequest(
199         ['open-ils.acq', method],
200         {
201             async : true,
202
203             params : [
204                 openils.User.authtoken, 
205                 year,
206                 contextOrg,
207                 (args.child_orgs[0] == 'on'),
208                 { encumb_only : encumbOnly }
209             ],
210
211             onresponse : function(r) {
212                 var resp = openils.Util.readResponse(r);
213                 rolloverResponses.push(resp.fund);
214                 count += 1;
215                 amount_rolled += Number(resp.rollover_amount);
216             }, 
217
218             oncomplete : function() {
219                 
220                 var nextYear = Number(year) + 1;
221                 rolloverResponses = rolloverResponses.sort(
222                     function(a, b) {
223                         if(a.code() > b.code())
224                             return 1;
225                         return -1;
226                     }
227                 )
228
229                 // add the new, rolled funds to the cache.  Note that in dry-run 
230                 // mode, these are ephemeral and no longer exist on the server.
231                 cachedFunds = cachedFunds.concat(rolloverResponses);
232
233                 dojo.byId('acq-fund-list-rollover-summary-header').innerHTML = 
234                     dojo.string.substitute(
235                         localeStrings.FUND_LIST_ROLLOVER_SUMMARY,
236                         [nextYear]
237                     );
238
239                 dojo.byId('acq-fund-list-rollover-summary-funds').innerHTML = 
240                     dojo.string.substitute(
241                         localeStrings.FUND_LIST_ROLLOVER_SUMMARY_FUNDS,
242                         [nextYear, '<b>' + count + '</b>']
243                     );
244
245                 dojo.byId('acq-fund-list-rollover-summary-rollover-amount').innerHTML = 
246                     dojo.string.substitute(
247                         localeStrings.FUND_LIST_ROLLOVER_SUMMARY_ROLLOVER_AMOUNT,
248                         [nextYear, '<b>' + amount_rolled + '</b>']
249                     );
250
251                 if(!dryRun) {
252                     openils.Util.hide('acq-fund-list-rollover-summary-dry-run');
253                     
254                     // add the new year to the year selector if it's not already there
255                     fundFilterYearSelect.store.fetch({
256                         query : {year : ''+nextYear}, 
257                         onComplete:
258                             function(list) {
259                                 if(list && list.length > 0) return;
260                                 fundFilterYearSelect.store.newItem({year : nextYear});
261                             }
262                     });
263                 }
264
265                 openils.Util.show('acq-fund-list-rollover-summary');
266                 progressDialog.hide();
267                 gridDataLoader();
268             }
269         }
270     );
271 }
272
273 openils.Util.addOnLoad(initPage);