From e39c9a91f2717cf05bb8a074e16f963ba9a2bd4e Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Wed, 20 Jan 2021 15:49:55 -0500 Subject: [PATCH] LP1929741 ACQ caching / batch editing improvements Ensure that funds/mods/locations of modified copies are available at render time after saving changes to copies. Hide the copy batch update bar when no copies are editable. Signed-off-by: Bill Erickson Signed-off-by: Galen Charlton Signed-off-by: Jane Sandberg --- .../staff/acq/lineitem/batch-copies.component.html | 22 +++--- .../staff/acq/lineitem/batch-copies.component.ts | 15 ++++ .../src/app/staff/acq/lineitem/copies.component.ts | 51 +++----------- .../app/staff/acq/lineitem/copy-attrs.component.ts | 18 +---- .../src/app/staff/acq/lineitem/lineitem.service.ts | 80 +++++++++++++++++++++- 5 files changed, 118 insertions(+), 68 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.html b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.html index 615ddb0b81..de3b2f43b0 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.html +++ b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.html @@ -25,18 +25,20 @@ - + + + + +
+ +
-
- -
-
diff --git a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.ts b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.ts index 592d7230fa..8ce878c66b 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/batch-copies.component.ts @@ -133,6 +133,21 @@ export class LineitemBatchCopiesComponent implements OnInit { return promise; } + + hasEditableCopies(): boolean { + if (this.lineitem) { + const copies = this.lineitem.lineitem_details(); + if (copies && copies.length > 0) { + for (let idx = 0; idx < copies.length; idx++) { // early break + if (this.liService.copyDisposition( + this.lineitem, copies[idx]) === 'pre-order') { + return true; + } + } + } + } + return false; + } } diff --git a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copies.component.ts b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copies.component.ts index 3ad72df237..e9f060e83d 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copies.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copies.component.ts @@ -171,51 +171,22 @@ export class LineitemCopiesComponent implements OnInit, AfterViewInit { // are not required to go fetch them en masse / en duplicato. fetchFormulaValues(): Promise { - const funds = this.formulaValues.fund ? - Object.keys(this.formulaValues.fund) : []; - - const mods = this.formulaValues.circ_modifier ? - Object.keys(this.formulaValues.circ_modifier) : []; - - const locs = this.formulaValues.location ? - Object.keys(this.formulaValues.location) : []; - - let promise = Promise.resolve(); - - if (funds.length > 0) { - promise = promise.then(_ => { - return this.pcrud.search('acqf', {id: funds}) - .pipe(tap(fund => { - this.liService.fundCache[fund.id()] = fund; - this.liService.batchOptionWanted.emit( - {fund: {id: fund.id(), label: fund.code(), fm: fund}}); - })).toPromise(); - }); + let funds = []; + if (this.formulaValues.fund) { + funds = Object.keys(this.formulaValues.fund).map(id => Number(id)); } - if (mods.length > 0) { - promise = promise.then(_ => { - return this.pcrud.search('ccm', {code: mods}) - .pipe(tap(mod => { - this.liService.circModCache[mod.code()] = mod; - this.liService.batchOptionWanted.emit({circ_modifier: - {id: mod.code(), label: mod.code(), fm: mod}}); - })).toPromise(); - }); + let locs = []; + if (this.formulaValues.location) { + locs = Object.keys(this.formulaValues.location).map(id => Number(id)); } - if (locs.length > 0) { - promise = promise.then(_ => { - return this.pcrud.search('acpl', {id: locs}) - .pipe(tap(loc => { - this.loc.locationCache[loc.id()] = loc; - this.liService.batchOptionWanted.emit({location: - {id: loc.id(), label: loc.name(), fm: loc}}); - })).toPromise(); - }); - } + const mods = this.formulaValues.circ_modifier ? + Object.keys(this.formulaValues.circ_modifier) : []; - return promise; + return this.liService.fetchFunds(funds) + .then(_ => this.liService.fetchLocations(locs)) + .then(_ => this.liService.fetchCircMods(mods)); } // Apply a formula entry to a single copy. diff --git a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copy-attrs.component.ts b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copy-attrs.component.ts index 94b9e6d987..fb9ecae815 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copy-attrs.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/copy-attrs.component.ts @@ -4,7 +4,7 @@ import {Pager} from '@eg/share/util/pager'; import {IdlObject, IdlService} from '@eg/core/idl.service'; import {NetService} from '@eg/core/net.service'; import {AuthService} from '@eg/core/auth.service'; -import {LineitemService} from './lineitem.service'; +import {LineitemService, COPY_ORDER_DISPOSITION} from './lineitem.service'; import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.component'; import {ItemLocationService} from '@eg/share/item-location-select/item-location-select.service'; import {ItemLocationSelectComponent} from '@eg/share/item-location-select/item-location-select.component'; @@ -152,20 +152,8 @@ export class LineitemCopyAttrsComponent implements OnInit { return false; } - disposition(): 'canceled' | 'delayed' | 'received' | 'on-order' | 'pre-order' { - if (!this.copy || !this.lineitem) { - return null; - } else if (this.copy.cancel_reason()) { - if (this.copy.cancel_reason().keep_debits() === 't') { - return 'delayed'; - } else { - return 'canceled'; - } - } else if (this.copy.recv_time()) { - return 'received'; - } else if (this.lineitem.state() === 'on-order') { - return 'on-order'; - } else { return 'pre-order'; } + disposition(): COPY_ORDER_DISPOSITION { + return this.liService.copyDisposition(this.lineitem, this.copy); } } diff --git a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/lineitem.service.ts b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/lineitem.service.ts index a4e49a1dbd..9ee2f73ec4 100644 --- a/Open-ILS/src/eg2/src/app/staff/acq/lineitem/lineitem.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/acq/lineitem/lineitem.service.ts @@ -8,6 +8,10 @@ import {PcrudService} from '@eg/core/pcrud.service'; import {ComboboxEntry} from '@eg/share/combobox/combobox.component'; import {ItemLocationService} from '@eg/share/item-location-select/item-location-select.service'; +const COPY_ORDER_DISPOSITIONS: + 'canceled' | 'delayed' | 'received' | 'on-order' | 'pre-order' = null; +export type COPY_ORDER_DISPOSITION = typeof COPY_ORDER_DISPOSITIONS; + export interface BatchLineitemStruct { id: number; lineitem: IdlObject; @@ -274,9 +278,21 @@ export class LineitemService { const lids = li.lineitem_details().filter(copy => (copy.isnew() || copy.ischanged() || copy.isdeleted())); - return this.net.request( - 'open-ils.acq', - 'open-ils.acq.lineitem_detail.cud.batch', this.auth.token(), lids); + return from( + + // Ensure we have the updated fund/loc/mod values before + // sending the copies off to be updated and then re-drawn. + this.fetchFunds(lids.map(lid => lid.fund())) + .then(_ => this.fetchLocations(lids.map(lid => lid.location()))) + .then(_ => this.fetchCircMods(lids.map(lid => lid.circ_modifier()))) + + ).pipe(switchMap(_ => + this.net.request( + 'open-ils.acq', + 'open-ils.acq.lineitem_detail.cud.batch', + this.auth.token(), lids + ) + )); } updateLineitems(lis: IdlObject[]): Observable { @@ -296,5 +312,63 @@ export class LineitemService { return obs; } + + + // Methods to fetch copy-related data, add it to our local cache, + // and announce that new values are available for comboboxes. + fetchFunds(fundIds: number[]): Promise { + fundIds = fundIds.filter(id => id && !(id in this.fundCache)); + if (fundIds.length === 0) { return Promise.resolve(); } + + return this.pcrud.search('acqf', {id: fundIds}) + .pipe(tap(fund => { + this.fundCache[fund.id()] = fund; + this.batchOptionWanted.emit( + {fund: {id: fund.id(), label: fund.code(), fm: fund}}); + })).toPromise(); + } + + fetchCircMods(circMods: string[]): Promise { + circMods = circMods + .filter(code => code && !(code in this.circModCache)); + + if (circMods.length === 0) { return Promise.resolve(); } + + return this.pcrud.search('ccm', {code: circMods}) + .pipe(tap(mod => { + this.circModCache[mod.code()] = mod; + this.batchOptionWanted.emit({circ_modifier: + {id: mod.code(), label: mod.code(), fm: mod}}); + })).toPromise(); + } + + fetchLocations(locIds: number[]): Promise { + locIds = locIds.filter(id => id && !(id in this.loc.locationCache)); + if (locIds.length === 0) { return Promise.resolve(); } + + return this.pcrud.search('acpl', {id: locIds}) + .pipe(tap(loc => { + this.loc.locationCache[loc.id()] = loc; + this.batchOptionWanted.emit({location: + {id: loc.id(), label: loc.name(), fm: loc}}); + })).toPromise(); + } + + // Order disposition of a single lineitem detail + copyDisposition(lineitem: IdlObject, copy: IdlObject): COPY_ORDER_DISPOSITION { + if (!copy || !lineitem) { + return null; + } else if (copy.cancel_reason()) { + if (copy.cancel_reason().keep_debits() === 't') { + return 'delayed'; + } else { + return 'canceled'; + } + } else if (copy.recv_time()) { + return 'received'; + } else if (lineitem.state() === 'on-order') { + return 'on-order'; + } else { return 'pre-order'; } + } } -- 2.11.0