1 angular.module('egSerialsMod', ['egCoreMod'])
2 .factory('egSerialsCoreSvc',
3 ['egCore','orderByFilter','$q','$filter','$uibModal','ngToast','egConfirmDialog',
4 function(egCore , orderByFilter , $q , $filter , $uibModal , ngToast , egConfirmDialog) {
13 potentialPatternList : [],
41 d : ['year','month','day'],
42 e : ['year','month','day'],
46 i : ['year','month','day'],
47 j : ['year','month','day'],
48 k : ['year','month','day'],
50 q : ['year','season'],
52 t : ['year','month','day'],
53 w : ['year','month','day'],
54 x : ['year','month','day']
57 year : function(d) { return d.getFullYear() },
58 season: function(d) { return _loose_season(d) },
59 month : function(d) { return ('00' + (d.getMonth() + 1)).slice(-2) },
60 week : function(d) { return $filter('date')(d, 'ww') },
61 day : function(d) { return ('00'+d.getDate()).slice(-2) },
62 hour : function(d) { return ('00'+d.getHours()).slice(-2) }
77 angular.forEach(service.item_status_list, function(status) {
78 service.item_status_i18n.push({
80 label : egCore.strings.SERIALS_ITEM_STATUS[status]
84 function _loose_season(D) {
85 var m = D.getMonth() + 1;
89 (m == 1 || m == 2) || (m == 12 && d >= 21) || (m == 3 && d < 20)
91 return 24; /* MFHD winter */
93 (m == 4 || m == 5) || (m == 3 && d >= 20) || (m == 6 && d < 21)
95 return 21; /* spring */
97 (m == 7 || m == 8) || (m == 6 && d >= 21) || (m == 9 && d < 22)
99 return 22; /* summer */
101 return 23; /* autumn */
105 service.fetch_mfhds = function(bibId, contextOrg) {
106 // TODO filter by contextOrg
107 return egCore.pcrud.search('sre', {
114 'sre' : ['owning_lib']
118 ).then(function(list) {
119 service.bibId = bibId;
120 service.mfhdList = list;
121 update_flat_mfhd_list();
125 service.fetch_patterns_from_bibs_mfhds = function(bibId) {
126 return egCore.net.request(
128 'open-ils.serial.caption_and_pattern.find_legacy_by_bib_record.atomic',
131 ).then(function(list) {
132 service.potentialPatternList = egCore.idl.toTypedHash(list);
133 angular.forEach(service.potentialPatternList, function(pot) {
134 var rec = new MARC21.Record({ marcxml : pot.marc });
135 var pattern_fields = rec.fields.filter(function(f) {
136 return (f.tag == '853' || f.tag == '854' || f.tag == '855');
139 if (pattern_fields.length > 0) {
140 // just take the first one
141 var fld = pattern_fields[0];
142 pot.desc = fld.tag + ' ' + fld.ind1 + fld.ind2 +
143 fld.subfields.map(function(sf) {
144 return '$' + sf[0] + sf[1]
151 // fetch subscription, distributions, streams, captions,
152 // and notes associated with the indicated bib
153 service.fetch = function(bibId, contextOrg) {
155 var filter = { record_entry : bibId };
156 if (contextOrg) filter.owning_lib = egCore.org.descendants(contextOrg, true);
157 return egCore.pcrud.search('ssub', filter,
161 'ssub' : ['owning_lib','distributions', 'scaps', 'notes'],
162 'sdist' : [ 'record_entry','holding_lib',
163 'receive_call_number',
164 'receive_unit_template',
166 'bind_unit_template',
168 'sstr' : ['routing_list_users'],
170 'au' : ['card','home_ou','mailing_address','billing_address']
174 ).then(function(list) {
175 service.bibId = bibId;
176 service.subTree = list;
177 update_flat_sdist_sstr_list();
178 return $q.when(list);
182 // fetch subscription, distributions, streams, captions,
183 // and notes associated with the indicated bib
184 service.fetchLastCallnumber = function(contextOrg) {
185 return egCore.pcrud.search('acn', {
186 record : service.bibId,
187 owning_lib : contextOrg,
190 flesh_fields : {acn : ['prefix','suffix']},
191 order_by : [{class:'acn',field:'create_date',direction:'desc'}],
194 ).then(function(list) {
195 return $q.when(list[0]);
199 service.fetchItemsForSubPaged = function(subId,filter,offset,limit,sort) {
200 return service.fetchItemsForSub(
203 { limit : limit, offset : offset, paging : true },
208 // Creates an inverted tree from item to sub
209 service.fetchItemsForSub = function(subId,filter,options,sort) {
210 var deferred = $q.defer(); // side-effects only, otherwise the grid is wonky
212 if (!filter) filter = {};
213 if (!options) options = { limit : 100 }; // only used during full refresh
215 if (!subId && service.subId) subId = service.subId;
216 if (!subId) return $q.reject('fetchItemsForSub: no subscription id');
218 var sub = service.get_ssub(subId);
219 if (!sub) return $q.reject('fetchItemsForSub: unknown subscription id');
222 angular.forEach(sub.distributions(), function(dist) {
225 function (stream) { return stream.id() }
227 function (sid) { streams.push(sid) }
231 angular.extend(filter, {stream:streams});
232 angular.extend(options, {
233 order_by : [{class:'sitem',field:'date_expected'}], // best aprox of pub date
236 sitem : ['notes','issuance','editor','creator','unit','url']
240 angular.extend(options, {
246 'sitem', filter, options,
248 ).then(function(list) {
249 service.subId = subId;
250 if (!options.paging) { // not paged
251 service.itemTree = list;
252 service.itemMap = {};
254 angular.forEach(list, function (item) {
255 var exists = service.itemTree.filter(function (i) {
256 return i.id() == item.id()
258 if (!exists) service.itemTree.push(item);
262 // map items by stream for faster lookup
264 angular.forEach(list, function(item) {
265 if (!tmp[item.stream()]) tmp[item.stream()] = [];
266 tmp[item.stream()].push(item);
267 service.itemMap[item.id()] = item;
270 angular.forEach(sub.distributions(), function(dist) {
271 angular.forEach(dist.streams(), function(stream) {
272 angular.forEach(tmp[stream.id()], function (item) {
273 var routing_list = egCore.idl.Clone(stream.routing_list_users());
274 var st = egCore.idl.Clone(stream,1);
275 st.routing_list_users(routing_list);
276 var d = egCore.idl.Clone(dist,1);
277 var ss = egCore.idl.Clone(sub,1);
278 ss.distributions([]);
287 var hashList = egCore.idl.toHash(service.itemTree);
288 angular.forEach(hashList, function (item) {
289 item['issuance.date_published'] = item.issuance.date_published;
290 item['stream.distribution.holding_lib.name'] = item.stream.distribution.holding_lib.name;
295 service.itemList = hashList;
297 service.itemList = orderByFilter(hashList, ['"issuance.date_published"', '"stream.distribution.holding_lib.name"', '"id"']);
302 return deferred.promise;
305 service.prep_new_holding_code = function (args) {
307 var type = args.type;
308 var date = args.date;
309 var prev_iss = args.prev_iss;
310 var curr_iss = args.curr_iss;
313 var current_values = {};
315 var sub = service.get_ssub(service.subId);
316 if (!sub) return args;
319 if (prev_iss && prev_iss.holding_code()) { // we're predicting
320 var old_link_parts = JSON.parse(prev_iss.holding_code())[3].split('.');
321 var olink = old_link_parts[0];
322 var oseq = parseInt(old_link_parts[1]) + 1;
323 link = [olink,oseq].join('.');
325 if (prev_iss.holding_type())
326 type = prev_iss.holding_type();
328 if (prev_iss.caption_and_pattern()) {
329 var tmp = sub.scaps().filter(function (s) {
330 return (s.id() == prev_iss.caption_and_pattern());
332 if (angular.isArray(tmp) && tmp[0]) scap = tmp[0];
335 date = new Date(prev_iss.date_published());
336 } else if (curr_iss) { // we're editing
337 if (curr_iss.holding_type())
338 type = curr_iss.holding_type();
340 if (curr_iss.caption_and_pattern()) {
341 var tmp = sub.scaps().filter(function (s) {
342 return (s.id() == curr_iss.caption_and_pattern());
344 if (angular.isArray(tmp) && tmp[0]) scap = tmp[0];
346 if (!curr_iss.holding_code()) {
349 var tmp = JSON.parse(curr_iss.holding_code());
350 for (var i = 2; i < tmp.length; i += 2) {
351 // we're intentionally being a bit sloppy here, as
352 // the only subfields we are about in this context
353 // are the ones that are not repeatable
354 current_values[tmp[i]] = tmp[i + 1];
358 date = new Date(curr_iss.date_published());
360 // starting from scratch, so default the
361 // first publication date to the subscription start date
362 if (!date) date = new Date(sub.start_date());
368 var tmp = sub.scaps().filter(function (s) {
369 return (s.type() == type && s.active() == 't');
371 if (angular.isArray(tmp) && tmp[0]) scap = tmp[0];
374 if (!scap) return args;
376 var others = [], enums = [], chrons = [], freq = '';
377 var pat = JSON.parse(scap.pattern_code()).slice(4); // just the part we care about
379 var freq_index = pat.indexOf('w');
380 if (freq_index > -1) {
381 freq = pat[freq_index + 1];
384 date.getTime() + service.freq_offset[freq]
389 if (!date) date = new Date();
391 for (var i = 0; i < pat.length; i++) {
401 var chron_part = String(val).replace(/[)(]+/g,'');
402 if (sf in current_values) {
403 pat_part.value = current_values[sf];
406 pat_part.value = service.get_chron_part[chron_part](date);
413 if (sf.match(/[a-f]/)) {
414 enums.push(pat_part);
415 } else if (sf.match(/[i-l]/)) {
416 chrons.push(pat_part);
418 others.push(pat_part);
423 if (enums.length == 0 && chrons.length == 0) {
424 var parts = service.freq_chrons[freq];
426 angular.forEach(parts, function(p, ind) {
427 var sf = !ind ? 'i' : !--ind ? 'j' : 'k';
430 value : service.get_chron_part.year(date)
435 { subfield : 'i', value : service.get_chron_part.year(date) },
436 { subfield : 'j', value : service.get_chron_part.month(date) },
437 { subfield : 'k', value : service.get_chron_part.day(date) }
443 holding_code : ["4","1","8",link],
455 service.new_holding_code = function (options) {
456 if (options === undefined) options = {};
457 options.count = options.count || 1;
458 options.label = options.label || '';
460 return $uibModal.open({
461 templateUrl: './serials/t_holding_code_dialog',
463 //windowClass: 'eg-wide-modal',
466 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
467 $scope.focusMe = true;
468 $scope.title = options.title;
469 $scope.request_count = options.request_count;
470 $scope.count = options.count;
471 $scope.label = options.label;
472 $scope.save_label = options.save_label;
473 $scope.pubdate = options.date;
474 $scope.type = options.type || 'basic';
475 $scope.args = { adhoc : false };
476 if (options.adhoc) $scope.args.adhoc = true;
477 $scope.can_change_adhoc = options.can_change_adhoc;
479 function refresh (n,o) {
480 if (n && o && n !== o) {
481 $scope.args = service.prep_new_holding_code({
483 date : $scope.pubdate,
484 prev_iss : options.prev_iss,
485 curr_iss : options.curr_iss,
487 if (!options.can_change_adhoc && options.adhoc) $scope.args.adhoc = true;
489 if ($scope.args.type && $scope.type != $scope.args.type)
490 $scope.type = $scope.args.type;
491 if ($scope.args.date)
492 $scope.pubdate = $scope.args.date;
494 delete options.prev_iss; // only use this once
495 delete options.curr_iss; // only use this once
499 $scope.$watch('count',function (n) {options.count = n});
500 $scope.$watch('label',function (n) {options.label = n});
501 $scope.$watch('type',refresh);
502 $scope.$watch('pubdate',refresh);
504 $scope.ok = function(args) { $uibModalInstance.close(args) }
505 $scope.cancel = function () { $uibModalInstance.dismiss() }
507 refresh(1,2); // force data loading
509 }).result.then(function (args) {
510 if (args.enums && args.chrons) {
512 args.enums.concat(args.chrons),
514 args.holding_code.push(e.subfield);
515 args.holding_code.push(e.value);
519 args.count = options.count;
520 args.label = options.label;
521 return $q.when(args);
525 function update_flat_mfhd_list() {
527 angular.forEach(service.mfhdList, function(sre) {
528 var mfhdHash = egCore.idl.toHash(sre);
529 var rec = new MARC21.Record({ marcxml : mfhdHash.marc });
532 'owning_lib.name' : mfhdHash.owning_lib.name,
533 'owning_lib.id' : mfhdHash.owning_lib.id,
534 'marc' : rec.toBreaker(),
535 'marc_xml' : mfhdHash.marc,
537 'basic_holdings' : null,
538 'index_holdings' : null,
539 'supplement_holdings' : null
544 'open-ils.search.serial.record.mfhd.retrieve',
546 ).then(function(svr) {
547 _mfhd.svr = egCore.idl.toTypedHash(svr);
548 _mfhd.basic_holdings = _mfhd.svr.basic_holdings.join("; ");
549 _mfhd.index_holdings = _mfhd.svr.index_holdings.join("; ");
550 _mfhd.supplement_holdings = _mfhd.svr.supplement_holdings.join("; ");
553 service.flatMfhdList.length = 0;
554 angular.extend(service.flatMfhdList, list);
557 // create/update a flat version of the subscription/distribution/stream
558 // tree for feeding to the distribution and stream grid
559 function update_flat_sdist_sstr_list() {
561 // flatten the structure...
563 angular.forEach(service.subTree, function(ssub) {
564 var ssubHash = egCore.idl.toHash(ssub);
568 'owning_lib.name' : ssubHash.owning_lib.name,
569 'owning_lib.id' : ssubHash.owning_lib.id,
570 'start_date' : ssubHash.start_date,
571 'end_date' : ssubHash.end_date,
572 'expected_date_offset' : ssubHash.expected_date_offset
574 // insert and escape if we have no distributions
575 if (ssubHash.distributions.length == 0) {
580 angular.forEach(ssubHash.distributions, function(sdist) {
591 _sdist['sdist.' + fld] = sdist[fld];
593 _sdist['sdist.holding_lib.name'] = sdist.holding_lib.name;
594 _sdist['sdist.holding_lib.id'] = sdist.holding_lib.id;
595 _sdist['sdist.receive_call_number.label'] =
596 sdist.receive_call_number ? sdist.receive_call_number.label : null;
597 _sdist['sdist.receive_unit_template.name'] =
598 sdist.receive_unit_template ? sdist.receive_unit_template.name : null;
599 _sdist['sdist.bind_call_number.label'] =
600 sdist.bind_call_number ? sdist.bind_call_number.label : null;
601 _sdist['sdist.bind_unit_template.name'] =
602 sdist.bind_unit_template ? sdist.bind_unit_template.name : null;
603 // if we have no streams, add to the list and escape
604 if (sdist.streams.length == 0) {
606 angular.extend(row, _ssub, _sdist);
611 angular.forEach(sdist.streams, function(sstr) {
614 'sstr.routing_label' : sstr.routing_label,
615 'sstr.additional_routing' : ((sstr.routing_list_users.length > 0) ? true : false)
618 angular.extend(row, _ssub, _sdist, _sstr);
625 service.subList.length = 0;
626 angular.extend(service.subList,
627 orderByFilter(list, ['"owning_lib.name"', '"start_date"', '"end_date"',
628 '"holding_lib.name"', '"sdist.id"', '"sstr.id"'])
631 // ... then remove duplication of owning library, distribution library,
632 // and distribution labels
635 var dist_label = null;
637 angular.forEach(service.subList, function(row) {
638 row['index'] = index++;
639 if (sub_lib == row['owning_lib.name']) {
640 row['owning_lib.name'] = null;
642 sub_lib = row['owning_lib.name'];
643 dist_lib = row['sdist.holding_lib.name'];
644 dist_label = row['sdist.label'];
647 if (dist_lib == row['sdist.holding_lib.name']) {
648 row['sdist.holding_lib.name'] = null;
650 dist_lib = row['sdist.holding_lib.name'];
652 if (dist_label == row['sdist.label']) {
653 row['sdist.label'] = null;
655 dist_label = row['sdist.label'];
660 // verify that a subscription ID and bib ID are actually
661 // associated with each other
662 service.verify_subscription_id = function(bibId, ssubId) {
663 var deferred = $q.defer();
664 egCore.pcrud.search('ssub', {
665 record_entry : bibId,
667 }, {}, { atomic : true, idlist : true }
668 ).then(function(list) {
669 if (list.length == 1) {
670 deferred.resolve(true);
672 deferred.resolve(false);
675 return deferred.promise;
678 service.get_ssub = function(ssubId) {
680 for (var i = 0; i <= service.subTree.length; i++) {
681 if (service.subTree[i].id() == ssubId) {
682 return service.subTree[i];
687 service.fetch_spt = function() {
688 return egCore.net.request(
690 'open-ils.serial.pattern_template.retrieve.at.atomic',
692 egCore.auth.user().ws_ou()
693 ).then(function(list) {
694 service.sptList.length = 0;
695 angular.extend(service.sptList, list);
699 service.fetch_templates = function(org) {
700 return egCore.pcrud.search('act',
701 {owning_lib : egCore.org.fullPath(org, true)},
702 {order_by : { act : 'name' }}, {atomic : true}
706 service.print_routing_lists = function (bibId, items, check, force, print_rl) {
707 if (!check && !print_rl && !force) return $q.when();
709 return egCore.net.request(
711 'open-ils.search.biblio.record.mods_slim.retrieve',
713 ).then(function(mvr) {
715 var by_issuance = {};
716 angular.forEach(items, function (i) {
717 if (check && !i._print_routing_list) return;
718 if (!by_issuance[i.issuance().id()])
719 by_issuance[i.issuance().id()] = [];
720 by_issuance[i.issuance().id()].push(i);
723 var issuance_matrix = [];
724 angular.forEach(by_issuance, function (list) {
725 issuance_matrix.push(list);
728 var deferred = $q.defer();
729 var promise = deferred.promise;
731 angular.forEach(issuance_matrix, function(item_list, index) {
733 promise = promise.then(function(){
734 return $uibModal.open({
735 templateUrl: './serials/t_print_routing_list',
737 windowClass: 'eg-wide-modal',
740 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
742 var all_streams = [];
744 angular.forEach(item_list, function(i){
745 all_streams.push(i.stream());
746 all_users = all_users.concat(i.stream().routing_list_users());
750 show_print_button: true,
752 streams : all_streams,
754 issuance: item_list[0].issuance(),
755 users : orderByFilter(all_users, 'pos')
759 $scope.url = '/eg/serial/print_routing_list_users?ses=' + egCore.auth.token();
760 $scope.last = index == issuance_matrix.length - 1 ? true : false;
761 $scope.ok = function() { $uibModalInstance.close() }
768 return deferred.resolve();
773 service.set_item_status = function(newStatus, bibId, list, callback) {
774 if (!callback) callback = function () { return $q.when() }
775 if (!list.length) return $q.reject();
777 return egConfirmDialog.open(
778 egCore.strings.CONFIRM_CHANGE_ITEMS.status,
779 egCore.strings.CONFIRM_CHANGE_ITEMS_MESSAGE.status,
780 {items : list.length}
781 ).result.then(function () {
782 var promises = [$q.when()];
783 angular.forEach(list, function(item) {
784 item.status(newStatus);
788 'open-ils.serial.item.update',
791 ).then(function(res) {
796 $q.all(promises).then(function() {
802 service.process_items = function (mode, bibId, list, do_barcode, bind, print_rl, callback) {
803 if (!callback) callback = function () { return $q.when() }
804 if (!list.length) return $q.reject();
806 // deal with locations and circ mods for *NEW* units
807 var copy_locations = {};
810 // deal with barcodes and call numbers for *NEW* units
812 var call_numbers = {};
813 var call_numbers_by_siss_and_sdist = {};
815 var deferred = $q.defer();
816 var current_promise = deferred.promise;
819 var sitem_alerts = [];
820 var sdist_alerts = [];
821 var ssub_alerts = list[0].stream().distribution().subscription().notes().filter(function(n){
822 return n.alert() == 't';
826 angular.forEach(list, function(i) {
827 sitem_alerts = sitem_alerts.concat(
828 i.notes().filter(function(n){
829 return n.alert() == 't';
832 var sdist = '_'+i.stream().distribution().id();
833 if (!dist_seen[sdist]) {
834 dist_seen[sdist] = 1;
835 sdist_alerts = sdist_alerts.concat(
836 i.stream().distribution().notes().filter(function(n){
837 return n.alert() == 't';
843 if (do_barcode || bind) {
845 last_promise = current_promise.then(function(){ return $uibModal.open({
846 templateUrl: './serials/t_batch_receive',
848 windowClass: 'eg-wide-modal',
851 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
853 $scope.print_routing_lists = print_rl;
854 $scope.barcode_items = do_barcode;
855 $scope.force_bind = bind;
858 $scope.ssub_alerts = ssub_alerts;
859 $scope.sdist_alerts = sdist_alerts;
860 $scope.sitem_alerts = sitem_alerts;
861 $scope.acn_list = [];
862 $scope.acnp_labels = [];
863 $scope.acns_labels = [];
864 $scope.acpl_list = [];
866 $scope.cannot_print = function (index) {
867 return $scope.items[index].stream().routing_list_users().length == 0 || ($scope.bind && index > 0);
870 $scope.bind_or_none = function (index) {
871 return !$scope.barcode_items || ($scope.bind && index > 0);
874 $scope.focus_next_barcode = function (index) {
876 $('#item_barcode_'+index).focus().select();
879 $scope.fullCNLabel = function (cn) {
880 var label = [cn.prefix.label,cn.label,cn.suffix.label].join(' ');
884 $scope.apply_template_overrides = function (e) {
885 if ($scope.selected_call_number) {
886 angular.forEach($scope.items, function (i) {
887 i._call_number = $scope.selected_call_number.label;
888 i._cn_prefix = $scope.selected_call_number.prefix.label;
889 i._cn_suffix = $scope.selected_call_number.suffix.label;
892 if ($scope.selected_circ_mod) {
893 angular.forEach($scope.items, function (i) {
894 i._circ_mod = $scope.selected_circ_mod;
897 if ($scope.selected_copy_location) {
898 angular.forEach($scope.items, function (i) {
899 i._copy_location = $scope.selected_copy_location;
904 $scope.ok = function(items) { $uibModalInstance.close(items) }
905 $scope.cancel = function () { $uibModalInstance.dismiss() }
908 var pile_o_promises = [$q.when()];
910 // let's gather what we need...
911 angular.forEach(list, function (i, index) {
912 var dlib = i.stream().distribution().holding_lib().id();
913 dist_libs[dlib] = egCore.org.fullPath(dlib, true);
915 i._barcode = i.unit().barcode();
916 pile_o_promises.push(
917 egCore.pcrud.retrieve(
918 'acn', i.unit().call_number(),
919 {flesh : 1, flesh_fields : {acn : ['prefix','suffix']}}
921 if (cn.deleted() == 'f') {
922 i._call_number = cn.label();
923 i._cn_prefix = cn.prefix().label();
924 i._cn_suffix = cn.suffix().label();
929 if (i.stream().distribution()[mode + '_call_number']() &&
930 i.stream().distribution()[mode + '_call_number']().deleted() == 'f'
932 i._call_number = i.stream().distribution()[mode + '_call_number']().label();
934 pile_o_promises.push(
935 service.fetchLastCallnumber(
936 i.stream().distribution().holding_lib().id()
939 i._call_number = cn.label();
940 i._cn_prefix = cn.prefix().label();
941 i._cn_suffix = cn.suffix().label();
948 if (i.stream().distribution()[mode + '_unit_template']()) {
949 i._copy_location = i.stream().distribution()[mode + '_unit_template']().location();
950 i._circ_mod = i.stream().distribution()[mode + '_unit_template']().circ_modifier();
953 if ($scope.print_routing_lists && !$scope.cannot_print(index))
954 i._print_routing_list = true;
959 // build unique list of orgs from distribution.holding_lib fullPaths
960 var dist_lib_list = [];
961 angular.forEach(dist_libs, function (l) {
962 dist_lib_list = dist_lib_list.concat(l);
964 dist_lib_list = dist_lib_list.filter(function(v,i,s){
965 return s.indexOf(v) == i;
968 // Copy locations only come from the workstation location, same as XUL
969 pile_o_promises.push(egCore.pcrud.search(
971 {owning_lib : egCore.org.fullPath(egCore.auth.user().ws_ou(), true)},
973 ).then(function (list) {
974 $scope.acpl_list = list.map(function(i){return egCore.idl.toHash(i)});
978 // Call numbers, however, come from anywhere the distributions might live
979 pile_o_promises.push(egCore.pcrud.search(
981 {deleted : 'f', record : bibId, owning_lib : dist_lib_list},
982 {flesh : 1, flesh_fields : {acn : ['prefix','suffix']}},{ atomic : true }
983 ).then(function (list) {
984 $scope.acn_list = list.map(function(i){return egCore.idl.toHash(i)});
988 // Likewise for prefix and suffix, for combo box
989 angular.forEach(['acnp','acns'], function (cl) {
990 pile_o_promises.push(egCore.pcrud.search(
992 {owning_lib : dist_lib_list},
994 ).then(function (list) {
995 $scope[cl+'_labels'] = list.map(function(i){return i.label()});
1000 pile_o_promises.push(egCore.pcrud.retrieveAll(
1001 'ccm', {}, { atomic : true }
1002 ).then(function (list) {
1003 $scope.ccm_list = list.map(function(i){return egCore.idl.toHash(i)});
1007 $q.all(pile_o_promises).then(function() {
1008 console.log('receive data collected');
1011 $scope.$watch('barcode_items', function (n,o) {
1012 if (n === undefined || n == o) return;
1016 $scope.$watch('bind', function (n,o) {
1017 if (n === undefined || n == o) return;
1020 angular.forEach($scope.items, function (i,index) {
1021 if (index > 0) i._print_routing_list = false;
1026 $scope.$watch('auto_barcodes', function (n,o) {
1027 if (n === undefined || n == o) return;
1032 angular.forEach($scope.items, function (i) {
1033 if (!i.stream().distribution().receive_unit_template()) return;
1034 var _barcode = i._barcode;
1035 i._barcode = bc || i._old_barcode;
1036 i._old_barcode = _barcode;
1040 $scope.$watch('print_routing_lists', function (n,o) {
1041 if (n === undefined || n == o) return;
1043 angular.forEach($scope.items, function(i, index) {
1044 if (!$scope.cannot_print(index)) {
1045 i._print_routing_list = n;
1047 i._print_routing_list = false;
1054 last_promise = current_promise.then(function(){ return $uibModal.open({
1055 templateUrl: './serials/t_receive_alerts',
1057 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
1058 $scope.title = egCore.strings.CONFIRM_CHANGE_ITEMS[mode];
1059 $scope.items = list.length;
1062 $scope.ssub_alerts = ssub_alerts;
1063 $scope.sdist_alerts = sdist_alerts;
1064 $scope.sitem_alerts = sitem_alerts;
1066 $scope.ok = function(items) { $uibModalInstance.close(items) }
1067 $scope.cancel = function () { $uibModalInstance.dismiss() }
1071 angular.forEach(list, function (i, index) {
1074 return $q.when(list);
1079 last_promise.then(function (items) {
1082 if (mode == 'receive') {
1083 method = 'open-ils.serial.receive_items';
1084 items = items.filter(function(i){return i._receive});
1085 } else if ( mode == 'bind') {
1086 method = 'open-ils.serial.bind_items';
1087 items = items.filter(function(i){return i._receive});
1088 } else if ( mode == 'reset') {
1089 method = 'open-ils.serial.reset_items';
1092 if (!items.length) return $q.reject();
1094 var donor_unit_ids = {};
1095 angular.forEach(items, function(i, index) {
1096 if (i.unit()) donor_unit_ids[i.unit().id()] = 1;
1097 if (do_barcode) i.unit(-1);
1098 if (bind) i.unit(-2);
1099 copy_locations[i.id()] = i._copy_location;
1100 circ_mods[i.id()] = i._circ_mod;
1101 call_numbers[i.id()] = [i._cn_prefix, i._call_number, i._cn_suffix] || 'DEFAULT';
1102 barcodes[i.id()] = i._barcode || '@@AUTO';
1103 if (bind && index > 0) barcodes[i.id()] = items[0]._barcode;
1106 return egCore.net.request(
1107 'open-ils.serial', method,
1108 egCore.auth.token(), items, barcodes, call_numbers, donor_unit_ids,
1109 {circ_mods:circ_mods, copy_locations : copy_locations}
1112 var evt = egCore.evt.parse(resp);
1114 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
1116 ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
1117 return service.print_routing_lists(bibId, items, do_barcode || bind, false, print_rl)
1122 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
1127 return deferred.resolve();
1130 service.add_issuances = function (mySsubId) {
1131 if (!mySsubId && service.subId) mySsubId = service.subId;
1132 if (!mySsubId) return $q.reject('fetchItemsForSub: no subscription id');
1134 var sub = service.get_ssub(mySsubId);
1135 if (!sub) return $q.reject('fetchItemsForSub: unknown subscription id');
1138 angular.forEach(sub.distributions(), function(dist) {
1141 function (stream) { return stream.id() }
1143 function (sid) { streams.push(sid) }
1148 order_by : [{class:'sitem',field:'date_expected',direction:'desc'}], // best aprox of pub date
1151 flesh_fields : { sitem : ['issuance'] }
1154 return egCore.pcrud.search(
1155 'sitem', {stream:streams},
1156 { order_by : [{class:'sitem',field:'date_expected',direction:'desc'}], // best aprox of pub date
1159 flesh_fields : { sitem : ['issuance'] }
1162 ).then(function(list) {
1163 var lastItem = list[0];
1165 if (lastItem) lastItem = lastItem.issuance();
1167 return service.new_holding_code({
1168 title : egCore.strings.SERIALS_ISSUANCE_PREDICT,
1169 request_count : true,
1170 prev_iss : lastItem,
1172 }).then(function(hc) {
1176 base_iss = new egCore.idl.siss();
1177 base_iss.creator( egCore.auth.user().id() );
1178 base_iss.editor( egCore.auth.user().id() );
1179 base_iss.date_published( hc.date.toISOString() );
1180 base_iss.subscription( mySsubId );
1181 base_iss.caption_and_pattern( hc.scap );
1182 base_iss.holding_code( JSON.stringify(hc.holding_code) );
1183 base_iss.holding_type( hc.type );
1186 // if we're predicting without a preexisting holding, reduce the count
1187 if (!lastItem) hc.count--;
1189 return egCore.net.request(
1191 'open-ils.serial.make_predictions',
1192 egCore.auth.token(),
1193 { ssub_id : mySsubId,
1194 include_base_issuance : lastItem ? 0 : 1,
1195 num_to_predict : hc.count,
1196 base_issuance : base_iss || lastItem
1200 var evt = egCore.evt.parse(resp);
1202 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
1204 ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
1208 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);