LP1904036 circ work log entries
authorBill Erickson <berickxx@gmail.com>
Tue, 20 Apr 2021 21:33:34 +0000 (17:33 -0400)
committerGalen Charlton <gmc@equinoxOLI.org>
Fri, 28 Oct 2022 00:13:32 +0000 (20:13 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Jane Sandberg <js7389@princeton.edu>
Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
Open-ILS/src/eg2/src/app/staff/circ/checkin/checkin.component.ts
Open-ILS/src/eg2/src/app/staff/share/circ/circ.module.ts
Open-ILS/src/eg2/src/app/staff/share/circ/circ.service.ts
Open-ILS/src/eg2/src/app/staff/share/circ/components.component.html
Open-ILS/src/eg2/src/app/staff/share/circ/components.component.ts
Open-ILS/src/eg2/src/app/staff/share/circ/work-log.service.ts [new file with mode: 0644]

index 5991c33..4a8a6d6 100644 (file)
@@ -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() {
index 3e9c13d..8a3602b 100644 (file)
@@ -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
     ]
 })
 
index da1706c..6dcbcef 100644 (file)
@@ -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<CheckoutResult> {
@@ -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<CheckinResult> {
@@ -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<any> {
         if (!this.suppressCheckinPopups && !this.ignoreCheckinPrecats) {
             // Tell the user its a precat and return the result.
index a937b4b..54bb765 100644 (file)
 
 <eg-copy-alert-manager #copyAlertManager></eg-copy-alert-manager>
 
+<!-- Worklog string identifiers should match #worlog_{{action}} -->
+<eg-string #worklog_checkout i18n-text text="Check Out"></eg-string>
+<eg-string #worklog_checkin i18n-text text="Check In"></eg-string>
+<eg-string #worklog_noncat_checkout i18n-text text="Noncataloged Checkout"></eg-string>
+<eg-string #worklog_renew i18n-text text="Renewal"></eg-string>
+<eg-string #worklog_requested_hold i18n-text text="Requested Hold"></eg-string>
+<eg-string #worklog_edited_patron i18n-text text="Edited Patron"></eg-string>
+<eg-string #worklog_registered_patron i18n-text text="Registered Patron"></eg-string>
+<eg-string #worklog_paid_bill i18n-text text="Paid Bill"></eg-string>
+
index 76dc5f5..5b9a51c 100644 (file)
@@ -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 (file)
index 0000000..724b0fb
--- /dev/null
@@ -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<any> {
+        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);
+        }
+    }
+}
+
+