LP1952931 ASN shipment notifiation Perl
authorBill Erickson <berickxx@gmail.com>
Thu, 2 Dec 2021 22:16:06 +0000 (17:16 -0500)
committerBill Erickson <berickxx@gmail.com>
Wed, 21 Sep 2022 15:29:34 +0000 (11:29 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/EDI.pm
Open-ILS/src/perlmods/lib/OpenILS/Utils/EDIReader.pm

index 5557027..c7f1e26 100644 (file)
@@ -636,6 +636,10 @@ sub process_parsed_msg {
     if ($incoming->message_type eq 'INVOIC') {
         return $class->create_acq_invoice_from_edi(
             $msg_hash, $account->provider, $incoming);
+
+    } elsif ($incoming->message_type eq 'DESADV') {
+        return $class->create_shipment_notification_from_edi(
+            $msg_hash, $account->provider, $incoming);
     }
 
     # ORDRSP
@@ -1070,6 +1074,7 @@ sub create_acq_invoice_from_edi {
     # those.
     my ($eg_inv_entries, $unknowns) = process_invoice_lineitems(
         $e, \%msg_kludges, $log_prefix, $message, $msg_data->{lineitems}
+
     );
 
     if (@$unknowns) {
@@ -1140,5 +1145,125 @@ sub create_acq_invoice_from_edi {
     return 1;
 }
 
+sub create_shipment_notification_from_edi {
+    my ($class, $msg_data, $provider_id, $edi_message) = @_;
+    # $msg_data is O::U::EDIReader hash
+
+    my $e = new_editor();
+
+    my $eg_asn = Fieldmapper::acq::shipment_notification->new;
+    $eg_asn->isnew(1);
+
+    # Some troubleshooting aids.  Yeah we should have made appropriate links
+    # for this in the schema, but this is better than nothing.  Probably
+    # *don't* try to i18n this.
+    $eg_asn->note("Generated from acq.edi_message #" . $edi_message->id . ".");
+
+    $eg_asn->provider($provider_id);
+    $eg_asn->shipper($provider_id);
+    $eg_asn->recv_method('EDI');
+
+    $eg_asn->recv_date( # invoice_date is a misnomer; should be message date.
+        $class->edi_date_to_iso($msg_data->{invoice_date}));
+
+    $class->process_message_buyer($e, $msg_data, $edi_message, "ASN" , $eg_asn);
+
+    if (!$eg_asn->receiver) {
+        die(sprintf(
+            "Unable to determine buyer (org unit) in shipment notification; ".
+            "buyer_san=%s; buyer_acct=%s",
+            ($msg_data->{buyer_san} || ''), 
+            ($msg_data->{buyer_acct} || '')
+        ));
+    }
+
+    $eg_asn->container_code($msg_data->{container_code});
+
+    die("No container code in DESADV message") unless $eg_asn->container_code;
+
+    my $entries = extract_shipment_notification_entries($msg_data->{lineitems});
+
+    $e->xact_begin;
+
+    die "Error updating EDI message: " . $e->die_event
+        unless $e->update_acq_edi_message($edi_message);
+
+    die "Error creating shipment notification: " . $e->die_event
+        unless $e->create_acq_shipment_notification($eg_asn);
+
+    for my $entry (@$entries) {
+        $entry->shipment_notification($eg_asn->id);
+        die "Error creating shipment notification entry: " . $e->die_event
+            unless $e->create_acq_shipment_notification_entry($entry);
+    }
+
+    $e->xact_commit;
+    return 1;
+}
+
+sub extract_shipment_notification_entries {
+    my ($lineitem_hashes) = @_;
+
+    my $e = new_editor();
+    my @entries;
+    for my $li_hash (@$lineitem_hashes) {
+
+        # A shipment notification may cover multiple PO's. 
+        # Each LI will include its own PO ID.
+        my $po_id = $li_hash->{purchase_order};
+
+        unless ($po_id) {
+            $logger->warn("Skipping ASN lineitem which has no PO ID");
+            next;
+        }
+
+        my ($quant) = grep {$_->{code} eq '12'} @{$li_hash->{quantities}};
+        my $quantity = ($quant) ? $quant->{quantity} : 0;
+
+        # LI identifiers map to order identifiers, not lineitem IDs, 
+        # at least not in the data seen so far.
+        my $li_id;
+        for my $ident_spec (@{$li_hash->{identifiers}}) {
+
+            my $ident = $ident_spec->{value};
+            next unless $ident;
+
+            my $li_id_hash = $e->json_query({
+                select => {jub => ['id']},
+                from => {
+                    jub => {
+                        acqlia => {
+                            filter => {order_ident => 't', value => $ident}
+                        }
+                    }
+                },
+                where => {'+jub' => {purchase_order => $po_id}}
+            })->[0];
+
+            if ($li_id_hash) {
+                $li_id = $li_id_hash->{id};
+                last;
+            } else {
+                $logger->warn("Cannot find lineitem with order ".
+                    "identifier=$ident and purchase_order=$po_id");
+            }
+        }
+
+        unless ($li_id) {
+            $logger->warn("Cannot find lineitem for ASN entry; skippping");
+            next;
+        }
+        
+        my $entry = Fieldmapper::acq::shipment_notification_entry->new;
+
+        $entry->lineitem($li_id);
+        $entry->item_count($quant);
+
+        push(@entries, $entry);
+    }
+
+    return \@entries;
+}
+
 1;
 
index e68f6ea..cd2ecbe 100644 (file)
@@ -114,11 +114,6 @@ sub read {
         next unless $msg;
 
         for my $field (keys %edi_fields) {
-
-            # With ASN, a purchase_order value specified per lineitem.
-            # Avoid tracking a message-level PO to avoid confusion.
-            next if $msg->{message_type} eq 'DESADV' && $field eq 'purchase_order';
-
             ($msg->{$field}) = $_ =~ /$edi_fields{$field}/
                 if /$edi_fields{$field}/;
         }