LPLP1929741 Optional experimental Acq; seed data
authorBill Erickson <berickxx@gmail.com>
Wed, 14 Jul 2021 14:52:44 +0000 (10:52 -0400)
committerJane Sandberg <js7389@princeton.edu>
Sun, 2 Oct 2022 15:02:49 +0000 (08:02 -0700)
Adds and org setting and a workstation setting to 1) enable display of
experimental Angular ACQ UI's and 2) enable display of links to the
experimental UI's from search results.

Display a new menu entry "Acquisitions (Experimental)" when the org
setting is enabled.  This menu contains "Create Purchase Order" only for
now.

Copy seed data from upgrade file to seed data file.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Galen Charlton <gmc@equinoxOLI.org>
Signed-off-by: Jane Sandberg <js7389@princeton.edu>

19 files changed:
Open-ILS/src/eg2/src/app/staff/acq/search/acq-search-form.component.html
Open-ILS/src/eg2/src/app/staff/acq/search/acq-search-form.component.ts
Open-ILS/src/eg2/src/app/staff/acq/search/acq-search.module.ts
Open-ILS/src/eg2/src/app/staff/acq/search/acq-search.service.ts
Open-ILS/src/eg2/src/app/staff/acq/search/invoice-results.component.ts
Open-ILS/src/eg2/src/app/staff/acq/search/lineitem-results.component.html
Open-ILS/src/eg2/src/app/staff/acq/search/lineitem-results.component.ts
Open-ILS/src/eg2/src/app/staff/acq/search/picklist-results.component.html
Open-ILS/src/eg2/src/app/staff/acq/search/picklist-results.component.ts
Open-ILS/src/eg2/src/app/staff/acq/search/purchase-order-results.component.html
Open-ILS/src/eg2/src/app/staff/acq/search/purchase-order-results.component.ts
Open-ILS/src/eg2/src/app/staff/acq/search/resolver.service.ts
Open-ILS/src/eg2/src/app/staff/nav.component.html
Open-ILS/src/eg2/src/app/staff/nav.component.ts
Open-ILS/src/eg2/src/app/staff/resolver.service.ts
Open-ILS/src/sql/Pg/950.data.seed-values.sql
Open-ILS/src/sql/Pg/upgrade/XXXX.data.picklist-po-angular.sql
Open-ILS/src/templates/staff/navbar.tt2
Open-ILS/web/js/ui/default/staff/services/navbar.js

index 81c1d7e..b78a2bd 100644 (file)
              [ngModelOptions]="{standalone: true}" [(ngModel)]="runImmediately"/>
       <label for="retrieve-immediately" class="form-check-label" i18n>Retrieve Results Immediately</label>
     </div>
+    <div class="col-xs-3 pl-2" *ngIf="showExpAngOptions()">
+      <div class="form-check form-check-inline">
+        <input class="form-check-input" type="checkbox" 
+          name="show-exp-ang-links" id="show-exp-ang-links"
+          (change)="toggleExpSearchLinks()" [ngModel]="showExpAngLinks()"/>
+        <label class="form-check-label" for="show-exp-ang-links" i18n>
+          Activate Experimental Links
+        </label>
+      </div>
+    </div>
   </div>
 </form>
 </div>
index 1ddc94f..0f0646f 100644 (file)
@@ -4,7 +4,7 @@ import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {PcrudService} from '@eg/core/pcrud.service';
 import {StringComponent} from '@eg/share/string/string.component';
 import {ToastService} from '@eg/share/toast/toast.service';
