From 421b42503ff54bf9a5ef4632dddb253b413e8c8f Mon Sep 17 00:00:00 2001 From: dbwells Date: Sat, 15 Jan 2011 04:04:23 +0000 Subject: [PATCH] Postpone advanced serial call-number handling until after 2.0 Sharing of a single call-number for multiple volumes, while well intentioned, was not ready for primetime for various reasons. This commit: 1) harmonizes and unifies call-number handling in Serial.pm, sticking with current practices 2) adds a very basic and now necessary prompt to the Serial Control view git-svn-id: svn://svn.open-ils.org/ILS/trunk@19182 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- .../src/perlmods/OpenILS/Application/Serial.pm | 119 +++++++++++++-------- .../xul/staff_client/server/serial/manage_items.js | 65 ++++++++--- 2 files changed, 129 insertions(+), 55 deletions(-) diff --git a/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm b/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm index 718c3fd6a1..0a94974cf5 100644 --- a/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm +++ b/Open-ILS/src/perlmods/OpenILS/Application/Serial.pm @@ -1058,6 +1058,11 @@ __PACKAGE__->register_method( name => 'barcodes', desc => 'hash of item_ids => barcodes', type => 'hash' + }, + { + name => 'call_numbers', + desc => 'hash of item_ids => call_numbers', + type => 'hash' } ], 'return' => { @@ -1083,6 +1088,11 @@ __PACKAGE__->register_method( name => 'barcodes', desc => 'hash of item_ids => barcodes', type => 'hash' + }, + { + name => 'call_numbers', + desc => 'hash of item_ids => call_numbers', + type => 'hash' } ], 'return' => { @@ -1115,7 +1125,7 @@ __PACKAGE__->register_method( ); sub unitize_items { - my ($self, $conn, $auth, $items, $barcodes) = @_; + my ($self, $conn, $auth, $items, $barcodes, $call_numbers) = @_; my $editor = new_editor("authtoken" => $auth, "xact" => 1); return $editor->die_event unless $editor->checkauth; @@ -1131,6 +1141,7 @@ sub unitize_items { my %unit_map; my %sdist_by_unit_id; + my %call_number_by_unit_id; my %sdist_by_stream_id; my $new_unit_id; # id for '-2' units to share @@ -1175,14 +1186,21 @@ sub unitize_items { # create unit if needed if ($unit_id == -1 or (!$new_unit_id and $unit_id == -2)) { # create unit per item my $unit; - my $sdists = $editor->search_serial_distribution([{"+sstr" => {"id" => $stream_id}}, { "join" => {"sstr" => {}} }]); - $unit = _build_unit($editor, $sdists->[0], $mode, 0, $barcodes->{$item->id}); + my $sdists = $editor->search_serial_distribution([ + {"+sstr" => {"id" => $stream_id}}, + { + "join" => {"sstr" => {}}, + "flesh" => 1, + "flesh_fields" => {"sdist" => ["subscription"]} + }]); + $unit = _build_unit($editor, $sdists->[0], $mode); # if _build_unit fails, $unit is an event, so return it if ($U->event_code($unit)) { $editor->rollback; $unit->{"note"} = "Item ID: " . $item->id; return $unit; } + $unit->barcode($barcodes->{$item->id}) if exists($barcodes->{$item->id}); my $evt = _create_sunit($editor, $unit); return $evt if $evt; if ($unit_id == -2) { @@ -1193,10 +1211,11 @@ sub unitize_items { } $item->unit($unit_id); - # get unit with 'DEFAULT's and save unit and sdist for later use + # get unit with 'DEFAULT's and save unit, sdist, and call number for later use $unit = $editor->retrieve_serial_unit($unit->id); $unit_map{$unit_id} = $unit; $sdist_by_unit_id{$unit_id} = $sdists->[0]; + $call_number_by_unit_id{$unit_id} = $call_numbers->{$item->id}; $sdist_by_stream_id{$stream_id} = $sdists->[0]; } elsif ($unit_id == -2) { # create one unit for all '-2' items $unit_id = $new_unit_id; @@ -1221,7 +1240,7 @@ sub unitize_items { delete $found_unit_ids{$unit->id}; } - # deal with unit level labels + # deal with unit level contents foreach my $unit_id (keys %found_unit_ids) { # get all the needed issuances for unit @@ -1232,21 +1251,31 @@ sub unitize_items { # retrieve and update unit contents my $sunit; my $sdist; - - # if we just created the unit, we will already have it and the distribution stored + my $call_number_string; + my $record_id; + # if we just created the unit, we will already have it and the distribution stored, and we will need to assign the call number if (exists $unit_map{$unit_id}) { $sunit = $unit_map{$unit_id}; $sdist = $sdist_by_unit_id{$unit_id}; + $call_number_string = $call_number_by_unit_id{$unit_id}; + $record_id = $sdist->subscription->record_entry; } else { $sunit = $editor->retrieve_serial_unit($unit_id); $sdist = $editor->search_serial_distribution([{"+sstr" => {"id" => $stream_ids_by_unit_id{$unit_id}}}, { "join" => {"sstr" => {}} }]); $sdist = $sdist->[0]; } - _prepare_unit_label($editor, $sunit, $sdist, $issuances); + my $evt = _prepare_unit($editor, $sunit, $sdist, $issuances, $call_number_string, $record_id); + if ($U->event_code($evt)) { + $editor->rollback; + return $evt; + } - my $evt = _update_sunit($editor, undef, $sunit); - return $evt if $evt; + $evt = _update_sunit($editor, undef, $sunit); + if ($U->event_code($evt)) { + $editor->rollback; + return $evt; + } } if ($mode ne 'bind') { # the summary holdings do not change when binding @@ -1348,10 +1377,26 @@ sub _issuances_received { return [ map { $e->retrieve_serial_issuance($_) } keys %$uniq ]; } -# _prepare_unit_label populates the detailed_contents, summary_contents, and +# _prepare_unit populates the detailed_contents, summary_contents, and # sort_key fields for a given unit based on a given set of issuances -sub _prepare_unit_label { - my ($e, $sunit, $sdist, $issuances) = @_; +# Also finds/creates call number as needed +sub _prepare_unit { + my ($e, $sunit, $sdist, $issuances, $call_number_string, $record_id) = @_; + + # Handle call number first if we have one + if ($call_number_string) { + my $org_unit_id = ref $sdist->holding_lib ? $sdist->holding_lib->id : $sdist->holding_lib; + my $real_cn = _find_or_create_call_number( + $e, $org_unit_id, + $call_number_string, $record_id + ); + + if ($U->event_code($real_cn)) { + return $real_cn; + } else { + $sunit->call_number($real_cn); + } + } my ($mfhd, $formatted_parts) = _summarize_contents($e, $issuances); @@ -1546,7 +1591,7 @@ sub receive_items_one_unit_per { my $user_unit = $item->unit; # get a unit based on associated template - my $template_unit = _build_unit($e, $sdist, "receive", 1); + my $template_unit = _build_unit($e, $sdist, "receive"); if ($U->event_code($template_unit)) { $e->rollback; $template_unit->{"note"} = "Item ID: " . $item->id; @@ -1562,22 +1607,16 @@ sub receive_items_one_unit_per { # Treat call number specially: the provided value from the # user will really be a string. + my $call_number_string; if ($user_unit->call_number) { - my $real_cn = _find_or_create_call_number( - $e, $sdist->holding_lib->id, - $user_unit->call_number, $record - ); - - if ($U->event_code($real_cn)) { - $e->rollback; - return $real_cn; - } else { - $user_unit->call_number($real_cn); - } + $call_number_string = $user_unit->call_number; + # clear call number for now (replaced in _prepare_unit) + $user_unit->clear_call_number; } - my $evt = _prepare_unit_label( - $e, $user_unit, $sdist, [$item->issuance] + my $evt = _prepare_unit( + $e, $user_unit, $sdist, [$item->issuance], + $call_number_string, $record ); if ($U->event_code($evt)) { $e->rollback; @@ -1639,8 +1678,7 @@ sub _build_unit { my $editor = shift; my $sdist = shift; my $mode = shift; - my $skip_call_number = shift; - my $barcode = shift; + #my $skip_call_number = shift; my $attr = $mode . '_unit_template'; my $template = $editor->retrieve_asset_copy_template($sdist->$attr) or @@ -1660,19 +1698,16 @@ sub _build_unit { $unit->creator($editor->requestor->id); $unit->editor($editor->requestor->id); - unless ($skip_call_number) { - $attr = $mode . '_call_number'; - my $cn = $sdist->$attr or - return new OpenILS::Event("SERIAL_DISTRIBUTION_HAS_NO_CALL_NUMBER"); - - $unit->call_number($cn); - } - - if ($barcode) { - $unit->barcode($barcode); - } else { - $unit->barcode('AUTO'); - } +# XXX: this feature has been pushed back until after 2.0 at least +# unless ($skip_call_number) { +# $attr = $mode . '_call_number'; +# my $cn = $sdist->$attr or +# return new OpenILS::Event("SERIAL_DISTRIBUTION_HAS_NO_CALL_NUMBER"); +# +# $unit->call_number($cn); +# } + $unit->call_number('-1'); # default to the dummy call number + $unit->barcode('@@PLACEHOLDER'); # generic unit will start with a generated placeholder barcode $unit->sort_key(''); $unit->summary_contents(''); $unit->detailed_contents(''); diff --git a/Open-ILS/xul/staff_client/server/serial/manage_items.js b/Open-ILS/xul/staff_client/server/serial/manage_items.js index 66ca3d8e3b..30982f82c7 100644 --- a/Open-ILS/xul/staff_client/server/serial/manage_items.js +++ b/Open-ILS/xul/staff_client/server/serial/manage_items.js @@ -316,40 +316,79 @@ serial.manage_items.prototype = { success_label = 'bound'; } - // deal with barcodes for *NEW* units + // deal with barcodes and call numbers for *NEW* units var barcodes = {}; + var call_numbers = {}; + var call_numbers_by_issuance_id = {}; + if (obj.current_sunit_id < 0) { // **AUTO** or **NEW** units - new_unit_barcode = ''; + var new_unit_barcode = ''; + var new_unit_call_number = ''; for (var i = 0; i < list.length; i++) { var item = list[i]; if (new_unit_barcode) { barcodes[item.id()] = new_unit_barcode; + call_numbers[item.id()] = new_unit_call_number; continue; } var prompt_text; if (obj.current_sunit_id == -1) { - prompt_text = 'Please enter a barcode for '+item.issuance().label()+ ' from Distribution: '+item.stream().distribution().label()+'/'+item.stream().id()+':'; + prompt_text = 'for '+item.issuance().label()+ ' from Distribution: '+item.stream().distribution().label()+'/'+item.stream().id()+':'; } else { // must be -2 - prompt_text = 'Please enter a barcode for new unit:'; + prompt_text = 'for the new unit:'; } - var barcode = window.prompt(prompt_text, - '', + + // first barcodes + var barcode = window.prompt('Please enter a barcode ' + prompt_text, + '@@AUTO', 'Unit Barcode Prompt'); barcode = String( barcode ).replace(/\s/g,''); /* Casting a possibly null input value to a String turns it into "null" */ if (!barcode || barcode == 'null') { alert('Invalid barcode entered, defaulting to system-generated.'); - barcode = 'auto'; + barcode = '@@AUTO'; + } else { + var test = obj.network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ barcode ]); + if (typeof test.ilsevent == 'undefined') { + alert('Another copy has barcode "' + barcode + '", defaulting to system-generated.'); + barcode = '@@AUTO'; + } } + barcodes[item.id()] = barcode; - var test = obj.network.simple_request('FM_ACP_RETRIEVE_VIA_BARCODE',[ barcode ]); - if (typeof test.ilsevent == 'undefined') { - alert('Another copy has barcode "' + barcode + '", defaulting to system-generated.'); - barcode = 'auto'; + // now call numbers + if (typeof call_numbers_by_issuance_id[item.issuance().id()] == 'undefined') { + var default_cn = 'DEFAULT'; + // for now, let's default to the last created call number if there is one + // TODO: make this distribution specific + var acn_list = obj.network.request( + 'open-ils.pcrud', + 'open-ils.pcrud.search.acn', + [ ses(), {"record" : obj.docid, "owning_lib" : obj.holding_lib, "deleted" : 'f' }, {"order_by" : {"acn" : "create_date DESC"}, "limit" : "1" } ] + ); + + if (acn_list) { + default_cn = acn_list.label(); + } + var call_number = window.prompt('Please enter/adjust a call number ' + prompt_text, + default_cn, //TODO: real default by setting + 'Unit Call Number Prompt'); + call_number = String( call_number ).replace(/^\s+/,'').replace(/\s$/,''); + /* Casting a possibly null input value to a String turns it into "null" */ + if (!call_number || call_number == 'null') { + alert('Invalid call number entered, setting to "DEFAULT".'); + call_number = 'DEFAULT'; //TODO: real default by setting + } + call_numbers[item.id()] = call_number; + call_numbers_by_issuance_id[item.issuance().id()] = call_number; + } else { + // we have already seen this same issuance, so use the same call number + call_numbers[item.id()] = call_numbers_by_issuance_id[item.issuance().id()]; } - barcodes[item.id()] = barcode; + if (obj.current_sunit_id == -2) { new_unit_barcode = barcode; + new_unit_call_number = call_number; } } } @@ -357,7 +396,7 @@ serial.manage_items.prototype = { var robj = obj.network.request( 'open-ils.serial', method, - [ ses(), list, barcodes ] + [ ses(), list, barcodes, call_numbers ] ); if (typeof robj.ilsevent != 'undefined') throw(robj); //TODO: catch for override -- 2.11.0