Postpone advanced serial call-number handling until after 2.0
authordbwells <dbwells@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Sat, 15 Jan 2011 04:04:23 +0000 (04:04 +0000)
committerdbwells <dbwells@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Sat, 15 Jan 2011 04:04:23 +0000 (04:04 +0000)
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

Open-ILS/src/perlmods/OpenILS/Application/Serial.pm
Open-ILS/xul/staff_client/server/serial/manage_items.js

index 718c3fd..0a94974 100644 (file)
@@ -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('');
index 66ca3d8..30982f8 100644 (file)
@@ -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