-import {AcqSearchTerm, AcqSearch} from './acq-search.service';
+import {AcqSearchService, AcqSearchTerm, AcqSearch} from './acq-search.service';
 import {ServerStoreService} from '@eg/core/server-store.service';
 
 @Component({
@@ -47,6 +47,7 @@ export class AcqSearchFormComponent implements OnInit, OnChanges {
         private store: ServerStoreService,
         private idl: IdlService,
         private toast: ToastService,
+        private acqSearch: AcqSearchService
     ) {}
 
     ngOnInit() {
@@ -239,4 +240,18 @@ export class AcqSearchFormComponent implements OnInit, OnChanges {
     saveRunImmediately() {
         return this.store.setItem(this.runImmediatelySetting, this.runImmediately);
     }
+
+    showExpAngOptions(): boolean {
+        return this.acqSearch.angSelectionEnabled;
+    }
+
+    showExpAngLinks(): boolean {
+        return this.acqSearch.angSearchLinksEnabled;
+    }
+
+    toggleExpSearchLinks() {
+        this.acqSearch.angSearchLinksEnabled = !this.acqSearch.angSearchLinksEnabled;
+        this.store.setItem('ui.staff.angular_acq_search.enabled',
+            this.acqSearch.angSearchLinksEnabled);
+    }
 }
index 4dc2251..1fea224 100644 (file)
@@ -11,6 +11,7 @@ import {PicklistCreateDialogComponent} from './picklist-create-dialog.component'
 import {PicklistCloneDialogComponent} from './picklist-clone-dialog.component';
 import {PicklistDeleteDialogComponent} from './picklist-delete-dialog.component';
 import {PicklistMergeDialogComponent} from './picklist-merge-dialog.component';
+import {AcqSearchService} from './acq-search.service';
 
 @NgModule({
   declarations: [
@@ -28,7 +29,8 @@ import {PicklistMergeDialogComponent} from './picklist-merge-dialog.component';
   imports: [
     StaffCommonModule,
     AcqSearchRoutingModule
-  ]
+  ],
+  providers: [AcqSearchService]
 })
 
 export class AcqSearchModule {
index e25495c..b1367da 100644 (file)
@@ -9,6 +9,7 @@ import {Pager} from '@eg/share/util/pager';
 import {IdlObject} from '@eg/core/idl.service';
 import {EventService} from '@eg/core/event.service';
 import {AttrDefsService} from './attr-defs.service';
+import {ServerStoreService} from '@eg/core/server-store.service';
 
 const baseIdlClass = {
     lineitem: 'jub',
@@ -108,11 +109,15 @@ export class AcqSearchService {
     _conjunction = 'all';
     firstRun = true;
 
+    angSelectionEnabled = false;
+    angSearchLinksEnabled = false;
+
     constructor(
         private net: NetService,
         private evt: EventService,
         private auth: AuthService,
         private pcrud: PcrudService,
+        private serverStore: ServerStoreService,
         private attrDefs: AttrDefsService
     ) {
         this.firstRun = true;
@@ -281,4 +286,15 @@ export class AcqSearchService {
         };
         return gridSource;
     }
+
+    loadUiPrefs(): Promise<any> {
+        return this.serverStore.getItemBatch([
+            'ui.staff.angular_acq_selection.enabled',
+            'ui.staff.angular_acq_search.enabled'
+        ]).then(sets => {
+            this.angSelectionEnabled = sets['ui.staff.angular_acq_selection.enabled'];
+            this.angSearchLinksEnabled =
+              sets['ui.staff.angular_acq_search.enabled'] && this.angSelectionEnabled;
+        });
+    }
 }
index e187963..13c22cf 100644 (file)
@@ -16,8 +16,7 @@ import {AcqSearchFormComponent} from './acq-search-form.component';
 
 @Component({
   selector: 'eg-invoice-results',
-  templateUrl: 'invoice-results.component.html',
-  providers: [AcqSearchService]
+  templateUrl: 'invoice-results.component.html'
 })
 export class InvoiceResultsComponent implements OnInit {
 
index bfd1652..9b39ef3 100644 (file)
@@ -3,32 +3,67 @@
   defaultSearchSetting="eg.acq.search.default.lineitems"></eg-acq-search-form>
 
 <ng-template #idTmpl let-lineitem="row">
-  <a *ngIf="lineitem.purchase_order()" 
-     routerLink="/staff/acq/po/{{lineitem.purchase_order().id()}}"
-     fragment="{{lineitem.id()}}" target="_blank">
-    {{lineitem.id()}}
-  </a>
-  <a *ngIf="lineitem.picklist() && !lineitem.purchase_order()" 
-     routerLink="/staff/acq/picklist/{{lineitem.picklist().id()}}"
-     fragment="{{lineitem.id()}}" target="_blank">
-    {{lineitem.id()}}
-  </a>
+
+  <ng-container *ngIf="showExpAngLinks(); else legacyId">
+    <a *ngIf="lineitem.purchase_order()" 
+      routerLink="/staff/acq/po/{{lineitem.purchase_order().id()}}"
+      fragment="{{lineitem.id()}}" target="_blank">
+      {{lineitem.id()}}
+    </a>
+    <a *ngIf="lineitem.picklist() && !lineitem.purchase_order()" 
+      routerLink="/staff/acq/picklist/{{lineitem.picklist().id()}}"
+      fragment="{{lineitem.id()}}" target="_blank">
+      {{lineitem.id()}}
+   </a>
+  </ng-container>
+
+  <ng-template #legacyId>
+    <a *ngIf="lineitem.purchase_order()" 
+      href="/eg/staff/acq/legacy/po/view/{{lineitem.purchase_order().id()}}?focus_li={{lineitem.id()}}"
+      target="_blank">
+      {{lineitem.id()}}
+    </a>
+    <a *ngIf="lineitem.picklist() && !lineitem.purchase_order()" 
+      href="/eg/staff/acq/legacy/picklist/view/{{lineitem.picklist().id()}}?focus_li={{lineitem.id()}}"
+      target="_blank">
+      {{lineitem.id()}}
+    </a>
+  </ng-template>
 </ng-template>
 
 <ng-template #poTmpl let-lineitem="row">
-  <a *ngIf="lineitem.purchase_order()" 
-     routerLink="/staff/acq/po/{{lineitem.purchase_order().id()}}"
-     fragment="{{lineitem.id()}}" target="_blank">
-    {{lineitem.purchase_order().name()}}
-  </a>
+  <ng-container *ngIf="showExpAngLinks(); else legacyPo">
+    <a *ngIf="lineitem.purchase_order()" 
+      routerLink="/staff/acq/po/{{lineitem.purchase_order().id()}}"
+      fragment="{{lineitem.id()}}" target="_blank">
+      {{lineitem.purchase_order().name()}}
+    </a>
+  </ng-container>
+  <ng-template #legacyPo>
+    <a *ngIf="lineitem.purchase_order()" 
+      href="/eg/staff/acq/legacy/po/view/{{lineitem.purchase_order().id()}}?focus_li={{lineitem.id()}}"
+      target="_blank">
+      {{lineitem.purchase_order().name()}}
+    </a>
+  </ng-template>
 </ng-template>
 
 <ng-template #plTmpl let-lineitem="row">
-  <a *ngIf="lineitem.picklist()"
-     routerLink="/staff/acq/picklist/{{lineitem.picklist().id()}}"
-     fragment="{{lineitem.id()}}" target="_blank">
-    {{lineitem.picklist().name()}}
-  </a>
+  <ng-container *ngIf="showExpAngLinks(); else legacyPl">
+    <a *ngIf="lineitem.picklist()"
+      routerLink="/staff/acq/picklist/{{lineitem.picklist().id()}}"
+      fragment="{{lineitem.id()}}" target="_blank">
+      {{lineitem.picklist().name()}}
+   </a>
+  </ng-container>
+
+  <ng-template #legacyPl>
+    <a *ngIf="lineitem.picklist()" 
+      href="/eg/staff/acq/legacy/picklist/view/{{lineitem.picklist().id()}}?focus_li={{lineitem.id()}}"
+      target="_blank">
+      {{lineitem.picklist().name()}}
+    </a>
+  </ng-template>
 </ng-template>
 
 <ng-template #liAttrTmpl let-lineitem="row" let-col="col">
     <li *ngIf="lineitem.eg_bib_id()">
       <a routerLink="/staff/catalog/record/{{lineitem.eg_bib_id()}}"
          target="_blank" i18n>Catalog</a></li>
-    <li><a routerLink="/staff/acq/lineitem/{{lineitem.id()}}/worksheet"
-           target="_blank" i18n>Worksheet</a></li>
+    <li>
+      <ng-container *ngIf="showExpAngLinks(); else legacyWs">
+        <a routerLink="/staff/acq/lineitem/{{lineitem.id()}}/worksheet"
+          target="_blank" i18n>Worksheet</a>
+      </ng-container>
+      <ng-template #legacyWs>
+        <a href="/eg/staff/acq/legacy/lineitem/worksheet/{{lineitem.id()}}"
+           target="_blank" i18n>Worksheet</a>
+      </ng-template>
+    </li>
+
     <li *ngIf="lineitem.purchase_order()">
-      <a routerLink="/staff/acq/po/{{lineitem.purchase_order().id()}}"
-          target="_blank" i18n>Purchase Order</a></li>
+      <ng-container *ngIf="showExpAngLinks(); else legacyPo2">
+        <a routerLink="/staff/acq/po/{{lineitem.purchase_order().id()}}"
+          target="_blank" i18n>Purchase Order</a>
+      </ng-container>
+      <ng-template #legacyPo2>
+        <a href="/eg/staff/acq/legacy/po/view/{{lineitem.purchase_order().id()}}"
+          target="_blank" i18n>Purchase Order</a>
+      </ng-template>
+    </li>
     <li><a href="/eg/staff/acq/requests/lineitem/{{lineitem.id()}}"
            target="_blank" i18n>Requests</a></li>
     <li>
       <a routerLink="/staff/cat/vandelay/queue/bib/{{lineitem.queued_record().queue()}}"
         target="_blank" i18n>Queue</a></li>
     <li *ngIf="lineitem.picklist()">
-      <a routerLink="/staff/acq/picklist/{{lineitem.picklist().id()}}"
-        target="_blank" i18n>Selection List</a></li>
+      <ng-container *ngIf="showExpAngLinks(); else legacyPl2">
+        <a routerLink="/staff/acq/picklist/{{lineitem.picklist().id()}}"
+          target="_blank" i18n>Selection List</a>
+      </ng-container>
+      <ng-template #legacyPl2>
+        <a href="/eg/staff/acq/legacy/picklist/view/{{lineitem.picklist().id()}}"
+          target="_blank" i18n>Selection List</a>
+      </ng-template>
+    </li>
   </ul>
 </ng-template>
 
index 044b3e2..6c757f8 100644 (file)
@@ -13,8 +13,7 @@ import {AcqSearchFormComponent} from './acq-search-form.component';
 
 @Component({
   selector: 'eg-lineitem-results',
-  templateUrl: 'lineitem-results.component.html',
-  providers: [AcqSearchService]
+  templateUrl: 'lineitem-results.component.html'
 })
 export class LineitemResultsComponent implements OnInit {
 
@@ -71,4 +70,8 @@ export class LineitemResultsComponent implements OnInit {
     showRow(row: any) {
         window.open('/eg/staff/acq/legacy/lineitem/worksheet/' + row.id(), '_blank');
     }
+
+    showExpAngLinks(): boolean {
+        return this.acqSearch.angSearchLinksEnabled;
+    }
 }
index 612b5a0..9aaeea0 100644 (file)
 </eg-string>
 
 <ng-template #nameTmpl let-selectionlist="row">
-  <a routerLink="/staff/acq/picklist/{{selectionlist.id()}}" target="_blank">
-    {{selectionlist.name()}}
-  </a>
+  <ng-container *ngIf="showExpAngLinks(); else legacyLinks">
+    <a routerLink="/staff/acq/picklist/{{selectionlist.id()}}" target="_blank">
+      {{selectionlist.name()}}
+    </a>
+  </ng-container>
+  <ng-template #legacyLinks>
+    <a href="/eg/staff/acq/legacy/picklist/view/{{selectionlist.id()}}"
+      target="_blank">
+      {{selectionlist.name()}}
+    </a>
+  </ng-template>
 </ng-template>
 
 <eg-picklist-create-dialog #picklistCreateDialog>
index 899f0ca..4fafe83 100644 (file)
@@ -20,8 +20,7 @@ import {AcqSearchFormComponent} from './acq-search-form.component';
 
 @Component({
   selector: 'eg-picklist-results',
-  templateUrl: 'picklist-results.component.html',
-  providers: [AcqSearchService]
+  templateUrl: 'picklist-results.component.html'
 })
 export class PicklistResultsComponent implements OnInit {
 
@@ -86,6 +85,14 @@ export class PicklistResultsComponent implements OnInit {
         };
     }
 
+    showExpAngOptions(): boolean {
+        return this.acqSearch.angSelectionEnabled;
+    }
+
+    showExpAngLinks(): boolean {
+        return this.acqSearch.angSearchLinksEnabled;
+    }
+
     openCreateDialog() {
         this.picklistCreateDialog.open().subscribe(
             modified => {
index 7f8a81d..6798708 100644 (file)
@@ -4,10 +4,17 @@
   defaultSearchSetting="eg.acq.search.default.purchaseorders"></eg-acq-search-form>
 
 <ng-template #nameTmpl let-purchaseorder="row">
-  <a href="/eg/staff/acq/legacy/po/view/{{purchaseorder.id()}}"
-     target="_blank">
-    {{purchaseorder.name()}}
-  </a>
+  <ng-container *ngIf="showExpAngLinks(); else legacyPo">
+    <a routerLink="/staff/acq/po/{{purchaseorder.id()}}" target="_blank">
+      {{purchaseorder.name()}}
+    </a>
+  </ng-container>
+  <ng-template #legacyPo>
+    <a href="/eg/staff/acq/legacy/po/view/{{purchaseorder.id()}}"
+      target="_blank">
+      {{purchaseorder.name()}}
+    </a>
+  </ng-template>
 </ng-template>
 
 <ng-template #providerTmpl let-purchaseorder="row">
index 81e7db5..b4556d8 100644 (file)
@@ -14,7 +14,6 @@ import {AcqSearchFormComponent} from './acq-search-form.component';
 @Component({
   selector: 'eg-purchase-order-results',
   templateUrl: 'purchase-order-results.component.html',
-  providers: [AcqSearchService]
 })
 export class PurchaseOrderResultsComponent implements OnInit {
 
@@ -65,4 +64,9 @@ export class PurchaseOrderResultsComponent implements OnInit {
             this.purchaseOrderResultsGrid.reload();
         });
     }
+
+    showExpAngLinks(): boolean {
+        return this.acqSearch.angSearchLinksEnabled;
+    }
+
 }
index d155e52..c3b559d 100644 (file)
@@ -2,6 +2,7 @@ import {Injectable} from '@angular/core';
 import {Router, Resolve, RouterStateSnapshot,
         ActivatedRouteSnapshot} from '@angular/router';
 import {AttrDefsService} from './attr-defs.service';
+import {AcqSearchService} from './acq-search.service';
 
 @Injectable()
 export class AttrDefsResolver implements Resolve<Promise<any[]>> {
@@ -11,15 +12,15 @@ export class AttrDefsResolver implements Resolve<Promise<any[]>> {
     constructor(
         private router: Router,
         private attrDefs: AttrDefsService,
+        private acqSearch: AcqSearchService
     ) {}
 
     resolve(
         route: ActivatedRouteSnapshot,
         state: RouterStateSnapshot): Promise<any[]> {
 
-        return Promise.all([
-            this.attrDefs.fetchAttrDefs()
-        ]);
+        return this.attrDefs.fetchAttrDefs()
+        .then(_ => this.acqSearch.loadUiPrefs());
     }
 
 }
index af3a9fb..95bd530 100644 (file)
       </div>
     </div>
 
+    <div class="navbar-nav" *ngIf="showAngularAcq">
+      <div ngbDropdown class="nav-item dropdown">
+        <a ngbDropdownToggle i18n class="nav-link dropdown-toggle">
+          Acquisitions (Experimental)
+        </a>
+        <div class="dropdown-menu" ngbDropdownMenu>
+          <a class="dropdown-item" 
+            routerLink="/staff/acq/po/create">
+            <span class="material-icons" aria-hidden="true">add_shopping_cart</span>
+            <span i18n>Create Purchase Order</span>
+          </a>
+        </div>
+      </div>
+    </div>
+
     <div class="navbar-nav">
       <div ngbDropdown class="nav-item dropdown">
         <a ngbDropdownToggle i18n class="nav-link dropdown-toggle">
index 8c421e8..1de372d 100644 (file)
@@ -25,6 +25,7 @@ export class StaffNavComponent implements OnInit, OnDestroy {
 
     // When active, show a link to the traditional staff catalog
     showTraditionalCatalog = true;
+    showAngularAcq: boolean;
     curbsideEnabled: boolean;
 
     @ViewChild('navOpChange', {static: false}) opChange: OpChangeComponent;
@@ -58,9 +59,16 @@ export class StaffNavComponent implements OnInit, OnDestroy {
         // Avoid attempts to fetch org settings if the user has not yet
         // logged in (e.g. this is the login page).
         if (this.user()) {
+            // Note these are all pre-cached by our resolver.
+            // Batching not required.
             this.org.settings('ui.staff.traditional_catalog.enabled')
             .then(settings => this.showTraditionalCatalog =
                 Boolean(settings['ui.staff.traditional_catalog.enabled']));
+
+            this.org.settings('ui.staff.angular_acq_selection.enabled')
+            .then(settings => this.showAngularAcq =
+                Boolean(settings['ui.staff.angular_acq_selection.enabled']));
+
             this.org.settings('circ.curbside')
             .then(settings => this.curbsideEnabled =
                 Boolean(settings['circ.curbside']));
index a627a44..13969a6 100644 (file)
@@ -141,6 +141,8 @@ export class StaffResolver implements Resolve<Observable<any>> {
             'webstaff.format.dates',
             'webstaff.format.date_and_time',
             'ui.staff.max_recent_patrons',
+            'circ.curbside', // navbar
+            'ui.staff.angular_acq_selection.enabled', // navbar
             'ui.staff.angular_catalog.enabled' // navbar
         ]).then(settings => {
             // Avoid clobbering defaults
index 8988dd5..c9eece1 100644 (file)
@@ -21916,6 +21916,44 @@ VALUES (
 
 INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
 VALUES (
+    'eg.grid.acq.lineitem.history', 'gui', 'object',
+    oils_i18n_gettext(
+        'eg.grid.acq.lineitem.history',
+        'Grid Config: Acq Lineitem History',
+        'cwst', 'label'
+    )
+), (
+    'eg.grid.acq.po.history', 'gui', 'object',
+    oils_i18n_gettext(
+        'eg.grid.acq.po.history',
+        'Grid Config: Acq PO History',
+        'cwst', 'label'
+    )
+), (
+    'eg.grid.acq.po.edi_messages', 'gui', 'object',
+    oils_i18n_gettext(
+        'eg.grid.acq.po.edi_messages',
+        'Grid Config: Acq PO EDI Messages',
+        'cwst', 'label'
+    )
+), (
+    'acq.lineitem.page_size', 'gui', 'integer',
+    oils_i18n_gettext(
+        'acq.lineitem.page_size',
+        'ACQ Lineitem List Page Size',
+        'cwst', 'label'
+    )
+), (
+    'ui.staff.angular_acq_search.enabled', 'gui', 'bool',
+    oils_i18n_gettext(
+        'ui.staff.angular_acq_search.enabled',
+        'Enable Experimental ACQ Selection/Purchase Search Interface Links',
+        'cwst', 'label'
+    )
+);
+
+INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
+VALUES (
     'eg.cat.volcopy.defaults', 'cat', 'object',
     oils_i18n_gettext(
         'eg.cat.volcopy.defaults',
@@ -21924,6 +21962,16 @@ VALUES (
     )
 );
 
+INSERT INTO config.org_unit_setting_type (name, grp, datatype, label)
+VALUES (
+    'ui.staff.angular_acq_selection.enabled', 'gui', 'bool',
+    oils_i18n_gettext(
+        'ui.staff.angular_acq_selection.enabled',
+        'Enable Experimental ACQ Selection/Purchase Interfaces',
+        'cwst', 'label'
+    )
+);
+
 INSERT into config.org_unit_setting_type
     (name, grp, label, description, datatype)
     VALUES (
@@ -22226,3 +22274,123 @@ VALUES (
     )
 );
 
+INSERT INTO config.print_template
+    (id, name, label, owner, active, locale, template)
+VALUES (
+    4, 'lineitem_worksheet', 'Lineitem Worksheet', 1, TRUE, 'en-US',
+$TEMPLATE$
+[%- 
+  USE money=format('%.2f');
+  SET li = template_data.lineitem;
+  SET title = '';
+  SET author = '';
+  FOREACH attr IN li.attributes;
+    IF attr.attr_type == 'lineitem_marc_attr_definition';
+      IF attr.attr_name == 'title';
+        title = attr.attr_value;
+      ELSIF attr.attr_name == 'author';
+        author = attr.attr_value;
+      END;
+    END;
+  END;
+-%]
+
+<div>Title: [% title.substr(0, 80) %][% IF title.length > 80 %]...[% END %]</div>
+<div>Author: [% author %]</div>
+<div>Item Count: [% li.lineitem_details.size %]</div>
+<div>Lineitem ID: [% li.id %]</div>
+<div>PO # : [% li.purchase_order%]</div>
+<div>Est. Price: [% money(li.estimated_unit_price) %]</div>
+
+$TEMPLATE$
+);
+
+INSERT INTO config.print_template
+    (id, name, label, owner, active, locale, template)
+VALUES (5, 'purchase_order', 'Purchase Order', 1, TRUE, 'en-US', 
+$TEMPLATE$
+
+[%- 
+  USE date;
+  USE String;
+  USE money=format('%.2f');
+  SET po = template_data.po;
+
+  # find a lineitem attribute by name and optional type
+  BLOCK get_li_attr;
+    FOR attr IN li.attributes;
+      IF attr.attr_name == attr_name;
+        IF !attr_type OR attr_type == attr.attr_type;
+          attr.attr_value;
+          LAST;
+        END;
+      END;
+    END;
+  END;
+
+  BLOCK get_li_order_attr_value;
+    FOR attr IN li.attributes;
+      IF attr.order_ident == 't';
+        attr.attr_value;
+        LAST;
+      END;
+    END;
+  END;
+-%]
+
+<table style="width:100%">
+  <thead>
+    <tr>
+      <th>PO#</th>
+      <th>Line#</th>
+      <th>ISBN / Item # / Charge Type</th>
+      <th>Title</th>
+      <th>Author</th>
+      <th>Pub Info</th>
+      <th>Quantity</th>
+      <th>Unit Price</th>
+      <th>Line Total</th>
+    </tr>
+  </thead>
+  <tbody>
+[% 
+  SET subtotal = 0;
+  FOR li IN po.lineitems;
+
+    SET idval = '';
+    IF vendnum != '';
+      idval = PROCESS get_li_attr attr_name = 'vendor_num';
+    END;
+    IF !idval;
+      idval = PROCESS get_li_order_attr_value;
+    END;
+-%]
+    <tr>
+      <td>[% po.id %]</td>
+      <td>[% li.id %]</td>
+      <td>[% idval %]</td>
+      <td>[% PROCESS get_li_attr attr_name = 'title' %]</td>
+      <td>[% PROCESS get_li_attr attr_name = 'author' %]</td>
+      <td>
+        <div>
+          [% PROCESS get_li_attr attr_name = 'publisher' %], 
+          [% PROCESS get_li_attr attr_name = 'pubdate' %]
+        </div>
+        <div>Edition: [% PROCESS get_li_attr attr_name = 'edition' %]</div>
+      </td>
+      [%- 
+        SET count = li.lineitem_details.size;
+        SET price = li.estimated_unit_price;
+        SET itotal = (price * count);
+      %]
+      <td>[% count %]</td>
+      <td>[% money(price) %]</td>
+      <td>[% money(litotal) %]</td>
+    </tr>
+  [% END %]
+
+  </tbody>
+</table>
+
+$TEMPLATE$
+);
index 674d1a3..242da10 100644 (file)
@@ -31,8 +31,26 @@ VALUES (
         'ACQ Lineitem List Page Size',
         'cwst', 'label'
     )
+), (
+    'ui.staff.angular_acq_search.enabled', 'gui', 'bool',
+    oils_i18n_gettext(
+        'ui.staff.angular_acq_search.enabled',
+        'Enable Experimental ACQ Selection/Purchase Search Interface Links',
+        'cwst', 'label'
+    )
 );
 
+INSERT INTO config.org_unit_setting_type (name, grp, datatype, label)
+VALUES (
+    'ui.staff.angular_acq_selection.enabled', 'gui', 'bool',
+    oils_i18n_gettext(
+        'ui.staff.angular_acq_selection.enabled',
+        'Enable Experimental ACQ Selection/Purchase Interfaces',
+        'cwst', 'label'
+    )
+);
+
+
 INSERT INTO config.print_template
     (id, name, label, owner, active, locale, template)
 VALUES (
index 9e22ed0..f241676 100644 (file)
        </ul>
       </li>
 
+      <!-- acquisitions experimental -->
+      <li class="dropdown" uib-dropdown>
+        <a href uib-dropdown-toggle>[% l('Acquisitions (Experimental)') %]<b class="caret" 
+          aria-hidden="true"></b>
+        </a>
+        <ul uib-dropdown-menu>
+          <li>
+            <a href="/eg2/staff/acq/po/create">
+              <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
+              [% l('Create Purchase Order') %]
+            </a>
+          </li>
+        </ul>
+      </li>
+
+
       <!-- booking -->
       <li class="dropdown" uib-dropdown>
         <a href uib-dropdown-toggle>[% l('Booking') %]<b class="caret" 
index e6d506c..feae878 100644 (file)
@@ -123,6 +123,7 @@ angular.module('egCoreMod')
                             egCore.org.settings([
                                 'ui.staff.max_recent_patrons',
                                 'ui.staff.traditional_catalog.enabled',
+                                'ui.staff.angular_acq_selection.enabled',
                                 'circ.curbside'
                             ]).then(function(s) {
                                 var val = s['ui.staff.max_recent_patrons'];
@@ -131,6 +132,8 @@ angular.module('egCoreMod')
 
                                 val = s['ui.staff.traditional_catalog.enabled'];
                                 $scope.showTraditionalCatalog = (val !== false);
+                                $scope.showAngularAcq =
+                                    s['ui.staff.angular_acq_selection.enabled'];
                                 $scope.enableCurbside = 
                                     s['circ.curbside'];
                             }).then(function() {