]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/staff/acq/po/summary.component.ts
LP1929741 ACQ Selection List & PO Angluar Port
[Evergreen.git] / Open-ILS / src / eg2 / src / app / staff / acq / po / summary.component.ts
1 import {Component, Input, OnInit, ViewChild} from '@angular/core';
2 import {Router} from '@angular/router';
3 import {of, Observable} from 'rxjs';
4 import {tap, take, map} from 'rxjs/operators';
5 import {IdlObject, IdlService} from '@eg/core/idl.service';
6 import {NetService} from '@eg/core/net.service';
7 import {AuthService} from '@eg/core/auth.service';
8 import {OrgService} from '@eg/core/org.service';
9 import {PcrudService} from '@eg/core/pcrud.service';
10 import {ServerStoreService} from '@eg/core/server-store.service';
11 import {ComboboxEntry, ComboboxComponent} from '@eg/share/combobox/combobox.component';
12 import {ProgressDialogComponent} from '@eg/share/dialog/progress.component';
13 import {EventService, EgEvent} from '@eg/core/event.service';
14 import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
15 import {PoService} from './po.service';
16 import {LineitemService} from '../lineitem/lineitem.service';
17 import {CancelDialogComponent} from '../lineitem/cancel-dialog.component';
18
19
20 @Component({
21   templateUrl: 'summary.component.html',
22   selector: 'eg-acq-po-summary'
23 })
24 export class PoSummaryComponent implements OnInit {
25
26     private _poId: number;
27     @Input() set poId(id: number) {
28         if (id === this._poId) { return; }
29         this._poId = id;
30         if (this.initDone) { this.load(); }
31     }
32     get poId(): number { return this._poId; }
33
34     newPoName: string;
35     editPoName = false;
36     initDone = false;
37     ediMessageCount = 0;
38     invoiceCount = 0;
39     showNotes = false;
40     canActivate: boolean = null;
41
42     activationBlocks: EgEvent[] = [];
43     activationEvent: EgEvent;
44     nameEditEnterToggled = false;
45
46     @ViewChild('cancelDialog') cancelDialog: CancelDialogComponent;
47     @ViewChild('progressDialog') progressDialog: ProgressDialogComponent;
48
49     constructor(
50         private router: Router,
51         private evt: EventService,
52         private idl: IdlService,
53         private net: NetService,
54         private org: OrgService,
55         private pcrud: PcrudService,
56         private auth: AuthService,
57         private store: ServerStoreService,
58         private liService: LineitemService,
59         private poService: PoService
60     ) {}
61
62     ngOnInit() {
63         this.load().then(_ => this.initDone = true);
64
65         // Re-check for activation blocks if the LI service tells us
66         // something significant happened.
67         this.liService.activateStateChange
68         .subscribe(_ => this.setCanActivate());
69     }
70
71     po(): IdlObject {
72         return this.poService.currentPo;
73     }
74
75     load(): Promise<any> {
76         if (!this.poId) { return Promise.resolve(); }
77
78         return this.poService.getFleshedPo(this.poId)
79         .then(po => {
80
81             // EDI message count
82             return this.pcrud.search('acqedim',
83                 {purchase_order: this.poId}, {}, {idlist: true, atomic: true}
84             ).toPromise().then(ids => this.ediMessageCount = ids.length);
85
86         }).then(_ => {
87
88             // Invoice count
89             return this.net.request('open-ils.acq',
90                 'open-ils.acq.invoice.unified_search.atomic',
91                 this.auth.token(), {acqpo: [{id: this.poId}]},
92                 null, null, {id_list: true}
93             ).toPromise().then(ids => this.invoiceCount = ids.length);
94
95         }).then(_ => this.setCanActivate());
96     }
97
98     // Can run via Enter or blur.  If it just ran via Enter, avoid
99     // running it again on the blur, which will happen directly after
100     // the Enter.
101     toggleNameEdit(fromEnter?: boolean) {
102         if (fromEnter) {
103             this.nameEditEnterToggled = true;
104         } else {
105             if (this.nameEditEnterToggled) {
106                 this.nameEditEnterToggled = false;
107                 return;
108             }
109         }
110
111         this.editPoName = !this.editPoName;
112
113         if (this.editPoName) {
114             this.newPoName = this.po().name();
115             setTimeout(() => {
116                 const node =
117                     document.getElementById('pl-name-input') as HTMLInputElement;
118                 if (node) { node.select(); }
119             });
120
121         } else if (this.newPoName && this.newPoName !== this.po().name()) {
122
123             const prevName = this.po().name();
124             this.po().name(this.newPoName);
125             this.newPoName = null;
126
127             this.pcrud.update(this.po()).subscribe(resp => {
128                 const evt = this.evt.parse(resp);
129                 if (evt) {
130                     alert(evt);
131                     this.po().name(prevName);
132                 }
133             });
134         }
135     }
136
137     cancelPo() {
138         this.cancelDialog.open().subscribe(reason => {
139             if (!reason) { return; }
140
141             this.progressDialog.reset();
142             this.progressDialog.open();
143             this.net.request('open-ils.acq',
144                 'open-ils.acq.purchase_order.cancel',
145                 this.auth.token(), this.poId, reason
146             ).subscribe(ok => {
147                 this.progressDialog.close();
148                 location.href = location.href;
149             });
150         });
151     }
152
153     setCanActivate() {
154         this.canActivate = null;
155         this.activationBlocks = [];
156
157         if (!(this.po().state().match(/new|pending/))) {
158             this.canActivate = false;
159             return;
160         }
161
162         this.net.request('open-ils.acq',
163             'open-ils.acq.purchase_order.activate.dry_run',
164             this.auth.token(), this.poId
165
166         ).pipe(tap(resp => {
167
168             const evt = this.evt.parse(resp);
169             if (evt) { this.activationBlocks.push(evt); }
170
171         })).toPromise().then(_ => {
172
173             if (this.activationBlocks.length === 0) {
174                 this.canActivate = true;
175                 return;
176             }
177
178             this.canActivate = false;
179
180             // TODO More logic likely needed here to handle zero-copy
181             // activation / ACQ_LINEITEM_NO_COPIES
182         });
183     }
184
185     activatePo() {
186         // TODO This code bypasses the Vandelay UI and force-loads the records.
187
188         this.activationEvent = null;
189         this.progressDialog.open();
190         this.progressDialog.update({max: this.po().lineitem_count() * 3});
191
192         this.net.request(
193             'open-ils.acq',
194             'open-ils.acq.purchase_order.activate',
195             this.auth.token(), this.poId, {
196                 // Import all records, no merging, etc.
197                 import_no_match: true,
198                 queue_name: `ACQ ${new Date().toISOString()}`
199             }
200         ).subscribe(resp => {
201             const evt = this.evt.parse(resp);
202
203             if (evt) {
204                 this.progressDialog.close();
205                 this.activationEvent = evt;
206                 return;
207             }
208
209             if (Number(resp) === 1) {
210                 this.progressDialog.close();
211                 // Refresh everything.
212                 location.href = location.href;
213
214             } else {
215                 this.progressDialog.update(
216                     {value: resp.bibs + resp.li + resp.vqbr});
217             }
218         });
219     }
220 }
221
222