Allow propagation of encumbrances without funds
[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     var connect = function() {
41         dojo.connect(contextOrgSelector, 'onChange',
42             function() {
43                 contextOrg = this.attr('value');
44                 dojo.byId('oils-acq-rollover-ctxt-org').innerHTML = 
45                     fieldmapper.aou.findOrgUnit(contextOrg).shortname();
46                 rolloverMode = false;
47                 gridDataLoader();
48             }
49         );
50     };
51
52     dojo.connect(refreshButton, 'onClick', 
53         function() { rolloverMode = false; gridDataLoader(); });
54
55     new openils.User().buildPermOrgSelector(
56         ['ADMIN_ACQ_FUND', 'VIEW_FUND'], 
57         contextOrgSelector, contextOrg, connect);
58
59     dojo.byId('oils-acq-rollover-ctxt-org').innerHTML = 
60         fieldmapper.aou.findOrgUnit(contextOrg).shortname();
61
62     loadYearSelector();
63     lfGrid.onItemReceived = function(item) {cachedFunds.push(item)};
64
65     new openils.User().getPermOrgList(
66         'ADMIN_ACQ_FUND',
67         function(list) {
68             adminPermOrgs = list;
69             loadFundGrid(
70                 new openils.CGI().param('year') 
71                     || new Date().getFullYear().toString());
72         },
73         true, true
74     );
75 }
76
77 function gridDataLoader() {
78     lfGrid.resetStore();
79     if(rolloverMode) {
80         var offset = lfGrid.displayOffset;
81         for(var i = offset; i < (offset + lfGrid.displayLimit - 1); i++) {
82             var fund = rolloverResponses[i];
83             if(!fund) break;
84             lfGrid.store.newItem(fieldmapper.acqf.toStoreItem(fund));
85         }
86     } else {
87         loadFundGrid();
88     }
89 }
90
91 function getBalanceInfo(rowIdx, item) {
92     if (!item) return '';
93     var fundId = this.grid.store.getValue(item, 'id');
94     var fund = cachedFunds.filter(function(f) { return f.id() == fundId })[0];
95     var cb = fund.combined_balance();
96     return cb ? cb.amount() : '0';
97 }
98
99 function loadFundGrid(year) {
100     openils.Util.hide('acq-fund-list-rollover-summary');
101     year = year || fundFilterYearSelect.attr('value');
102     cachedFunds = [];
103
104     lfGrid.loadAll(
105         {
106             flesh : 1,  
107             flesh_fields : {acqf : fundFleshFields},
108             
109             // by default, sort funds I can edit to the front
110             order_by : [
111                 {   'class' : 'acqf',
112                     field : 'org',
113                     compare : {'in' : adminPermOrgs},
114                     direction : 'desc'
115                 },
116                 {   'class' : 'acqf',
117                     field : 'name'
118                 }
119             ]
120         }, {   
121             year : year, 
122             org : fieldmapper.aou.descendantNodeList(contextOrg, true) 
123         } 
124     );
125 }
126
127 function loadYearSelector() {
128
129     fieldmapper.standardRequest(
130         ['open-ils.acq', 'open-ils.acq.fund.org.years.retrieve'],
131         {   async : true,
132             params : [openils.User.authtoken, {}, {limit_perm : 'VIEW_FUND'}],
133             oncomplete : function(r) {
134
135                 var yearList = openils.Util.readResponse(r);
136                 if(!yearList) return;
137                 yearList = yearList.map(function(year){return {year:year+''};}); // dojo wants strings
138
139                 var yearStore = {identifier:'year', name:'year', items:yearList};
140                 yearStore.items = yearStore.items.sort().reverse();
141                 fundFilterYearSelect.store = new dojo.data.ItemFileWriteStore({data:yearStore});
142
143                 // default to this year
144                 fundFilterYearSelect.setValue(new Date().getFullYear().toString());
145
146                 dojo.connect(
147                     fundFilterYearSelect, 
148                     'onChange', 
149                     function() { 
150                         rolloverMode = false;
151                         gridDataLoader();
152                     }
153                 );
154             }
155         }
156     );
157 }
158
159 function performRollover(args) {
160
161     rolloverMode = true;
162     progressDialog.show(true, "Processing...");
163     rolloverResponses = [];
164
165     var method = 'open-ils.acq.fiscal_rollover';
166
167     if(args.rollover[0] == 'on') {
168         method += '.combined';
169     } else {
170         method += '.propagate';
171     }
172         
173     var dryRun = args.dry_run[0] == 'on';
174     if(dryRun) method += '.dry_run';
175
176     var encumbOnly = args.encumb_only[0] == 'on';
177
178     var count = 0;
179     var amount_rolled = 0;
180     var year = fundFilterYearSelect.attr('value'); // TODO alternate selector?
181     
182     fieldmapper.standardRequest(
183         ['open-ils.acq', method],
184         {
185             async : true,
186
187             params : [
188                 openils.User.authtoken, 
189                 year,
190                 contextOrg,
191                 (args.child_orgs[0] == 'on'),
192                 { encumb_only : encumbOnly }
193             ],
194
195             onresponse : function(r) {
196                 var resp = openils.Util.readResponse(r);
197                 rolloverResponses.push(resp.fund);
198                 count += 1;
199                 amount_rolled += Number(resp.rollover_amount);
200             }, 
201
202             oncomplete : function() {
203                 
204                 var nextYear = Number(year) + 1;
205                 rolloverResponses = rolloverResponses.sort(
206                     function(a, b) {
207                         if(a.code() > b.code())
208                             return 1;
209                         return -1;
210                     }
211                 )
212
213                 // add the new, rolled funds to the cache.  Note that in dry-run 
214                 // mode, these are ephemeral and no longer exist on the server.
215                 cachedFunds = cachedFunds.concat(rolloverResponses);
216
217                 dojo.byId('acq-fund-list-rollover-summary-header').innerHTML = 
218                     dojo.string.substitute(
219                         localeStrings.FUND_LIST_ROLLOVER_SUMMARY,
220                         [nextYear]
221                     );
222
223                 dojo.byId('acq-fund-list-rollover-summary-funds').innerHTML = 
224                     dojo.string.substitute(
225                         localeStrings.FUND_LIST_ROLLOVER_SUMMARY_FUNDS,
226                         [nextYear, count]
227                     );
228
229                 dojo.byId('acq-fund-list-rollover-summary-rollover-amount').innerHTML = 
230                     dojo.string.substitute(
231                         localeStrings.FUND_LIST_ROLLOVER_SUMMARY_ROLLOVER_AMOUNT,
232                         [nextYear, amount_rolled]
233                     );
234
235                 if(!dryRun) {
236                     openils.Util.hide('acq-fund-list-rollover-summary-dry-run');
237                     
238                     // add the new year to the year selector if it's not already there
239                     fundFilterYearSelect.store.fetch({
240                         query : {year : nextYear}, 
241                         onComplete:
242                             function(list) {
243                                 if(list && list.length > 0) return;
244                                 fundFilterYearSelect.store.newItem({year : nextYear});
245                             }
246                     });
247                 }
248
249                 openils.Util.show('acq-fund-list-rollover-summary');
250                 progressDialog.hide();
251                 gridDataLoader();
252             }
253         }
254     );
255 }
256
257 openils.Util.addOnLoad(initPage);