From 76870bbb745869005c125e51616b08657986c209 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Mon, 8 Mar 2021 10:47:05 -0500 Subject: [PATCH] LP1904036 Billing continued Signed-off-by: Bill Erickson Signed-off-by: Jane Sandberg Signed-off-by: Galen Charlton --- .../staff/circ/patron/bills.component.html | 3 +- .../app/staff/circ/patron/bills.component.ts | 60 ++++++++------ .../app/staff/circ/patron/resolver.service.ts | 12 ++- .../perlmods/lib/OpenILS/Application/Actor.pm | 83 +++++++++++++++++++ 4 files changed, 128 insertions(+), 30 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.html b/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.html index a211e96006..53523121b4 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.html +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.html @@ -102,7 +102,8 @@
- +
diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.ts b/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.ts index ba8d39c627..9feb702cba 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.ts @@ -1,11 +1,11 @@ import {Component, Input, OnInit, AfterViewInit, ViewChild} from '@angular/core'; import {Router, ActivatedRoute, ParamMap} from '@angular/router'; import {from, empty} from 'rxjs'; -import {concatMap, tap} from 'rxjs/operators'; +import {concatMap, tap, takeLast} from 'rxjs/operators'; import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap'; import {IdlObject} from '@eg/core/idl.service'; import {NetService} from '@eg/core/net.service'; -import {PcrudService} from '@eg/core/pcrud.service'; +import {PcrudService, PcrudContext} from '@eg/core/pcrud.service'; import {AuthService} from '@eg/core/auth.service'; import {ServerStoreService} from '@eg/core/server-store.service'; import {PatronService} from '@eg/staff/share/patron/patron.service'; @@ -53,6 +53,7 @@ export class BillsComponent implements OnInit, AfterViewInit { sessionVoided = 0; paymentType = 'cash_payment'; checkNumber: string; + payAmount: number; annotatePayment = false; entries: BillGridEntry[]; @@ -103,30 +104,27 @@ export class BillsComponent implements OnInit, AfterViewInit { load() { - const xactIds = []; - - - // TODO: run this in a single pcrud transaction - - this.pcrud.retrieve('mous', this.patronId, {}, {authoritative : true}) - .pipe(tap(sum => this.summary = sum)) - .pipe(concatMap(_ => { - return this.pcrud.search('mbts', - {usr: this.patronId, balance_owed: {'<>' : 0}}, - {select: {mbts: ['id']}}, {authoritative : true} - ).pipe(tap(summary => xactIds.push(summary.id()))); - })) - .pipe(concatMap(_ => { - this.entries = []; - return this.pcrud.search('mbt', {id: xactIds}, { - flesh: XACT_FLESH_DEPTH, - flesh_fields: XACT_FLESH_FIELDS, - order_by: {mbts : ['xact_start']}, - select: {bre : ['id']} - }, {authoritative : true} - ).pipe(tap(xact => this.entries.push(this.formatForDisplay(xact)))); - })) - .subscribe(null, null, () => this.billGrid.reload()); + this.summary = null; + this.entries = []; + this.gridDataSource.requestingData = true; + + this.net.request('open-ils.actor', + 'open-ils.actor.user.transactions.for_billing', + this.auth.token(), this.patronId + ).subscribe( + resp => { + if (!this.summary) { // 1st response is summary + this.summary = resp; + } else { + this.entries.push(this.formatForDisplay(resp)); + } + }, + null, + () => { + this.gridDataSource.requestingData = false; + this.billGrid.reload(); + } + ); } formatForDisplay(xact: IdlObject): BillGridEntry { @@ -156,6 +154,16 @@ export class BillsComponent implements OnInit, AfterViewInit { return this.context.patron; } + disablePayment(): boolean { + if (!this.billGrid) { return true; } // still loading + + // TODO: pay amount can be zero when refunding + return ( + this.payAmount <= 0 || + this.billGrid.context.rowSelector.selected().length === 0 + ); + } + // TODO refundsAvailable(): number { return 0; diff --git a/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts b/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts index e9ea79d511..bb71414ccb 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/patron/resolver.service.ts @@ -24,8 +24,8 @@ export class PatronResolver implements Resolve> { fetchSettings(): Promise { - // Some of these are used by the shared circ service. - // Go ahead and precache them since we're making the call anyway. + // Some of these are used by the shared circ services. + // Precache them since we're making the call anyway. return this.store.getItemBatch([ 'eg.circ.patron.summary.collapse', 'circ.do_not_tally_claims_returned', @@ -35,7 +35,13 @@ export class PatronResolver implements Resolve> { 'ui.admin.patron_log.max_entries', 'circ.staff_client.do_not_auto_attempt_print', 'circ.clear_hold_on_checkout', - 'ui.circ.suppress_checkin_popups' + 'ui.circ.suppress_checkin_popups', + 'ui.circ.billing.uncheck_bills_and_unfocus_payment_box', + 'ui.circ.billing.amount_warn', + 'ui.circ.billing.amount_limit', + 'circ.staff_client.do_not_auto_attempt_print', + 'circ.disable_patron_credit', + 'credit.processor.default' ]).then(settings => { this.context.noTallyClaimsReturned = settings['circ.do_not_tally_claims_returned']; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm index 01741b5b5c..f6b97d0b54 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm @@ -5343,4 +5343,87 @@ sub filter_group_entry_crud { } } + +__PACKAGE__->register_method( + method => 'user_billing_xacts', + api_name => 'open-ils.actor.user.transactions.for_billing', + signature => { + desc => q/Returns a stream of user billing data appropriate for + display in the user bills UI. API is natively "authoritative"./, + params => [ + {desc => 'Authentication token', type => 'string'}, + {desc => 'User ID', type => 'number'} + ], + return => { + desc => q/First response is the user money summary, following + responses are fleshed billable transactions/ + } + } +); + +sub user_billing_xacts { + my ($self, $client, $auth, $user_id) = @_; + + my $e = new_editor(authtoken => $auth, xact => 1); + return $e->die_event unless $e->checkauth; + + my $user = $e->retrieve_actor_user($user_id) or return $e->die_event; + + return $e->die_event unless + $e->allowed('VIEW_USER_TRANSACTIONS', $user->home_ou); + + # Start with the user summary. + $client->respond($e->retrieve_money_user_summary($user_id)); + + my $xact_ids = $e->json_query({ + select => {mbts => ['id']}, + from => 'mbts', + where => { + usr => $user_id, + balance_owed => {'<>' => 0} + }, + order_by => {mbts => {xact_start => 'asc'}} + }); + + for my $xact_id (map { $_->{id} } @$xact_ids) { + + my $xact = $e->retrieve_money_billable_transaction([ + $xact_id, { + flesh => 5, + flesh_fields => { + mbt => [qw/summary circulation grocery/], + circ => [qw/ + target_copy + workstation + checkin_workstation + circ_lib + /], + acp => [qw/ + call_number + holds_count + status + circ_lib + location + floating + age_protect + parts + /], + acpm => [qw/part/], + acn => [qw/record owning_lib prefix suffix/], + bre => [qw/wide_display_entry/] + }, + # Avoid adding the MARXML + # Fleshed fields are implicitly included. + select => {bre => ['id']} + } + ]); + + $client->respond($xact); + } + + $e->rollback; + + return undef; +} + 1; -- 2.43.2