[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

SF.net SVN: ledger-smb: [1699] branches/1.2/LedgerSMB/IS.pm



Revision: 1699
          http://ledger-smb.svn.sourceforge.net/ledger-smb/?rev=1699&view=rev
Author:   einhverfr
Date:     2007-10-04 10:29:54 -0700 (Thu, 04 Oct 2007)

Log Message:
-----------
COGS fixes for sales invoice reversals

Modified Paths:
--------------
    branches/1.2/LedgerSMB/IS.pm

Modified: branches/1.2/LedgerSMB/IS.pm
===================================================================
--- branches/1.2/LedgerSMB/IS.pm	2007-10-04 06:08:43 UTC (rev 1698)
+++ branches/1.2/LedgerSMB/IS.pm	2007-10-04 17:29:54 UTC (rev 1699)
@@ -1510,6 +1510,12 @@
 }
 
 sub cogs {
+    # This is nearly entirely rewritten since 1.2.8 based in part on the works
+    # of Victor Sterpu and Dieter Simader (see CONTRIBUTORS for more 
+    # information).  However, there are a number of areas where I have 
+    # substantially rewritten the logic.  This function is heavily annotated 
+    # largely because COGS/invoices are still scheduled to be re-engineered in
+    # 1.4 so it is a good idea to have records of opinions in the code.-- CT
     my ( $dbh2, $form, $id, $totalqty, $project_id, $sellprice) = @_;
     my $dbh   = $form->{dbh};
     my $query;
@@ -1614,40 +1620,79 @@
                             $dbh, "invoice", "allocated", 
                             qq|id = $ref->{id}|, $qty * -1 
             );
-            $allocated += $qty;
-            my $linetotal = $qty*$ref->{sellprice};
-            $query = qq|
-		INSERT INTO acc_trans 
-		            (trans_id, chart_id, amount, 
-                             transdate, project_id, invoice_id) 
-		     VALUES (?, ?, ?, ?, ?, ?)|;
 
-            my $sth1 = $dbh->prepare($query);
-            $sth1->execute(
-                         $form->{id}, $ref->{"expense_accno_id"}, 
-                         $linetotal, $form->{transdate}, 
-                         $project_id, $ref->{id}
-            ) || $form->dberror($query);
+            # Note:  No COGS calculations on reversed short sale invoices.  
+            # This merely prevents COGS calculations in the future agaisnt
+            # such short invoices.  -- CT
 
+            $totalqty -= $qty;
+            last if $totalqty == 0;
+        }
+        # If the total quantity is still less than zero, we must assume that
+        # this is just an invoice which has been voided or products returns 
+        # but is not merely representing a voided short sale, and therefore 
+        # we need to unallocate the items from AP.  There has been some debate
+        # as to how to approach this, and I think it is safest to unallocate
+        # the most recently allocated AP items of the same type regardless of
+        # the relevant dates of the invoices.  I can see cases where this 
+        # might require adjustments, however.  -- CT
+
+        if ($totalqty < 0){
             $query = qq|
-		INSERT INTO acc_trans 
-		            (trans_id, chart_id, amount, transdate, 
-		             project_id, invoice_id) 
-		     VALUES (?, ?, ?, ?, ?, ?)|;
+		  SELECT i.allocated, i.sellprice, p.inventory_accno_id, 
+		         p.expense_accno_id 
+		    FROM invoice i
+		    JOIN parts p ON (i.parts_id = p.id)
+		    JOIN ap ON (i.trans_id = a.id)
+		   WHERE (i.allocated + i.qty) < 0
+		         AND i.parts_id = ?
+		ORDER BY a.transdate DESC, a.id DESC
+            |;
 
-            $sth1 = $dbh->prepare($query);
-            $sth1->execute(
-                 $form->{id}, $ref->{"inventory_accno_id"}, 
-                 -$linetotal, $form->{transdate}, 
-                 $project_id, $ref->{id}
-            ) || $form->dberror($query);
+            my $sth = $dbh->prepare($query);
+            $sth->execute($id);
 
-            $totalqty -= $qty;
-            last if $totalqty == 0;
+            while (my $ref = $sth->fetchrow_hashref(NAME_lc)){
+                my $qty = $ref->{allocated};
+
+                %qty = ($qty > $totalqty) ? $totalqty : $qty;
+
+                $allocated += $qty;
+                my $linetotal = $qty*$ref->{sellprice};
+                push @{ $form->{acc_trans}{lineitems} },
+                  {
+                    chart_id   => $ref->{expense_accno_id},
+                    amount     => $linetotal,
+                    project_id => $project_id,
+                    invoice_id => $ref->{id}
+                  };
+
+                push @{ $form->{acc_trans}{lineitems} },
+                  {
+                    chart_id   => $ref->{inventory_accno_id},
+                    amount     => -$linetotal,
+                    project_id => $project_id,
+                    invoice_id => $ref->{id}
+                  };
+
+                $totalqty -= $qty;
+                $allocated += $qty;
+
+                last if $totalqty == 0;
+            }
         }
+
+        # If we still have less than 0 total quantity, this is not a return
+        # or a void.  Throw an error.  If there are valid workflows that throw
+        # this error, they will require more work to address and will not work
+        # safely with the current system.  -- CT
         if ($totalqty < 0){
             $form->error("Too many reversed items on an invoice");
         }
+        elsif ($totalqty > 0){
+            $form->error("Unexpected and invalid quantity allocated.".
+                   "  Aborting.");
+        }
     }
 
     return $allocated;


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.