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

SF.net SVN: ledger-smb:[5518] trunk/LedgerSMB



Revision: 5518
          http://ledger-smb.svn.sourceforge.net/ledger-smb/?rev=5518&view=rev
Author:   einhverfr
Date:     2013-01-08 10:15:15 +0000 (Tue, 08 Jan 2013)
Log Message:
-----------
New code object model for inventory adjustments

Added Paths:
-----------
    trunk/LedgerSMB/Inventory/
    trunk/LedgerSMB/Inventory/Adjust.pm
    trunk/LedgerSMB/Inventory/Adjust_Line.pm

Added: trunk/LedgerSMB/Inventory/Adjust.pm
===================================================================
--- trunk/LedgerSMB/Inventory/Adjust.pm	                        (rev 0)
+++ trunk/LedgerSMB/Inventory/Adjust.pm	2013-01-08 10:15:15 UTC (rev 5518)
@@ -0,0 +1,192 @@
+=head1 NAME
+
+LedgerSMB::Inventory::Adjust - Inventory Adjustments for LedgerSMB
+
+=head1 SYNPOSIS
+
+ my $adjustment = LedgerSMB::Inventory::Adjust->new(%$request);
+ $adjustment->add_line({parts_id => 1024, expected => 37, counted => 42});
+ $adjustment->lines_from_request($request);
+ $adjustment->save;
+
+=cut
+
+package LedgerSMB::Inventory::Adjust;
+use Moose;
+with 'LedgerSMB::DBObject_Moose';
+use LedgerSMB::MooseTypes;
+use LedgerSMB::Inventory::Adjust_Line;
+
+=head1 DESCRIPTION
+
+This module includes the basic routines for importing inventory adjustments, 
+initial inventory and the like.  Inventory adjustments follow the following 
+rules:
+
+=over
+
+=item Shrinkage and Loss
+
+If the counted is less than expected (the normal case) then an we sell the 
+goods to ourselves at a 100% discount thus recording cost of goods sold for the
+missing parts.
+
+=item More than Expected
+
+In the case where more is counted than expected we purchase the difference 	
+from ourselves at last cost.  This invoice would be expected to be paid using an
+equity account, though this is not currently automated.
+
+=back
+
+The process of counting inventory is a periodic one and therefore this needs to handle both initial inventory import and periodic corrections.
+
+=head1 PROPERTIES
+
+=over
+
+=item id int
+
+This is the id of the report, only valid once stored
+
+=cut
+
+has id => (is => 'rw', isa => 'Int', required => '0');
+
+=item transdate date
+
+This is the date the inventory was counted at.  The invoices take effect on 
+this date.  Required.
+
+=cut
+
+has transdate => (is => 'ro',      isa => 'LedgerSMB::Moose::Date', 
+              coerce => '1',  required => '1');
+
+=item source text
+
+This is the reference number or description of the count, may be the username
+of the individual or the like.
+
+=cut
+
+has source => (is => 'ro', isa => 'Str', required => '1');
+
+=item rows arrayref[LedgerSMB::Inventory::Adjust_Line]
+
+This is a an array of journal entry lines to be added (lines are added one at
+a time.)
+
+=cut
+
+has rows => (is => 'rw', 
+            isa => 'ArrayRef[LedgerSMB::Inventory::Adjust_Line]',
+       required => '0');
+
+
+=back
+
+=head1 METHODS
+
+=over
+
+=item add_line($hashref)
+
+This function adds a line from a hashref.  Typically used by automatic import
+routines and the like.
+
+=cut
+
+sub add_line{
+    my ($self, $hashref) = @_;
+    return if !$hashref->{partnumber} and !$hashref->{parts_id};
+    my $line = LedgerSMB::Inventory::Adjust_Line->new(%$hashref);
+    my @lines = @{$self->rows};
+    push @lines, $line;
+    $self->rows(..hidden..);
+}
+
+=item lines_from_form
+
+This function flattens a form.  It loops from 1 to $hashref->{rowcount}, and 
+for each item found, checks for parts_id_$_ and partnumber_$_.  If either is
+found and counted_$_ is found, it creates a new line with the indexed keys of
+parts_id, partnumber, counted, and expected.
+
+Note that expected is optional and if not defined gets calculated based on the
+date of the report.   This happens during the save process.
+
+This then appends the lines onto the current report's @rows in order to ensure
+that many differnet sources could be combined together in this way.
+
+=cut
+
+sub lines_from_form {
+    my ($self, $hashref) = @_;
+    my @lines;
+    for my $ln (1 .. $hashref->{rowcount}){
+        next if !$hashref->{"counted_$ln"};
+        next if !$hashref->{"partnumber_$ln"} and !$hashref->{"parts_id_$ln"};
+        my $line = LedgerSMB::Inventory::Adjust_Line->new(
+          {parts_id => $hashref->{"parts_id_$ln"},
+         partnumber => $hashref->{"partnumber_$ln"},
+            counted => $hashref->{"counted_$ln"},
+           expected => $hashref->{"expected_$ln"}});
+        push @lines, $line;
+    }
+    my $rows = $self->rows;
+    push @$rows, @lines;
+    $self->rows($rows);
+} 
+
+=item save
+
+This saves the report.  In the process we run every line through a variance 
+check which allows the expected number of parts to be looked up if not provided.
+
+=cut
+
+sub save {
+    my ($self) = @_;
+    my ($ref) = $self->exec_method({funcname => 'inventory_adjust__save_info'});
+    $self->id($ref->{id});
+    for my $row(@{$self->rows}){
+        $row->check_variance($self->transdate);
+        $row->save($self->id);
+    }
+}
+
+=item approve
+
+Approves the inventory adjustment and creates the (draft) AR/AP invoices. 
+These can then be approved, adjusted, have payment lines recorded, and the like.
+
+=cut
+
+sub approve {
+    my ($self) = @_;
+    my ($ref) = $self->exec_method({funcname => 'inventory_adjust__approve'});
+};
+    
+
+=item delete
+
+Deletes the inventory adjustment.  This can only be done if the inventory
+adjustment is not approved.
+
+=cut
+
+sub delete {
+    my ($self) = @_;
+    my ($ref) = $self->exec_method({funcname => 'inventory_adjust__delete'});
+}
+
+=head1 COPYRIGHT
+
+COPYRIGHT (C) 2013 The LedgerSMB Core Team.  This file may be re-used under the
+terms of the LedgerSMB General Public License version 2 or at your option any
+later version.  Please see enclosed LICENSE file for details.
+
+=cut
+
+__PACKAGE__->meta->make_immutable;

