consolidated invoice attach and create API call into a single cud call
authorerickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Wed, 7 Apr 2010 21:42:37 +0000 (21:42 +0000)
committererickson <erickson@dcc99617-32d9-48b4-a31d-7c20da2025e4>
Wed, 7 Apr 2010 21:42:37 +0000 (21:42 +0000)
initial invoice process call to create/update the associated debits
added keep_li_marc option, otherwise strip the marc and just return
li attrs

git-svn-id: svn://svn.open-ils.org/ILS/trunk@16164 dcc99617-32d9-48b4-a31d-7c20da2025e4

Open-ILS/src/perlmods/OpenILS/Application/Acq/Invoice.pm

index da7d7ab..8c99f0b 100644 (file)
@@ -12,27 +12,14 @@ my $U = 'OpenILS::Application::AppUtils';
 
 __PACKAGE__->register_method(
        method => 'build_invoice_api',
-       api_name        => 'open-ils.acq.invoice.create',
+       api_name        => 'open-ils.acq.invoice.update',
        signature => {
-        desc => q/Creates a new stub invoice/,
+        desc => q/Creates, updates, and deletes invoices, and related invoice entries, and invoice items/,
         params => [
             {desc => 'Authentication token', type => 'string'},
-            {desc => q/Invoice Object/, type => 'object', class => 'acqinv'},
-        ],
-        return => {desc => 'The new invoice w/ entries and items attached', type => 'object', class => 'acqinv'}
-    }
-);
-
-__PACKAGE__->register_method(
-       method => 'build_invoice_api',
-       api_name        => 'open-ils.acq.invoice.attach',
-       signature => {
-        desc => q/Attach invoice entries and invoice items to an existing invoice/,
-        params => [
-            {desc => 'Authentication token', type => 'string'},
-            {desc => q/Invoice ID/, type => 'number'},
-            {desc => q/Entries/, type => 'array'},
-            {desc => q/Items/, type => 'array'},
+            {desc => q/Invoice/, type => 'number'},
+            {desc => q/Entries.  Array of 'acqie' objects/, type => 'array'},
+            {desc => q/Items.  Array of 'acqii' objects/, type => 'array'},
         ],
         return => {desc => 'The invoice w/ entries and items attached', type => 'object', class => 'acqinv'}
     }
@@ -44,13 +31,19 @@ sub build_invoice_api {
     my $e = new_editor(xact => 1, authtoken=>$auth);
     return $e->die_event unless $e->checkauth;
 
-
-    if($self->api_name =~ /create/) {
-        $invoice->receiver($e->requestor->ws_ou) unless $invoice->receiver;
-        $invoice->recv_method('PPR') unless $invoice->recv_method;
-        $invoice->recv_date('now') unless $invoice->recv_date;
-        $e->create_acq_invoice($invoice) or return $e->die_event;
+    if(ref $invoice) {
+        if($invoice->isnew) {
+            $invoice->receiver($e->requestor->ws_ou) unless $invoice->receiver;
+            $invoice->recv_method('PPR') unless $invoice->recv_method;
+            $invoice->recv_date('now') unless $invoice->recv_date;
+            $e->create_acq_invoice($invoice) or return $e->die_event;
+        } elsif($invoice->isdeleted) {
+            i$e->delete_acq_invoice($invoice) or return $e->die_event;
+        } else {
+            $e->update_acq_invoice($invoice) or return $e->die_event;
+        }
     } else {
+        # call only provided the ID
         $invoice = $e->retrieve_acq_invoice($invoice) or return $e->die_event;
     }
 
@@ -59,14 +52,26 @@ sub build_invoice_api {
     if($entries) {
         for my $entry (@$entries) {
             $entry->invoice($invoice->id);
-            $e->create_acq_invoice_entry($entry) or return $e->die_event;
+            if($entry->isnew) {
+                $e->create_acq_invoice_entry($entry) or return $e->die_event;
+            } elsif($entry->isdeleted) {
+                $e->delete_acq_invoice_entry($entry) or return $e->die_event;
+            } elsif($entry->ischanged) {
+                $e->update_acq_invoice_entry($entry) or return $e->die_event;
+            }
         }
     }
 
     if($items) {
         for my $item (@$items) {
             $item->invoice($invoice->id);
-            $e->create_acq_invoice_item($item) or return $e->die_event;
+            if($item->isnew) {
+                $e->create_acq_invoice_item($item) or return $e->die_event;
+            } elsif($item->isdeleted) {
+                $e->delete_acq_invoice_item($item) or return $e->die_event;
+            } elsif($item->ischanged) {
+                $e->update_acq_invoice_item($item) or return $e->die_event;
+            }
         }
     }
 
@@ -120,7 +125,100 @@ sub fetch_invoice_impl {
             }
         }
     ];
-    return $e->retrieve_acq_invoice($args);
+
+    my $invoice = $e->retrieve_acq_invoice($args);
+    return $invoice if $options->{no_flesh_misc} or $options->{keep_li_marc};
+
+    $_->lineitem->clear_marc for @{$invoice->entries};
+    return $invoice;
+}
+
+__PACKAGE__->register_method(
+       method => 'process_invoice',
+       api_name        => 'open-ils.acq.invoice.process',
+       signature => {
+        desc => q/
+            Process an invoice.  This updates the related fund debits by applying the now known cost
+            and sets the encumbrance flag to false.  It creates new debits for ad-hoc expenditures (invoice_item's).
+            For all invoice items that have the prorate flag set to true, this will create the necessary 
+            additional invoice_item's to prorate the cost across all affected funds by percent spent for each fund.
+        /,
+        params => [
+            {desc => 'Authentication token', type => 'string'},
+            {desc => q/Invoice Id/, type => 'number'},
+        ],
+        return => {desc => 'The updated invoice w/ entries and items attached', type => 'object', class => 'acqinv'}
+    }
+);
+
+
+sub process_invoice {
+    my($self, $conn, $auth, $invoice_id) = @_;
+
+    my $e = new_editor(xact => 1, authtoken=>$auth);
+    return $e->die_event unless $e->checkauth;
+
+    my $invoice = fetch_invoice_impl($e, $invoice_id) or return $e->die_event;
+    return $e->die_event unless $e->allowed('CREATE_INVOICE', $invoice->receiver);
+
+    my %fund_totals;
+
+    for my $entry (@{$invoice->entries}) {
+        
+        my $debits = $e->json_query({
+            select => {acqfdeb => ['id']},
+            from => {
+                acqfdeb => {
+                    acqlid => {
+                        filter => {cancel_reason => undef, recv_time => {'!=' => undef}},
+                        join => {
+                            jub =>  {
+                                join => {
+                                    acqie => {
+                                        filter => {id => $entry->id}
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            },
+            where => {'+acqfdeb' => {encumbrance => 't'}}
+        });
+
+        next unless @$debits;
+
+        if($entry->phys_item_count > @$debits) {
+            $e->rollback;
+            # We can't invoice for more items than we have debits for
+            return OpenILS::Event->new('ACQ_INVOICE_ENTRY_COUNT_EXCEEDS_DEBITS', payload => {entry => $entry->id});
+        }
+
+        for my $debit_id (map { $_->{id} } @$debits) {
+            my $debit = $e->retrieve_acq_fund_debit($debit_id);
+            $debit->amount($entry->cost_billed);
+            $debit->encumbrance('f');
+            $e->update_acq_fund_debit($debit) or return $e->die_event;
+            $fund_totals{$debit->fund} ||= 0;
+            $fund_totals{$debit->fund} += $entry->cost_billed;
+        }
+    }
+
+    my $total_entry_cost = 0;
+    $total_entry_cost += $fund_totals{$_} for keys %fund_totals;
+
+    $logger->info("invoice: total bib cost for invoice = $total_entry_cost");
+
+    # collect amount spent per fund to get percents
+
+    for my $item (@{$invoice->items}) {
+
+        # prorate and create fund debits as appropriate
+    }
+
+    $e->rollback;
+    return $invoice;
+
 }