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

SF.net SVN: ledger-smb:[4929] trunk/doc/dev_manual



Revision: 4929
          http://ledger-smb.svn.sourceforge.net/ledger-smb/?rev=4929&view=rev
Author:   einhverfr
Date:     2012-06-20 10:27:24 +0000 (Wed, 20 Jun 2012)
Log Message:
-----------
Still not perfect, but beginnings of reference manual based on developer docs

Added Paths:
-----------
    trunk/doc/dev_manual/LSMB_development_reference.tex
    trunk/doc/dev_manual/metatron.sty
    trunk/doc/dev_manual/model.tex
    trunk/doc/dev_manual/sprocs.tex
    trunk/doc/dev_manual/tables.tex
    trunk/doc/dev_manual/workflow.tex

Added: trunk/doc/dev_manual/LSMB_development_reference.tex
===================================================================
--- trunk/doc/dev_manual/LSMB_development_reference.tex	                        (rev 0)
+++ trunk/doc/dev_manual/LSMB_development_reference.tex	2012-06-20 10:27:24 UTC (rev 4929)
@@ -0,0 +1,16 @@
+\documentclass[usletter twoside]{book}
+\usepackage{metatron}
+\title{LedgerSMB Developer's Reference}
+\begin{document}
+\maketitle
+\part{Database}
+\chapter{Tables}
+\input tables
+\chapter{Stored Procedures}
+\input sprocs
+\part{Perl Modules}
+\chapter{Workflow Modules}
+\input workflow
+\chapter{Model Classes}
+\input model
+\end{document}

Added: trunk/doc/dev_manual/metatron.sty
===================================================================
--- trunk/doc/dev_manual/metatron.sty	                        (rev 0)
+++ trunk/doc/dev_manual/metatron.sty	2012-06-20 10:27:24 UTC (rev 4929)
@@ -0,0 +1,49 @@
+\NeedsTeXFormat{LaTeX2e}
+
+\ProvidesPackage{metatron}
+\RequirePackage{url, palatino, color}
+\RequirePackage[colorlinks, linkcolor=black, urlcolor=black]{hyperref}
+\RequirePackage[margin=3cm]{geometry}
+\newcommand{\product}[1]{#1\texttrademark}
+
+% For centralized management of company information
+\newcommand{\metaname}[1][]{Metatron Technology Consulting#1\space}
+\newcommand{\metaddress}{130 Henderson Terrace \\ Chelan, WA 98816}
+\newcommand{\metaphone}{(509)630-7794}
+
+% Necessary because \url does not allow for variable substitution
+\newcommand{\metaurl}[1][]{\href{http://www.metatrontech.com/#1}
+{http://www.metatrontech.com/#1}
+}
+
+% Simple email functions to make life easier.
+\newcommand{\mailto}[1]{\href{mailto:#1}{#1}}
..hidden..
+
+% Copyright notices (central management)
+% Internal (private) macro for base statements)
..hidden..@copyright}{\textcopyright \space \today \space  
+\metaname}
+
+
+% For redistributables
+\newcommand{\copyrightredist}{
+
..hidden..@copyright.  Permission is granted for verbatim 
+redistribution of this document provided that this copyright notice remains 
+intact. 
+
+}
+
+% For a standard "All rights reserved" copyright notice
+\newcommand{\copyrightstd}{
+
+Copyright ..hidden..@copyright. All rights reserved.
+
+}
+
+% Other copyright notices may be added below.  Please keep them separate from
+% documents so that they can be maintained separately. 
+
+\urlstyle{same}
+\endinput

Added: trunk/doc/dev_manual/model.tex
===================================================================
--- trunk/doc/dev_manual/model.tex	                        (rev 0)
+++ trunk/doc/dev_manual/model.tex	2012-06-20 10:27:24 UTC (rev 4929)
@@ -0,0 +1,13581 @@
+\section{LedgerSMB\label{LedgerSMB}\index{LedgerSMB}}
+
+
+The Base class for many LedgerSMB objects, including DBObject.
+
+\subsection*{SYNOPSIS\label{LedgerSMB_SYNOPSIS}\index{LedgerSMB!SYNOPSIS}}
+
+
+This module creates a basic request handler with utility functions available
+in database objects (LedgerSMB::DBObject)
+
+\subsection*{METHODS\label{LedgerSMB_METHODS}\index{LedgerSMB!METHODS}}
+\begin{description}
+
+\item[{new ()}] \mbox{}
+
+This method creates a new base request instance. It also validates the 
+session/user credentials, as appropriate for the run mode.  Finally, it sets up 
+the database connections for the user.
+
+
+\item[{date\_to\_number (user =$>$ \$LedgerSMB::User,}] \textbf{date =$>$ \$string);}
+
+This function takes the date in the format provided and returns a numeric 
+string in YYMMDD format.  This may be moved to User in the future.
+
+
+\item[{open\_form()}] \mbox{}
+
+This sets a \$self-$>$\{form\_id\} to be used in later form validation (anti-XSRF 
+measure).
+
+
+\item[{check\_form()}] \mbox{}
+
+This returns true if the form\_id was associated with the session, and false if 
+not.  Use this if the form may be re-used (back-button actions are valid).
+
+
+\item[{close\_form()}] \mbox{}
+
+Identical with check\_form() above, but also removes the form\_id from the 
+session.  This should be used when back-button actions are not valid.
+
+
+\item[{debug (file =$>$ \$path);}] \mbox{}
+
+This dumps the current object to the file if that is defined and otherwise to 
+standard output.
+
+
+\item[{escape (string =$>$ \$string);}] \mbox{}
+
+This function returns the current string escaped using \%hexhex notation.
+
+
+\item[{unescape (string =$>$ \$string);}] \mbox{}
+
+This function returns the \$string encoded using \%hexhex using ordinary notation.
+
+
+\item[{format\_amount (user =$>$ \$LedgerSMB::User::hash,}] \textbf{amount =$>$ \$string, precision =$>$ \$integer, neg\_format =$>$ (-$|$DRCR));}
+
+The function takes a monetary amount and formats it according to the user 
+preferences, the negative format (- or DR/CR).  Note that it may move to
+LedgerSMB::User at some point in the future.
+
+
+\item[{parse\_amount (user =$>$ \$LedgerSMB::User::hash,}] \textbf{amount =$>$ \$variable);}
+
+If \$amount is a Bigfloat, it is returned as is.  If it is a string, it is 
+parsed according to the user preferences stored in the LedgerSMB::User object.
+
+
+\item[{is\_blank (name =$>$ \$string)}] \mbox{}
+
+This function returns true if \$self-$>$\{\$string\} only consists of whitespace
+characters or is an empty string.
+
+
+\item[{is\_run\_mode ('(cli$|$cgi$|$mod\_perl)')}] \mbox{}
+
+This function returns 1 if the run mode is what is specified.  Otherwise
+returns 0.
+
+
+\item[{is\_allowed\_role(\{allowed\_roles =$>$ @role\_names\})}] \mbox{}
+
+This function returns 1 if the user's roles include any of the roles in
..hidden..
+
+
+\item[{num\_text\_rows (string =$>$ \$string, cols}] \textbf{=$>$ \$number, max =$>$ \$number);}
+
+This function determines the likely number of rows needed to hold text in a 
+textbox.  It returns either that number or max, which ever is lower.
+
+
+\item[{merge (\$hashref, keys =$>$ @list, index}] \textbf{=$>$ \$number);}
+
+This command merges the \$hashref into the current object.  If keys are 
+specified, only those keys are used.  Otherwise all keys are merged.
+
+
+
+If an index is specified, the merged keys are given a form of 
+"\$key" . "\_\$index", otherwise the key is used on both sides.
+
+
+\item[{redirect (msg =$>$ \$string)}] \mbox{}
+
+This function redirects to the script and argument set determined by 
+\$self-$>$\{callback\}, and if this is not set, goes to an info screen and prints
+\$msg.
+
+
+\item[{redo\_rows (fields =$>$ ..hidden..,}] \textbf{count =$>$ \$integer, [index =$>$ \$string);}
+
+This function is undergoing serious redesign at the moment.  If index is 
+defined, that field is used for ordering the rows.  If not, runningnumber is 
+used.  Behavior is not defined when index points to a field containing 
+non-numbers.
+
+
+\item[{set (@attrs)}] \mbox{}
+
+Copies the given key=$>$vars to \$self. Allows for finer control of 
+merging hashes into self.
+
+
+\item[{remove\_cgi\_globals()}] \mbox{}
+
+Removes all elements starting with a . because these elements conflict with the
+ability to hide the entire structure for things like CSV lookups.
+
+
+\item[{get\_default\_value\_by\_key(\$key)}] \mbox{}
+
+Retrieves a default value for the given key, it is just a wrapper on LedgerSMB::Setting;
+
+
+\item[{call\_procedure( procname =$>$ \$procname,}] \textbf{args =$>$ \$args )}
+
+Function that allows you to call a stored procedure by name and map the appropriate argument to the function values.
+
+
+
+Args is an arrayref.  The members of args can be scalars or arrayrefs in which 
+case they are just bound to the placeholders (arrayref to Pg array conversion
+occurs automatically in DBD::Pg 2.x), or they can be hashrefs of the following
+syntax: \{value =$>$ \$data, type=$>$ \$db\_type\}.  The type field is any SQL type 
+DBD::Pg supports (such as 'PG\_BYTEA').
+
+
+\item[{dberror()}] \mbox{}
+
+Localizes and returns database errors and error codes within LedgerSMB
+
+
+\item[{error()}] \mbox{}
+
+Returns HTML errors in LedgerSMB. Needs refactored into a general Error class.
+
+
+\item[{get\_user\_info()}] \mbox{}
+
+Loads user configuration info from LedgerSMB::User
+
+
+\item[{round\_amount()}] \mbox{}
+
+Uses Math::Float with an amount and a set number of decimal places to round the amount and return it.
+
+
+
+Defaults to the default decimal places setting in the LedgerSMB configuration if there is no places argument passed in.
+
+
+
+They should be changed to allow different rules for different accounts.
+
+
+\item[{sanitize\_for\_display()}] \mbox{}
+
+Expands a hash into human-readable key =$>$ value pairs, and formats and rounds amounts, recursively expanding hashes until there are no hash members present.
+
+
+\item[{take\_top\_level()}] \mbox{}
+
+Removes blank keys and non-reference keys from a hash and returns a hash with only non-blank and referenced keys.
+
+
+\item[{type()}] \mbox{}
+
+Ensures that the \$ENV\{REQUEST\_METHOD\} is defined and either "HEAD", "GET", "POST".
+
+
+\item[{finalize\_request()}] \mbox{}
+
+This function throws a CancelFurtherProcessing exception to be caught
+by the outermost processing script.  This construct allows the outer
+script and intermediate levels to clean up, if required.
+
+
+
+This construct replaces 'exit;' calls randomly scattered
+around the code everywhere.
+
+\end{description}
+\subsection*{Copyright (C) 2006, The LedgerSMB core team.\label{LedgerSMB_Copyright_C_2006_The_LedgerSMB_core_team_}\index{LedgerSMB!Copyright (C) 2006, The LedgerSMB core team.}}
+\begin{verbatim}
+ # This work contains copyrighted information from a number of sources 
+ # all used with permission.
+ #
+ # This file contains source code included with or based on SQL-Ledger
+ # which is Copyright Dieter Simader and DWS Systems Inc. 2000-2005
+ # and licensed under the GNU General Public License version 2 or, at
+ # your option, any later version.  For a full list including contact
+ # information of contributors, maintainers, and copyright holders, 
+ # see the CONTRIBUTORS file.
+ #
+ # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
+ # Copyright (C) 2000
+ #
+ #  Author: DWS Systems Inc.
+ #     Web: http://www.sql-ledger.org
+ #
+ # Contributors: Thomas Bayen <..hidden..>
+ #               Antti Kaihola <..hidden..>
+ #               Moritz Bunkus (tex)
+ #               Jim Rawlings <..hidden..> (DB2)
+ #====================================================================
+=cut
+\end{verbatim}
+
+
+use CGI::Simple;
+\$CGI::Simple::DISABLE\_UPLOADS = 0;
+use LedgerSMB::PGNumber;
+use LedgerSMB::PGDate;
+use LedgerSMB::Sysconfig;
+use Data::Dumper;
+use Error;
+use LedgerSMB::App\_State;
+use LedgerSMB::Auth;
+use LedgerSMB::Session;
+use LedgerSMB::CancelFurtherProcessing;
+use LedgerSMB::Template;
+use LedgerSMB::Locale;
+use LedgerSMB::User;
+use LedgerSMB::Setting;
+use LedgerSMB::Company\_Config;
+use strict;
+use utf8;
+
+
+
+\$CGI::Simple::POST\_MAX = -1;
+
+
+
+package LedgerSMB;
+our \$VERSION = '1.3.999';
+
+
+
+my \$logger = Log::Log4perl-$>$get\_logger('LedgerSMB');
+
+
+
+sub new \{
+    \#my \$type   = "" unless defined shift @\_;
+    \#my \$argstr = "" unless defined shift @\_;
+    (my \$package,my \$filename,my \$line)=caller;
+
+\begin{verbatim}
+    my $type   = shift @_;
+    my $argstr = shift @_;
+    my %cookie;
+    my $self = {};
+\end{verbatim}
+\begin{verbatim}
+    $type = "" unless defined $type;
+    $argstr = "" unless defined $argstr;
+\end{verbatim}
+\begin{verbatim}
+    $logger->debug("Begin called from \$filename=$filename \$line=$line \$type=$type \$argstr=$argstr ref argstr=".ref $argstr);
+\end{verbatim}
+\begin{verbatim}
+    $self->{version} = $VERSION;
+    $self->{dbversion} = "1.3.999";
+\end{verbatim}
+\begin{verbatim}
+    bless $self, $type;
+\end{verbatim}
+\begin{verbatim}
+    my $query;
+    my %params=();
+    if(ref($argstr) eq 'DBI::db')
+    {
+     $self->{dbh}=$argstr;
+     $logger->info("setting dbh from argstr \$self->{dbh}=$self->{dbh}");
+    }
+    else
+    {
+     $query = ($argstr) ? new CGI::Simple($argstr) : new CGI::Simple;
+     # my $params = $query->Vars; returns a tied hash with keys that
+     # are not parameters of the CGI query.
+     %params = $query->Vars;
+     for my $p(keys %params){
+         utf8::decode($params{$p});
+         utf8::upgrade($params{$p});
+     }
+     $logger->debug("params=", Data::Dumper::Dumper(\%params));
+    }
+    $self->{VERSION} = $VERSION;
+    $self->{_request} = $query;
+\end{verbatim}
+\begin{verbatim}
+    $self->merge(\%params);
+    $self->{have_latex} = $LedgerSMB::Sysconfig::latex;
+\end{verbatim}
+\begin{verbatim}
+    # Adding this so that empty values are stored in the db as NULL's.  If
+    # stored procedures want to handle them differently, they must opt to do so.
+    # -- CT
+    for (keys %$self){
+        if ($self->{$_} eq ''){
+            $self->{$_} = undef;
+        }
+    }
+\end{verbatim}
+\begin{verbatim}
+    if ($self->is_run_mode('cgi', 'mod_perl')) {
+        $ENV{HTTP_COOKIE} =~ s/;\s*/;/g;
+        my @cookies = split /;/, $ENV{HTTP_COOKIE};
+        foreach (@cookies) {
+            my ( $name, $value ) = split /=/, $_, 2;
+            $cookie{$name} = $value;
+        }
+    }
+    #HV set _locale already to default here,so routines lower in stack can use it;e.g. login.pl
+    $self->{_locale}=LedgerSMB::Locale->get_handle(${LedgerSMB::Sysconfig::language})
+      or $self->error( __FILE__ . ':' . __LINE__ .": Locale not loaded: $!\n" );
+\end{verbatim}
+\begin{verbatim}
+    $self->{action} = "" unless defined $self->{action};
+    $self->{action} =~ s/\W/_/g;
+    $self->{action} = lc $self->{action};
+\end{verbatim}
+\begin{verbatim}
+    $self->{path} = "" unless defined $self->{path};
+\end{verbatim}
+\begin{verbatim}
+    if ( $self->{path} eq "bin/lynx" ) {
+        $self->{menubar} = 1;
+\end{verbatim}
+\begin{verbatim}
+        # Applying the path is deprecated.  Use menubar instead.  CT.
+        $self->{lynx} = 1;
+        $self->{path} = "bin/lynx";
+    }
+    else {
+        $self->{path} = "bin/mozilla";
+\end{verbatim}
+\begin{verbatim}
+    }
+\end{verbatim}
+\begin{verbatim}
+    $ENV{SCRIPT_NAME} = "" unless defined $ENV{SCRIPT_NAME};
+\end{verbatim}
+\begin{verbatim}
+    $ENV{SCRIPT_NAME} =~ m/([^\/\\]*.pl)\?*.*$/;
+    $self->{script} = $1 unless !defined $1;
+    $self->{script} = "" unless defined $self->{script};
+\end{verbatim}
+\begin{verbatim}
+    if ( ( $self->{script} =~ m#(\.\.|\\|/)# ) ) {
+        $self->error("Access Denied");
+    }
+    if (!$self->{script}) {
+        $self->{script} = 'login.pl';
+    }
+    $logger->debug("\$self->{script} = $self->{script} \$self->{action} = $self->{action}");
+#    if ($self->{action} eq 'migrate_user'){
+#        return $self;
+#    }
+\end{verbatim}
+\begin{verbatim}
+    # This is suboptimal.  We need to have a better way for 1.4
+    #HV we should try to have DBI->connect in one place?
+    #HV  why not trying _db_init also in case of login authenticate? quid logout-function?
+    if ($self->{script} eq 'login.pl' &&
+        ($self->{action} eq 'authenticate'  || $self->{action} eq '__default' 
+                || !$self->{action})){
+        return $self;
+    }
+    if ($self->{script} eq 'setup.pl'){
+        return $self;
+    }
+    my $ccookie;
+    if (!$self->{company} && $self->is_run_mode('cgi', 'mod_perl')){
+         $ccookie = $cookie{${LedgerSMB::Sysconfig::cookie_name}};
+         $ccookie =~ s/.*:([^:]*)$/$1/;
+         if($ccookie ne 'Login') { $self->{company} = $ccookie; } 
+    }
+    $logger->debug("\$ccookie=$ccookie cookie.LedgerSMB::Sysconfig::cookie_name=".$cookie{${LedgerSMB::Sysconfig::cookie_name}}." \$self->{company}=$self->{company}");
+\end{verbatim}
+\begin{verbatim}
+    if(! $cookie{${LedgerSMB::Sysconfig::cookie_name}} && $self->{action} eq 'logout')
+    {
+     $logger->debug("quitting because of logout and no cookie,avoid _db_init");
+     return $self;
+    }
+\end{verbatim}
+\begin{verbatim}
+    #dbh may have been set elsewhere,by DBObject.pm?
+    if(!$self->{dbh})
+    {
+     $self->_db_init;
+    }
+    LedgerSMB::Company_Config::initialize($self);
+\end{verbatim}
+\begin{verbatim}
+    #TODO move before _db_init to avoid _db_init with invalid session?
+    #  Can't do that:  Company_Config has to pull company data from the db --CT
+    if ($self->is_run_mode('cgi', 'mod_perl') and !$ENV{LSMB_NOHEAD}) {
+       #check for valid session unless this is an inital authentication
+       #request -- CT
+       if (!LedgerSMB::Session::check( $cookie{${LedgerSMB::Sysconfig::cookie_name}}, $self) ) {
+            $logger->error("Session did not check");
+            $self->_get_password("Session Expired");
+            exit;
+       }
+       $logger->debug("session_check completed OK \$self->{session_id}=$self->{session_id} caller=\$filename=$filename \$line=$line");
+    }
+    $self->get_user_info;
+\end{verbatim}
+\begin{verbatim}
+    my %date_setting = (
+        'mm/dd/yy' => "SQL, US",
+        'mm-dd-yy' => "POSTGRES, US",
+        'dd/mm/yy' => "SQL, EUROPEAN",
+        'dd-mm-yy' => "POSTGRES, EUROPEAN",
+        'dd.mm.yy' => "GERMAN",
+    );
+\end{verbatim}
+\begin{verbatim}
+    $self->{dbh}->do("set DateStyle to '".$date_setting{$self->{_user}->{dateformat}}."'");
+    #my $locale   = LedgerSMB::Locale->get_handle($self->{_user}->{language})
+    # or $self->error(__FILE__.':'.__LINE__.": Locale not loaded: $!\n");
+    #$self->{_locale} = $locale;
+    $self->{_locale}=LedgerSMB::Locale->get_handle($self->{_user}->{language})
+     or $self->error(__FILE__.':'.__LINE__.": Locale not loaded: $!\n");
+\end{verbatim}
+\begin{verbatim}
+    $self->{stylesheet} = $self->{_user}->{stylesheet};
+\end{verbatim}
+\begin{verbatim}
+    $logger->debug("End");
+\end{verbatim}
+\begin{verbatim}
+    return $self;
+\end{verbatim}
+
+
+\}
+
+
+
+sub open\_form \{
+    my (\$self, \$args) = @\_;
+    if (!\$ENV\{GATEWAY\_INTERFACE\})\{
+        return 1;
+    \}
+    my @vars = \$self-$>$call\_procedure(procname =$>$ 'form\_open', 
+                              args =$>$ [\$self-$>$\{session\_id\}],
+                              continue\_on\_error =$>$ 1
+    );
+    if (\$args-$>$\{commit\})\{
+       \$self-$>$\{dbh\}-$>$commit;
+    \}
+    \$self-$>$\{form\_id\} = \$vars[0]-$>$\{form\_open\};
+\}
+
+
+
+sub check\_form \{
+    my (\$self) = @\_;
+    if (!\$ENV\{GATEWAY\_INTERFACE\})\{
+        return 1;
+    \}
+    my @vars = \$self-$>$call\_procedure(procname =$>$ 'form\_check', 
+                              args =$>$ [\$self-$>$\{session\_id\}, \$self-$>$\{form\_id\}]
+    );
+    return \$vars[0]-$>$\{form\_check\};
+\}
+
+
+
+sub close\_form \{
+    my (\$self) = @\_;
+    if (!\$ENV\{GATEWAY\_INTERFACE\})\{
+        return 1;
+    \}
+    my @vars = \$self-$>$call\_procedure(procname =$>$ 'form\_close', 
+                              args =$>$ [\$self-$>$\{session\_id\}, \$self-$>$\{form\_id\}]
+    );
+    delete \$self-$>$\{form\_id\};
+    return \$vars[0]-$>$\{form\_close\};
+\}
+
+
+
+sub get\_user\_info \{
+    my (\$self) = @\_;
+    \$self-$>$\{\_user\} = LedgerSMB::User-$>$fetch\_config(\$self);
+\}
+\#This function needs to be moved into the session handler.
+sub \_get\_password \{
+    my (\$self) = shift @\_;
+    \$self-$>$\{sessionexpired\} = shift @\_;
+    LedgerSMB::Auth::credential\_prompt();
+    exit;
+\}
+
+
+
+sub debug \{
+    my \$self = shift @\_;
+    my \$args = shift @\_;
+    my \$file;
+    if (scalar keys \%\$args)\{
+        \$file = \$args-$>$\{'file'\};
+    \}
+    my \$d    = Data::Dumper-$>$new( [\$self] );
+    \$d-$>$Sortkeys(1);
+
+\begin{verbatim}
+    if ($file) {
+        open( FH, '>', "$file" ) or die $!;
+        print FH $d->Dump();
+        close(FH);
+    }
+    else {
+        print "\n";
+        print $d->Dump();
+    }
+\end{verbatim}
+
+
+\}
+
+
+
+sub escape \{
+    my \$self = shift;
+    my \%args = @\_;
+    my \$str  = \$args\{string\};
+    \$str = "" unless defined \$str;
+
+\begin{verbatim}
+    my $regex = qr/([^a-zA-Z0-9_.-])/;
+    $str =~ s/$regex/sprintf("%%%02x", ord($1))/ge;
+    return $str;
+}
+\end{verbatim}
+
+
+sub is\_blank \{
+    my \$self = shift @\_;
+    my \%args = @\_;
+    my \$name = \$args\{name\};
+    my \$rc;
+
+\begin{verbatim}
+    if (not defined $name){
+        $self->{_locale} = LedgerSMB::Locale->get_handle('en') unless defined $self->{_locale};
+        $self->error($self->{_locale}->text('Field \"Name\" Not Defined'));
+    }
+\end{verbatim}
+\begin{verbatim}
+    if ( $self->{$name} =~ /^\s*$/ ) {
+        $rc = 1;
+    }
+    else {
+        $rc = 0;
+    }
+    $rc;
+}
+\end{verbatim}
+
+
+sub is\_run\_mode \{
+    my \$self = shift @\_;
+    \#avoid 'uninitialized' warnings in tests
+    my \$mode = shift @\_;
+    my \$rc   = 0;
+    if(! \$mode)\{return \$rc;\}
+    \$mode=lc \$mode;
+    if ( \$mode eq 'cgi' \&\& \$ENV\{GATEWAY\_INTERFACE\} ) \{
+        \$rc = 1;
+    \}
+    elsif ( \$mode eq 'cli' \&\& !( \$ENV\{GATEWAY\_INTERFACE\} $|$$|$ \$ENV\{MOD\_PERL\} ) ) \{
+        \$rc = 1;
+    \}
+    elsif ( \$mode eq 'mod\_perl' \&\& \$ENV\{MOD\_PERL\} ) \{
+        \$rc = 1;
+    \}
+    \$rc;
+\}
+
+
+
+sub num\_text\_rows \{
+    my \$self    = shift @\_;
+    my \%args    = @\_;
+    my \$string  = \$args\{string\};
+    my \$cols    = \$args\{cols\};
+    my \$maxrows = \$args\{max\};
+
+\begin{verbatim}
+    my $rows = 0;
+\end{verbatim}
+\begin{verbatim}
+    for ( split /\n/, $string ) {
+        my $line = $_;
+        while ( length($line) > $cols ) {
+            my $fragment = substr( $line, 0, $cols + 1 );
+            $fragment =~ s/^(.*)\W.*$/$1/;
+            $line =~ s/$fragment//;
+            if ( $line eq $fragment ) {    # No word breaks!
+                $line = "";
+            }
+            ++$rows;
+        }
+        ++$rows;
+    }
+\end{verbatim}
+\begin{verbatim}
+    if ( !defined $maxrows ) {
+        $maxrows = $rows;
+    }
+\end{verbatim}
+\begin{verbatim}
+    return ( $rows > $maxrows ) ? $maxrows : $rows;
+\end{verbatim}
+
+
+\}
+
+
+
+sub redirect \{
+    my \$self = shift @\_;
+    my \%args = @\_;
+    my \$msg  = \$args\{msg\};
+
+\begin{verbatim}
+    if ( $self->{callback} || !$msg ) {
+\end{verbatim}
+\begin{verbatim}
+        main::redirect();
+        exit;
+    }
+    else {
+\end{verbatim}
+\begin{verbatim}
+        $self->info($msg);
+    }
+}
+\end{verbatim}
+
+
+\# TODO:  Either we should have an amount class with formats and such attached
+\# Or maybe we should move this into the user class...
+sub format\_amount \{
+
+\begin{verbatim}
+    # Based on SQL-Ledger's Form::format_amount
+    my $self     = shift @_;
+    my %args  = (ref($_[0]) eq 'HASH')? %{$_[0]}: @_;
+    my $myconfig = $args{user} || $self->{_user};
+    my $amount   = $args{amount};
+    my $places   = $args{precision};
+    my $dash     = $args{neg_format};
+    my $format   = $args{format};
+\end{verbatim}
+\begin{verbatim}
+    if (defined $amount and ! UNIVERSAL::isa($amount, 'LedgerSMB::PGNumber' )) {
+        $amount = $self->parse_amount('user' => $myconfig, 'amount' => $amount);
+    }
+    $dash = undef unless defined $dash;
+\end{verbatim}
+\begin{verbatim}
+    if (!defined $format){
+       $format = $myconfig->{numberformat}
+    }
+    if (!defined $amount){
+        return undef;
+    }
+    if (!defined $args{precision} and defined $args{money}){
+       $places = $LedgerSMB::Sysconfig::decimal_places;
+    }
+\end{verbatim}
+\begin{verbatim}
+    return $amount->to_output({format => $format, 
+                           neg_format => $args{neg_format}, 
+                               places => $places,
+                                money => $args{money},
+           });
+}
+\end{verbatim}
+
+
+\# For backwards compatibility only
+sub parse\_amount \{
+    my \$self     = shift @\_;
+    my \%args     = @\_;
+    my \$amount   = \$args\{amount\};
+    my \$user     = (\$args\{user\})? (\$args\{user\}) : \$self-$>$\{\_user\};
+    if (UNIVERSAL::isa(\$amount, 'LedgerSMB::PGNumber'))\{
+        return \$amount;
+    \} 
+    return LedgerSMB::PGNumber-$>$from\_input(\$amount, 
+                                     \{format =$>$ \$user-$>$\{numberformat\}\}
+    ); 
+\}
+
+
+
+sub round\_amount \{
+
+\begin{verbatim}
+    my ( $self, $amount, $places ) = @_;
+\end{verbatim}
+\begin{verbatim}
+    #
+    # We will grab the default value, if it isnt defined
+    #
+    if (!defined $places){
+       $places = ${LedgerSMB::Sysconfig::decimal_places};
+    }
+\end{verbatim}
+\begin{verbatim}
+    # These rounding rules follow from the previous implementation.
+    # They should be changed to allow different rules for different accounts.
+    if ($amount >= 0) {
+        Math::BigFloat->round_mode('+inf');
+    } 
+    else {
+        Math::BigFloat->round_mode('-inf');
+    }
+\end{verbatim}
+\begin{verbatim}
+    if ($places >= 0) {
+        $amount = Math::BigFloat->new($amount)->ffround( -$places );
+    } 
+    else {
+        $amount = Math::BigFloat->new($amount)->ffround( -( $places - 1 ) );
+    } 
+    $amount->precision(undef);
+\end{verbatim}
+\begin{verbatim}
+    return $amount;
+}
+\end{verbatim}
+
+
+sub call\_procedure \{
+    my \$self     = shift @\_;
+    my \%args     = @\_;
+    my \$procname = \$args\{procname\};
+    my \$schema   = \$args\{schema\};
+    my @call\_args;
+    @call\_args = @\{ \$args\{args\} \} if defined \$args\{args\};
+    my \$order\_by = \$args\{order\_by\};
+    my \$query\_rc;
+    my \$argstr   = "";
+    my @results;
+    my \$dbh = \$LedgerSMB::App\_State::DBH;
+    \$dbh $|$$|$= \$self-$>$\{dbh\};
+    die 'Database handle not found!' if !\$dbh;
+
+\begin{verbatim}
+    if (!defined $procname){
+        $self->error('Undefined function in call_procedure.');
+    }
+    $procname = $dbh->quote_identifier($procname);
+    # Add the test for whether the schema is something useful.
+    $logger->trace("\$procname=$procname");
+\end{verbatim}
+\begin{verbatim}
+    $schema = $schema || $LedgerSMB::Sysconfig::db_namespace;
+\end{verbatim}
+\begin{verbatim}
+    $schema = $dbh->quote_identifier($schema);
+\end{verbatim}
+\begin{verbatim}
+    for my $arg ( @call_args ) {
+        if (eval { $arg->can('to_db') }){
+           $arg = $arg->to_db;
+        }
+        $argstr .= "?, ";
+    }
+    $argstr =~ s/\, $//;
+    my $query = "SELECT * FROM $schema.$procname()";
+    if ($order_by){
+        $query .= " ORDER BY $order_by";
+    }
+    $query =~ s/\(\)/($argstr)/;
+    my $sth = $dbh->prepare($query);
+    my $place = 1;
+    # API Change here to support byteas:  
+    # If the argument is a hashref, allow it to define it's SQL type
+    # for example PG_BYTEA, and use that to bind.  The API supports the old
+    # syntax (array of scalars and arrayrefs) but extends this so that hashrefs
+    # now have special meaning. I expect this to be somewhat recursive in the
+    # future if hashrefs to complex types are added, but we will have to put 
+    # that off for another day. --CT
+    foreach my $carg (@call_args){
+        if (ref($carg) eq 'HASH'){
+            $sth->bind_param($place, $carg->{value}, 
+                       { pg_type => $carg->{type} });
+        } else {
+            $sth->bind_param($place, $carg);
+        }
+        ++$place;
+    }
+    $query_rc = $sth->execute();
+    if (!$query_rc){
+          if ($args{continue_on_error} and  #  only for plpgsql exceptions
+                          ($dbh->state =~ /^P/)){
+                $@ = $dbh->errstr;
+          } else {
+                $self->dberror($dbh->errstr . ": " . $query);
+          }
+    }
+\end{verbatim}
+\begin{verbatim}
+    my @types = @{$sth->{TYPE}};
+    my @names = @{$sth->{NAME_lc}};
+    while ( my $ref = $sth->fetchrow_hashref('NAME_lc') ) {
+        for (0 .. $#names){
+            #   numeric            float4/real
+            if ($types[$_] == 3 or $types[$_] == 2) {
+                $ref->{$names[$_]} = LedgerSMB::PGNumber->from_db($ref->{$names[$_]}, 'datetime') if defined $ref->{$names[$_]};
+            }
+            #    DATE                TIMESTAMP
+            if ($types[$_] == 91 or $types[$_] == 11){
+                $ref->{$names[$_]} = LedgerSMB::PGDate->from_db($ref->{$names[$_]}, 'date') if defined $ref->{$names[$_]};
+            }
+        }
+        push @results, $ref;
+    }
+    return @results;
+}
+\end{verbatim}
+
+
+\# Keeping this here due to common requirements
+sub is\_allowed\_role \{
+    my (\$self, \$args) = @\_;
+    my @roles = @\{\$args-$>$\{allowed\_roles\}\};
+    for my \$role (@roles)\{
+        \$self-$>$\{\_role\_prefix\} = "lsmb\_\$self-$>$\{company\}\_\_" unless defined \$self-$>$\{\_role\_prefix\};
+        my @roleset = grep m/\^{}\$self-$>$\{\_role\_prefix\}\$role\$/, @\{\$self-$>$\{\_roles\}\};
+        if (scalar @roleset)\{
+            return 1;
+        \}
+    \}
+    return 0; 
+\}
+
+
+
+\# This should probably be moved to User too...
+sub date\_to\_number \{
+
+\begin{verbatim}
+    #based on SQL-Ledger's Form::datetonum
+    my $self     = shift @_;
+    my %args     = @_;
+    my $myconfig = $args{user};
+    my $date     = $args{date};
+\end{verbatim}
+\begin{verbatim}
+    $date = "" unless defined $date;
+\end{verbatim}
+\begin{verbatim}
+    my ( $yy, $mm, $dd );
+    if ( $date ne "" && $date && $date =~ /\D/ ) {
+\end{verbatim}
+\begin{verbatim}
+        if ( $date =~ /^\d{4}-\d\d-\d\d$/ ) {
+            ( $yy, $mm, $dd ) = split /\D/, $date;
+        } elsif ( $myconfig->{dateformat} =~ /^yy/ ) {
+            ( $yy, $mm, $dd ) = split /\D/, $date;
+        } elsif ( $myconfig->{dateformat} =~ /^mm/ ) {
+            ( $mm, $dd, $yy ) = split /\D/, $date;
+        } elsif ( $myconfig->{dateformat} =~ /^dd/ ) {
+            ( $dd, $mm, $yy ) = split /\D/, $date;
+        }
+\end{verbatim}
+\begin{verbatim}
+        $dd *= 1;
+        $mm *= 1;
+        $yy += 2000 if length $yy == 2;
+\end{verbatim}
+\begin{verbatim}
+        $dd = substr( "0$dd", -2 );
+        $mm = substr( "0$mm", -2 );
+\end{verbatim}
+\begin{verbatim}
+        $date = "$yy$mm$dd";
+    }
+\end{verbatim}
+\begin{verbatim}
+    $date;
+}
+\end{verbatim}
+
+
+sub sanitize\_for\_display \{
+    my \$self = shift;
+    my \$var = shift;
+    \$self-$>$error('Untested API');
+    if (!\$var)\{ 
+	\$var = \$self;
+    \}
+    for my \$k (keys \%\$var)\{
+	my \$type = ref(\$var);
+	if (UNIVERSAL::isa(\$var-$>$\{\$k\}, 'Math::BigFloat'))\{
+              \$var-$>$\{\$k\} = 
+                  \$self-$>$format\_amount(\{amount =$>$ \$var-$>$\{\$k\}\});
+	\}
+	elsif (\$type == 'HASH')\{
+               \$self-$>$sanitize\_for\_display(\$var-$>$\{\$k\});
+        \}
+    \}
+
+
+
+\}
+
+
+
+sub finalize\_request \{
+    \$logger-$>$debug("throwing CancelFurtherProcessing()");\#if trying to follow flow of request
+    throw CancelFurtherProcessing();
+\}
+
+
+
+\# To be replaced with a generic interface to an Error class
+sub error \{
+
+\begin{verbatim}
+    my ( $self, $msg ) = @_;
+\end{verbatim}
+\begin{verbatim}
+    if ( $ENV{GATEWAY_INTERFACE} ) {
+\end{verbatim}
+\begin{verbatim}
+        $self->{msg}    = $msg;
+        $self->{format} = "html";
+        $logger->error($msg);
+        $logger->error("dbversion: $self->{dbversion}, company: $self->{company}");
+\end{verbatim}
+\begin{verbatim}
+        delete $self->{pre};
+\end{verbatim}
+\begin{verbatim}
+        print qq|Content-Type: text/html; charset=utf-8\n\n|;
+        print "<head><link rel='stylesheet' href='css/$self->{_user}->{stylesheet}' type='text/css'></head>";
+        $self->{msg} =~ s/\n/<br \/>\n/;
+        print
+          qq|<body><h2 class="error">Error!</h2> <p><b>$self->{msg}</b></p>
+             <p>dbversion: $self->{dbversion}, company: $self->{company}</p>
+             </body>|;
+\end{verbatim}
+\begin{verbatim}
+        exit;
+\end{verbatim}
+\begin{verbatim}
+    }
+    else {
+\end{verbatim}
+\begin{verbatim}
+        if ( $ENV{error_function} ) {
+            &{ $ENV{error_function} }($msg);
+        }
+        die "Error: $msg\n";
+    }
+}
+# Database routines used throughout
+\end{verbatim}
+
+
+sub \_db\_init \{
+    my \$self     = shift @\_;
+    my \%args     = @\_;
+    (my \$package,my \$filename,my \$line)=caller;
+    if(\$self-$>$\{dbh\})
+    \{
+     \$logger-$>$error("dbh already set $\backslash$\$self-$>$\{dbh\}=\$self-$>$\{dbh\},called from \$filename");
+    \}
+
+\begin{verbatim}
+    my $creds = LedgerSMB::Auth::get_credentials();
+\end{verbatim}
+\begin{verbatim}
+    $self->{login} = $creds->{login};
+    if (!$self->{company}){ 
+        $self->{company} = $LedgerSMB::Sysconfig::default_db;
+    }
+    my $dbname = $self->{company};
+\end{verbatim}
+\begin{verbatim}
+    # Note that we have to request the login/password again if the db
+    # connection fails since this probably means bad credentials are entered.
+    # Just in case, however, I think it is a good idea to include the DBI
+    # error string.  CT
+    $self->{dbh} = DBI->connect(
+        "dbi:Pg:dbname=$dbname", "$creds->{login}", "$creds->{password}", { AutoCommit => 0 }
+    ); 
+    $logger->debug("DBI->connect dbh=$self->{dbh}");
+    my $dbi_trace=$LedgerSMB::Sysconfig::DBI_TRACE;
+    if($dbi_trace)
+    {
+     $logger->debug("\$dbi_trace=$dbi_trace");
+     $self->{dbh}->trace(split /=/,$dbi_trace,2);#http://search.cpan.org/~timb/DBI-1.616/DBI.pm#TRACING
+    }
+\end{verbatim}
+\begin{verbatim}
+    if (($self->{script} eq 'login.pl') && ($self->{action} eq 
+        'authenticate')){
+        if (!$self->{dbh}){
+            $self->{_auth_error} = $DBI::errstr;
+        }
+        return;
+    }
+    elsif (!$self->{dbh}){
+        $self->_get_password;
+    }
+    $self->{dbh}->{pg_server_prepare} = 0;
+    $self->{dbh}->{pg_enable_utf8} = 1;
+    $LedgerSMB::App_State::DBH = $self->{dbh};
+    $LedgerSMB::App_State::DBName = $dbname;
+\end{verbatim}
+\begin{verbatim}
+    # This is the general version check
+    my $sth = $self->{dbh}->prepare("
+            SELECT value FROM defaults 
+             WHERE setting_key = 'version'");
+    $sth->execute;
+    my ($dbversion) = $sth->fetchrow_array;
+    $sth = $self->{dbh}->prepare("
+            SELECT value FROM defaults 
+             WHERE setting_key = 'role_prefix'");
+    $sth->execute;
+\end{verbatim}
+\begin{verbatim}
+    ($self->{_role_prefix}) = $sth->fetchrow_array;
+    if ($dbversion ne $self->{dbversion}){
+        $self->error("Database is not the expected version.  Was $dbversion, expected $self->{dbversion}.  Please re-run setup.pl against this database to correct.<a href='setup.pl'>setup.pl</a>");
+    }
+\end{verbatim}
+\begin{verbatim}
+    $sth = $self->{dbh}->prepare('SELECT check_expiration()');
+    $sth->execute;
+    ($self->{warn_expire}) = $sth->fetchrow_array;
+\end{verbatim}
+\begin{verbatim}
+    if ($self->{warn_expire}){
+        $sth = $self->{dbh}->prepare('SELECT user__check_my_expiration()');
+        $sth->execute;
+        ($self->{pw_expires})  = $sth->fetchrow_array;
+    }
+\end{verbatim}
+\begin{verbatim}
+    my $query = "SELECT t.extends, 
+                        coalesce (t.table_name, 'custom_' || extends) 
+                        || ':' || f.field_name as field_def
+                FROM custom_table_catalog t
+                JOIN custom_field_catalog f USING (table_id)";
+    $sth = $self->{dbh}->prepare($query);
+    $sth->execute;
+    my $ref;
+    $self->{custom_db_fields} = {};
+    while ( $ref = $sth->fetchrow_hashref('NAME_lc') ) {
+        push @{ $self->{custom_db_fields}->{ $ref->{extends} } },
+          $ref->{field_def};
+    }
+\end{verbatim}
+\begin{verbatim}
+    # Adding role list to self 
+    $self->{_roles} = [];
+    $query = "select rolname from pg_roles 
+               where pg_has_role(SESSION_USER, 'USAGE')";
+    $sth = $self->{dbh}->prepare($query);
+    $sth->execute();
+    while (my @roles = $sth->fetchrow_array){
+        push @{$self->{_roles}}, $roles[0];
+    }
+\end{verbatim}
+\begin{verbatim}
+    $LedgerSMB::App_State::Roles = @{$self->{_roles}};
+    $LedgerSMB::App_State::Role_Prefix = $self->{_role_prefix};
+    # @{$self->{_roles}} will eventually go away. --CT
+\end{verbatim}
+\begin{verbatim}
+    $sth->finish();
+    $logger->debug("end");
+}
+\end{verbatim}
+
+
+\#private, for db connection errors
+sub \_on\_connection\_error \{
+    for (@\_)\{
+        \$logger-$>$error("\$\_");
+    \}
+\}
+
+
+
+sub dberror\{
+   my \$self = shift @\_;
+   my \$state\_error = \{\};
+   my \$locale = \$LedgerSMB::App\_State::Locale;
+   my \$dbh = \$LedgerSMB::App\_State::DBH;
+   \$state\_error = \{
+            '42883' =$>$ \$locale-$>$text('Internal Database Error'),
+            '42501' =$>$ \$locale-$>$text('Access Denied'),
+            '42401' =$>$ \$locale-$>$text('Access Denied'),
+            '22008' =$>$ \$locale-$>$text('Invalid date/time entered'),
+            '22012' =$>$ \$locale-$>$text('Division by 0 error'),
+            '22004' =$>$ \$locale-$>$text('Required input not provided'),
+            '23502' =$>$ \$locale-$>$text('Required input not provided'),
+            '23505' =$>$ \$locale-$>$text('Conflict with Existing Data.  Perhaps you already entered this?'),
+            'P0001' =$>$ \$locale-$>$text('Error from Function:') . "$\backslash$n" .
+                    \$dbh-$>$errstr,
+   \};
+   \$logger-$>$error("Logging SQL State ".\$dbh-$>$state.", error ".
+           \$dbh-$>$err . ", string " .\$dbh-$>$errstr);
+   if (defined \$state\_error-$>$\{\$dbh-$>$state\})\{
+       die \$state\_error-$>$\{\$dbh-$>$state\}
+           . "$\backslash$n" . 
+          \$locale-$>$text('More information has been reported in the error logs');
+       \$dbh-$>$rollback;
+       exit;
+   \}
+   die \$dbh-$>$state . ":" . \$dbh-$>$errstr;
+\}
+
+
+
+sub redo\_rows \{
+
+\begin{verbatim}
+    my $self  = shift @_;
+    my %args  = @_;
+    my @flds  = @{ $args{fields} };
+    my $count = $args{count};
+    my $index = ( $args{index} ) ? $args{index} : 'runningnumber';
+\end{verbatim}
+\begin{verbatim}
+    my @rows;
+    my $i;    # increment counter use only
+    for $i ( 1 .. $count ) {
+        my $temphash = { _inc => $i };
+        for my $fld (@flds) {
+            $temphash->{$fld} = $self->{ "$fld" . "_$i" };
+        }
+        push @rows, $temphash;
+    }
+    $i = 1;
+    for my $row ( sort { $a->{$index} <=> $b->{$index} } @rows ) {
+        for my $fld (@flds) {
+            $self->{ "$fld" . "_$i" } = $row->{$fld};
+        }
+        ++$i;
+    }
+}
+\end{verbatim}
+
+
+sub merge \{
+    (my \$package,my \$filename,my \$line)=caller;
+    my ( \$self, \$src ) = @\_;
+    \$logger-$>$debug("begin caller $\backslash$\$filename=\$filename $\backslash$\$line=\$line");
+       \# Removed dbh from logging string since not used on this api call and
+       \# not initialized in test cases -CT
+    for my \$arg ( \$self, \$src ) \{
+        shift;
+    \}
+    my \%args  = @\_;
+    my @keys;
+    if (defined \$args\{keys\})\{
+         @keys  = @\{ \$args\{keys\} \};
+    \}
+    my \$index = \$args\{index\};
+    if ( !scalar @keys ) \{
+        @keys = keys \%\{\$src\};
+    \}
+    for my \$arg ( @keys ) \{
+        my \$dst\_arg;
+        if (\$index) \{
+            \$dst\_arg = \$arg . "\_\$index";
+        \}
+        else \{
+            \$dst\_arg = \$arg;
+        \}
+        if ( defined \$dst\_arg \&\& defined \$src-$>$\{\$arg\} )
+        \{
+            \$logger-$>$trace("LedgerSMB.pm: merge setting \$dst\_arg to \$src-$>$\{\$arg\}");
+        \}
+        elsif ( !defined \$dst\_arg \&\& defined \$src-$>$\{\$arg\} )
+        \{
+            \$logger-$>$trace("LedgerSMB.pm: merge setting $\backslash$\$dst\_arg is undefined $\backslash$\$src-$>$\{$\backslash$\$arg\} is defined \$src-$>$\{\$arg\}");
+        \}
+        elsif ( defined \$dst\_arg \&\& !defined \$src-$>$\{\$arg\} )
+        \{
+            \$logger-$>$trace("LedgerSMB.pm: merge setting $\backslash$\$dst\_arg is defined \$dst\_arg $\backslash$\$src-$>$\{$\backslash$\$arg\} is undefined");
+        \}
+        elsif ( !defined \$dst\_arg \&\& !defined \$src-$>$\{\$arg\} )
+        \{
+            \$logger-$>$trace("LedgerSMB.pm: merge setting $\backslash$\$dst\_arg is undefined $\backslash$\$src-$>$\{$\backslash$\$arg\} is undefined");
+        \}
+        \$self-$>$\{\$dst\_arg\} = \$src-$>$\{\$arg\};
+    \}
+    \$logger-$>$debug("end caller $\backslash$\$filename=\$filename $\backslash$\$line=\$line");
+\}
+
+
+
+sub type \{
+
+\begin{verbatim}
+    my $self = shift @_;
+\end{verbatim}
+\begin{verbatim}
+    if (!$ENV{REQUEST_METHOD} or 
+        ( !grep {$ENV{REQUEST_METHOD} eq $_} ("HEAD", "GET", "POST") ) ) {
+\end{verbatim}
+\begin{verbatim}
+        $self->error("Request method unset or set to unknown value");
+    }
+\end{verbatim}
+\begin{verbatim}
+    return $ENV{REQUEST_METHOD};
+}
+\end{verbatim}
+
+
+sub DESTROY \{\}
+
+
+
+sub set \{
+
+\begin{verbatim}
+    my $self = shift @_;
+    my %args = @_;
+\end{verbatim}
+\begin{verbatim}
+    for my $arg (keys(%args)) {
+        $self->{$arg} = $args{$arg};
+    }
+    return 1;
+\end{verbatim}
+
+
+\}
+
+
+
+sub remove\_cgi\_globals \{
+    my (\$self) = @\_;
+    for my \$key (keys \%\$self)\{
+        if (\$key =\texttt{\~{}} /\^{}$\backslash$./)\{
+            delete \$self-$>$\{key\}
+        \}
+    \}
+\}
+
+
+
+sub take\_top\_level \{
+   my (\$self) = @\_;
+   my \$return\_hash = \{\};
+   for my \$key (keys \%\$self)\{
+       if (!ref(\$self-$>$\{\$key\}) \&\& \$key !\texttt{\~{}} /\^{}$\backslash$./)\{
+          \$return\_hash-$>$\{\$key\} = \$self-$>$\{\$key\}
+       \}
+   \}
+   return \$return\_hash;
+\}
+
+
+
+sub get\_default\_value\_by\_key 
+\{
+    my (\$self, \$key) = @\_;
+    my \$Settings = LedgerSMB::Setting-$>$new(\{base =$>$ \$self, copy =$>$ 'base'\});
+    \$Settings-$>$\{key\} = \$key;
+    \$Settings-$>$get;    
+    \$Settings-$>$\{value\};    
+\}
+1;
+
+\section{LedgerSMB::DBObject::Business\_Unit\_Class\label{LedgerSMB::DBObject::Business_Unit_Class}\index{LedgerSMB::DBObject::Business\ Unit\ Class}}
+
+
+
+
+\subsection*{SYNOPSYS\label{LedgerSMB::DBObject::Business_Unit_Class_SYNOPSYS}\index{LedgerSMB::DBObject::Business Unit Class!SYNOPSYS}}
+
+
+This holds the information as to the handling of classes of buisness units.  
+Business units are reporting units which can be used to classify various line 
+items of transactions in different ways and include handling for departments, 
+funds, and projects.
+
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Business_Unit_Class_PROPERTIES}\index{LedgerSMB::DBObject::Business Unit Class!PROPERTIES}}
+\begin{description}
+
+\item[{id}] \mbox{}
+
+This is the internal id of the unit class.  It is undef when the class has not
+yet been saved in the database
+
+
+\item[{label}] \mbox{}
+
+This is the human-readible label for the class.  It must be unique among
+classes.
+
+
+\item[{active bool}] \mbox{}
+
+If true, indicates that this will show up on screens.  If not, it will be
+hidden.
+
+
+\item[{modules bool}] \mbox{}
+
+If true, indicates that this will not show up on accounting transaction screens.
+this is indivated for CRM and other applications.
+
+
+\item[{ordering}] \mbox{}
+
+The entry boxes (drop down or text entry) are set arranged from low to high
+by this field on the data entry screens.
+
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Business_Unit_Class_METHODS}\index{LedgerSMB::DBObject::Business Unit Class!METHODS}}
+\begin{description}
+
+\item[{get(\$id)}] \mbox{}
+
+returns the business unit class that corresponds to the id requested.
+
+
+\item[{save}] \mbox{}
+
+Saves the existing buisness unit class to the database, and updates any fields 
+changed in the process.
+
+
+\item[{save\_modules}] \mbox{}
+
+This saves only the module permissions.  This takes the list of modules and prepares an array for the saving and then saves the modules.  This is broken off as a public 
+interface because it makes it possible to activate/deactive regarding modules after the 
+fact without changing anything else.
+
+
+\item[{list}] \mbox{}
+
+Returns a list of all business unit classes.
+
+
+\item[{delete}] \mbox{}
+
+Deletes a business unit class.  Such classes may not have business units attached.
+
+\end{description}
+\subsection*{PREDEFINED CLASSES\label{LedgerSMB::DBObject::Business_Unit_Class_PREDEFINED_CLASSES}\index{LedgerSMB::DBObject::Business Unit Class!PREDEFINED CLASSES}}
+\begin{description}
+
+\item[{Department, ID: 1}] \mbox{}
+\item[{Project, ID: 2}] \mbox{}
+\item[{Job, ID: 3}] \mbox{}
+
+Used for manufacturing lots
+
+
+\item[{Fund, ID: 4}] \mbox{}
+
+Used by non-profits for funds accounting
+
+
+\item[{Customer, ID 5}] \mbox{}
+
+Used in some countries/industries for multi-customer receipts
+
+
+\item[{Vendor, ID 6}] \mbox{}
+
+Used in some countries/industries for multi-vendor payments
+
+\subsection*{COPYRIGHT\label{LedgerSMB::DBObject::Business_Unit_Class_COPYRIGHT}\index{LedgerSMB::DBObject::Business Unit Class!COPYRIGHT}}
+
+
+Copyright (C) 2012 The LedgerSMB Core Team.  This module may be used under the
+GNU GPL in accordance with the LICENSE file listed.
+
+\section{LedgerSMB::DBObject::Business\_Unit\_Class\label{LedgerSMB::DBObject::Business_Unit_Class}\index{LedgerSMB::DBObject::Business\ Unit\ Class}}
+
+
+
+
+\subsection*{SYNOPSYS\label{LedgerSMB::DBObject::Business_Unit_Class_SYNOPSYS}\index{LedgerSMB::DBObject::Business Unit Class!SYNOPSYS}}
+
+
+This holds the information as to the handling of classes of buisness units.  
+Business units are reporting units which can be used to classify various line 
+items of transactions in different ways and include handling for departments, 
+funds, and projects.
+
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Business_Unit_Class_PROPERTIES}\index{LedgerSMB::DBObject::Business Unit Class!PROPERTIES}}
+\begin{description}
+
+\item[{id}] \mbox{}
+
+This is the internal id of the unit class.  It is undef when the class has not
+yet been saved in the database
+
+
+\item[{class\_id}] \mbox{}
+
+Required. Internal id of class (1 for department, 2 for project, etc)
+
+
+\item[{control\_code}] \mbox{}
+
+This is a textual reference to the business reporting unit.  It must be unique
+to the business units of its class.
+
+
+\item[{description}] \mbox{}
+
+Textual description of the reporting unit.
+
+
+\item[{start\_date}] \mbox{}
+
+The first date the business reporting unit is valid.  We use the PGDate class
+here for conversion to/from input and to/from strings for the db.
+
+
+\item[{end\_date}] \mbox{}
+
+The last date the business reporting unit is valid.  We use the PGDate class
+here for conversion to/from input and to/from strings for the db.
+
+
+\item[{parent\_id}] \mbox{}
+
+The internal id of the parent, if applicable.  undef means no parent.
+
+
+\item[{parent}] \mbox{}
+
+A reference to the parent business reporting unit
+
+
+\item[{credit\_id}] \mbox{}
+
+The internal id of the customer, vendor, employee, etc. attached to this 
+unit.
+
+
+\item[{children}] \mbox{}
+
+The children of the current unit, if applicable, and desired.
+
+
+
+This is not set unless get\_tree has already been called.
+
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Business_Unit_Class_METHODS}\index{LedgerSMB::DBObject::Business Unit Class!METHODS}}
+\begin{description}
+
+\item[{get(\$id)}] \mbox{}
+
+Returns the business reporting unit referenced by the id.
+
+
+\item[{save}] \mbox{}
+
+Saves the business reporting unit ot the database and updates changes to object.
+
+
+\item[{list (\$date, \$class\_id, \$credit\_id,}] \textbf{\$strict, \$active\_on)}
+
+Lists all business reporting units active on \$date, for \$credit\_id (or for all
+credit\_ids), and of \$class.  Undef on date and credit\_id match all rows.
+
+
+\item[{delete}] \mbox{}
+
+Deletes the buisness reporting unit.  A unit can only be deleted if it has no 
+children and no transactions attached.
+
+
+\item[{search}] \mbox{}
+
+Returns a list of buisness reporting units matching search criteria.
+
+
+\item[{get\_tree}] \mbox{}
+
+Retrieves children recursively from the database and populates children 
+appropriately
+
+
+\item[{tree\_to\_list}] \mbox{}
+
+Returns tree as a list.
+
+\end{description}
+\subsection*{COPYRIGHT\label{LedgerSMB::DBObject::Business_Unit_Class_COPYRIGHT}\index{LedgerSMB::DBObject::Business Unit Class!COPYRIGHT}}
+
+
+Copyright (C) 2012 The LedgerSMB Core Team.  This module may be used under the
+GNU GPL in accordance with the LICENSE file listed.
+
+\section{LedgerSMB::DBObject\label{LedgerSMB::DBObject}\index{LedgerSMB::DBObject}}
+
+
+LedgerSMB class for building objects from db relations
+
+\subsection*{SYOPSIS\label{LedgerSMB::DBObject_SYOPSIS}\index{LedgerSMB::DBObject!SYOPSIS}}
+
+
+This module creates object instances based on LedgerSMB's in-database ORM.
+
+\subsection*{METHODS\label{LedgerSMB::DBObject_METHODS}\index{LedgerSMB::DBObject!METHODS}}
+\begin{description}
+
+\item[{new (\$class, base =$>$ \$LedgerSMB::hash)}] \mbox{}
+
+This is the base constructor for all child classes.  It must be used with base
+argument because this is necessary for database connectivity and the like.
+
+
+
+Of course the base object can be any object that inherits LedgerSMB, so you can
+use any subclass of that.  The per-session dbh is passed between the objects 
+this way as is any information that is needed.
+
+
+\item[{exec\_method}] \mbox{}
+
+(\$self, procname =$>$ \$function\_name, [args =$>$ ..hidden.., schema =$>$ \$schema,
+continue\_on\_error=$>$\$continue\_on\_error])
+
+
+
+Provides the basic mapping of parameters to the SQL stored procedure function 
+arguments.
+
+
+
+If ..hidden.. is not defined, args are mapped from the object's properties, 
+stripping them of their in\_ prefix.  If schema is provided, that is used 
+instead of PostgreSQL's search path.  If continue\_on\_error is provided and true,
+the operation will not raise an exception in the event of a database error, and 
+it will be up to the application to handle any exceptions.
+
+
+\item[{\_db\_array\_scalars(@elements) creates}] \textbf{a db array from scalars.}
+\item[{\_db\_array\_literal(@elements) creates}] \textbf{a multiple dimension db array from 	preparsed db arrays or other data which does not need to be escaped.}
+\item[{set\_ordering}] \mbox{}
+
+Sets the ordering used by default for specific functions called by exec\_method
+
+
+\item[{run\_custom\_queries}] \mbox{}
+
+Backward-compatible with 1.2 custom query system for moving forward.
+
+\end{description}
+\subsection*{Copyright (C) 2007, The LedgerSMB core team.\label{LedgerSMB::DBObject_Copyright_C_2007_The_LedgerSMB_core_team_}\index{LedgerSMB::DBObject!Copyright (C) 2007, The LedgerSMB core team.}}
+
+
+This file is licensed under the Gnu General Public License version 2, or at your
+option any later version.  A copy of the license should have been included with
+your software.
+
+\section{LedgerSMB::DBObject::Budget\_Report\label{LedgerSMB::DBObject::Budget_Report}\index{LedgerSMB::DBObject::Budget\ Report}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::DBObject::Budget_Report_SYNOPSIS}\index{LedgerSMB::DBObject::Budget Report!SYNOPSIS}}
+
+
+Reporting routines for budgets.  Currently only displays a variance report.
+
+\subsection*{INHERITANCE\label{LedgerSMB::DBObject::Budget_Report_INHERITANCE}\index{LedgerSMB::DBObject::Budget Report!INHERITANCE}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Budget_Report_PROPERTIES}\index{LedgerSMB::DBObject::Budget Report!PROPERTIES}}
+\begin{description}
+
+\item[{id
+The id of the budget}] \mbox{}
+\item[{start\_date The start date of the budget,}] \textbf{inclusive}
+\item[{end\_date The end date of the budget, inclusive}] \mbox{}
+\item[{reference The reference or control code}] \textbf{of the budget}
+\item[{description
+Description of the budget}] \mbox{}
+\item[{entered\_by entity id of the one who entered}] \textbf{the budget}
+\item[{approved\_by entity id of the one who approved}] \textbf{the budget}
+\item[{obsolete\_by entity id of the one who marked}] \textbf{the budget obsolete}
+\item[{entered\_at Timestamp when the budget was}] \textbf{saved}
+\item[{approved\_at Timestamp when the budget was}] \textbf{approved}
+\item[{obsolete\_at Timestamp when the budget was}] \textbf{marked obsolete}
+\item[{entered\_by\_name Name of the entity who}] \textbf{entered the budget}
+\item[{approved\_by\_name Name of the entity who}] \textbf{approved the budget}
+\item[{obsolete\_by\_name Name of the entity who}] \textbf{marked the budget obsolete}
+\item[{department\_id The ID of the department}] \textbf{for which this budget was written}
+\item[{department\_name Name of the department}] \textbf{for which this budget was written}
+\item[{project\_id ID of project for which this}] \textbf{budget was written}
+\item[{projectnumber Project number for which this}] \textbf{budget was written}
+\item[{lines Lines of the report. Each line is}] \textbf{a hashref containing:}\begin{description}
+
+\item[{accno Account number for the account in}] \textbf{question}
+\item[{account\_label Description for the account}] \textbf{in question}
+\item[{account\_id ID for the account in question}] \mbox{}
+\item[{budget\_description Description for the}] \textbf{line item of the budget}
+\item[{budget\_amount
+The amount budgetted}] \mbox{}
+\item[{used\_amount
+The amount actually used}] \mbox{}
+\item[{variance
+budgetted - used}] \mbox{}\end{description}
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Budget_Report_METHODS}\index{LedgerSMB::DBObject::Budget Report!METHODS}}
+\begin{description}
+
+\item[{run\_report(\$id);}] \mbox{}
+
+Takes a blank (base) object and populates with the variance report data provided
+by the id argument.
+
+\end{description}
+\subsection*{COPYRIGHT AND LICENSE\label{LedgerSMB::DBObject::Budget_Report_COPYRIGHT_AND_LICENSE}\index{LedgerSMB::DBObject::Budget Report!COPYRIGHT AND LICENSE}}
+
+
+Copyright (C) 2011 LedgerSMB Core Team.  This file is licensed under the GNU 
+General Public License version 2, or at your option any later version.  Please
+see the included License.txt for details.
+
+\section{LedgerSMB::DBObject::Budget\label{LedgerSMB::DBObject::Budget}\index{LedgerSMB::DBObject::Budget}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::DBObject::Budget_SYNOPSIS}\index{LedgerSMB::DBObject::Budget!SYNOPSIS}}
+
+
+This module provides budget management routines, such as entering budgets,
+approving or rejecting them, and marking them obsolete.  It does not include
+more free-form areas like reporting.  For those, see
+LedgerSMB::DBObject::Budget\_Report.
+
+\subsection*{INHERITANCE\label{LedgerSMB::DBObject::Budget_INHERITANCE}\index{LedgerSMB::DBObject::Budget!INHERITANCE}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Budget_PROPERTIES}\index{LedgerSMB::DBObject::Budget!PROPERTIES}}
+\begin{description}
+
+\item[{\$id INT
+   The id of the budget}] \mbox{}
+\item[{\$start\_date date The start date of the}] \textbf{budget, inclusive}
+\item[{\$end\_date date The end date of the budget,}] \textbf{inclusive}
+\item[{\$reference text This is a text reference}] \textbf{identifier for the budget}
+\item[{\$description text This is a text field}] \textbf{for the budget description. It is searchable.}
+\item[{\$entered\_by int Entity id of the employee}] \textbf{or contractor who entered the budget}
+\item[{\$approved\_by int Entity id of the employee}] \textbf{or contractor who approved the budget}
+\item[{\$obsolete\_by int Entity id for the employee}] \textbf{or contractor who marked the budget obsolete}
+\item[{\$entered\_at timestamp Time the budget}] \textbf{was entered}
+\item[{\$approved\_at timestamp Time the budget}] \textbf{was approved}
+\item[{\$obsolete\_at timestamp Time the budget}] \textbf{was deleted}
+\item[{\$entered\_by\_name text Name of entity}] \textbf{who entered the budget.}
+\item[{\$approved\_by\_name text Name of entity}] \textbf{who approved the budget}
+\item[{\$obsolete\_by\_name text Name of entity}] \textbf{who obsoleted the budget}
+\item[{\$department\_id int ID of department for}] \textbf{which the budget is for}
+\item[{\$department\_name text Name of the department}] \textbf{for which the budget is for}
+\item[{\$project\_id int ID of project of which}] \textbf{the budget is for}
+\item[{\$projectnumber text Text descriptor of}] \textbf{the project of which the budget is for}
..hidden.. These are the actual lines of the}] \textbf{budget. Each one is a hashref containing}\begin{description}
+
+\item[{\$budget\_id int Optional. Don't use. Use}] \textbf{the \$id field of the parent instead.}
+\item[{\$account\_id int The id of the chart of}] \textbf{accounts entry}
+\item[{\$accno text The account number for the}] \textbf{coa entry}
+\item[{\$amount numeric The amount budgetted}] \mbox{}
+\item[{\$description text Description of line item}] \mbox{}\end{description}
+
..hidden.. Where each note is a hashref containing}] \mbox{}\begin{description}
+
+\item[{\$subject string
+   Subject of note}] \mbox{}
+\item[{\$note string
+   The body of the note.}] \mbox{}
+\item[{\$created timestamp This is when the note}] \textbf{was created}
+\item[{\$created\_by string Username of the individual}] \textbf{who created the note at the time of its creation.}\end{description}
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Budget_METHODS}\index{LedgerSMB::DBObject::Budget!METHODS}}
+\begin{description}
+
+\item[{save}] \mbox{}
+
+Saves the current budget.
+
+
+\item[{}] \mbox{}
+\item[{search This method uses the object as the}] \textbf{search criteria. Nulls/undefs match all values. The properties used are:}\begin{description}
+
+\item[{start\_date Matches the start date of the}] \textbf{budget. Full match only.}
+\item[{end\_date Matches the end date of the budget.}] \textbf{Full match only}
+\item[{includes\_date This date is between start}] \textbf{date and end date of budget, inclusive.}
+\item[{reference Partial match on budget reference}] \mbox{}
+\item[{description Full text search against description}] \mbox{}
+\item[{entered\_by
+Exact match of entered by.}] \mbox{}
+\item[{approved\_by
+Exact match of approved by}] \mbox{}
+\item[{department\_id Exact match of department\_id}] \mbox{}
+\item[{project\_id
+Exact match of project\_id}] \mbox{}
+\item[{is\_approved true lists approved budgets,}] \textbf{false lists unapproved budgets. null/undef lists all.}
+\item[{is\_obsolete true lists obsolete budgets.}] \textbf{False lists non-obsolete budgets. null/undef lists all.}\end{description}
+
+\item[{get(id) takes a new (base) object and populates}] \textbf{with info for the budget.}
+\item[{approve
+Marks the budget as approved.}] \mbox{}
+\item[{reject
+Reject and deletes the budget.}] \mbox{}
+\item[{obsolete Marks the budget as obsolete/superceded.}] \mbox{}
+\item[{save\_note(subject string, note string)}] \textbf{Attaches a note with this subject and content to the budget.}
+\item[{list\_projects Lists all projects available}] \textbf{for the start date of the budget.}
+\item[{list\_departments
+Lists all departments}] \mbox{}\end{description}
+\subsection*{SEE ALSO\label{LedgerSMB::DBObject::Budget_SEE_ALSO}\index{LedgerSMB::DBObject::Budget!SEE ALSO}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}
+\item[{LedgerSMB::DBObject::Budget\_Report}] \mbox{}\end{description}
+\subsection*{COPYRIGHT AND LICENSE\label{LedgerSMB::DBObject::Budget_COPYRIGHT_AND_LICENSE}\index{LedgerSMB::DBObject::Budget!COPYRIGHT AND LICENSE}}
+
+
+Copyright (C) 2011 LedgerSMB Core Team.  This file is licensed under the GNU 
+General Public License version 2, or at your option any later version.  Please
+see the included License.txt for details.
+
+\section{LedgerSMB::DBObject::Budget\_Report\label{LedgerSMB::DBObject::Budget_Report}\index{LedgerSMB::DBObject::Budget\ Report}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::DBObject::Budget_Report_SYNOPSIS}\index{LedgerSMB::DBObject::Budget Report!SYNOPSIS}}
+
+
+Reporting routines for budgets.  Currently only displays a variance report.
+
+\subsection*{INHERITANCE\label{LedgerSMB::DBObject::Budget_Report_INHERITANCE}\index{LedgerSMB::DBObject::Budget Report!INHERITANCE}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Budget_Report_PROPERTIES}\index{LedgerSMB::DBObject::Budget Report!PROPERTIES}}
+\begin{description}
+
+\item[{id
+The id of the budget}] \mbox{}
+\item[{start\_date The start date of the budget,}] \textbf{inclusive}
+\item[{end\_date The end date of the budget, inclusive}] \mbox{}
+\item[{reference The reference or control code}] \textbf{of the budget}
+\item[{description
+Description of the budget}] \mbox{}
+\item[{entered\_by entity id of the one who entered}] \textbf{the budget}
+\item[{approved\_by entity id of the one who approved}] \textbf{the budget}
+\item[{obsolete\_by entity id of the one who marked}] \textbf{the budget obsolete}
+\item[{entered\_at Timestamp when the budget was}] \textbf{saved}
+\item[{approved\_at Timestamp when the budget was}] \textbf{approved}
+\item[{obsolete\_at Timestamp when the budget was}] \textbf{marked obsolete}
+\item[{entered\_by\_name Name of the entity who}] \textbf{entered the budget}
+\item[{approved\_by\_name Name of the entity who}] \textbf{approved the budget}
+\item[{obsolete\_by\_name Name of the entity who}] \textbf{marked the budget obsolete}
+\item[{department\_id The ID of the department}] \textbf{for which this budget was written}
+\item[{department\_name Name of the department}] \textbf{for which this budget was written}
+\item[{project\_id ID of project for which this}] \textbf{budget was written}
+\item[{projectnumber Project number for which this}] \textbf{budget was written}
+\item[{lines Lines of the report. Each line is}] \textbf{a hashref containing:}\begin{description}
+
+\item[{accno Account number for the account in}] \textbf{question}
+\item[{account\_label Description for the account}] \textbf{in question}
+\item[{account\_id ID for the account in question}] \mbox{}
+\item[{budget\_description Description for the}] \textbf{line item of the budget}
+\item[{budget\_amount
+The amount budgetted}] \mbox{}
+\item[{used\_amount
+The amount actually used}] \mbox{}
+\item[{variance
+budgetted - used}] \mbox{}\end{description}
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Budget_Report_METHODS}\index{LedgerSMB::DBObject::Budget Report!METHODS}}
+\begin{description}
+
+\item[{run\_report(\$id);}] \mbox{}
+
+Takes a blank (base) object and populates with the variance report data provided
+by the id argument.
+
+\end{description}
+\subsection*{COPYRIGHT AND LICENSE\label{LedgerSMB::DBObject::Budget_Report_COPYRIGHT_AND_LICENSE}\index{LedgerSMB::DBObject::Budget Report!COPYRIGHT AND LICENSE}}
+
+
+Copyright (C) 2011 LedgerSMB Core Team.  This file is licensed under the GNU 
+General Public License version 2, or at your option any later version.  Please
+see the included License.txt for details.
+
+\section{LedgerSMB::DBObject::Budget\label{LedgerSMB::DBObject::Budget}\index{LedgerSMB::DBObject::Budget}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::DBObject::Budget_SYNOPSIS}\index{LedgerSMB::DBObject::Budget!SYNOPSIS}}
+
+
+This module provides budget management routines, such as entering budgets,
+approving or rejecting them, and marking them obsolete.  It does not include
+more free-form areas like reporting.  For those, see
+LedgerSMB::DBObject::Budget\_Report.
+
+\subsection*{INHERITANCE\label{LedgerSMB::DBObject::Budget_INHERITANCE}\index{LedgerSMB::DBObject::Budget!INHERITANCE}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Budget_PROPERTIES}\index{LedgerSMB::DBObject::Budget!PROPERTIES}}
+\begin{description}
+
+\item[{\$id INT
+   The id of the budget}] \mbox{}
+\item[{\$start\_date date The start date of the}] \textbf{budget, inclusive}
+\item[{\$end\_date date The end date of the budget,}] \textbf{inclusive}
+\item[{\$reference text This is a text reference}] \textbf{identifier for the budget}
+\item[{\$description text This is a text field}] \textbf{for the budget description. It is searchable.}
+\item[{\$entered\_by int Entity id of the employee}] \textbf{or contractor who entered the budget}
+\item[{\$approved\_by int Entity id of the employee}] \textbf{or contractor who approved the budget}
+\item[{\$obsolete\_by int Entity id for the employee}] \textbf{or contractor who marked the budget obsolete}
+\item[{\$entered\_at timestamp Time the budget}] \textbf{was entered}
+\item[{\$approved\_at timestamp Time the budget}] \textbf{was approved}
+\item[{\$obsolete\_at timestamp Time the budget}] \textbf{was deleted}
+\item[{\$entered\_by\_name text Name of entity}] \textbf{who entered the budget.}
+\item[{\$approved\_by\_name text Name of entity}] \textbf{who approved the budget}
+\item[{\$obsolete\_by\_name text Name of entity}] \textbf{who obsoleted the budget}
+\item[{\$department\_id int ID of department for}] \textbf{which the budget is for}
+\item[{\$department\_name text Name of the department}] \textbf{for which the budget is for}
+\item[{\$project\_id int ID of project of which}] \textbf{the budget is for}
+\item[{\$projectnumber text Text descriptor of}] \textbf{the project of which the budget is for}
..hidden.. These are the actual lines of the}] \textbf{budget. Each one is a hashref containing}\begin{description}
+
+\item[{\$budget\_id int Optional. Don't use. Use}] \textbf{the \$id field of the parent instead.}
+\item[{\$account\_id int The id of the chart of}] \textbf{accounts entry}
+\item[{\$accno text The account number for the}] \textbf{coa entry}
+\item[{\$amount numeric The amount budgetted}] \mbox{}
+\item[{\$description text Description of line item}] \mbox{}\end{description}
+
..hidden.. Where each note is a hashref containing}] \mbox{}\begin{description}
+
+\item[{\$subject string
+   Subject of note}] \mbox{}
+\item[{\$note string
+   The body of the note.}] \mbox{}
+\item[{\$created timestamp This is when the note}] \textbf{was created}
+\item[{\$created\_by string Username of the individual}] \textbf{who created the note at the time of its creation.}\end{description}
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Budget_METHODS}\index{LedgerSMB::DBObject::Budget!METHODS}}
+\begin{description}
+
+\item[{save}] \mbox{}
+
+Saves the current budget.
+
+
+\item[{}] \mbox{}
+\item[{search This method uses the object as the}] \textbf{search criteria. Nulls/undefs match all values. The properties used are:}\begin{description}
+
+\item[{start\_date Matches the start date of the}] \textbf{budget. Full match only.}
+\item[{end\_date Matches the end date of the budget.}] \textbf{Full match only}
+\item[{includes\_date This date is between start}] \textbf{date and end date of budget, inclusive.}
+\item[{reference Partial match on budget reference}] \mbox{}
+\item[{description Full text search against description}] \mbox{}
+\item[{entered\_by
+Exact match of entered by.}] \mbox{}
+\item[{approved\_by
+Exact match of approved by}] \mbox{}
+\item[{department\_id Exact match of department\_id}] \mbox{}
+\item[{project\_id
+Exact match of project\_id}] \mbox{}
+\item[{is\_approved true lists approved budgets,}] \textbf{false lists unapproved budgets. null/undef lists all.}
+\item[{is\_obsolete true lists obsolete budgets.}] \textbf{False lists non-obsolete budgets. null/undef lists all.}\end{description}
+
+\item[{get(id) takes a new (base) object and populates}] \textbf{with info for the budget.}
+\item[{approve
+Marks the budget as approved.}] \mbox{}
+\item[{reject
+Reject and deletes the budget.}] \mbox{}
+\item[{obsolete Marks the budget as obsolete/superceded.}] \mbox{}
+\item[{save\_note(subject string, note string)}] \textbf{Attaches a note with this subject and content to the budget.}
+\item[{list\_projects Lists all projects available}] \textbf{for the start date of the budget.}
+\item[{list\_departments
+Lists all departments}] \mbox{}\end{description}
+\subsection*{SEE ALSO\label{LedgerSMB::DBObject::Budget_SEE_ALSO}\index{LedgerSMB::DBObject::Budget!SEE ALSO}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}
+\item[{LedgerSMB::DBObject::Budget\_Report}] \mbox{}\end{description}
+\subsection*{COPYRIGHT AND LICENSE\label{LedgerSMB::DBObject::Budget_COPYRIGHT_AND_LICENSE}\index{LedgerSMB::DBObject::Budget!COPYRIGHT AND LICENSE}}
+
+
+Copyright (C) 2011 LedgerSMB Core Team.  This file is licensed under the GNU 
+General Public License version 2, or at your option any later version.  Please
+see the included License.txt for details.
+
+\section{LedgerSMB::DBObject::Budget\_Report\label{LedgerSMB::DBObject::Budget_Report}\index{LedgerSMB::DBObject::Budget\ Report}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::DBObject::Budget_Report_SYNOPSIS}\index{LedgerSMB::DBObject::Budget Report!SYNOPSIS}}
+
+
+Reporting routines for budgets.  Currently only displays a variance report.
+
+\subsection*{INHERITANCE\label{LedgerSMB::DBObject::Budget_Report_INHERITANCE}\index{LedgerSMB::DBObject::Budget Report!INHERITANCE}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Budget_Report_PROPERTIES}\index{LedgerSMB::DBObject::Budget Report!PROPERTIES}}
+\begin{description}
+
+\item[{id
+The id of the budget}] \mbox{}
+\item[{start\_date The start date of the budget,}] \textbf{inclusive}
+\item[{end\_date The end date of the budget, inclusive}] \mbox{}
+\item[{reference The reference or control code}] \textbf{of the budget}
+\item[{description
+Description of the budget}] \mbox{}
+\item[{entered\_by entity id of the one who entered}] \textbf{the budget}
+\item[{approved\_by entity id of the one who approved}] \textbf{the budget}
+\item[{obsolete\_by entity id of the one who marked}] \textbf{the budget obsolete}
+\item[{entered\_at Timestamp when the budget was}] \textbf{saved}
+\item[{approved\_at Timestamp when the budget was}] \textbf{approved}
+\item[{obsolete\_at Timestamp when the budget was}] \textbf{marked obsolete}
+\item[{entered\_by\_name Name of the entity who}] \textbf{entered the budget}
+\item[{approved\_by\_name Name of the entity who}] \textbf{approved the budget}
+\item[{obsolete\_by\_name Name of the entity who}] \textbf{marked the budget obsolete}
+\item[{department\_id The ID of the department}] \textbf{for which this budget was written}
+\item[{department\_name Name of the department}] \textbf{for which this budget was written}
+\item[{project\_id ID of project for which this}] \textbf{budget was written}
+\item[{projectnumber Project number for which this}] \textbf{budget was written}
+\item[{lines Lines of the report. Each line is}] \textbf{a hashref containing:}\begin{description}
+
+\item[{accno Account number for the account in}] \textbf{question}
+\item[{account\_label Description for the account}] \textbf{in question}
+\item[{account\_id ID for the account in question}] \mbox{}
+\item[{budget\_description Description for the}] \textbf{line item of the budget}
+\item[{budget\_amount
+The amount budgetted}] \mbox{}
+\item[{used\_amount
+The amount actually used}] \mbox{}
+\item[{variance
+budgetted - used}] \mbox{}\end{description}
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Budget_Report_METHODS}\index{LedgerSMB::DBObject::Budget Report!METHODS}}
+\begin{description}
+
+\item[{run\_report(\$id);}] \mbox{}
+
+Takes a blank (base) object and populates with the variance report data provided
+by the id argument.
+
+\end{description}
+\subsection*{COPYRIGHT AND LICENSE\label{LedgerSMB::DBObject::Budget_Report_COPYRIGHT_AND_LICENSE}\index{LedgerSMB::DBObject::Budget Report!COPYRIGHT AND LICENSE}}
+
+
+Copyright (C) 2011 LedgerSMB Core Team.  This file is licensed under the GNU 
+General Public License version 2, or at your option any later version.  Please
+see the included License.txt for details.
+
+\section{LedgerSMB::DBObject::Budget\label{LedgerSMB::DBObject::Budget}\index{LedgerSMB::DBObject::Budget}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::DBObject::Budget_SYNOPSIS}\index{LedgerSMB::DBObject::Budget!SYNOPSIS}}
+
+
+This module provides budget management routines, such as entering budgets,
+approving or rejecting them, and marking them obsolete.  It does not include
+more free-form areas like reporting.  For those, see
+LedgerSMB::DBObject::Budget\_Report.
+
+\subsection*{INHERITANCE\label{LedgerSMB::DBObject::Budget_INHERITANCE}\index{LedgerSMB::DBObject::Budget!INHERITANCE}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Budget_PROPERTIES}\index{LedgerSMB::DBObject::Budget!PROPERTIES}}
+\begin{description}
+
+\item[{\$id INT
+   The id of the budget}] \mbox{}
+\item[{\$start\_date date The start date of the}] \textbf{budget, inclusive}
+\item[{\$end\_date date The end date of the budget,}] \textbf{inclusive}
+\item[{\$reference text This is a text reference}] \textbf{identifier for the budget}
+\item[{\$description text This is a text field}] \textbf{for the budget description. It is searchable.}
+\item[{\$entered\_by int Entity id of the employee}] \textbf{or contractor who entered the budget}
+\item[{\$approved\_by int Entity id of the employee}] \textbf{or contractor who approved the budget}
+\item[{\$obsolete\_by int Entity id for the employee}] \textbf{or contractor who marked the budget obsolete}
+\item[{\$entered\_at timestamp Time the budget}] \textbf{was entered}
+\item[{\$approved\_at timestamp Time the budget}] \textbf{was approved}
+\item[{\$obsolete\_at timestamp Time the budget}] \textbf{was deleted}
+\item[{\$entered\_by\_name text Name of entity}] \textbf{who entered the budget.}
+\item[{\$approved\_by\_name text Name of entity}] \textbf{who approved the budget}
+\item[{\$obsolete\_by\_name text Name of entity}] \textbf{who obsoleted the budget}
+\item[{\$department\_id int ID of department for}] \textbf{which the budget is for}
+\item[{\$department\_name text Name of the department}] \textbf{for which the budget is for}
+\item[{\$project\_id int ID of project of which}] \textbf{the budget is for}
+\item[{\$projectnumber text Text descriptor of}] \textbf{the project of which the budget is for}
..hidden.. These are the actual lines of the}] \textbf{budget. Each one is a hashref containing}\begin{description}
+
+\item[{\$budget\_id int Optional. Don't use. Use}] \textbf{the \$id field of the parent instead.}
+\item[{\$account\_id int The id of the chart of}] \textbf{accounts entry}
+\item[{\$accno text The account number for the}] \textbf{coa entry}
+\item[{\$amount numeric The amount budgetted}] \mbox{}
+\item[{\$description text Description of line item}] \mbox{}\end{description}
+
..hidden.. Where each note is a hashref containing}] \mbox{}\begin{description}
+
+\item[{\$subject string
+   Subject of note}] \mbox{}
+\item[{\$note string
+   The body of the note.}] \mbox{}
+\item[{\$created timestamp This is when the note}] \textbf{was created}
+\item[{\$created\_by string Username of the individual}] \textbf{who created the note at the time of its creation.}\end{description}
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Budget_METHODS}\index{LedgerSMB::DBObject::Budget!METHODS}}
+\begin{description}
+
+\item[{save}] \mbox{}
+
+Saves the current budget.
+
+
+\item[{}] \mbox{}
+\item[{search This method uses the object as the}] \textbf{search criteria. Nulls/undefs match all values. The properties used are:}\begin{description}
+
+\item[{start\_date Matches the start date of the}] \textbf{budget. Full match only.}
+\item[{end\_date Matches the end date of the budget.}] \textbf{Full match only}
+\item[{includes\_date This date is between start}] \textbf{date and end date of budget, inclusive.}
+\item[{reference Partial match on budget reference}] \mbox{}
+\item[{description Full text search against description}] \mbox{}
+\item[{entered\_by
+Exact match of entered by.}] \mbox{}
+\item[{approved\_by
+Exact match of approved by}] \mbox{}
+\item[{department\_id Exact match of department\_id}] \mbox{}
+\item[{project\_id
+Exact match of project\_id}] \mbox{}
+\item[{is\_approved true lists approved budgets,}] \textbf{false lists unapproved budgets. null/undef lists all.}
+\item[{is\_obsolete true lists obsolete budgets.}] \textbf{False lists non-obsolete budgets. null/undef lists all.}\end{description}
+
+\item[{get(id) takes a new (base) object and populates}] \textbf{with info for the budget.}
+\item[{approve
+Marks the budget as approved.}] \mbox{}
+\item[{reject
+Reject and deletes the budget.}] \mbox{}
+\item[{obsolete Marks the budget as obsolete/superceded.}] \mbox{}
+\item[{save\_note(subject string, note string)}] \textbf{Attaches a note with this subject and content to the budget.}
+\item[{list\_projects Lists all projects available}] \textbf{for the start date of the budget.}
+\item[{list\_departments
+Lists all departments}] \mbox{}\end{description}
+\subsection*{SEE ALSO\label{LedgerSMB::DBObject::Budget_SEE_ALSO}\index{LedgerSMB::DBObject::Budget!SEE ALSO}}
+\begin{description}
+
+\item[{LedgerSMB}] \mbox{}
+\item[{LedgerSMB::DBObject}] \mbox{}
+\item[{LedgerSMB::DBObject::Budget\_Report}] \mbox{}\end{description}
+\subsection*{COPYRIGHT AND LICENSE\label{LedgerSMB::DBObject::Budget_COPYRIGHT_AND_LICENSE}\index{LedgerSMB::DBObject::Budget!COPYRIGHT AND LICENSE}}
+
+
+Copyright (C) 2011 LedgerSMB Core Team.  This file is licensed under the GNU 
+General Public License version 2, or at your option any later version.  Please
+see the included License.txt for details.
+
+\section{LedgerSMB\label{LedgerSMB}\index{LedgerSMB}}
+
+
+Wx Console
+
+\subsection*{SYNOPSIS\label{LedgerSMB_SYNOPSIS}\index{LedgerSMB!SYNOPSIS}}
+
+
+This is the main window, menu and handler for the LedgerSMB Wx client
+
+\subsection*{METHODS\label{LedgerSMB_METHODS}\index{LedgerSMB!METHODS}}
+\begin{description}
+
+\item[{new()}] \mbox{}
+
+This method creates a new Frame that will work as main window, then it uses Login package poping up
+a small dialog asking for database credentials. Once the database handler is gotten, it will show
+a menu.
+
+
+\item[{\_load\_module()}] \mbox{}
+
+This is the main handler. It will get from the menu \$module and \$action in order to init a \$module-$>$new(\$action).
+
+
+\item[{\$self-$>$\{sesion\}}] \mbox{}
+
+This is a hash reference that works as a container for all that variables shared by the whole program. It will be passed as argument to the modules.
+
+
+
+Initialized by Login module:
+-$>$\{user\} = User logged to database.
+-$>$\{comp\} = Database name.
+-$>$\{serv\} = Server ip or host where the database is listening.
+-$>$\{logo\} = Wx bitmap containing LedgerSMB 200x100 logo.
+-$>$\{ldb\} = LedgerSMB database interface. LSMBDP object with an active connection to database.
+-$>$\{user\_info\} = User full name, etc.
+-$>$\{defaults\} = This is a hash stored into note table on the database. It would be like WX user defaults and each user should have at least a warehouse assigned in order to work.
+
+
+
+Initialized by Console:
+-$>$\{nb\} = It is the NoteBook object that works as window parent.
+
+\end{description}
+\subsection*{AUTHOR\label{LedgerSMB_AUTHOR}\index{LedgerSMB!AUTHOR}}
+
+
+Andres Basile (..hidden..)
+
+\section{LedgerSMB\label{LedgerSMB}\index{LedgerSMB}}
+
+
+Wx LedgerSMB DataBase interface
+
+\subsection*{SYNOPSIS\label{LedgerSMB_SYNOPSIS}\index{LedgerSMB!SYNOPSIS}}
+
+
+This object provides a database abstraction layer for the modules. The idea is to provide an easy way
+to select, update and insert.
+
+\subsection*{METHODS\label{LedgerSMB_METHODS}\index{LedgerSMB!METHODS}}
+\begin{description}
+
+\item[{new (USER, PASSWORD, COMPANY, HOST)}] \mbox{}
+
+This method must recieve database basic information to estabish a connection, then it, will be blassed
+and returned.
+
+
+\item[{getPartsList ([\$part\_id, \$part\_description])}] \mbox{}\end{description}
+\subsection*{AUTHOR\label{LedgerSMB_AUTHOR}\index{LedgerSMB!AUTHOR}}
+
+
+Andres Basile (..hidden..)
+
+\section{LedgerSMB\label{LedgerSMB}\index{LedgerSMB}}
+
+
+Wx Login
+
+\subsection*{SYNOPSIS\label{LedgerSMB_SYNOPSIS}\index{LedgerSMB!SYNOPSIS}}
+
+
+This is a dialog that will pop up at start asking about user, pass and company. This credential is used to get a database handler.
+
+\subsection*{METHODS\label{LedgerSMB_METHODS}\index{LedgerSMB!METHODS}}
+\begin{description}
+
+\item[{new ()}] \mbox{}
+
+This method creates a new Dialog showing an intro login screen. From the class, ShowModal is used to keep the dialog up till a valid handler is created.
+
+
+\item[{Login ()}] \mbox{}
+
+It is an event function that get the text on the fields and tries a connection to the database.
+If the connection is made, it will be saved under ldb key and EndModal with a return 0 code will
+be trigged so the conditional on console.pm will avoid die.
+
+\end{description}
+\subsection*{AUTHOR\label{LedgerSMB_AUTHOR}\index{LedgerSMB!AUTHOR}}
+
+
+Andres Basile (..hidden..)
+
+\section{LedgerSMB\label{LedgerSMB}\index{LedgerSMB}}
+
+
+Wx Inventory Control
+
+\subsection*{SYNOPSIS\label{LedgerSMB_SYNOPSIS}\index{LedgerSMB!SYNOPSIS}}
+
+
+This module is on charge of inventory operations.
+
+\subsection*{METHODS\label{LedgerSMB_METHODS}\index{LedgerSMB!METHODS}}
+\begin{description}
+
+\item[{new (\$sesion, \$action)}] \mbox{}
+
+This will get, set and go an action from the menu that is a method of this class. It will
+work as a kind of handler and will return a reference to that action.
+\$sesion = It is a hash with all objects and variables needed.
+\$action = Method name to invoque as String
+
+
+\item[{Parts ()}] \mbox{}
+
+This is an action that will show a panel asiking for number or description.
+
+
+\item[{\_listPartsByName ()}] \mbox{}
+
+A private function used by the Search action that invoques lsmbdb interface to get parts list from the db.
+
+\end{description}
+\subsection*{AUTHOR\label{LedgerSMB_AUTHOR}\index{LedgerSMB!AUTHOR}}
+
+
+Andres Basile (..hidden..)
+
+\section{LedgerSMB::DBObject::Report::co::Balance\_y\_Mayor\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor}\index{LedgerSMB::DBObject::Report::co::Balance\ y\ Mayor}}
+
+
+Colombian Balance/Ledger Rpt
+
+\subsection*{SYNPOSIS\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor_SYNPOSIS}\index{LedgerSMB::DBObject::Report::co::Balance y Mayor!SYNPOSIS}}
+\begin{verbatim}
+  my $bmreport = LedgerSMB::DBObject::Report::co::Balance_y_Mayor->new(%$request);
+  $bmreport->run;
+  $bmreport->render($request, $format);
+\end{verbatim}
+\subsection*{DESCRIPTION\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor_DESCRIPTION}\index{LedgerSMB::DBObject::Report::co::Balance y Mayor!DESCRIPTION}}
+
+
+This module provides Balance y Mayor reports for LedgerSMB to Colombian 
+standards. This report shows total activity over a time period.
+
+\subsection*{INHERITS\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor_INHERITS}\index{LedgerSMB::DBObject::Report::co::Balance y Mayor!INHERITS}}
+\begin{description}
+
+\item[{LedgerSMB::DBObject::Report;}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor_PROPERTIES}\index{LedgerSMB::DBObject::Report::co::Balance y Mayor!PROPERTIES}}
+\begin{description}
+
+\item[{columns}] \mbox{}
+
+Read-only accessor, returns a list of columns.
+
+\begin{description}
+
+\item[{accno}] \mbox{}
+
+Account Number
+
+
+\item[{description}] \mbox{}
+
+Account name
+
+
+\item[{document\_type}] \mbox{}
+\item[{debits}] \mbox{}
+\item[{credits}] \mbox{}\end{description}
+
+\item[{filter\_template}] \mbox{}
+
+Returns the template name for the filter.
+
+
+\item[{name}] \mbox{}
+
+Returns the localized template name
+
+
+\item[{header\_lines}] \mbox{}
+
+Returns the inputs to display on header.
+
+\subsubsection*{Criteria Properties\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor_Criteria_Properties}\index{LedgerSMB::DBObject::Report::co::Balance y Mayor!Criteria Properties}}
+
+
+Note that in all cases, undef matches everything.
+
+
+\item[{date\_from (text)}] \mbox{}
+
+start date for the report
+
+
+\item[{date\_to}] \mbox{}
+
+End date for the report
+
+\subsection*{METHODS\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor_METHODS}\index{LedgerSMB::DBObject::Report::co::Balance y Mayor!METHODS}}
+\begin{description}
+
+\item[{prepare\_criteria(\$request)}] \mbox{}
+
+Instantiates the PGDate and PGNumber inputs.
+
+
+\item[{run\_report()}] \mbox{}
+
+Runs the report, and assigns rows to \$self-$>$rows.
+
+\subsection*{COPYRIGHT\label{LedgerSMB::DBObject::Report::co::Balance_y_Mayor_COPYRIGHT}\index{LedgerSMB::DBObject::Report::co::Balance y Mayor!COPYRIGHT}}
+
+
+COPYRIGHT (C) 2012 The LedgerSMB Core Team.  This file may be re-used following
+the terms of the GNU General Public License version 2 or at your option any
+later version.  Please see included LICENSE.TXT for details.
+
+\section{LedgerSMB::DBObject::Report::co::Caja\_Diaria\label{LedgerSMB::DBObject::Report::co::Caja_Diaria}\index{LedgerSMB::DBObject::Report::co::Caja\ Diaria}}
+
+
+Caja Diaria Reports (Colombia)
+
+\subsection*{SYNPOSIS\label{LedgerSMB::DBObject::Report::co::Caja_Diaria_SYNPOSIS}\index{LedgerSMB::DBObject::Report::co::Caja Diaria!SYNPOSIS}}
+\begin{verbatim}
+  my $cdreport = LedgerSMB::DBObject::Report::co::Caja_Diaria->new(%$request);
+  $cdreport->run;
+  $cdreport->render($request, $format);
+\end{verbatim}
+\subsection*{DESCRIPTION\label{LedgerSMB::DBObject::Report::co::Caja_Diaria_DESCRIPTION}\index{LedgerSMB::DBObject::Report::co::Caja Diaria!DESCRIPTION}}
+
+
+This module provides Caja Diaria eports for LedgerSMB to Colombian standards.
+These reports provide an overview of cash activity to a set of accounts for a
+specific period.
+
+\subsection*{INHERITS\label{LedgerSMB::DBObject::Report::co::Caja_Diaria_INHERITS}\index{LedgerSMB::DBObject::Report::co::Caja Diaria!INHERITS}}
+\begin{description}
+
+\item[{LedgerSMB::DBObject::Report;}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Report::co::Caja_Diaria_PROPERTIES}\index{LedgerSMB::DBObject::Report::co::Caja Diaria!PROPERTIES}}
+\begin{description}
+
+\item[{columns}] \mbox{}
+
+Read-only accessor, returns a list of columns.
+
+\begin{description}
+
+\item[{accno}] \mbox{}
+
+Account Number
+
+
+\item[{description}] \mbox{}
+
+Account name
+
+
+\item[{document\_type}] \mbox{}
+\item[{debits}] \mbox{}
+\item[{credits}] \mbox{}\end{description}
+
+\item[{filter\_template}] \mbox{}
+
+Returns the template name for the filter.
+
+
+\item[{name}] \mbox{}
+
+Returns the localized template name
+
+
+\item[{header\_lines}] \mbox{}
+
+Returns the inputs to display on header.
+
+\subsubsection*{Criteria Properties\label{LedgerSMB::DBObject::Report::co::Caja_Diaria_Criteria_Properties}\index{LedgerSMB::DBObject::Report::co::Caja Diaria!Criteria Properties}}
+
+
+Note that in all cases, undef matches everything.
+
+
+\item[{date\_from (text)}] \mbox{}
+
+start date for the report
+
+
+\item[{date\_to}] \mbox{}
+
+End date for the report
+
+
+\item[{from\_accno}] \mbox{}
+\item[{to\_accno}] \mbox{}\subsection*{METHODS\label{LedgerSMB::DBObject::Report::co::Caja_Diaria_METHODS}\index{LedgerSMB::DBObject::Report::co::Caja Diaria!METHODS}}
+\begin{description}
+
+\item[{prepare\_criteria(\$request)}] \mbox{}
+
+Instantiates the PGDate and PGNumber inputs.
+
+
+\item[{run\_report()}] \mbox{}
+
+Runs the report, and assigns rows to \$self-$>$rows.
+
+\subsection*{COPYRIGHT\label{LedgerSMB::DBObject::Report::co::Caja_Diaria_COPYRIGHT}\index{LedgerSMB::DBObject::Report::co::Caja Diaria!COPYRIGHT}}
+
+
+COPYRIGHT (C) 2012 The LedgerSMB Core Team.  This file may be re-used following
+the terms of the GNU General Public License version 2 or at your option any
+later version.  Please see included LICENSE.TXT for details.
+
+\section{LedgerSMB::App\_State\label{LedgerSMB::App_State}\index{LedgerSMB::App\ State}}
+
+
+
+
+\subsection*{SYNPOSIS\label{LedgerSMB::App_State_SYNPOSIS}\index{LedgerSMB::App State!SYNPOSIS}}
+
+
+This is a generic container class for non-web-application related state
+information.  It provides a central place to track such things as localization,
+user, and other application state objects.
+
+\subsection*{OBJECTS FOR STORAGE\label{LedgerSMB::App_State_OBJECTS_FOR_STORAGE}\index{LedgerSMB::App State!OBJECTS FOR STORAGE}}
+
+
+The following are objects that are expected to be stored in this namespace:
+
+\begin{description}
+
+\item[{Locale}] \mbox{}
+
+Stores a LedgerSMB::Locale object for the specific user.
+
+
+\item[{User}] \mbox{}
+
+Stores a LedgerSMB::User object for the currently logged in user.
+
+
+\item[{SODA}] \mbox{}
+
+Stores the SODA database access handle.
+
+
+\item[{Company\_Settings}] \mbox{}
+
+Hashref for storing connection-specific settings for the application.
+
+
+\item[{DBH}] \mbox{}
+
+Database handle for current connection
+
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::App_State_METHODS}\index{LedgerSMB::App State!METHODS}}
+\begin{description}
+
+\item[{zero()}] \mbox{}
+
+zeroes out all majro parts.
+
+
+\item[{cleanup}] \mbox{}
+
+Deletes all objects attached here.
+
+\end{description}
+\subsection*{COPYRIGHT\label{LedgerSMB::App_State_COPYRIGHT}\index{LedgerSMB::App State!COPYRIGHT}}
+
+
+Copyright (C) 2009 LedgerSMB Core Team.  This file is licensed under the GNU 
+General Public License version 2, or at your option any later version.  Please
+see the included License.txt for details.
+
+\section{LedgerSMB::DBObject::Report\label{LedgerSMB::DBObject::Report}\index{LedgerSMB::DBObject::Report}}
+
+
+Base Reporting Functionality for LedgerSMB
+
+\subsection*{SYNPOSIS\label{LedgerSMB::DBObject::Report_SYNPOSIS}\index{LedgerSMB::DBObject::Report!SYNPOSIS}}
+
+
+This Perl module provides base utility functions for reporting in LedgerSMB.
+This is intended to be an abstract class, never having direct instances, but
+instead inherited out to other modules.
+
+\subsection*{DESCRIPTION\label{LedgerSMB::DBObject::Report_DESCRIPTION}\index{LedgerSMB::DBObject::Report!DESCRIPTION}}
+
+
+LedgerSMB::DBObject::Report provides basic utility functions for reporting in
+LedgerSMB.  It is an abstract class.  Individual report types MUST inherit this
+out.
+
+
+
+Subclasses MUST define the following subroutines:
+
+\begin{description}
+
+\item[{get\_columns}] \mbox{}
+
+This MUST return a list of hashrefs for the columns per the dynatable block.
+
+\end{description}
+
+
+Additionally, subclasses MAY define any of the following:
+
+\begin{description}
+
+\item[{template}] \mbox{}
+
+Returns the name of the template to be used.  Otherwise a generic
+UI/reports/display\_report template will be used.
+
+\end{description}
+\subsection*{INHERITS\label{LedgerSMB::DBObject::Report_INHERITS}\index{LedgerSMB::DBObject::Report!INHERITS}}
+\begin{description}
+
+\item[{LedgerSMB::DBObject\_Moose}] \mbox{}\end{description}
+\subsection*{PROPERTIES\label{LedgerSMB::DBObject::Report_PROPERTIES}\index{LedgerSMB::DBObject::Report!PROPERTIES}}
+\begin{description}
+
+\item[{cols}] \mbox{}
+
+This is an array of hashrefs.  Properties for each hashref:
+
+\begin{description}
+
+\item[{col\_id}] \mbox{}
+
+ID of column, alphanumeric, used in names of elements, classes, etc.  Required
+for smooth operation.
+
+
+\item[{name}] \mbox{}
+
+Localized name of column for labelling purposes
+
+
+\item[{type}] \mbox{}
+
+Display type of info.  May be text, href, input\_text, checkbox, or radio.  For a
+report, it will typically be text or href.
+
+
+\item[{href\_base}] \mbox{}
+
+Base for href.  Only meaningful if type is href
+
+
+\item[{class}] \mbox{}
+
+CSS class (additional) for the column.
+
+\end{description}
+
+\item[{rows}] \mbox{}
+
+This is an arrayref of rows.  Each row has fields with keys equal to the col\_id
+fields of the columns above.
+
+
+\item[{format}] \mbox{}
+
+This is the format, and must be one used by LedgerSMB::Template.  Options
+expected for 1.4 out of the box include csv, pdf, ps, xls, and ods.  Other
+formats could be supported in the future.  If undefined, defaults html.
+
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Report_METHODS}\index{LedgerSMB::DBObject::Report!METHODS}}
+\begin{description}
+
+\item[{render}] \mbox{}
+
+This takes no arguments and simply renders the report as is.
+
+
+\item[{show\_cols}] \mbox{}
+
+Returns a list of columns based on selected ones from the report
+
+\end{description}
+\subsection*{COPYRIGHT\label{LedgerSMB::DBObject::Report_COPYRIGHT}\index{LedgerSMB::DBObject::Report!COPYRIGHT}}
+
+
+COPYRIGHT (C) 2012 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.
+
+\section{LedgerSMB::DBObject\label{LedgerSMB::DBObject}\index{LedgerSMB::DBObject}}
+
+
+LedgerSMB class for building objects from db relations
+
+\subsection*{SYOPSIS\label{LedgerSMB::DBObject_SYOPSIS}\index{LedgerSMB::DBObject!SYOPSIS}}
+
+
+This module creates object instances based on LedgerSMB's in-database ORM.
+
+\subsection*{METHODS\label{LedgerSMB::DBObject_METHODS}\index{LedgerSMB::DBObject!METHODS}}
+\begin{description}
+
+\item[{new (\$class, base =$>$ \$LedgerSMB::hash)}] \mbox{}
+
+This is the base constructor for all child classes.  It must be used with base
+argument because this is necessary for database connectivity and the like.
+
+
+
+Of course the base object can be any object that inherits LedgerSMB, so you can
+use any subclass of that.  The per-session dbh is passed between the objects 
+this way as is any information that is needed.
+
+
+\item[{exec\_method}] \mbox{}
+
+(\$self, procname =$>$ \$function\_name, [args =$>$ ..hidden.., schema =$>$ \$schema,
+continue\_on\_error=$>$\$continue\_on\_error])
+
+
+
+Provides the basic mapping of parameters to the SQL stored procedure function 
+arguments.
+
+
+
+If ..hidden.. is not defined, args are mapped from the object's properties, 
+stripping them of their in\_ prefix.  If schema is provided, that is used 
+instead of PostgreSQL's search path.  If continue\_on\_error is provided and true,
+the operation will not raise an exception in the event of a database error, and 
+it will be up to the application to handle any exceptions.
+
+
+\item[{\_db\_array\_scalars(@elements) creates}] \textbf{a db array from scalars.}
+\item[{\_db\_array\_literal(@elements) creates}] \textbf{a multiple dimension db array from 	preparsed db arrays or other data which does not need to be escaped.}
+\item[{set\_ordering}] \mbox{}
+
+Sets the ordering used by default for specific functions called by exec\_method
+
+
+\item[{run\_custom\_queries}] \mbox{}
+
+Backward-compatible with 1.2 custom query system for moving forward.
+
+\end{description}
+\subsection*{Copyright (C) 2007, The LedgerSMB core team.\label{LedgerSMB::DBObject_Copyright_C_2007_The_LedgerSMB_core_team_}\index{LedgerSMB::DBObject!Copyright (C) 2007, The LedgerSMB core team.}}
+
+
+This file is licensed under the Gnu General Public License version 2, or at your
+option any later version.  A copy of the license should have been included with
+your software.
+
+
+
+LedgerSMB::Report:  Stub function for custom reports.
+
+
+
+Copyright (c) 2007.  LedgerSMB Core Team
+
+\section{METHODS\label{METHODS}\index{METHODS}}
+\section{DEFINED REPORTS\label{DEFINED_REPORTS}\index{DEFINED REPORTS}}
+\section{ADDING DEFINED REPORTS\label{ADDING_DEFINED_REPORTS}\index{ADDING DEFINED REPORTS}}
+\section{LedgerSMB::DBObject::Saved\_Report: Saved Report Handling for LSMB\label{LedgerSMB::DBObject::Saved_Report:_Saved_Report_Handling_for_LSMB}\index{LedgerSMB::DBObject::Saved\ Report: Saved Report Handling for LSMB}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::DBObject::Saved_Report:_Saved_Report_Handling_for_LSMB_SYNOPSIS}\index{LedgerSMB::DBObject::Saved Report: Saved Report Handling for LSMB!SYNOPSIS}}
+
+
+This module handles saving the reports and retrieving them.
+
+\subsection*{ATTRIBUTES\label{LedgerSMB::DBObject::Saved_Report:_Saved_Report_Handling_for_LSMB_ATTRIBUTES}\index{LedgerSMB::DBObject::Saved Report: Saved Report Handling for LSMB!ATTRIBUTES}}
+
+
+Objects of this package have the following attributes
+
+\begin{description}
+
+\item[{id int}] \mbox{}
+
+Internal id.
+
+
+\item[{description text}] \mbox{}
+
+User-readable name.
+
+
+\item[{module text}] \mbox{}
+
+This tells which perl script runs the report.
+
+
+\item[{action text}] \mbox{}
+
+This provides the entry point on that perl script.
+
+\end{description}
+
+
+Each object may also have:
+
+\begin{description}
+
+\item[{attr}] \mbox{}
+
+This is a two-dimensional text array.  Each row is two elements long.  The first
+element is the attribute name and the second is the value.  These are handled
+by workflow scripts.
+
+\end{description}
+\subsection*{METHODS\label{LedgerSMB::DBObject::Saved_Report:_Saved_Report_Handling_for_LSMB_METHODS}\index{LedgerSMB::DBObject::Saved Report: Saved Report Handling for LSMB!METHODS}}
+\begin{description}
+
+\item[{save}] \mbox{}
+
+This saves the report.
+
+
+\item[{list\_mine}] \mbox{}
+
+This returns a list of blessed saved\_reports.
+
+
+
+The returned list is also saved as @\{\$self-$>$\{search\_results\}\};
+
+
+\item[{get}] \mbox{}
+
+\$self-$>$\{id\} must be set to use this method.
+
+
+
+It retrieves the report, provided it is from the user, and merges it into the 
+current object.
+
+
+\item[{delete}] \mbox{}
+
+\$self-$>$\{id\} must be set to use this method.
+
+
+
+This function deletes the report from the database if the id matches and
+that record was created by the user.
+
+
+
+This returns 1 if successful and 0 if not.
+
+\end{description}
+\subsection*{COPYRIGHT\label{LedgerSMB::DBObject::Saved_Report:_Saved_Report_Handling_for_LSMB_COPYRIGHT}\index{LedgerSMB::DBObject::Saved Report: Saved Report Handling for LSMB!COPYRIGHT}}
+
+
+Copyright 2010, LedgerSMB Core Team.  Licensed under the GNU General Public 
+License version 2.0 or, at your option, any later version.
+
+\section{LedgerSMB::Mailer   Mail output for LedgerSMB\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB}\index{LedgerSMB::Mailer   Mail output for LedgerSMB}}
+
+
+
+
+\subsection*{SYNOPSIS\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB_SYNOPSIS}\index{LedgerSMB::Mailer Mail output for LedgerSMB!SYNOPSIS}}
+\subsection*{COPYRIGHT\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB_COPYRIGHT}\index{LedgerSMB::Mailer Mail output for LedgerSMB!COPYRIGHT}}
+\begin{verbatim}
+ #====================================================================
+ # LedgerSMB
+ # Small Medium Business Accounting software
+ # http://www.ledgersmb.org/
+ #
+ # Copyright (C) 2006
+ # This work contains copyrighted information from a number of sources
+ # all used with permission.
+ #
+ # This file contains source code included with or based on SQL-Ledger
+ # which # is Copyright Dieter Simader and DWS Systems Inc. 2000-2005
+ # and licensed under the GNU General Public License version 2 or, at
+ # your option, any later version.  For a full list including contact
+ # information of contributors, maintainers, and copyright holders,
+ # see the CONTRIBUTORS file.
+ #
+ # Original Copyright Notice from SQL-Ledger 2.6.17 (before the fork):
+ # Copyright (C) 2002
+ #
+ #  Author: DWS Systems Inc.
+ #       Web: http://www.sql-ledger.org
+ #
+ #  Contributors:
+ #
+ # Original Author and copyright holder:
+ # Dieter Simader ..hidden..
+ #====================================================================
+\end{verbatim}
+\subsection*{METHODS\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB_METHODS}\index{LedgerSMB::Mailer Mail output for LedgerSMB!METHODS}}
+\subsubsection*{LedgerSMB::Mailer-$>$new(...)\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB_LedgerSMB::Mailer-_new_}\index{LedgerSMB::Mailer Mail output for LedgerSMB!LedgerSMB::Mailer-$>$new(...)}}
+
+
+Create a new Mailer object.  If any arguments are passed in, a message
+that uses them will be automatically prepared but not sent.
+
+\subsubsection*{\$mail-$>$prepare\_message(to =$>$ \$to, from =$>$ \$from, ...)\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB__mail-_prepare_message_to_to_from_from_}\index{LedgerSMB::Mailer Mail output for LedgerSMB!\$mail-$>$prepare\ message(to =$>$ \$to, from =$>$ \$from, ...)}}
+
+
+Prepares and encodes base message for sending or adding attachments.
+
+\paragraph*{Arguments\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB_Arguments}\index{LedgerSMB::Mailer Mail output for LedgerSMB!Arguments}}
+\begin{description}
+
+\item[{to, from, cc, bcc}] \mbox{}
+
+Address fields for the email.
+
+
+\item[{subject}] \mbox{}
+
+The subject for the email.
+
+
+\item[{message}] \mbox{}
+
+The message body for the email.
+
+
+\item[{contenttype}] \mbox{}
+
+The conttent type for the body of the message, not for any attachments.
+
+
+\item[{notify}] \mbox{}
+
+Sets the Disposition-Notification-To header (read receipt request) for the
+message.  This header will only be added if a from address is set.
+
+\end{description}
+\subsubsection*{\$mail-$>$attach(data =$>$ \$data, filename =$>$ \$name, strip =$>$ \$strip)\label{LedgerSMB::Mailer_Mail_output_for_LedgerSMB__mail-_attach_data_data_filename_name_strip_strip_}\index{LedgerSMB::Mailer Mail output for LedgerSMB!\$mail-$>$attach(data =$>$ \$data, filename =$>$ \$name, strip =$>$ \$strip)}}
+
+
+Add an attachment to the prepared message.  If \$data is specified, use the
+value of that variable as the attachment value, otherwise attach the file
+given by \$name.  If both a filename and data are given, the data is attached
+and given the name from filename.
+
+
+

@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.