On holdings edit screen cast cost, price, deposit as numeric when they have a value... user/lew/3_9_1_holdings_editor_fixes
authorLlewellyn Marshall <llewellyn.marshall@ncdcr.gov>
Wed, 23 Nov 2022 18:50:04 +0000 (13:50 -0500)
committerLlewellyn Marshall <llewellyn.marshall@ncdcr.gov>
Tue, 24 Jan 2023 15:09:50 +0000 (10:09 -0500)
grab all call number prefixes and suffixes from the database, filter them down based on owning library of the holding.

Do not permit editing of status when template value or holding are "magic". Do not allow a template to apply an alert_message.

Signed-off-by: Llewellyn Marshall <llewellyn.marshall@ncdcr.gov>
Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.html
Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.service.ts
Open-ILS/src/perlmods/lib/OpenILS/Application/Cat.pm

index e5f08be..9cbdd45 100644 (file)
@@ -272,6 +272,22 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
         return changeSelection[disValue] === true;
     }
 
+       copyChangePermitted(copy: IdlObject, field: string,
+            value: any) : boolean {
+               switch(field){
+                       case 'status': {
+                               return this.statusEditable([copy]) &&
+                                       !this.volcopy.copyStatIsMagic(value);   
+                       }
+                       case 'alert_message': {
+                               return false;
+                       }
+                       default: {
+                               return true;
+                       }
+               }
+       }
+
     applyCopyValue(field: string, value?: any, changeSelection?: BatchChangeSelection) {
         if (value === undefined) {
             value = this.values[field];
@@ -295,6 +311,11 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
                     return;
                 }
 
+                               // prevent unpermitted changes from going through 
+                               if(!this.copyChangePermitted(copy, field, value)){
+                                       return;
+                               }
+
                 copy[field](value);
                 copy.ischanged(true);
             });
@@ -602,6 +623,14 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
                 // May be a 'remote' location.  Fetch as needed.
                 promise = this.volcopy.getLocation(value);
             }
