From 58837e14313c037889c7ae568c32c38a352be08f Mon Sep 17 00:00:00 2001 From: miker Date: Fri, 22 Jul 2005 15:55:47 +0000 Subject: [PATCH] fixing money views; adding unfulfilled holds tracker; transaction-ifying hold capture targeting git-svn-id: svn://svn.open-ils.org/ILS/trunk@1358 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../Application/Storage/CDBI/action.pm | 8 ++ .../OpenILS/Application/Storage/CDBI/money.pm | 3 +- .../Application/Storage/Driver/Pg/dbi.pm | 7 ++ .../Application/Storage/Publisher/action.pm | 111 +++++++++++------- .../src/perlmods/OpenILS/Utils/Fieldmapper.pm | 5 +- .../src/sql/Postgres/080.schema.money.sql | 44 +++++-- .../src/sql/Postgres/090.schema.action.sql | 8 ++ 7 files changed, 131 insertions(+), 55 deletions(-) diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/action.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/action.pm index 60761cc250..8ff2aae70f 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/action.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/action.pm @@ -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; diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/money.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/money.pm index 1f3daa671c..c4fe509403 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/money.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/CDBI/money.pm @@ -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; diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/dbi.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/dbi.pm index c42791d606..4c1e768ead 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/dbi.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Driver/Pg/dbi.pm @@ -549,6 +549,13 @@ #------------------------------------------------------------------------------- + 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'); + + #------------------------------------------------------------------------------- + } diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm index fe69771114..2255b0d7b8 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/action.pm @@ -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 ); diff --git a/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm b/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm index 98fab9df04..292c8489f5 100644 --- a/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm +++ b/Open-ILS/src/perlmods/OpenILS/Utils/Fieldmapper.pm @@ -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', diff --git a/Open-ILS/src/sql/Postgres/080.schema.money.sql b/Open-ILS/src/sql/Postgres/080.schema.money.sql index 19ee3b11e1..0f92341a98 100644 --- a/Open-ILS/src/sql/Postgres/080.schema.money.sql +++ b/Open-ILS/src/sql/Postgres/080.schema.money.sql @@ -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, diff --git a/Open-ILS/src/sql/Postgres/090.schema.action.sql b/Open-ILS/src/sql/Postgres/090.schema.action.sql index bbe46a1fe0..5bbfdc8cb6 100644 --- a/Open-ILS/src/sql/Postgres/090.schema.action.sql +++ b/Open-ILS/src/sql/Postgres/090.schema.action.sql @@ -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; -- 2.43.2