LP1904036 billing uses flat data service
authorBill Erickson <berickxx@gmail.com>
Mon, 19 Apr 2021 16:44:13 +0000 (12:44 -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/patron/billing-history.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.html
Open-ILS/src/eg2/src/app/staff/circ/patron/bills.component.ts
Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm

index 66e1e24..4b3f0f0 100644 (file)
   </ng-container>
 </ng-template>
 
-<ng-template #callNumberTemplate let-r="row">
-  <ng-container *ngIf="r.volume">
-    {{r.volume.prefix().label()}} {{r.volume.label()}} {{r.volume.suffix().label()}}
-  </ng-container>
-  <ng-container *ngIf="!r.volume" i18n>UNCATALOGED</ng-container>
-</ng-template>
-
 
 <ul ngbNav #nav="ngbNav" class="nav-tabs" [(activeId)]="tab">
   <li ngbNavItem="transactions">
@@ -55,6 +48,7 @@
       <eg-grid idlClass="mbt" #xactsGrid
         persistKey="circ.patron.billhistory_xacts"
         (onRowActivate)="showStatement($event)"
+        [showDeclaredFieldsOnly]="true"
         [reloadOnColumnChange]="true"
         [dataSource]="xactsDataSource" [sortable]="true">
 
       <eg-grid idlClass="mp" #paymentsGrid
         persistKey="circ.patron.billhistory_payments"
         (onRowActivate)="showStatement($event)"
+        [showDeclaredFieldsOnly]="true"
         [reloadOnColumnChange]="true"
         [dataSource]="paymentsDataSource" [sortable]="true">
 
index 6e790ea..fe26a62 100644 (file)
 <!-- BILLS GRID -->
 
 <ng-template #titleTemplate let-r="row">
-  <ng-container *ngIf="r.record">
-    <a routerLink="/staff/catalog/record/{{r.record.id()}}">{{r.title}}</a>
+  <ng-container *ngIf="r.record_id">
+    <a routerLink="/staff/catalog/record/{{r.record_id}}">{{r.title}}</a>
   </ng-container>
   <ng-container *ngIf="!r.record">{{r.title}}</ng-container>
 </ng-template>
 
 <ng-template #barcodeTemplate let-r="row">
-  <ng-container *ngIf="r.copy">
-    <a href="/eg/staff/cat/item/{{r.copy.id()}}">{{r.copy.barcode()}}</a>
+  <ng-container *ngIf="r.copy_id">
+    <a href="/eg/staff/cat/item/{{r.copy_id}}">{{r.copy_barcode}}</a>
   </ng-container>
 </ng-template>
 
-<ng-template #callNumberTemplate let-r="row">
-  <ng-container *ngIf="r.volume">
-    {{r.volume.prefix().label()}} {{r.volume.label()}} {{r.volume.suffix().label()}}
-  </ng-container>
-  <ng-container *ngIf="!r.volume" i18n>UNCATALOGED</ng-container>
-</ng-template>
-
-<eg-grid #billGrid [dataSource]="gridDataSource"
+<eg-grid #billGrid idlClass="mbt" [dataSource]="gridDataSource"
   persistKey="circ.patron.bills" [sortable]="true" 
-  [useLocalSort]="true" (onRowActivate)="showStatement($event)"
+  (onRowActivate)="showStatement($event)"
+  [reloadOnColumnChange]="true"
+  [showDeclaredFieldsOnly]="true"
   [cellTextGenerator]="cellTextGenerator">
 
   <eg-grid-toolbar-button i18n-label label="Add Billing"
 
   <!-- COLUMNS -->
 
-  <eg-grid-column path="xact.id" [index]="true" label="Bill #" i18n-label>
-  </eg-grid-column>
+  <eg-grid-column path="id" [index]="true" [required]="true" 
+    label="Bill #" i18n-label> </eg-grid-column>
 
-  <eg-grid-column path="xact.xact_start" datatype="timestamp" [datePlusTime]="true"
+  <eg-grid-column path="xact_start" datatype="timestamp" [datePlusTime]="true"
     label="Start" i18n-label></eg-grid-column>
 
-  <eg-grid-column path="xact.summary.xact_type"
+  <eg-grid-column path="summary.xact_type"
     label="Type" i18n-label></eg-grid-column>
 
-  <eg-grid-column path="xact.summary.last_billing_type"
+  <eg-grid-column path="summary.last_billing_type"
     label="Last Billing Type" i18n-label></eg-grid-column>
 
-  <eg-grid-column path="billingLocation"
+  <eg-grid-column name="billingLocation"
     label="Billing Location" i18n-label></eg-grid-column>
 
-  <eg-grid-column path="call_number" label="Call Number" i18n-label
-    [cellTemplate]="callNumberTemplate"></eg-grid-column>
+  <eg-grid-column name="call_number_label"
+    path="circulation.target_copy.call_number.label" 
+    i18n-label label="Call Number" [hidden]="true"></eg-grid-column>
+
+  <eg-grid-column path="circulation.target_copy.call_number.prefix.label" 
+    i18n-label label="CN Prefix" [hidden]="true"></eg-grid-column>
+  <eg-grid-column path="circulation.target_copy.call_number.suffix.label" 
+    i18n-label label="CN Suffix" [hidden]="true"></eg-grid-column>
 
   <eg-grid-column name="copy_barcode" label="Item Barcode" i18n-label
-    [cellTemplate]="barcodeTemplate"></eg-grid-column>
+    path="circulation.target_copy.barcode" [cellTemplate]="barcodeTemplate">
+  </eg-grid-column>
 
-  <eg-grid-column path="copy.location.name" label="Shelving Location"
-    i18n-label></eg-grid-column>
+  <eg-grid-column name="copy_id" path="circulation.target_copy.id" 
+    [required]="true" [hidden]="true"></eg-grid-column>
 
-  <eg-grid-column name="title" label="Title" i18n-label
-    [cellTemplate]="titleTemplate"></eg-grid-column>
+  <eg-grid-column path="circulation.target_copy.location.name" 
+    label="Shelving Location" i18n-label></eg-grid-column>
 
-  <eg-grid-column path="xact.summary.balance_owed" datatype="money"
-    label="Balance Owed" i18n-label></eg-grid-column>
+  <eg-grid-column i18n-label label="Title" name="title" 
+    [cellTemplate]="titleTemplate"
+    path="circulation.target_copy.call_number.record.simple_record.title">
+  </eg-grid-column>
+
+  <eg-grid-column name="record_id" 
+    path="circulation.target_copy.call_number.record.id" 
+    [required]="true" [hidden]="true"></eg-grid-column>
+
+  <eg-grid-column path="summary.balance_owed" datatype="money"
+    [required]="true" label="Balance Owed" i18n-label></eg-grid-column>
 
-  <eg-grid-column path="xact.summary.total_owed" datatype="money"
+  <eg-grid-column path="summary.total_owed" datatype="money"
     label="Total Billed" i18n-label></eg-grid-column>
 
-  <eg-grid-column path="xact.summary.total_paid" datatype="money"
+  <eg-grid-column path="summary.total_paid" datatype="money"
     label="Total Paid" i18n-label></eg-grid-column>
 
   <eg-grid-column name="paymentPending" datatype="money"
     label="Payment Pending" i18n-label></eg-grid-column>
 
-  <eg-grid-column name="author" [hidden]="true"
-    label="Author" i18n-label></eg-grid-column>
+  <eg-grid-column [hidden]="true" label="Author" i18n-label
+    path="circulation.target_copy.call_number.record.simple_record.author">
+  </eg-grid-column>
+
   <eg-grid-column path="usr" [hidden]="true"></eg-grid-column>
   <eg-grid-column path="unrecovered" [hidden]="true"></eg-grid-column>
 
index 035ffc0..4282db8 100644 (file)
@@ -11,7 +11,7 @@ import {PcrudService, PcrudContext} from '@eg/core/pcrud.service';
 import {AuthService} from '@eg/core/auth.service';
 import {ServerStoreService} from '@eg/core/server-store.service';
 import {PatronService} from '@eg/staff/share/patron/patron.service';
-import {PatronContextService, BillGridEntry} from './patron.service';
+import {PatronContextService} from './patron.service';
 import {GridDataSource, GridColumn, GridCellTextGenerator} from '@eg/share/grid/grid';
 import {GridComponent} from '@eg/share/grid/grid.component';
 import {Pager} from '@eg/share/util/pager';
@@ -26,6 +26,7 @@ import {BillingService, CreditCardPaymentParams} from '@eg/staff/share/billing/b
 import {AddBillingDialogComponent} from '@eg/staff/share/billing/billing-dialog.component';
 import {AudioService} from '@eg/share/util/audio.service';
 import {ToastService} from '@eg/share/toast/toast.service';
+import {GridFlatDataService} from '@eg/share/grid/grid-flat-data.service';
 
 @Component({
   templateUrl: 'bills.component.html',
@@ -42,7 +43,6 @@ export class BillsComponent implements OnInit, AfterViewInit {
     paymentAmount: number;
     annotatePayment = false;
     paymentNote: string;
-    entries: BillGridEntry[];
     convertChangeToCredit = false;
     receiptOnPayment = false;
     applyingPayment = false;
@@ -83,6 +83,7 @@ export class BillsComponent implements OnInit, AfterViewInit {
         private serverStore: ServerStoreService,
         private circ: CircService,
         private billing: BillingService,
+        private flatData: GridFlatDataService,
         public patronService: PatronService,
         public context: PatronContextService
     ) {}
@@ -91,23 +92,29 @@ export class BillsComponent implements OnInit, AfterViewInit {
 
         this.cellTextGenerator = {
             title: row => row.title,
-            copy_barcode: row => row.copy ? row.copy.barcode() : '',
-            call_number: row => row.volume ? row.volume.label() : ''
+            copy_barcode: row => row.copy_barcode,
+            call_number: row => row.call_number_label
         };
 
-        // The grid never fetches data directly, it only serves what
-        // we have manually retrieved.
         this.gridDataSource.getRows = (pager: Pager, sort: any[]) => {
-            if (!this.entries) { return empty(); }
 
-            const page =
-                this.entries.slice(pager.offset, pager.offset + pager.limit)
-                .filter(entry => entry !== undefined);
+            const query: any = {
+               usr: this.patronId,
+               xact_finish: null,
+               'summary.balance_owed' : {'<>' : 0}
+            };
 
-            return from(page);
+            return this.flatData.getRows(
+                this.billGrid.context, query, pager, sort)
+            .pipe(tap(row => {
+                row.paymentPending = 0;
+            }));
         };
 
-        this.loadSettings().then(_ => this.load());
+        this.pcrud.retrieve('mowbus', this.patronId).toPromise()
+        // Summary will be null for users with no billing history.
+        .then(summary => this.summary = summary || this.idl.create('mowbus'))
+        .then(_ => this.loadSettings());
     }
 
     loadSettings(): Promise<any> {
@@ -151,89 +158,6 @@ export class BillsComponent implements OnInit, AfterViewInit {
         });
     }
 
-    // In refresh mode, only fetch the requested xacts, with updated user
-    // summary, and slot them back into the entries array.
-    load(refreshXacts?: number[]): Promise<any> {
-
-        const entriesFetched: number[] = [];
-        this.gridDataSource.requestingData = true;
-
-        if (!refreshXacts) { this.entries = []; }
-
-        // Could nullify summary, but that causes a minor screen
-        // flicker as the new data loads.
-        let first = true;
-
-        return this.net.request(
-            'open-ils.actor',
-            'open-ils.actor.user.transactions.for_billing',
-            this.auth.token(), this.patronId,
-            {have_balance: true, xact_ids: refreshXacts}
-
-        ).pipe(tap(resp => {
-
-            if (first) { // 1st response is summary
-                this.summary = resp;
-                first = false;
-                return;
-            }
-
-            if (!refreshXacts) {
-                this.entries.push(this.context.formatXactForDisplay(resp));
-                return;
-            }
-
-            entriesFetched.push(resp.id());
-
-            let idx;
-            for (idx = 0; idx < this.entries.length; idx++) {
-                const entry = this.entries[idx];
-                if (entry.xact.id() === resp.id()) { break; }
-            }
-
-            if (idx < this.entries.length) {
-                // Update the existing entry
-                this.entries[idx] = this.context.formatXactForDisplay(resp);
-            } else {
-                // Adding a new transaction (e.g. from new billing)
-                this.entries.push(this.context.formatXactForDisplay(resp));
-            }
-
-        })).toPromise()
-
-        .then(_ => {
-
-            if (!this.summary) {
-                // If the patron has no billing history, there will be
-                // no money summary.
-                this.summary = this.idl.create('mus');
-            }
-
-            if (!refreshXacts) { return; }
-
-            // Refreshing means some transactions may be removed from the list
-            // Remove them from the local entries array.
-            refreshXacts.forEach(xactId => {
-                if (entriesFetched.includes(xactId)) { return; }
-
-                let idx;
-                for (idx = 0; idx < this.entries.length; idx++) {
-                    const entry = this.entries[idx];
-                    if (entry.xact.id() === xactId) { break; }
-                }
-
-                this.billGrid.context.rowSelector.deselect(xactId + '');
-                this.entries.splice(idx, 1);
-            });
-        })
-
-        .then(_ => {
-            this.gridDataSource.requestingData = false;
-            if (refreshXacts) { this.context.refreshPatron(); }
-            this.billGrid.reload();
-        });
-    }
-
     patron(): IdlObject {
         return this.context.summary ? this.context.summary.patron : null;
     }
@@ -241,13 +165,16 @@ export class BillsComponent implements OnInit, AfterViewInit {
     selectedPaymentInfo(): {owed: number, billed: number, paid: number} {
         const info = {owed : 0, billed : 0, paid : 0};
 
+        if (!this.billGrid) { return info; } // page loading
+
         this.billGrid.context.rowSelector.selected().forEach(id => {
             const row = this.billGrid.context.getRowByIndex(id);
-            const sum = row.xact.summary();
 
-            info.owed   += Number(sum.balance_owed()) * 100;
-            info.billed += Number(sum.total_owed()) * 100;
-            info.paid   += Number(sum.total_paid()) * 100;
+            if (!row) { return; } // Called mid-reload
+
+            info.owed   += Number(row['summary.balance_owed']) * 100;
+            info.billed += Number(row['summary.total_owed']) * 100;
+            info.paid   += Number(row['summary.total_paid']) * 100;
         });
 
         info.owed /= 100;
@@ -257,6 +184,7 @@ export class BillsComponent implements OnInit, AfterViewInit {
         return info;
     }
 
+
     pendingPaymentInfo(): {payment: number, change: number} {
 
         const amt = this.paymentAmount || 0;
@@ -287,7 +215,7 @@ export class BillsComponent implements OnInit, AfterViewInit {
     refundsAvailable(): number {
         let amount = 0;
         this.gridDataSource.data.forEach(row => {
-            const balance = row.xact.summary().balance_owed();
+            const balance = row['summary.balance_owed'];
             if (balance < 0) { amount += balance * 100; }
 
         });
@@ -341,7 +269,7 @@ export class BillsComponent implements OnInit, AfterViewInit {
         .then(paymentIds => this.handlePayReceipt(payments, paymentIds))
 
         // refresh affected xact IDs
-        .then(_ => this.load(payments.map(p => p[0])))
+        .then(_ => this.billGrid.reload())
 
         .then(_ => {
             this.paymentAmount = null;
@@ -357,9 +285,9 @@ export class BillsComponent implements OnInit, AfterViewInit {
 
     compilePayments(): Array<Array<number>> { // [ [xactId, payAmount], ... ]
         const payments = [];
-        this.entries.forEach(row => {
+        this.gridDataSource.data.forEach(row => {
             if (row.paymentPending) {
-                payments.push([row.xact.id(), row.paymentPending]);
+                payments.push([row.id, row.paymentPending]);
             }
         });
         return payments;
@@ -418,7 +346,7 @@ export class BillsComponent implements OnInit, AfterViewInit {
     updatePendingColumn() {
 
         // Reset...
-        this.entries.forEach(row => row.paymentPending = 0);
+        this.gridDataSource.data.forEach(row => row.paymentPending = 0);
 
         let amount = this.pendingPayment();
         let done = false;
@@ -427,7 +355,7 @@ export class BillsComponent implements OnInit, AfterViewInit {
             if (done) { return; }
 
             const row = this.billGrid.context.getRowByIndex(index);
-            const owed = Number(row.xact.summary().balance_owed());
+            const owed = Number(row['summary.balance_owed']);
 
             if (amount > owed) {
                 // Pending payment amount exceeds balance of this
@@ -448,12 +376,12 @@ export class BillsComponent implements OnInit, AfterViewInit {
         });
     }
 
-    printBills(rows: BillGridEntry[]) {
+    printBills(rows: any[]) {
         if (rows.length === 0) { return; }
 
         this.printer.print({
             templateName: 'bills_current',
-            contextData: {xacts: rows.map(r => r.xact)},
+            contextData: {xacts: rows},
             printContext: 'default'
         });
     }
@@ -481,14 +409,15 @@ export class BillsComponent implements OnInit, AfterViewInit {
         };
 
         payments.forEach(payment => {
+
             const entry =
-                this.entries.filter(e => e.xact.id() === payment[0])[0];
+                this.gridDataSource.data.filter(e => e.xact.id() === payment[0])[0];
 
             context.payments.push({
                 amount: payment[1],
-                xact: entry.xact,
+                xact: entry,
                 title: entry.title,
-                copy_barcode: entry.copy ? entry.copy.barcode() : ''
+                copy_barcode: entry.copy_barcode
             });
         });
 
@@ -505,9 +434,9 @@ export class BillsComponent implements OnInit, AfterViewInit {
 
     selectRefunds() {
         this.billGrid.context.rowSelector.clear();
-        this.entries.forEach(entry => {
-            if (entry.xact.summary().balance_owed() < 0) {
-                this.billGrid.context.toggleSelectOneRow(entry.xact.id());
+        this.gridDataSource.data.forEach(row => {
+            if (row['summary.balance_owed'] < 0) {
+                this.billGrid.context.toggleSelectOneRow(row.id);
             }
         });
     }
@@ -516,14 +445,14 @@ export class BillsComponent implements OnInit, AfterViewInit {
         this.billingDialog.newXact = true;
         this.billingDialog.open().subscribe(data => {
             if (data) {
-                this.load([data.xactId]);
+                this.billGrid.reload();
             }
         });
     }
 
-    addBillingForXact(rows: BillGridEntry[]) {
+    addBillingForXact(rows: any[]) {
         if (rows.length === 0) { return; }
-        const xactIds = rows.map(r => r.xact.id());
+        const xactIds = rows.map(r => r.id);
 
         this.billingDialog.newXact = false;
         const xactsChanged = [];
@@ -540,15 +469,15 @@ export class BillsComponent implements OnInit, AfterViewInit {
         }))
         .subscribe(null, null, () => {
             if (xactsChanged.length > 0) {
-                this.load(xactsChanged);
+                this.billGrid.reload();
             }
         });
     }
 
-    voidBillings(rows: BillGridEntry[]) {
+    voidBillings(rows: any[]) {
         if (rows.length === 0) { return; }
 
-        const xactIds = rows.map(r => r.xact.id());
+        const xactIds = rows.map(r => r.id);
         const billIds = [];
         let cents = 0;
 
@@ -584,13 +513,13 @@ export class BillsComponent implements OnInit, AfterViewInit {
 
             this.sessionVoided = (this.sessionVoided * 100 + cents) / 100;
             this.voidAmount = 0;
-            this.load(xactIds);
+            this.billGrid.reload();
         });
     }
 
-    adjustToZero(rows: BillGridEntry[]) {
+    adjustToZero(rows: any[]) {
         if (rows.length === 0) { return; }
-        const xactIds = rows.map(r => r.xact.id());
+        const xactIds = rows.map(r => r.id);
 
         this.audio.play('warning.circ.adjust_to_zero_confirmation');
 
@@ -602,7 +531,7 @@ export class BillsComponent implements OnInit, AfterViewInit {
                 'open-ils.circ.money.billable_xact.adjust_to_zero',
                 this.auth.token(), xactIds
             ).subscribe(resp => {
-                if (!this.reportError(resp)) { this.load(xactIds); }
+                if (!this.reportError(resp)) { this.billGrid.reload(); }
             });
         });
     }
@@ -622,9 +551,9 @@ export class BillsComponent implements OnInit, AfterViewInit {
     // This is functionally equivalent to selecting a neg. transaction
     // then clicking Apply Payment -- this just adds a speed bump (ditto
     // the XUL client).
-    refund(rows: BillGridEntry[]) {
+    refund(rows: any[]) {
         if (rows.length === 0) { return; }
-        const xactIds = rows.map(r => r.xact.id());
+        const xactIds = rows.map(r => r.id);
 
         this.refundDialog.open().subscribe(confirmed => {
             if (!confirmed) { return; }
@@ -633,9 +562,9 @@ export class BillsComponent implements OnInit, AfterViewInit {
         });
     }
 
-    showStatement(row: BillGridEntry) {
+    showStatement(row: any) {
         this.router.navigate(['/staff/circ/patron',
-            this.patronId, 'bills', row.xact.id(), 'statement']);
+            this.patronId, 'bills', row.id, 'statement']);
     }
 }
 
index c591ad8..56df630 100644 (file)
@@ -5349,108 +5349,4 @@ sub filter_group_entry_crud {
     }
 }
 
-
-__PACKAGE__->register_method(
-    method        => 'user_billing_xacts',
-    api_name      => 'open-ils.actor.user.transactions.for_billing',
-    signature     => {
-        desc   => q/Returns a stream of user billing data appropriate for
-            display in the user bills UI.  API is natively "authoritative"./,
-        params => [
-            {desc => 'Authentication token', type => 'string'},
-            {desc => 'User ID', type => 'number'},
-            {desc => q/Options: {
-                xact_ids: load specific transactions
-                have_balance:
-                have_charge:
-            }/, type => 'object'},
-            {desc => 'Xact IDs.  Optionally limit to specific transactions', 
-             type => 'array'}
-        ],
-        return => {
-            desc => q/First response is the user money summary, following
-                responses are fleshed billable transactions/
-        }
-    }
-);
-
-sub user_billing_xacts {
-    my ($self, $client, $auth, $user_id, $options) = @_;
-
-    $options ||= {};
-    my $xact_ids = $options->{xact_ids};
-    my $have_balance = $options->{have_balance};
-    my $have_charge = $options->{have_charge};
-    my $have_payment = $options->{have_payment};
-
-    my $e = new_editor(authtoken => $auth, xact => 1);
-    return $e->die_event unless $e->checkauth;
-
-    my $user = $e->retrieve_actor_user($user_id) or return $e->die_event;
-
-    return $e->die_event unless 
-        $e->allowed('VIEW_USER_TRANSACTIONS', $user->home_ou);
-
-    # Start with the user summary.
-    $client->respond($e->retrieve_money_open_with_balance_user_summary($user_id));
-
-    my $where = {};
-    if ($xact_ids) { $where->{id} = $xact_ids; }
-    if ($have_balance) { $where->{balance_owed} = {'<>' => 0}; }
-    if ($have_charge) { $where->{last_billing_ts} = {'<>' => undef}; }
-    if ($have_payment) { $where->{last_payment_ts} = {'<>' => undef}; }
-
-    # Even if xact_ids are specified, run this query to confirm the
-    # provided IDs are linked to the specified user and have a balance.
-    $xact_ids = $e->json_query({
-        select => {mbts => ['id']},
-        from => 'mbts',
-        where => {
-            usr => $user_id,
-            balance_owed => {'<>' => 0},
-            $xact_ids ? (id => $xact_ids) : ()
-        },
-        order_by => {mbts => {xact_start => 'asc'}}
-    });
-
-    for my $xact_id (map { $_->{id} } @$xact_ids) {
-
-        my $xact = $e->retrieve_money_billable_transaction([
-            $xact_id, {
-                flesh => 5,
-                flesh_fields => {
-                    mbt => [qw/summary circulation grocery/],
-                    circ => [qw/
-                        target_copy 
-                        workstation 
-                        checkin_workstation 
-                    /],
-                    acp =>  [qw/
-                        call_number
-                        holds_count
-                        status
-                        circ_lib
-                        location
-                        floating
-                        age_protect
-                        parts
-                    /],
-                    acpm => [qw/part/],
-                    acn =>  [qw/record owning_lib prefix suffix/],
-                    bre =>  [qw/wide_display_entry/]
-                },
-                # Avoid adding the MARXML
-                # Fleshed fields are implicitly included.
-                select => {bre => ['id']} 
-            }
-        ]);
-
-        $client->respond($xact);
-    }
-
-    $e->rollback;
-
-    return undef;
-}
-
 1;