Added: trunk/LedgerSMB/Inventory/Adjust_Line.pm
===================================================================
--- trunk/LedgerSMB/Inventory/Adjust_Line.pm	                        (rev 0)
+++ trunk/LedgerSMB/Inventory/Adjust_Line.pm	2013-01-08 10:15:15 UTC (rev 5518)
@@ -0,0 +1,173 @@
+=head1 NAME
+
+LedgerSMB::Inventory::Adjust_Line - Inventory Adjustemnt Lines for LedgerSMB
+
+=head1 SYNPOSIS
+
+ my $line = LedgerSMB::Inventory::Adjust_Line->new(%$hashref);
+ $line->check_variance($date);
+ $line->save($adjustment_set_id);
+
+=cut
+
+package LedgerSMB::Inventory::Adjust_Line;
+use Moose;
+use LedgerSMB::MooseTypes;
+with 'LedgerSMB::DBObject_Moose';
+
+=head1 DESCRIPTION
+
+This module provides the actual inventory check routines for inventory
+adjustments.  This module handles things like checking expected values and the
+like.
+
+=head1 PROPERTIES
+
+=over
+
+=item parts_id int
+
+This is the id of the part.  It is required on saving but not before then as
+it may be looked up.
+
+=cut
+
+has parts_id => (is => 'rw', isa => 'Int', required => 0);
+
+=item partnumber
+
+This matches either the barcode or partnumber of the part.  If there is a 
+conflict, partnumber wins.  Note that this is an exact match, not a prefix
+search.
+
+=cut
+
+has partnumber  => (is => 'rw', isa => 'Str', required => 0);
+
+=item expected
+
+This is the number expected.  If blank we will look up the expected amount from
+the database during the check_variance method.
+
+=cut
+
+has expected => (is => 'rw', isa => 'LedgerSMB::Moose::Number', coerce => 1,
+           required => 0);
+
+=item counted
+
+The number counted.  Obviously for a valid inventory count, we need to have
+this....
+
+=cut
+
+has counted => (is => 'ro', isa => 'LedgerSMB::Moose::Number', coerce => 1,
+          required => 1);
+
+=item variance
+
+This is the variance.  It is usually calculated during the variance check
+or, if expected is set and variance not, on save.
+
+=cut
+
+has variance => (is => 'rw', isa => 'LedgerSMB::Moose::Number', coerce => 1,
+           required => 1);
+
+=item adjust_id int
+
+This is the adjustment set id, usually set during the save process.
+
+=cut
+
+has adjust_id => (is => 'rw', isa => 'Int', required => 0);
+
+=item counted_date date
+
+This is the counted date, usually set during the variance check.
+
+=cut
+
+has counted_date => (is => 'rw', isa => 'LedgerSMB::Moose::Date', coerce => 1,
+               required => 0);
+
+=back
+
+=head1 METHODS
+
+=over
+
+=item search_part($partnumber, $count_on)
+
+This routine searches for a part based on partnumber and returns a hashref with
+the parts_id and counted if it is found.  The $count_on parameter provides an 
+optional date which to use to calculate.  If none is provided, current date is
+used.
+
+=cut
+
+sub search_part{
+    my ($self, $partnumber, $count_on) = @_;
+    my $ref;
+    if ($partnumber){
+        ($ref) = $self->exec_method(
+           {funcname => 'inventory__search_part', 
+                args => [$partnumber, $count_on]}
+        );
+    } else {
+        die 'Bad call for search_part' if !$self->{parts_id};
+        ($ref) = $self->exec_method({funcname => 'inventory__search_part'});
+    }
+    return $ref;
+}
+
+=item check_variance($date)
+
+This routine calculates the variance and sets it as of the date provided.  Note
+that if $self->expected is set, then that value is used instead of calculating
+the value from the database.
+
+=cut
+
+sub check_variance {
+    my ($self, $date) = @_;
+    $self->counted_date($date);
+    if (defined $self->expected){
+        $self->variance($self->counted - $self->expected);
+        return $self->variance;
+    }
+    my $ref;
+    if ($self->parts_id){
+       $ref = $self->search_part;
+    } else {
+       $ref = $self->search_part($self->partnumber, $date);
+       $self->parts_id($ref->{parts_id});
+    }
+    $self->expected($ref->{expected});
+    $self->variance($self->counted - $self->expected);
+    return $self->variance;
+}
+
+=item save($adjustment_id)
+
+Saves the adjustment to the report indicated.
+
+=cut
+
+sub save {
+    my ($self, $adjustment_id) = @_;
+    $self->adjust_id($adjustment_id);
+    die 'No part specified' unless $self->parts_id;
+    $self->check_variance unless defined $self->variance;
+    $self->exec_method({funcname => 'inventory__save_adjust_line'});
+}
+
+=head1 COPYRIGHT
+
+COPYRIGHT (C) 2013 The LedgerSMB Core Team.  This file may be re-used under the
+terms of the LedgerSMB General Public License version 2 or at your option any
+later version.  Please see enclosed LICENSE file for details.
+
+=cut
+
+__PACKAGE__->meta->make_immutable;

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