LP#1436906 clean up PO direct charges on delete/cancel
authorBill Erickson <berickxx@gmail.com>
Mon, 6 Apr 2015 15:24:33 +0000 (11:24 -0400)
committerBen Shum <bshum@biblio.org>
Fri, 10 Apr 2015 02:05:01 +0000 (22:05 -0400)
1. Deleting a "direct charge" from a PO removes the linked fund_debit if
the fund_debit has not been paid (i.e. it's still encumbered).

If the debit has been paid, the charge cannot be removed, unless/until
the debit is re-encumbered by un-invoicing the charge.

2. When a PO is canceled, fund_debits linked to PO items are removed.
As above, if the debit has been paid (invoiced), the PO cannot be
canceled, unless/until direct charge debits are un-invoiced.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Signed-off-by: Ben Shum <bshum@biblio.org>
Open-ILS/src/perlmods/lib/OpenILS/Application/Acq/Order.pm
Open-ILS/web/js/ui/default/acq/po/item_table.js

index 6883a0d..a63b948 100644 (file)
@@ -2926,6 +2926,26 @@ sub cancel_purchase_order {
         }
     }
 
+    my $po_item_ids = $mgr->editor
+        ->search_acq_po_item({purchase_order => $po_id}, {idlist => 1});
+
+    for my $po_item_id (@$po_item_ids) {
+
+        my $po_item = $mgr->editor->retrieve_acq_po_item([
+            $po_item_id, {
+                flesh => 1,
+                flesh_fields => {acqpoi => ['purchase_order', 'fund_debit']}
+            }
+        ]) or return -1; # results in rollback
+
+        # returns undef on success
+        my $result = clear_po_item($mgr->editor, $po_item);
+
+        return $result if not_cancelable($result);
+        return -1 if $result; # other failure events, results in rollback
+    }
+
+
     # TODO who/what/where/how do we indicate this change for electronic orders?
     # TODO return changes to encumbered/spent
     # TODO maybe cascade up from smaller object to container object if last
@@ -3281,6 +3301,78 @@ sub cancel_lineitem_detail {
     return {"lid" => {$lid_id => {"cancel_reason" => $cancel_reason}}};
 }
 
+__PACKAGE__->register_method(
+    method => "delete_po_item_api",
+    api_name    => "open-ils.acq.po_item.delete",
+    signature => {
+        desc => q/Deletes a po_item and removes its debit/,
+        params => [
+            {desc => "Authentication token", type => "string"},
+            {desc => "po_item ID to delete", type => "number"},
+        ],
+        return => {desc => q/1 on success, Event on error/}
+    }
+);
+
+sub delete_po_item_api {
+    my($self, $client, $auth, $po_item_id) = @_;
+    my $e = new_editor(authtoken => $auth, xact => 1);
+    return $e->die_event unless $e->checkauth;
+
+    my $po_item = $e->retrieve_acq_po_item([
+        $po_item_id, {
+            flesh => 1,
+            flesh_fields => {acqpoi => ['purchase_order', 'fund_debit']}
+        }
+    ]) or return $e->die_event;
+
+    return $e->die_event unless 
+        $e->allowed('CREATE_PURCHASE_ORDER', 
+            $po_item->purchase_order->ordering_agency);
+
+    # remove debit, delete item
+    my $result = clear_po_item($e, $po_item, 1);
+
+    if ($result) {
+        $e->rollback;
+        return $result;
+    }
+
+    $e->commit;
+    return 1;
+}
+
+
+# 1. Removes linked fund debit from a PO item if present and still encumbered.
+# 2. Optionally also deletes the po_item object
+# po_item is fleshed with purchase_order and fund_debit
+sub clear_po_item {
+    my ($e, $po_item, $delete_item) = @_;
+
+    if ($po_item->fund_debit) {
+
+        if (!$U->is_true($po_item->fund_debit->encumbrance)) {
+            # debit has been paid.  We cannot delete it.
+            return OpenILS::Event->new('ACQ_NOT_CANCELABLE', 
+               note => "Debit is marked as paid: ".$po_item->fund_debit->id);
+        }
+
+        # fund_debit is OK to delete.
+        $e->delete_acq_fund_debit($po_item->fund_debit)
+            or return $e->die_event;
+    }
+
+    if ($delete_item) {
+        $e->delete_acq_po_item($po_item) or return $e->die_event;
+    } else {
+        # remove our link to the now-deleted fund_debit.
+        $po_item->clear_fund_debit;
+        $e->update_acq_po_item($po_item) or return $e->die_event;
+    }
+
+    return undef;
+}
+
 
 __PACKAGE__->register_method(
     method    => 'user_requests',
index 4ed9a72..8752e34 100644 (file)
@@ -110,13 +110,16 @@ function PoItemTable() {
     this.deleteRow = function(id) {
         if (id > 0) {
             progressDialog.show(true);
-            pcrud.eliminate(
-                this.realItems[id], {
-                    "oncomplete": function(r) {
+            fieldmapper.standardRequest(
+                ['open-ils.acq', 'open-ils.acq.po_item.delete'],
+                {   async : true,
+                    params: [openils.User.authtoken, id],
+                    oncomplete : function(r) {
                         progressDialog.hide();
                         r = openils.Util.readResponse(r); /* may not use */
-
-                        self._deleteRow(id);
+                        if (r == '1') {
+                            self._deleteRow(id);
+                        } 
                     }
                 }
             );