fixing money views; adding unfulfilled holds tracker; transaction-ifying hold capture...
authormiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 22 Jul 2005 15:55:47 +0000 (15:55 +0000)
committermiker <miker@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Fri, 22 Jul 2005 15:55:47 +0000 (15:55 +0000)
git-svn-id: svn://svn.open-ils.org/ILS/trunk@1358 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/action.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/money.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/dbi.pm
Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm
Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm
Open-ILS/src/sql/Postgres/080.schema.money.sql
Open-ILS/src/sql/Postgres/090.schema.action.sql

index 60761cc..8ff2aae 100644 (file)
@@ -107,5 +107,13 @@ __PACKAGE__->columns(Essential => qw/source dest persistant_transfer target_copy
 
 #-------------------------------------------------------------------------------
 
+package action::unfulfilled_hold_list;
+use base qw/action/;
+__PACKAGE__->table('action_.unfulfilled_hold_list');
+__PACKAGE__->columns(Primary => 'id');
+__PACKAGE__->columns(Essential => qw/hold current_copy circ_lib fail_time /);
+
+#-------------------------------------------------------------------------------
+
 1;
 
index 1f3daa6..c4fe509 100644 (file)
@@ -34,7 +34,8 @@ __PACKAGE__->table('money_billable_transaction_summary');
 __PACKAGE__->columns(Primary => 'id');
 __PACKAGE__->columns(Essential => qw/xact_start usr xact_finish total_paid
                                     last_payment_ts total_owed last_billing_ts
-                                    balance_owed xact_type last_billing_note/);
+                                    balance_owed xact_type last_billing_note
+                                    last_payment_note/);
 #-------------------------------------------------------------------------------
 
 package money::billing;
index c42791d..4c1e768 100644 (file)
 
        #-------------------------------------------------------------------------------
 
+       package action::unfulfilled_hold_list;
+
+       action::unfulfilled_hold_list->sequence( 'action.unfulfilled_hold_list_id_seq' );
+       action::unfulfilled_hold_list->table('action.unfulfilled_hold_list');
+
+       #-------------------------------------------------------------------------------
+
 
 }
 
index fe69771..2255b0d 100644 (file)
@@ -400,6 +400,8 @@ sub hold_copy_targeter {
                $year, $mon, $mday, $hour, $min, $sec
        );
 
+       $self->method_lookup( 'open-ils.storage.transaction.begin')->run($client);
+
        ($statuses) = $self->method_lookup('open-ils.storage.direct.config.copy_status.search.holdable.atomic')->run('t');
 
        ($locations) = $self->method_lookup('open-ils.storage.direct.asset.copy_location.search.holdable.atomic')->run('t');
@@ -419,65 +421,91 @@ sub hold_copy_targeter {
                                                          prev_check_time => { '<=' => $expire_threshold },
                                                        },
                                                        { order_by => 'request_time,prev_check_time' } );
-                       push @$holds, @{
-                               $self->method_lookup('open-ils.storage.direct.action.hold_request.search.atomic')
+                       push @$holds, $self->method_lookup('open-ils.storage.direct.action.hold_request.search')
                                                ->run(
                                                        { capture_time => undef,
                                                          prev_check_time => undef },
-                                                       { order_by => 'request_time' } ) };
+                                                       { order_by => 'request_time' } );
                }
        } catch Error with {
                my $e = shift;
                die "Could not retrieve uncaptured hold requests:\n\n$e\n";
        };
 
