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 var pattern_changed = false;
320 if (prev_iss && prev_iss.holding_code()) { // we're predicting
321 var old_link_parts = JSON.parse(prev_iss.holding_code())[3].split('.');
322 var olink = old_link_parts[0];
323 var oseq = parseInt(old_link_parts[1]) + 1;
324 link = [olink,oseq].join('.');
326 if (prev_iss.holding_type())
327 type = prev_iss.holding_type();
329 if (prev_iss.caption_and_pattern()) {
330 var tmp = sub.scaps().filter(function (s) {
331 return (s.id() == prev_iss.caption_and_pattern() && s.active() == 't');
333 if (angular.isArray(tmp) && tmp[0]) {
336 // pattern associated with last issue must no longer be active
337 pattern_changed = true;
341 date = new Date(prev_iss.date_published());
342 } else if (curr_iss) { // we're editing
343 if (curr_iss.holding_type())
344 type = curr_iss.holding_type();
346 if (curr_iss.caption_and_pattern()) {
347 var tmp = sub.scaps().filter(function (s) {
348 return (s.id() == curr_iss.caption_and_pattern());
350 if (angular.isArray(tmp) && tmp[0]) scap = tmp[0];
352 if (!curr_iss.holding_code()) {
355 var tmp = JSON.parse(curr_iss.holding_code());
356 for (var i = 2; i < tmp.length; i += 2) {
357 // we're intentionally being a bit sloppy here, as
358 // the only subfields we are about in this context
359 // are the ones that are not repeatable
360 current_values[tmp[i]] = tmp[i + 1];
364 date = new Date(curr_iss.date_published());
366 // starting from scratch, so default the
367 // first publication date to the subscription start date
368 if (!date) date = new Date(sub.start_date());
374 var tmp = sub.scaps().filter(function (s) {
375 return (s.type() == type && s.active() == 't');
377 if (angular.isArray(tmp) && tmp[0]) scap = tmp[0];
380 if (!scap) return args;
382 var others = [], enums = [], chrons = [], freq = '';
383 var pat = JSON.parse(scap.pattern_code()).slice(4); // just the part we care about
385 var freq_index = pat.indexOf('w');
386 if (freq_index > -1) {
387 freq = pat[freq_index + 1];
388 if (prev_iss && !args.pattern_changed) {
390 date.getTime() + service.freq_offset[freq]
395 if (!date) date = new Date();
397 for (var i = 0; i < pat.length; i++) {
407 var chron_part = String(val).replace(/[)(]+/g,'');
408 if (sf in current_values) {
409 pat_part.value = current_values[sf];
412 pat_part.value = service.get_chron_part[chron_part](date);
419 if (sf.match(/[a-f]/)) {
420 enums.push(pat_part);
421 } else if (sf.match(/[i-l]/)) {
422 chrons.push(pat_part);
424 others.push(pat_part);
429 if (enums.length == 0 && chrons.length == 0) {
430 var parts = service.freq_chrons[freq];
432 angular.forEach(parts, function(p, ind) {
433 var sf = !ind ? 'i' : !--ind ? 'j' : 'k';
436 value : service.get_chron_part.year(date)
441 { subfield : 'i', value : service.get_chron_part.year(date) },
442 { subfield : 'j', value : service.get_chron_part.month(date) },
443 { subfield : 'k', value : service.get_chron_part.day(date) }
449 holding_code : ["4","1","8",link],
458 pattern_changed : pattern_changed
462 service.new_holding_code = function (options) {
463 if (options === undefined) options = {};
464 options.count = options.count || 1;
465 options.label = options.label || '';
467 return $uibModal.open({
468 templateUrl: './serials/t_holding_code_dialog',
470 //windowClass: 'eg-wide-modal',
473 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
474 $scope.focusMe = true;
475 $scope.title = options.title;
476 $scope.request_count = options.request_count;
477 $scope.count = options.count;
478 $scope.label = options.label;
479 $scope.save_label = options.save_label;
480 $scope.pubdate = options.date;
481 $scope.type = options.type || 'basic';
482 $scope.args = { adhoc : false };
483 if (options.adhoc) $scope.args.adhoc = true;
484 $scope.can_change_adhoc = options.can_change_adhoc;
486 function refresh (n,o) {
487 if (n && o && n !== o) {
488 $scope.args = service.prep_new_holding_code({
490 date : $scope.pubdate,
491 prev_iss : options.prev_iss,
492 curr_iss : options.curr_iss,
494 if (!options.can_change_adhoc && options.adhoc) $scope.args.adhoc = true;
496 if ($scope.args.type && $scope.type != $scope.args.type)
497 $scope.type = $scope.args.type;
498 if ($scope.args.date)
499 $scope.pubdate = $scope.args.date;
501 delete options.prev_iss; // only use this once
502 delete options.curr_iss; // only use this once
506 $scope.$watch('count',function (n) {options.count = n});
507 $scope.$watch('label',function (n) {options.label = n});
508 $scope.$watch('type',refresh);
509 $scope.$watch('pubdate',refresh);
511 $scope.ok = function(args) { $uibModalInstance.close(args) }
512 $scope.cancel = function () { $uibModalInstance.dismiss() }
514 refresh(1,2); // force data loading
516 }).result.then(function (args) {
517 if (args.enums && args.chrons) {
519 args.enums.concat(args.chrons),
521 args.holding_code.push(e.subfield);
522 args.holding_code.push(e.value);
526 args.count = options.count;
527 args.label = options.label;
528 return $q.when(args);
532 function update_flat_mfhd_list() {
534 angular.forEach(service.mfhdList, function(sre) {
535 var mfhdHash = egCore.idl.toHash(sre);
536 var rec = new MARC21.Record({ marcxml : mfhdHash.marc });
539 'owning_lib.name' : mfhdHash.owning_lib.name,
540 'owning_lib.id' : mfhdHash.owning_lib.id,
541 'marc' : rec.toBreaker(),
542 'marc_xml' : mfhdHash.marc,
544 'basic_holdings' : null,
545 'index_holdings' : null,
546 'supplement_holdings' : null
551 'open-ils.search.serial.record.mfhd.retrieve',
553 ).then(function(svr) {
554 _mfhd.svr = egCore.idl.toTypedHash(svr);
555 _mfhd.basic_holdings = _mfhd.svr.basic_holdings.join("; ");
556 _mfhd.index_holdings = _mfhd.svr.index_holdings.join("; ");
557 _mfhd.supplement_holdings = _mfhd.svr.supplement_holdings.join("; ");
560 service.flatMfhdList.length = 0;
561 angular.extend(service.flatMfhdList, list);
564 // create/update a flat version of the subscription/distribution/stream
565 // tree for feeding to the distribution and stream grid
566 function update_flat_sdist_sstr_list() {
568 // flatten the structure...
570 angular.forEach(service.subTree, function(ssub) {
571 var ssubHash = egCore.idl.toHash(ssub);
575 'owning_lib.name' : ssubHash.owning_lib.name,
576 'owning_lib.id' : ssubHash.owning_lib.id,
577 'start_date' : ssubHash.start_date,
578 'end_date' : ssubHash.end_date,
579 'expected_date_offset' : ssubHash.expected_date_offset
581 // insert and escape if we have no distributions
582 if (ssubHash.distributions.length == 0) {
587 angular.forEach(ssubHash.distributions, function(sdist) {
598 _sdist['sdist.' + fld] = sdist[fld];
600 _sdist['sdist.holding_lib.name'] = sdist.holding_lib.name;
601 _sdist['sdist.holding_lib.id'] = sdist.holding_lib.id;
602 _sdist['sdist.receive_call_number.label'] =
603 sdist.receive_call_number ? sdist.receive_call_number.label : null;
604 _sdist['sdist.receive_unit_template.name'] =
605 sdist.receive_unit_template ? sdist.receive_unit_template.name : null;
606 _sdist['sdist.bind_call_number.label'] =
607 sdist.bind_call_number ? sdist.bind_call_number.label : null;
608 _sdist['sdist.bind_unit_template.name'] =
609 sdist.bind_unit_template ? sdist.bind_unit_template.name : null;
610 // if we have no streams, add to the list and escape
611 if (sdist.streams.length == 0) {
613 angular.extend(row, _ssub, _sdist);
618 angular.forEach(sdist.streams, function(sstr) {
621 'sstr.routing_label' : sstr.routing_label,
622 'sstr.additional_routing' : ((sstr.routing_list_users.length > 0) ? true : false)
625 angular.extend(row, _ssub, _sdist, _sstr);
632 service.subList.length = 0;
633 angular.extend(service.subList,
634 orderByFilter(list, ['"owning_lib.name"', '"start_date"', '"end_date"',
635 '"holding_lib.name"', '"sdist.id"', '"sstr.id"'])
638 // ... then remove duplication of owning library, distribution library,
639 // and distribution labels
642 var dist_label = null;
644 angular.forEach(service.subList, function(row) {
645 row['index'] = index++;
646 if (sub_lib == row['owning_lib.name']) {
647 row['owning_lib.name'] = null;
649 sub_lib = row['owning_lib.name'];
650 dist_lib = row['sdist.holding_lib.name'];
651 dist_label = row['sdist.label'];
654 if (dist_lib == row['sdist.holding_lib.name']) {
655 row['sdist.holding_lib.name'] = null;
657 dist_lib = row['sdist.holding_lib.name'];
659 if (dist_label == row['sdist.label']) {
660 row['sdist.label'] = null;
662 dist_label = row['sdist.label'];
667 // verify that a subscription ID and bib ID are actually
668 // associated with each other
669 service.verify_subscription_id = function(bibId, ssubId) {
670 var deferred = $q.defer();
671 egCore.pcrud.search('ssub', {
672 record_entry : bibId,
674 }, {}, { atomic : true, idlist : true }
675 ).then(function(list) {
676 if (list.length == 1) {
677 deferred.resolve(true);
679 deferred.resolve(false);
682 return deferred.promise;
685 service.get_ssub = function(ssubId) {
687 for (var i = 0; i <= service.subTree.length; i++) {
688 if (service.subTree[i].id() == ssubId) {
689 return service.subTree[i];
694 service.fetch_spt = function() {
695 return egCore.net.request(
697 'open-ils.serial.pattern_template.retrieve.at.atomic',
699 egCore.auth.user().ws_ou()
700 ).then(function(list) {
701 service.sptList.length = 0;
702 angular.extend(service.sptList, list);
706 service.fetch_templates = function(org) {
707 return egCore.pcrud.search('act',
708 {owning_lib : egCore.org.fullPath(org, true)},
709 {order_by : { act : 'name' }}, {atomic : true}
713 service.print_routing_lists = function (bibId, items, check, force, print_rl) {
714 if (!check && !print_rl && !force) return $q.when();
716 return egCore.net.request(
718 'open-ils.search.biblio.record.mods_slim.retrieve',
720 ).then(function(mvr) {
722 var by_issuance = {};
723 angular.forEach(items, function (i) {
724 if (check && !i._print_routing_list) return;
725 if (!by_issuance[i.issuance().id()])
726 by_issuance[i.issuance().id()] = [];
727 by_issuance[i.issuance().id()].push(i);
730 var issuance_matrix = [];
731 angular.forEach(by_issuance, function (list) {
732 issuance_matrix.push(list);
735 var deferred = $q.defer();
736 var promise = deferred.promise;
738 angular.forEach(issuance_matrix, function(item_list, index) {
740 promise = promise.then(function(){
741 return $uibModal.open({
742 templateUrl: './serials/t_print_routing_list',
744 windowClass: 'eg-wide-modal',
747 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
749 var all_streams = [];
751 angular.forEach(item_list, function(i){
752 all_streams.push(i.stream());
753 all_users = all_users.concat(i.stream().routing_list_users());
757 show_print_button: true,
759 streams : all_streams,
761 issuance: item_list[0].issuance(),
762 users : orderByFilter(all_users, 'pos')
766 $scope.url = '/eg/serial/print_routing_list_users?ses=' + egCore.auth.token();
767 $scope.last = index == issuance_matrix.length - 1 ? true : false;
768 $scope.ok = function() { $uibModalInstance.close() }
775 return deferred.resolve();
780 service.set_item_status = function(newStatus, bibId, list, callback) {
781 if (!callback) callback = function () { return $q.when() }
782 if (!list.length) return $q.reject();
784 return egConfirmDialog.open(
785 egCore.strings.CONFIRM_CHANGE_ITEMS.status,
786 egCore.strings.CONFIRM_CHANGE_ITEMS_MESSAGE.status,
787 {items : list.length}
788 ).result.then(function () {
789 var promises = [$q.when()];
790 angular.forEach(list, function(item) {
791 item.status(newStatus);
795 'open-ils.serial.item.update',
798 ).then(function(res) {
803 $q.all(promises).then(function() {
809 service.process_items = function (mode, bibId, list, do_barcode, bind, print_rl, callback) {
810 if (!callback) callback = function () { return $q.when() }
811 if (!list.length) return $q.reject();
813 // deal with locations and circ mods for *NEW* units
814 var copy_locations = {};
817 // deal with barcodes and call numbers for *NEW* units
819 var call_numbers = {};
820 var call_numbers_by_siss_and_sdist = {};
822 var deferred = $q.defer();
823 var current_promise = deferred.promise;
826 var sitem_alerts = [];
827 var sdist_alerts = [];
828 var ssub_alerts = list[0].stream().distribution().subscription().notes().filter(function(n){
829 return n.alert() == 't';
833 angular.forEach(list, function(i) {
834 sitem_alerts = sitem_alerts.concat(
835 i.notes().filter(function(n){
836 return n.alert() == 't';
839 var sdist = '_'+i.stream().distribution().id();
840 if (!dist_seen[sdist]) {
841 dist_seen[sdist] = 1;
842 sdist_alerts = sdist_alerts.concat(
843 i.stream().distribution().notes().filter(function(n){
844 return n.alert() == 't';
850 if (do_barcode || bind) {
852 last_promise = current_promise.then(function(){ return $uibModal.open({
853 templateUrl: './serials/t_batch_receive',
855 windowClass: 'eg-wide-modal',
858 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
860 $scope.print_routing_lists = print_rl;
861 $scope.barcode_items = do_barcode;
862 $scope.force_bind = bind;
865 $scope.ssub_alerts = ssub_alerts;
866 $scope.sdist_alerts = sdist_alerts;
867 $scope.sitem_alerts = sitem_alerts;
868 $scope.acn_list = [];
869 $scope.acnp_labels = [];
870 $scope.acns_labels = [];
871 $scope.acpl_list = [];
873 $scope.cannot_print = function (index) {
874 return $scope.items[index].stream().routing_list_users().length == 0 || ($scope.bind && index > 0);
877 $scope.bind_or_none = function (index) {
878 return !$scope.barcode_items || ($scope.bind && index > 0);
881 $scope.focus_next_barcode = function (index) {
883 $('#item_barcode_'+index).focus().select();
886 $scope.fullCNLabel = function (cn) {
887 var label = [cn.prefix.label,cn.label,cn.suffix.label].join(' ');
891 $scope.apply_template_overrides = function (e) {
892 if ($scope.selected_call_number) {
893 angular.forEach($scope.items, function (i) {
894 i._call_number = $scope.selected_call_number.label;
895 i._cn_prefix = $scope.selected_call_number.prefix.label;
896 i._cn_suffix = $scope.selected_call_number.suffix.label;
899 if ($scope.selected_circ_mod) {
900 angular.forEach($scope.items, function (i) {
901 i._circ_mod = $scope.selected_circ_mod;
904 if ($scope.selected_copy_location) {
905 angular.forEach($scope.items, function (i) {
906 i._copy_location = $scope.selected_copy_location;
911 $scope.ok = function(items) { $uibModalInstance.close(items) }
912 $scope.cancel = function () { $uibModalInstance.dismiss() }
915 var pile_o_promises = [$q.when()];
917 // let's gather what we need...
918 angular.forEach(list, function (i, index) {
919 var dlib = i.stream().distribution().holding_lib().id();
920 dist_libs[dlib] = egCore.org.fullPath(dlib, true);
922 i._barcode = i.unit().barcode();
923 pile_o_promises.push(
924 egCore.pcrud.retrieve(
925 'acn', i.unit().call_number(),
926 {flesh : 1, flesh_fields : {acn : ['prefix','suffix']}}
928 if (cn.deleted() == 'f') {
929 i._call_number = cn.label();
930 i._cn_prefix = cn.prefix().label();
931 i._cn_suffix = cn.suffix().label();
936 if (i.stream().distribution()[mode + '_call_number']() &&
937 i.stream().distribution()[mode + '_call_number']().deleted() == 'f'
939 i._call_number = i.stream().distribution()[mode + '_call_number']().label();
941 pile_o_promises.push(
942 service.fetchLastCallnumber(
943 i.stream().distribution().holding_lib().id()
946 i._call_number = cn.label();
947 i._cn_prefix = cn.prefix().label();
948 i._cn_suffix = cn.suffix().label();
955 if (i.stream().distribution()[mode + '_unit_template']()) {
956 i._copy_location = i.stream().distribution()[mode + '_unit_template']().location();
957 i._circ_mod = i.stream().distribution()[mode + '_unit_template']().circ_modifier();
960 if ($scope.print_routing_lists && !$scope.cannot_print(index))
961 i._print_routing_list = true;
966 // build unique list of orgs from distribution.holding_lib fullPaths
967 var dist_lib_list = [];
968 angular.forEach(dist_libs, function (l) {
969 dist_lib_list = dist_lib_list.concat(l);
971 dist_lib_list = dist_lib_list.filter(function(v,i,s){
972 return s.indexOf(v) == i;
975 // Copy locations only come from the workstation location, same as XUL
976 pile_o_promises.push(egCore.pcrud.search(
978 {owning_lib : egCore.org.fullPath(egCore.auth.user().ws_ou(), true)},
980 ).then(function (list) {
981 $scope.acpl_list = list.map(function(i){return egCore.idl.toHash(i)});
985 // Call numbers, however, come from anywhere the distributions might live
986 pile_o_promises.push(egCore.pcrud.search(
988 {deleted : 'f', record : bibId, owning_lib : dist_lib_list},
989 {flesh : 1, flesh_fields : {acn : ['prefix','suffix']}},{ atomic : true }
990 ).then(function (list) {
991 $scope.acn_list = list.map(function(i){return egCore.idl.toHash(i)});
995 // Likewise for prefix and suffix, for combo box
996 angular.forEach(['acnp','acns'], function (cl) {
997 pile_o_promises.push(egCore.pcrud.search(
999 {owning_lib : dist_lib_list},
1000 {},{ atomic : true }
1001 ).then(function (list) {
1002 $scope[cl+'_labels'] = list.map(function(i){return i.label()});
1007 pile_o_promises.push(egCore.pcrud.retrieveAll(
1008 'ccm', {}, { atomic : true }
1009 ).then(function (list) {
1010 $scope.ccm_list = list.map(function(i){return egCore.idl.toHash(i)});
1014 $q.all(pile_o_promises).then(function() {
1015 console.log('receive data collected');
1018 $scope.$watch('barcode_items', function (n,o) {
1019 if (n === undefined || n == o) return;
1023 $scope.$watch('bind', function (n,o) {
1024 if (n === undefined || n == o) return;
1027 angular.forEach($scope.items, function (i,index) {
1028 if (index > 0) i._print_routing_list = false;
1033 $scope.$watch('auto_barcodes', function (n,o) {
1034 if (n === undefined || n == o) return;
1039 angular.forEach($scope.items, function (i) {
1040 if (!i.stream().distribution().receive_unit_template()) return;
1041 var _barcode = i._barcode;
1042 i._barcode = bc || i._old_barcode;
1043 i._old_barcode = _barcode;
1047 $scope.$watch('print_routing_lists', function (n,o) {
1048 if (n === undefined || n == o) return;
1050 angular.forEach($scope.items, function(i, index) {
1051 if (!$scope.cannot_print(index)) {
1052 i._print_routing_list = n;
1054 i._print_routing_list = false;
1061 last_promise = current_promise.then(function(){ return $uibModal.open({
1062 templateUrl: './serials/t_receive_alerts',
1065 ['$scope', '$uibModalInstance', function($scope, $uibModalInstance) {
1066 $scope.title = egCore.strings.CONFIRM_CHANGE_ITEMS[mode];
1067 $scope.items = list.length;
1070 $scope.ssub_alerts = ssub_alerts;
1071 $scope.sdist_alerts = sdist_alerts;
1072 $scope.sitem_alerts = sitem_alerts;
1074 $scope.ok = function(items) { $uibModalInstance.close(items) }
1075 $scope.cancel = function () { $uibModalInstance.dismiss() }
1079 angular.forEach(list, function (i, index) {
1082 return $q.when(list);
1087 last_promise.then(function (items) {
1090 if (mode == 'receive') {
1091 method = 'open-ils.serial.receive_items';
1092 items = items.filter(function(i){return i._receive});
1093 } else if ( mode == 'bind') {
1094 method = 'open-ils.serial.bind_items';
1095 items = items.filter(function(i){return i._receive});
1096 } else if ( mode == 'reset') {
1097 method = 'open-ils.serial.reset_items';
1100 if (!items.length) return $q.reject();
1102 var donor_unit_ids = {};
1103 angular.forEach(items, function(i, index) {
1104 if (i.unit()) donor_unit_ids[i.unit().id()] = 1;
1105 if (do_barcode) i.unit(-1);
1106 if (bind) i.unit(-2);
1107 copy_locations[i.id()] = i._copy_location;
1108 circ_mods[i.id()] = i._circ_mod;
1109 call_numbers[i.id()] = [i._cn_prefix, i._call_number, i._cn_suffix] || 'DEFAULT';
1110 barcodes[i.id()] = i._barcode || '@@AUTO';
1111 if (bind && index > 0) barcodes[i.id()] = items[0]._barcode;
1114 return egCore.net.request(
1115 'open-ils.serial', method,
1116 egCore.auth.token(), items, barcodes, call_numbers, donor_unit_ids,
1117 {circ_mods:circ_mods, copy_locations : copy_locations}
1120 var evt = egCore.evt.parse(resp);
1122 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
1124 ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
1125 return service.print_routing_lists(bibId, items, do_barcode || bind, false, print_rl)
1130 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
1135 return deferred.resolve();
1138 service.add_issuances = function (mySsubId) {
1139 if (!mySsubId && service.subId) mySsubId = service.subId;
1140 if (!mySsubId) return $q.reject('fetchItemsForSub: no subscription id');
1142 var sub = service.get_ssub(mySsubId);
1143 if (!sub) return $q.reject('fetchItemsForSub: unknown subscription id');
1146 angular.forEach(sub.distributions(), function(dist) {
1149 function (stream) { return stream.id() }
1151 function (sid) { streams.push(sid) }
1156 order_by : [{class:'sitem',field:'date_expected',direction:'desc'}], // best aprox of pub date
1159 flesh_fields : { sitem : ['issuance'] }
1162 return egCore.pcrud.search(
1163 'sitem', {stream:streams},
1164 { order_by : [{class:'sitem',field:'date_expected',direction:'desc'}], // best aprox of pub date
1167 flesh_fields : { sitem : ['issuance'] }
1170 ).then(function(list) {
1171 var lastItem = list[0];
1173 if (lastItem) lastItem = lastItem.issuance();
1175 return service.new_holding_code({
1176 title : egCore.strings.SERIALS_ISSUANCE_PREDICT,
1177 request_count : true,
1178 prev_iss : lastItem,
1180 }).then(function(hc) {
1183 var include_base_iss = 0;
1184 if (!lastItem || hc.pattern_changed) {
1185 include_base_iss = 1;
1186 base_iss = new egCore.idl.siss();
1187 base_iss.creator( egCore.auth.user().id() );
1188 base_iss.editor( egCore.auth.user().id() );
1189 base_iss.date_published( hc.date.toISOString() );
1190 base_iss.subscription( mySsubId );
1191 base_iss.caption_and_pattern( hc.scap );
1192 base_iss.holding_code( JSON.stringify(hc.holding_code) );
1193 base_iss.holding_type( hc.type );
1196 // if we're predicting without a preexisting holding, reduce the count
1197 if (!lastItem) hc.count--;
1199 return egCore.net.request(
1201 'open-ils.serial.make_predictions',
1202 egCore.auth.token(),
1203 { ssub_id : mySsubId,
1204 include_base_issuance : include_base_iss,
1205 num_to_predict : hc.count,
1206 base_issuance : base_iss || lastItem
1210 var evt = egCore.evt.parse(resp);
1212 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);
1214 ngToast.success(egCore.strings.SERIALS_ISSUANCE_SUCCESS_SAVE);
1218 ngToast.danger(egCore.strings.SERIALS_ISSUANCE_FAIL_SAVE);