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';
21 templateUrl: 'summary.component.html',
22 selector: 'eg-acq-po-summary'
24 export class PoSummaryComponent implements OnInit {
26 private _poId: number;
27 @Input() set poId(id: number) {
28 if (id === this._poId) { return; }
30 if (this.initDone) { this.load(); }
32 get poId(): number { return this._poId; }
40 canActivate: boolean = null;
42 activationBlocks: EgEvent[] = [];
43 activationEvent: EgEvent;
44 nameEditEnterToggled = false;
46 @ViewChild('cancelDialog') cancelDialog: CancelDialogComponent;
47 @ViewChild('progressDialog') progressDialog: ProgressDialogComponent;
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
63 this.load().then(_ => this.initDone = true);
65 // Re-check for activation blocks if the LI service tells us
66 // something significant happened.
67 this.liService.activateStateChange
68 .subscribe(_ => this.setCanActivate());
72 return this.poService.currentPo;
75 load(): Promise<any> {
76 if (!this.poId) { return Promise.resolve(); }
78 return this.poService.getFleshedPo(this.poId)
82 return this.pcrud.search('acqedim',
83 {purchase_order: this.poId}, {}, {idlist: true, atomic: true}
84 ).toPromise().then(ids => this.ediMessageCount = ids.length);
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);
95 }).then(_ => this.setCanActivate());
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
101 toggleNameEdit(fromEnter?: boolean) {
103 this.nameEditEnterToggled = true;
105 if (this.nameEditEnterToggled) {
106 this.nameEditEnterToggled = false;
111 this.editPoName = !this.editPoName;
113 if (this.editPoName) {
114 this.newPoName = this.po().name();
117 document.getElementById('pl-name-input') as HTMLInputElement;
118 if (node) { node.select(); }
121 } else if (this.newPoName && this.newPoName !== this.po().name()) {
123 const prevName = this.po().name();
124 this.po().name(this.newPoName);
125 this.newPoName = null;
127 this.pcrud.update(this.po()).subscribe(resp => {
128 const evt = this.evt.parse(resp);
131 this.po().name(prevName);
138 this.cancelDialog.open().subscribe(reason => {
139 if (!reason) { return; }
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
147 this.progressDialog.close();
148 location.href = location.href;
154 this.canActivate = null;
155 this.activationBlocks = [];
157 if (!(this.po().state().match(/new|pending/))) {
158 this.canActivate = false;
162 this.net.request('open-ils.acq',
163 'open-ils.acq.purchase_order.activate.dry_run',
164 this.auth.token(), this.poId
168 const evt = this.evt.parse(resp);
169 if (evt) { this.activationBlocks.push(evt); }
171 })).toPromise().then(_ => {
173 if (this.activationBlocks.length === 0) {
174 this.canActivate = true;
178 this.canActivate = false;
180 // TODO More logic likely needed here to handle zero-copy
181 // activation / ACQ_LINEITEM_NO_COPIES
186 // TODO This code bypasses the Vandelay UI and force-loads the records.
188 this.activationEvent = null;
189 this.progressDialog.open();
190 this.progressDialog.update({max: this.po().lineitem_count() * 3});
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()}`
200 ).subscribe(resp => {
201 const evt = this.evt.parse(resp);
204 this.progressDialog.close();
205 this.activationEvent = evt;
209 if (Number(resp) === 1) {
210 this.progressDialog.close();
211 // Refresh everything.
212 location.href = location.href;
215 this.progressDialog.update(
216 {value: resp.bibs + resp.li + resp.vqbr});