-       $_->clear_current_copy for (@$holds);
-
        for my $hold (@$holds) {
-               my $copies;
-
-               my @captured_copies = [ map {$_->current_copy} @$holds ];
+               try {
+                       my $copies;
 
-               if (0) { # hold isn't check-expired
-                       # get the copies from the hold-map
-                       # and filter on "avialable"
-               } else {
                        $copies = $self->metarecord_hold_capture($hold) if ($hold->hold_type eq 'M');
                        $copies = $self->title_hold_capture($hold) if ($hold->hold_type eq 'T');
                        $copies = $self->volume_hold_capture($hold) if ($hold->hold_type eq 'V');
                        $copies = $self->copy_hold_capture($hold) if ($hold->hold_type eq 'C');
-               }
 
-               next unless (ref $copies);
+                       $client->respond("Processing hold ".$hold->id."...\n");
+                       unless (ref $copies) {
+                               $client->respond("\tNo copies available for targeting!\n");
+                               next;
+                       }
 
-               my @good_copies;
-               for my $c (@$copies) {
-                       next if ( grep {$c->id == $_} @captured_copies);
-                       push @good_copies, $c;
-               }
+                       my @good_copies;
+                       for my $c (@$copies) {
+                               next if ( grep {$c->id == $hold->current_copy} @good_copies);
+                               push @good_copies, $c if ($c);
+                       }
+
+                       $client->respond("\t".scalar(@good_copies)." (non-current) copies available for targeting...\n");
+
+                       my $old_best = $hold->current_copy;
+                       $hold->clear_current_copy;
+       
+                       if (!scalar(@good_copies)) {
+                               if ( $old_best && grep {$c->id == $hold->current_copy} @$copies ) {
+                                       $client->respond("\tPushing current_copy back onto the targeting list\n");
+                               push @good_copies, $self->method_lookup('open-ils.storage.direct.asset.copy.retrieve')->run( $old_best );
+                               } else {
+                                       $client->respond("\tcurrent_copy is no longer available for targeting... NEXT!\n");
+                                       next;
+                               }
+                       }
 
-               my $prox_list;
-               $$prox_list[0] = [grep {$_->circ_lib == $hold->pickup_lib } @$copies];
-               $copies = [grep {$_->circ_lib != $hold->pickup_lib } @$copies];
+                       my $prox_list;
+                       $$prox_list[0] = [grep {$_->circ_lib == $hold->pickup_lib } @good_copies];
+                       $copies = [grep {$_->circ_lib != $hold->pickup_lib } @good_copies];
 
-               my $best = $self->choose_nearest_copy($hold, $prox_list);
+                       my $best = $self->choose_nearest_copy($hold, $prox_list);
 
-               if (!$best) {
-                       $prox_list = $self->create_prox_list( $hold->pickup_lib, $copies );
-                       $best = $self->choose_nearest_copy($hold, $prox_list);
-               }
+                       if (!$best) {
+                               $prox_list = $self->create_prox_list( $hold->pickup_lib, $copies );
+                               $best = $self->choose_nearest_copy($hold, $prox_list);
+                       }
 
-               if ($best) {
-                       $hold->current_copy( $best->id );
-               }
+                       if ($old_best) {
+                               # hold wasn't fulfilled, record the fact
+                       
+                               $client->respond("\tHold was not (but should have been) fulfilled by ".$old_best->id.".\n");
+                               my $ufh = new Fieldmapper::action::unfulfilled_hold_list;
+                               $ufh->hold( $hold->id );
+                               $ufh->current_copy( $old_best->id );
+                               $ufh->circ_lib( $old_best->circ_lib );
+                               $self->method_lookup('open-ils.storage.direct.action.unfulfilled_hold_list.create')->run( $ufh );
+                       }
 
-               $hold->prev_check_time( 'now');
-               my ($r) = $self->method_lookup('open-ils.storage.direct.action.hold_request.update')->run( $hold );
+                       if ($best) {
+                               $hold->current_copy( $best->id );
+                               $client->respond("\tTargeting copy ".$best->id." for hold fulfillment.\n");
+                       }
 
-               $client->respond("Processed hold ".$hold->id.".  ".
-                       do{ $hold->current_copy ? "Targeting copy ".$hold->current_copy." for capture." : ''; }.
-                       "\n"
-               );
+                       $hold->prev_check_time( 'now' );
+                       my ($r) = $self->method_lookup('open-ils.storage.direct.action.hold_request.update')->run( $hold );
+
+                       $client->respond("\tProcessing of hold ".$hold->id." complete.\n");
+                       $self->method_lookup('open-ils.storage.transaction.commit')->run;
+
+               } otherwise {
+                       my $e = shift;
+                       $client->respond("\tProcessing of hold ".$hold->id." failed!.\n\t\t$e\n");
+                       $self->method_lookup('open-ils.storage.transaction.rollback')->run;
+               };
        }
        return undef;
 }
