From 79b9fc2b57dcbaf1a507f86c0971128d14936a2c Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Tue, 20 Apr 2021 17:33:34 -0400 Subject: [PATCH] LP1904036 circ work log entries Signed-off-by: Bill Erickson Signed-off-by: Jane Sandberg Signed-off-by: Galen Charlton --- .../app/staff/circ/checkin/checkin.component.ts | 3 +- .../eg2/src/app/staff/share/circ/circ.module.ts | 4 +- .../eg2/src/app/staff/share/circ/circ.service.ts | 42 +++++++++- .../app/staff/share/circ/components.component.html | 10 +++ .../app/staff/share/circ/components.component.ts | 16 +++- .../src/app/staff/share/circ/work-log.service.ts | 93 ++++++++++++++++++++++ 6 files changed, 162 insertions(+), 6 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/staff/share/circ/work-log.service.ts diff --git a/Open-ILS/src/eg2/src/app/staff/circ/checkin/checkin.component.ts b/Open-ILS/src/eg2/src/app/staff/circ/checkin/checkin.component.ts index 5991c330f7..4a8a6d6faa 100644 --- a/Open-ILS/src/eg2/src/app/staff/circ/checkin/checkin.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/circ/checkin/checkin.component.ts @@ -121,8 +121,7 @@ export class CheckinComponent implements OnInit, AfterViewInit { this.modifiers.noop = false; this.modifiers.auto_print_holds_transits = true; } - - }); + }).then(_ => this.circ.applySettings()); } ngAfterViewInit() { diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/circ.module.ts b/Open-ILS/src/eg2/src/app/staff/share/circ/circ.module.ts index 3e9c13dbbd..8a3602b72e 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/circ/circ.module.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/circ/circ.module.ts @@ -14,6 +14,7 @@ import {RouteDialogComponent} from './route-dialog.component'; import {CopyInTransitDialogComponent} from './in-transit-dialog.component'; import {CancelTransitDialogComponent} from './cancel-transit-dialog.component'; import {BackdateDialogComponent} from './backdate-dialog.component'; +import {WorkLogService} from './work-log.service'; @NgModule({ declarations: [ @@ -41,7 +42,8 @@ import {BackdateDialogComponent} from './backdate-dialog.component'; CircComponentsComponent ], providers: [ - CircService + CircService, + WorkLogService ] }) 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 da1706cc25..6dcbcefece 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 @@ -14,6 +14,7 @@ import {CircComponentsComponent} from './components.component'; import {StringService} from '@eg/share/string/string.service'; import {ServerStoreService} from '@eg/core/server-store.service'; import {HoldingsService} from '@eg/staff/share/holdings/holdings.service'; +import {WorkLogService, WorkLogEntry} from './work-log.service'; export interface CircDisplayInfo { title?: string; @@ -208,6 +209,7 @@ export class CircService { private strings: StringService, private auth: AuthService, private holdings: HoldingsService, + private worklog: WorkLogService, private bib: BibRecordService ) {} @@ -216,6 +218,7 @@ export class CircService { 'circ.clear_hold_on_checkout', ]).then(sets => { this.clearHoldsOnCheckout = sets['circ.clear_hold_on_checkout']; + return this.worklog.loadSettings(); }); } @@ -425,7 +428,10 @@ export class CircService { result.record = payload.record; result.nonCatCirc = payload.noncat_circ; - return this.fleshCommonData(result); + return this.fleshCommonData(result).then(_ => { + this.addWorkLog(params._renewal ? 'renewal' : 'checkout', result); + return result; + }); } processCheckoutResult(result: CheckoutResult): Promise { @@ -780,7 +786,10 @@ export class CircService { result.mbts = parent_circ.billable_transaction().summary(); } - return this.fleshCommonData(result).then(_ => result); + return this.fleshCommonData(result).then(_ => { + this.addWorkLog('checkin', result); + return result; + }); } processCheckinResult(result: CheckinResult): Promise { @@ -833,6 +842,35 @@ export class CircService { return Promise.resolve(result); } + addWorkLog(action: string, result: CircResultCommon) { + const entry: WorkLogEntry = {action: action}; + + const params = result.params; + const copy = result.copy; + const patron = result.patron; + + if (copy) { + entry.item = copy.barcode(); + entry.item_id = copy.id(); + } else { + entry.item = params.copy_barcode; + entry.item_id = params.copy_id; + } + + if (patron) { + entry.patron_id = patron.id(); + entry.user = patron.family_name(); + } else { + entry.patron_id = (params as CheckoutParams).patron_id; + } + + if (result.hold) { + entry.hold_id = result.hold.id(); + } + + this.worklog.record(entry); + } + showPrecatAlert(): Promise { if (!this.suppressCheckinPopups && !this.ignoreCheckinPrecats) { // Tell the user its a precat and return the result. diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html b/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html index a937b4bb64..54bb765289 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html +++ b/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html @@ -61,3 +61,13 @@ + + + + + + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts b/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts index 76dc5f5aab..5b9a51c966 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts @@ -9,6 +9,7 @@ import {RouteDialogComponent} from './route-dialog.component'; import {CopyInTransitDialogComponent} from './in-transit-dialog.component'; import {CopyAlertManagerDialogComponent } from '@eg/staff/share/holdings/copy-alert-manager.component'; +import {WorkLogService, WorkLogEntry} from './work-log.service'; /* Container component for sub-components used by circulation actions. * @@ -37,8 +38,21 @@ export class CircComponentsComponent { @ViewChild('holdShelfStr') holdShelfStr: StringComponent; @ViewChild('catalogingStr') catalogingStr: StringComponent; - constructor(private circ: CircService) { + // Worklog string variable names have to match "worklog_{{action}}" + @ViewChild('worklog_checkout') worklog_checkout: StringComponent; + @ViewChild('worklog_checkin') worklog_checkin: StringComponent; + @ViewChild('worklog_noncat_checkout') worklog_noncat_checkout: StringComponent; + @ViewChild('worklog_renew') worklog_renew: StringComponent; + @ViewChild('worklog_requested_hold') worklog_requested_hold: StringComponent; + @ViewChild('worklog_edited_patron') worklog_edited_patron: StringComponent; + @ViewChild('worklog_registered_patron') worklog_registered_patron: StringComponent; + @ViewChild('worklog_paid_bill') worklog_paid_bill: StringComponent; + + constructor( + private worklog: WorkLogService, + private circ: CircService) { this.circ.components = this; + this.worklog.components = this; } } diff --git a/Open-ILS/src/eg2/src/app/staff/share/circ/work-log.service.ts b/Open-ILS/src/eg2/src/app/staff/share/circ/work-log.service.ts new file mode 100644 index 0000000000..724b0fbc45 --- /dev/null +++ b/Open-ILS/src/eg2/src/app/staff/share/circ/work-log.service.ts @@ -0,0 +1,93 @@ +import {Injectable} from '@angular/core'; +import {Observable, empty, from} from 'rxjs'; +import {map, concatMap, mergeMap} from 'rxjs/operators'; +import {IdlObject} from '@eg/core/idl.service'; +import {NetService} from '@eg/core/net.service'; +import {OrgService} from '@eg/core/org.service'; +import {PcrudService} from '@eg/core/pcrud.service'; +import {EventService, EgEvent} from '@eg/core/event.service'; +import {AuthService} from '@eg/core/auth.service'; +import {BibRecordService, BibRecordSummary} from '@eg/share/catalog/bib-record.service'; +import {AudioService} from '@eg/share/util/audio.service'; +import {CircEventsComponent} from './events-dialog.component'; +import {CircComponentsComponent} from './components.component'; +import {StringService} from '@eg/share/string/string.service'; +import {ServerStoreService} from '@eg/core/server-store.service'; +import {StoreService} from '@eg/core/store.service'; +import {HoldingsService} from '@eg/staff/share/holdings/holdings.service'; + +export interface WorkLogEntry { + when?: Date; + msg?: string; + action?: string; + actor?: string // staff username + item?: string; // barcode + item_id?: number; + user?: string; // patron family name + patron_id?: number; + hold_id?: number; + amount?: number; // paid amount +} + + +@Injectable() +export class WorkLogService { + + maxEntries: number = null; + maxPatrons: number = null; + components: CircComponentsComponent; + + constructor( + private store: StoreService, + private serverStore: ServerStoreService, + private auth: AuthService + ) {} + + loadSettings(): Promise { + return this.serverStore.getItemBatch([ + 'ui.admin.work_log.max_entries', + 'ui.admin.patron_log.max_entries' + ]).then(sets => { + this.maxEntries = sets['ui.admin.work_log.max_entries'] || 20; + this.maxPatrons = sets['ui.admin.patron_log.max_entries'] || 10; + }); + } + + record(entry: WorkLogEntry) { + + if (this.maxEntries === null) { + throw new Error('WorkLogService.loadSettings() required'); + return; + } + + entry.when = new Date(); + entry.actor = this.auth.user().usrname(); + entry.msg = this.components[`worklog_${entry.action}`].text; + + const workLog = this.store.getLocalItem('eg.work_log') || []; + let patronLog = this.store.getLocalItem('eg.patron_log') || []; + + workLog.push(entry); + if (workLog.lenth > this.maxEntries) { + workLog.shift(); + } + + console.log('HERE', workLog); + + this.store.setLocalItem('eg.work_log', workLog); + + if (entry.patron_id) { + // Remove existing entries that match this patron + patronLog = patronLog.filter(e => e.patron_id !== entry.patron_id); + + patronLog.push(entry); + if (patronLog.length > this.maxPatrons) { + patronLog.shift(); + } + + this.store.setLocalItem('eg.patron_log', patronLog); + } + } +} + + -- 2.11.0