]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/circ/patron/bill-statement.component.ts
LP1904036 Bills/Payments modify notes fix
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / circ / patron / bill-statement.component.ts
1 import {Component, Input, OnInit, AfterViewInit, ViewChild} from '@angular/core';
2 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
3 import {from, empty, range} from 'rxjs';
4 import {concatMap, tap, takeLast} from 'rxjs/operators';
5 import {NgbNav, NgbNavChangeEvent} from '@ng-bootstrap/ng-bootstrap';
6 import {IdlObject} from '@eg/core/idl.service';
7 import {EventService} from '@eg/core/event.service';
8 import {OrgService} from '@eg/core/org.service';
9 import {NetService} from '@eg/core/net.service';
10 import {PcrudService, PcrudContext} from '@eg/core/pcrud.service';
11 import {AuthService} from '@eg/core/auth.service';
12 import {ServerStoreService} from '@eg/core/server-store.service';
13 import {PatronService} from '@eg/staff/share/patron/patron.service';
14 import {PatronContextService, BillGridEntry} from './patron.service';
15 import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
16 import {GridComponent} from '@eg/share/grid/grid.component';
17 import {Pager} from '@eg/share/util/pager';
18 import {CircService, CircDisplayInfo} from '@eg/staff/share/circ/circ.service';
19 import {PrintService} from '@eg/share/print/print.service';
20 import {PromptDialogComponent} from '@eg/share/dialog/prompt.component';
21 import {AlertDialogComponent} from '@eg/share/dialog/alert.component';
22 import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
23 import {CreditCardDialogComponent
24     } from '@eg/staff/share/billing/credit-card-dialog.component';
25 import {BillingService, CreditCardPaymentParams} from '@eg/staff/share/billing/billing.service';
26 import {AddBillingDialogComponent} from '@eg/staff/share/billing/billing-dialog.component';
27 import {AudioService} from '@eg/share/util/audio.service';
28 import {ToastService} from '@eg/share/toast/toast.service';
29
30 @Component({
31   templateUrl: 'bill-statement.component.html',
32   selector: 'eg-patron-bill-statement'
33 })
34 export class BillStatementComponent implements OnInit {
35
36     @Input() patronId: number;
37     @Input() xactId: number;
38     statement: any;
39     statementTab = 'statement';
40     billingDataSource: GridDataSource = new GridDataSource();
41     paymentDataSource: GridDataSource = new GridDataSource();
42     cellTextGenerator: GridCellTextGenerator;
43     noteTargets: string;
44     voidTargets: string;
45     voidAmount: number;
46
47     @ViewChild('billingGrid') private billingGrid: GridComponent;
48     @ViewChild('noteDialog') private noteDialog: PromptDialogComponent;
49     @ViewChild('voidBillsDialog') private voidBillsDialog: ConfirmDialogComponent;
50
51     constructor(
52         private router: Router,
53         private route: ActivatedRoute,
54         private audio: AudioService,
55         private toast: ToastService,
56         private org: OrgService,
57         private evt: EventService,
58         private net: NetService,
59         private pcrud: PcrudService,
60         private auth: AuthService,
61         private printer: PrintService,
62         private serverStore: ServerStoreService,
63         private circ: CircService,
64         private billing: BillingService,
65         public patronService: PatronService,
66         public context: PatronContextService
67     ) {}
68
69     ngOnInit() {
70
71         this.cellTextGenerator = {
72         };
73
74         this.billingDataSource.getRows = (pager: Pager, sort: any[]) => {
75             const orderBy: any = {};
76             if (sort.length) {
77                 orderBy.mb = sort[0].name + ' ' + sort[0].dir;
78             }
79             return this.pcrud.search('mb', {xact: this.xactId}, {
80                 flesh: 1,
81                 flesh_fields: {mb: ['voider']},
82                 order_by: orderBy
83             });
84         };
85
86         this.paymentDataSource.getRows = (pager: Pager, sort: any[]) => {
87             const orderBy: any = {};
88             if (sort.length) {
89                 orderBy.mbp = sort[0].name + ' ' + sort[0].dir;
90             }
91             return this.pcrud.search('mbp', {xact: this.xactId}, {
92                 flesh: 1,
93                 flesh_fields: {mbp: ['accepting_usr']},
94                 order_by: orderBy
95             });
96         };
97
98         this.net.request(
99             'open-ils.circ',
100             'open-ils.circ.money.statement.retrieve',
101             this.auth.token(), this.xactId
102         ).subscribe(s => this.statement = s);
103     }
104
105     openNoteDialog(rows: IdlObject[]) {
106         if (rows.length === 0) { return; }
107
108         const notes = rows.map(r => r.note() || '').join(',');
109         const ids = rows.map(r => r.id());
110         this.noteTargets = ids.join(',');
111         this.noteDialog.promptValue = notes;
112
113         this.noteDialog.open().subscribe(value => {
114             if (value === notes) { return; }
115
116             let method = 'open-ils.circ.money.billing.note.edit';
117             if (rows[0].classname === 'mbp') {
118                 method = 'open-ils.circ.money.payment.note.edit';
119             }
120
121             this.net.requestWithParamList(
122                 'open-ils.circ', method, [this.auth.token(), value].concat(ids))
123             .toPromise().then(resp => {
124                 const evt = this.evt.parse(resp);
125                 if (evt) {
126                     console.error(evt);
127                 } else {
128                     rows.forEach(r => r.note(value));
129                 }
130             });
131         });
132     }
133
134     openVoidDialog(rows: IdlObject[]) {
135         rows = rows.filter(r => r.voided() === 'f');
136
137         let amount = 0;
138         rows.forEach(billing => amount += billing.amount() * 100);
139
140         const ids = rows.map(r => r.id());
141         this.voidAmount = amount / 100;
142         this.voidTargets = ids.join(',');
143
144         this.voidBillsDialog.open().subscribe(confirmed => {
145             if (!confirmed) { return; }
146
147             this.net.requestWithParamList(
148                 'open-ils.circ',
149                 'open-ils.circ.money.billing.void',
150                 [this.auth.token()].concat(ids)).toPromise()
151             .then(resp => {
152                 const evt = this.evt.parse(resp);
153                 if (evt) {
154                     console.error(evt);
155                 } else {
156                     this.context.refreshPatron();
157                     this.billingGrid.reload();
158                 }
159             });
160         });
161     }
162
163     copy(): IdlObject {
164         if (this.statement && this.statement.xact.circulation()) {
165             return this.statement.xact.circulation().target_copy();
166         }
167     }
168
169     totalBilled(): number {
170         if (!this.statement) { return 0; }
171
172         const billed = (this.statement.summary.billing_total || 0) * 100;
173         const voided = (this.statement.summary.void_total || 0) * 100;
174
175         return (billed - voided) / 100;
176     }
177 }
178