From 139814e87b62adc7bf7e186d0371c3dcd903dff9 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Tue, 23 Feb 2021 18:10:10 -0500 Subject: [PATCH] LP1904036 Mark missing; initial checkin api Signed-off-by: Bill Erickson Signed-off-by: Jane Sandberg Signed-off-by: Galen Charlton --- .../eg2/src/app/staff/share/circ/circ.service.ts | 95 +++++++++++++++++++++- .../src/app/staff/share/circ/grid.component.html | 13 +++ .../eg2/src/app/staff/share/circ/grid.component.ts | 43 +++++++++- 3 files changed, 149 insertions(+), 2 deletions(-) diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/circ.service.ts b/Open-ILS/src/eg2/src/app/staff/share/circ/circ.service.ts index 7bede2fb4b..3c513d0736 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/circ/circ.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/circ/circ.service.ts @@ -1,5 +1,5 @@ import {Injectable} from '@angular/core'; -import {Observable} from 'rxjs'; +import {Observable, empty} from 'rxjs'; import {map, mergeMap} from 'rxjs/operators'; import {IdlObject} from '@eg/core/idl.service'; import {NetService} from '@eg/core/net.service'; @@ -39,6 +39,22 @@ export interface CheckoutResult { record?: IdlObject; } +export interface CheckinParams { + noop?: boolean; + copy_id?: number; + copy_barcode?: string; +} + +export interface CheckinResult { + index: number; + evt: EgEvent; + params: CheckinParams; + success: boolean; + copy?: IdlObject; + circ?: IdlObject; + record?: IdlObject; +} + @Injectable() export class CircService { static resultIndex = 0; @@ -109,5 +125,82 @@ export class CircService { return Promise.resolve(result); } + + checkin(params: CheckinParams, override?: boolean): Promise { + + console.debug('checking in with', params); + + let method = 'open-ils.circ.checkin'; + if (override) { method += '.override'; } + + return this.net.request( + 'open-ils.circ', method, + this.auth.token(), params).toPromise() + .then(result => this.processCheckinResult(params, result)); + } + + processCheckinResult( + params: CheckinParams, response: any): Promise { + + console.debug('checkout resturned', response); + + if (Array.isArray(response)) { response = response[0]; } + + const evt = this.evt.parse(response); + const payload = evt.payload; + + if (!payload) { + this.audio.play('error.unknown.no_payload'); + return Promise.reject(); + } + + switch (evt.textcode) { + case 'ITEM_NOT_CATALOGED': + // alert, etc. + } + + const result: CheckinResult = { + index: CircService.resultIndex++, + evt: evt, + params: params, + success: evt.textcode === 'SUCCESS', // or route, no change, etc. + circ: payload.circ, + copy: payload.copy, + record: payload.record + }; + + return Promise.resolve(result); + } + + // The provided params (minus the copy_id) will be used + // for all items. + checkinBatch(copyIds: number[], params?: CheckinParams): Observable { + if (copyIds.length === 0) { return empty(); } + + if (!params) { params = {}; } + const ids = [].concat(copyIds); // clone + + let observer; + const observable = new Observable(o => observer = o); + + const checkinOne = (ids: number[]): Promise => { + if (ids.length === 0) { + observer.complete(); + return Promise.resolve(null); + } + + const cparams = Object.assign(params, {}); // clone + cparams.copy_id = ids.pop(); + + return this.checkin(cparams).then(result => { + observer.next(result); + return checkinOne(ids); + }); + } + + checkinOne(ids); + + return observable; + } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.html b/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.html index 2b8d81d187..53177274fa 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.html @@ -5,6 +5,12 @@ + + + @@ -44,6 +50,13 @@ group="Mark" i18n-group i18n-label label="Mark Item Damaged" (onClick)="showMarkDamagedDialog($event)"> + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.ts b/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.ts index 56bebe16a7..43d1f1f6e4 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/circ/grid.component.ts @@ -6,8 +6,10 @@ import {IdlObject} from '@eg/core/idl.service'; import {OrgService} from '@eg/core/org.service'; import {NetService} from '@eg/core/net.service'; import {PcrudService} from '@eg/core/pcrud.service'; -import {CheckoutParams, CheckoutResult, CircService} from './circ.service'; +import {CheckoutParams, CheckoutResult, CheckinParams, CheckinResult, + CircService} from './circ.service'; import {PromptDialogComponent} from '@eg/share/dialog/prompt.component'; +import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component'; import {GridDataSource, GridColumn, GridCellTextGenerator, GridRowFlairEntry} from '@eg/share/grid/grid'; import {GridComponent} from '@eg/share/grid/grid.component'; @@ -23,6 +25,8 @@ import {StringComponent} from '@eg/share/string/string.component'; import {DueDateDialogComponent} from './due-date-dialog.component'; import {MarkDamagedDialogComponent } from '@eg/staff/share/holdings/mark-damaged-dialog.component'; +import {MarkMissingDialogComponent + } from '@eg/staff/share/holdings/mark-missing-dialog.component'; export interface CircGridEntry { index: string; // class + id -- row index @@ -90,6 +94,10 @@ export class CircGridComponent implements OnInit { @ViewChild('dueDateDialog') private dueDateDialog: DueDateDialogComponent; @ViewChild('markDamagedDialog') private markDamagedDialog: MarkDamagedDialogComponent; + @ViewChild('markMissingDialog') + private markMissingDialog: MarkMissingDialogComponent; + @ViewChild('itemsOutConfirm') + private itemsOutConfirm: ConfirmDialogComponent; constructor( private org: OrgService, @@ -322,6 +330,39 @@ export class CircGridComponent implements OnInit { }); } + showMarkMissingDialog(rows: CircGridEntry[]) { + const copyIds = this.getCopyIds(rows, 4 /* ignore missing */); + + if (copyIds.length === 0) { return; } + + // This assumes all of our items our checked out, since this is + // a circ grid. If we add support later for showing completed + // circulations, there may be cases where we can skip the items + // out confirmation alert and subsequent checkin + this.itemsOutConfirm.open().subscribe(confirmed => { + if (!confirmed) { return; } + + this.checkin(rows, {noop: true}, true).then(_ => { + + this.markMissingDialog.copyIds = copyIds; + this.markMissingDialog.open({}).subscribe( + rowsModified => { + if (rowsModified) { + this.emitReloadRequest(); + } + } + ); + }); + }); + } + + // TODO: progress dialog + // Same params will be used for each copy + checkin(rows: CircGridEntry[], params?: CheckinParams, noReload?: boolean): Promise { + return this.circ.checkinBatch(this.getCopyIds(rows), params).toPromise() + .then(_ => { if (!noReload) { this.emitReloadRequest(); } }); + } + emitReloadRequest() { this.entries = null; this.reloadRequested.emit(); -- 2.11.0