[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
SF.net SVN: ledger-smb:[4929] trunk/doc/dev_manual
- Subject: SF.net SVN: ledger-smb:[4929] trunk/doc/dev_manual
- From: ..hidden..
- Date: Wed, 20 Jun 2012 10:27:25 +0000
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.