<label class="font-weight-bold" i18n>Classification</label>
<div>
<eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolClass">
- <eg-combobox-entry *ngFor="let cls of volClasses"
+ <eg-combobox-entry *ngFor="let cls of volClasses"
[entryId]="cls.id()" [entryLabel]="cls.name()">
</eg-combobox-entry>
</eg-combobox>
<label class="font-weight-bold" i18n>Prefix</label>
<div>
<eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolPrefix">
- <eg-combobox-entry *ngFor="let pfx of volPrefixes"
+ <eg-combobox-entry *ngFor="let pfx of volPrefixes"
[entryId]="pfx.id()" [entryLabel]="pfx.label()">
</eg-combobox-entry>
</eg-combobox>
<label class="font-weight-bold" i18n>Suffix</label>
<div>
<eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolSuffix">
- <eg-combobox-entry *ngFor="let sfx of volSuffixes"
+ <eg-combobox-entry *ngFor="let sfx of volSuffixes"
[entryId]="sfx.id()" [entryLabel]="sfx.label()">
</eg-combobox-entry>
</eg-combobox>
<div class="p-1" [ngStyle]="{flex: flexAt(7)}">
<label class="font-weight-bold" i18n>Batch</label>
<div>
- <button class="btn btn-sm btn-outline-dark label-with-material-icon"
+ <button class="btn btn-sm btn-outline-dark label-with-material-icon"
(click)="batchVolApply()">
<span i18n>Apply</span>
<span class="material-icons">arrow_downward</span>
</div>
<div class="p-1" [ngStyle]="{flex: flexAt(8)}">
<label class="font-weight-bold" i18n>Generate Barcodes</label>
- <button class="btn btn-sm btn-outline-dark label-with-material-icon"
+ <button class="btn btn-sm btn-outline-dark label-with-material-icon"
(click)="generateBarcodes()">
<span i18n>Generate</span>
<span class="material-icons">arrow_downward</span>
</button>
</div>
- <div class="p-1" [ngStyle]="{flex: flexAt(9)}"></div>
- <div class="p-1" [ngStyle]="{flex: flexAt(10)}"></div>
+ <div class="p-1" [ngStyle]="{flex: flexSpan(9, 10)}">
+ <label class="font-weight-bold" i18n>Checkdigit</label>
+ <div class="form-check form-check-inline">
+ <input class="form-check-input" type="checkbox"
+ id="use-checkdigit" [(ngModel)]="useCheckdigit">
+ <label class="form-check-label" for="use-checkdigit" i18n>
+ Use Checkdigit
+ </label>
+ </div>
+ </div>
</div>
</div>
<div class="p-1" [ngStyle]="{flex: flexAt(3)}">
<ng-container *ngIf="copyIdx == 0">
- <eg-combobox
+ <eg-combobox
[selectedId]="volNode.target.label_class()"
[smallFormControl]="true"
- [required]="true"
+ [required]="true"
(onChange)="applyVolValue(volNode.target, 'label_class', $event ? $event.id : null)">
- <eg-combobox-entry *ngFor="let cls of volClasses"
+ <eg-combobox-entry *ngFor="let cls of volClasses"
[entryId]="cls.id()" [entryLabel]="cls.name()">
</eg-combobox-entry>
</eg-combobox>
</div>
<div class="p-1" [ngStyle]="{flex: flexAt(4)}">
<ng-container *ngIf="copyIdx == 0">
- <eg-combobox
+ <eg-combobox
[selectedId]="volNode.target.prefix()"
- [required]="true"
+ [required]="true"
[smallFormControl]="true"
(onChange)="applyVolValue(volNode.target, 'prefix', $event ? $event.id : null)">
- <eg-combobox-entry *ngFor="let pfx of volPrefixes"
+ <eg-combobox-entry *ngFor="let pfx of volPrefixes"
[entryId]="pfx.id()" [entryLabel]="pfx.label()">
</eg-combobox-entry>
</eg-combobox>
</div>
<div class="p-1" [ngStyle]="{flex: flexAt(6)}">
<ng-container *ngIf="copyIdx == 0">
- <eg-combobox
+ <eg-combobox
[selectedId]="volNode.target.suffix()"
- [required]="true"
+ [required]="true"
[smallFormControl]="true"
(onChange)="applyVolValue(volNode.target, 'suffix', $event ? $event.id : null)">
- <eg-combobox-entry *ngFor="let sfx of volSuffixes"
+ <eg-combobox-entry *ngFor="let sfx of volSuffixes"
[entryId]="sfx.id()" [entryLabel]="sfx.label()">
</eg-combobox-entry>
</eg-combobox>
id="barcode-input-{{copyNode.target.id()}}"
spellcheck="false"
[required]="true"
+ [ngClass]="{'text-danger': copyNode.target._dupe_barcode}"
+ (ngModelChange)="barcodeChanged(copyNode.target, $event)"
(keyup.enter)="selectNextBarcode(copyNode.target.id())"
(keyup.shift.enter)="selectNextBarcode(copyNode.target.id(), true)"
[ngModel]="copyNode.target.barcode()"
(ngModelChange)="applyCopyValue(copyNode.target, 'barcode', $event)"/>
+ <div *ngIf="copyNode.target._dupe_barcode"
+ class="alert alert-danger font-italic p-1" i18n>
+ Duplicate Barcode</div>
</div>
<div class="p-1" [ngStyle]="{flex: flexAt(9)}">
<input type="number" class="form-control form-control-sm"
<label i18n>N/A</label>
</ng-container>
<ng-container *ngIf="recordHasParts(volNode.target.record())">
- <eg-combobox
+ <eg-combobox
[disabled]="bibParts[volNode.target.record()].length == 0"
[selectedId]="copyNode.target.parts()[0] ? copyNode.target.parts()[0].id() : null"
[smallFormControl]="true"
import {Component, OnInit, AfterViewInit, ViewChild, Input, Renderer2} from '@angular/core';
import {Router, ActivatedRoute, ParamMap} from '@angular/router';
+import {tap} from 'rxjs/operators';
import {IdlObject} from '@eg/core/idl.service';
import {OrgService} from '@eg/core/org.service';
+import {AuthService} from '@eg/core/auth.service';
import {NetService} from '@eg/core/net.service';
import {PcrudService} from '@eg/core/pcrud.service';
import {VolCopyContext, HoldingsTreeNode} from './volcopy';
recordVolLabels: string[] = [];
+ autoBarcodeInProgress = false;
+ useCheckdigit = false;
+
constructor(
private renderer: Renderer2,
private pcrud: PcrudService,
private net: NetService,
+ private auth: AuthService,
private holdings: HoldingsService
) {}
return this.flexSettings[column];
}
+ // Returns the flex amount occupied by a span of columns.
+ flexSpan(column1: number, column2: number): number {
+ let flex = 0;
+ for (let i = column1; i <= column2; i++) {
+ flex += this.flexSettings[i];
+ }
+ return flex;
+ }
+
volCountChanged(orgNode: HoldingsTreeNode, count: number) {
console.log('vol set set to ', count);
}
'#barcode-input-' + (nextId || firstId)).select();
}
+ barcodeCanChange(copy: IdlObject): boolean {
+ // TODO
+ return true;
+ }
+
generateBarcodes() {
+ this.autoBarcodeInProgress = true;
+
+ // Autogen only replaces barcodes for items which are in
+ // certain statuses.
+ const copies = this.context.copyList()
+ .filter((copy, idx) => {
+ // During autogen we do not replace the first item,
+ // so it's status is not relevant.
+ return idx === 0 || this.barcodeCanChange(copy);
+ });
+
+ if (copies.length > 1) { // seed barcode will always be present
+ this.proceedWithAutogen(copies)
+ .then(_ => this.autoBarcodeInProgress = false);
+ };
+ }
+
+ proceedWithAutogen(copyList: IdlObject[]): Promise<any> {
+
+ const seedBarcode: string = copyList[0].barcode();
+ copyList.shift(); // Avoid replacing the seed barcode
+
+ const count = copyList.length;
+
+ return this.net.request('open-ils.cat',
+ 'open-ils.cat.item.barcode.autogen',
+ this.auth.token(), seedBarcode, count, {
+ checkdigit: this.useCheckdigit,
+ skip_dupes: true
+ }
+ ).pipe(tap(barcodes => {
+
+ copyList.forEach(copy => {
+ if (copy.barcode() !== barcodes[0]) {
+ copy.barcode(barcodes[0]);
+ copy.ischanged(true);
+ }
+ barcodes.shift();
+ });
+
+ })).toPromise();
+ }
+
+ barcodeChanged(copy: IdlObject, barcode: string) {
+ copy.barcode(barcode);
+ copy.ischanged(true);
+ copy._dupe_barcode = false;
+
+ if (barcode && !this.autoBarcodeInProgress) {
+ // Manual barcode entry requires dupe check
+
+ copy._dupe_barcode = false;
+ this.pcrud.search('acp', {
+ deleted: 'f',
+ barcode: barcode,
+ id: {'!=': copy.id()}
+ }).subscribe(resp => {
+ if (resp) { copy._dupe_barcode = true; }
+ });
+ }
}
}