1 package OpenILS::Application::Acq::Lineitem;
2 use base qw/OpenILS::Application/;
3 use strict; use warnings;
6 use OpenSRF::Utils::Logger qw(:logger);
7 use OpenILS::Utils::Fieldmapper;
8 use OpenILS::Utils::CStoreEditor q/:funcs/;
9 use OpenILS::Const qw/:const/;
10 use OpenSRF::Utils::SettingsClient;
11 use OpenILS::Application::AppUtils;
12 use OpenILS::Application::Acq::Financials;
13 use OpenILS::Application::Cat::BibCommon;
14 use OpenILS::Application::Cat::AssetCommon;
15 use OpenILS::Application::Acq::Lineitem::BatchUpdate;
16 my $U = 'OpenILS::Application::AppUtils';
19 __PACKAGE__->register_method(
20 method => 'create_lineitem',
21 api_name => 'open-ils.acq.lineitem.create',
23 desc => 'Creates a lineitem',
25 {desc => 'Authentication token', type => 'string'},
26 {desc => 'The lineitem object to create', type => 'object'},
28 return => {desc => 'ID of newly created lineitem on success, Event on error'}
33 my($self, $conn, $auth, $li) = @_;
34 my $e = new_editor(xact=>1, authtoken=>$auth);
35 return $e->die_event unless $e->checkauth;
39 my $picklist = $e->retrieve_acq_picklist($li->picklist)
40 or return $e->die_event;
42 if($picklist->owner != $e->requestor->id) {
43 return $e->die_event unless
44 $e->allowed('CREATE_PICKLIST', $picklist->org_unit, $picklist);
47 # indicate the picklist was updated
48 $picklist->edit_time('now');
49 $picklist->editor($e->requestor->id);
50 $e->update_acq_picklist($picklist) or return $e->die_event;
54 if($li->purchase_order) {
55 $po = $e->retrieve_acq_purchase_order([
57 {flesh => 1, flesh_fields => {acqpo => ['provider']}}
58 ]) or return $e->die_event;
59 return $e->die_event unless
60 $e->allowed('MANAGE_PROVIDER', $po->ordering_agency, $po);
62 $li->provider($po->provider) unless defined $li->provider;
65 $li->selector($e->requestor->id);
66 $li = $e->create_acq_lineitem($li) or return $e->die_event;
68 # if no price is set, see if it can be extracted from the price attribute.
69 if (not defined $li->estimated_unit_price) { # '0' is valid
70 my $evt = set_li_price_from_attr($e, $li);
75 # apply the default number of copies for this provider
76 for (1 .. $po->provider->default_copy_count) {
77 my $lid = Fieldmapper::acq::lineitem_detail->new;
78 $lid->lineitem($li->id);
79 $lid->owning_lib($e->requestor->ws_ou);
80 $e->create_acq_lineitem_detail($lid) or return $e->die_event;
88 # See if we have a value for the price attribute. If so, apply the price
89 # value to the lineitem.
90 # Returns undef on success, Event on error.
91 sub set_li_price_from_attr {
94 my $attr = $e->search_acq_lineitem_attr({
96 attr_type => 'lineitem_marc_attr_definition',
102 my $val = $attr->attr_value;
104 return unless defined $val; # '0' is valid
106 $li->estimated_unit_price($val);
108 if (!$e->update_acq_lineitem($li)) {
110 return OpenILS::Event->new('BAD_PARAMS',
111 desc => "Invalid lineitem price value: '$val'") ;
118 __PACKAGE__->register_method(
119 method => 'retrieve_lineitem',
120 api_name => 'open-ils.acq.lineitem.retrieve',
123 desc => 'Retrieves a lineitem',
125 {desc => 'Authentication token', type => 'string'},
126 {desc => 'lineitem ID to retrieve', type => 'number'},
127 {options => q/Hash of options, including:
128 flesh_attrs : for attributes,
129 flesh_notes : for notes,
130 flesh_cancel_reason : for cancel reason,
131 flesh_li_details : for order details objects,
132 clear_marc : to clear marcxml from lineitem/, type => 'hash'},
134 return => {desc => 'lineitem object on success, Event on error'}
139 sub retrieve_lineitem {
140 my($self, $conn, $auth, $li_id, $options) = @_;
141 my $e = new_editor(authtoken=>$auth);
142 return $e->die_event unless $e->checkauth;
143 return retrieve_lineitem_impl($e, $li_id, $options);
146 sub retrieve_lineitem_impl {
147 my ($e, $li_id, $options, $no_auth) = @_; # no_auth needed for EDI scripts
153 jub => ['purchase_order', 'picklist'], # needed for permission check
159 my $fields = $flesh->{flesh_fields};
161 push(@{$fields->{jub} }, 'attributes') if $$options{flesh_attrs};
162 push(@{$fields->{jub} },'lineitem_notes') if $$options{flesh_notes};
163 push(@{$fields->{acqlin}}, 'alert_text') if $$options{flesh_notes};
164 push(@{$fields->{jub} }, 'order_summary') if $$options{flesh_order_summary};
165 push(@{$fields->{jub} }, 'cancel_reason') if $$options{flesh_cancel_reason};
167 if($$options{flesh_li_details}) {
168 push(@{$fields->{jub} }, 'lineitem_details');
169 push(@{$fields->{acqlid}}, 'fund' ) if $$options{flesh_fund};
170 push(@{$fields->{acqlid}}, 'fund_debit' ) if $$options{flesh_fund_debit};
171 push(@{$fields->{acqlid}}, 'cancel_reason') if $$options{flesh_cancel_reason};
174 if($$options{clear_marc}) { # avoid fetching marc blob
175 my @fields = grep { $_ ne 'marc' } Fieldmapper::acq::lineitem->new->real_fields;
176 $flesh->{select} = {jub => [@fields]};
179 my $li = $e->retrieve_acq_lineitem([$li_id, $flesh]) or return $e->event;
181 # collect the # of lids
182 if($$options{flesh_li_details}) {
183 $li->item_count(scalar(@{$li->lineitem_details}));
185 my $details = $e->search_acq_lineitem_detail({lineitem => $li_id}, {idlist=>1});
186 $li->item_count(scalar(@$details));
189 # attach claims to LIDs
190 if($$options{flesh_li_details}) {
191 foreach (@{$li->lineitem_details}) {
193 $e->search_acq_claim([
194 {"lineitem_detail", $_->id}, {
195 "flesh" => 1, "flesh_fields" => {"acqcl" => ["type"]}
202 return $e->event unless ((
203 $li->purchase_order and
204 ($no_auth or $e->allowed(['VIEW_PURCHASE_ORDER', 'CREATE_PURCHASE_ORDER'],
205 $li->purchase_order->ordering_agency, $li->purchase_order))
207 $li->picklist and !$li->purchase_order and # user doesn't have view_po perms
208 ($no_auth or $e->allowed(['VIEW_PICKLIST', 'CREATE_PICKLIST'],
209 $li->picklist->org_unit, $li->picklist))
212 unless ($$options{flesh_po}) {
214 $li->purchase_order ? $li->purchase_order->id : undef
217 unless ($$options{flesh_pl}) {
218 $li->picklist($li->picklist ? $li->picklist->id : undef);
225 __PACKAGE__->register_method(
226 method => 'delete_lineitem',
227 api_name => 'open-ils.acq.lineitem.delete',
229 desc => 'Deletes a lineitem',
231 {desc => 'Authentication token', type => 'string'},
232 {desc => 'lineitem ID to delete', type => 'number'},
234 return => {desc => '1 on success, Event on error'}
238 __PACKAGE__->register_method(
239 method => 'delete_lineitem',
240 api_name => 'open-ils.acq.purchase_order.lineitem.delete',
242 desc => 'Deletes a lineitem from a purchase order',
244 {desc => 'Authentication token', type => 'string'},
245 {desc => 'lineitem ID to delete', type => 'number'},
247 return => {desc => '1 on success, Event on error'}
251 __PACKAGE__->register_method(
252 method => 'delete_lineitem',
253 api_name => 'open-ils.acq.picklist.lineitem.delete',
255 desc => 'Deletes a lineitem from a picklist',
257 {desc => 'Authentication token', type => 'string'},
258 {desc => 'lineitem ID to delete', type => 'number'},
260 return => {desc => '1 on success, Event on error'}
264 sub delete_lineitem {
265 my($self, $conn, $auth, $li_id) = @_;
266 my $e = new_editor(xact=>1, authtoken=>$auth);
267 return $e->die_event unless $e->checkauth;
269 my $li = $e->retrieve_acq_lineitem($li_id)
270 or return $e->die_event;
275 my $picklist = $e->retrieve_acq_picklist($li->picklist)
276 or return $e->die_event;
277 return OpenILS::Event->new('BAD_PARAMS')
278 if $picklist->owner != $e->requestor->id;
283 # once a LI is attached to a PO, deleting it
284 # from a picklist means *detaching* it from the picklist
285 if ($self->api_name =~ /picklist/ && $li->purchase_order) {
287 my $evt = update_lineitem_impl($e, $li);
293 # delete the attached lineitem_details
294 my $lid_ids = $e->search_acq_lineitem_detail(
295 {lineitem => $li_id}, {idlist=>1});
297 for my $lid_id (@$lid_ids) {
298 $e->delete_acq_lineitem_detail(
299 $e->retrieve_acq_lineitem_detail($lid_id))
300 or return $e->die_event;
303 $e->delete_acq_lineitem($li) or return $e->die_event;
309 __PACKAGE__->register_method(
310 method => 'update_lineitem',
311 api_name => 'open-ils.acq.lineitem.update',
313 desc => 'Update one or many lineitems',
315 {desc => 'Authentication token', type => 'string'},
316 {desc => 'lineitem object update', type => 'object'}
318 return => {desc => '1 on success, Event on error'}
322 sub update_lineitem {
323 my($self, $conn, $auth, $li) = @_;
324 my $e = new_editor(xact=>1, authtoken=>$auth);
325 return $e->die_event unless $e->checkauth;
327 $li = [$li] unless ref $li eq "ARRAY";
329 my $evt = update_lineitem_impl($e, $_);
337 sub update_lineitem_impl {
340 my $orig_li = $e->retrieve_acq_lineitem([
342 { flesh => 1, # grab the lineitem with picklist attached
343 flesh_fields => {jub => ['picklist', 'purchase_order']}
345 ]) or return $e->die_event;
347 # the marc may have been cleared on retrieval...
348 $li->marc($orig_li->marc) unless $li->marc;
350 $li->editor($e->requestor->id);
351 $li->edit_time('now');
352 $e->update_acq_lineitem($li) or return $e->die_event;
356 __PACKAGE__->register_method(
357 method => 'lineitem_search',
358 api_name => 'open-ils.acq.lineitem.search',
361 desc => 'Searches lineitems',
363 {desc => 'Authentication token', type => 'string'},
364 {desc => 'Search definition', type => 'object'},
365 {desc => 'Options hash. idlist=true', type => 'object'},
366 {desc => 'List of lineitems', type => 'object/number'},
371 sub lineitem_search {
372 my($self, $conn, $auth, $search, $options) = @_;
373 my $e = new_editor(authtoken=>$auth);
374 return $e->event unless $e->checkauth;
375 return $e->event unless $e->allowed('CREATE_PICKLIST');
376 # XXX needs permissions consideration
377 my $lis = $e->search_acq_lineitem($search, {idlist=>1});
378 for my $li_id (@$lis) {
379 if($$options{idlist}) {
380 $conn->respond($li_id);
382 my $res = retrieve_lineitem($self, $conn, $auth, $li_id, $options);
383 $conn->respond($res) unless $U->event_code($res);
389 __PACKAGE__->register_method (
390 method => 'lineitems_related_by_bib',
391 api_name => 'open-ils.acq.lineitems_for_bib.by_bib_id',
394 Retrieves lineitems attached to same bib record, subject to the PO ordering agency. This variant takes the bib id.
395 @param authtoken Login session key
396 @param bib_id Id for the pertinent bib record.
397 @param options Object for tweaking the selection criteria and fleshing options.
401 __PACKAGE__->register_method (
402 method => 'lineitems_related_by_bib',
403 api_name => 'open-ils.acq.lineitems_for_bib.by_lineitem_id',
406 Retrieves lineitems attached to same bib record, subject to the PO ordering agency. This variant takes the id for any of the pertinent lineitems.
407 @param authtoken Login session key
408 @param bib_id Id for a pertinent lineitem.
409 @param options Object for tweaking the selection criteria and fleshing options.
413 __PACKAGE__->register_method (
414 method => 'lineitems_related_by_bib',
415 api_name => 'open-ils.acq.lineitems_for_bib.by_lineitem_id.count',
417 signature => q/See open-ils.acq.lineitems_for_bib.by_lineitem_id. This version returns numbers of lineitems only (XXX may count lineitems we don't actually have permission to retrieve)/
420 sub lineitems_related_by_bib {
421 my($self, $conn, $auth, $test_value, $options) = @_;
422 my $e = new_editor(authtoken => $auth);
423 return $e->event unless $e->checkauth;
425 my $perm_orgs = $U->user_has_work_perm_at($e, 'VIEW_PURCHASE_ORDER', {descendants =>1}, $e->requestor->id);
428 "select"=>{"jub"=>["id"]},
429 "from"=>{"jub" => {"acqpo" => {type => 'left'}, "acqpl" => {type => 'left'}}},
432 { "+acqpo"=>{ "ordering_agency" => $perm_orgs } },
433 { '+acqpl' => { org_unit => $perm_orgs } }
436 "order_by"=>[{"class"=>"jub", "field"=>"create_time", "direction"=>"desc"}]
439 # Be sure we just return the original LI if no related bibs
440 if ($self->api_name =~ /by_lineitem_id/) {
441 my $orig = retrieve_lineitem($self, $conn, $auth, $test_value) or
442 return $e->die_event;
443 if ($test_value = $orig->eg_bib_id) {
444 $query->{"where"}->{"eg_bib_id"} = $test_value;
446 $query->{"where"}->{"id"} = $orig->id;
448 } elsif ($test_value) {
449 $query->{"where"}->{"eg_bib_id"} = $test_value;
452 return new OpenILS::Event("BAD_PARAMS", "Null bib id");
455 if ($options && defined $options->{lineitem_state}) {
456 $query->{'where'}{'jub'}{'state'} = $options->{lineitem_state};
459 if ($options && defined $options->{po_state}) {
460 $query->{'where'}{'+acqpo'}{'state'} = $options->{po_state};
463 if ($options && defined $options->{order_by}) {
464 $query->{'order_by'} = $options->{order_by};
467 my $results = $e->json_query($query);
468 if ($self->api_name =~ /count$/) {
469 return scalar(@$results);
471 for my $result (@$results) {
472 # retrieve_lineitem takes care of POs and PLs and also handles
473 # options like flesh_notes and permissions checking.
475 retrieve_lineitem($self, $conn, $auth, $result->{"id"}, $options)
484 __PACKAGE__->register_method(
485 method => "lineitem_search_by_attributes",
486 api_name => "open-ils.acq.lineitem.search.by_attributes",
489 desc => "Performs a search against lineitem_attrs",
491 {desc => "Authentication token", type => "string"},
494 attr_value_pairs : list of pairs of (attr definition ID, attr value) where value can be scalar (fuzzy match) or array (exact match)
495 li_states : list of lineitem states
496 po_agencies : list of purchase order ordering agencies (org) ids
498 At least one of these search terms is required.
503 idlist : if set, only return lineitem IDs
504 clear_marc : if set, strip the MARC xml from the lineitem before delivery
505 flesh_attrs : flesh lineitem attributes;
512 __PACKAGE__->register_method(
513 method => "lineitem_search_by_attributes",
514 api_name => "open-ils.acq.lineitem.search.by_attributes.ident",
517 desc => "Performs a search against lineitem_attrs where ident is true. ".
518 "See open-ils.acq.lineitem.search.by_attributes for params."
522 sub lineitem_search_by_attributes {
523 my ($self, $conn, $auth, $search, $options) = @_;
525 my $e = new_editor(authtoken => $auth, xact => 1);
526 return $e->die_event unless $e->checkauth;
527 # XXX needs permissions consideration
529 return [] unless $search;
530 my $attr_value_pairs = $search->{attr_value_pairs};
531 my $li_states = $search->{li_states};
532 my $po_agencies = $search->{po_agencies}; # XXX if none, base it on perms
535 "select" => {"acqlia" =>
536 [{"column" => "lineitem", "transform" => "distinct"}]
540 "acqliad" => {"field" => "id", "fkey" => "definition"},
543 "fkey" => "lineitem",
548 "fkey" => "purchase_order"
557 $where->{"+acqliad"} = {"ident" => "t"}
558 if $self->api_name =~ /\.ident/;
560 my $searched_for_something = 0;
562 if (ref $attr_value_pairs eq "ARRAY") {
563 $where->{"-or"} = [];
564 foreach (@$attr_value_pairs) {
566 my ($def, $value) = @$_;
567 push @{$where->{"-or"}}, {
569 "attr_value" => (ref $value) ?
570 $value : {"ilike" => "%" . $value . "%"},
575 $searched_for_something = 1;
578 if ($li_states and @$li_states) {
579 $where->{"+jub"} = {"state" => $li_states};
580 $searched_for_something = 1;
583 if ($po_agencies and @$po_agencies) {
584 $where->{"+acqpo"} = {"ordering_agency" => $po_agencies};
585 $searched_for_something = 1;
588 if (not $searched_for_something) {
590 return new OpenILS::Event(
591 "BAD_PARAMS", note => "You have provided no search terms."
595 $query->{"where"} = $where;
596 my $lis = $e->json_query($query);
598 for my $li_id_obj (@$lis) {
599 my $li_id = $li_id_obj->{"lineitem"};
600 if($options->{"idlist"}) {
601 $conn->respond($li_id);
604 retrieve_lineitem($self, $conn, $auth, $li_id, $options)
612 __PACKAGE__->register_method(
613 method => 'lineitem_search_ident',
614 api_name => 'open-ils.acq.lineitem.search.ident',
617 desc => 'Performs a search against lineitem_attrs where ident is true',
619 {desc => 'Authentication token', type => 'string'},
620 { desc => q/Search definition. Options are:
621 attr_values : list of attribute values (required)
622 li_states : list of lineitem states
623 po_agencies : list of purchase order ordering agencies (org) ids
628 Options hash. Options are:
629 idlist : if set, only return lineitem IDs
630 clear_marc : if set, strip the MARC xml from the lineitem before delivery
631 flesh_attrs : flesh lineitem attributes;
639 my $LI_ATTR_SEARCH = {
640 select => { acqlia => ['lineitem'] },
653 fkey => 'purchase_order'
661 sub lineitem_search_ident {
662 my($self, $conn, $auth, $search, $options) = @_;
663 my $e = new_editor(authtoken=>$auth, xact=>1);
664 return $e->event unless $e->checkauth;
665 # XXX needs permissions consideration
667 return [] unless $search;
668 my $attr_values = $search->{attr_values};
669 my $li_states = $search->{li_states};
670 my $po_agencies = $search->{po_agencies}; # XXX if none, base it on perms
675 '+acqliad' => {ident => 't'},
679 push(@{$where_clause->{'-or'}}, {attr_value => {ilike => "%$_%"}}) for @$attr_values;
681 $where_clause->{'+jub'} = {state => {in => $li_states}}
682 if $li_states and @$li_states;
684 $where_clause->{'+acqpo'} = {ordering_agency => $po_agencies}
685 if $po_agencies and @$po_agencies;
687 $LI_ATTR_SEARCH->{where} = $where_clause;
689 my $lis = $e->json_query($LI_ATTR_SEARCH);
691 for my $li_id_obj (@$lis) {
692 my $li_id = $li_id_obj->{lineitem};
693 if($$options{idlist}) {
694 $conn->respond($li_id);
697 if($$options{flesh_attrs}) {
698 $li = $e->retrieve_acq_lineitem([
699 $li_id, {flesh => 1, flesh_fields => {jub => ['attributes']}}])
701 $li = $e->retrieve_acq_lineitem($li_id);
703 $li->clear_marc if $$options{clear_marc};
711 __PACKAGE__->register_method(
712 method => 'retrieve_lineitem_detail',
713 api_name => 'open-ils.acq.lineitem_detail.retrieve',
716 desc => q/Updates a lineitem detail/,
718 { desc => 'Authentication token', type => 'string' },
719 { desc => 'id of lineitem_detail to retrieve', type => 'number' },
721 return => { desc => 'object on success, Event on failure' }
724 sub retrieve_lineitem_detail {
725 my($self, $conn, $auth, $li_detail_id) = @_;
726 my $e = new_editor(authtoken=>$auth);
727 return $e->event unless $e->checkauth;
729 my $li_detail = $e->retrieve_acq_lineitem_detail($li_detail_id)
732 if($li_detail->fund) {
733 my $fund = $e->retrieve_acq_fund($li_detail->fund) or return $e->event;
734 return $e->event unless
735 $e->allowed('MANAGE_FUND', $fund->org, $fund);
738 # XXX check lineitem perms
743 __PACKAGE__->register_method(
744 method => 'approve_lineitem',
745 api_name => 'open-ils.acq.lineitem.approve',
747 desc => 'Mark a lineitem as approved',
749 { desc => 'Authentication token', type => 'string' },
750 { desc => 'lineitem ID', type => 'number' }
752 return => { desc => '1 on success, Event on error' }
755 sub approve_lineitem {
756 my($self, $conn, $auth, $li_id) = @_;
757 my $e = new_editor(xact=>1, authtoken=>$auth);
758 return $e->die_event unless $e->checkauth;
760 # XXX perm checks for each lineitem detail
762 my $li = $e->retrieve_acq_lineitem($li_id)
763 or return $e->die_event;
765 return OpenILS::Event->new('ACQ_LINEITEM_APPROVED', payload => $li_id)
766 if $li->state eq 'approved';
768 my $details = $e->search_acq_lineitem_detail({lineitem => $li_id});
769 return OpenILS::Event->new('ACQ_LINEITEM_NO_COPIES', payload => $li_id)
770 unless scalar(@$details) > 0;
772 for my $detail (@$details) {
773 return OpenILS::Event->new('ACQ_LINEITEM_DETAIL_NO_FUND', payload => $detail->id)
774 unless $detail->fund;
776 return OpenILS::Event->new('ACQ_LINEITEM_DETAIL_NO_ORG', payload => $detail->id)
777 unless $detail->owning_lib;
780 $li->state('approved');
781 $li->edit_time('now');
782 $e->update_acq_lineitem($li) or return $e->die_event;
790 __PACKAGE__->register_method(
791 method => 'set_lineitem_attr',
792 api_name => 'open-ils.acq.lineitem_usr_attr.set',
794 desc => 'Sets a lineitem_usr_attr value',
796 { desc => 'Authentication token', type => 'string' },
797 { desc => 'Lineitem ID', type => 'number' },
798 { desc => 'Attr name', type => 'string' },
799 { desc => 'Attr value', type => 'string' }
801 return => { desc => '1 on success, Event on error' }
805 __PACKAGE__->register_method(
806 method => 'set_lineitem_attr',
807 api_name => 'open-ils.acq.lineitem_local_attr.set',
809 desc => 'Sets a lineitem_local_attr value',
811 { desc => 'Authentication token', type => 'string' },
812 { desc => 'Lineitem ID', type => 'number' },
813 { desc => 'Attr name', type => 'string' },
814 { desc => 'Attr value', type => 'string' }
816 return => { desc => 'ID of the attr object on success, Event on error' }
821 sub set_lineitem_attr {
822 my($self, $conn, $auth, $li_id, $attr_name, $attr_value) = @_;
823 my $e = new_editor(xact=>1, authtoken=>$auth);
824 return $e->die_event unless $e->checkauth;
828 my $attr_type = $self->api_name =~ /local_attr/ ?
829 'lineitem_local_attr_definition' : 'lineitem_usr_attr_definition';
831 my $attr = $e->search_acq_lineitem_attr({
833 attr_type => $attr_type,
834 attr_name => $attr_name})->[0];
836 my $find = "search_acq_$attr_type";
839 $attr->attr_value($attr_value);
840 $e->update_acq_lineitem_attr($attr) or return $e->die_event;
842 $attr = Fieldmapper::acq::lineitem_attr->new;
843 $attr->lineitem($li_id);
844 $attr->attr_type($attr_type);
845 $attr->attr_name($attr_name);
846 $attr->attr_value($attr_value);
848 my $attr_def_id = $e->$find({code => $attr_name}, {idlist=>1})->[0]
849 or return $e->die_event;
850 $attr->definition($attr_def_id);
851 $e->create_acq_lineitem_attr($attr) or return $e->die_event;
858 __PACKAGE__->register_method(
859 method => 'get_lineitem_attr_defs',
860 api_name => 'open-ils.acq.lineitem_attr_definition.retrieve.all',
863 desc => 'Retrieve lineitem attr definitions',
864 params => [ { desc => 'Authentication token', type => 'string' }, ],
865 return => { desc => 'List of attr definitions' }
869 sub get_lineitem_attr_defs {
870 my($self, $conn, $auth) = @_;
871 my $e = new_editor(authtoken=>$auth);
872 return $e->event unless $e->checkauth;
874 for my $type (qw/generated marc local usr provider/) {
875 my $call = "retrieve_all_acq_lineitem_${type}_attr_definition";
876 $results{$type} = $e->$call;
882 __PACKAGE__->register_method(
883 method => 'lineitem_note_CUD_batch',
884 api_name => 'open-ils.acq.lineitem_note.cud.batch',
887 desc => q/Manage lineitem notes/,
889 { desc => 'Authentication token', type => 'string' },
890 { desc => 'List of lineitem_notes to manage', type => 'array' },
893 { desc => 'Streaming response of current position in the array' }
897 sub lineitem_note_CUD_batch {
898 my($self, $conn, $auth, $li_notes) = @_;
900 my $e = new_editor(xact=>1, authtoken=>$auth);
901 return $e->die_event unless $e->checkauth;
904 my $total = @$li_notes;
907 for my $note (@$li_notes) {
909 $note->editor($e->requestor->id);
910 $note->edit_time('now');
913 $note->creator($e->requestor->id);
914 $note = $e->create_acq_lineitem_note($note) or return $e->die_event;
916 } elsif($note->isdeleted) {
917 $e->delete_acq_lineitem_note($note) or return $e->die_event;
919 } elsif($note->ischanged) {
920 $e->update_acq_lineitem_note($note) or return $e->die_event;
923 if(!$note->isdeleted) {
924 $note = $e->retrieve_acq_lineitem_note([
926 "flesh" => 1, "flesh_fields" => {"acqlin" => ["alert_text"]}
931 $conn->respond({maximum => $total, progress => ++$count, note => $note});
935 return {complete => 1};
938 __PACKAGE__->register_method(
939 method => 'ranged_line_item_alert_text',
940 api_name => 'open-ils.acq.line_item_alert_text.ranged.retrieve.all'); # TODO: signature
942 sub ranged_line_item_alert_text {
943 my($self, $conn, $auth, $org_id, $depth) = @_;
944 my $e = new_editor(authtoken => $auth);
945 return $e->event unless $e->checkauth;
946 return $e->event unless $e->allowed('ADMIN_ACQ_LINEITEM_ALERT_TEXT', $org_id);
947 return $e->search_acq_lineitem_alert_text(
948 {owning_lib => $U->get_org_full_path($org_id, $depth)});
952 __PACKAGE__->register_method(
953 method => "retrieve_lineitem_by_copy_id",
954 api_name => "open-ils.acq.lineitem.retrieve.by_copy_id",
957 desc => q/Manage lineitem notes/,
959 {desc => "Authentication token", type => "string"},
960 {desc => "Evergreen internal copy ID", type => "number"},
961 {desc => "Hash of options (see open-ils.acq.lineitem.retrieve",
965 desc => "Lineitem associated with given copy",
966 type => "object", class => "jub"
971 sub retrieve_lineitem_by_copy_id {
972 my ($self, $conn, $auth, $object_id, $options) = @_;
974 my $e = new_editor("authtoken" => $auth);
975 return $e->die_event unless $e->checkauth;
977 my $result = $e->json_query({
978 "select" => {"acqlid" => ["lineitem"]},
980 "where" => {"eg_copy_id" => $object_id}
983 return new OpenILS::Event("ACQ_LINEITEM_NOT_FOUND");
986 my $li = retrieve_lineitem_impl($e, $result->{"lineitem"}, $options) or
987 return $e->die_event;