+                       
+                       if ((field === 'cost' || field === 'price' || field === 'deposit_amount')){
+                               // Make sure monetary fields are properly cast as numeric values
+                               // and discard if no cast possible.
+                               let n = Number(value);
+                               if(isNaN(n) || value === ''){return;}
+                               promise = Promise.resolve(n);
+                       }
 
             promise.then(val => {
                 this.applyCopyValue(field, val);
@@ -725,14 +754,15 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
         return def ? def.label : '';
     }
 
-    // Returns false if any items are in magic statuses
-    statusEditable(): boolean {
-        const copies = this.context.copyList();
-        for (let idx = 0; idx < copies.length; idx++) {
-            if (this.volcopy.copyStatIsMagic(copies[idx].status())) {
-                return false;
-            }
-        }
+    // Returns false if status is in magic statuses
+    statusEditable(c?: IdlObject[]): boolean {
+                       if(c === undefined || !c.length)
+                               c = this.context.copyList();
+                       for (let idx = 0; idx < c.length; idx++) {
+                               if (this.volcopy.copyStatIsMagic(c[idx].status())) {
+                                       return false;
+                               }
+                       }               
         return true;
     }
 
index 2e29528..f41d33b 100644 (file)
@@ -46,7 +46,7 @@
       <div><label class="font-weight-bold" i18n>Prefix</label></div>
       <div>
         <eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolPrefix">
-          <eg-combobox-entry *ngFor="let pfx of volcopy.commonData.acn_prefix"
+          <eg-combobox-entry *ngFor="let pfx of batchPrefixes()"
             [entryId]="pfx.id()" [entryLabel]="pfx.label()">
           </eg-combobox-entry>
         </eg-combobox>
@@ -73,7 +73,7 @@
       <div><label class="font-weight-bold" i18n>Suffix</label></div>
       <div>
         <eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolSuffix">
-          <eg-combobox-entry *ngFor="let sfx of volcopy.commonData.acn_suffix"
+          <eg-combobox-entry *ngFor="let sfx of batchSuffixes()"
             [entryId]="sfx.id()" [entryLabel]="sfx.label()">
           </eg-combobox-entry>
         </eg-combobox>
                 <eg-combobox-entry
                   [entryId]="-1" entryLabel="<None>" i18n-entryLabel>
                 </eg-combobox-entry>
-                <eg-combobox-entry *ngFor="let pfx of volcopy.commonData.acn_prefix"
+                <eg-combobox-entry *ngFor="let pfx of orgPrefixes(orgNode.target.id())"
                   [entryId]="pfx.id()" [entryLabel]="pfx.label()">
                 </eg-combobox-entry>
               </eg-combobox>
                 <eg-combobox-entry
                   [entryId]="-1" entryLabel="<None>" i18n-entryLabel>
                 </eg-combobox-entry>
-                <eg-combobox-entry *ngFor="let sfx of volcopy.commonData.acn_suffix"
+                <eg-combobox-entry *ngFor="let sfx of orgSuffixes(orgNode.target.id())"
                   [entryId]="sfx.id()" [entryLabel]="sfx.label()">
                 </eg-combobox-entry>
               </eg-combobox>
index 9370a07..1d2860c 100644 (file)
@@ -588,5 +588,37 @@ export class VolEditComponent implements OnInit {
             !this.volcopy.defaults.visible.batch_actions;
         this.volcopy.saveDefaults();
     }
+
+       // Retrieve call number prefixes for the work station OU
+       batchPrefixes(): IdlObject[]{
+               return this.orgPrefixes(this.auth.user().ws_ou());
+       }
+
+       // Retrieve call number suffixes for the work station OU
+       batchSuffixes(): IdlObject[]{
+               return this.orgSuffixes(this.auth.user().ws_ou());
+       }
+
+       // Given an org unit ID, find all call number prefixes belonging to
+       // the org unit, its ancestors, and its descendants
+    orgPrefixes(orgId: number): IdlObject[] {
+        let r = [];
+               this.org.fullPath(orgId,true).forEach( org => {
+                       if(this.volcopy.callNumberPrefixMap[org])
+                               this.volcopy.callNumberPrefixMap[org].forEach(prefix => r.push(prefix));
+               });
+               return r;
+    }
+
+       // Given an org unit ID, find all call number suffixes belonging to
+       // the org unit, its ancestors, and its descendants
+    orgSuffixes(orgId: number): IdlObject[] {
+        let r = [];
+               this.org.fullPath(orgId,true).forEach( org => {
+                       if(this.volcopy.callNumberSuffixMap[org])
+                               this.volcopy.callNumberSuffixMap[org].forEach(suffix => r.push(suffix));
+               });
+               return r;
+    }
 }
 
index ed023ee..960641e 100644 (file)
@@ -42,6 +42,8 @@ export class VolCopyService {
     currentContext: VolCopyContext;
 
     statCatEntryMap: {[id: number]: IdlObject} = {}; // entry id => entry
+       callNumberPrefixMap: {[key: string]: IdlObject[]} = {};
+       callNumberSuffixMap: {[key: string]: IdlObject[]} = {};
 
     templateNames: ComboboxEntry[] = [];
     templates: any = {};
@@ -107,10 +109,30 @@ export class VolCopyService {
         // specially in the markup.
         this.commonData.acn_prefix =
             this.commonData.acn_prefix.filter(pfx => pfx.id() !== -1);
-
+               // Map the call number prefixes by their owning libraries
+        this.commonData.acn_prefix.forEach(
+                       pfx => {
+                               let ol = pfx.owning_lib();
+                if (!this.callNumberPrefixMap[ol]) {
+                    this.callNumberPrefixMap[ol] = [];
+                }
+                this.callNumberPrefixMap[ol].push(pfx);                                
+                       }
+               );
+               
         this.commonData.acn_suffix =
             this.commonData.acn_suffix.filter(sfx => sfx.id() !== -1);
-
+               // Map the call number suffixes by their owning libraries
+        this.commonData.acn_suffix.forEach(
+                       sfx => {
+                               let ol = sfx.owning_lib();
+                if (!this.callNumberSuffixMap[ol]) {
+                    this.callNumberSuffixMap[ol] = [];
+                }
+                this.callNumberSuffixMap[ol].push(sfx);                                
+                       }
+               );
+               
         this.commonData.acp_status.forEach(
             stat => this.copyStatuses[stat.id()] = stat);
 
index deb7ad4..de49876 100644 (file)
@@ -2039,14 +2039,14 @@ sub volcopy_data {
     
     $client->respond({
         acn_prefix => $e->search_asset_call_number_prefix([
-            {owning_lib => $org_ids},
+            {id => {'!=' => undef}},
             {order_by => {acnp => 'label_sortkey'}}
         ])
     });
 
     $client->respond({
         acn_suffix => $e->search_asset_call_number_suffix([
-            {owning_lib => $org_ids},
+            {id => {'!=' => undef}},
             {order_by => {acns => 'label_sortkey'}}
         ])
     });