@@ -509,8 +537,9 @@ sub copy_hold_capture {
        my @copies = grep { $_->holdable == 1  and $_->ref == 0 } @$cps;
 
        for (my $i = 0; $i < @copies; $i++) {
+               next unless $copies[$i];
                
-               my $cn = $cache{cns}{$copies[0]->call_number};
+               my $cn = $cache{cns}{$copies[$i]->call_number};
                my $rec = $cache{titles}{$cn->record};
                $copies[$i] = undef if ($copies[$i] && !grep{ $copies[$i]->status eq $_->id}@$statuses);
                $copies[$i] = undef if ($copies[$i] && !grep{ $copies[$i]->location eq $_->id}@$locations);
@@ -526,9 +555,9 @@ sub copy_hold_capture {
 
        return unless ($count);
        
-       my ($old_maps) = $self->method_lookup('open-ils.storage.direct.action.hold_copy_map.search.hold.atomic')->run( $hold->id );
+       my @old_maps = $self->method_lookup('open-ils.storage.direct.action.hold_copy_map.search.hold')->run( $hold->id );
 
-       $self->method_lookup('open-ils.storage.direct.action.hold_copy_map.batch.delete')->run(@$old_maps );
+       $self->method_lookup('open-ils.storage.direct.action.hold_copy_map.batch.delete')->run(@old_maps );
        
        my @maps;
        for my $c (@copies) {
@@ -650,8 +679,8 @@ sub metarecord_hold_capture {
 
        try {
                my @recs = map {$_->record}
-                               @{$self->method_lookup('open-ils.storage.direct.metabib.record_descriptor.search.atomic')
-                                               ->run( record => $titles, item_type => [split '', $hold->holdable_formats] )}
+                               $self->method_lookup('open-ils.storage.direct.metabib.record_descriptor.search')
+                                               ->run( record => $titles, item_type => [split '', $hold->holdable_formats] ); 
 
                $titles = [];
                ($titles) = $self->method_lookup('open-ils.storage.direct.biblio.record_entry.search.id.atomic')->run( \@recs );
index 98fab9d..292c848 100644 (file)
@@ -185,10 +185,11 @@ sub _init {
                'Fieldmapper::permission::usr_perm_map'         => { hint => 'pupm'   },
                'Fieldmapper::permission::grp_perm_map'         => { hint => 'pgpm'   },
                'Fieldmapper::action::hold_request'             => { hint => 'ahr', proto_fields => { status => 1 } },
-               'Fieldmapper::action::hold_notification'        => { hint => 'ahn'   },
+               'Fieldmapper::action::hold_notification'        => { hint => 'ahn'    },
                'Fieldmapper::action::hold_copy_map'            => { hint => 'ahcm'   },
                'Fieldmapper::action::hold_transit_copy'        => { hint => 'ahtc'   },
-               'Fieldmapper::action::transit_copy'     => { hint => 'atc'   },
+               'Fieldmapper::action::transit_copy'             => { hint => 'atc'    },
+               'Fieldmapper::action::unfulfilled_hold_list'    => { hint => 'aufh'   },
 
 
                'Fieldmapper::ex'                               => { hint           => 'ex',
index 19ee3b1..0f92341 100644 (file)
@@ -37,25 +37,47 @@ CREATE OR REPLACE VIEW money.payment_view AS
          FROM  money.payment p
                JOIN pg_class c ON (p.tableoid = c.oid);
 
+CREATE OR REPLACE VIEW money.transaction_billing_summary AS
+       SELECT  xact,
+               note AS last_billing_note,
+               MAX(billing_ts) AS last_billing_ts,
+               SUM(COALESCE(amount,0)) AS total_owed
+         FROM  money.billing
+         WHERE voided IS FALSE
+         GROUP BY xact,note
+         ORDER BY MAX(billing_ts);
+
+CREATE OR REPLACE VIEW money.transaction_payment_summary AS
+       SELECT  xact,
+               note AS last_payment_note,
+               MAX(payment_ts) as last_payment_ts,
+               SUM(COALESCE(amount,0)) AS total_paid
+         FROM  money.payment
+         WHERE voided IS FALSE
+         GROUP BY xact,note
+         ORDER BY MAX(payment_ts);
 
 CREATE OR REPLACE VIEW money.billable_xact_summary AS
        SELECT  xact.id AS id,
                xact.usr AS usr,
                xact.xact_start AS xact_start,
                xact.xact_finish AS xact_finish,
-               SUM(COALESCE(credit.amount,0)) AS total_paid,
-               MAX(credit.payment_ts) AS last_payment_ts,
-               SUM(COALESCE(debit.amount,0)) AS total_owed,
-               MAX(debit.billing_ts) AS last_billing_ts,
-               COALESCE(debit.note,'') AS last_billing_note,
-               SUM(COALESCE(debit.amount,0) - COALESCE(credit.amount,0)) AS balance_owed,
+               credit.total_paid,
+               credit.last_payment_ts,
+               credit.last_payment_note,
+               debit.total_owed,
+               debit.last_billing_ts,
+               debit.last_billing_note,
+               COALESCE(debit.total_owed,0) - COALESCE(credit.total_paid,0) AS balance_owed,
                p.relname AS xact_type
-         FROM  money.billable_xact xact
-               JOIN pg_class p ON (xact.tableoid = p.oid)
-               LEFT JOIN money.billing debit ON (xact.id = debit.xact AND debit.voided IS FALSE)
-               LEFT JOIN money.payment credit ON (xact.id = credit.xact AND credit.voided IS FALSE)
+         FROM  money.billable_xact xact,
+               pg_class p,
+               money.transaction_billing_summary debit,
+               money.transaction_payment_summary credit
          WHERE xact.xact_finish IS NULL
-       GROUP BY 1,2,3,4,9,11;
+               AND xact.tableoid = p.oid
+               AND xact.id = debit.xact
+               AND xact.id = credit.xact;
 
 CREATE OR REPLACE VIEW money.usr_summary AS
        SELECT  usr,
index bbe46a1..5bbfdc8 100644 (file)
@@ -152,5 +152,13 @@ CREATE TABLE action.hold_transit_copy (
        hold                    INT                             REFERENCES action.hold_request (id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED
 ) INHERITS (action.transit_copy);
 
+CREATE TABLE action.unfulfilled_hold_list (
+       id              BIGSERIAL       PRIMARY KEY,
+       hold            INT                             NOT NULL,
+       current_copy    BIGINT                          NOT NULL,
+       circ_lib        INT                             NOT NULL,
+       fail_time       TIMESTAMP WITH TIME ZONE        NOT NULL DEFAULT NOW()
+);
+
 COMMIT;