Subversion Repositories sql-ledger-old

Compare Revisions

Ignore whitespace Rev 108 → Rev 109

/tags/release_2_0_6-2/.cvsignore
New file
0,0 → 1,2
configure-stamp
build-stamp
/tags/release_2_0_6-2/Makefile
New file
0,0 → 1,34
PACKAGE = sql-ledger
 
MODULES = ap.pl ar.pl ca.pl cp.pl ct.pl gl.pl ic.pl \
ir.pl is.pl oe.pl pe.pl rc.pl rp.pl
SUBDIRS = bin css doc SL locale sql templates users etc
 
LIB_FILES = am.pl favicon.ico login.pl menu.ini setup.pl \
sql-ledger.conf.default VERSION
 
SHR_FILES = sql-ledger.png
 
all:
 
clean:
# find -type l | xargs -r rm
rm -rf debian/sql-ledger
 
install:
mkdir -p $(DESTDIR)/usr/lib/sql-ledger
cp $(LIB_FILES) $(DESTDIR)/usr/lib/sql-ledger
mkdir -p $(DESTDIR)/usr/share/sql-ledger
cp $(SHR_FILES) $(DESTDIR)/usr/share/sql-ledger
 
cd $(DESTDIR)/usr/lib/sql-ledger ; \
ln -sf login.pl admin.pl ; \
ln -sf am.pl menu.pl ; \
set -e ; for module in $(MODULES) ; do \
ln -s am.pl $$module ; \
done ; \
ln -sf /etc/sql-ledger/sql-ledger.conf
 
set -e ; for subdir in $(SUBDIRS) ; do \
$(MAKE) -C $$subdir $@ ; \
done
/tags/release_2_0_6-2/SL/IC.pm
New file
0,0 → 1,864
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Inventory Control backend
#
#======================================================================
 
package IC;
 
 
sub get_part {
my ($self, $myconfig, $form) = @_;
 
# connect to db
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT p.*,
(SELECT accno FROM chart c
WHERE p.inventory_accno_id = c.id) AS inventory_accno,
(SELECT accno FROM chart c
WHERE p.income_accno_id = c.id) AS income_accno,
(SELECT accno FROM chart c
WHERE p.expense_accno_id = c.id) AS expense_accno
FROM parts p
WHERE p.id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my $ref = $sth->fetchrow_hashref(NAME_lc);
 
# copy to $form variables
map { $form->{$_} = $ref->{$_} } ( keys %{ $ref } );
$sth->finish;
# part or service item
$form->{item} = ($form->{inventory_accno}) ? 'part' : 'service';
if ($form->{assembly}) {
$form->{item} = 'assembly';
 
# retrieve assembly items
$query = qq|SELECT p.id, p.partnumber, p.description,
p.sellprice, p.weight, a.qty, p.unit
FROM parts p, assembly a
WHERE a.parts_id = p.id
AND a.id = $form->{id}|;
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
$form->{assembly_rows} = 0;
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
$form->{assembly_rows}++;
foreach my $key ( keys %{ $ref } ) {
$form->{"${key}_$form->{assembly_rows}"} = $ref->{$key};
}
}
$sth->finish;
}
 
# setup accno hash for <option checked> {amount} is used in create_links
$form->{amount}{IC} = $form->{inventory_accno};
$form->{amount}{IC_income} = $form->{income_accno};
$form->{amount}{IC_sale} = $form->{income_accno};
$form->{amount}{IC_expense} = $form->{expense_accno};
$form->{amount}{IC_cogs} = $form->{expense_accno};
 
unless ($form->{item} eq 'service') {
# get makes
if ($form->{makemodel}) {
$query = qq|SELECT name FROM makemodel
WHERE parts_id = $form->{id}|;
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my $i = 1;
while (($form->{"make_$i"}, $form->{"model_$i"}) = split(/:/, $sth->fetchrow_array)) {
$i++;
}
$sth->finish;
$form->{makemodel_rows} = $i - 1;
 
}
}
 
# now get accno for taxes
$query = qq|SELECT c.accno
FROM chart c, partstax pt
WHERE pt.chart_id = c.id
AND pt.parts_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (($key) = $sth->fetchrow_array) {
$form->{amount}{$key} = $key;
}
 
$sth->finish;
 
$dbh->disconnect;
}
 
 
sub save {
my ($self, $myconfig, $form) = @_;
 
($form->{inventory_accno}) = split(/--/, $form->{IC});
($form->{expense_accno}) = split(/--/, $form->{IC_expense});
($form->{income_accno}) = split(/--/, $form->{IC_income});
 
# connect to database, turn off AutoCommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
# save the part
# make up a unique handle and store in partnumber field
# then retrieve the record based on the unique handle to get the id
# replace the partnumber field with the actual variable
# add records for makemodel
 
# if there is a $form->{id} then replace the old entry
# delete all makemodel entries and add the new ones
 
# escape '
map { $form->{$_} =~ s/'/''/g } qw(partnumber description notes unit);
 
# undo amount formatting
map { $form->{$_} = $form->parse_amount($myconfig, $form->{$_}) } qw(rop weight listprice sellprice lastcost);
# set date to NULL if nothing entered
$form->{priceupdate} = ($form->{priceupdate}) ? qq|'$form->{priceupdate}'| : "NULL";
$form->{makemodel} = (($form->{make_1}) || ($form->{model_1})) ? 1 : 0;
 
$form->{alternate} = 0;
$form->{assembly} = ($form->{item} eq 'assembly') ? 1 : 0;
$form->{obsolete} *= 1;
$form->{bom} *= 1;
my ($query, $sth);
if ($form->{id}) {
 
# get old price
$query = qq|SELECT sellprice, weight
FROM parts
WHERE id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my ($sellprice, $weight) = $sth->fetchrow_array;
$sth->finish;
 
# if item is part of an assembly adjust all assemblies
$query = qq|SELECT id, qty
FROM assembly
WHERE parts_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my ($id, $qty) = $sth->fetchrow_array) {
&update_assembly($dbh, $form, $id, $qty * 1, $sellprice * 1, $weight * 1);
}
$sth->finish;
 
 
unless ($form->{item} eq 'service') {
# delete makemodel records
$query = qq|DELETE FROM makemodel
WHERE parts_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
 
if ($form->{item} eq 'assembly') {
if ($form->{onhand} != 0) {
&adjust_inventory($dbh, $form, $form->{id}, $form->{onhand} * -1);
}
# delete assembly records
$query = qq|DELETE FROM assembly
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
# delete tax records
$query = qq|DELETE FROM partstax
WHERE parts_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
} else {
my $uid = time;
$uid .= $form->{login};
 
$query = qq|INSERT INTO parts (partnumber)
VALUES ('$uid')|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|SELECT id FROM parts
WHERE partnumber = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
}
$query = qq|UPDATE parts SET
partnumber = '$form->{partnumber}',
description = '$form->{description}',
makemodel = '$form->{makemodel}',
alternate = '$form->{alternate}',
assembly = '$form->{assembly}',
listprice = $form->{listprice},
sellprice = $form->{sellprice},
lastcost = $form->{lastcost},
weight = $form->{weight},
priceupdate = $form->{priceupdate},
unit = '$form->{unit}',
notes = '$form->{notes}',
rop = $form->{rop},
bin = '$form->{bin}',
inventory_accno_id = (SELECT id FROM chart
WHERE accno = '$form->{inventory_accno}'),
income_accno_id = (SELECT id FROM chart
WHERE accno = '$form->{income_accno}'),
expense_accno_id = (SELECT id FROM chart
WHERE accno = '$form->{expense_accno}'),
obsolete = '$form->{obsolete}',
bom = '$form->{bom}',
image = '$form->{image}',
drawing = '$form->{drawing}',
microfiche = '$form->{microfiche}'
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# insert makemodel records
unless ($form->{item} eq 'service') {
for my $i (1 .. $form->{makemodel_rows}) {
# put make and model together
if (($form->{"make_$i"}) || ($form->{"model_$i"})) {
map { $form->{"${_}_$i"} =~ s/'/''/g } qw(make model);
$query = qq|INSERT INTO makemodel (parts_id, name)
VALUES ($form->{id},
'$form->{"make_$i"}:$form->{"model_$i"}')|;
$dbh->do($query) || $form->dberror($query);
}
}
}
 
 
# insert taxes
foreach $item (split / /, $form->{taxaccounts}) {
if ($form->{"IC_tax_$item"}) {
$query = qq|INSERT INTO partstax (parts_id, chart_id)
VALUES ($form->{id},
(SELECT id
FROM chart
WHERE accno = '$item'))|;
$dbh->do($query) || $form->dberror($query);
}
}
 
# add assembly records
if ($form->{item} eq 'assembly') {
for my $i (1 .. $form->{assembly_rows}) {
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
if ($form->{"qty_$i"} != 0) {
$query = qq|INSERT INTO assembly (id, parts_id, qty)
VALUES ($form->{id}, $form->{"id_$i"}, $form->{"qty_$i"})|;
$dbh->do($query) || $form->dberror($query);
}
}
# adjust onhand for the parts
if ($form->{onhand} != 0) {
&adjust_inventory($dbh, $form, $form->{id}, $form->{onhand});
}
}
 
# commit
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
sub update_assembly {
my ($dbh, $form, $id, $qty, $sellprice, $weight) = @_;
 
my $query = qq|SELECT id, qty
FROM assembly
WHERE parts_id = $id|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my ($pid, $aqty) = $sth->fetchrow_array) {
&update_assembly($dbh, $form, $pid, $aqty * $qty, $sellprice, $weight);
}
$sth->finish;
 
$query = qq|UPDATE parts
SET sellprice = sellprice +
$qty * ($form->{sellprice} - $sellprice),
weight = weight +
$qty * ($form->{weight} - $weight)
WHERE id = $id|;
$dbh->do($query) || $form->dberror($query);
 
}
 
 
 
sub retrieve_assemblies {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $where = '1 = 1';
if ($form->{partnumber}) {
my $partnumber = $form->like(lc $form->{partnumber});
$where .= " AND lower(p.partnumber) LIKE '$partnumber'";
}
if ($form->{description}) {
my $description = $form->like(lc $form->{description});
$where .= " AND lower(p.description) LIKE '$description'";
}
$where .= " AND NOT p.obsolete = '1'";
 
# retrieve assembly items
my $query = qq|SELECT p.id, p.partnumber, p.description,
p.bin, p.onhand, p.rop,
(SELECT sum(p2.inventory_accno_id)
FROM parts p2, assembly a
WHERE p2.id = a.parts_id
AND a.id = p.id) AS inventory
FROM parts p
WHERE $where
AND assembly = '1'|;
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{assembly_items} }, $ref if $ref->{inventory};
}
$sth->finish;
 
$dbh->disconnect;
}
 
 
sub restock_assemblies {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
for my $i (1 .. $form->{rowcount}) {
 
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
 
if ($form->{"qty_$i"} != 0) {
&adjust_inventory($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"});
}
 
}
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
 
}
 
 
sub adjust_inventory {
my ($dbh, $form, $id, $qty) = @_;
 
my $query = qq|SELECT p.id, p.inventory_accno_id, p.assembly, a.qty
FROM parts p, assembly a
WHERE a.parts_id = p.id
AND a.id = $id|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
my $allocate = $qty * $ref->{qty};
# is it a service item, then loop
$ref->{inventory_accno_id} *= 1;
next if (($ref->{inventory_accno_id} == 0) && !$ref->{assembly});
# adjust parts onhand
$form->update_balance($dbh,
"parts",
"onhand",
qq|id = $ref->{id}|,
$allocate * -1);
}
 
$sth->finish;
 
# update assembly
$form->update_balance($dbh,
"parts",
"onhand",
qq|id = $id|,
$qty);
}
 
 
sub delete {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn off AutoCommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
# check if the item is in the invoice table
my $query = qq|SELECT trans_id
FROM invoice
WHERE parts_id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my ($id) = $sth->fetchrow_array;
$sth->finish;
 
if ($id) {
$dbh->disconnect;
return -2;
}
# check if part belongs to an assembly
$query = qq|SELECT id
FROM assembly
WHERE parts_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
($id) = $sth->fetchrow_array;
$sth->finish;
 
if ($id) {
$dbh->disconnect;
return -3;
}
 
# check if the item is in the orderitems table
my $query = qq|SELECT trans_id
FROM orderitems
WHERE parts_id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my ($id) = $sth->fetchrow_array;
$sth->finish;
 
if ($id) {
$dbh->disconnect;
return -4;
}
$query = qq|DELETE FROM parts
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM partstax
WHERE parts_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# check if it is a part, assembly or service
if ($form->{item} eq 'part') {
$query = qq|DELETE FROM makemodel
WHERE parts_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
 
if ($form->{item} eq 'assembly') {
$query = qq|DELETE FROM assembly
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
if ($form->{item} eq 'alternate') {
$query = qq|DELETE FROM alternate
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
 
# commit
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
sub assembly_item {
my ($self, $myconfig, $form) = @_;
 
my $i = $form->{assembly_rows};
my $partnumber = $form->like(lc $form->{"partnumber_$i"});
my $description = $form->like(lc $form->{"description_$i"});
my $where = "1 = 1";
 
if ($partnumber) {
$where .= " AND lower(partnumber) LIKE '$partnumber'";
}
if ($description) {
$where .= " AND lower(description) LIKE '$description'";
}
if ($form->{id}) {
$where .= " AND NOT id = $form->{id}";
}
 
if ($partnumber) {
$where .= " ORDER BY partnumber";
} else {
$where .= " ORDER BY description";
}
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT id, partnumber, description, sellprice, weight,
onhand, unit
FROM parts
WHERE $where|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{item_list} }, $ref;
}
$sth->finish;
$dbh->disconnect;
}
 
 
sub all_parts {
my ($self, $myconfig, $form) = @_;
 
my $where = '1 = 1';
my $var;
foreach my $item (qw(partnumber drawing microfiche)) {
if ($form->{$item}) {
$var = $form->like(lc $form->{$item});
$where .= " AND lower(p.$item) LIKE '$var'";
}
}
# special case for description
if ($form->{description}) {
unless ($form->{bought} || $form->{sold} || $form->{onorder} || $form->{ordered}) {
$var = $form->like(lc $form->{description});
$where .= " AND lower(p.description) LIKE '$var'";
}
}
 
if ($form->{searchitems} eq 'part') {
$where .= " AND p.inventory_accno_id > 0";
}
if ($form->{searchitems} eq 'assembly') {
$form->{bought} = "";
$where .= " AND p.assembly = '1'";
}
if ($form->{searchitems} eq 'service') {
$where .= " AND p.inventory_accno_id IS NULL AND NOT p.assembly = '1'";
# irrelevant for services
$form->{make} = $form->{model} = "";
}
 
# items which were never bought, sold or on an order
if ($form->{itemstatus} eq 'orphaned') {
$form->{onhand} = $form->{short} = 0;
$form->{bought} = $form->{sold} = 0;
$form->{onorder} = $form->{ordered} = 0;
$form->{transdatefrom} = $form->{transdateto} = "";
$where .= " AND p.onhand = 0
AND p.id NOT IN (SELECT p.id FROM parts p, invoice i
WHERE p.id = i.parts_id)
AND p.id NOT IN (SELECT p.id FROM parts p, assembly a
WHERE p.id = a.parts_id)
AND p.id NOT IN (SELECT p.id FROM parts p, orderitems o
WHERE p.id = o.parts_id)";
}
if ($form->{itemstatus} eq 'active') {
$where .= " AND p.obsolete = '0'";
}
if ($form->{itemstatus} eq 'obsolete') {
$where .= " AND p.obsolete = '1'";
$form->{onhand} = $form->{short} = 0;
}
if ($form->{itemstatus} eq 'onhand') {
$where .= " AND p.onhand > 0";
}
if ($form->{itemstatus} eq 'short') {
$where .= " AND p.onhand < 0";
}
 
if ($form->{make}) {
$var = $form->like(lc $form->{make}.":");
$where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
FROM makemodel m WHERE lower(m.name) LIKE '$var')";
}
if ($form->{model}) {
$var = $form->like(lc ":".$form->{model});
$where .= " AND p.id IN (SELECT DISTINCT ON (m.parts_id) m.parts_id
FROM makemodel m WHERE lower(m.name) LIKE '$var')";
}
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $sortorder = join ', ', $form->sort_columns(qw(partnumber description bin priceupdate));
$sortorder = $form->{sort} unless $sortorder;
 
my $query = qq|SELECT p.id, p.partnumber, p.description, p.onhand, p.unit,
p.bin, p.sellprice, p.listprice, p.lastcost, p.rop, p.weight,
p.priceupdate, p.image, p.drawing, p.microfiche
FROM parts p
WHERE $where
ORDER BY $sortorder|;
 
# rebuild query for bought and sold items
if ($form->{bought} || $form->{sold} || $form->{onorder} || $form->{ordered}) {
my $union = "";
$query = "";
if ($form->{bought} || $form->{sold}) {
my $invwhere = "$where
AND i.parts_id = p.id AND i.trans_id = a.id";
$invwhere .= " AND i.assemblyitem = '0'";
$invwhere .= " AND a.transdate >= '$form->{transdatefrom}'" if $form->{transdatefrom};
$invwhere .= " AND a.transdate <= '$form->{transdateto}'" if $form->{transdateto};
 
if ($form->{description}) {
$var = $form->like(lc $form->{description});
$invwhere .= " AND lower(i.description) LIKE '$var'";
}
 
my $flds = qq|p.id, p.partnumber, i.description,
i.qty AS onhand, i.unit, p.bin, i.sellprice,
p.listprice, p.lastcost, p.rop, p.weight,
p.priceupdate, p.image, p.drawing, p.microfiche,
a.invnumber, a.ordnumber, i.trans_id|;
 
if ($form->{bought}) {
$query = qq|
SELECT $flds, 'ir' AS module, '' AS type,
1 AS exchangerate
FROM parts p, invoice i, ap a
WHERE $invwhere|;
$union = "
UNION";
}
 
if ($form->{sold}) {
$query .= qq|$union
SELECT $flds, 'is' AS module, '' AS type,
1 As exchangerate
FROM parts p, invoice i, ar a
WHERE $invwhere|;
$union = "
UNION";
}
}
 
if ($form->{onorder} || $form->{ordered}) {
my $ordwhere = "$where
AND o.closed = '0'
AND oi.parts_id = p.id AND oi.trans_id = o.id";
$ordwhere .= " AND o.transdate >= '$form->{transdatefrom}'" if $form->{transdatefrom};
$ordwhere .= " AND o.transdate <= '$form->{transdateto}'" if $form->{transdateto};
 
if ($form->{description}) {
$var = $form->like(lc $form->{description});
$ordwhere .= " AND lower(oi.description) LIKE '$var'";
}
 
$flds = qq|p.id, p.partnumber, oi.description,
oi.qty AS onhand, oi.unit, p.bin, oi.sellprice,
p.listprice, p.lastcost, p.rop, p.weight,
p.priceupdate, p.image, p.drawing, p.microfiche,
'' AS invnumber, o.ordnumber, oi.trans_id|;
 
if ($form->{ordered}) {
$query .= qq|$union
SELECT $flds, 'oe' AS module, 'sales_order' AS type,
(SELECT buy FROM exchangerate ex
WHERE ex.curr = o.curr
AND ex.transdate = o.transdate) AS exchangerate
FROM parts p, orderitems oi, oe o
WHERE $ordwhere
AND o.customer_id > 0|;
$union = "
UNION";
}
if ($form->{onorder}) {
$flds = qq|p.id, p.partnumber, oi.description,
oi.qty * -1 AS onhand, oi.unit, p.bin, oi.sellprice,
p.listprice, p.lastcost, p.rop, p.weight,
p.priceupdate, p.image, p.drawing, p.microfiche,
'' AS invnumber, o.ordnumber, oi.trans_id|;
 
$query .= qq|$union
SELECT $flds, 'oe' AS module, 'purchase_order' AS type,
(SELECT sell FROM exchangerate ex
WHERE ex.curr = o.curr
AND ex.transdate = o.transdate) AS exchangerate
FROM parts p, orderitems oi, oe o
WHERE $ordwhere
AND o.vendor_id > 0|;
}
 
}
 
$query .= qq|
ORDER BY $sortorder|;
 
}
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{parts} }, $ref;
}
 
$sth->finish;
 
 
# include individual items for assemblies
if ($form->{searchitems} eq 'assembly' && $form->{bom}) {
foreach $item (@{ $form->{parts} }) {
push @assemblies, $item;
$query = qq|SELECT p.id, p.partnumber, p.description, a.qty AS onhand,
p.unit, p.bin,
p.sellprice, p.listprice, p.lastcost,
p.rop, p.weight, p.priceupdate,
p.image, p.drawing, p.microfiche
FROM parts p, assembly a
WHERE p.id = a.parts_id
AND a.id = $item->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
$ref->{assemblyitem} = 1;
push @assemblies, $ref;
}
$sth->finish;
 
push @assemblies, {id => $item->{id}};
 
}
 
# copy assemblies to $form->{parts}
@{ $form->{parts} } = @assemblies;
}
 
$dbh->disconnect;
 
}
 
 
sub create_links {
my ($self, $module, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT accno, description, link
FROM chart
WHERE link LIKE '%$module%'
ORDER BY accno|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
foreach my $key (split(/:/, $ref->{link})) {
if ($key =~ /$module/) {
push @{ $form->{"${module}_links"}{$key} }, { accno => $ref->{accno},
description => $ref->{description} };
}
}
}
 
$sth->finish;
 
if ($form->{id}) {
$query = qq|SELECT weightunit
FROM defaults|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{weightunit}) = $sth->fetchrow_array;
$sth->finish;
 
} else {
$query = qq|SELECT weightunit, current_date
FROM defaults|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{weightunit}, $form->{priceupdate}) = $sth->fetchrow_array;
$sth->finish;
}
$dbh->disconnect;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/AM.pm
New file
0,0 → 1,694
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Administration module
# Chart of Accounts
# template routines
# preferences
#
#======================================================================
 
package AM;
 
 
sub get_account {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT accno, description, charttype, gifi_accno,
category, link
FROM chart
WHERE id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $ref = $sth->fetchrow_hashref(NAME_lc);
foreach my $key (keys %$ref) {
$form->{"$key"} = $ref->{"$key"};
}
 
$sth->finish;
 
 
# get default accounts
$query = qq|SELECT inventory_accno_id, income_accno_id, expense_accno_id
FROM defaults|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
 
map { $form->{$_} = $ref->{$_} } keys %ref;
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub save_account {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn off AutoCommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
# sanity check, can't have AR with AR_...
if ($form->{AR} || $form->{AP} || $form->{IC}) {
map { delete $form->{$_} } qw(AR_amount AR_tax AR_paid AP_amount AP_tax AP_paid IC_sale IC_cogs IC_taxpart IC_income IC_expense IC_taxservice);
}
$form->{link} = "";
foreach my $item ($form->{AR},
$form->{AR_amount},
$form->{AR_tax},
$form->{AR_paid},
$form->{AP},
$form->{AP_amount},
$form->{AP_tax},
$form->{AP_paid},
$form->{IC},
$form->{IC_sale},
$form->{IC_cogs},
$form->{IC_taxpart},
$form->{IC_income},
$form->{IC_expense},
$form->{IC_taxservice},
$form->{CT_tax}
) {
$form->{link} .= "${item}:" if ($item);
}
chop $form->{link};
 
# if we have an id then replace the old record
$form->{description} =~ s/'/''/g;
 
# strip blanks from accno
map { $form->{$_} =~ s/ //g; } qw(accno gifi_accno);
my ($query, $sth);
if ($form->{id}) {
$query = qq|UPDATE chart SET
accno = '$form->{accno}',
description = '$form->{description}',
charttype = '$form->{charttype}',
gifi_accno = '$form->{gifi_accno}',
category = '$form->{category}',
link = '$form->{link}'
WHERE id = $form->{id}|;
} else {
$query = qq|INSERT INTO chart
(accno, description, charttype, gifi_accno, category, link)
VALUES ('$form->{accno}', '$form->{description}',
'$form->{charttype}', '$form->{gifi_accno}',
'$form->{category}', '$form->{link}')|;
}
$dbh->do($query) || $form->dberror($query);
 
if ($form->{IC_taxpart} || $form->{IC_taxservice} || $form->{CT_tax}) {
 
my $chart_id = $form->{id};
unless ($form->{id}) {
# get id from chart
$query = qq|SELECT id
FROM chart
WHERE accno = '$form->{accno}'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($chart_id) = $sth->fetchrow_array;
$sth->finish;
}
# add account if it doesn't exist in tax
$query = qq|SELECT chart_id
FROM tax
WHERE chart_id = $chart_id|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my ($tax_id) = $sth->fetchrow_array;
$sth->finish;
# add tax if it doesn't exist
unless ($tax_id) {
$query = qq|INSERT INTO tax (chart_id, rate)
VALUES ($chart_id, 0)|;
$dbh->do($query) || $form->dberror($query);
}
} else {
# remove tax
if ($form->{id}) {
$query = qq|DELETE FROM tax
WHERE chart_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
}
 
 
# commit
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
sub delete_account {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn off AutoCommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
# delete chart of account record
$query = qq|DELETE FROM chart
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# set inventory_accno_id, income_accno_id, expense_accno_id to defaults
$query = qq|UPDATE parts
SET inventory_accno_id =
(SELECT inventory_accno_id FROM defaults)
WHERE inventory_accno_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
$query = qq|UPDATE parts
SET income_accno_id =
(SELECT income_accno_id FROM defaults)
WHERE income_accno_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
$query = qq|UPDATE parts
SET expense_accno_id =
(SELECT expense_accno_id FROM defaults)
WHERE expense_accno_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
foreach my $table (qw(partstax customertax vendortax tax)) {
$query = qq|DELETE FROM $table
WHERE chart_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
 
# commit and redirect
my $rc = $dbh->commit;
$dbh->disconnect;
$rc;
 
}
 
 
sub gifi_accounts {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT accno, description
FROM gifi
ORDER BY accno|;
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{ALL} }, $ref;
}
 
$sth->finish;
$dbh->disconnect;
}
 
 
 
sub get_gifi {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $query = qq|SELECT accno, description
FROM gifi
WHERE accno = '$form->{accno}'|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub save_gifi {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
$form->{description} =~ s/'/''/g;
$form->{accno} =~ s/ //g;
 
# id is the old account number!
if ($form->{id}) {
$query = qq|UPDATE gifi SET
accno = '$form->{accno}',
description = '$form->{description}'
WHERE accno = '$form->{id}'|;
} else {
$query = qq|INSERT INTO gifi
(accno, description)
VALUES ('$form->{accno}', '$form->{description}')|;
}
$dbh->do($query) || $form->dberror($query);
$dbh->disconnect;
 
}
 
 
sub delete_gifi {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
# id is the old account number!
$query = qq|DELETE FROM gifi
WHERE accno = '$form->{id}'|;
$dbh->do($query) || $form->dberror($query);
$dbh->disconnect;
 
}
 
 
sub load_template {
my ($self, $form) = @_;
open(TEMPLATE, "$form->{file}") or $form->error("$form->{file} : $!");
 
while (<TEMPLATE>) {
$form->{body} .= $_;
}
 
close(TEMPLATE);
 
}
 
 
sub save_template {
my ($self, $form) = @_;
open(TEMPLATE, ">$form->{file}") or $form->error("$form->{file} : $!");
# strip
$form->{body} =~ s/\r\n/\n/g;
print TEMPLATE $form->{body};
 
close(TEMPLATE);
 
}
 
 
 
sub save_preferences {
my ($self, $myconfig, $form, $memberfile, $userspath) = @_;
 
map { ($form->{$_}) = split /--/, $form->{$_} } qw(inventory_accno income_accno expense_accno fxgain_accno fxloss_accno);
my @a;
$form->{curr} =~ s/ //g;
map { push(@a, uc pack "A3", $_) if $_ } split /:/, $form->{curr};
$form->{curr} = join ':', @a;
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
# these defaults are database wide
# user specific variables are in myconfig
# save defaults
my $query = qq|UPDATE defaults SET
inventory_accno_id =
(SELECT id FROM chart
WHERE accno = '$form->{inventory_accno}'),
income_accno_id =
(SELECT id FROM chart
WHERE accno = '$form->{income_accno}'),
expense_accno_id =
(SELECT id FROM chart
WHERE accno = '$form->{expense_accno}'),
fxgain_accno_id =
(SELECT id FROM chart
WHERE accno = '$form->{fxgain_accno}'),
fxloss_accno_id =
(SELECT id FROM chart
WHERE accno = '$form->{fxloss_accno}'),
invnumber = '$form->{invnumber}',
sonumber = '$form->{sonumber}',
ponumber = '$form->{ponumber}',
yearend = '$form->{yearend}',
curr = '$form->{curr}',
weightunit = '$form->{weightunit}',
businessnumber = '$form->{businessnumber}'
|;
$dbh->do($query) || $form->dberror($query);
 
# update name
my $name = $form->{name};
$name =~ s/'/''/g;
$query = qq|UPDATE employee
SET name = '$name'
WHERE login = '$form->{login}'|;
$dbh->do($query) || $form->dberror($query);
foreach my $item (split / /, $form->{taxaccounts}) {
$query = qq|UPDATE tax
SET rate = |.($form->{$item} / 100).qq|,
taxnumber = '$form->{"taxnumber_$item"}'
WHERE chart_id = $item|;
$dbh->do($query) || $form->dberror($query);
}
 
my $rc = $dbh->commit;
$dbh->disconnect;
 
# save first currency in myconfig
$form->{currency} = substr($form->{curr},0,3);
my $myconfig = new User "$memberfile", "$form->{login}";
foreach my $item (keys %$form) {
$myconfig->{$item} = $form->{$item};
}
 
$myconfig->save_member($memberfile, $userspath);
 
$rc;
}
 
 
sub defaultaccounts {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
# get defaults from defaults table
my $query = qq|SELECT * FROM defaults|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
$form->{defaults} = $sth->fetchrow_hashref(NAME_lc);
$form->{defaults}{IC} = $form->{defaults}{inventory_accno_id};
$form->{defaults}{IC_income} = $form->{defaults}{income_accno_id};
$form->{defaults}{IC_expense} = $form->{defaults}{expense_accno_id};
$form->{defaults}{FX_gain} = $form->{defaults}{fxgain_accno_id};
$form->{defaults}{FX_loss} = $form->{defaults}{fxloss_accno_id};
$sth->finish;
 
 
$query = qq|SELECT id, accno, description, link
FROM chart
WHERE link LIKE '%IC%'
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $self->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
foreach my $key (split(/:/, $ref->{link})) {
if ($key =~ /IC/) {
$nkey = $key;
if ($key =~ /cogs/) {
$nkey = "IC_expense";
}
if ($key =~ /sale/) {
$nkey = "IC_income";
}
%{ $form->{IC}{$nkey}{$ref->{accno}} } = ( id => $ref->{id},
description => $ref->{description} );
}
}
}
$sth->finish;
 
 
$query = qq|SELECT id, accno, description
FROM chart
WHERE category = 'I'
AND charttype = 'A'
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $self->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
%{ $form->{IC}{FX_gain}{$ref->{accno}} } = ( id => $ref->{id},
description => $ref->{description} );
}
$sth->finish;
 
$query = qq|SELECT id, accno, description
FROM chart
WHERE category = 'E'
AND charttype = 'A'
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $self->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
%{ $form->{IC}{FX_loss}{$ref->{accno}} } = ( id => $ref->{id},
description => $ref->{description} );
}
$sth->finish;
 
 
# now get the tax rates and numbers
$query = qq|SELECT chart.id, chart.accno, chart.description,
tax.rate * 100 AS rate, tax.taxnumber
FROM chart, tax
WHERE chart.id = tax.chart_id|;
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
$form->{taxrates}{$ref->{accno}}{id} = $ref->{id};
$form->{taxrates}{$ref->{accno}}{description} = $ref->{description};
$form->{taxrates}{$ref->{accno}}{taxnumber} = $ref->{taxnumber} if $ref->{taxnumber};
$form->{taxrates}{$ref->{accno}}{rate} = $ref->{rate} if $ref->{rate};
}
 
$sth->finish;
$dbh->disconnect;
}
 
 
sub backup {
my ($self, $myconfig, $form, $userspath) = @_;
my ($tmpfile, $out, $mail);
if ($form->{media} eq 'email') {
 
my $boundary = time;
$tmpfile = "$userspath/$boundary.$myconfig->{dbname}-$form->{dbversion}.sql";
$out = $form->{OUT};
$form->{OUT} = ">$tmpfile";
use SL::Mailer;
$mail = new Mailer;
 
$mail->{to} = qq|"$myconfig->{name}" <$myconfig->{email}>|;
$mail->{from} = qq|"$myconfig->{name}" <$myconfig->{email}>|;
$mail->{subject} = "SQL-Ledger Backup / $myconfig->{dbname}-$form->{dbversion}.sql";
@{ $mail->{attachments} } = ($tmpfile);
$mail->{version} = $form->{version};
$mail->{fileid} = "$boundary.";
 
$myconfig->{signature} =~ s/\\n/\r\n/g;
$mail->{message} = "--\n$myconfig->{signature}";
}
if ($form->{OUT}) {
open(OUT, "$form->{OUT}") or $form->error("$form->{OUT} : $!");
} else {
open(OUT, ">-") or $form->error("STDOUT : $!");
}
 
if ($form->{media} eq 'file') {
print OUT qq|Content-Type: Application/File;
Content-Disposition: filename="$myconfig->{dbname}-$form->{dbversion}.sql"\n\n|;
}
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
# get all the tables
my @tables = $dbh->tables;
my $today = scalar localtime;
 
$myconfig->{dbhost} = 'localhost' unless $myconfig->{dbhost};
print OUT qq|-- SQL-Ledger Backup
-- Dataset: $myconfig->{dbname}
-- Version: $form->{dbversion}
-- Host: $myconfig->{dbhost}
-- Login: $form->{login}
-- User: $myconfig->{name}
-- Date: $today
--
-- set options
$myconfig->{dboptions};
--
|;
 
foreach $table (@tables) {
my $query = qq|SELECT * FROM $table|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$query = qq|INSERT INTO $table (|;
map { $query .= qq|$sth->{NAME}->[$_],| } (0 .. $sth->{NUM_OF_FIELDS} - 1);
chop $query;
 
$query .= qq|) VALUES|;
print OUT qq|--
DELETE FROM $table;
|;
while (my @arr = $sth->fetchrow_array) {
 
$fields = "(";
foreach my $item (@arr) {
if (defined $item) {
$item =~ s/'/''/g;
$fields .= qq|'$item',|;
} else {
$fields .= 'NULL,';
}
}
chop $fields;
$fields .= ")";
print OUT qq|$query $fields;\n|;
}
$sth->finish;
}
 
$query = qq|SELECT last_value FROM id|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my ($id) = $sth->fetchrow_array;
$sth->finish;
print OUT qq|--
DROP SEQUENCE id;
CREATE SEQUENCE id START $id;
|;
close(OUT);
$dbh->disconnect;
 
if ($form->{media} eq 'email') {
my $err = $mail->send($out);
$_ = $tmpfile;
unlink;
}
}
 
 
sub closedto {
my ($self, $myconfig, $form) = @_;
 
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT closedto, revtrans FROM defaults|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{closedto}, $form->{revtrans}) = $sth->fetchrow_array;
$sth->finish;
$dbh->disconnect;
 
}
 
sub closebooks {
my ($self, $myconfig, $form) = @_;
 
my $dbh = $form->dbconnect($myconfig);
 
if ($form->{revtrans}) {
$query = qq|UPDATE defaults SET closedto = NULL,
revtrans = '1'|;
} else {
if ($form->{closedto}) {
$query = qq|UPDATE defaults SET closedto = '$form->{closedto}',
revtrans = '0'|;
} else {
$query = qq|UPDATE defaults SET closedto = NULL,
revtrans = '0'|;
}
}
 
# set close in defaults
$dbh->do($query) || $form->dberror($query);
$dbh->disconnect;
}
 
 
1;
 
/tags/release_2_0_6-2/SL/AP.pm
New file
0,0 → 1,381
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Accounts Payables database backend routines
#
#======================================================================
 
 
package AP;
 
 
sub post_transaction {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
my ($null, $taxrate, $amount);
my $exchangerate = 0;
# split and store id numbers in link accounts
($form->{AP}{payables}) = split(/--/, $form->{AP});
map { ($form->{AP}{"amount_$_"}) = split(/--/, $form->{"AP_amount_$_"}) } (1 .. $form->{rowcount});
 
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{exchangerate} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, 'sell');
 
$form->{exchangerate} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{exchangerate});
}
# reverse and parse amounts
for my $i (1 .. $form->{rowcount}) {
$form->{"amount_$i"} = $form->round_amount($form->parse_amount($myconfig, $form->{"amount_$i"}) * $form->{exchangerate} * -1, 2);
$amount += ($form->{"amount_$i"} * -1);
}
 
# this is for ap
$form->{amount} = $amount;
# taxincluded doesn't make sense if there is no amount
$form->{taxincluded} = 0 if ($form->{amount} == 0);
 
for my $item (split / /, $form->{taxaccounts}) {
$form->{AP}{"tax_$item"} = $item;
 
$amount = $form->round_amount($form->parse_amount($myconfig, $form->{"tax_$item"}), 2);
$form->{"tax_$item"} = $form->round_amount($amount * $form->{exchangerate}, 2) * -1;
$form->{total_tax} += ($form->{"tax_$item"} * -1);
}
 
# adjust paidaccounts if there is no date in the last row
$form->{paidaccounts}-- unless ($form->{"datepaid_$form->{paidaccounts}"});
$form->{invpaid} = 0;
# add payments
for my $i (1 .. $form->{paidaccounts}) {
$form->{"paid_$i"} = $form->round_amount($form->parse_amount($myconfig, $form->{"paid_$i"}), 2);
$form->{invpaid} += $form->{"paid_$i"};
$form->{datepaid} = $form->{"datepaid_$i"};
 
}
$form->{invpaid} = $form->round_amount($form->{invpaid} * $form->{exchangerate}, 2);
if ($form->{taxincluded} *= 1) {
for $i (1 .. $form->{rowcount}) {
$tax = $form->{total_tax} * $form->{"amount_$i"} / $form->{amount};
$amount = $form->{"amount_$i"} - $tax;
$form->{"amount_$i"} = $form->round_amount($amount, 2);
$diff += $amount - $form->{"amount_$i"};
}
 
# deduct taxes from amount
$form->{amount} -= $form->{total_tax};
# deduct difference from amount_1
$form->{amount_1} += $form->round_amount($diff, 2);
}
 
$form->{netamount} = $form->{amount};
# store invoice total, this goes into ap table
$form->{invtotal} = $form->{amount} + $form->{total_tax};
# amount for total AP
$form->{payables} = $form->{invtotal};
 
my ($query, $sth);
 
# if we have an id delete old records
if ($form->{id}) {
 
# delete detail records
$query = qq|DELETE FROM acc_trans WHERE trans_id = $form->{id}|;
 
$dbh->do($query) || $form->dberror($query);
} else {
my $uid = time;
$uid .= $form->{login};
 
$query = qq|INSERT INTO ap (invnumber, employee_id)
VALUES ('$uid', (SELECT id FROM employee
WHERE login = '$form->{login}') )|;
$dbh->do($query) || $form->dberror($query);
$query = qq|SELECT id FROM ap
WHERE invnumber = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
}
 
# escape '
$form->{notes} =~ s/'/''/g;
$form->{datepaid} = $form->{transdate} unless ($form->{datepaid});
my $datepaid = ($form->{invpaid} != 0) ? qq|'$form->{datepaid}'| : 'NULL';
 
$query = qq|UPDATE ap SET
invnumber = '$form->{invnumber}',
transdate = '$form->{transdate}',
ordnumber = '$form->{ordnumber}',
vendor_id = $form->{vendor_id},
taxincluded = '$form->{taxincluded}',
amount = $form->{invtotal},
duedate = '$form->{duedate}',
paid = $form->{invpaid},
datepaid = $datepaid,
netamount = $form->{netamount},
curr = '$form->{currency}',
notes = '$form->{notes}'
WHERE id = $form->{id}
|;
$dbh->do($query) || $form->dberror($query);
 
 
# update exchangerate
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, 0, $form->{exchangerate});
}
 
# add individual transactions
foreach my $item (keys %{ $form->{AP} }) {
if ($form->{$item} != 0) {
$project_id = 'NULL';
if ($item =~ /amount_/) {
if ($form->{"project_id_$'"}) {
$project_id = $form->{"project_id_$'"};
}
}
 
# insert detail records in acc_trans
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
project_id)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$form->{AP}{$item}'),
$form->{$item}, '$form->{transdate}', $project_id)|;
$dbh->do($query) || $form->dberror($query);
}
}
 
# if there is no amount but a payment record a payable
if ($form->{amount} == 0 && $form->{invtotal} == 0) {
$form->{payables} = $form->{invpaid};
}
# add paid transactions
for my $i (1 .. $form->{paidaccounts}) {
if ($form->{"paid_$i"} != 0) {
 
$exchangerate = 0;
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{"exchangerate_$i"} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'sell');
 
$form->{"exchangerate_$i"} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{"exchangerate_$i"});
}
# get paid account
($form->{AP}{"paid_$i"}) = split(/--/, $form->{"AP_paid_$i"});
$form->{"datepaid_$i"} = $form->{transdate} unless ($form->{"datepaid_$i"});
 
# if there is no amount and invtotal is zero there is no exchangerate
if ($form->{amount} == 0 && $form->{invtotal} == 0) {
$form->{exchangerate} = $form->{"exchangerate_$i"};
}
$amount = $form->round_amount($form->{"paid_$i"} * $form->{exchangerate} * -1, 2);
if ($form->{payables}) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($form->{id},
(SELECT id FROM chart
WHERE accno = '$form->{AP}{payables}'),
$amount, '$form->{"datepaid_$i"}')|;
$dbh->do($query) || $form->dberror($query);
}
$form->{payables} = $amount;
 
# add payment
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, source)
VALUES ($form->{id},
(SELECT id FROM chart
WHERE accno = '$form->{AP}{"paid_$i"}'),
$form->{"paid_$i"}, '$form->{"datepaid_$i"}',
'$form->{"source_$i"}')|;
$dbh->do($query) || $form->dberror($query);
# add exchange rate difference
$amount = $form->round_amount($form->{"paid_$i"} * ($form->{"exchangerate_$i"} - 1), 2);
if ($amount != 0) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, fx_transaction, cleared)
VALUES ($form->{id},
(SELECT id FROM chart
WHERE accno = '$form->{AP}{"paid_$i"}'),
$amount, '$form->{"datepaid_$i"}', '1', '0')|;
 
$dbh->do($query) || $form->dberror($query);
}
 
# exchangerate gain/loss
$amount = $form->round_amount($form->{"paid_$i"} * ($form->{exchangerate} - $form->{"exchangerate_$i"}), 2);
 
if ($amount != 0) {
$accno = ($amount > 0) ? $form->{fxgain_accno} : $form->{fxloss_accno};
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, fx_transaction, cleared)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$accno'),
$amount, '$form->{"datepaid_$i"}', '1', '0')|;
$dbh->do($query) || $form->dberror($query);
}
 
# update exchange rate record
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{"datepaid_$i"}, 0, $form->{"exchangerate_$i"});
}
}
}
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
 
sub delete_transaction {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
# check for other foreign currency transactions
$form->delete_exchangerate($dbh) if ($form->{currency} ne $form->{defaultcurrency});
my $query = qq|DELETE FROM ap WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM acc_trans WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
# commit and redirect
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
 
}
 
 
 
 
sub ap_transactions {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $incemp = qq|, (SELECT e.name FROM employee e
WHERE a.employee_id = e.id) AS employee
| if ($form->{l_employee});
my $query = qq|SELECT a.id, a.invnumber, a.transdate, a.duedate,
a.amount, a.paid, a.ordnumber, v.name, a.invoice,
a.netamount, a.datepaid, a.notes
$incemp
FROM ap a, vendor v
WHERE a.vendor_id = v.id|;
 
if ($form->{vendor_id}) {
$query .= " AND a.vendor_id = $form->{vendor_id}";
} else {
if ($form->{vendor}) {
my $vendor = $form->like(lc $form->{vendor});
$query .= " AND lower(v.name) LIKE '$vendor'";
}
}
if ($form->{invnumber}) {
my $invnumber = $form->like(lc $form->{invnumber});
$query .= " AND lower(a.invnumber) LIKE '$invnumber'";
}
if ($form->{ordnumber}) {
my $ordnumber = $form->like(lc $form->{ordnumber});
$query .= " AND lower(a.ordnumber) LIKE '$ordnumber'";
}
if ($form->{notes}) {
my $notes = $form->like(lc $form->{notes});
$query .= " AND lower(a.notes) LIKE '$notes'";
}
 
$query .= " AND a.transdate >= '$form->{transdatefrom}'" if $form->{transdatefrom};
$query .= " AND a.transdate <= '$form->{transdateto}'" if $form->{transdateto};
if ($form->{open} || $form->{closed}) {
unless ($form->{open} && $form->{closed}) {
$query .= " AND a.amount <> a.paid" if ($form->{open});
$query .= " AND a.amount = a.paid" if ($form->{closed});
}
}
 
my @a = (transdate, invnumber, name);
push @a, "employee" if $self->{l_employee};
my $sortorder = join ', ', $form->sort_columns(@a);
$sortorder = $form->{sort} unless $sortorder;
 
$query .= " ORDER by $sortorder";
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ap = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{AP} }, $ap;
}
$sth->finish;
$dbh->disconnect;
}
 
 
1;
 
/tags/release_2_0_6-2/SL/AR.pm
New file
0,0 → 1,381
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Accounts Receivable module backend routines
#
#======================================================================
 
package AR;
 
 
sub post_transaction {
my ($self, $myconfig, $form) = @_;
 
my ($null, $taxrate, $amount, $tax, $diff);
my $exchangerate = 0;
my $i;
 
# split and store id numbers in link accounts
map { ($form->{AR}{"amount_$_"}) = split(/--/, $form->{"AR_amount_$_"}) } (1 .. $form->{rowcount});
($form->{AR}{receivables}) = split(/--/, $form->{AR});
 
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{exchangerate} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, 'buy');
}
$form->{exchangerate} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{exchangerate});
 
for $i (1 .. $form->{rowcount}) {
$form->{"amount_$i"} = $form->round_amount($form->parse_amount($myconfig, $form->{"amount_$i"}) * $form->{exchangerate}, 2);
$amount += $form->{"amount_$i"};
}
# this is for ar
$form->{amount} = $amount;
 
# taxincluded doesn't make sense if there is no amount
$form->{taxincluded} = 0 if ($form->{amount} == 0);
 
foreach my $item (split / /, $form->{taxaccounts}) {
$form->{AR}{"tax_$item"} = $item;
 
$amount = $form->round_amount($form->parse_amount($myconfig, $form->{"tax_$item"}), 2);
$form->{"tax_$item"} = $form->round_amount($amount * $form->{exchangerate}, 2);
$form->{total_tax} += $form->{"tax_$item"};
 
}
 
# adjust paidaccounts if there is no date in the last row
$form->{paidaccounts}-- unless ($form->{"datepaid_$form->{paidaccounts}"});
 
$form->{invpaid} = 0;
# add payments
for $i (1 .. $form->{paidaccounts}) {
$form->{"paid_$i"} = $form->round_amount($form->parse_amount($myconfig, $form->{"paid_$i"}), 2);
$form->{invpaid} += $form->{"paid_$i"};
$form->{datepaid} = $form->{"datepaid_$i"};
 
# reverse payment
$form->{"paid_$i"} *= -1;
 
}
$form->{invpaid} = $form->round_amount($form->{invpaid} * $form->{exchangerate}, 2);
if ($form->{taxincluded} *= 1) {
for $i (1 .. $form->{rowcount}) {
$tax = $form->{total_tax} * $form->{"amount_$i"} / $form->{amount};
$amount = $form->{"amount_$i"} - $tax;
$form->{"amount_$i"} = $form->round_amount($amount, 2);
$diff += $amount - $form->{"amount_$i"};
}
$form->{amount} -= $form->{total_tax};
# deduct difference from amount_1
$form->{amount_1} += $form->round_amount($diff, 2);
}
 
# store invoice total, this goes into ar table
$form->{invtotal} = $form->{amount} + $form->{total_tax};
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
my ($query, $sth);
# if we have an id delete old records
if ($form->{id}) {
 
# delete detail records
$query = qq|DELETE FROM acc_trans WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
} else {
my $uid = time;
$uid .= $form->{login};
 
$query = qq|INSERT INTO ar (invnumber, employee_id)
VALUES ('$uid', (SELECT id FROM employee
WHERE login = '$form->{login}') )|;
$dbh->do($query) || $form->dberror($query);
$query = qq|SELECT id FROM ar
WHERE invnumber = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
 
}
 
# escape '
$form->{notes} =~ s/'/''/g;
 
# record last payment date in ar table
$form->{datepaid} = $form->{transdate} unless $form->{datepaid};
my $datepaid = ($form->{invpaid} != 0) ? qq|'$form->{datepaid}'| : 'NULL';
$query = qq|UPDATE ar set
invnumber = '$form->{invnumber}',
ordnumber = '$form->{ordnumber}',
transdate = '$form->{transdate}',
customer_id = $form->{customer_id},
taxincluded = '$form->{taxincluded}',
amount = $form->{invtotal},
duedate = '$form->{duedate}',
paid = $form->{invpaid},
datepaid = $datepaid,
netamount = $form->{amount},
curr = '$form->{currency}',
notes = '$form->{notes}'
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# amount for AR account
$form->{receivables} = $form->round_amount($form->{invtotal} * -1, 2);
 
# update exchangerate
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{transdate}, $form->{exchangerate}, 0);
}
# add individual transactions for AR, amount and taxes
foreach my $item (keys %{ $form->{AR} }) {
if ($form->{$item} != 0) {
$project_id = 'NULL';
if ($item =~ /amount_/) {
if ($form->{"project_id_$'"}) {
$project_id = $form->{"project_id_$'"};
}
}
# insert detail records in acc_trans
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
project_id)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$form->{AR}{$item}'),
$form->{$item}, '$form->{transdate}', $project_id)|;
$dbh->do($query) || $form->dberror($query);
}
}
 
# if there is no amount but a payment record a receivables
if ($form->{amount} == 0 && $form->{invtotal} == 0) {
$form->{receivables} = $form->{invpaid} * -1;
}
# add paid transactions
for my $i (1 .. $form->{paidaccounts}) {
if ($form->{"paid_$i"} != 0) {
($form->{AR}{"paid_$i"}) = split(/--/, $form->{"AR_paid_$i"});
$form->{"datepaid_$i"} = $form->{transdate} unless ($form->{"datepaid_$i"});
$exchangerate = 0;
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{"exchangerate_$i"} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'buy');
$form->{"exchangerate_$i"} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{"exchangerate_$i"});
}
 
# if there is no amount and invtotal is zero there is no exchangerate
if ($form->{amount} == 0 && $form->{invtotal} == 0) {
$form->{exchangerate} = $form->{"exchangerate_$i"};
}
# receivables amount
$amount = $form->round_amount($form->{"paid_$i"} * $form->{exchangerate} * -1, 2);
if ($form->{receivables} != 0) {
# add receivable
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($form->{id},
(SELECT id FROM chart
WHERE accno = '$form->{AR}{receivables}'),
$amount, '$form->{"datepaid_$i"}')|;
$dbh->do($query) || $form->dberror($query);
}
$form->{receivables} = $amount;
# add payment
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, source)
VALUES ($form->{id},
(SELECT id FROM chart
WHERE accno = '$form->{AR}{"paid_$i"}'),
$form->{"paid_$i"}, '$form->{"datepaid_$i"}',
'$form->{"source_$i"}')|;
$dbh->do($query) || $form->dberror($query);
# exchangerate difference for payment
$amount = $form->round_amount($form->{"paid_$i"} * ($form->{"exchangerate_$i"} - 1), 2);
if ($amount != 0) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, fx_transaction, cleared)
VALUES ($form->{id},
(SELECT id FROM chart
WHERE accno = '$form->{AR}{"paid_$i"}'),
$amount, '$form->{"datepaid_$i"}', '1', '0')|;
$dbh->do($query) || $form->dberror($query);
}
# exchangerate gain/loss
$amount = $form->round_amount($form->{"paid_$i"} * ($form->{exchangerate} - $form->{"exchangerate_$i"}), 2);
if ($amount != 0) {
$accno = ($amount > 0) ? $form->{fxgain_accno} : $form->{fxloss_accno};
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, fx_transaction, cleared)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$accno'),
$amount, '$form->{"datepaid_$i"}', '1', '0')|;
$dbh->do($query) || $form->dberror($query);
}
# update exchangerate record
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{"datepaid_$i"}, $form->{"exchangerate_$i"}, 0);
}
}
}
 
 
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
sub delete_transaction {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn AutoCommit off
my $dbh = $form->dbconnect_noauto($myconfig);
 
# check for other foreign currency transactions
$form->delete_exchangerate($dbh) if ($form->{currency} ne $form->{defaultcurrency});
 
my $query = qq|DELETE FROM ar WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM acc_trans WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
# commit
my $rc = $dbh->commit;
$dbh->disconnect;
$rc;
 
}
 
 
 
sub ar_transactions {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $incemp = qq|, (SELECT e.name FROM employee e
WHERE a.employee_id = e.id) AS employee
| if ($form->{l_employee});
my $query = qq|SELECT a.id, a.invnumber, a.ordnumber, a.transdate,
a.duedate, a.netamount, a.amount, a.paid, c.name,
a.invoice, a.datepaid, a.terms, a.notes
$incemp
FROM ar a, customer c
WHERE a.customer_id = c.id|;
if ($form->{customer_id}) {
$query .= " AND a.customer_id = $form->{customer_id}";
} else {
if ($form->{customer}) {
my $customer = $form->like(lc $form->{customer});
$query .= " AND lower(c.name) LIKE '$customer'";
}
}
if ($form->{invnumber}) {
my $invnumber = $form->like(lc $form->{invnumber});
$query .= " AND lower(a.invnumber) LIKE '$invnumber'";
}
if ($form->{ordnumber}) {
my $ordnumber = $form->like(lc $form->{ordnumber});
$query .= " AND lower(a.ordnumber) LIKE '$ordnumber'";
}
if ($form->{notes}) {
my $notes = $form->like(lc $form->{notes});
$query .= " AND lower(a.notes) LIKE '$notes'";
}
$query .= " AND a.transdate >= '$form->{transdatefrom}'" if $form->{transdatefrom};
$query .= " AND a.transdate <= '$form->{transdateto}'" if $form->{transdateto};
if ($form->{open} || $form->{closed}) {
unless ($form->{open} && $form->{closed}) {
$query .= " AND a.amount <> a.paid" if ($form->{open});
$query .= " AND a.amount = a.paid" if ($form->{closed});
}
}
 
my @a = (transdate, invnumber, name);
push @a, "employee" if $form->{l_employee};
my $sortorder = join ', ', $form->sort_columns(@a);
$sortorder = $form->{sort} unless $sortorder;
$query .= " ORDER by $sortorder";
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ar = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{AR} }, $ar;
}
$sth->finish;
$dbh->disconnect;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/CP.pm
New file
0,0 → 1,308
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2002
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Check and receipt printing payment module backend routines
# Number to text conversion routines are in
# locale/{countrycode}/Num2text
#
#======================================================================
 
package CP;
 
 
sub new {
my ($type, $countrycode) = @_;
 
$self = {};
 
if ($countrycode) {
if (-f "locale/$countrycode/Num2text") {
require "locale/$countrycode/Num2text";
} else {
use SL::Num2text;
}
} else {
use SL::Num2text;
}
 
bless $self, $type;
 
}
 
 
sub paymentaccounts {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $query = qq|SELECT accno, description
FROM chart
WHERE link LIKE '%$form->{arap}_paid%'
ORDER BY accno|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{PR} }, $ref;
}
$sth->finish;
# get currencies and closedto
$query = qq|SELECT curr, closedto
FROM defaults|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
($form->{currencies}, $form->{closedto}) = $sth->fetchrow_array;
$sth->finish;
 
$dbh->disconnect;
 
}
 
 
sub get_openvc {
my ($self, $myconfig, $form) = @_;
 
my $dbh = $form->dbconnect($myconfig);
 
my $arap = ($form->{vc} eq 'customer') ? 'ar' : 'ap';
my $query = qq|SELECT count(*)
FROM $form->{vc} ct, $arap a
WHERE a.$form->{vc}_id = ct.id
AND a.amount != a.paid|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my ($count) = $sth->fetchrow_array;
$sth->finish;
 
# build selection list
if ($count < $myconfig->{vclimit}) {
$query = qq|SELECT DISTINCT ct.id, ct.name
FROM $form->{vc} ct, $arap a
WHERE a.$form->{vc}_id = ct.id
AND a.amount != a.paid
ORDER BY name|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{"all_$form->{vc}"} }, $ref;
}
 
$sth->finish;
 
}
 
$dbh->disconnect;
 
}
 
 
sub get_openinvoices {
my ($self, $myconfig, $form) = @_;
 
return unless $form->{"$form->{vc}_id"};
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $where = qq|WHERE $form->{vc}_id = $form->{"$form->{vc}_id"}
AND curr = '$form->{currency}'
AND NOT amount = paid|;
if ($form->{transdatefrom}) {
$where .= " AND transdate >= '$form->{transdatefrom}'";
}
if ($form->{transdateto}) {
$where .= " AND transdate <= '$form->{transdateto}'";
}
my ($arap, $buysell);
if ($form->{vc} eq 'customer') {
$arap = "ar";
$buysell = "buy";
} else {
$arap = "ap";
$buysell = "sell";
}
my $query = qq|SELECT id, invnumber, transdate, amount, paid, curr
FROM $arap
$where
ORDER BY id|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
# if this is a foreign currency transaction get exchangerate
$ref->{exchangerate} = $form->get_exchangerate($dbh, $ref->{curr}, $ref->{transdate}, $buysell) if ($form->{currency} ne $form->{defaultcurrency});
push @{ $form->{PR} }, $ref;
}
$sth->finish;
$dbh->disconnect;
 
}
 
 
 
sub process_payment {
my ($self, $myconfig, $form) = @_;
# connect to database, turn AutoCommit off
my $dbh = $form->dbconnect_noauto($myconfig);
 
my ($paymentaccno) = split /--/, $form->{account};
# if currency ne defaultcurrency update exchangerate
if ($form->{currency} ne $form->{defaultcurrency}) {
$form->{exchangerate} = $form->parse_amount($myconfig, $form->{exchangerate});
 
if ($form->{vc} eq 'customer') {
$form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, $form->{exchangerate}, 0);
} else {
$form->update_exchangerate($dbh, $form->{currency}, $form->{datepaid}, 0, $form->{exchangerate});
}
} else {
$form->{exchangerate} = 1;
}
 
my $query = qq|SELECT fxgain_accno_id, fxloss_accno_id
FROM defaults|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my ($fxgain_accno_id, $fxloss_accno_id) = $sth->fetchrow_array;
$sth->finish;
 
my ($ARAP, $arap, $buysell);
if ($form->{vc} eq 'customer') {
$ARAP = "AR";
$arap = "ar";
$buysell = "buy";
} else {
$ARAP = "AP";
$arap = "ap";
$buysell = "sell";
}
# go through line by line
for my $i (1 .. $form->{rowcount}) {
 
if ($form->{"paid_$i"}) {
 
$form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"});
# get exchangerate for original
$query = qq|SELECT $buysell FROM exchangerate e, $arap a
WHERE e.curr = '$form->{currency}'
AND a.transdate = e.transdate
AND a.id = $form->{"id_$i"}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my ($exchangerate) = $sth->fetchrow_array;
$sth->finish;
 
$exchangerate = 1 unless $exchangerate;
 
$query = qq|SELECT c.id FROM chart c, acc_trans a
WHERE a.chart_id = c.id
AND c.link = '$ARAP'
AND a.trans_id = $form->{"id_$i"}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my ($id) = $sth->fetchrow_array;
$sth->finish;
 
my $amount = $form->round_amount($form->{"paid_$i"} * $exchangerate * -1, 2);
$ml = ($ARAP eq 'AR') ? -1 : 1;
# add AR/AP
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, transdate, amount)
VALUES ($form->{"id_$i"}, $id,
'$form->{datepaid}', $amount * $ml)|;
$dbh->do($query) || $form->dberror($query);
# add payment
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, transdate, amount,
source)
VALUES ($form->{"id_$i"},
(SELECT id FROM chart
WHERE accno = '$paymentaccno'),
'$form->{datepaid}', $form->{"paid_$i"} * $ml,
'$form->{source}')|;
$dbh->do($query) || $form->dberror($query);
 
# add exchangerate difference if currency ne defaultcurrency
$amount = $form->round_amount($form->{"paid_$i"} * ($form->{exchangerate} - 1), 2);
 
if ($amount != 0) {
# exchangerate difference
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, transdate,
amount, cleared, fx_transaction)
VALUES ($form->{"id_$i"},
(SELECT id FROM chart
WHERE accno = '$paymentaccno'),
'$form->{datepaid}', $amount * $ml, '0', '1')|;
$dbh->do($query) || $form->dberror($query);
 
# gain/loss
$amount = $form->round_amount($form->{"paid_$i"} * ($exchangerate - $form->{exchangerate}) * $ml, 2);
if ($amount != 0) {
my $accno_id = ($amount > 0) ? $fxgain_accno_id : $fxloss_accno_id;
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, transdate,
amount, cleared, fx_transaction)
VALUES ($form->{"id_$i"}, $accno_id,
'$form->{datepaid}', $amount, '0', '1')|;
$dbh->do($query) || $form->dberror($query);
}
}
 
$form->{"paid_$i"} = $form->round_amount($form->{"paid_$i"} * $exchangerate, 2);
 
# update AR/AP transaction
$query = qq|UPDATE $arap set
paid = paid + $form->{"paid_$i"},
datepaid = '$form->{datepaid}'
WHERE id = $form->{"id_$i"}|;
$dbh->do($query) || $form->dberror($query);
}
}
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/GL.pm
New file
0,0 → 1,462
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# General ledger backend code
#
# CHANGE LOG:
# DS. 2000-07-04 Created
# DS. 2001-06-12 Changed relations from accno to chart_id
#
#======================================================================
 
package GL;
 
 
sub delete_transaction {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $query = qq|DELETE FROM gl WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM acc_trans WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# commit and redirect
my $rc = $dbh->commit;
$dbh->disconnect;
$rc;
}
 
 
sub post_transaction {
my ($self, $myconfig, $form) = @_;
my ($debit, $credit) = (0, 0);
my $project_id;
 
my $i;
# check if debit and credit balances
for $i (1 .. $form->{rowcount}) {
if ($form->{"debit_$i"} && $form->{"credit_$i"}) {
return -1;
}
 
$form->{"debit_$i"} = $form->parse_amount($myconfig, $form->{"debit_$i"});
$form->{"credit_$i"} = $form->parse_amount($myconfig, $form->{"credit_$i"});
 
$debit += $form->{"debit_$i"};
$credit += $form->{"credit_$i"};
}
 
$debit = $form->round_amount($debit, 2);
$credit = $form->round_amount($credit, 2);
if ($debit != $credit) {
return -2;
}
 
if (($debit + $credit) == 0) {
return -3;
}
# connect to database, turn off AutoCommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
# post the transaction
# make up a unique handle and store in reference field
# then retrieve the record based on the unique handle to get the id
# replace the reference field with the actual variable
# add records to acc_trans
 
# if there is a $form->{id} replace the old transaction
# delete all acc_trans entries and add the new ones
 
# escape '
map { $form->{$_} =~ s/'/''/g } qw(reference description);
 
 
my ($query, $sth);
if ($form->{id}) {
# delete individual transactions
$query = qq|DELETE FROM acc_trans
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
} else {
my $uid = time;
$uid .= $form->{login};
 
$query = qq|INSERT INTO gl (reference, employee_id)
VALUES ('$uid', (SELECT id FROM employee
WHERE login = '$form->{login}'))|;
$dbh->do($query) || $form->dberror($query);
$query = qq|SELECT id FROM gl
WHERE reference = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
 
}
$query = qq|UPDATE gl SET
reference = '$form->{reference}',
description = '$form->{description}',
notes = '$form->{notes}',
transdate = '$form->{transdate}'
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# insert acc_trans transactions
for $i (1 .. $form->{rowcount}) {
# extract accno
($accno) = split(/--/, $form->{"accno_$i"});
my $amount = 0;
if ($form->{"credit_$i"} != 0) {
$amount = $form->{"credit_$i"};
}
if ($form->{"debit_$i"} != 0) {
$amount = $form->{"debit_$i"} * -1;
}
 
 
# if there is an amount, add the record
if ($amount != 0) {
$project_id = ($form->{"project_id_$i"}) ? $form->{"project_id_$i"} : 'NULL';
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
source, project_id)
VALUES
($form->{id}, (SELECT id
FROM chart
WHERE accno = '$accno'),
$amount, '$form->{transdate}', '$form->{reference}',
$project_id)|;
$dbh->do($query) || $form->dberror($query);
}
}
 
# commit and redirect
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
 
}
 
 
 
sub all_transactions {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $query;
my $sth;
 
my ($glwhere, $arwhere, $apwhere) = ("1 = 1", "1 = 1", "1 = 1");
if ($form->{reference}) {
my $source = $form->like(lc $form->{reference});
$glwhere .= " AND lower(g.reference) LIKE '$source'";
$arwhere .= " AND lower(a.invnumber) LIKE '$source'";
$apwhere .= " AND lower(a.invnumber) LIKE '$source'";
}
if ($form->{source}) {
my $source = $form->like(lc $form->{source});
$glwhere .= " AND lower(ac.source) LIKE '$source'";
$arwhere .= " AND lower(ac.source) LIKE '$source'";
$apwhere .= " AND lower(ac.source) LIKE '$source'";
}
if ($form->{datefrom}) {
$glwhere .= " AND ac.transdate >= '$form->{datefrom}'";
$arwhere .= " AND ac.transdate >= '$form->{datefrom}'";
$apwhere .= " AND ac.transdate >= '$form->{datefrom}'";
}
if ($form->{dateto}) {
$glwhere .= " AND ac.transdate <= '$form->{dateto}'";
$arwhere .= " AND ac.transdate <= '$form->{dateto}'";
$apwhere .= " AND ac.transdate <= '$form->{dateto}'";
}
if ($form->{description}) {
my $description = $form->like(lc $form->{description});
$glwhere .= " AND lower(g.description) LIKE '$description'";
$arwhere .= " AND lower(ct.name) LIKE '$description'";
$apwhere .= " AND lower(ct.name) LIKE '$description'";
}
if ($form->{notes}) {
my $notes = $form->like(lc $form->{notes});
$glwhere .= " AND lower(g.notes) LIKE '$notes'";
$arwhere .= " AND lower(a.notes) LIKE '$notes'";
$apwhere .= " AND lower(a.notes) LIKE '$notes'";
}
if ($form->{accno}) {
$glwhere .= " AND c.accno = '$form->{accno}'";
$arwhere .= " AND c.accno = '$form->{accno}'";
$apwhere .= " AND c.accno = '$form->{accno}'";
}
if ($form->{gifi_accno}) {
$glwhere .= " AND c.gifi_accno = '$form->{gifi_accno}'";
$arwhere .= " AND c.gifi_accno = '$form->{gifi_accno}'";
$apwhere .= " AND c.gifi_accno = '$form->{gifi_accno}'";
}
if ($form->{category} ne 'X') {
$glwhere .= " AND c.category = '$form->{category}'";
$arwhere .= " AND c.category = '$form->{category}'";
$apwhere .= " AND c.category = '$form->{category}'";
}
 
if ($form->{accno}) {
# get category for account
$query = qq|SELECT category
FROM chart
WHERE accno = '$form->{accno}'|;
$sth = $dbh->prepare($query);
 
$sth->execute || $form->dberror($query);
($form->{ml}) = $sth->fetchrow_array;
$sth->finish;
if ($form->{datefrom}) {
$query = qq|SELECT SUM(ac.amount)
FROM acc_trans ac, chart c
WHERE ac.chart_id = c.id
AND c.accno = '$form->{accno}'
AND ac.transdate < date '$form->{datefrom}'
|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{balance}) = $sth->fetchrow_array;
$sth->finish;
}
}
if ($form->{gifi_accno}) {
# get category for account
$query = qq|SELECT category
FROM chart
WHERE gifi_accno = '$form->{gifi_accno}'|;
$sth = $dbh->prepare($query);
 
$sth->execute || $form->dberror($query);
($form->{ml}) = $sth->fetchrow_array;
$sth->finish;
if ($form->{datefrom}) {
$query = qq|SELECT SUM(ac.amount)
FROM acc_trans ac, chart c
WHERE ac.chart_id = c.id
AND c.gifi_accno = '$form->{gifi_accno}'
AND ac.transdate < date '$form->{datefrom}'
|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{balance}) = $sth->fetchrow_array;
$sth->finish;
}
}
 
my $false = ($myconfig->{dbdriver} eq 'Pg') ? FALSE : q|'0'|;
 
my $sortorder = join ', ', $form->sort_columns(qw(transdate reference source description accno));
my %ordinal = ( transdate => 6,
reference => 4,
source => 7,
description => 5 );
map { $sortorder =~ s/$_/$ordinal{$_}/ } keys %ordinal;
my $query = qq|SELECT g.id, 'gl' AS type, $false AS invoice, g.reference,
g.description, ac.transdate, ac.source,
ac.amount, c.accno, c.gifi_accno, g.notes
FROM gl g, acc_trans ac, chart c
WHERE $glwhere
AND ac.chart_id = c.id
AND g.id = ac.trans_id
UNION ALL
SELECT a.id, 'ar' AS type, a.invoice, a.invnumber,
ct.name, ac.transdate, ac.source,
ac.amount, c.accno, c.gifi_accno, a.notes
FROM ar a, acc_trans ac, chart c, customer ct
WHERE $arwhere
AND ac.chart_id = c.id
AND a.customer_id = ct.id
AND a.id = ac.trans_id
UNION ALL
SELECT a.id, 'ap' AS type, a.invoice, a.invnumber,
ct.name, ac.transdate, ac.source,
ac.amount, c.accno, c.gifi_accno, a.notes
FROM ap a, acc_trans ac, chart c, vendor ct
WHERE $apwhere
AND ac.chart_id = c.id
AND a.vendor_id = ct.id
AND a.id = ac.trans_id
ORDER BY $sortorder|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
# gl
if ($ref->{type} eq "gl") {
$ref->{module} = "gl";
}
 
# ap
if ($ref->{type} eq "ap") {
if ($ref->{invoice}) {
$ref->{module} = "ir";
} else {
$ref->{module} = "ap";
}
}
 
# ar
if ($ref->{type} eq "ar") {
if ($ref->{invoice}) {
$ref->{module} = "is";
} else {
$ref->{module} = "ar";
}
}
 
if ($ref->{amount} < 0) {
$ref->{debit} = $ref->{amount} * -1;
$ref->{credit} = 0;
} else {
$ref->{credit} = $ref->{amount};
$ref->{debit} = 0;
}
 
push @{ $form->{GL} }, $ref;
}
 
$sth->finish;
 
if ($form->{accno}) {
$query = qq|SELECT description FROM chart WHERE accno = '$form->{accno}'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{account_description}) = $sth->fetchrow_array;
$sth->finish;
}
if ($form->{gifi_accno}) {
$query = qq|SELECT description FROM gifi WHERE accno = '$form->{gifi_accno}'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{gifi_account_description}) = $sth->fetchrow_array;
$sth->finish;
}
$dbh->disconnect;
 
}
 
 
sub transaction {
my ($self, $myconfig, $form) = @_;
my ($query, $sth);
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
if ($form->{id}) {
$query = "SELECT closedto, revtrans
FROM defaults";
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{closedto}, $form->{revtrans}) = $sth->fetchrow_array;
$sth->finish;
 
$query = "SELECT reference, description, notes, transdate
FROM gl
WHERE id = $form->{id}";
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{reference}, $form->{description}, $form->{notes}, $form->{transdate}) = $sth->fetchrow_array;
$sth->finish;
# retrieve individual rows
$query = "SELECT c.accno, a.amount, project_id,
(SELECT p.projectnumber FROM project p
WHERE a.project_id = p.id) AS projectnumber
FROM acc_trans a, chart c
WHERE a.chart_id = c.id
AND a.trans_id = $form->{id}
ORDER BY accno";
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{GL} }, $ref;
}
} else {
$query = "SELECT current_date AS transdate, closedto, revtrans
FROM defaults";
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{transdate}, $form->{closedto}, $form->{revtrans}) = $sth->fetchrow_array;
}
 
$sth->finish;
 
# get chart of accounts
$query = qq|SELECT accno,description
FROM chart
WHERE charttype = 'A'
ORDER by accno|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
$form->{chart} = "";
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{chart} }, $ref;
}
$sth->finish;
$dbh->disconnect;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/Makefile
New file
0,0 → 1,13
PACKAGE = sql-ledger
 
FILES = Inifile.pm AM.pm AP.pm AR.pm CA.pm CP.pm CT.pm Form.pm GL.pm \
IC.pm IR.pm IS.pm Mailer.pm Menu.pm Num2text.pm OE.pm PE.pm \
RC.pm RP.pm User.pm
 
all:
 
clean:
 
install:
mkdir -p $(DESTDIR)/usr/lib/sql-ledger/SL
cp -r $(FILES) $(DESTDIR)/usr/lib/sql-ledger/SL
/tags/release_2_0_6-2/SL/OE.pm
New file
0,0 → 1,653
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Order entry module
#
#======================================================================
 
package OE;
 
 
sub transactions {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $query;
 
my $rate = ($form->{vc} eq 'customer') ? 'buy' : 'sell';
my $query = qq|SELECT o.id, o.ordnumber, o.transdate, o.reqdate,
o.amount, ct.name, o.netamount, o.$form->{vc}_id,
(SELECT $rate FROM exchangerate ex
WHERE ex.curr = o.curr
AND ex.transdate = o.transdate) AS exchangerate,
o.closed
FROM oe o, $form->{vc} ct
WHERE o.$form->{vc}_id = ct.id|;
my $ordnumber = $form->like(lc $form->{ordnumber});
if ($form->{"$form->{vc}_id"}) {
$query .= qq| AND o.$form->{vc}_id = $form->{"$form->{vc}_id"}|;
} else {
if ($form->{$form->{vc}}) {
my $name = $form->like(lc $form->{$form->{vc}});
$query .= " AND lower(name) LIKE '$name'";
}
}
unless ($form->{open} && $form->{closed}) {
$query .= ($form->{open}) ? " AND o.closed = '0'" : " AND o.closed = '1'";
}
 
my $sortorder = join ', ', $form->sort_columns(qw(transdate ordnumber name));
$sortorder = $form->{sort} unless $sortorder;
$query .= " AND lower(ordnumber) LIKE '$ordnumber'" if $form->{ordnumber};
$query .= " AND transdate >= '$form->{transdatefrom}'" if $form->{transdatefrom};
$query .= " AND transdate <= '$form->{transdateto}'" if $form->{transdateto};
$query .= " ORDER by $sortorder";
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $oe = $sth->fetchrow_hashref(NAME_lc)) {
$oe->{exchangerate} = 1 unless $oe->{exchangerate};
push @{ $form->{OE} }, $oe;
}
 
$sth->finish;
$dbh->disconnect;
}
 
 
sub save_order {
my ($self, $myconfig, $form) = @_;
# connect to database, turn off autocommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
my ($query, $sth);
my $exchangerate = 0;
 
if ($form->{id}) {
 
$query = qq|DELETE FROM orderitems
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
} else {
my $uid = time;
$uid .= $form->{login};
$query = qq|INSERT INTO oe (ordnumber, employee_id)
VALUES ('$uid', (SELECT id FROM employee
WHERE login = '$form->{login}') )|;
$dbh->do($query) || $form->dberror($query);
$query = qq|SELECT id FROM oe
WHERE ordnumber = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
}
 
map { $form->{$_} =~ s/'/''/g } qw(ordnumber shippingpoint notes message);
my ($amount, $linetotal, $discount, $project_id, $reqdate);
my ($taxrate, $taxamount, $fxsellprice);
my %taxbase = ();
my %taxaccounts = ();
my ($netamount, $tax) = (0, 0);
 
for my $i (1 .. $form->{rowcount}) {
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
if ($form->{"qty_$i"} != 0) {
map { $form->{"${_}_$i"} =~ s/'/''/g } qw(partnumber description unit);
# set values to 0 if nothing entered
$form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
 
$form->{"sellprice_$i"} = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
$fxsellprice = $form->{"sellprice_$i"};
 
my ($dec) = ($form->{"sellprice_$i"} =~ /\.(\d+)/);
$dec = length $dec;
my $decimalplaces = ($dec > 2) ? $dec : 2;
$discount = $form->round_amount($form->{"sellprice_$i"} * $form->{"discount_$i"}, $decimalplaces);
$form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} - $discount, $decimalplaces);
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2);
$taxrate = 0;
map { $taxrate += $form->{"${_}_rate"} } split / /, $form->{"taxaccounts_$i"};
 
if ($form->{taxincluded}) {
$taxamount = $linetotal * $taxrate / (1 + $taxrate);
$taxbase = $linetotal - $taxamount;
# we are not keeping a natural price, do not round
$form->{"sellprice_$i"} = $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
} else {
$taxamount = $linetotal * $taxrate;
$taxbase = $linetotal;
}
 
if ($taxamount != 0) {
foreach my $item (split / /, $form->{"taxaccounts_$i"}) {
$taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
$taxbase{$item} += $taxbase;
}
}
$netamount += $form->{"sellprice_$i"} * $form->{"qty_$i"};
$project_id = 'NULL';
if ($form->{"project_id_$i"}) {
$project_id = $form->{"project_id_$i"};
}
$reqdate = ($form->{"reqdate_$i"}) ? qq|'$form->{"reqdate_$i"}'| : "NULL";
# save detail record in orderitems table
$query = qq|INSERT INTO orderitems
(trans_id, parts_id, description, qty, sellprice, discount,
unit, reqdate, project_id) VALUES (
$form->{id}, $form->{"id_$i"}, '$form->{"description_$i"}',
$form->{"qty_$i"}, $fxsellprice, $form->{"discount_$i"},
'$form->{"unit_$i"}', $reqdate, $project_id)|;
$dbh->do($query) || $form->dberror($query);
 
$form->{"sellprice_$i"} = $fxsellprice;
$form->{"discount_$i"} *= 100;
}
}
 
 
# set values which could be empty
map { $form->{$_} *= 1 } qw(vendor_id customer_id taxincluded closed);
 
$reqdate = ($form->{reqdate}) ? qq|'$form->{reqdate}'| : "NULL";
# add up the tax
foreach my $item (sort keys %taxaccounts) {
$taxamount = $form->round_amount($taxaccounts{$item}, 2);
$tax += $taxamount;
}
$amount = $form->round_amount($netamount + $tax, 2);
$netamount = $form->round_amount($netamount, 2);
 
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{exchangerate} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, ($form->{vc} eq 'customer') ? 'buy' : 'sell');
}
$form->{exchangerate} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{exchangerate});
# fill in subject if there is none
$form->{subject} = qq|$form->{label} $form->{ordnumber}| unless $form->{subject};
# if there is a message stuff it into the notes
my $cc = "Cc: $form->{cc}\\r\n" if $form->{cc};
my $bcc = "Bcc: $form->{bcc}\\r\n" if $form->{bcc};
$form->{notes} .= qq|\r
\r
[email]\r
To: $form->{email}\r
$cc${bcc}Subject: $form->{subject}\r
\r
Message: $form->{message}\r| if $form->{message};
# save OE record
$query = qq|UPDATE oe set
ordnumber = '$form->{ordnumber}',
transdate = '$form->{orddate}',
vendor_id = $form->{vendor_id},
customer_id = $form->{customer_id},
amount = $amount,
netamount = $netamount,
reqdate = $reqdate,
taxincluded = '$form->{taxincluded}',
shippingpoint = '$form->{shippingpoint}',
notes = '$form->{notes}',
curr = '$form->{currency}',
closed = '$form->{closed}'
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$form->{ordtotal} = $amount;
 
# add shipto
$form->{name} = $form->{$form->{vc}};
$form->{name} =~ s/--$form->{"$form->{vc}_id"}//;
$form->add_shipto($dbh, $form->{id});
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
if ($form->{vc} eq 'customer') {
$form->update_exchangerate($dbh, $form->{currency}, $form->{orddate}, $form->{exchangerate}, 0);
}
if ($form->{vc} eq 'vendor') {
$form->update_exchangerate($dbh, $form->{currency}, $form->{orddate}, 0, $form->{exchangerate});
}
}
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
sub delete_order {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $query;
 
# can't use $form->delete_exchangerate
if ($form->{currency} ne $form->{defaultcurrency}) {
$query = qq|SELECT transdate FROM acc_trans
WHERE ar.id = trans_id
AND ar.curr = '$form->{currency}'
AND transdate = '$form->{orddate}'
UNION SELECT transdate FROM acc_trans
WHERE ap.id = trans_id
AND ap.curr = '$form->{currency}'
AND transdate = '$form->{orddate}'|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my ($transdate) = $sth->fetchrow_array;
$sth->finish;
 
if (!$transdate) {
$query = qq|DELETE FROM exchangerate
WHERE curr = '$form->{currency}'
AND transdate = '$form->{orddate}'|;
$dbh->do($query) || $self->dberror($query);
}
}
# delete OE record
$query = qq|DELETE FROM oe
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# delete individual entries
$query = qq|DELETE FROM orderitems
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
sub retrieve_order {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $query;
 
if ($form->{id}) {
# get default accounts and last order number
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE d.inventory_accno_id = c.id) AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE d.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c
WHERE d.expense_accno_id = c.id) AS expense_accno,
(SELECT c.accno FROM chart c
WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
(SELECT c.accno FROM chart c
WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
d.curr AS currencies
FROM defaults d|;
} else {
my $ordnumber = ($form->{vc} eq 'customer') ? 'sonumber' : 'ponumber';
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE d.inventory_accno_id = c.id) AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE d.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c
WHERE d.expense_accno_id = c.id) AS expense_accno,
(SELECT c.accno FROM chart c
WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
(SELECT c.accno FROM chart c
WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
$ordnumber AS ordnumber, d.curr AS currencies,
current_date AS orddate, current_date AS reqdate
FROM defaults d|;
}
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
 
($form->{currency}) = split /:/, $form->{currencies};
if ($form->{id}) {
# retrieve order
$query = qq|SELECT o.ordnumber, o.transdate AS orddate, o.reqdate,
o.taxincluded, o.shippingpoint, o.notes, o.curr AS currency,
(SELECT name FROM employee e
WHERE e.id = o.employee_id) AS employee,
o.$form->{vc}_id, cv.name AS $form->{vc}, o.amount AS invtotal,
o.closed, o.reqdate
FROM oe o, $form->{vc} cv
WHERE o.$form->{vc}_id = cv.id
AND o.id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
$query = qq|SELECT * FROM shipto
WHERE trans_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
my %oid = ( 'Pg' => 'oid',
'Oracle' => 'rowid',
'DB2' => '' );
 
# retrieve individual items
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE p.inventory_accno_id = c.id)
AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE p.income_accno_id = c.id)
AS income_accno,
(SELECT c.accno FROM chart c
WHERE p.expense_accno_id = c.id)
AS expense_accno,
p.partnumber, p.assembly, p.bom, o.description, o.qty,
o.sellprice, o.parts_id AS id, o.unit, o.discount, p.bin,
o.reqdate, (SELECT projectnumber FROM project pr
WHERE o.project_id = pr.id) AS projectnumber,
o.project_id
FROM orderitems o, parts p
WHERE o.parts_id = p.id
AND trans_id = $form->{id}
ORDER BY o.$oid{$myconfig->{dbdriver}}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
 
# get tax rates for part
$query = qq|SELECT c.accno
FROM chart c, tax t, partstax pt
WHERE t.chart_id = pt.chart_id
AND pt.chart_id = c.id
AND pt.parts_id = $ref->{id}|;
my $pth = $dbh->prepare($query);
$pth->execute || $form->dberror($query);
 
$ref->{taxaccounts} = "";
my $taxrate = 0;
while (my $ptref = $pth->fetchrow_hashref(NAME_lc)) {
$ref->{taxaccounts} .= "$ptref->{accno} ";
$taxrate += $form->{"$ptref->{accno}_rate"};
}
$pth->finish;
chop $ref->{taxaccounts};
 
push @{ $form->{order_details} }, $ref;
}
$sth->finish;
 
} else {
 
my $ordnumber = ($form->{vc} eq 'customer') ? 'sonumber' : 'ponumber';
# up order number by 1
$form->{ordnumber}++;
 
# save the new number
$query = qq|UPDATE defaults
SET $ordnumber = '$form->{ordnumber}'|;
$dbh->do($query) || $form->dberror($query);
 
$form->get_employee($dbh);
# get last name used
$form->lastname_used($dbh, $myconfig, $form->{vc}) unless $form->{"$form->{vc}_id"};
 
}
$form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{orddate}, ($form->{vc} eq 'customer') ? "buy" : "sell");
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
sub order_details {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $tax = 0;
my $item;
my $i;
my @projects = ();
# sort items by projectnumber
for $i (1 .. $form->{rowcount}) {
# get project description
$form->{"projectdescription_$i"} = "";
if ($form->{"project_id_$i"}) {
$form->{"projectdescription_$i"} = &project_description("", $dbh, $form->{"project_id_$i"});
$form->format_string("projectnumber_$i", "projectdescription_$i");
}
push @projects, [ $i, $form->{"projectnumber_$i"}, $form->{"projectdescription_$i"} ];
}
my $sameitem = "";
foreach $item (sort { $a->[1] cmp $b->[1] } @projects) {
$i = $item->[0];
 
if ($item->[2] ne $sameitem) {
push(@{ $form->{description} }, qq|$item->[2]|);
$sameitem = $item->[2];
 
map { push(@{ $form->{$_} }, "") } qw(runningnumber number bin qty unit reqdate sellprice netprice discount linetotal);
}
 
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
if ($form->{"qty_$i"} != 0) {
 
# add number, description and qty to $form->{number}, ....
push(@{ $form->{runningnumber} }, $i);
push(@{ $form->{number} }, qq|$form->{"partnumber_$i"}|);
push(@{ $form->{description} }, qq|$form->{"description_$i"}|);
push(@{ $form->{qty} }, $form->format_amount($myconfig, $form->{"qty_$i"}));
push(@{ $form->{unit} }, qq|$form->{"unit_$i"}|);
push(@{ $form->{reqdate} }, qq|$form->{"reqdate_$i"}|);
push(@{ $form->{sellprice} }, $form->{"sellprice_$i"});
my $sellprice = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
my ($dec) = ($sellprice =~ /\.(\d+)/);
$dec = length $dec;
my $decimalplaces = ($dec > 2) ? $dec : 2;
my $discount = $form->round_amount($sellprice * $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100, $decimalplaces);
 
# keep a netprice as well, (sellprice - discount)
$form->{"netprice_$i"} = $sellprice - $discount;
 
my $linetotal = $form->round_amount($form->{"qty_$i"} * $form->{"netprice_$i"}, 2);
 
push(@{ $form->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : " ");
$discount = ($discount != 0) ? $form->format_amount($myconfig, $discount * -1, $decimalplaces) : " ";
$linetotal = ($linetotal != 0) ? $linetotal : " ";
 
push(@{ $form->{discount} }, $discount);
$form->{ordtotal} += $linetotal;
 
push(@{ $form->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2));
my ($taxamount, $taxbase);
my $taxrate = 0;
map { $taxrate += $form->{"${_}_rate"} } split / /, $form->{"taxaccounts_$i"};
 
if ($form->{taxincluded}) {
# calculate tax
$taxamount = $linetotal * $taxrate / (1 + $taxrate);
$taxbase = $linetotal / (1 + $taxrate);
} else {
$taxamount = $linetotal * $taxrate;
$taxbase = $linetotal;
}
 
 
if ($taxamount != 0) {
foreach my $item (split / /, $form->{"taxaccounts_$i"}) {
$taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
$taxbase{$item} += $taxbase;
}
}
 
if ($form->{"assembly_$i"} && $form->{"bom_$i"}) {
# get parts and push them onto the stack
$query = qq|SELECT p.partnumber, p.description, p.unit, a.qty
FROM assembly a, parts p
WHERE a.parts_id = p.id
AND a.id = '$form->{"id_$i"}'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push(@{ $form->{number} }, qq|$ref->{partnumber}|);
push(@{ $form->{description} }, qq|$ref->{description}|);
push(@{ $form->{unit} }, qq|$ref->{unit}|);
push(@{ $form->{qty} }, $form->format_amount($myconfig, $ref->{qty}));
 
map { push(@{ $form->{$_} }, "") } qw(runningnumber bin sellprice listprice netprice discount linetotal);
}
$sth->finish;
}
 
}
}
 
 
foreach $item (sort keys %taxaccounts) {
if ($form->round_amount($taxaccounts{$item}, 2) != 0) {
push(@{ $form->{taxbase} }, $form->format_amount($myconfig, $taxbase{$item}, 2));
$taxamount = $form->round_amount($taxaccounts{$item}, 2);
$tax += $taxamount;
push(@{ $form->{tax} }, $form->format_amount($myconfig, $taxamount, 2));
push(@{ $form->{taxdescription} }, $form->{"${item}_description"});
push(@{ $form->{taxrate} }, $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
push(@{ $form->{taxnumber} }, $form->{"${item}_taxnumber"});
}
}
 
 
$form->{subtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
$form->{ordtotal} = ($form->{taxincluded}) ? $form->{ordtotal} : $form->{ordtotal} + $tax;
# format amounts
$form->{ordtotal} = $form->format_amount($myconfig, $form->{ordtotal}, 2);
 
# myconfig variables
map { $form->{$_} = $myconfig->{$_} } (qw(company address tel fax signature businessnumber));
$form->{username} = $myconfig->{name};
 
$dbh->disconnect;
 
}
 
 
sub project_description {
my ($self, $dbh, $id) = @_;
 
my $query = qq|SELECT description
FROM project
WHERE id = $id|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($_) = $sth->fetchrow_array;
$sth->finish;
 
$_;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/Form.pm
New file
0,0 → 1,1417
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 1998-2003
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors: Thomas Bayen <bayen@gmx.de>
# Antti Kaihola <akaihola@siba.fi>
# Moritz Bunkus (tex code)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
# Utilities for parsing forms
# and supporting routines for linking account numbers
# used in AR, AP and IS, IR modules
#
#======================================================================
 
package Form;
 
 
sub new {
my $type = shift;
my $self = {};
 
read(STDIN, $_, $ENV{CONTENT_LENGTH});
if ($ENV{QUERY_STRING}) {
$_ = $ENV{QUERY_STRING};
}
 
if ($ARGV[0]) {
$_ = $ARGV[0];
}
 
foreach $item (split(/&/)) {
($key, $value) = split(/=/, $item);
$self->{$key} = &unescape("",$value);
}
 
$self->{action} = lc $self->{action};
$self->{action} =~ s/( |-|,)/_/g;
 
$self->{version} = "2.0.6";
$self->{dbversion} = "2.0.0";
 
bless $self, $type;
}
 
 
sub debug {
my ($self) = @_;
print "\n";
map { print "$_ = $self->{$_}\n" } (sort keys %{$self});
}
 
sub escape {
my ($self, $str, $beenthere) = @_;
 
# for Apache 2 we escape strings twice
if (($ENV{SERVER_SOFTWARE} =~ /Apache\/2/) && !$beenthere) {
$str = $self->escape($str, 1);
}
$str =~ s/([^a-zA-Z0-9_.-])/sprintf("%%%02x", ord($1))/ge;
$str;
 
}
 
 
sub unescape {
my ($self, $str) = @_;
$str =~ tr/+/ /;
$str =~ s/\\$//;
 
$str =~ s/%([0-9a-fA-Z]{2})/pack("c",hex($1))/eg;
 
$str;
 
}
 
 
sub error {
my ($self, $msg) = @_;
 
if ($ENV{HTTP_USER_AGENT}) {
$msg =~ s/\n/<br>/g;
 
print qq|Content-Type: text/html
 
<body bgcolor=ffffff>
 
<h2><font color=red>Error!</font></h2>
 
<p><b>$msg</b>
</body>
</html>
|;
 
die "Error: $msg\n";
 
} else {
if ($self->{error_function}) {
&{ $self->{error_function} }($msg);
} else {
die "Error: $msg\n";
}
}
}
 
 
 
sub info {
my ($self, $msg) = @_;
 
if ($ENV{HTTP_USER_AGENT}) {
$msg =~ s/\n/<br>/g;
 
if (!$self->{header}) {
$self->header;
print qq|
<body>|;
}
 
print qq|
 
<p><b>$msg</b>
|;
} else {
if ($self->{info_function}) {
&{ $self->{info_function} }($msg);
} else {
print "$msg\n";
}
}
}
 
 
sub numtextrows {
my ($self, $str, $cols, $maxrows) = @_;
 
my $rows;
 
map { $rows += int ((length $_)/$cols) + 1 } (split /\r/, $str);
 
$rows = $maxrows if (defined $maxrows && ($rows > $maxrows));
$rows;
 
}
 
 
sub dberror {
my ($self, $msg) = @_;
 
$self->error("$msg\n".$DBI::errstr);
}
 
 
sub isblank {
my ($self, $name, $msg) = @_;
 
if ($self->{$name} =~ /^\s*$/) {
$self->error($msg);
}
}
 
sub header {
my ($self) = @_;
 
my ($nocache, $stylesheet, $charset);
# use expire tag to prevent caching
# $nocache = qq|<META HTTP-EQUIV="Expires" CONTENT="Tue, 01 Jan 1980 1:00:00 GMT">
# <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
#|;
 
if ($self->{stylesheet} && (-f "css/$self->{stylesheet}")) {
$stylesheet = qq|<LINK REL="stylesheet" HREF="css/$self->{stylesheet}" TYPE="text/css" TITLE="SQL-Ledger style sheet">
|;
}
 
if ($self->{charset}) {
$charset = qq|<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=$self->{charset}">
|;
}
 
$self->{titlebar} = ($self->{title}) ? "$self->{title} - $self->{titlebar}" : $self->{titlebar};
print qq|Content-Type: text/html
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<head>
<title>$self->{titlebar}</title>
$nocache
$stylesheet
$charset
</head>
 
|;
 
}
 
 
sub redirect {
my ($self, $msg) = @_;
 
if ($self->{callback}) {
 
($script, $argv) = split(/\?/, $self->{callback});
 
exec ("perl", "$script", $argv);
} else {
if ($ENV{HTTP_USER_AGENT}) {
$msg =~ s/\n/<br>/g;
 
print qq|Content-Type: text/html
 
<body bgcolor=ffffff>
 
<h2>$msg</h2>
 
</body>
</html>
|;
 
} else {
print "$msg\n";
}
 
exit;
}
 
}
 
 
sub sort_columns {
my ($self, @columns) = @_;
 
@columns = grep !/^$self->{sort}$/, @columns;
splice @columns, 0, 0, $self->{sort};
 
@columns;
}
 
 
sub format_amount {
my ($self, $myconfig, $amount, $places, $dash) = @_;
 
if ($places =~ /\d/) {
$amount = $self->round_amount($amount, $places);
}
 
# is the amount negative
my $negative = ($amount < 0);
if ($amount != 0) {
if ($myconfig->{numberformat} && ($myconfig->{numberformat} ne '1000.00')) {
my ($whole, $dec) = split /\./, "$amount";
$whole =~ s/-//;
$amount = join '', reverse split //, $whole;
if ($myconfig->{numberformat} eq '1,000.00') {
$amount =~ s/\d{3,}?/$&,/g;
$amount =~ s/,$//;
$amount = join '', reverse split //, $amount;
$amount .= "\.$dec" if ($dec ne "");
}
if ($myconfig->{numberformat} eq '1.000,00') {
$amount =~ s/\d{3,}?/$&./g;
$amount =~ s/\.$//;
$amount = join '', reverse split //, $amount;
$amount .= ",$dec" if ($dec ne "");
}
if ($myconfig->{numberformat} eq '1000,00') {
$amount = "$whole";
$amount .= ",$dec" if ($dec ne "");
}
 
if ($dash =~ /-/) {
$amount = ($negative) ? "($amount)" : "$amount";
} elsif ($dash =~ /DRCR/) {
$amount = ($negative) ? "$amount DR" : "$amount CR";
} else {
$amount = ($negative) ? "-$amount" : "$amount";
}
}
} else {
if ($dash eq "0" && $places) {
if ($myconfig->{numberformat} eq '1.000,00') {
$amount = "0".","."0" x $places;
} else {
$amount = "0"."."."0" x $places;
}
} else {
$amount = ($dash ne "") ? "$dash" : "";
}
}
 
$amount;
 
}
 
 
sub parse_amount {
my ($self, $myconfig, $amount) = @_;
 
if (($myconfig->{numberformat} eq '1.000,00') ||
($myconfig->{numberformat} eq '1000,00')) {
$amount =~ s/\.//g;
$amount =~ s/,/\./;
}
 
$amount =~ s/,//g;
return ($amount * 1);
 
}
 
 
sub round_amount {
my ($self, $amount, $places) = @_;
 
# $places = 3 if $places == 2;
if (($places * 1) >= 0) {
# compensate for perl behaviour, add 1/10^$places+3
sprintf("%.${places}f", $amount + (1 / (10 ** ($places + 3))) * (($amount > 0) ? 1 : -1));
} else {
$places *= -1;
sprintf("%.f", $amount / (10 ** $places) + (($amount > 0) ? 0.1 : -0.1)) * (10 ** $places);
}
 
}
 
 
sub parse_template {
my ($self, $myconfig, $userspath) = @_;
 
# { Moritz Bunkus
# Some variables used for page breaks
my ($chars_per_line, $lines_on_first_page, $lines_on_second_page) = (0, 0, 0);
my ($current_page, $current_line) = (1, 1);
my $pagebreak = "";
my $sum = 0;
# } Moritz Bunkus
 
open(IN, "$self->{templates}/$self->{IN}") or $self->error("$self->{IN} : $!");
 
@_ = <IN>;
close(IN);
$self->{copies} = 1 if (($self->{copies} *= 1) <= 0);
# OUT is used for the media, screen, printer, email
# for postscript we store a copy in a temporary file
my $fileid = time;
$self->{tmpfile} = "$userspath/${fileid}.$self->{IN}";
if ($self->{format} =~ /(postscript|pdf)/ || $self->{media} eq 'email') {
$out = $self->{OUT};
$self->{OUT} = ">$self->{tmpfile}";
}
if ($self->{OUT}) {
open(OUT, "$self->{OUT}") or $self->error("$self->{OUT} : $!");
} else {
open(OUT, ">-") or $self->error("STDOUT : $!");
$self->header;
}
 
 
# first we generate a tmpfile
# read file and replace <%variable%>
while ($_ = shift) {
$par = "";
$var = $_;
 
 
# { Moritz Bunkus
# detect pagebreak block and its parameters
if (/<%pagebreak ([0-9]+) ([0-9]+) ([0-9]+)%>/) {
$chars_per_line = $1;
$lines_on_first_page = $2;
$lines_on_second_page = $3;
while ($_ = shift) {
last if (/<\%end pagebreak%>/);
$pagebreak .= $_;
}
}
# } Moritz Bunkus
 
if (/<%foreach /) {
# this one we need for the count
chomp $var;
$var =~ s/<%foreach (.+?)%>/$1/;
while ($_ = shift) {
last if (/<%end /);
 
# store line in $par
$par .= $_;
}
# display contents of $self->{number}[] array
for $i (0 .. $#{ $self->{$var} }) {
 
# { Moritz Bunkus
# Try to detect whether a manual page break is necessary
# but only if there was a <%pagebreak ...%> block before
if ($chars_per_line) {
my $lines = int(length($self->{"description"}[$i]) / $chars_per_line + 0.95);
my $lpp;
if ($current_page == 1) {
$lpp = $lines_on_first_page;
} else {
$lpp = $lines_on_second_page;
}
 
# Yes we need a manual page break
if (($current_line + $lines) > $lpp) {
my $pb = $pagebreak;
# replace the special variables <%sumcarriedforward%>
# and <%lastpage%>
my $psum = $self->format_amount($myconfig, $sum, 2);
$pb =~ s/<%sumcarriedforward%>/$psum/g;
$pb =~ s/<%lastpage%>/$current_page/g;
# only "normal" variables are supported here
# (no <%if, no <%foreach, no <%include)
$pb =~ s/<%(.+?)%>/$self->{$1}/g;
# page break block is ready to rock
print(OUT $pb);
$current_page++;
$current_line = 1;
}
$current_line += $lines;
}
$sum += $self->parse_amount($myconfig, $self->{"linetotal"}[$i]);
# } Moritz Bunkus
 
 
# don't parse par, we need it for each line
$_ = $par;
s/<%(.+?)%>/$self->{$1}[$i]/mg;
print OUT;
}
next;
}
 
# if not comes before if!
if (/<%if not /) {
# check if it is not set and display
chop;
s/<%if not (.+?)%>/$1/;
 
unless ($self->{$_}) {
while ($_ = shift) {
last if (/<%end /);
 
# store line in $par
$par .= $_;
}
$_ = $par;
} else {
while ($_ = shift) {
last if (/<%end /);
}
next;
}
}
if (/<%if /) {
# check if it is set and display
chop;
s/<%if (.+?)%>/$1/;
 
if ($self->{$_}) {
while ($_ = shift) {
last if (/<%end /);
 
# store line in $par
$par .= $_;
}
$_ = $par;
} else {
while ($_ = shift) {
last if (/<%end /);
}
next;
}
}
# check for <%include filename%>
if (/<%include /) {
# get the filename
chomp $var;
$var =~ s/<%include (.+?)%>/$1/;
 
# mangle filename if someone tries to be cute
$var =~ s/\///g;
 
# prevent the infinite loop!
next if ($self->{"$var"});
 
open(INC, "$self->{templates}/$var") or $self->error($self->cleanup."$self->{templates}/$var : $!");
unshift(@_, <INC>);
close(INC);
 
$self->{"$var"} = 1;
 
next;
}
s/<%(.+?)%>/$self->{$1}/g;
print OUT;
}
 
close(OUT);
 
 
# { Moritz Bunkus
# Convert the tex file to postscript
if ($self->{format} =~ /(postscript|pdf)/) {
 
use Cwd;
$self->{cwd} = cwd();
chdir("$userspath") or $self->error($self->cleanup."chdir : $!");
 
$self->{tmpfile} =~ s/$userspath\///g;
 
# DS. added screen and email option in addition to printer
# screen
if ($self->{format} eq 'postscript') {
system("latex --interaction=nonstopmode $self->{tmpfile} > $self->{tmpfile}.err");
$self->error($self->cleanup) if ($?);
$self->{tmpfile} =~ s/tex$/dvi/;
 
system("dvips $self->{tmpfile} -o -q > /dev/null");
$self->error($self->cleanup."dvips : $!") if ($?);
$self->{tmpfile} =~ s/dvi$/ps/;
}
if ($self->{format} eq 'pdf') {
system("pdflatex --interaction=nonstopmode $self->{tmpfile} > $self->{tmpfile}.err");
$self->error($self->cleanup) if ($?);
$self->{tmpfile} =~ s/tex$/pdf/;
}
 
}
 
if ($self->{format} =~ /(postscript|pdf)/ || $self->{media} eq 'email') {
 
if ($self->{media} eq 'email') {
use SL::Mailer;
 
my $mail = new Mailer;
$self->{email} =~ s/,/>,</g;
map { $mail->{$_} = $self->{$_} } qw(cc bcc subject message version format charset);
$mail->{to} = qq|"$self->{name}" <$self->{email}>|;
$mail->{from} = qq|"$myconfig->{name}" <$myconfig->{email}>|;
$mail->{fileid} = "$fileid.";
 
# if we send html or plain text inline
if (($self->{format} eq 'html') && ($self->{sendmode} eq 'inline')) {
$mail->{contenttype} = "text/html";
 
$mail->{message} =~ s/\r\n/<br>\n/g;
$myconfig->{signature} =~ s/\\n/<br>\n/g;
$mail->{message} .= "<br>\n--<br>\n$myconfig->{signature}\n<br>";
open(IN, $self->{tmpfile}) or $self->error($self->cleanup."$self->{tmpfile} : $!");
while (<IN>) {
$mail->{message} .= $_;
}
 
close(IN);
 
} else {
@{ $mail->{attachments} } = ($self->{tmpfile});
 
$myconfig->{signature} =~ s/\\n/\r\n/g;
$mail->{message} .= "\r\n--\r\n$myconfig->{signature}";
 
}
my $err = $mail->send($out);
$self->error($self->cleanup."$err") if ($err);
} else {
$self->{OUT} = $out;
open(IN, $self->{tmpfile}) or $self->error($self->cleanup."$self->{tmpfile} : $!");
if ($self->{OUT}) {
open(OUT, $self->{OUT}) or $self->error($self->cleanup."$self->{OUT} : $!");
} else {
open(OUT, ">-") or $self->error($self->cleanup."$!: STDOUT");
# launch application
print qq|Content-Type: application/$self->{format}; name="$self->{tmpfile}"
Content-Disposition: filename="$self->{tmpfile}"
 
|;
$self->{copies} = 1;
}
for my $i (1 .. $self->{copies}) {
while (<IN>) {
print OUT $_;
}
seek IN, 0, 0;
}
 
close(IN);
close(OUT);
}
 
$self->cleanup;
 
}
# } Moritz Bunkus
 
}
 
 
sub cleanup {
my $self = shift;
 
my @err = ();
if (-f "$self->{tmpfile}.err") {
open(FH, "$self->{tmpfile}.err");
@err = <FH>;
close(FH);
}
if ($self->{tmpfile}) {
# strip extension
$self->{tmpfile} =~ s/\.\w+$//g;
my $tmpfile = $self->{tmpfile};
unlink(<$tmpfile.*>);
}
 
 
chdir("$self->{cwd}");
"@err";
}
 
 
sub format_string {
my ($self, @fields) = @_;
 
my $format = $self->{format};
if ($self->{format} =~ /(postscript|pdf)/) {
$format = 'tex';
}
 
+' ],
+',
+ '\$', '%', '_', '#', quotemeta('^'),
+ '{', '}', '<', '>', '£' ] },
+ 'html' => {
+' => '<br>'
+ },
+ 'tex' => {
+ '&' => '\&', '\$' => '\$', '%' => '\%', '_' => '\_',
+ '#' => '\#', quotemeta('^') => '\^\\', '{' => '\{', '}' => '\}',
+ '<' => '$<$', '>' => '$>$',
+' => '\newline ',
+ '£' => '\pounds ',
+ }
+ );
+
+ foreach my $key (@{ $replace{order}{$format} }) {
+ map { $self->{$_} =~ s/$key/$replace{$format}{$key}/g; } @fields;
+ }
+
+}
+
+
+sub datetonum {
+ my ($self, $date, $myconfig) = @_;
+
+ if ($date) {
+ # get separator
+ my $spc = $myconfig->{dateformat};
+ $spc =~ s/\w//g;
+ $spc = substr($spc, 1, 1);
+
+ if ($spc eq '.') {
+ $spc = '\.';
+ }
+ if ($spc eq '/') {
+ $spc = '\/';
+ }
+
+ if ($myconfig->{dateformat} =~ /^yy/) {
+ ($yy, $mm, $dd) = split /$spc/, $date;
+ }
+ if ($myconfig->{dateformat} =~ /^mm/) {
+ ($mm, $dd, $yy) = split /$spc/, $date;
+ }
+ if ($myconfig->{dateformat} =~ /^dd/) {
+ ($dd, $mm, $yy) = split /$spc/, $date;
+ }
+
+ $dd *= 1;
+ $mm *= 1;
+ $yy = ($yy < 70) ? $yy + 2000 : $yy;
+ $yy = ($yy >= 70 && $yy <= 99) ? $yy + 1900 : $yy;
+
+ $dd = "0$dd" if ($dd < 10);
+ $mm = "0$mm" if ($mm < 10);
+
+ $date = "$yy$mm$dd";
+ }
+
+ $date;
+
+}
+
+
+
+# Database routines used throughout
+
+sub dbconnect {
+ my ($self, $myconfig) = @_;
+
+ # connect to database
+ my $dbh = DBI->connect($myconfig->{dbconnect}, $myconfig->{dbuser}, $myconfig->{dbpasswd}) or $self->dberror;
+
+ # set db options
+ if ($myconfig->{dboptions}) {
+ $dbh->do($myconfig->{dboptions}) || $self->dberror($myconfig->{dboptions});
+ }
+
+ $dbh;
+
+}
+
+
+sub dbconnect_noauto {
+ my ($self, $myconfig) = @_;
+
+ # connect to database
+ $dbh = DBI->connect($myconfig->{dbconnect}, $myconfig->{dbuser}, $myconfig->{dbpasswd}, {AutoCommit => 0}) or $self->dberror;
+
+ # set db options
+ if ($myconfig->{dboptions}) {
+ $dbh->do($myconfig->{dboptions}) || $self->dberror($myconfig->{dboptions});
+ }
+
+ $dbh;
+
+}
+
+
+sub update_balance {
+ my ($self, $dbh, $table, $field, $where, $value) = @_;
+
+ # if we have a value, go do it
+ if ($value != 0) {
+ # retrieve balance from table
+ my $query = "SELECT $field FROM $table WHERE $where";
+ my $sth = $dbh->prepare($query);
+
+ $sth->execute || $self->dberror($query);
+ my ($balance) = $sth->fetchrow_array;
+ $sth->finish;
+
+ $balance += $value;
+ # update balance
+ $query = "UPDATE $table SET $field = $balance WHERE $where";
+ $dbh->do($query) || $self->dberror($query);
+ }
+}
+
+
+
+sub update_exchangerate {
+ my ($self, $dbh, $curr, $transdate, $buy, $sell) = @_;
+
+ # some sanity check for currency
+ return if ($curr eq '');
+
+ my $query = qq|SELECT curr FROM exchangerate
+ WHERE curr = '$curr'
+ AND transdate = '$transdate'|;
+ my $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ my $set;
+ if ($buy != 0 && $sell != 0) {
+ $set = "buy = $buy, sell = $sell";
+ } elsif ($buy != 0) {
+ $set = "buy = $buy";
+ } elsif ($sell != 0) {
+ $set = "sell = $sell";
+ }
+
+ if ($sth->fetchrow_array) {
+ $query = qq|UPDATE exchangerate
+ SET $set
+ WHERE curr = '$curr'
+ AND transdate = '$transdate'|;
+ } else {
+ $query = qq|INSERT INTO exchangerate (curr, buy, sell, transdate)
+ VALUES ('$curr', $buy, $sell, '$transdate')|;
+ }
+ $sth->finish;
+ $dbh->do($query) || $self->dberror($query);
+
+}
+
+
+sub get_exchangerate {
+ my ($self, $dbh, $curr, $transdate, $fld) = @_;
+
+ my $query = qq|SELECT $fld FROM exchangerate
+ WHERE curr = '$curr'
+ AND transdate = '$transdate'|;
+ my $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ my ($exchangerate) = $sth->fetchrow_array;
+ $sth->finish;
+
+ $exchangerate;
+
+}
+
+
+sub delete_exchangerate {
+ my ($self, $dbh) = @_;
+
+ my @transdate = ();
+ my $transdate;
+
+ my $query = qq|SELECT DISTINCT transdate
+ FROM acc_trans
+ WHERE trans_id = $self->{id}|;
+ my $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ while ($transdate = $sth->fetchrow_array) {
+ push @transdate, $transdate;
+ }
+ $sth->finish;
+
+ $query = qq|SELECT transdate FROM acc_trans
+ WHERE ar.id = trans_id
+ AND ar.curr = '$self->{currency}'
+ AND transdate IN
+ (SELECT transdate FROM acc_trans
+ WHERE trans_id = $self->{id})
+ AND trans_id != $self->{id}
+ UNION SELECT transdate FROM acc_trans
+ WHERE ap.id = trans_id
+ AND ap.curr = '$self->{currency}'
+ AND transdate IN
+ (SELECT transdate FROM acc_trans
+ WHERE trans_id = $self->{id})
+ AND trans_id != $self->{id}
+ UNION SELECT transdate FROM oe
+ WHERE oe.curr = '$self->{currency}'
+ AND transdate IN
+ (SELECT transdate FROM acc_trans
+ WHERE trans_id = $self->{id})|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ while ($transdate = $sth->fetchrow_array) {
+ @transdate = grep !/^$transdate$/, @transdate;
+ }
+ $sth->finish;
+
+ foreach $transdate (@transdate) {
+ $query = qq|DELETE FROM exchangerate
+ WHERE curr = '$self->{currency}'
+ AND transdate = '$transdate'|;
+ $dbh->do($query) || $self->dberror($query);
+ }
+
+}
+
+
+sub check_exchangerate {
+ my ($self, $myconfig, $currency, $transdate, $fld) = @_;
+
+ return "" unless $transdate;
+
+ my $dbh = $self->dbconnect($myconfig);
+
+ my $query = qq|SELECT $fld FROM exchangerate
+ WHERE curr = '$currency'
+ AND transdate = '$transdate'|;
+ my $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ my ($exchangerate) = $sth->fetchrow_array;
+ $sth->finish;
+ $dbh->disconnect;
+
+ $exchangerate;
+
+}
+
+
+sub add_shipto {
+ my ($self, $dbh, $id) = @_;
+
+ my $shipto;
+ foreach my $item (qw(name addr1 addr2 addr3 addr4 contact phone fax email)) {
+ if ($self->{"shipto$item"}) {
+ $shipto = 1 if ($self->{$item} ne $self->{"shipto$item"});
+ }
+ $self->{"shipto$item"} =~ s/'/''/g;
+ }
+
+ if ($shipto) {
+ my $query = qq|INSERT INTO shipto (trans_id, shiptoname, shiptoaddr1,
+ shiptoaddr2, shiptoaddr3, shiptoaddr4, shiptocontact,
+ shiptophone, shiptofax, shiptoemail) VALUES ($id,
+ '$self->{shiptoname}', '$self->{shiptoaddr1}',
+ '$self->{shiptoaddr2}', '$self->{shiptoaddr3}',
+ '$self->{shiptoaddr4}', '$self->{shiptocontact}',
+ '$self->{shiptophone}', '$self->{shiptofax}',
+ '$self->{shiptoemail}')|;
+ $dbh->do($query) || $self->dberror($query);
+ }
+
+}
+
+
+sub get_employee {
+ my ($self, $dbh) = @_;
+
+ my $query = qq|SELECT name FROM employee
+ WHERE login = '$self->{login}'|;
+ my $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ ($self->{employee}) = $sth->fetchrow_array;
+ $sth->finish;
+
+}
+
+
+# this sub gets the id and name from $table
+sub get_name {
+ my ($self, $myconfig, $table) = @_;
+
+ # connect to database
+ my $dbh = $self->dbconnect($myconfig);
+
+ my $name = $self->like(lc $self->{$table});
+ my $query = qq~SELECT id, name,
+ addr1 || ' ' || addr2 || ' ' || addr3 || ' ' || addr4 AS address
+ FROM $table
+ WHERE lower(name) LIKE '$name'
+ ORDER BY name~;
+ my $sth = $dbh->prepare($query);
+
+ $sth->execute || $self->dberror($query);
+
+ my $i = 0;
+ while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
+ push(@{ $self->{name_list} }, $ref);
+ $i++;
+ }
+ $sth->finish;
+ $dbh->disconnect;
+
+ $i;
+
+}
+
+
+# the selection sub is used in the AR, AP, IS, IR and OE module
+#
+sub all_vc {
+ my ($self, $myconfig, $table) = @_;
+
+ my $dbh = $self->dbconnect($myconfig);
+
+ my $query = qq|SELECT count(*) FROM $table|;
+ my $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+ my ($count) = $sth->fetchrow_array;
+ $sth->finish;
+
+ # build selection list
+ if ($count < $myconfig->{vclimit}) {
+ $query = qq|SELECT id, name
+ FROM $table
+ ORDER BY name|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
+ push @{ $self->{"all_$table"} }, $ref;
+ }
+
+ $sth->finish;
+
+ }
+
+ $dbh->disconnect;
+
+}
+
+
+sub create_links {
+ my ($self, $module, $myconfig, $table) = @_;
+
+ $self->all_vc($myconfig, $table);
+
+ # get last customers or vendors
+ my ($query, $sth);
+
+ my $dbh = $self->dbconnect($myconfig);
+
+ my %xkeyref = ();
+
+
+ # now get the account numbers
+ $query = qq|SELECT accno, description, link
+ FROM chart
+ WHERE link LIKE '%$module%'
+ ORDER BY accno|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ $self->{accounts} = "";
+ while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
+
+ foreach my $key (split(/:/, $ref->{link})) {
+ if ($key =~ /$module/) {
+ # cross reference for keys
+ $xkeyref{$ref->{accno}} = $key;
+
+ push @{ $self->{"${module}_links"}{$key} }, { accno => $ref->{accno},
+ description => $ref->{description} };
+
+ $self->{accounts} .= "$ref->{accno} " unless $key =~ /tax/;
+ }
+ }
+ }
+ $sth->finish;
+
+
+ if ($self->{id}) {
+ my $arap = ($table eq 'customer') ? 'ar' : 'ap';
+
+ $query = qq|SELECT a.invnumber, a.transdate,
+ a.${table}_id, a.datepaid, a.duedate, a.ordnumber,
+ a.taxincluded, a.curr AS currency, a.notes, c.name AS $table,
+ a.amount AS oldinvtotal, a.paid AS oldtotalpaid
+ FROM $arap a, $table c
+ WHERE a.${table}_id = c.id
+ AND a.id = $self->{id}|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ $ref = $sth->fetchrow_hashref(NAME_lc);
+ foreach $key (keys %$ref) {
+ $self->{$key} = $ref->{$key};
+ }
+ $sth->finish;
+
+ # get amounts from individual entries
+ $query = qq|SELECT c.accno, c.description, a.source, a.amount,
+ a.transdate, a.cleared, a.project_id,
+ (SELECT projectnumber
+ FROM project p
+ WHERE a.project_id = p.id
+ AND a.trans_id = $self->{id}) AS projectnumber
+ FROM acc_trans a, chart c
+ WHERE c.id = a.chart_id
+ AND a.trans_id = $self->{id}
+ AND a.fx_transaction = '0'
+ ORDER BY transdate|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ my $fld = ($table eq 'customer') ? 'buy' : 'sell';
+ # get exchangerate for currency
+ $self->{exchangerate} = $self->get_exchangerate($dbh, $self->{currency}, $self->{transdate}, $fld);
+
+ # store amounts in {acc_trans}{$key} for multiple accounts
+ while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
+ $ref->{exchangerate} = $self->get_exchangerate($dbh, $self->{currency}, $ref->{transdate}, $fld);
+
+ push @{ $self->{acc_trans}{$xkeyref{$ref->{accno}}} }, $ref;
+ }
+
+ $sth->finish;
+
+ $query = qq|SELECT d.curr AS currencies, d.closedto, d.revtrans,
+ (SELECT c.accno FROM chart c
+ WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
+ (SELECT c.accno FROM chart c
+ WHERE d.fxloss_accno_id = c.id) AS fxloss_accno
+ FROM defaults d|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ $ref = $sth->fetchrow_hashref(NAME_lc);
+ map { $self->{$_} = $ref->{$_} } keys %$ref;
+ $sth->finish;
+
+ } else {
+
+ # get date
+ $query = qq|SELECT current_date AS transdate,
+ d.curr AS currencies, d.closedto, d.revtrans,
+ (SELECT c.accno FROM chart c
+ WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
+ (SELECT c.accno FROM chart c
+ WHERE d.fxloss_accno_id = c.id) AS fxloss_accno
+ FROM defaults d|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ $ref = $sth->fetchrow_hashref(NAME_lc);
+ map { $self->{$_} = $ref->{$_} } keys %$ref;
+ $sth->finish;
+
+ if ($self->{"$self->{vc}_id"}) {
+ # only setup currency
+ ($self->{currency}) = split /:/, $self->{currencies};
+
+ } else {
+
+ $self->lastname_used($dbh, $myconfig, $table, $module);
+
+ my $fld = ($table eq 'customer') ? 'buy' : 'sell';
+ # get exchangerate for currency
+ $self->{exchangerate} = $self->get_exchangerate($dbh, $self->{currency}, $self->{transdate}, $fld);
+
+ }
+
+ }
+
+ $dbh->disconnect;
+
+}
+
+
+sub lastname_used {
+ my ($self, $dbh, $myconfig, $table, $module) = @_;
+
+ my $arap = ($table eq 'customer') ? "ar" : "ap";
+ $arap = 'oe' if ($self->{type} =~ /_order/);
+ my %oid = ( 'Pg' => 'a.oid',
+ 'Oracle' => 'a.rowid');
+
+ my $query = qq|SELECT a.id, ct.name, a.curr, a.${table}_id,
+ current_date + ct.terms AS duedate
+ FROM $arap a, $table ct
+ WHERE a.${table}_id = ct.id
+ AND $oid{$myconfig->{dbdriver}} =
+ (SELECT max($oid{$myconfig->{dbdriver}}) FROM $arap a
+ WHERE a.${table}_id > 0)|;
+ my $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ my $trans_id;
+ ($trans_id, $self->{$table}, $self->{currency}, $self->{"${table}_id"}, $self->{duedate}) = $sth->fetchrow_array;
+ $sth->finish;
+
+ $trans_id *= 1;
+ # get AR or AP account
+ $query = qq|SELECT c.accno FROM acc_trans a, chart c
+ WHERE a.chart_id = c.id
+ AND a.trans_id = $trans_id|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+
+ while (my ($accno) = $sth->fetchrow_array) {
+ if ($self->{accounts} =~ /$accno/) {
+ foreach my $key (keys %{$self->{"${module}_links"}}) {
+ foreach my $ref (@{ $self->{"${module}_links"}{$key} }) {
+ if ($ref->{accno} eq $accno) {
+ my $item = ($key =~ /amount/) ? "_1" : "";
+ $self->{"${key}$item"} = "$ref->{accno}--$ref->{description}";
+ last;
+ }
+ }
+ }
+ }
+ }
+ $sth->finish;
+
+}
+
+
+
+sub current_date {
+ my ($self, $myconfig, $thisdate, $days) = @_;
+
+ my $dbh = $self->dbconnect($myconfig);
+ my ($sth, $query);
+
+ $days *= 1;
+ if ($thisdate) {
+ $query = qq|SELECT date '$thisdate' + $days AS thisdate
+ FROM defaults|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+ } else {
+ $query = qq|SELECT current_date AS thisdate
+ FROM defaults|;
+ $sth = $dbh->prepare($query);
+ $sth->execute || $self->dberror($query);
+ }
+
+ ($thisdate) = $sth->fetchrow_array;
+ $sth->finish;
+
+ $dbh->disconnect;
+
+ $thisdate;
+
+}
+
+
+sub like {
+ my ($self, $string) = @_;
+
+ unless ($string =~ /%/) {
+ $string = "%$string%";
+ }
+
+ $string;
+
+}
+
+
+sub redo_rows {
+ my ($self, $flds, $new, $count, $numrows) = @_;
+
+ my @ndx = ();
+
+ map { push @ndx, { num => $new->[$_-1]->{runningnumber}, ndx => $_ } } (1 .. $count);
+
+ my $i = 0;
+ # fill rows
+ foreach my $item (sort { $a->{num} <=> $b->{num} } @ndx) {
+ $i++;
+ $j = $item->{ndx} - 1;
+ map { $self->{"${_}_$i"} = $new->[$j]->{$_} } @{$flds};
+ }
+
+ # delete empty rows
+ for $i ($count + 1 .. $numrows) {
+ map { delete $self->{"${_}_$i"} } @{$flds};
+ }
+
+}
+
+
+package Locale;
+
+
+sub new {
+ my ($type, $country, $NLS_file) = @_;
+ my $self = {};
+
+ %self = ();
+ if ($country && -d "locale/$country") {
+ $self->{countrycode} = $country;
+ eval { require "locale/$country/$NLS_file"; };
+ }
+
+ $self->{NLS_file} = $NLS_file;
+
+ push @{ $self->{LONG_MONTH} }, ("January", "February", "March", "April", "May ", "June", "July", "August", "September", "October", "November", "December");
+ push @{ $self->{SHORT_MONTH} }, (qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec));
+
+ bless $self, $type;
+
+}
+
+
+sub text {
+ my ($self, $text) = @_;
+
+ return (exists $self{texts}{$text}) ? $self{texts}{$text} : $text;
+
+}
+
+
+sub findsub {
+ my ($self, $text) = @_;
+
+ if (exists $self{subs}{$text}) {
+ $text = $self{subs}{$text};
+ } else {
+ if ($self->{countrycode} && $self->{NLS_file}) {
+ Form->error("$text not defined in locale/$self->{countrycode}/$self->{NLS_file}");
+ }
+ }
+
+ $text;
+
+}
+
+
+sub date {
+ my ($self, $myconfig, $date, $longformat) = @_;
+
+ my $longdate = "";
+ my $longmonth = ($longformat) ? 'LONG_MONTH' : 'SHORT_MONTH';
+
+ if ($date) {
+ # get separator
+ $spc = $myconfig->{dateformat};
+ $spc =~ s/\w//g;
+ $spc = substr($spc, 1, 1);
+
+ if ($spc eq '.') {
+ $spc = '\.';
+ }
+ if ($spc eq '/') {
+ $spc = '\/';
+ }
+
+ if ($myconfig->{dateformat} =~ /^yy/) {
+ ($yy, $mm, $dd) = split /$spc/, $date;
+ }
+ if ($myconfig->{dateformat} =~ /^mm/) {
+ ($mm, $dd, $yy) = split /$spc/, $date;
+ }
+ if ($myconfig->{dateformat} =~ /^dd/) {
+ ($dd, $mm, $yy) = split /$spc/, $date;
+ }
+
+ $dd *= 1;
+ $mm--;
+ $yy = ($yy < 70) ? $yy + 2000 : $yy;
+ $yy = ($yy >= 70 && $yy <= 99) ? $yy + 1900 : $yy;
+
+ if ($myconfig->{dateformat} =~ /^dd/) {
+ $longdate = "$dd. ".&text($self, $self->{$longmonth}[$mm])." $yy";
+ } else {
+ $longdate = &text($self, $self->{$longmonth}[$mm])." $dd, $yy";
+ }
+
+ }
+
+ $longdate;
+
+}
+
+
+1;
+
/tags/release_2_0_6-2/SL/RC.pm
New file
0,0 → 1,186
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2002
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Account reconciliation routines
#
#======================================================================
 
package RC;
 
 
sub paymentaccounts {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT accno, description
FROM chart
WHERE link LIKE '%_paid%'
AND category = 'A'
ORDER BY accno|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{PR} }, $ref;
}
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub payment_transactions {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn AutoCommit off
my $dbh = $form->dbconnect_noauto($myconfig);
 
my ($query, $sth);
# get cleared balance
if ($form->{fromdate}) {
$query = qq|SELECT sum(a.amount)
FROM acc_trans a, chart c
WHERE a.transdate < date '$form->{fromdate}'
AND a.cleared = '1'
AND c.id = a.chart_id
AND c.accno = '$form->{accno}'
|;
} else {
$query = qq|SELECT sum(a.amount)
FROM acc_trans a, chart c
WHERE a.cleared = '1'
AND c.id = a.chart_id
AND c.accno = '$form->{accno}'
|;
}
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{beginningbalance}) = $sth->fetchrow_array;
 
$sth->finish;
 
my %oid = ( 'Pg' => 'ac.oid',
'Oracle' => 'ac.rowid');
 
$query = qq|SELECT c.name, ac.source, ac.transdate, ac.cleared,
ac.fx_transaction, ac.amount, a.id,
$oid{$myconfig->{dbdriver}} AS oid
FROM customer c, acc_trans ac, ar a, chart ch
WHERE c.id = a.customer_id
AND ac.cleared = '0'
AND ac.trans_id = a.id
AND ac.chart_id = ch.id
AND ch.accno = '$form->{accno}'
|;
$query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate};
$query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate};
 
 
$query .= qq|
UNION
SELECT v.name, ac.source, ac.transdate, ac.cleared,
ac.fx_transaction, ac.amount, a.id,
$oid{$myconfig->{dbdriver}} AS oid
FROM vendor v, acc_trans ac, ap a, chart ch
WHERE v.id = a.vendor_id
AND ac.cleared = '0'
AND ac.trans_id = a.id
AND ac.chart_id = ch.id
AND ch.accno = '$form->{accno}'
|;
$query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate};
$query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate};
 
$query .= qq|
UNION
SELECT g.description, ac.source, ac.transdate, ac.cleared,
ac.fx_transaction, ac.amount, g.id,
$oid{$myconfig->{dbdriver}} AS oid
FROM gl g, acc_trans ac, chart ch
WHERE g.id = ac.trans_id
AND ac.cleared = '0'
AND ac.trans_id = g.id
AND ac.chart_id = ch.id
AND ch.accno = '$form->{accno}'
|;
 
$query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate};
$query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate};
 
$query .= " ORDER BY 3,7,8";
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $pr = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{PR} }, $pr;
}
$sth->finish;
 
$dbh->disconnect;
}
 
 
sub reconcile {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my ($query, $i);
my %oid = ( 'Pg' => 'oid',
'Oracle' => 'rowid');
# clear flags
for $i (1 .. $form->{rowcount}) {
if ($form->{"cleared_$i"}) {
$query = qq|UPDATE acc_trans SET cleared = '1'
WHERE $oid{$myconfig->{dbdriver}} = $form->{"oid_$i"}|;
$dbh->do($query) || $form->dberror($query);
 
# clear fx_transaction
if ($form->{"fxoid_$i"}) {
$query = qq|UPDATE acc_trans SET cleared = '1'
WHERE $oid{$myconfig->{dbdriver}} = $form->{"fxoid_$i"}|;
$dbh->do($query) || $form->dberror($query);
}
}
}
 
$dbh->disconnect;
 
}
 
1;
 
/tags/release_2_0_6-2/SL/PE.pm
New file
0,0 → 1,147
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 1998-2002
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Project module
#
#======================================================================
 
package PE;
 
 
sub projects {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $sortorder = ($form->{sort}) ? $form->{sort} : "projectnumber";
 
my $query = qq|SELECT id, projectnumber, description
FROM project
WHERE 1 = 1|;
 
if ($form->{projectnumber}) {
my $projectnumber = $form->like(lc $form->{projectnumber});
$query .= " AND lower(projectnumber) LIKE '$projectnumber'";
}
if ($form->{projectdescription}) {
my $description = $form->like(lc $form->{projectdescription});
$query .= " AND lower(description) LIKE '$description'";
}
if ($form->{status} eq 'orphaned') {
$query .= " AND id NOT IN (SELECT p.id
FROM project p, acc_trans a
WHERE p.id = a.project_id)
AND id NOT IN (SELECT p.id
FROM project p, invoice i
WHERE p.id = i.project_id)
AND id NOT IN (SELECT p.id
FROM project p, orderitems o
WHERE p.id = o.project_id)";
}
 
$query .= qq|
ORDER BY $sortorder|;
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $i = 0;
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{project_list} }, $ref;
$i++;
}
 
$sth->finish;
$dbh->disconnect;
$i;
 
}
 
 
sub get_project {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $query = qq|SELECT projectnumber, description
FROM project
WHERE id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub save_project {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
map { $form->{$_} =~ s/'/''/g } (projectnumber, description);
 
if ($form->{id}) {
$query = qq|UPDATE project SET
projectnumber = '$form->{projectnumber}',
description = '$form->{description}'
WHERE id = $form->{id}|;
} else {
$query = qq|INSERT INTO project
(projectnumber, description)
VALUES ('$form->{projectnumber}', '$form->{description}')|;
}
$dbh->do($query) || $form->dberror($query);
$dbh->disconnect;
 
}
 
 
sub delete_project {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
$query = qq|DELETE FROM project
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
$dbh->disconnect;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/Menu.pm
New file
0,0 → 1,113
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=====================================================================
#
# routines for menu items
#
#=====================================================================
 
package Menu;
 
 
sub new {
my ($type, $menufile, $level) = @_;
 
use SL::Inifile;
my $self = Inifile->new($menufile, $level);
bless $self, $type;
 
}
 
 
sub menuitem {
my ($self, $myconfig, $form, $item) = @_;
 
my $module = $form->{script};
my $action = "section_menu";
my $target = "main_window";
 
if ($self->{$item}{module}) {
$module = $self->{$item}{module};
}
if ($self->{$item}{action}) {
$action = $self->{$item}{action};
}
if ($self->{$item}{target}) {
$target = $self->{$item}{target};
}
 
my $level = $form->escape($item);
my $str = qq|<a href=$module?path=$form->{path}&action=$action&level=$level&login=$form->{login}&password=$form->{password}|;
my @vars = qw(module action target href);
if ($self->{$item}{href}) {
$str = qq|<a href=$self->{$item}{href}|;
@vars = qw(module target href);
}
 
map { delete $self->{$item}{$_} } @vars;
# add other params
foreach my $key (keys %{ $self->{$item} }) {
$str .= "&".$form->escape($key,1)."=";
($value, $conf) = split /=/, $self->{$item}{$key}, 2;
$value = $myconfig->{$value}."/$conf" if ($conf);
$str .= $form->escape($value, 1);
}
 
$str .= qq| target=$target>|;
}
 
 
sub access_control {
my ($self, $myconfig, $menulevel) = @_;
my @menu = ();
 
if ($menulevel eq "") {
@menu = grep { !/--/ } @{ $self->{ORDER} };
} else {
@menu = grep { /^${menulevel}--/ } @{ $self->{ORDER} };
}
 
my @a = split /;/, $myconfig->{acs};
my $excl = ();
 
# remove --AR, --AP from array
grep { ($a, $b) = split /--/; s/--$a$//; } @a;
 
map { $excl{$_} = 1 } @a;
 
@a = ();
map { push @a, $_ unless $excl{$_} } (@menu);
 
@a;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/CT.pm
New file
0,0 → 1,447
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# backend code for customers and vendors
#
# CHANGE LOG:
# DS. 2000-07-04 Created
#
#======================================================================
 
package CT;
 
 
sub get_tuple {
my ($self, $myconfig, $form) = @_;
 
my $dbh = $form->dbconnect($myconfig);
my $query = qq|SELECT *
FROM $form->{db}
WHERE id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my $ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
 
$sth->finish;
 
 
# get ship to
$query = qq|SELECT *
FROM shipto
WHERE trans_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
 
map { $form->{$_} = $ref->{$_} } keys %$ref;
 
$sth->finish;
 
 
# get tax labels
$query = qq|SELECT accno, description
FROM chart, tax
WHERE link LIKE '%CT_tax%'
AND chart.id = tax.chart_id
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
$form->{taxaccounts} .= "$ref->{accno} ";
$form->{tax}{$ref->{accno}}{description} = $ref->{description};
}
$sth->finish;
chop $form->{taxaccounts};
 
# get taxes for customer/vendor
$query = qq|SELECT chart_id, accno
FROM $form->{db}tax, chart
WHERE chart_id = chart.id
AND $form->{db}_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
$form->{tax}{$ref->{accno}}{taxable} = 1;
}
$sth->finish;
 
$dbh->disconnect;
 
}
 
 
sub taxaccounts {
my ($self, $myconfig, $form) = @_;
 
my $dbh = $form->dbconnect($myconfig);
 
# get tax labels
my $query = qq|SELECT accno, description
FROM chart, tax
WHERE link LIKE '%CT_tax%'
AND chart.id = tax.chart_id
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $taxref = $sth->fetchrow_hashref(NAME_lc)) {
$form->{taxaccounts} .= "$taxref->{accno} ";
$form->{tax}{$taxref->{accno}}{description} = $taxref->{description};
}
$sth->finish;
chop $form->{taxaccounts};
 
$dbh->disconnect;
 
}
 
 
sub delete_customer {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn AutoCommit off
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $query = qq|SELECT id FROM ar
WHERE customer_id = $form->{id}
UNION
SELECT id FROM oe
WHERE customer_id = $form->{id}|;
my $sth = $dbh->prepare($query) || $form->dberror($query);
$sth->execute;
 
my ($rc) = $sth->fetchrow_array;
$sth->finish;
 
if ($rc) {
$dbh->disconnect;
$rc = -1;
} else {
# delete customer
$query = qq|DELETE FROM customer
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
$query = qq|DELETE FROM customertax
WHERE customer_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# commit and redirect
$rc = $dbh->commit;
$dbh->disconnect;
}
 
$rc;
}
 
 
sub save_customer {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
# escape '
map { $form->{$_} =~ s/'/''/g } qw(customernumber name addr1 addr2 addr3 addr4 contact notes);
 
# assign value discount, terms, creditlimit
$form->{discount} /= 100;
$form->{terms} *= 1;
$form->{taxincluded} *= 1;
$form->{creditlimit} = $form->parse_amount($myconfig, $form->{creditlimit});
my ($query, $sth);
 
if ($form->{id}) {
$query = qq|DELETE FROM customertax
WHERE customer_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
} else {
my $uid = time;
$uid .= $form->{login};
 
$query = qq|INSERT INTO customer (name)
VALUES ('$uid')|;
$dbh->do($query) || $form->dberror($query);
$query = qq|SELECT id FROM customer
WHERE name = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
 
}
$query = qq|UPDATE customer SET
customernumber = '$form->{customernumber}',
name = '$form->{name}',
addr1 = '$form->{addr1}',
addr2 = '$form->{addr2}',
addr3 = '$form->{addr3}',
addr4 = '$form->{addr4}',
contact = '$form->{contact}',
phone = '$form->{phone}',
fax = '$form->{fax}',
email = '$form->{email}',
cc = '$form->{cc}',
bcc = '$form->{bcc}',
notes = '$form->{notes}',
discount = $form->{discount},
creditlimit = $form->{creditlimit},
terms = $form->{terms},
taxincluded = '$form->{taxincluded}'
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# save taxes
foreach $item (split / /, $form->{taxaccounts}) {
if ($form->{"tax_$item"}) {
$query = qq|INSERT INTO customertax (customer_id, chart_id)
VALUES ($form->{id}, (SELECT id
FROM chart
WHERE accno = '$item'))|;
$dbh->do($query) || $form->dberror($query);
}
}
# add shipto
$form->add_shipto($dbh, $form->{id});
 
$dbh->disconnect;
 
}
 
 
sub save_vendor {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
# escape '
map { $form->{$_} =~ s/'/''/g } qw(vendornumber name addr1 addr2 addr3 addr4 contact notes);
 
$form->{terms} *= 1;
$form->{taxincluded} *= 1;
my $query;
if ($form->{id}) {
$query = qq|DELETE FROM vendortax
WHERE vendor_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
} else {
my $uid = time;
$uid .= $form->{login};
$query = qq|INSERT INTO vendor (name)
VALUES ('$uid')|;
$dbh->do($query) || $form->dberror($query);
$query = qq|SELECT id FROM vendor
WHERE name = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
 
}
 
$query = qq|UPDATE vendor SET
vendornumber = '$form->{vendornumber}',
name = '$form->{name}',
addr1 = '$form->{addr1}',
addr2 = '$form->{addr2}',
addr3 = '$form->{addr3}',
addr4 = '$form->{addr4}',
contact = '$form->{contact}',
phone = '$form->{phone}',
fax = '$form->{fax}',
email = '$form->{email}',
cc = '$form->{cc}',
bcc = '$form->{bcc}',
notes = '$form->{notes}',
terms = $form->{terms},
taxincluded = '$form->{taxincluded}'
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# save taxes
foreach $item (split / /, $form->{taxaccounts}) {
if ($form->{"tax_$item"}) {
$query = qq|INSERT INTO vendortax (vendor_id, chart_id)
VALUES ($form->{id}, (SELECT id
FROM chart
WHERE accno = '$item'))|;
$dbh->do($query) || $form->dberror($query);
}
}
 
# add shipto
$form->add_shipto($dbh, $form->{id});
 
$dbh->disconnect;
 
}
 
 
 
sub delete_vendor {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn AutoCommit off
my $dbh = $form->dbconnect_noauto($myconfig);
 
# check if there are any transactions on file
my $query = qq|SELECT id FROM ap
WHERE vendor_id = $form->{id}
UNION
SELECT id FROM oe
WHERE vendor_id = $form->{id}|;
my $sth = $dbh->prepare($query) || $form->dberror($query);
$sth->execute;
my ($rc) = $sth->fetchrow_array;
$sth->finish;
if ($rc) {
$dbh->disconnect;
$rc = -1;
} else {
# delete vendor
$query = qq|DELETE FROM vendor
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM vendortax
WHERE vendor_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# commit and redirect
$rc = $dbh->commit;
$dbh->disconnect;
 
}
 
$rc;
 
}
 
 
sub search {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $where = "1 = 1";
$form->{sort} = "name" unless ($form->{sort});
if ($form->{"$form->{db}number"}) {
my $companynumber = $form->like(lc $form->{"$form->{db}number"});
$where .= " AND lower($form->{db}number) LIKE '$companynumber'";
}
if ($form->{name}) {
my $name = $form->like(lc $form->{name});
$where .= " AND lower(name) LIKE '$name'";
}
if ($form->{contact}) {
my $contact = $form->like(lc $form->{contact});
$where .= " AND lower(contact) LIKE '$contact'";
}
if ($form->{email}) {
my $email = $form->like(lc $form->{email});
$where .= " AND lower(email) LIKE '$email'";
}
 
if ($form->{status} eq 'orphaned') {
$where .= qq| AND id NOT IN (SELECT o.$form->{db}_id
FROM oe o, $form->{db} ct
WHERE ct.id = o.$form->{db}_id)|;
if ($form->{db} eq 'customer') {
$where .= qq| AND id NOT IN (SELECT a.customer_id
FROM ar a, customer ct
WHERE ct.id = a.customer_id)|;
}
if ($form->{db} eq 'vendor') {
$where .= qq| AND id NOT IN (SELECT a.vendor_id
FROM ap a, vendor ct
WHERE ct.id = a.vendor_id)|;
}
}
my $query = qq~SELECT id, name, $form->{db}number,
addr1 || ' ' || addr2 || ' ' || addr3 || ' ' || addr4 AS address,
contact, phone, fax, email, cc, terms
FROM $form->{db}
WHERE $where
ORDER BY $form->{sort}~;
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{CT} }, $ref;
}
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
1;
 
/tags/release_2_0_6-2/SL/Mailer.pm
New file
0,0 → 1,147
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
 
package Mailer;
 
sub new {
my ($type) = @_;
my $self = {};
 
bless $self, $type;
}
 
 
sub send {
my ($self, $out) = @_;
 
my $boundary = time;
$boundary = "SL-$self->{version}-$boundary";
my $domain = $self->{from};
$domain =~ s/(.*?\@|>)//g;
my $msgid = "$boundary\@$domain";
$self->{charset} = "ISO-8859-1" unless $self->{charset};
if ($out) {
open(OUT, $out) or return "$out : $!";
} else {
open(OUT, ">-") or return "STDOUT : $!";
}
 
$self->{contenttype} = "text/plain" unless $self->{contenttype};
my ($cc, $bcc);
$cc = "Cc: $self->{cc}\n" if $self->{cc};
$bcc = "Bcc: $self->{bcc}\n" if $self->{bcc};
print OUT qq|From: $self->{from}
To: $self->{to}
${cc}${bcc}Subject: $self->{subject}
Message-ID: <$msgid>
X-Mailer: SQL-Ledger $self->{version}
MIME-Version: 1.0
|;
 
 
if ($self->{attachments}) {
print OUT qq|Content-Type: multipart/mixed; boundary="$boundary"
 
--${boundary}
Content-Type: $self->{contenttype}; charset="$self->{charset}"
 
$self->{message}
 
|;
 
foreach my $attachment (@{ $self->{attachments} }) {
my $application = ($attachment =~ /(^\w+$)|\.(html|text|txt|sql)$/) ? "text" : "application";
open(IN, $attachment);
if ($?) {
close(OUT);
return "$attachment : $!";
}
my $filename = $attachment;
# strip path
$filename =~ s/(.*\/|$self->{fileid})//g;
print OUT qq|--${boundary}
Content-Type: $application/$self->{format}; name="$filename"; charset="$self->{charset}"
Content-Transfer-Encoding: BASE64
Content-Disposition: attachment; filename="$filename"\n\n|;
 
my $msg = "";
while (<IN>) {;
$msg .= $_;
}
print OUT &encode_base64($msg);
 
close(IN);
}
print OUT qq|--${boundary}--\n|;
 
} else {
print OUT qq|Content-Type: $self->{contenttype}; charset="$self->{charset}"
 
$self->{message}
|;
}
 
close(OUT);
 
return "";
}
 
 
sub encode_base64 ($;$) {
 
# this code is from the MIME-Base64-2.12 package
# Copyright 1995-1999,2001 Gisle Aas <gisle@ActiveState.com>
 
my $res = "";
my $eol = $_[1];
$eol = "\n" unless defined $eol;
pos($_[0]) = 0; # ensure start at the beginning
 
$res = join '', map( pack('u',$_)=~ /^.(\S*)/, ($_[0]=~/(.{1,45})/gs));
 
$res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs
# fix padding at the end
my $padding = (3 - length($_[0]) % 3) % 3;
$res =~ s/.{$padding}$/'=' x $padding/e if $padding;
# break encoded string into lines of no more than 60 characters each
if (length $eol) {
$res =~ s/(.{1,60})/$1$eol/g;
}
return $res;
}
 
 
1;
 
/tags/release_2_0_6-2/SL/IR.pm
New file
0,0 → 1,958
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Inventory received module
#
#======================================================================
 
package IR;
 
 
sub post_invoice {
my ($self, $myconfig, $form) = @_;
# connect to database, turn off autocommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
my ($query, $sth, $null, $project_id);
my $exchangerate = 0;
 
if ($form->{id}) {
 
&reverse_invoice($dbh, $form);
 
} else {
my $uid = time;
$uid .= $form->{login};
 
$query = qq|INSERT INTO ap (invnumber, employee_id)
VALUES ('$uid', (SELECT id FROM employee
WHERE login = '$form->{login}'))|;
$dbh->do($query) || $form->dberror($query);
$query = qq|SELECT id FROM ap
WHERE invnumber = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
}
 
map { $form->{$_} =~ s/'/''/g } qw(invnumber ordnumber);
my ($amount, $linetotal, $lastinventoryaccno, $lastexpenseaccno);
my ($netamount, $invoicediff, $expensediff) = (0, 0, 0);
 
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{exchangerate} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, 'sell');
}
$form->{exchangerate} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{exchangerate});
 
for my $i (1 .. $form->{rowcount}) {
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
if ($form->{"qty_$i"} != 0) {
map { $form->{"${_}_$i"} =~ s/'/''/g } qw(partnumber description unit);
my ($allocated, $taxrate) = (0, 0);
my $taxamount;
$form->{"sellprice_$i"} = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
my $fxsellprice = $form->{"sellprice_$i"};
 
my ($dec) = ($fxsellprice =~ /\.(\d+)/);
$dec = length $dec;
my $decimalplaces = ($dec > 2) ? $dec : 2;
map { $taxrate += $form->{"${_}_rate"} } split / /, $form->{"taxaccounts_$i"};
 
if ($form->{"inventory_accno_$i"}) {
 
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2);
if ($form->{taxincluded}) {
$taxamount = $linetotal * ($taxrate / (1 + $taxrate));
$form->{"sellprice_$i"} = $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
} else {
$taxamount = $linetotal * $taxrate;
}
 
$netamount += $linetotal;
if ($taxamount != 0) {
map { $form->{amount}{$form->{id}}{$_} -= $taxamount * $form->{"${_}_rate"} / $taxrate } split / /, $form->{"taxaccounts_$i"};
}
 
# add purchase to inventory, this one is without the tax!
$amount = $form->{"sellprice_$i"} * $form->{"qty_$i"} * $form->{exchangerate};
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2) * $form->{exchangerate};
$linetotal = $form->round_amount($linetotal, 2);
 
# this is the difference for the inventory
$invoicediff += ($amount - $linetotal);
$form->{amount}{$form->{id}}{$form->{"inventory_accno_$i"}} -= $linetotal;
 
# adjust and round sellprice
$form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate}, $decimalplaces);
 
# update parts table
$query = qq|UPDATE parts SET
lastcost = $form->{"sellprice_$i"},
onhand = onhand + $form->{"qty_$i"}
WHERE id = $form->{"id_$i"}|;
$dbh->do($query) || $form->dberror($query);
 
 
# check if we sold the item already and
# make an entry for the expense and inventory
$query = qq|SELECT i.id, i.qty, i.allocated, i.trans_id,
p.inventory_accno_id, p.expense_accno_id, a.transdate
FROM invoice i, ar a, parts p
WHERE i.parts_id = p.id
AND i.parts_id = $form->{"id_$i"}
AND (i.qty + i.allocated) > 0
AND i.trans_id = a.id
ORDER BY transdate|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
 
my $totalqty = $form->{"qty_$i"};
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
my $qty = $ref->{qty} + $ref->{allocated};
if (($qty - $totalqty) > 0) {
$qty = $totalqty;
}
 
 
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $qty, 2);
if ($ref->{allocated} < 0) {
# we have an entry for it already, adjust amount
$form->update_balance($dbh,
"acc_trans",
"amount",
qq|trans_id = $ref->{trans_id} AND chart_id = $ref->{inventory_accno_id} AND transdate = '$ref->{transdate}'|,
$linetotal);
 
$form->update_balance($dbh,
"acc_trans",
"amount",
qq|trans_id = $ref->{trans_id} AND chart_id = $ref->{expense_accno_id} AND transdate = '$ref->{transdate}'|,
$linetotal * -1);
 
} else {
# add entry for inventory, this one is for the sold item
if ($linetotal != 0) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($ref->{trans_id}, $ref->{inventory_accno_id},
$linetotal, '$ref->{transdate}')|;
$dbh->do($query) || $form->dberror($query);
 
# add expense
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($ref->{trans_id}, $ref->{expense_accno_id},
|. ($linetotal * -1) .qq|, '$ref->{transdate}')|;
$dbh->do($query) || $form->dberror($query);
}
}
# update allocated for sold item
$form->update_balance($dbh,
"invoice",
"allocated",
qq|id = $ref->{id}|,
$qty * -1);
$allocated += $qty;
 
last if (($totalqty -= $qty) <= 0);
}
 
$sth->finish;
 
$lastinventoryaccno = $form->{"inventory_accno_$i"};
} else {
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2);
if ($form->{taxincluded}) {
$taxamount = $linetotal * ($taxrate / (1 + $taxrate));
$form->{"sellprice_$i"} = $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
} else {
$taxamount = $linetotal * $taxrate;
}
$netamount += $linetotal;
if ($taxamount != 0) {
map { $form->{amount}{$form->{id}}{$_} -= $taxamount * $form->{"${_}_rate"} / $taxrate } split / /, $form->{"taxaccounts_$i"};
}
 
$amount = $form->{"sellprice_$i"} * $form->{"qty_$i"} * $form->{exchangerate};
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2) * $form->{exchangerate};
$linetotal = $form->round_amount($linetotal, 2);
 
# this is the difference for expense
$expensediff += ($amount - $linetotal);
# add amount to expense
$form->{amount}{$form->{id}}{$form->{"expense_accno_$i"}} -= $linetotal;
 
$lastexpenseaccno = $form->{"expense_accno_$i"};
 
# adjust and round sellprice
$form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate}, $decimalplaces);
# update lastcost
$query = qq|UPDATE parts SET
lastcost = $form->{"sellprice_$i"}
WHERE id = $form->{"id_$i"}|;
$dbh->do($query) || $form->dberror($query);
 
}
 
$project_id = 'NULL';
if ($form->{"project_id_$i"}) {
$project_id = $form->{"project_id_$i"};
}
$deliverydate = ($form->{"deliverydate_$i"}) ? qq|'$form->{"deliverydate_$i"}'| : "NULL";
# save detail record in invoice table
$query = qq|INSERT INTO invoice (trans_id, parts_id, description, qty,
sellprice, fxsellprice, allocated, unit, deliverydate)
VALUES ($form->{id}, $form->{"id_$i"},
'$form->{"description_$i"}', |. ($form->{"qty_$i"} * -1) .qq|,
$form->{"sellprice_$i"}, $fxsellprice, $allocated,
'$form->{"unit_$i"}', $deliverydate)|;
$dbh->do($query) || $form->dberror($query);
 
}
}
 
 
$form->{datepaid} = $form->{invdate};
 
# all amounts are in natural state, netamount includes the taxes
# if tax is included, netamount is rounded to 2 decimal places,
# taxes are not
# total payments
for my $i (1 .. $form->{paidaccounts}) {
$form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"});
$form->{paid} += $form->{"paid_$i"};
$form->{datepaid} = $form->{"datepaid_$i"} if ($form->{"datepaid_$i"});
}
 
my ($tax, $paiddiff) = (0, 0);
 
$netamount = $form->round_amount($netamount, 2);
# figure out rounding errors for amount paid and total amount
if ($form->{taxincluded}) {
 
$amount = $form->round_amount($netamount * $form->{exchangerate}, 2);
$paiddiff = $amount - $netamount * $form->{exchangerate};
$netamount = $amount;
 
foreach my $item (split / /, $form->{taxaccounts}) {
$amount = $form->{amount}{$form->{id}}{$item} * $form->{exchangerate};
$form->{amount}{$form->{id}}{$item} = $form->round_amount($amount, 2);
$amount = $form->{amount}{$form->{id}}{$item} * -1;
$tax += $amount;
$netamount -= $amount;
}
 
$invoicediff += $paiddiff;
$expensediff += $paiddiff;
######## this only applies to tax included
if ($lastinventoryaccno) {
$form->{amount}{$form->{id}}{$lastinventoryaccno} -= $invoicediff;
}
if ($lastexpenseaccno) {
$form->{amount}{$form->{id}}{$lastexpenseaccno} -= $expensediff;
}
 
} else {
$amount = $form->round_amount($netamount * $form->{exchangerate}, 2);
$paiddiff = $amount - $netamount * $form->{exchangerate};
$netamount = $amount;
foreach my $item (split / /, $form->{taxaccounts}) {
$form->{amount}{$form->{id}}{$item} = $form->round_amount($form->{amount}{$form->{id}}{$item}, 2);
$amount = $form->round_amount($form->{amount}{$form->{id}}{$item} * $form->{exchangerate} * -1, 2);
$paiddiff += $amount - $form->{amount}{$form->{id}}{$item} * $form->{exchangerate} * -1;
$form->{amount}{$form->{id}}{$item} = $form->round_amount($amount * -1, 2);
$amount = $form->{amount}{$form->{id}}{$item} * -1;
$tax += $amount;
}
}
 
 
$form->{amount}{$form->{id}}{$form->{AP}} = $netamount + $tax;
 
if ($form->{paid} != 0) {
$form->{paid} = $form->round_amount($form->{paid} * $form->{exchangerate} + $paiddiff, 2);
}
 
 
# update exchangerate
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{invdate}, 0, $form->{exchangerate});
}
# record acc_trans transactions
foreach my $trans_id (keys %{$form->{amount}}) {
foreach my $accno (keys %{ $form->{amount}{$trans_id} }) {
if (($form->{amount}{$trans_id}{$accno} = $form->round_amount($form->{amount}{$trans_id}{$accno}, 2)) != 0) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($trans_id, (SELECT id FROM chart
WHERE accno = '$accno'),
$form->{amount}{$trans_id}{$accno}, '$form->{invdate}')|;
$dbh->do($query) || $form->dberror($query);
}
}
}
 
# deduct payment differences from paiddiff
for my $i (1 .. $form->{paidaccounts}) {
if ($form->{"paid_$i"} != 0) {
$amount = $form->round_amount($form->{"paid_$i"} * $form->{exchangerate}, 2);
$paiddiff -= $amount - $form->{"paid_$i"} * $form->{exchangerate};
}
}
 
# force AP entry if 0
$form->{amount}{$form->{id}}{$form->{AP}} = $form->{paid} if ($form->{amount}{$form->{id}}{$form->{AP}} == 0);
# record payments and offsetting AP
for my $i (1 .. $form->{paidaccounts}) {
 
if ($form->{"paid_$i"} != 0) {
my ($accno) = split /--/, $form->{"AP_paid_$i"};
$form->{"datepaid_$i"} = $form->{invdate} unless ($form->{"datepaid_$i"});
$form->{datepaid} = $form->{"datepaid_$i"};
$amount = ($form->round_amount($form->{"paid_$i"} * $form->{exchangerate} + $paiddiff, 2)) * -1;
# record AP
if ($form->{amount}{$form->{id}}{$form->{AP}} != 0) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$form->{AP}'),
$amount, '$form->{"datepaid_$i"}')|;
$dbh->do($query) || $form->dberror($query);
}
 
# record payment
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
source)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$accno'),
$form->{"paid_$i"}, '$form->{"datepaid_$i"}',
'$form->{"source_$i"}')|;
$dbh->do($query) || $form->dberror($query);
 
 
$exchangerate = 0;
 
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{"exchangerate_$i"} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'sell');
 
$form->{"exchangerate_$i"} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{"exchangerate_$i"});
}
 
# exchangerate difference
$form->{fx}{$accno}{$form->{"datepaid_$i"}} += $form->{"paid_$i"} * ($form->{"exchangerate_$i"} - 1) + $paiddiff;
 
# gain/loss
$amount = ($form->{"paid_$i"} * $form->{exchangerate}) - ($form->{"paid_$i"} * $form->{"exchangerate_$i"});
if ($amount > 0) {
$form->{fx}{$form->{fxgain_accno}}{$form->{"datepaid_$i"}} += $amount;
} else {
$form->{fx}{$form->{fxloss_accno}}{$form->{"datepaid_$i"}} += $amount;
}
$paiddiff = 0;
 
# update exchange rate
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{"datepaid_$i"}, 0, $form->{"exchangerate_$i"});
}
}
}
 
# record exchange rate differences and gains/losses
foreach my $accno (keys %{$form->{fx}}) {
foreach my $transdate (keys %{ $form->{fx}{$accno} }) {
if (($form->{fx}{$accno}{$transdate} = $form->round_amount($form->{fx}{$accno}{$transdate}, 2)) != 0) {
 
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, cleared, fx_transaction)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$accno'),
$form->{fx}{$accno}{$transdate}, '$transdate', '0', '1')|;
$dbh->do($query) || $form->dberror($query);
}
}
}
 
 
$amount = $netamount + $tax;
 
# set values which could be empty
$form->{taxincluded} *= 1;
my $datepaid = ($form->{paid}) ? qq|'$form->{datepaid}'| : "NULL";
my $duedate = ($form->{duedate}) ? qq|'$form->{duedate}'| : "NULL";
# save AP record
$query = qq|UPDATE ap set
invnumber = '$form->{invnumber}',
ordnumber = '$form->{ordnumber}',
transdate = '$form->{invdate}',
vendor_id = $form->{vendor_id},
amount = $amount,
netamount = $netamount,
paid = $form->{paid},
datepaid = $datepaid,
duedate = $duedate,
invoice = '1',
taxincluded = '$form->{taxincluded}',
notes = '$form->{notes}',
curr = '$form->{currency}'
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# add shipto
$form->{name} = $form->{vendor};
$form->{name} =~ s/--$form->{vendor_id}//;
$form->add_shipto($dbh, $form->{id});
# delete zero entries
$query = qq|DELETE FROM acc_trans
WHERE amount = 0|;
$dbh->do($query) || $form->dberror($query);
my $rc = $dbh->commit;
$dbh->disconnect;
$rc;
}
 
 
 
sub reverse_invoice {
my ($dbh, $form) = @_;
# reverse inventory items
my $query = qq|SELECT i.parts_id, p.inventory_accno_id, p.expense_accno_id,
i.qty, i.allocated, i.sellprice
FROM invoice i, parts p
WHERE i.parts_id = p.id
AND i.trans_id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $netamount = 0;
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
$netamount += $form->round_amount($ref->{sellprice} * $ref->{qty} * -1, 2);
 
if ($ref->{inventory_accno_id}) {
# update onhand
$form->update_balance($dbh,
"parts",
"onhand",
qq|id = $ref->{parts_id}|,
$ref->{qty});
# if $ref->{allocated} > 0 than we sold that many items
if ($ref->{allocated} > 0) {
 
# get references for sold items
$query = qq|SELECT i.id, i.trans_id, i.allocated, a.transdate
FROM invoice i, ar a
WHERE i.parts_id = $ref->{parts_id}
AND i.allocated < 0
AND i.trans_id = a.id
ORDER BY transdate DESC|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $pthref = $sth->fetchrow_hashref(NAME_lc)) {
my $qty = $ref->{allocated};
if (($ref->{allocated} + $pthref->{allocated}) > 0) {
$qty = $pthref->{allocated} * -1;
}
 
my $amount = $form->round_amount($ref->{sellprice} * $qty, 2);
#adjust allocated
$form->update_balance($dbh,
"invoice",
"allocated",
qq|id = $pthref->{id}|,
$qty);
$form->update_balance($dbh,
"acc_trans",
"amount",
qq|trans_id = $pthref->{trans_id} AND chart_id = $ref->{expense_accno_id} AND transdate = '$pthref->{transdate}'|,
$amount);
$form->update_balance($dbh,
"acc_trans",
"amount",
qq|trans_id = $pthref->{trans_id} AND chart_id = $ref->{inventory_accno_id} AND transdate = '$pthref->{transdate}'|,
$amount * -1);
 
last if (($ref->{allocated} -= $qty) <= 0);
}
$sth->finish;
}
}
}
$sth->finish;
# delete acc_trans
$query = qq|DELETE FROM acc_trans
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
# delete invoice entries
$query = qq|DELETE FROM invoice
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
}
 
 
 
sub delete_invoice {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
# check for other foreign currency transactions
$form->delete_exchangerate($dbh) if ($form->{currency} ne $form->{defaultcurrency});
 
&reverse_invoice($dbh, $form);
# delete zero entries
my $query = qq|DELETE FROM acc_trans
WHERE amount = 0|;
$dbh->do($query) || $form->dberror($query);
 
# delete AP record
my $query = qq|DELETE FROM ap
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
 
sub retrieve_invoice {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $query;
 
if ($form->{id}) {
# get default accounts and last invoice number
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE d.inventory_accno_id = c.id) AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE d.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c
WHERE d.expense_accno_id = c.id) AS expense_accno,
(SELECT c.accno FROM chart c
WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
(SELECT c.accno FROM chart c
WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
d.curr AS currencies
FROM defaults d|;
} else {
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE d.inventory_accno_id = c.id) AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE d.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c
WHERE d.expense_accno_id = c.id) AS expense_accno,
(SELECT c.accno FROM chart c
WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
(SELECT c.accno FROM chart c
WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
d.ponumber AS invnumber, d.curr AS currencies,
current_date AS invdate
FROM defaults d|;
}
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
 
 
if ($form->{id}) {
# retrieve invoice
$query = qq|SELECT a.invnumber, a.transdate AS invdate, a.duedate,
a.ordnumber, a.paid, a.taxincluded, a.notes, a.curr AS currency
FROM ap a
WHERE id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
 
$form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{invdate}, "sell");
# get shipto
$query = qq|SELECT * FROM shipto
WHERE trans_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
# retrieve individual items
$query = qq|SELECT (SELECT accno FROM chart c
WHERE p.inventory_accno_id = c.id) AS inventory_accno,
(SELECT accno FROM chart c
WHERE p.income_accno_id = c.id) AS income_accno,
(SELECT accno FROM chart c
WHERE p.expense_accno_id = c.id) AS expense_accno,
p.partnumber, i.description, i.qty, i.fxsellprice AS sellprice,
i.parts_id AS id, i.unit, p.bin, i.deliverydate,
(SELECT projectnumber FROM project pr
WHERE i.project_id = pr.id) AS projectnumber,
i.project_id
FROM invoice i, parts p
WHERE i.parts_id = p.id
AND trans_id = $form->{id}
ORDER BY i.id|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
 
# get tax rates for part
$query = qq|SELECT c.accno
FROM chart c, tax t, partstax pt
WHERE t.chart_id = pt.chart_id
AND pt.chart_id = c.id
AND pt.parts_id = $ref->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref->{taxaccounts} = "";
my $taxrate = 0;
while (my $ptref = $sth->fetchrow_hashref(NAME_lc)) {
$ref->{taxaccounts} .= "$ptref->{accno} ";
$taxrate += $form->{"$ptref->{accno}_rate"};
}
$sth->finish;
chop $ref->{taxaccounts};
 
$ref->{qty} *= -1;
push @{ $form->{invoice_details} }, $ref;
}
$sth->finish;
} else {
 
# up invoice number by 1
$form->{invnumber}++;
 
# save the new number
$query = qq|UPDATE defaults
SET ponumber = '$form->{invnumber}'|;
$dbh->do($query) || $form->dberror($query);
 
}
my $rc = $dbh->commit;
$dbh->disconnect;
$rc;
}
 
 
 
sub get_vendor {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $duedate = ($form->{invdate}) ? "date '$form->{invdate}'" : "current_date";
 
$form->{vendor_id} *= 1;
# get vendor
my $query = qq|SELECT taxincluded, terms, email, cc, bcc,
addr1, addr2, addr3, addr4,
$duedate + terms AS duedate
FROM vendor
WHERE id = $form->{vendor_id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
# get shipto if we do not convert an order or invoice
if (!$form->{shipto}) {
map { delete $form->{$_} } qw(shiptoname shiptoaddr1 shiptoaddr2 shiptoaddr3 shiptoaddr4 shiptocontact shiptophone shiptofax shiptoemail);
 
$query = qq|SELECT * FROM shipto
WHERE trans_id = $form->{vendor_id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
}
# get taxes for vendor
$query = qq|SELECT c.accno
FROM chart c, vendortax v
WHERE v.chart_id = c.id
AND v.vendor_id = $form->{vendor_id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $vendortax = ();
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
$vendortax{$ref->{accno}} = 1;
}
$sth->finish;
 
 
# get tax rates and description
$query = qq|SELECT c.accno, c.description, c.link, t.rate
FROM chart c, tax t
WHERE c.id = t.chart_id
AND c.link LIKE '%CT_tax%'
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$form->{taxaccounts} = "";
$form->{taxpart} = "";
$form->{taxservice} = "";
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
if ($vendortax{$ref->{accno}}) {
$form->{"$ref->{accno}_rate"} = $ref->{rate};
$form->{"$ref->{accno}_description"} = $ref->{description};
$form->{taxaccounts} .= "$ref->{accno} ";
}
foreach my $item (split /:/, $ref->{link}) {
if ($item =~ /IC_taxpart/) {
$form->{taxpart} .= "$ref->{accno} ";
}
if ($item =~ /IC_taxservice/) {
$form->{taxservice} .= "$ref->{accno} ";
}
}
}
$sth->finish;
chop $form->{taxaccounts};
chop $form->{taxpart};
chop $form->{taxservice};
 
$dbh->disconnect;
}
 
 
sub retrieve_item {
my ($self, $myconfig, $form) = @_;
 
my $i = $form->{rowcount};
# don't include assemblies or obsolete parts
my $where = "NOT assembly = '1' AND NOT obsolete = '1'";
if ($form->{"partnumber_$i"}) {
my $partnumber = $form->like(lc $form->{"partnumber_$i"});
$where .= " AND lower(partnumber) LIKE '$partnumber'";
}
if ($form->{"description_$i"}) {
my $description = $form->like(lc $form->{"description_$i"});
$where .= " AND lower(description) LIKE '$description'";
}
 
if ($form->{"description_$i"}) {
$where .= " ORDER BY description";
} else {
$where .= " ORDER BY partnumber";
}
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT p.id, p.partnumber, p.description,
(SELECT c.accno FROM chart c
WHERE p.inventory_accno_id = c.id) AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE p.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c
WHERE p.expense_accno_id = c.id) AS expense_accno,
p.lastcost AS sellprice, p.unit, p.bin, p.onhand
FROM parts p
WHERE $where|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
# get tax rates for part
$query = qq|SELECT c.accno
FROM chart c, tax t, partstax pt
WHERE t.chart_id = pt.chart_id
AND pt.chart_id = c.id
AND pt.parts_id = $ref->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref->{taxaccounts} = "";
while (my $ptref = $sth->fetchrow_hashref(NAME_lc)) {
$ref->{taxaccounts} .= "$ptref->{accno} ";
}
$sth->finish;
chop $ref->{taxaccounts};
push @{ $form->{item_list} }, $ref;
}
$sth->finish;
$dbh->disconnect;
}
 
 
 
sub vendor_details {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
# get rest for the vendor
my $query = qq|SELECT vendornumber, name, addr1, addr2, addr3, addr4,
contact, phone as vendorphone, fax as vendorfax, vendornumber
FROM vendor
WHERE id = $form->{vendor_id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub item_links {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT accno, description, link
FROM chart
WHERE link LIKE '%IC%'
ORDER BY accno|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
foreach my $key (split(/:/, $ref->{link})) {
if ($key =~ /IC/) {
push @{ $form->{IC_links}{$key} }, { accno => $ref->{accno},
description => $ref->{description} };
}
}
}
 
$sth->finish;
}
 
1;
 
/tags/release_2_0_6-2/SL/IS.pm
New file
0,0 → 1,1176
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 1998-2002
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# Inventory invoicing module
#
#======================================================================
 
package IS;
 
 
sub invoice_details {
my ($self, $myconfig, $form) = @_;
 
$form->{duedate} = $form->{invdate} unless ($form->{duedate});
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT date '$form->{duedate}' - date '$form->{invdate}'
AS terms
FROM defaults|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{terms}) = $sth->fetchrow_array;
$sth->finish;
 
my $tax = 0;
my $item;
my $i;
my @projects = ();
# sort items by projectnumber
for $i (1 .. $form->{rowcount}) {
# get project description
$form->{"projectdescription_$i"} = "";
if ($form->{"project_id_$i"}) {
$form->{"projectdescription_$i"} = &project_description("", $dbh, $form->{"project_id_$i"});
$form->format_string("projectnumber_$i", "projectdescription_$i");
}
push @projects, [ $i, $form->{"projectnumber_$i"}, $form->{"projectdescription_$i"} ];
}
my $sameitem = "";
foreach $item (sort { $a->[1] cmp $b->[1] } @projects) {
$i = $item->[0];
 
if ($item->[2] ne $sameitem) {
push(@{ $form->{description} }, qq|$item->[2]|);
$sameitem = $item->[2];
 
map { push(@{ $form->{$_} }, "") } qw(runningnumber number bin qty unit deliverydate sellprice listprice netprice discount linetotal);
}
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
if ($form->{"qty_$i"} != 0) {
 
# add number, description and qty to $form->{number}, ....
push(@{ $form->{runningnumber} }, $i);
push(@{ $form->{number} }, qq|$form->{"partnumber_$i"}|);
push(@{ $form->{bin} }, qq|$form->{"bin_$i"}|);
push(@{ $form->{description} }, qq|$form->{"description_$i"}|);
push(@{ $form->{qty} }, $form->format_amount($myconfig, $form->{"qty_$i"}));
push(@{ $form->{unit} }, qq|$form->{"unit_$i"}|);
push(@{ $form->{deliverydate} }, qq|$form->{"deliverydate_$i"}|);
push(@{ $form->{sellprice} }, $form->{"sellprice_$i"});
# listprice
push(@{ $form->{listprice} }, $form->{"listprice_$i"});
 
my $sellprice = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
my ($dec) = ($sellprice =~ /\.(\d+)/);
$dec = length $dec;
my $decimalplaces = ($dec > 2) ? $dec : 2;
my $discount = $form->round_amount($sellprice * $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100, $decimalplaces);
# keep a netprice as well, (sellprice - discount)
$form->{"netprice_$i"} = $sellprice - $discount;
push(@{ $form->{netprice} }, ($form->{"netprice_$i"} != 0) ? $form->format_amount($myconfig, $form->{"netprice_$i"}, $decimalplaces) : " ");
 
my $linetotal = $form->round_amount($form->{"qty_$i"} * $form->{"netprice_$i"}, 2);
 
$discount = ($discount != 0) ? $form->format_amount($myconfig, $discount * -1, $decimalplaces) : " ";
$linetotal = ($linetotal != 0) ? $linetotal : " ";
push(@{ $form->{discount} }, $discount);
 
$form->{total} += $linetotal;
 
push(@{ $form->{linetotal} }, $form->format_amount($myconfig, $linetotal, 2));
my $taxrate = 0;
my ($taxamount, $taxbase);
map { $taxrate += $form->{"${_}_rate"} } split / /, $form->{"taxaccounts_$i"};
 
if ($form->{taxincluded}) {
# calculate tax
$taxamount = $linetotal * ($taxrate / (1 + $taxrate));
$taxbase = $linetotal - $taxamount;
} else {
$taxamount = $linetotal * $taxrate;
$taxbase = $linetotal;
}
if ($taxamount != 0) {
foreach my $item (split / /, $form->{"taxaccounts_$i"}) {
$taxaccounts{$item} += $taxamount * $form->{"${item}_rate"} / $taxrate;
$taxbase{$item} += $taxbase;
}
}
 
if ($form->{"assembly_$i"} && $form->{"bom_$i"}) {
# get parts and push them onto the stack
$query = qq|SELECT p.partnumber, p.description, p.unit, a.qty
FROM assembly a, parts p
WHERE a.parts_id = p.id
AND a.id = '$form->{"id_$i"}'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push(@{ $form->{number} }, qq|$ref->{partnumber}|);
push(@{ $form->{description} }, qq|$ref->{description}|);
push(@{ $form->{unit} }, qq|$ref->{unit}|);
push(@{ $form->{qty} }, $form->format_amount($myconfig, $ref->{qty}));
 
map { push(@{ $form->{$_} }, "") } qw(runningnumber bin sellprice listprice netprice discount linetotal);
}
$sth->finish;
}
}
}
 
 
foreach my $item (sort keys %taxaccounts) {
if ($form->round_amount($taxaccounts{$item}, 2) != 0) {
push(@{ $form->{taxbase} }, $form->format_amount($myconfig, $taxbase{$item}, 2));
$tax += $taxamount = $form->round_amount($taxaccounts{$item}, 2);
push(@{ $form->{tax} }, $form->format_amount($myconfig, $taxamount));
push(@{ $form->{taxdescription} }, $form->{"${item}_description"});
push(@{ $form->{taxrate} }, $form->format_amount($myconfig, $form->{"${item}_rate"} * 100));
push(@{ $form->{taxnumber} }, $form->{"${item}_taxnumber"});
}
}
 
for my $i (1 .. $form->{paidaccounts}) {
if ($form->{"paid_$i"}) {
push(@{ $form->{payment} }, $form->{"paid_$i"});
my ($accno, $description) = split /--/, $form->{"AR_paid_$i"};
push(@{ $form->{paymentaccount} }, $description);
push(@{ $form->{paymentdate} }, $form->{"datepaid_$i"});
push(@{ $form->{paymentsource} }, $form->{"source_$i"});
 
$form->{paid} += $form->parse_amount($myconfig, $form->{"paid_$i"});
}
}
$form->{subtotal} = $form->format_amount($myconfig, $form->{total}, 2);
$form->{invtotal} = ($form->{taxincluded}) ? $form->{total} : $form->{total} + $tax;
$form->{total} = $form->format_amount($myconfig, $form->{invtotal} - $form->{paid}, 2);
$form->{invtotal} = $form->format_amount($myconfig, $form->{invtotal}, 2);
 
$form->{paid} = $form->format_amount($myconfig, $form->{paid}, 2);
 
# myconfig variables
map { $form->{$_} = $myconfig->{$_} } (qw(company address tel fax signature businessnumber));
$form->{username} = $myconfig->{name};
 
$dbh->disconnect;
}
 
 
sub project_description {
my ($self, $dbh, $id) = @_;
 
my $query = qq|SELECT description
FROM project
WHERE id = $id|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($_) = $sth->fetchrow_array;
 
$sth->finish;
 
$_;
 
}
 
 
sub customer_details {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
# get rest for the customer
my $query = qq|SELECT customernumber, name, addr1, addr2, addr3, addr4,
phone as customerphone, fax as customerfax, contact
FROM customer
WHERE id = $form->{customer_id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub post_invoice {
my ($self, $myconfig, $form) = @_;
# connect to database, turn off autocommit
my $dbh = $form->dbconnect_noauto($myconfig);
 
my ($query, $sth, $null, $project_id, $deliverydate);
my $exchangerate = 0;
if ($form->{id}) {
 
&reverse_invoice($dbh, $form);
 
} else {
my $uid = time;
$uid .= $form->{login};
$query = qq|INSERT INTO ar (invnumber, employee_id)
VALUES ('$uid', (SELECT id FROM employee
WHERE login = '$form->{login}') )|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|SELECT id FROM ar
WHERE invnumber = '$uid'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{id}) = $sth->fetchrow_array;
$sth->finish;
}
 
 
map { $form->{$_} =~ s/'/''/g } (qw(invnumber shippingpoint notes message));
 
my ($netamount, $invoicediff) = (0, 0);
my ($amount, $linetotal, $lastincomeaccno);
 
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{exchangerate} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{transdate}, 'buy');
}
 
$form->{exchangerate} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{exchangerate});
 
foreach my $i (1 .. $form->{rowcount}) {
$form->{"qty_$i"} = $form->parse_amount($myconfig, $form->{"qty_$i"});
if ($form->{"qty_$i"} != 0) {
 
map { $form->{"${_}_$i"} =~ s/'/''/g } (qw(partnumber description unit));
# undo discount formatting
$form->{"discount_$i"} = $form->parse_amount($myconfig, $form->{"discount_$i"}) / 100;
 
my ($allocated, $taxrate) = (0, 0);
my $taxamount;
# keep entered selling price
my $fxsellprice = $form->parse_amount($myconfig, $form->{"sellprice_$i"});
my ($dec) = ($fxsellprice =~ /\.(\d+)/);
$dec = length $dec;
my $decimalplaces = ($dec > 2) ? $dec : 2;
# deduct discount
my $discount = $form->round_amount($fxsellprice * $form->{"discount_$i"}, $decimalplaces);
$form->{"sellprice_$i"} = $fxsellprice - $discount;
# add tax rates
map { $taxrate += $form->{"${_}_rate"} } split / /, $form->{"taxaccounts_$i"};
 
# round linetotal to 2 decimal places
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2);
if ($form->{taxincluded}) {
$taxamount = $linetotal * ($taxrate / (1 + $taxrate));
$form->{"sellprice_$i"} = $form->{"sellprice_$i"} * (1 / (1 + $taxrate));
} else {
$taxamount = $linetotal * $taxrate;
}
 
$netamount += $linetotal;
if ($taxamount != 0) {
map { $form->{amount}{$form->{id}}{$_} += $taxamount * $form->{"${_}_rate"} / $taxrate } split / /, $form->{"taxaccounts_$i"};
}
# add amount to income, $form->{amount}{trans_id}{accno}
$amount = $form->{"sellprice_$i"} * $form->{"qty_$i"} * $form->{exchangerate};
$linetotal = $form->round_amount($form->{"sellprice_$i"} * $form->{"qty_$i"}, 2) * $form->{exchangerate};
$linetotal = $form->round_amount($linetotal, 2);
# this is the difference from the inventory
$invoicediff += ($amount - $linetotal);
$form->{amount}{$form->{id}}{$form->{"income_accno_$i"}} += $linetotal;
$lastincomeaccno = $form->{"income_accno_$i"};
 
# adjust and round sellprice
$form->{"sellprice_$i"} = $form->round_amount($form->{"sellprice_$i"} * $form->{exchangerate}, $decimalplaces);
if ($form->{"inventory_accno_$i"} || $form->{"assembly_$i"}) {
# adjust parts onhand quantity
 
if ($form->{"assembly_$i"}) {
# do not update if assembly consists of all services
$query = qq|SELECT sum(p.inventory_accno_id)
FROM parts p, assembly a
WHERE a.parts_id = p.id
AND a.id = $form->{"id_$i"}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
if ($sth->fetchrow_array) {
$form->update_balance($dbh,
"parts",
"onhand",
qq|id = $form->{"id_$i"}|,
$form->{"qty_$i"} * -1);
}
$sth->finish;
# record assembly item as allocated
&process_assembly($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"});
} else {
$form->update_balance($dbh,
"parts",
"onhand",
qq|id = $form->{"id_$i"}|,
$form->{"qty_$i"} * -1);
$allocated = &cogs($dbh, $form, $form->{"id_$i"}, $form->{"qty_$i"});
}
}
 
$project_id = 'NULL';
if ($form->{"project_id_$i"}) {
$project_id = $form->{"project_id_$i"};
}
$deliverydate = ($form->{"deliverydate_$i"}) ? qq|'$form->{"deliverydate_$i"}'| : "NULL";
 
# save detail record in invoice table
$query = qq|INSERT INTO invoice (trans_id, parts_id, description, qty,
sellprice, fxsellprice, discount, allocated, assemblyitem,
unit, deliverydate, project_id)
VALUES ($form->{id}, $form->{"id_$i"},
'$form->{"description_$i"}', $form->{"qty_$i"},
$form->{"sellprice_$i"}, $fxsellprice,
$form->{"discount_$i"}, $allocated, 'f',
'$form->{"unit_$i"}', $deliverydate, $project_id)|;
$dbh->do($query) || $form->dberror($query);
 
}
}
 
 
$form->{datepaid} = $form->{invdate};
# total payments, don't move we need it here
for my $i (1 .. $form->{paidaccounts}) {
$form->{"paid_$i"} = $form->parse_amount($myconfig, $form->{"paid_$i"});
$form->{paid} += $form->{"paid_$i"};
$form->{datepaid} = $form->{"datepaid_$i"} if ($form->{"datepaid_$i"});
}
my ($tax, $diff) = (0, 0);
$netamount = $form->round_amount($netamount, 2);
# figure out rounding errors for total amount vs netamount + taxes
if ($form->{taxincluded}) {
$amount = $form->round_amount($netamount * $form->{exchangerate}, 2);
$diff += $amount - $netamount * $form->{exchangerate};
$netamount = $amount;
foreach my $item (split / /, $form->{taxaccounts}) {
$amount = $form->{amount}{$form->{id}}{$item} * $form->{exchangerate};
$form->{amount}{$form->{id}}{$item} = $form->round_amount($amount, 2);
$tax += $form->{amount}{$form->{id}}{$item};
$netamount -= $form->{amount}{$form->{id}}{$item};
}
 
$invoicediff += $diff;
######## this only applies to tax included
if ($lastincomeaccno) {
$form->{amount}{$form->{id}}{$lastincomeaccno} += $invoicediff;
}
 
} else {
$amount = $form->round_amount($netamount * $form->{exchangerate}, 2);
$diff = $amount - $netamount * $form->{exchangerate};
$netamount = $amount;
foreach my $item (split / /, $form->{taxaccounts}) {
$form->{amount}{$form->{id}}{$item} = $form->round_amount($form->{amount}{$form->{id}}{$item}, 2);
$amount = $form->round_amount($form->{amount}{$form->{id}}{$item} * $form->{exchangerate}, 2);
$diff += $amount - $form->{amount}{$form->{id}}{$item} * $form->{exchangerate};
$form->{amount}{$form->{id}}{$item} = $form->round_amount($amount, 2);
$tax += $form->{amount}{$form->{id}}{$item};
}
}
 
$form->{amount}{$form->{id}}{$form->{AR}} = $netamount + $tax;
 
if ($form->{paid} != 0) {
$form->{paid} = $form->round_amount($form->{paid} * $form->{exchangerate} + $diff, 2);
}
# reverse AR
$form->{amount}{$form->{id}}{$form->{AR}} *= -1;
 
 
# update exchangerate
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{invdate}, $form->{exchangerate}, 0);
}
foreach my $trans_id (keys %{$form->{amount}}) {
foreach my $accno (keys %{ $form->{amount}{$trans_id} }) {
if (($form->{amount}{$trans_id}{$accno} = $form->round_amount($form->{amount}{$trans_id}{$accno}, 2)) != 0) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($trans_id, (SELECT id FROM chart
WHERE accno = '$accno'),
$form->{amount}{$trans_id}{$accno}, '$form->{invdate}')|;
$dbh->do($query) || $form->dberror($query);
}
}
}
 
# deduct payment differences from diff
for my $i (1 .. $form->{paidaccounts}) {
if ($form->{"paid_$i"} != 0) {
$amount = $form->round_amount($form->{"paid_$i"} * $form->{exchangerate}, 2);
$diff -= $amount - $form->{"paid_$i"} * $form->{exchangerate};
}
}
 
# force AR entry if 0
$form->{amount}{$form->{id}}{$form->{AR}} = 1 if ($form->{amount}{$form->{id}}{$form->{AR}} == 0);
# record payments and offsetting AR
for my $i (1 .. $form->{paidaccounts}) {
if ($form->{"paid_$i"} != 0) {
my ($accno) = split /--/, $form->{"AR_paid_$i"};
$form->{"datepaid_$i"} = $form->{invdate} unless ($form->{"datepaid_$i"});
$form->{datepaid} = $form->{"datepaid_$i"};
# record AR
$amount = $form->round_amount($form->{"paid_$i"} * $form->{exchangerate} + $diff, 2);
 
if ($form->{amount}{$form->{id}}{$form->{AR}} != 0) {
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$form->{AR}'),
$amount, '$form->{"datepaid_$i"}')|;
$dbh->do($query) || $form->dberror($query);
}
 
# record payment
$form->{"paid_$i"} *= -1;
 
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate,
source)
VALUES ($form->{id}, (SELECT id FROM chart
WHERE accno = '$accno'),
$form->{"paid_$i"}, '$form->{"datepaid_$i"}',
'$form->{"source_$i"}')|;
$dbh->do($query) || $form->dberror($query);
 
$exchangerate = 0;
if ($form->{currency} eq $form->{defaultcurrency}) {
$form->{"exchangerate_$i"} = 1;
} else {
$exchangerate = $form->check_exchangerate($myconfig, $form->{currency}, $form->{"datepaid_$i"}, 'buy');
$form->{"exchangerate_$i"} = ($exchangerate) ? $exchangerate : $form->parse_amount($myconfig, $form->{"exchangerate_$i"});
}
# exchangerate difference
$form->{fx}{$accno}{$form->{"datepaid_$i"}} += $form->{"paid_$i"} * ($form->{"exchangerate_$i"} - 1) + $diff;
 
# gain/loss
$amount = $form->{"paid_$i"} * $form->{exchangerate} - $form->{"paid_$i"} * $form->{"exchangerate_$i"};
if ($amount > 0) {
$form->{fx}{$form->{fxgain_accno}}{$form->{"datepaid_$i"}} += $amount;
} else {
$form->{fx}{$form->{fxloss_accno}}{$form->{"datepaid_$i"}} += $amount;
}
 
$diff = 0;
 
# update exchange rate
if (($form->{currency} ne $form->{defaultcurrency}) && !$exchangerate) {
$form->update_exchangerate($dbh, $form->{currency}, $form->{"datepaid_$i"}, $form->{"exchangerate_$i"}, 0);
}
}
}
 
# record exchange rate differences and gains/losses
foreach my $accno (keys %{$form->{fx}}) {
foreach my $transdate (keys %{ $form->{fx}{$accno} }) {
if (($form->{fx}{$accno}{$transdate} = $form->round_amount($form->{fx}{$accno}{$transdate}, 2)) != 0) {
 
$query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount,
transdate, cleared, fx_transaction)
VALUES ($form->{id},
(SELECT id FROM chart
WHERE accno = '$accno'),
$form->{fx}{$accno}{$transdate}, '$transdate', '0', '1')|;
$dbh->do($query) || $form->dberror($query);
}
}
}
 
$amount = $netamount + $tax;
# set values which could be empty to 0
$form->{terms} *= 1;
$form->{taxincluded} *= 1;
my $datepaid = ($form->{paid}) ? qq|'$form->{datepaid}'| : "NULL";
my $duedate = ($form->{duedate}) ? qq|'$form->{duedate}'| : "NULL";
 
# fill in subject if there is none
$form->{subject} = qq|$form->{label} $form->{invnumber}| unless $form->{subject};
# if there is a message stuff it into the notes
my $cc = "Cc: $form->{cc}\\r\n" if $form->{cc};
my $bcc = "Bcc: $form->{bcc}\\r\n" if $form->{bcc};
$form->{notes} .= qq|\r
\r
[email]\r
To: $form->{email}\r
$cc${bcc}Subject: $form->{subject}\r
\r
Message: $form->{message}\r| if $form->{message};
 
# save AR record
$query = qq|UPDATE ar set
invnumber = '$form->{invnumber}',
ordnumber = '$form->{ordnumber}',
transdate = '$form->{invdate}',
customer_id = $form->{customer_id},
amount = $amount,
netamount = $netamount,
paid = $form->{paid},
datepaid = $datepaid,
duedate = $duedate,
invoice = '1',
shippingpoint = '$form->{shippingpoint}',
terms = $form->{terms},
notes = '$form->{notes}',
taxincluded = '$form->{taxincluded}',
curr = '$form->{currency}'
WHERE id = $form->{id}
|;
$dbh->do($query) || $form->dberror($query);
 
# add shipto
$form->{name} = $form->{customer};
$form->{name} =~ s/--$form->{customer_id}//;
$form->add_shipto($dbh, $form->{id});
 
my $rc = $dbh->commit;
$dbh->disconnect;
 
$rc;
}
 
 
sub process_assembly {
my ($dbh, $form, $id, $totalqty) = @_;
 
my $query = qq|SELECT a.parts_id, a.qty, p.assembly,
p.partnumber, p.description, p.unit,
p.inventory_accno_id, p.income_accno_id,
p.expense_accno_id
FROM assembly a, parts p
WHERE a.parts_id = p.id
AND a.id = $id|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
my $allocated = 0;
$ref->{inventory_accno_id} *= 1;
$ref->{expense_accno_id} *= 1;
 
map { $ref->{$_} =~ s/'/''/g } (qw(partnumber description unit));
# multiply by number of assemblies
$ref->{qty} *= $totalqty;
if ($ref->{assembly}) {
&process_assembly($dbh, $form, $ref->{parts_id}, $ref->{qty});
next;
} else {
if ($ref->{inventory_accno_id}) {
$allocated = &cogs($dbh, $form, $ref->{parts_id}, $ref->{qty});
}
}
 
# save detail record for individual assembly item in invoice table
$query = qq|INSERT INTO invoice (trans_id, description, parts_id, qty,
sellprice, fxsellprice, allocated, assemblyitem, unit)
VALUES
($form->{id}, '$ref->{description}',
$ref->{parts_id}, $ref->{qty}, 0, 0, $allocated, 't',
'$ref->{unit}')|;
$dbh->do($query) || $form->dberror($query);
}
 
$sth->finish;
 
}
 
 
sub cogs {
my ($dbh, $form, $id, $totalqty) = @_;
my $query = qq|SELECT i.id, i.trans_id, i.qty, i.allocated, i.sellprice,
(SELECT c.accno FROM chart c
WHERE p.inventory_accno_id = c.id)
AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE p.expense_accno_id = c.id)
AS expense_accno
FROM invoice i, parts p
WHERE i.parts_id = p.id
AND i.parts_id = $id
AND (i.qty + i.allocated) < 0
ORDER BY trans_id|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $allocated = 0;
my $qty;
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
if (($qty = (($ref->{qty} * -1) - $ref->{allocated})) > $totalqty) {
$qty = $totalqty;
}
$form->update_balance($dbh,
"invoice",
"allocated",
qq|id = $ref->{id}|,
$qty);
 
# total expenses and inventory
# sellprice is the cost of the item
$linetotal = $form->round_amount($ref->{sellprice} * $qty, 2);
# add to expense
$form->{amount}{$form->{id}}{$ref->{expense_accno}} += -$linetotal;
 
# deduct inventory
$form->{amount}{$form->{id}}{$ref->{inventory_accno}} -= -$linetotal;
 
# add allocated
$allocated += -$qty;
last if (($totalqty -= $qty) <= 0);
}
 
$sth->finish;
 
$allocated;
}
 
 
 
sub reverse_invoice {
my ($dbh, $form) = @_;
# reverse inventory items
my $query = qq|SELECT i.id, i.parts_id, i.qty, i.assemblyitem, p.assembly,
p.inventory_accno_id
FROM invoice i, parts p
WHERE i.parts_id = p.id
AND i.trans_id = $form->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
if ($ref->{inventory_accno_id} || $ref->{assembly}) {
 
# if the invoice item is not an assemblyitem adjust parts onhand
unless ($ref->{assemblyitem}) {
# adjust onhand in parts table
$form->update_balance($dbh,
"parts",
"onhand",
qq|id = $ref->{parts_id}|,
$ref->{qty});
}
 
# loop if it is an assembly
next if ($ref->{assembly});
# de-allocated purchases
$query = qq|SELECT id, trans_id, allocated
FROM invoice
WHERE parts_id = $ref->{parts_id}
AND allocated > 0
ORDER BY trans_id DESC|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $inhref = $sth->fetchrow_hashref(NAME_lc)) {
$qty = $ref->{qty};
if (($ref->{qty} - $inhref->{allocated}) > 0) {
$qty = $inhref->{allocated};
}
# update invoice
$form->update_balance($dbh,
"invoice",
"allocated",
qq|id = $inhref->{id}|,
$qty * -1);
 
last if (($ref->{qty} -= $qty) <= 0);
}
$sth->finish;
}
}
$sth->finish;
# delete acc_trans
$query = qq|DELETE FROM acc_trans
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
# delete invoice entries
$query = qq|DELETE FROM invoice
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
$query = qq|DELETE FROM shipto
WHERE trans_id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
}
 
 
 
sub delete_invoice {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
# check for other foreign currency transactions
$form->delete_exchangerate($dbh) if ($form->{currency} ne $form->{defaultcurrency});
&reverse_invoice($dbh, $form);
# delete AR record
my $query = qq|DELETE FROM ar
WHERE id = $form->{id}|;
$dbh->do($query) || $form->dberror($query);
 
my $rc = $dbh->commit;
$dbh->disconnect;
$rc;
}
 
 
 
sub retrieve_invoice {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $query;
if ($form->{id}) {
# get default accounts and last invoice number
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE d.inventory_accno_id = c.id) AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE d.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c
WHERE d.expense_accno_id = c.id) AS expense_accno,
(SELECT c.accno FROM chart c
WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
(SELECT c.accno FROM chart c
WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
d.curr AS currencies
FROM defaults d|;
} else {
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE d.inventory_accno_id = c.id) AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE d.income_accno_id = c.id) AS income_accno,
(SELECT c.accno FROM chart c
WHERE d.expense_accno_id = c.id) AS expense_accno,
(SELECT c.accno FROM chart c
WHERE d.fxgain_accno_id = c.id) AS fxgain_accno,
(SELECT c.accno FROM chart c
WHERE d.fxloss_accno_id = c.id) AS fxloss_accno,
d.invnumber, d.curr AS currencies, current_date AS invdate
FROM defaults d|;
}
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
 
if ($form->{id}) {
# retrieve invoice
$query = qq|SELECT a.invnumber, a.ordnumber, a.transdate AS invdate, a.paid,
a.shippingpoint, a.terms, a.notes, a.duedate, a.taxincluded,
a.curr AS currency, (SELECT e.name FROM employee e
WHERE e.id = a.employee_id) AS employee
FROM ar a
WHERE a.id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
 
$form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{invdate}, "buy");
 
# get shipto
$query = qq|SELECT * FROM shipto
WHERE trans_id = $form->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
# retrieve individual items
$query = qq|SELECT (SELECT c.accno FROM chart c
WHERE p.inventory_accno_id = c.id)
AS inventory_accno,
(SELECT c.accno FROM chart c
WHERE p.income_accno_id = c.id)
AS income_accno,
(SELECT c.accno FROM chart c
WHERE p.expense_accno_id = c.id)
AS expense_accno,
i.description, i.qty, i.fxsellprice AS sellprice,
i.discount, i.parts_id AS id, i.unit, i.deliverydate,
(SELECT projectnumber FROM project pr
WHERE i.project_id = pr.id) AS projectnumber,
i.project_id,
p.partnumber, p.assembly, p.bom, p.bin
FROM invoice i, parts p
WHERE i.parts_id = p.id
AND i.trans_id = $form->{id}
AND NOT i.assemblyitem = '1'
ORDER BY i.id|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
# get taxes
$query = qq|SELECT c.accno
FROM chart c, partstax pt
WHERE pt.chart_id = c.id
AND pt.parts_id = $ref->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref->{taxaccounts} = "";
my $taxrate = 0;
while (my $ptref = $sth->fetchrow_hashref(NAME_lc)) {
$ref->{taxaccounts} .= "$ptref->{accno} ";
$taxrate += $form->{"$ptref->{accno}_rate"};
}
$sth->finish;
chop $ref->{taxaccounts};
 
push @{ $form->{invoice_details} }, $ref;
}
$sth->finish;
 
} else {
 
$form->{shippingpoint} = $myconfig->{shippingpoint} unless $form->{shippingpoint};
 
# up invoice number by 1
$form->{invnumber}++;
 
# save the new number
$query = qq|UPDATE defaults
SET invnumber = '$form->{invnumber}'|;
$dbh->do($query) || $form->dberror($query);
 
$form->get_employee($dbh);
 
}
 
 
my $rc = $dbh->commit;
$dbh->disconnect;
$rc;
 
}
 
 
sub get_customer {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $duedate = ($form->{invdate}) ? "date '$form->{invdate}'" : "current_date";
 
$form->{customer_id} *= 1;
# get customer
my $query = qq|SELECT c.name AS customer, c.discount, c.creditlimit, c.terms,
c.email, c.cc, c.bcc, c.taxincluded,
c.addr1, c.addr2, c.addr3, c.addr4,
$duedate + c.terms AS duedate
FROM customer c
WHERE c.id = $form->{customer_id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
 
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
$form->{creditremaining} = $form->{creditlimit};
$query = qq|SELECT SUM(amount - paid)
FROM ar
WHERE customer_id = $form->{customer_id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
($form->{creditremaining}) -= $sth->fetchrow_array;
 
$sth->finish;
$query = qq|SELECT o.amount,
(SELECT e.buy FROM exchangerate e
WHERE e.curr = o.curr
AND e.transdate = o.transdate)
FROM oe o
WHERE o.customer_id = $form->{customer_id}
AND o.closed = '0'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my ($amount, $exch) = $sth->fetchrow_array) {
$exch = 1 unless $exch;
$form->{creditremaining} -= $amount * $exch;
}
$sth->finish;
 
 
# get shipto if we did not converted an order or invoice
if (!$form->{shipto}) {
map { delete $form->{$_} } qw(shiptoname shiptoaddr1 shiptoaddr2 shiptoaddr3 shiptoaddr4 shiptocontact shiptophone shiptofax shiptoemail);
 
$query = qq|SELECT * FROM shipto
WHERE trans_id = $form->{customer_id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref = $sth->fetchrow_hashref(NAME_lc);
map { $form->{$_} = $ref->{$_} } keys %$ref;
$sth->finish;
}
# get taxes we charge for this customer
$query = qq|SELECT c.accno
FROM chart c, customertax ct
WHERE ct.chart_id = c.id
AND ct.customer_id = $form->{customer_id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my $customertax = ();
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
$customertax{$ref->{accno}} = 1;
}
$sth->finish;
# get tax rates and description
$query = qq|SELECT c.accno, c.description, t.rate, t.taxnumber
FROM chart c, tax t
WHERE c.id = t.chart_id
AND c.link LIKE '%CT_tax%'
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$form->{taxaccounts} = "";
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
if ($customertax{$ref->{accno}}) {
$form->{"$ref->{accno}_rate"} = $ref->{rate};
$form->{"$ref->{accno}_description"} = $ref->{description};
$form->{"$ref->{accno}_taxnumber"} = $ref->{taxnumber};
$form->{taxaccounts} .= "$ref->{accno} ";
}
}
$sth->finish;
chop $form->{taxaccounts};
 
$dbh->disconnect;
}
 
 
 
sub retrieve_item {
my ($self, $myconfig, $form) = @_;
 
my $i = $form->{rowcount};
my $where = "NOT obsolete = '1'";
 
if ($form->{"partnumber_$i"}) {
my $partnumber = $form->like(lc $form->{"partnumber_$i"});
$where .= " AND lower(partnumber) LIKE '$partnumber'";
}
if ($form->{"description_$i"}) {
my $description = $form->like(lc $form->{"description_$i"});
$where .= " AND lower(description) LIKE '$description'";
}
 
if ($form->{"description_$i"}) {
$where .= " ORDER BY description";
} else {
$where .= " ORDER BY partnumber";
}
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT p.id, p.partnumber, p.description, p.sellprice,
p.listprice,
(SELECT accno FROM chart c
WHERE p.inventory_accno_id = c.id)
AS inventory_accno,
(SELECT accno FROM chart c
WHERE p.income_accno_id = c.id)
AS income_accno,
(SELECT accno FROM chart c
WHERE p.expense_accno_id = c.id)
AS expense_accno,
p.unit, p.assembly, p.bom, p.bin, p.onhand, p.makemodel
FROM parts p
WHERE $where|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
 
# get taxes for part
$query = qq|SELECT c.accno
FROM chart c, partstax pt
WHERE c.id = pt.chart_id
AND pt.parts_id = $ref->{id}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
$ref->{taxaccounts} = "";
while (my $ptref = $sth->fetchrow_hashref(NAME_lc)) {
$ref->{taxaccounts} .= "$ptref->{accno} ";
}
$sth->finish;
chop $ref->{taxaccounts};
 
# get makemodel
if ($ref->{makemodel}) {
$query = qq|SELECT name
FROM makemodel
WHERE parts_id = $ref->{id}|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
$ref->{makemodel} = "";
while (my $ptref = $sth->fetchrow_hashref(NAME_lc)) {
$ref->{makemodel} .= "$ptref->{name}:";
}
$sth->finish;
chop $ref->{makemodel};
}
 
push @{ $form->{item_list} }, $ref;
 
}
$sth->finish;
$dbh->disconnect;
}
 
 
1;
 
/tags/release_2_0_6-2/SL/User.pm
New file
0,0 → 1,692
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=====================================================================
#
# user related functions
#
#=====================================================================
 
package User;
 
 
sub new {
my ($type, $memfile, $login) = @_;
my $self = {};
 
if ($login ne "") {
# check if the file is locked
&error("", "$memfile locked!") if (-f "${memfile}.LCK");
open(MEMBER, "$memfile") or &error("", "$memfile : $!");
while (<MEMBER>) {
if (/^\[$login\]/) {
while (<MEMBER>) {
last if /^\[/;
next if /^(#|\s)/;
# remove comments
s/\s#.*//g;
 
# remove any trailing whitespace
s/^\s*(.*?)\s*$/$1/;
 
($key, $value) = split /=/, $_, 2;
$self->{$key} = $value;
}
$self->{login} = $login;
 
last;
}
}
close MEMBER;
}
bless $self, $type;
}
 
 
sub country_codes {
 
my %cc = ();
my @language = ();
# scan the locale directory and read in the LANGUAGE files
opendir DIR, "locale";
 
my @dir = grep !/(^\.\.?$|\..*)/, readdir DIR;
foreach my $dir (@dir) {
next unless open(FH, "locale/$dir/LANGUAGE");
@language = <FH>;
close FH;
 
$cc{$dir} = "@language";
}
 
closedir(DIR);
%cc;
 
}
 
 
sub login {
my ($self, $form, $userspath) = @_;
 
 
if ($self->{login}) {
if ($self->{password}) {
$form->{password} = crypt $form->{password}, substr($self->{login}, 0, 2);
if ($self->{password} ne $form->{password}) {
return -1;
}
}
unless (-e "$userspath/$self->{login}.conf") {
$self->create_config("$userspath/$self->{login}.conf");
}
do "$userspath/$self->{login}.conf";
$myconfig{dbpasswd} = unpack 'u', $myconfig{dbpasswd};
# check if database is down
my $dbh = DBI->connect($myconfig{dbconnect}, $myconfig{dbuser}, $myconfig{dbpasswd}) or $self->error(DBI::errstr);
 
# we got a connection, check the version
my $query = qq|SELECT version FROM defaults|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my ($dbversion) = $sth->fetchrow_array;
$sth->finish;
 
# add login to employee table if it does not exist
# no error check for employee table, ignore if it does not exist
$query = qq|SELECT id FROM employee WHERE login = '$self->{login}'|;
$sth = $dbh->prepare($query);
$sth->execute;
 
my ($login) = $sth->fetchrow_array;
$sth->finish;
 
if (!$login) {
$query = qq|INSERT INTO employee (login, name, workphone)
VALUES ('$self->{login}', '$myconfig{name}', '$myconfig{tel}')|;
$dbh->do($query);
}
$dbh->disconnect;
 
if ($form->{dbversion} ne $dbversion) {
return -2;
}
 
} else {
return -3;
}
 
}
 
 
 
sub dbconnect_vars {
my ($form, $db) = @_;
my %dboptions = (
'Pg' => {
'yy-mm-dd' => 'set DateStyle to \'ISO\'',
'mm/dd/yy' => 'set DateStyle to \'SQL, US\'',
'mm-dd-yy' => 'set DateStyle to \'POSTGRES, US\'',
'dd/mm/yy' => 'set DateStyle to \'SQL, EUROPEAN\'',
'dd-mm-yy' => 'set DateStyle to \'POSTGRES, EUROPEAN\'',
'dd.mm.yy' => 'set DateStyle to \'GERMAN\''
},
'Oracle' => {
'yy-mm-dd' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'YY-MM-DD\'',
'mm/dd/yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'MM/DD/YY\'',
'mm-dd-yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'MM-DD-YY\'',
'dd/mm/yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'DD/MM/YY\'',
'dd-mm-yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'DD-MM-YY\'',
'dd.mm.yy' => 'ALTER SESSION SET NLS_DATE_FORMAT = \'DD.MM.YY\'',
}
);
$form->{dboptions} = $dboptions{$form->{dbdriver}}{$form->{dateformat}};
 
if ($form->{dbdriver} eq 'Pg') {
$form->{dbconnect} = "dbi:Pg:dbname=$db";
}
 
if ($form->{dbdriver} eq 'Oracle') {
$form->{dbconnect} = "dbi:Oracle:sid=$form->{sid}";
}
 
if ($form->{dbhost}) {
$form->{dbconnect} .= ";host=$form->{dbhost}";
}
if ($form->{dbport}) {
$form->{dbconnect} .= ";port=$form->{dbport}";
}
}
 
 
sub dbdrivers {
 
my @drivers = DBI->available_drivers();
 
return (grep { /(Pg|Oracle)$/ } @drivers);
 
}
 
 
sub dbsources {
my ($self, $form) = @_;
 
my @dbsources = ();
my ($sth, $query);
$form->{dbdefault} = $form->{dbuser} unless $form->{dbdefault};
$form->{sid} = $form->{dbdefault};
&dbconnect_vars($form, $form->{dbdefault});
 
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
 
 
if ($form->{dbdriver} eq 'Pg') {
 
$query = qq|SELECT datname FROM pg_database|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
while (my ($db) = $sth->fetchrow_array) {
 
if ($form->{only_acc_db}) {
next if ($db =~ /^template/);
 
&dbconnect_vars($form, $db);
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
 
$query = qq|SELECT tablename FROM pg_tables
WHERE tablename = 'defaults'
AND tableowner = '$form->{dbuser}'|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
if ($sth->fetchrow_array) {
push @dbsources, $db;
}
$sth->finish;
$dbh->disconnect;
next;
}
push @dbsources, $db;
}
}
 
if ($form->{dbdriver} eq 'Oracle') {
if ($form->{only_acc_db}) {
$query = qq|SELECT owner FROM dba_objects
WHERE object_name = 'DEFAULTS'
AND object_type = 'TABLE'|;
} else {
$query = qq|SELECT username FROM dba_users|;
}
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my ($db) = $sth->fetchrow_array) {
push @dbsources, $db;
}
}
 
$sth->finish;
$dbh->disconnect;
return @dbsources;
 
}
 
 
sub dbcreate {
my ($self, $form) = @_;
 
my %dbcreate = ( 'Pg' => qq|CREATE DATABASE "$form->{db}"|,
'Oracle' => qq|CREATE USER "$form->{db}" DEFAULT TABLESPACE USERS TEMPORARY TABLESPACE TEMP IDENTIFIED BY "$form->{db}"|);
 
$dbcreate{Pg} .= " WITH ENCODING = '$form->{encoding}'" if $form->{encoding};
$form->{sid} = $form->{dbdefault};
&dbconnect_vars($form, $form->{dbdefault});
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
my $query = qq|$dbcreate{$form->{dbdriver}}|;
$dbh->do($query) || $form->dberror($query);
 
if ($form->{dbdriver} eq 'Oracle') {
$query = qq|GRANT CONNECT,RESOURCE TO "$form->{db}"|;
$dbh->do($query) || $form->dberror($query);
}
$dbh->disconnect;
 
 
# setup variables for the new database
if ($form->{dbdriver} eq 'Oracle') {
$form->{dbuser} = $form->{db};
$form->{dbpasswd} = $form->{db};
}
&dbconnect_vars($form, $form->{db});
$dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
# create the tables
my $filename = qq|sql/$form->{dbdriver}-tables.sql|;
$self->processquery($form, $dbh, $filename);
 
# load gifi
($filename) = split /_/, $form->{chart};
$filename =~ s/_//;
$self->processquery($form, $dbh, "sql/${filename}-gifi.sql");
 
# load chart of accounts
$filename = qq|sql/$form->{chart}-chart.sql|;
$self->processquery($form, $dbh, $filename);
 
# create indices
$filename = qq|sql/$form->{dbdriver}-indices.sql|;
$self->processquery($form, $dbh, $filename);
$dbh->disconnect;
 
}
 
 
 
sub processquery {
my ($self, $form, $dbh, $filename) = @_;
return unless (-f $filename);
open(FH, "$filename") or $form->error("$filename : $!\n");
my $query = "";
while (<FH>) {
$query .= $_;
 
if (/;\s*$/) {
# strip ;... Oracle doesn't like it
$query =~ s/;\s*$//;
$dbh->do($query) || $form->dberror($query);
$query = "";
}
}
close FH;
 
}
 
 
sub dbdelete {
my ($self, $form) = @_;
 
my %dbdelete = ( 'Pg' => qq|DROP DATABASE "$form->{db}"|,
'Oracle' => qq|DROP USER $form->{db} CASCADE|
);
$form->{sid} = $form->{dbdefault};
&dbconnect_vars($form, $form->{dbdefault});
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
my $query = qq|$dbdelete{$form->{dbdriver}}|;
$dbh->do($query) || $form->dberror($query);
 
$dbh->disconnect;
 
}
 
 
sub dbsources_unused {
my ($self, $form, $memfile) = @_;
 
my @dbexcl = ();
my @dbsources = ();
$form->error('File locked!') if (-f "${memfile}.LCK");
# open members file
open(FH, "$memfile") or $form->error("$memfile : $!");
 
while (<FH>) {
if (/^dbname=/) {
my ($null,$item) = split /=/;
push @dbexcl, $item;
}
}
 
close FH;
 
$form->{only_acc_db} = 1;
my @db = &dbsources("", $form);
 
push @dbexcl, $form->{dbdefault};
 
foreach $item (@db) {
unless (grep /$item$/, @dbexcl) {
push @dbsources, $item;
}
}
 
return @dbsources;
 
}
 
 
sub dbneedsupdate {
my ($self, $form) = @_;
 
my %dbsources = ();
my $query;
$form->{sid} = $form->{dbdefault};
&dbconnect_vars($form, $form->{dbdefault});
 
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
 
if ($form->{dbdriver} eq 'Pg') {
 
$query = qq|SELECT d.datname FROM pg_database d, pg_user u
WHERE d.datdba = u.usesysid
AND u.usename = '$form->{dbuser}'|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
while (my ($db) = $sth->fetchrow_array) {
 
next if ($db =~ /^template/);
 
&dbconnect_vars($form, $db);
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
 
$query = qq|SELECT tablename FROM pg_tables
WHERE tablename = 'defaults'|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
if ($sth->fetchrow_array) {
$query = qq|SELECT version FROM defaults|;
my $sth = $dbh->prepare($query);
$sth->execute;
if (my ($version) = $sth->fetchrow_array) {
$dbsources{$db} = $version;
}
$sth->finish;
}
$sth->finish;
$dbh->disconnect;
}
$sth->finish;
}
 
 
if ($form->{dbdriver} eq 'Oracle') {
$query = qq|SELECT owner FROM dba_objects
WHERE object_name = 'DEFAULTS'
AND object_type = 'TABLE'|;
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my ($db) = $sth->fetchrow_array) {
$form->{dbuser} = $db;
&dbconnect_vars($form, $db);
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
 
$query = qq|SELECT version FROM defaults|;
my $sth = $dbh->prepare($query);
$sth->execute;
if (my ($version) = $sth->fetchrow_array) {
$dbsources{$db} = $version;
}
$sth->finish;
$dbh->disconnect;
}
$sth->finish;
}
$dbh->disconnect;
%dbsources;
 
}
 
 
sub dbupdate {
my ($self, $form) = @_;
 
$form->{sid} = $form->{dbdefault};
my @upgradescripts = ();
my $query;
if ($form->{dbupdate}) {
# read update scripts into memory
opendir SQLDIR, "sql/." or $form-error($!);
@upgradescripts = sort grep /$form->{dbdriver}-upgrade-.*?\.sql/, readdir SQLDIR;
closedir SQLDIR;
}
 
foreach my $db (split / /, $form->{dbupdate}) {
 
next unless $form->{$db};
 
# strip db from dataset
$db =~ s/^db//;
&dbconnect_vars($form, $db);
 
my $dbh = DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) or $form->dberror;
 
# check version
$query = qq|SELECT version FROM defaults|;
my $sth = $dbh->prepare($query);
# no error check, let it fall through
$sth->execute;
 
my $version = $sth->fetchrow_array;
$sth->finish;
next unless $version;
 
foreach my $upgradescript (@upgradescripts) {
my $a = $upgradescript;
$a =~ s/(^$form->{dbdriver}-upgrade-|\.sql$)//g;
my ($mindb, $maxdb) = split /-/, $a;
 
next if ($version ge $maxdb);
 
# if there is no upgrade script exit
last if ($version lt $mindb);
 
# apply upgrade
$self->processquery($form, $dbh, "sql/$upgradescript");
 
$version = $maxdb;
}
$dbh->disconnect;
}
}
 
 
sub create_config {
my ($self, $filename) = @_;
 
 
@config = &config_vars;
open(CONF, ">$filename") or $self->error("$filename : $!");
# create the config file
print CONF qq|# configuration file for $self->{login}
 
\%myconfig = (
|;
 
foreach $key (sort @config) {
$self->{$key} =~ s/'/\\'/g;
print CONF qq| $key => '$self->{$key}',\n|;
}
 
print CONF qq|);\n\n|;
 
close CONF;
 
}
 
 
sub save_member {
my ($self, $memberfile, $userspath) = @_;
 
my $newmember = 1;
# format dbconnect and dboptions string
map { $self->{$_} = lc $self->{$_} } qw(dbname host);
&dbconnect_vars($self, $self->{dbname});
$self->error('File locked!') if (-f "${memberfile}.LCK");
open(FH, ">${memberfile}.LCK") or $self->error("${memberfile}.LCK : $!");
close(FH);
open(CONF, "+<$memberfile") or $self->error("$memberfile : $!");
@config = <CONF>;
seek(CONF, 0, 0);
truncate(CONF, 0);
while ($line = shift @config) {
if ($line =~ /^\[$self->{login}\]/) {
$newmember = 0;
last;
}
print CONF $line;
}
 
# remove everything up to next login or EOF
while ($line = shift @config) {
last if ($line =~ /^\[/);
}
 
# this one is either the next login or EOF
print CONF $line;
 
while ($line = shift @config) {
print CONF $line;
}
 
print CONF qq|[$self->{login}]\n|;
if ((($self->{dbpasswd} ne $self->{old_dbpasswd}) || $newmember) && $self->{root}) {
$self->{dbpasswd} = pack 'u', $self->{dbpasswd};
chop $self->{dbpasswd};
}
if ($self->{password} ne $self->{old_password}) {
$self->{password} = crypt $self->{password}, substr($self->{login}, 0, 2) if $self->{password};
}
if ($self->{'root login'}) {
@config = ("password");
} else {
@config = &config_vars;
}
# replace \r\n with \n
$self->{address} =~ s/\r\n/\\n/g if $self->{address};
$self->{signature} =~ s/\r\n/\\n/g if $self->{signature};
 
foreach $key (sort @config) {
print CONF qq|$key=$self->{$key}\n|;
}
 
print CONF "\n";
close CONF;
unlink "${memberfile}.LCK";
# create conf file
$self->create_config("$userspath/$self->{login}.conf") unless $self->{'root login'};
}
 
 
sub config_vars {
my @conf = qw(acs address admin businessnumber charset company countrycode
currency dateformat dbconnect dbdriver dbhost dbport dboptions
dbname dbuser dbpasswd email fax name numberformat password
printer sid shippingpoint signature stylesheet tel templates
vclimit);
 
@conf;
 
}
 
 
sub error {
my ($self, $msg) = @_;
 
if ($ENV{HTTP_USER_AGENT}) {
print qq|Content-Type: text/html
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
 
<body bgcolor=ffffff>
 
<h2><font color=red>Error!</font></h2>
<p><b>$msg</b>|;
 
}
die "Error: $msg\n";
}
 
 
1;
 
/tags/release_2_0_6-2/SL/Inifile.pm
New file
0,0 → 1,87
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=====================================================================
#
# routines to retrieve / manipulate win ini style files
# ORDER is used to keep the elements in the order they appear in .ini
#
#=====================================================================
 
package Inifile;
 
 
sub new {
my ($type, $file, $level) = @_;
my $id = "";
my $skip;
$type = ref($self) || $self;
open FH, "$file" or Form->error("$file : $!");
 
while (<FH>) {
next if /^(#|;|\s)/;
last if /^\./;
 
chop;
 
# strip comments
s/\s*(#|;).*//g;
# remove any trailing whitespace
s/^\s*(.*?)\s*$/$1/;
 
if (/^\[/) {
s/(\[|\])//g;
 
$id = $_;
 
# if there is a level skip
if ($skip = ($id !~ /^$level/)) {
next;
}
 
push @{$self->{ORDER}}, $_;
next;
}
 
if (!$skip) {
# add key=value to $id
my ($key, $value) = split /=/, $_, 2;
$self->{$id}{$key} = $value;
}
 
}
close FH;
bless $self, $type;
}
 
 
1;
 
/tags/release_2_0_6-2/SL/RP.pm
New file
0,0 → 1,1381
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 1998-2002
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors: Benjamin Lee <benjaminlee@consultant.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
#
# backend code for reports
#
#======================================================================
 
package RP;
 
 
sub income_statement {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $last_period = 0;
my @categories = qw(I E);
my $category;
 
$form->{decimalplaces} *= 1;
 
&get_accounts($dbh, $last_period, $form->{fromdate}, $form->{todate}, $form, \@categories);
# if there are any compare dates
if ($form->{comparefromdate} || $form->{comparetodate}) {
$last_period = 1;
 
&get_accounts($dbh, $last_period, $form->{comparefromdate}, $form->{comparetodate}, $form, \@categories);
}
 
# disconnect
$dbh->disconnect;
 
 
# now we got $form->{I}{accno}{ }
# and $form->{E}{accno}{ }
my %account = ( 'I' => { 'label' => 'income',
'labels' => 'income',
'ml' => 1 },
'E' => { 'label' => 'expense',
'labels' => 'expenses',
'ml' => -1 }
);
my $str;
foreach $category (@categories) {
foreach $key (sort keys %{ $form->{$category} }) {
# push description onto array
$str = ($form->{l_heading}) ? $form->{padding} : "";
if ($form->{$category}{$key}{charttype} eq "A") {
$str .= ($form->{l_accno}) ? "$form->{$category}{$key}{accno} - $form->{$category}{$key}{description}" : "$form->{$category}{$key}{description}";
}
if ($form->{$category}{$key}{charttype} eq "H") {
if ($account{$category}{subtotal} && $form->{l_subtotal}) {
$dash = "- ";
push(@{$form->{"$account{$category}{label}_account"}}, "$str$form->{bold}$account{$category}{subdescription}$form->{endbold}");
push(@{$form->{"$account{$category}{labels}_this_period"}}, $form->format_amount($myconfig, $account{$category}{subthis} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
if ($last_period) {
push(@{$form->{"$account{$category}{labels}_last_period"}}, $form->format_amount($myconfig, $account{$category}{sublast} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
}
}
$str = "$form->{br}$form->{bold}$form->{$category}{$key}{description}$form->{endbold}";
 
$account{$category}{subthis} = $form->{$category}{$key}{this};
$account{$category}{sublast} = $form->{$category}{$key}{last};
$account{$category}{subdescription} = $form->{$category}{$key}{description};
$account{$category}{subtotal} = 1;
 
$form->{$category}{$key}{this} = 0;
$form->{$category}{$key}{last} = 0;
 
next unless $form->{l_heading};
 
$dash = " ";
}
push(@{$form->{"$account{$category}{label}_account"}}, $str);
if ($form->{$category}{$key}{charttype} eq 'A') {
$form->{"total_$account{$category}{labels}_this_period"} += $form->{$category}{$key}{this} * $account{$category}{ml};
$dash = "- ";
}
push(@{$form->{"$account{$category}{labels}_this_period"}}, $form->format_amount($myconfig, $form->{$category}{$key}{this} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
# add amount or - for last period
if ($last_period) {
$form->{"total_$account{$category}{labels}_last_period"} += $form->{$category}{$key}{last} * $account{$category}{ml};
 
push(@{$form->{"$account{$category}{labels}_last_period"}}, $form->format_amount($myconfig,$form->{$category}{$key}{last} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
}
}
 
$str = ($form->{l_heading}) ? $form->{padding} : "";
if ($account{$category}{subtotal} && $form->{l_subtotal}) {
push(@{$form->{"$account{$category}{label}_account"}}, "$str$form->{bold}$account{$category}{subdescription}$form->{endbold}");
push(@{$form->{"$account{$category}{labels}_this_period"}}, $form->format_amount($myconfig, $account{$category}{subthis} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
 
if ($last_period) {
push(@{$form->{"$account{$category}{labels}_last_period"}}, $form->format_amount($myconfig, $account{$category}{sublast} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
}
}
}
 
# totals for income and expenses
$form->{total_income_this_period} = $form->round_amount($form->{total_income_this_period}, $form->{decimalplaces});
$form->{total_expenses_this_period} = $form->round_amount($form->{total_expenses_this_period}, $form->{decimalplaces});
 
# total for income/loss
$form->{total_this_period} = $form->{total_income_this_period} - $form->{total_expenses_this_period};
if ($last_period) {
# total for income/loss
$form->{total_last_period} = $form->format_amount($myconfig, $form->{total_income_last_period} - $form->{total_expenses_last_period}, $form->{decimalplaces}, "- ");
# totals for income and expenses for last_period
$form->{total_income_last_period} = $form->format_amount($myconfig, $form->{total_income_last_period}, $form->{decimalplaces}, "- ");
$form->{total_expenses_last_period} = $form->format_amount($myconfig, $form->{total_expenses_last_period}, $form->{decimalplaces}, "- ");
 
}
 
 
$form->{total_income_this_period} = $form->format_amount($myconfig,$form->{total_income_this_period}, $form->{decimalplaces}, "- ");
$form->{total_expenses_this_period} = $form->format_amount($myconfig,$form->{total_expenses_this_period}, $form->{decimalplaces}, "- ");
$form->{total_this_period} = $form->format_amount($myconfig,$form->{total_this_period}, $form->{decimalplaces}, "- ");
 
}
 
 
 
sub balance_sheet {
my ($self, $myconfig, $form) = @_;
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $last_period = 0;
my @categories = qw(A L Q);
 
# if there are any dates construct a where
if ($form->{asofdate}) {
$form->{this_period} = "$form->{asofdate}";
$form->{period} = "$form->{asofdate}";
}
 
$form->{decimalplaces} *= 1;
 
&get_accounts($dbh, $last_period, "", $form->{asofdate}, $form, \@categories);
# if there are any compare dates
if ($form->{compareasofdate}) {
 
$last_period = 1;
&get_accounts($dbh, $last_period, "", $form->{compareasofdate}, $form, \@categories);
$form->{last_period} = "$form->{compareasofdate}";
 
}
 
# disconnect
$dbh->disconnect;
 
 
# now we got $form->{A}{accno}{ } assets
# and $form->{L}{accno}{ } liabilities
# and $form->{Q}{accno}{ } equity
# build asset accounts
my $str;
my $key;
my %account = ( 'A' => { 'label' => 'asset',
'labels' => 'assets',
'ml' => -1 },
'L' => { 'label' => 'liability',
'labels' => 'liabilities',
'ml' => 1 },
'Q' => { 'label' => 'equity',
'labels' => 'equities',
'ml' => 1 }
);
foreach $category (@categories) {
 
foreach $key (sort keys %{ $form->{$category} }) {
 
$str = ($form->{l_heading}) ? $form->{padding} : "";
 
if ($form->{$category}{$key}{charttype} eq "A") {
$str .= ($form->{l_accno}) ? "$form->{$category}{$key}{accno} - $form->{$category}{$key}{description}" : "$form->{$category}{$key}{description}";
}
if ($form->{$category}{$key}{charttype} eq "H") {
if ($account{$category}{subtotal} && $form->{l_subtotal}) {
$dash = "- ";
push(@{$form->{"$account{$category}{label}_account"}}, "$str$form->{bold}$account{$category}{subdescription}$form->{endbold}");
push(@{$form->{"$account{$category}{label}_this_period"}}, $form->format_amount($myconfig, $account{$category}{subthis} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
if ($last_period) {
push(@{$form->{"$account{$category}{label}_last_period"}}, $form->format_amount($myconfig, $account{$category}{sublast} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
}
}
 
$str = "$form->{bold}$form->{$category}{$key}{description}$form->{endbold}";
$account{$category}{subthis} = $form->{$category}{$key}{this};
$account{$category}{sublast} = $form->{$category}{$key}{last};
$account{$category}{subdescription} = $form->{$category}{$key}{description};
$account{$category}{subtotal} = 1;
$form->{$category}{$key}{this} = 0;
$form->{$category}{$key}{last} = 0;
 
next unless $form->{l_heading};
 
$dash = " ";
}
# push description onto array
push(@{$form->{"$account{$category}{label}_account"}}, $str);
if ($form->{$category}{$key}{charttype} eq 'A') {
$form->{"total_$account{$category}{labels}_this_period"} += $form->{$category}{$key}{this} * $account{$category}{ml};
$dash = "- ";
}
 
push(@{$form->{"$account{$category}{label}_this_period"}}, $form->format_amount($myconfig, $form->{$category}{$key}{this} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
if ($last_period) {
$form->{"total_$account{$category}{labels}_last_period"} += $form->{$category}{$key}{last} * $account{$category}{ml};
 
push(@{$form->{"$account{$category}{label}_last_period"}}, $form->format_amount($myconfig, $form->{$category}{$key}{last} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
}
}
 
$str = ($form->{l_heading}) ? $form->{padding} : "";
if ($account{$category}{subtotal} && $form->{l_subtotal}) {
push(@{$form->{"$account{$category}{label}_account"}}, "$str$form->{bold}$account{$category}{subdescription}$form->{endbold}");
push(@{$form->{"$account{$category}{label}_this_period"}}, $form->format_amount($myconfig, $account{$category}{subthis} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
if ($last_period) {
push(@{$form->{"$account{$category}{label}_last_period"}}, $form->format_amount($myconfig, $account{$category}{sublast} * $account{$category}{ml}, $form->{decimalplaces}, $dash));
}
}
 
}
 
# totals for assets, liabilities
$form->{total_assets_this_period} = $form->round_amount($form->{total_assets_this_period}, $form->{decimalplaces});
$form->{total_liabilities_this_period} = $form->round_amount($form->{total_liabilities_this_period}, $form->{decimalplaces});
 
# calculate retained earnings
$form->{earnings_this_period} = $form->{total_assets_this_period} - $form->{total_liabilities_this_period} - $form->{total_equity_this_period};
 
push(@{$form->{equity_this_period}}, $form->format_amount($myconfig, $form->{earnings_this_period}, $form->{decimalplaces}, "- "));
$form->{total_equity_this_period} = $form->round_amount($form->{total_equity_this_period} + $form->{earnings_this_period}, $form->{decimalplaces});
# add liability + equity
$form->{total_this_period} = $form->format_amount($myconfig, $form->{total_liabilities_this_period} + $form->{total_equity_this_period}, $form->{decimalplaces}, "- ");
 
 
if ($last_period) {
# totals for assets, liabilities
$form->{total_assets_last_period} = $form->round_amount($form->{total_assets_last_period}, $form->{decimalplaces});
$form->{total_liabilities_last_period} = $form->round_amount($form->{total_liabilities_last_period}, $form->{decimalplaces});
 
# calculate retained earnings
$form->{earnings_last_period} = $form->{total_assets_last_period} - $form->{total_liabilities_last_period} - $form->{total_equity_last_period};
 
push(@{$form->{equity_last_period}}, $form->format_amount($myconfig,$form->{earnings_last_period}, $form->{decimalplaces}, "- "));
$form->{total_equity_last_period} = $form->round_amount($form->{total_equity_last_period} + $form->{earnings_last_period}, $form->{decimalplaces});
 
# add liability + equity
$form->{total_last_period} = $form->format_amount($myconfig, $form->{total_liabilities_last_period} + $form->{total_equity_last_period}, $form->{decimalplaces}, "- ");
 
}
 
$form->{total_liabilities_last_period} = $form->format_amount($myconfig, $form->{total_liabilities_last_period}, $form->{decimalplaces}, "- ") if ($form->{total_liabilities_last_period} != 0);
$form->{total_equity_last_period} = $form->format_amount($myconfig, $form->{total_equity_last_period}, $form->{decimalplaces}, "- ") if ($form->{total_equity_last_period} != 0);
$form->{total_assets_last_period} = $form->format_amount($myconfig, $form->{total_assets_last_period}, $form->{decimalplaces}, "- ") if ($form->{total_assets_last_period} != 0);
$form->{total_assets_this_period} = $form->format_amount($myconfig, $form->{total_assets_this_period}, $form->{decimalplaces}, "- ");
$form->{total_liabilities_this_period} = $form->format_amount($myconfig, $form->{total_liabilities_this_period}, $form->{decimalplaces}, "- ");
$form->{total_equity_this_period} = $form->format_amount($myconfig, $form->{total_equity_this_period}, $form->{decimalplaces}, "- ");
}
 
 
 
sub get_accounts {
my ($dbh, $last_period, $fromdate, $todate, $form, $categories) = @_;
 
my ($null, $department_id) = split /--/, $form->{department};
my $query;
my $dpt_where;
my $dpt_join;
my $where = "WHERE 1 = 1";
my $subwhere;
my $item;
my $category = "AND (";
foreach $item (@{ $categories }) {
$category .= qq|c.category = '$item' OR |;
}
$category =~ s/OR $/\)/;
 
 
# get headings
$query = qq|SELECT accno, description, category
FROM chart c
WHERE c.charttype = 'H'
$category
ORDER by c.accno|;
 
if ($form->{accounttype} eq 'gifi')
{
$query = qq|SELECT g.accno, g.description, c.category
FROM gifi g
JOIN chart c ON (c.gifi_accno = g.accno)
WHERE c.charttype = 'H'
$category
ORDER BY g.accno|;
}
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my @headingaccounts = ();
while ($ref = $sth->fetchrow_hashref(NAME_lc))
{
$form->{$ref->{category}}{$ref->{accno}}{description} = "$ref->{description}";
$form->{$ref->{category}}{$ref->{accno}}{charttype} = "H";
$form->{$ref->{category}}{$ref->{accno}}{accno} = $ref->{accno};
push @headingaccounts, $ref->{accno};
}
 
$sth->finish;
 
 
$where .= " AND ac.transdate >= '$fromdate'" if $fromdate;
 
if ($todate) {
$where .= " AND ac.transdate <= '$todate'";
$subwhere = " AND transdate <= '$todate'";
}
 
if ($department_id)
{
$dpt_join = qq|
JOIN department t ON (a.department_id = t.id)
|;
$dpt_where = qq|
AND t.id = $department_id
|;
}
 
if ($form->{project_id})
{
$project = qq|
AND ac.project_id = $form->{project_id}
|;
}
 
 
if ($form->{accounttype} eq 'gifi')
{
if ($form->{method} eq 'cash')
{
 
$query = qq|
SELECT g.accno, sum(ac.amount) AS amount,
g.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN ar a ON (a.id = ac.trans_id)
JOIN gifi g ON (g.accno = c.gifi_accno)
$dpt_join
$where
$dpt_where
$category
AND ac.trans_id IN
(
SELECT trans_id
FROM acc_trans
JOIN chart ON (chart_id = id)
WHERE link LIKE '%AR_paid%'
$subwhere
)
$project
GROUP BY g.accno, g.description, c.category
UNION
SELECT '' AS accno, SUM(ac.amount) AS amount,
'' AS description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN ar a ON (a.id = ac.trans_id)
$dpt_join
$where
$dpt_where
$category
AND c.gifi_accno = ''
AND ac.trans_id IN
(
SELECT trans_id
FROM acc_trans
JOIN chart ON (chart_id = id)
WHERE link LIKE '%AR_paid%'
$subwhere
)
$project
GROUP BY c.category
 
UNION
 
SELECT g.accno, sum(ac.amount) AS amount,
g.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN ap a ON (a.id = ac.trans_id)
JOIN gifi g ON (g.accno = c.gifi_accno)
$dpt_join
$where
$dpt_where
$category
AND ac.trans_id IN
(
SELECT trans_id
FROM acc_trans
JOIN chart ON (chart_id = id)
WHERE link LIKE '%AP_paid%'
$subwhere
)
$project
GROUP BY g.accno, g.description, c.category
UNION
SELECT '' AS accno, SUM(ac.amount) AS amount,
'' AS description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN ap a ON (a.id = ac.trans_id)
$dpt_join
$where
$dpt_where
$category
AND c.gifi_accno = ''
AND ac.trans_id IN
(
SELECT trans_id
FROM acc_trans
JOIN chart ON (chart_id = id)
WHERE link LIKE '%AP_paid%'
$subwhere
)
$project
GROUP BY c.category
 
UNION
 
-- add gl
SELECT g.accno, sum(ac.amount) AS amount,
g.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN gifi g ON (g.accno = c.gifi_accno)
JOIN gl a ON (a.id = ac.trans_id)
$dpt_join
$where
$dpt_where
$category
AND NOT (c.link = 'AR' OR c.link = 'AP')
$project
GROUP BY g.accno, g.description, c.category
UNION
SELECT '' AS accno, SUM(ac.amount) AS amount,
'' AS description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN gl a ON (a.id = ac.trans_id)
$dpt_join
$where
$dpt_where
$category
AND c.gifi_accno = ''
AND NOT (c.link = 'AR' OR c.link = 'AP')
$project
GROUP BY c.category
|;
 
} else {
 
if ($department_id)
{
$dpt_join = qq|
JOIN dpt_trans t ON (t.trans_id = ac.trans_id)
|;
$dpt_where = qq|
AND t.department_id = $department_id
|;
 
}
 
$query = qq|
SELECT g.accno, SUM(ac.amount) AS amount,
g.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN gifi g ON (c.gifi_accno = g.accno)
$dpt_join
$where
$dpt_from
$category
$project
GROUP BY g.accno, g.description, c.category
UNION
SELECT '' AS accno, SUM(ac.amount) AS amount,
'' AS description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
$dpt_join
$where
$dpt_from
$category
AND c.gifi_accno = ''
$project
GROUP by c.category
|;
}
} else {
 
if ($form->{method} eq 'cash')
{
 
 
$query = qq|
SELECT c.accno, sum(ac.amount) AS amount,
c.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN ar a ON (a.id = ac.trans_id)
$dpt_join
$where
$dpt_where
$category
AND ac.trans_id IN
(
SELECT trans_id
FROM acc_trans
JOIN chart ON (chart_id = id)
WHERE link LIKE '%AR_paid%'
$subwhere
)
$project
GROUP BY c.accno, c.description, c.category
UNION
SELECT c.accno, sum(ac.amount) AS amount,
c.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN ap a ON (a.id = ac.trans_id)
$dpt_join
$where
$dpt_where
$category
AND ac.trans_id IN
(
SELECT trans_id
FROM acc_trans
JOIN chart ON (chart_id = id)
WHERE link LIKE '%AP_paid%'
$subwhere
)
$project
GROUP BY c.accno, c.description, c.category
UNION
 
SELECT c.accno, sum(ac.amount) AS amount,
c.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
JOIN gl a ON (a.id = ac.trans_id)
$dpt_join
$where
$dpt_from
$category
AND NOT (c.link = 'AR' OR c.link = 'AP')
$project
GROUP BY c.accno, c.description, c.category
|;
} else {
if ($department_id)
{
$dpt_join = qq|
JOIN dpt_trans t ON (t.trans_id = ac.trans_id)
|;
$dpt_where = qq|
AND t.department_id = $department_id
|;
}
 
$query = qq|
SELECT c.accno, sum(ac.amount) AS amount,
c.description, c.category
FROM acc_trans ac
JOIN chart c ON (c.id = ac.chart_id)
$dpt_join
$where
$dpt_where
$category
$project
GROUP BY c.accno, c.description, c.category
|;
 
}
}
 
 
my @accno;
my $accno;
my $ref;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ($ref = $sth->fetchrow_hashref(NAME_lc))
{
 
if ($ref->{category} eq 'C') {
$ref->{category} = 'A';
}
# get last heading account
@accno = grep { $_ le "$ref->{accno}" } @headingaccounts;
$accno = pop @accno;
if ($accno) {
if ($last_period)
{
$form->{$ref->{category}}{$accno}{last} += $ref->{amount};
} else {
$form->{$ref->{category}}{$accno}{this} += $ref->{amount};
}
}
$form->{$ref->{category}}{$ref->{accno}}{accno} = $ref->{accno};
$form->{$ref->{category}}{$ref->{accno}}{description} = $ref->{description};
$form->{$ref->{category}}{$ref->{accno}}{charttype} = "A";
if ($last_period)
{
$form->{$ref->{category}}{$ref->{accno}}{last} += $ref->{amount};
} else {
$form->{$ref->{category}}{$ref->{accno}}{this} += $ref->{amount};
}
}
$sth->finish;
 
# remove accounts with zero balance
foreach $category (@{ $categories }) {
foreach $accno (keys %{ $form->{$category} }) {
$form->{$category}{$accno}{last} = $form->round_amount($form->{$category}{$accno}{last}, $form->{decimalplaces});
$form->{$category}{$accno}{this} = $form->round_amount($form->{$category}{$accno}{this}, $form->{decimalplaces});
 
delete $form->{$category}{$accno} if ($form->{$category}{$accno}{this} == 0 && $form->{$category}{$accno}{last} == 0);
}
}
 
}
 
 
 
sub trial_balance_details {
my ($self, $myconfig, $form) = @_;
 
my $dbh = $form->dbconnect($myconfig);
 
my ($query, $sth);
my %balance = ();
my $ref = ();
my ($null, $department_id) = split /--/, $form->{department};
 
my $where = "WHERE 1 = 1";
 
if ($department_id) {
$dpt_join = qq|
JOIN dpt_trans t ON (a.trans_id = t.trans_id)
|;
$where .= qq|
AND t.department_id = $department_id
|;
}
if ($form->{project_id}) {
$where .= qq|
AND a.project_id = $form->{project_id}
|;
}
# get beginning balances
if ($form->{fromdate}) {
 
if ($form->{accounttype} eq 'gifi') {
$query = qq|SELECT g.accno, c.category, SUM(a.amount) AS amount
FROM acc_trans a
JOIN chart c ON (a.chart_id = c.id)
JOIN gifi g ON (c.gifi_accno = g.accno)
$dpt_join
$where
AND a.transdate < '$form->{fromdate}'
GROUP BY g.accno, c.category
|;
} else {
$query = qq|SELECT c.accno, c.category, SUM(a.amount) AS amount
FROM acc_trans a
JOIN chart c ON (a.chart_id = c.id)
$dpt_join
$where
AND a.transdate < '$form->{fromdate}'
GROUP BY c.accno, c.category|;
}
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
$balance{$ref->{accno}} = $ref->{amount};
}
$sth->finish;
 
}
 
 
# get headings
$query = qq|SELECT c.accno, c.description, c.category
FROM chart c
WHERE c.charttype = 'H'
ORDER by c.accno|;
 
if ($form->{accounttype} eq 'gifi')
{
$query = qq|SELECT g.accno, g.description, c.category
FROM gifi g
JOIN chart c ON (c.gifi_accno = g.accno)
WHERE c.charttype = 'H'
ORDER BY g.accno|;
}
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
my @headingaccounts = ();
while ($ref = $sth->fetchrow_hashref(NAME_lc))
{
$trb{$ref->{accno}}{description} = $ref->{description};
$trb{$ref->{accno}}{charttype} = 'H';
$trb{$ref->{accno}}{category} = ($ref->{category} eq 'C') ? 'A' : $ref->{category};
push @headingaccounts, $ref->{accno};
}
 
$sth->finish;
 
 
if ($form->{fromdate} || $form->{todate}) {
if ($form->{fromdate}) {
$where .= " AND a.transdate >= '$form->{fromdate}'";
}
if ($form->{todate}) {
$where .= " AND a.transdate <= '$form->{todate}'";
}
}
 
 
if ($form->{accounttype} eq 'gifi') {
 
$query = qq|SELECT g.accno, g.description, c.category,
SUM(a.amount) AS amount
FROM acc_trans a
JOIN chart c ON (c.id = a.chart_id)
JOIN gifi g ON (c.gifi_accno = g.accno)
$dpt_join
$where
GROUP BY g.accno, g.description, c.category
UNION
 
SELECT '' AS accno, '' AS description, c.category,
SUM(a.amount) AS amount
FROM acc_trans a
JOIN chart c ON (c.id = a.chart_id)
$dpt_join
$where
AND c.gifi_accno = ''
GROUP BY c.category
ORDER BY accno|;
} else {
 
$query = qq|SELECT c.accno, c.description, c.category,
SUM(a.amount) AS amount
FROM acc_trans a
JOIN chart c ON (c.id = a.chart_id)
$dpt_join
$where
GROUP BY c.accno, c.description, c.category
ORDER BY accno|;
 
}
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
 
# prepare query for each account
$query = qq|SELECT (SELECT SUM(a.amount) * -1
FROM acc_trans a
JOIN chart c ON (c.id = a.chart_id)
$dpt_join
$where
AND a.amount < 0
AND c.accno = ?) AS debit,
(SELECT SUM(a.amount)
FROM acc_trans a
JOIN chart c ON (c.id = a.chart_id)
$dpt_join
$where
AND a.amount > 0
AND c.accno = ?) AS credit
|;
 
if ($form->{accounttype} eq 'gifi') {
 
$query = qq|SELECT (SELECT SUM(a.amount) * -1
FROM acc_trans a
JOIN chart c ON (c.id = a.chart_id)
$dpt_join
$where
AND a.amount < 0
AND c.gifi_accno = ?) AS debit,
(SELECT SUM(a.amount)
FROM acc_trans a
JOIN chart c ON (c.id = a.chart_id)
$dpt_join
$where
AND a.amount > 0
AND c.gifi_accno = ?) AS credit|;
}
$drcr = $dbh->prepare($query);
my $trb = ();
# calculate the debit and credit in the period
while ($ref = $sth->fetchrow_hashref(NAME_lc)) {
$trb{$ref->{accno}}{description} = $ref->{description};
$trb{$ref->{accno}}{charttype} = 'A';
$trb{$ref->{accno}}{category} = $ref->{category};
$trb{$ref->{accno}}{amount} += $ref->{amount};
 
}
$sth->finish;
 
my ($debit, $credit);
foreach my $accno (sort keys %trb) {
$ref = ();
 
$ref->{accno} = $accno;
map { $ref->{$_} = $trb{$accno}{$_} } qw(description category charttype amount);
$ref->{balance} = $form->round_amount($balance{$ref->{accno}}, 2);
 
if ($trb{$accno}{charttype} eq 'A') {
# get DR/CR
$drcr->execute($ref->{accno}, $ref->{accno}) || $form->dberror($query);
($debit, $credit) = (0,0);
while (($debit, $credit) = $drcr->fetchrow_array) {
$ref->{debit} += $debit;
$ref->{credit} += $credit;
}
$drcr->finish;
 
$ref->{debit} = $form->round_amount($ref->{debit}, 2);
$ref->{credit} = $form->round_amount($ref->{credit}, 2);
}
 
 
# add subtotal
@accno = grep { $_ le "$ref->{accno}" } @headingaccounts;
$accno = pop @accno;
if ($accno) {
$trb{$accno}{debit} += $ref->{debit};
$trb{$accno}{credit} += $ref->{credit};
}
push @{ $form->{TB} }, $ref;
}
 
$dbh->disconnect;
 
# debits and credits for headings
foreach $accno (@headingaccounts) {
foreach $ref (@{ $form->{TB} }) {
if ($accno eq $ref->{accno}) {
$ref->{debit} = $trb{$accno}{debit};
$ref->{credit} = $trb{$accno}{credit};
}
}
}
 
}
 
 
 
sub aging {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
my $invoice = ($form->{arap} eq 'ar') ? 'is' : 'ir';
$form->{todate} = $form->current_date($myconfig) unless ($form->{todate});
 
my $where = "1 = 1";
my $name;
 
if ($form->{"$form->{ct}_id"}) {
$where .= qq| AND ct.id = $form->{"$form->{ct}_id"}|;
} else {
if ($form->{$form->{ct}}) {
$name = $form->like(lc $form->{$form->{ct}});
$where .= qq| AND lower(ct.name) LIKE '$name'| if $form->{$form->{ct}};
}
}
 
# select outstanding vendors or customers, depends on $ct
my $query = qq|SELECT DISTINCT ct.id, ct.name
FROM $form->{ct} ct, $form->{arap} a
WHERE $where
AND a.$form->{ct}_id = ct.id
AND a.paid != a.amount
AND (a.transdate <= date '$form->{todate}')
ORDER BY ct.name|;
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror;
 
my $buysell = ($form->{arap} eq 'ar') ? 'buy' : 'sell';
# for each company that has some stuff outstanding
while ( my ($id) = $sth->fetchrow_array ) {
$query = qq|
 
-- between 0-30 days
 
SELECT $form->{ct}.id AS ctid, $form->{ct}.name,
addr1, addr2, addr3, addr4, contact,
phone as customerphone, fax as customerfax, $form->{ct}number,
"invnumber", "transdate",
(amount - paid) as "c0", 0.00 as "c30", 0.00 as "c60", 0.00 as "c90",
"duedate", invoice, $form->{arap}.id,
(SELECT $buysell FROM exchangerate
WHERE $form->{arap}.curr = exchangerate.curr
AND exchangerate.transdate = $form->{arap}.transdate) AS exchangerate
FROM $form->{arap}, $form->{ct}
WHERE paid != amount
AND $form->{arap}.$form->{ct}_id = $form->{ct}.id
AND $form->{ct}.id = $id
AND (
transdate <= (date '$form->{todate}' - interval '0 days')
AND transdate >= (date '$form->{todate}' - interval '30 days')
)
UNION
 
-- between 31-60 days
 
SELECT $form->{ct}.id AS ctid, $form->{ct}.name,
addr1, addr2, addr3, addr4, contact,
phone as customerphone, fax as customerfax, $form->{ct}number,
"invnumber", "transdate",
0.00 as "c0", (amount - paid) as "c30", 0.00 as "c60", 0.00 as "c90",
"duedate", invoice, $form->{arap}.id,
(SELECT $buysell FROM exchangerate
WHERE $form->{arap}.curr = exchangerate.curr
AND exchangerate.transdate = $form->{arap}.transdate) AS exchangerate
FROM $form->{arap}, $form->{ct}
WHERE paid != amount
AND $form->{arap}.$form->{ct}_id = $form->{ct}.id
AND $form->{ct}.id = $id
AND (
transdate < (date '$form->{todate}' - interval '30 days')
AND transdate >= (date '$form->{todate}' - interval '60 days')
)
 
UNION
-- between 61-90 days
 
SELECT $form->{ct}.id AS ctid, $form->{ct}.name,
addr1, addr2, addr3, addr4, contact,
phone as customerphone, fax as customerfax, $form->{ct}number,
"invnumber", "transdate",
0.00 as "c0", 0.00 as "c30", (amount - paid) as "c60", 0.00 as "c90",
"duedate", invoice, $form->{arap}.id,
(SELECT $buysell FROM exchangerate
WHERE $form->{arap}.curr = exchangerate.curr
AND exchangerate.transdate = $form->{arap}.transdate) AS exchangerate
FROM $form->{arap}, $form->{ct}
WHERE paid != amount
AND $form->{arap}.$form->{ct}_id = $form->{ct}.id
AND $form->{ct}.id = $id
AND (
transdate < (date '$form->{todate}' - interval '60 days')
AND transdate >= (date '$form->{todate}' - interval '90 days')
)
 
UNION
-- over 90 days
 
SELECT $form->{ct}.id AS ctid, $form->{ct}.name,
addr1, addr2, addr3, addr4, contact,
phone as customerphone, fax as customerfax, $form->{ct}number,
"invnumber", "transdate",
0.00 as "c0", 0.00 as "c30", 0.00 as "c60", (amount - paid) as "c90",
"duedate", invoice, $form->{arap}.id,
(SELECT $buysell FROM exchangerate
WHERE $form->{arap}.curr = exchangerate.curr
AND exchangerate.transdate = $form->{arap}.transdate) AS exchangerate
FROM $form->{arap}, $form->{ct}
WHERE paid != amount
AND $form->{arap}.$form->{ct}_id = $form->{ct}.id
AND $form->{ct}.id = $id
AND transdate < (date '$form->{todate}' - interval '90 days')
 
ORDER BY
ctid, invnumber, transdate
|;
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror;
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
$ref->{module} = ($ref->{invoice}) ? $invoice : $form->{arap};
$ref->{exchangerate} = 1 unless $ref->{exchangerate};
push @{ $form->{AG} }, $ref;
}
$sth->finish;
 
}
 
$sth->finish;
# disconnect
$dbh->disconnect;
 
}
 
 
sub get_customer {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT name, email, cc, bcc
FROM $form->{ct} ct
WHERE ct.id = $form->{"$form->{ct}_id"}|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror;
 
($form->{$form->{ct}}, $form->{email}, $form->{cc}, $form->{bcc}) = $sth->fetchrow_array;
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub get_taxaccounts {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
# get tax accounts
my $query = qq|SELECT accno, description
FROM chart
WHERE link LIKE '%CT_tax%'
ORDER BY accno|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror;
 
while ( my ($accno, $description) = $sth->fetchrow_array ) {
push @{ $form->{taxaccounts} }, "$accno--$description";
}
$sth->finish;
 
# get gifi tax accounts
my $query = qq|SELECT DISTINCT ON (g.accno) g.accno, g.description
FROM gifi g, chart c
WHERE g.accno = c.gifi_accno
AND c.link LIKE '%CT_tax%'
ORDER BY accno|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror;
 
while ( my ($accno, $description) = $sth->fetchrow_array ) {
push @{ $form->{gifi_taxaccounts} }, "$accno--$description";
}
$sth->finish;
 
$dbh->disconnect;
 
}
 
 
 
sub tax_report {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
# build WHERE
my $where = qq|WHERE ac.trans_id = a.id
AND ac.chart_id = ch.id|;
 
if ($form->{accno} =~ /^gifi_/) {
my ($null, $accno) = split /_/, $form->{accno};
$where .= qq| AND ch.gifi_accno = '$accno'|;
} else {
$where .= qq| AND ch.accno = '$form->{accno}'|;
}
 
my $table;
if ($form->{db} eq 'ar') {
$where .= " AND n.id = a.customer_id";
$table = "customer";
}
if ($form->{db} eq 'ap') {
$where .= " AND n.id = a.vendor_id";
$table = "vendor";
}
 
my $transdate = ($form->{cashbased}) ? "a.datepaid" : "ac.transdate";
if ($form->{cashbased}) {
$where .= " AND a.amount = a.paid";
}
 
# if there are any dates construct a where
if ($form->{fromdate} || $form->{todate}) {
if ($form->{fromdate}) {
$where .= " AND $transdate >= '$form->{fromdate}'";
}
if ($form->{todate}) {
$where .= " AND $transdate <= '$form->{todate}'";
}
}
my $query = qq|SELECT a.id, a.invoice, $transdate AS transdate, a.invnumber,
n.name, a.netamount,|;
my $sortorder = join ', ', $form->sort_columns(qw(transdate invnumber name));
$sortorder = $form->{sort} unless $sortorder;
if ($form->{db} eq 'ar') {
$query .= " ac.amount AS tax";
}
if ($form->{db} eq 'ap') {
$query .= " ac.amount * -1 AS tax";
}
 
$query .= qq|
FROM acc_trans ac, "$form->{db}" a, "$table" n, chart ch
$where
ORDER by $sortorder|;
 
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while ( my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{TR} }, $ref;
}
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub paymentaccounts {
my ($self, $myconfig, $form) = @_;
# connect to database, turn AutoCommit off
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $arap = uc $form->{db};
$arap .= "_paid";
# get A(R|P)_paid accounts
my $query = qq|SELECT accno, description
FROM chart
WHERE link LIKE '%$arap%'|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{PR} }, $ref;
}
 
$sth->finish;
$dbh->disconnect;
 
}
 
sub payments {
my ($self, $myconfig, $form) = @_;
 
# connect to database, turn AutoCommit off
my $dbh = $form->dbconnect_noauto($myconfig);
 
my $ml = 1;
if ($form->{db} eq 'ar') {
$table = 'customer';
$ml = -1;
}
if ($form->{db} eq 'ap') {
$table = 'vendor';
}
my ($query, $sth);
# cycle through each id
foreach my $accno (split(/ /, $form->{paymentaccounts})) {
 
$query = qq|SELECT id, accno, description
FROM chart
WHERE accno = '$accno'|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $ref = $sth->fetchrow_hashref(NAME_lc);
push @{ $form->{PR} }, $ref;
$sth->finish;
 
$query = qq|SELECT c.name, a.invnumber, a.ordnumber,
ac.transdate,
ac.amount * $ml AS paid, ac.source, a.invoice, a.id,
'$form->{db}' AS module
FROM $table c, acc_trans ac, $form->{db} a
WHERE c.id = a.${table}_id
AND ac.trans_id = a.id
AND ac.chart_id = $ref->{id}|;
$query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate};
$query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate};
 
$query .= qq|
UNION
SELECT g.description, g.reference, NULL AS ordnumber,
ac.transdate,
ac.amount * $ml AS paid, ac.source, '0' as invoice, g.id,
'gl' AS module
FROM gl g, acc_trans ac
WHERE g.id = ac.trans_id
AND ac.chart_id = $ref->{id}
AND (ac.amount * $ml) > 0
|;
 
$query .= " AND ac.transdate >= '$form->{fromdate}'" if $form->{fromdate};
$query .= " AND ac.transdate <= '$form->{todate}'" if $form->{todate};
 
 
my $sortorder = join ', ', $form->sort_columns(qw(name invnumber ordnumber transdate source));
$query .= " ORDER BY $sortorder";
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $pr = $sth->fetchrow_hashref(NAME_lc)) {
push @{ $form->{$ref->{id}} }, $pr;
}
$sth->finish;
 
}
$dbh->disconnect;
}
 
 
1;
 
 
/tags/release_2_0_6-2/SL/CA.pm
New file
0,0 → 1,262
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#======================================================================
# chart of accounts
#
# CHANGE LOG:
# DS. 2000-07-04 Created
#
#======================================================================
 
 
package CA;
 
 
sub all_accounts {
my ($self, $myconfig, $form) = @_;
 
my $amount = ();
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
my $query = qq|SELECT accno,
SUM(acc_trans.amount) AS amount
FROM chart, acc_trans
WHERE chart.id = acc_trans.chart_id
GROUP BY accno|;
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ref = $sth->fetchrow_hashref(NAME_lc)) {
$amount{$ref->{accno}} = $ref->{amount}
}
$sth->finish;
$query = qq|SELECT accno, description
FROM gifi|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my $gifi = ();
while (my ($accno, $description) = $sth->fetchrow_array) {
$gifi{$accno} = $description;
}
$sth->finish;
 
$query = qq|SELECT c.id, c.accno, c.description, c.charttype, c.gifi_accno,
c.category, c.link
FROM chart c
ORDER BY accno|;
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
while (my $ca = $sth->fetchrow_hashref(NAME_lc)) {
$ca->{amount} = $amount{$ca->{accno}};
$ca->{gifi_description} = $gifi{$ca->{gifi_accno}};
if ($ca->{amount} < 0) {
$ca->{debit} = $ca->{amount} * -1;
} else {
$ca->{credit} = $ca->{amount};
}
push @{ $form->{CA} }, $ca;
}
 
$sth->finish;
$dbh->disconnect;
 
}
 
 
sub all_transactions {
my ($self, $myconfig, $form) = @_;
 
# connect to database
my $dbh = $form->dbconnect($myconfig);
 
# get chart_id
my $query = qq|SELECT id FROM chart
WHERE accno = '$form->{accno}'|;
if ($form->{accounttype} eq 'gifi') {
$query = qq|SELECT id FROM chart
WHERE gifi_accno = '$form->{gifi_accno}'|;
}
my $sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
my @id = ();
while (my ($id) = $sth->fetchrow_array) {
push @id, $id;
}
 
$sth->finish;
 
my $where = '1 = 1';
# build WHERE clause from dates if any
if ($form->{fromdate}) {
$where .= " AND ac.transdate >= '$form->{fromdate}'";
}
if ($form->{todate}) {
$where .= " AND ac.transdate <= '$form->{todate}'";
}
 
my $sortorder = join ', ', $form->sort_columns(qw(transdate reference description));
my $false = ($myconfig->{dbdriver} eq 'Pg') ? FALSE : q|'0'|;
# Oracle workaround, use ordinal positions
my %ordinal = ( transdate => 4,
reference => 2,
description => 3 );
map { $sortorder =~ s/$_/$ordinal{$_}/ } keys %ordinal;
 
if ($form->{accno}) {
# get category for account
$query = qq|SELECT category
FROM chart
WHERE accno = '$form->{accno}'|;
$sth = $dbh->prepare($query);
 
$sth->execute || $form->dberror($query);
($form->{category}) = $sth->fetchrow_array;
$sth->finish;
if ($form->{fromdate}) {
# get beginning balance
$query = qq|SELECT SUM(ac.amount)
FROM acc_trans ac, chart c
WHERE ac.chart_id = c.id
AND c.accno = '$form->{accno}'
AND ac.transdate < date '$form->{fromdate}'
|;
$sth = $dbh->prepare($query);
 
$sth->execute || $form->dberror($query);
($form->{balance}) = $sth->fetchrow_array;
$sth->finish;
}
}
if ($form->{accounttype} eq 'gifi' && $form->{gifi_accno}) {
# get category for account
$query = qq|SELECT category
FROM chart
WHERE gifi_accno = '$form->{gifi_accno}'|;
$sth = $dbh->prepare($query);
 
$sth->execute || $form->dberror($query);
($form->{category}) = $sth->fetchrow_array;
$sth->finish;
if ($form->{fromdate}) {
# get beginning balance
$query = qq|SELECT SUM(ac.amount)
FROM acc_trans ac, chart c
WHERE ac.chart_id = c.id
AND c.gifi_accno = '$form->{gifi_accno}'
AND ac.transdate < date '$form->{fromdate}'
|;
$sth = $dbh->prepare($query);
 
$sth->execute || $form->dberror($query);
($form->{balance}) = $sth->fetchrow_array;
$sth->finish;
}
}
$query = "";
foreach my $id (@id) {
# get all transactions
$query .= qq|
SELECT g.id, g.reference, g.description, ac.transdate,
$false AS invoice,
ac.amount, 'gl' as charttype
FROM gl g, acc_trans ac
WHERE $where
AND ac.chart_id = $id
AND ac.trans_id = g.id
UNION ALL
SELECT a.id, a.invnumber, c.name, ac.transdate,
a.invoice,
ac.amount, 'ar' as charttype
FROM ar a, acc_trans ac, customer c
WHERE $where
AND ac.chart_id = $id
AND ac.trans_id = a.id
AND a.customer_id = c.id
UNION ALL
SELECT a.id, a.invnumber, v.name, ac.transdate,
a.invoice,
ac.amount, 'ap' as charttype
FROM ap a, acc_trans ac, vendor v
WHERE $where
AND ac.chart_id = $id
AND ac.trans_id = a.id
AND a.vendor_id = v.id
UNION ALL|;
}
 
$query =~ s/UNION ALL$//;
$query .= qq|
ORDER BY $sortorder|;
 
$sth = $dbh->prepare($query);
$sth->execute || $form->dberror($query);
 
while (my $ca = $sth->fetchrow_hashref(NAME_lc)) {
 
# gl
if ($ca->{charttype} eq "gl") {
$ca->{module} = "gl";
}
 
# ap
if ($ca->{charttype} eq "ap") {
$ca->{module} = ($ca->{invoice}) ? 'ir' : 'ap';
}
 
# ar
if ($ca->{charttype} eq "ar") {
$ca->{module} = ($ca->{invoice}) ? 'is' : 'ar';
}
 
if ($ca->{amount} < 0) {
$ca->{debit} = $ca->{amount} * -1;
$ca->{credit} = 0;
} else {
$ca->{credit} = $ca->{amount};
$ca->{debit} = 0;
}
 
push @{ $form->{CA} }, $ca;
 
}
$sth->finish;
$dbh->disconnect;
 
}
 
1;
 
/tags/release_2_0_6-2/SL/Num2text.pm
New file
0,0 → 1,162
#=====================================================================
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#=====================================================================
#
# this is the default code for the Check package
#
#=====================================================================
 
 
sub init {
my $self = shift;
 
%{ $self->{numbername} } =
(0 => 'Zero',
1 => 'One',
2 => 'Two',
3 => 'Three',
4 => 'Four',
5 => 'Five',
6 => 'Six',
7 => 'Seven',
8 => 'Eight',
9 => 'Nine',
10 => 'Ten',
11 => 'Eleven',
12 => 'Twelve',
13 => 'Thirteen',
14 => 'Fourteen',
15 => 'Fifteen',
16 => 'Sixteen',
17 => 'Seventeen',
18 => 'Eighteen',
19 => 'Nineteen',
20 => 'Twenty',
30 => 'Thirty',
40 => 'Forty',
50 => 'Fifty',
60 => 'Sixty',
70 => 'Seventy',
80 => 'Eighty',
90 => 'Ninety',
10**2 => 'Hundred',
10**3 => 'Thousand',
10**6 => 'Million',
10**9 => 'Billion',
10**12 => 'Trillion',
);
 
}
 
 
sub num2text {
my ($self, $amount) = @_;
 
return $self->{numbername}{0} unless $amount;
 
my @textnumber = ();
 
# split amount into chunks of 3
my @num = reverse split //, $amount;
my @numblock = ();
my @a;
my $i;
 
while (@num) {
@a = ();
for (1 .. 3) {
push @a, shift @num;
}
push @numblock, join / /, reverse @a;
}
while (@numblock) {
 
$i = $#numblock;
@num = split //, $numblock[$i];
if ($numblock[$i] == 0) {
pop @numblock;
next;
}
if ($numblock[$i] > 99) {
# the one from hundreds
push @textnumber, $self->{numbername}{$num[0]};
# add hundred designation
push @textnumber, $self->{numbername}{10**2};
 
# reduce numblock
$numblock[$i] -= $num[0] * 100;
}
$numblock[$i] *= 1;
if ($numblock[$i] > 9) {
# tens
push @textnumber, $self->format_ten($numblock[$i]);
} elsif ($numblock[$i] > 0) {
# ones
push @textnumber, $self->{numbername}{$numblock[$i]};
}
# add thousand, million
if ($i) {
$num = 10**($i * 3);
push @textnumber, $self->{numbername}{$num};
}
pop @numblock;
}
 
join ' ', @textnumber;
 
}
 
 
sub format_ten {
my ($self, $amount) = @_;
my $textnumber = "";
my @num = split //, $amount;
 
if ($amount > 20) {
$textnumber = $self->{numbername}{$num[0]*10};
$amount = $num[1];
} else {
$textnumber = $self->{numbername}{$amount};
$amount = 0;
}
 
$textnumber .= " ".$self->{numbername}{$amount} if $amount;
 
$textnumber;
}
 
 
1;
 
/tags/release_2_0_6-2/sql-ledger.png
New file
0,0 → 1,76
‰PNG

+òHA€8¦€6qJ³1JHðóKH0Jr‚ÜÈ
+´‡ r| ïpI‹µ£ ¤4'ØcâÌ(ñÏÄ("-Æ ò ˆr‰IKsrJáq @¾Èe@ „¢ŒA”>¥0Lÿÿ—]iýÕãõ%8Ä¼º5Q݀BÒ]bðç#ÕÇ=ˆ¨"!ÑæÜŽÇ£›±t)ÂÒo²R Ñà%€ÐÈÊÉ)Ä&È(ÀÃÎÎÂÂÎÎÎà 4€M„M„S”KäJAv `Àñ›ˆ(ì˜á ‰¨†G(Œ¼ M,2âx!@1 ¹OZZè>^ .¹‘G€ŸhfJ9ä  ˜6`òâG8l0|Á@DD¤‹E†Ձ¬’Àpgäeaâãc>&° AÄH®|`çÃ›E† ¬… ¤…WìB6!Qn˜ åĘÀ’0
+‰uõ‰Ëáq @1 d_I Na>qq9f_& ÙĸøдrsrJ‹€ÜÇ t0«Õuˆ} w +€(É$ 9 #Y`&Sqqq|î“ ¤lÆ!Ær;ÈO̐œ''Ît!0MIs¡å511!¨û˜À%3Ô  ‚†;Š ÁÆqðÉÃBPLTZ
+âq!@!9PŽ œzE$™Òą¼üŒ’\ܨáʅ`÷ۃ¥@áû
+êB61V¤‚NŽA‚¢DÔ:ĀT ðBRƒJý%ÎL7lœ2È¥‘8µ(+ƒ™†À¾bᑀäW  á&ʉ3É"HDU@ CùdÁãBËT@3Yxø9Y‘Í - qŸ –B•à”‹exi#ÎÄKRâL‚T-ŠVG1s0ȃPa³—8µ² òðq`¯v¡)â.n>„oIs @1 ‰ší0Jdf>`
+B$
+œÐ„0k9q1”’:x
+ x8€æNÀ.”€ÎÇaq¡8h"J‘‘‡‰iž©+ɉu„•OLHÅ°)€b@nwc5¨3¬›@%3R±.ƒ˜ÔvWЇp¤DÁÓºŒì ðcÆÖĖÄÖ§afâ”ÞBý @ yÆI€fåX‘†Œä¤X¹Ä@3´Â2(ãÑàyX/<íŠ<Æ qŸhež ˜ÔE`ÍQÔõ (7H#¨È…MýLŒ<ùk.VÐÊ`AŠ›2Ù/À‚:cjD@ڊàΰÎú
+ôпBðž,7hx!€>ˆIB:Ñ°T€Br ¯hþÜQåV¨MÀ@ŸñbFêåCœÈ
+^2¶…S´D€—ièt1N1iPÄC€ bbbÒÀ°Ë
+
+rÂô’YXd ½ð²A6Y!! ã@‹+€!1cjÍBzù<e
+‚’œ å¢¢\E@ç11 t{Ü<üD ˜F€BÊ$L@óÀ“Ñ@7J Ôòò°È`÷òáýSE$…@“Œ"B =2|ÈÉÔaå^^^2aËà€
+Ï0ài`úGMµ $Ë^£€dH(@”„hnÉÃ&j€}9 0ÀÇ]€«í
+n°ñJ€úfBðÑn>>Ø
+GPÙÃu%;;ØïÀN3þæ@1`ó> tlžWF†Ð"Xl¹TBLAh¹‘œs@®¹Ôfà Ð\ Ì
+4÷í\³ð[¤m ·²!ÝsY´!°#!”Åq-úGĀ¥)ÈÁÀ) ¤ù8À-/Èد(Öð—^Ä`ĀolžƒÌ†&ÔA|k»ˆl
+Ö±yèв ™LØzXiÊ7—VBV³² ‘k>lD‘ì@Ā}†€\äÇ0Ä&*ìÎ lÚ ÐBF†Üí?r ূˆk CÆäȏa,Tˆay€bÀ=ÈI®ùÌ°–£Ü}òĀ%†¡K@ æafÌr ,ÄÌ Ã̸
+!i.ÐFp ˱rûD<2L<Ò¬RR¬ÒB õ~r`Õ@øÁ&0€Ô‰‰€¶A‰q2È3‹Š‰ 6mc €°LñBbw!Æ,Ã%&È lòð "pÉprŠƒZg ¦šԃr¢œb’@÷E¥¹€nÛpÊ1³BM™lԊ
+1ò‚¦PE¤Å™E%Ù@ÍmIÈÞ€Âp 8¤ÀSˆ}(-È jÅ M”Õ3³ŠßìLà¦xöDÃÌ¢ QdY`“M´“IR„—…<¼ËÊ)1¨TR’I^Töà$—œŒˆ xå#d¯@1ÃÌ cBlKÁmRpËHKƒ¶nðúš¦*( sƒöH ²ƒDY„A#I AvQ1û`&ˆðÉÃì@>iAð~>YHê ò¡Nb:PFDˆMÔPä•v‚b ·$(¤€ 9Ðì· ÔƒM¼ 6¸}쥀†nùØ%¡&0AL`à‘`º–”™¸Ø„!Ý&HW €°WólÒ¸zª| ®
+žÀ†4xV4Óà [)ÌÃr£X€&Aæ—@ÛÀ@Íi¨ r|€mx& k!#ÉÅ")ÌinCçeˆGCG spC¼ÍEŽE„Q‚è*NЪ PX‚V@
+)ðšPZM!‚âORÔ{ª–›
+có>¤fðÌbèÔOƒô²0, Ô¦:Φ °­Zž""))ž)7E +jä™D„Á±È·ºIð3r[r2àéO`ò'!I!¸ ̨Å/ fý
+IŒuÌ &ț"Òb|ù'fxÍ("ÂÎz bl< @KAó»<ü‚¬RLàâ4#.'.z¤9‘L@®`E°ls "›‚2Bb", ê´g6Å íKŠ€WÛpK1vX= ^ãÅÃ+ÌlY€GÙ@)Vœ ¼Ù[1Äό܏æÁR}ʀΆhϼ ¸àà…ÉŠsKAVX
+‰‚Øf’•E¡ 0À‹7e¹4/,Ãǎv °Ý£À:26
+‹al €Bq ¤Ä€¯©Aª€¥í&1ðæjø
+9Q.QpiÌ&&
+nsÝ'# ÚÃÄ,ÇÊÊ
+,‹Ù¹D€U+h*œãA{÷‘–Ìñ‰B~@‹_Il €BYÃÊÝ΄Ã|œ EDìÊb½¸Ü\’Ò `B| ŠKX† 4ê$&*.Î*-ÉÔ&**ÍÁƒÔÓÐÝÏÈ&ˆ#õ£±òŽiÐZ+I.؈*tC
+¼F‡‰T²W‰‹ý ŸO4O#$
+jÍ[Pà˜°S"$Ì$Ç'šcO+A³¨ldoôç“båš)
+€M- 0‡« ¥¹Ò¬Èó„ esH&ÀƧ¥#Ð ¬õ?@1@mAë-À'a€ŽÐ@]ƒ!>CB²bY¶”î¡ õøÁ–1Ût •' F“¸8 hù5h“#bmhå!ÄvØZв1­Ø[xÄ]Å$[u=rXÀ“« žØ9àÖ8dô\3€—±°#œ 䀗a€öu
+DtŒŠ0xʼ"I –Y ê9G s‚8Ƭˆ˜ÙN”c0ÏB€$Î*
+(ÇÉì܋›óÐå>àaD8E¥H7 €¨¿¨BŽ<4%
+Õl€šH۝À¥9/b$Œ4@ ԏap“
+¢t|¿„ˆ(¬Æ Z®ËÂ@Æä$@Ñ “ðA7QƒŒƒ–JÛÎ"Œüè+±‰DýrrÎxQ;då°ß YóMÎì.@Ñ¢ 烮å·u…A-`Pó¼u˜D‹ÅeµËÀ6RËyÍ·<)³¨D‹Æx!1R´ìe¥3)! @´ZýY€lÛBš³È‹cH›… ­~ƒ,L〶nÑæ:™I B€¢é)¢8N¸$)hÐs
+vIEND®B`‚
\ No newline at end of file
/tags/release_2_0_6-2/debian/TODO
New file
0,0 → 1,11
cp users/ templates/ /var/lib/sql-ledger/
cp/edit sql-ledger-default.conf /etc/sql-ledger/sql-ledger.conf
create /etc/sql-ledger/sql-ledger-httpd.conf
edit /etc/apache(-ssl)/http.conf to include sql-ledger-httpd.conf
cp bin/ /usr/lib/sql-ledger/bin
cd bin/lynx for ALL in ../mozilla/*.pl ; do ln -s $ALL ; done
cp -r ~/MY-CVS/sql-ledger/SL .
chown www-data:www-data users templates
cp -r ~/MY-CVS/sql-ledger/sql .
cp -r ~/MY-CVS/sql-ledger/locale .
 
/tags/release_2_0_6-2/debian/prerm
New file
0,0 → 1,5
#!/bin/bash
 
rm /usr/doc/sql-ledger || true
 
#DEBHELPER#
/tags/release_2_0_6-2/debian/changelog
New file
0,0 → 1,16
sql-ledger (2.0.6-2) UNRELEASED; urgency=low
 
* Made the Makefiles so that it fits with <package>_<version>.orig.tar.gz
* created symlink to /var (Closes #245008)
 
-- Finn-Arne Johansen <faj@bzz.no> Wed, 21 Apr 2004 04:39:49 +0200
 
sql-ledger (2.0.6-1) unstable; urgency=low
 
* Initial Release. (Closes: #129723, #138938)
* Fixed some errors to make it "lintian clean"
* Petter Reinholdtsen
- Removed (s) from copyright file to get rid of lintian warning
copyright-lists-upstream-authors-with-dh_make-boilerplate.
 
-- Finn-Arne Johansen <faj@bzz.no> Sun, 21 Mar 2004 14:07:45 +0100
/tags/release_2_0_6-2/debian/copyright
New file
0,0 → 1,86
This package was debianized by Finn-Arne Johansen <faj@bzz.no> on
Sun, 4 May 2003 05:21:25 +0200.
 
It was downloaded from http://prdownloads.sourceforge.net/sql-ledger/sql-ledger-2.0.6.tar.gz?download
 
Upstream Author: Dieter Simader dsimader@sql-ledger.org
 
Brazilian texts:
Author: Andre Felipe Machado <andremachado@techforce.com.br>
Miguel Koren O'Brien de Lacy <miguelk@konsultex.com.br>
Simplified Chinese texts:
Author: Chien Hsin Chang <werther@elixus.org>
Autrijus Tang <autrijus@autrijus.org>
Catalan Translation:
Author: Jaume Teixi <teixi@rocacorbit.com>
Czech texts:
Author: Tomas Fencl <tomas.fencl@centrum.cz>
German texts:
Author: Thomas Bayen <tbayen@bayen.de>
Gunter Ohrner <G.Ohrner@post.rwth-aachen.de>
Danish texts:
Author: Keld Jørn Simonsen <keld@dkuug.dk>
Jonas Smedegaard <jonas@jones.dk>
Estonian texts:
Author: Martin Lillepuu <martin@lillepuu.com>
Lauri Jesmin <jesmin@ut.ee>
Tanel Kurvits <rauge@hot.ee>
Spanish texts:
Author: Maria Gabriela Fong <mgfong@maga.tzo.org>
John Stoddart <jstypo@imagencolor.com.ve>
Federico Montesino Pouzols <fedemp@arrok.com>
Tomás Pereira <topec@percar.com>
Finish texts:
Author: Petri Leppänen <mpj@mail.htk.fi>
French texts:
Author: Sèbastien Brassard <sbrassar.cgocable.ca>
Oscar Buijten <oscar@elbie.com>
Wolfgang Sourdeau <wolfgang@contre.com>
Aguibou KONE <aguibou.kone@rocketmail.com>
Jens-Ingo Brodesser <jens-ingo@all2all.org>
Hungarian texts:
Author: unknown
Italien texts:
Author: Paolo Bizzarri <p.bizzarri@icube.it>
Luca Venturini <luca@yepa.com>
Alessandro Pasotti <apasotti@isoleborromee.it>
Spanish texts (Mexico):
Author: Alberto Ladron <h@grupoh.com.mx>
Dutch texts:
Author: AJ Hettema <Ignite@ecosse.net>
Oscar Buijten <oscar@elbie.com>
Bert Tijhuis <domino@dse.nl>
Paul Tammes <ptammes@home.nl>
Norwegian texts:
Author: Keld Jørn Simonsen <keld@dkuug.dk>
Morten Pedersen <morten@workzone.no>
Finn-Arne Johansen <faj@bzz.no>
Spanish texts:
Author: Maria Gabriela Fong <mgfong@maga.tzo.org>
Polish texts:
Author: Peter Dabrowski <meritage@mail.com>
Portugese texts:
Author: Paulo Rodrigues <prodrigues@vianetworks.pt>
Russian texts:
Author: Unknown
Swedish texts:
Author: jonny@lernbo.com
Turkish texts:
Author: Mufit Eribol <meribol@deltagrup.com.tr>
Traditional Chinese texts:
Author: ¤è²»³Ç (Jacky Fang) <jackyf@5star.com.tw>
Chien Hsin Chang <werther@elixus.org>
Autrijus Tang <autrijus@autrijus.org>
Ukrainian texts:
Author: Ivan Petrouchtchak <impe@telus.net>
Spanish Texts (Venezuela):
Author: John Stoddart <jstypo@imagencolor.com.ve>
 
These scripts are free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
 
On Debian GNU/Linux systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL'.
 
/tags/release_2_0_6-2/debian/rules
New file
0,0 → 1,94
#!/usr/bin/make -f
# Sample debian/rules that uses debhelper.
# GNU copyright 1997 to 1999 by Joey Hess.
 
# Uncomment this to turn on verbose mode.
#export DH_VERBOSE=1
 
# This is the debhelper compatibility version to use.
export DH_COMPAT=3
 
 
 
ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS)))
CFLAGS += -g
endif
ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS)))
INSTALL_PROGRAM += -s
endif
 
configure: configure-stamp
configure-stamp:
dh_testdir
# Add here commands to configure the package.
 
touch configure-stamp
 
 
build: build-stamp
 
build-stamp: configure-stamp
dh_testdir
 
# Add here commands to compile the package.
$(MAKE)
#/usr/bin/docbook-to-man debian/sql-ledger.sgml > sql-ledger.1
 
touch build-stamp
 
clean:
dh_testdir
dh_testroot
rm -f build-stamp configure-stamp
 
# Add here commands to clean up after the build process.
-$(MAKE) clean
 
dh_clean
 
install: build
dh_testdir
dh_testroot
dh_clean -k
dh_installdirs
 
# Add here commands to install the package into debian/sql-ledger.
$(MAKE) install DESTDIR=$(CURDIR)/debian/sql-ledger
 
 
# Build architecture-independent files here.
binary-indep: build install
# We have nothing to do by default.
 
# Build architecture-dependent files here.
binary-arch: build install
dh_testdir
dh_testroot
# dh_installdebconf
dh_installdocs
dh_installexamples
dh_installmenu
# dh_installlogrotate
# dh_installemacsen
# dh_installpam
# dh_installmime
# dh_installinit
dh_installcron
dh_installman
dh_installinfo
# dh_undocumented
dh_installchangelogs
dh_link
dh_strip
dh_compress
dh_fixperms
# dh_makeshlibs
dh_installdeb
dh_perl
dh_shlibdeps
dh_gencontrol
dh_md5sums
dh_builddeb
 
binary: binary-indep binary-arch
.PHONY: build clean binary-indep binary-arch binary install configure
Property changes:
Added: svn:executable
+ *
/tags/release_2_0_6-2/debian/.cvsignore
New file
0,0 → 1,3
files
sql-ledger
sql-ledger.substvars
/tags/release_2_0_6-2/debian/README.Debian
New file
0,0 → 1,30
sql-ledger for Debian
---------------------
 
To test this package you need to add this line to you
/etc/apache/httpd.conf:
 
include /etc/sql-ledger/sql-ledger-httpd.conf
 
then restart apache.
 
You also have to add some users to your postgres DB
 
The easiest way to test this package is to add a postgres-users with
the name of www-data. This however will mean that every apache process
will be able to authenticate to your DB.
 
To make a more robust security scheme, please read your postgres
documentation, but for now, do , as root, a
 
su - postgres
createuser -d www-data
 
Answer "n" to the question "Shall the new user be allowed to create
more new users?"
 
To finally test this, point your browser at
http://localhost/sql-ledger/admin.pl to create the DB and the initial
user, and afterwards: http://localhost/sql-ledger/login.pl to log in.
 
-- Finn-Arne Johansen <faj@bzz.no>, Sun, March 21, 2004 15:41:25 +0100
/tags/release_2_0_6-2/debian/control
New file
0,0 → 1,31
Source: sql-ledger
Section: web
Priority: optional
Maintainer: Finn-Arne Johansen <faj@bzz.no>
Uploaders: Petter Reinholdtsen <pere@debian.org>
Build-Depends-Indep: debhelper (>> 3.0.0), rsync
Standards-Version: 3.6.1
 
Package: sql-ledger
Architecture: all
Depends: ${perl:Depends}, apache | httpd, postgresql, libdbd-pg-perl
Suggests: latex
Description: A double-entry accounting program written in perl
Accounting data is stored in a SQL Server, for the display any text or
GUI browser can be used. The entire system is linked through a chart
of accounts. Each item in inventory is linked to revenue, expense,
inventory and tax accounts. When you sell and purchase goods and
services the accounts are automatically updated.
.
With the assembly feature you can build manufactured goods from parts,
services and assemblies. When you sell assemblies all the accounts
linked to the individual parts, services and assemblies are updated
and stock levels adjusted accordingly. If any item belonging to an
assembly is changed all assemblies are updated as well.
.
Invoices, Packing List, Income Statement, Balance Sheet, Sales and
Purchase Order, Statements, Receipts and Checks are generated from
templates and may be changed to suit your needs. Templates are provided
in html and tex format. The tex templates are processed with latex
to produce postscript and PDF documents and can be sent to a printer,
displayed in a PDF viewer or sent out via email ...
/tags/release_2_0_6-2/debian/dirs
New file
0,0 → 1,4
etc/sql-ledger
usr/lib/sql-ledger
usr/share/sql-ledger
var/lib/sql-ledger
/tags/release_2_0_6-2/debian/postinst
New file
0,0 → 1,8
#!/bin/sh
 
(
cd /var/lib/sql-ledger ;
chown www-data:www-data users templates
)
 
#DEBHELPER#
/release_2_0_6-2/debian
Property changes:
Added: svn:ignore
+ files
sql-ledger
sql-ledger.substvars
/tags/release_2_0_6-2/login.pl
New file
0,0 → 1,132
#!/usr/bin/perl
#
######################################################################
# SQL-Ledger Accounting
# Copyright (C) 2001
#
# Author: Dieter Simader
# Email: dsimader@sql-ledger.org
# Web: http://www.sql-ledger.org
#
# Contributors:
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#######################################################################
#
# this script sets up the terminal and runs the scripts
# in bin/$terminal directory
# admin.pl is linked to this script
#
#######################################################################
 
 
# setup defaults, these are overidden by sql-ledger.conf
# DO NOT CHANGE
$userspath = "users";
$templates = "templates";
$memberfile = "users/members";
$sendmail = "| /usr/sbin/sendmail -t";
########## end ###########################################
 
 
$| = 1;
 
eval { require "sql-ledger.conf"; };
 
if (-e "$userspath/nologin") {
print "
Login disabled!\n";
 
exit;
}
 
 
if ($ENV{CONTENT_LENGTH}) {
read(STDIN, $_, $ENV{CONTENT_LENGTH});
}
 
if ($ENV{QUERY_STRING}) {
$_ = $ENV{QUERY_STRING};
}
 
if ($ARGV[0]) {
$_ = $ARGV[0];
}
 
 
%form = split /[&=]/;
 
# fix for apache 2.0
map { $form{$_} =~ s/\\$// } keys %form;
 
# name of this script
$0 =~ tr/\\/\//;
$pos = rindex $0, '/';
$script = substr($0, $pos + 1);
 
 
if ($form{path}) {
$form{path} =~ s/%2[fF]/\//g;
$form{path} =~ s/\.\.\///g;
 
if ($form{path} !~ /^bin\//) {
print "
Invalid path!\n";
die;
}
 
 
$ARGV[0] = "$_&script=$script";
require "$form{path}/$script";
} else {
 
if (!$form{terminal}) {
if ($ENV{HTTP_USER_AGENT}) {
# web browser
if ($ENV{HTTP_USER_AGENT} =~ /(mozilla|links|opera|w3m)/i) {
$form{terminal} = "mozilla";
}
 
if ($ENV{HTTP_USER_AGENT} =~ /lynx/i) {
$form{terminal} = "lynx";
}
} else {
if ($ENV{TERM} =~ /xterm/) {
$form{terminal} = "xterm";
}
if ($ENV{TERM} =~ /(console|linux|vt.*)/i) {
$form{terminal} = "console";
}
}
}
 
 
if ($form{terminal}) {
 
$ARGV[0] = "path=bin/$form{terminal}&script=$script";
map { $ARGV[0] .= "&${_}=$form{$_}" } keys %form;
 
require "bin/$form{terminal}/$script";
} else {
 
print qq|
Unknown terminal
|;
}
 
}
 
# end of main
 
Property changes:
Added: svn:executable
+ *
/tags/release_2_0_6-2/menu.ini
New file
0,0 → 1,382
[AR]
 
[AR--Add Transaction]
module=ar.pl
action=add
 
[AR--Sales Invoice]
module=is.pl
action=add
type=invoice
 
[AR--Reports]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[AR--Reports--Transactions]
module=ar.pl
action=search
nextsub=ar_transactions
 
[AR--Reports--AR Aging]
module=rp.pl
action=report
report=ar_aging
 
[AR--Reports--Tax collected]
module=rp.pl
action=report
report=tax_collected
 
[AR--Customers]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[AR--Customers--Add Customer]
module=ct.pl
action=add
db=customer
 
[AR--Customers--Reports]
module=ct.pl
action=search
db=customer
 
[AP]
 
[AP--Add Transaction]
module=ap.pl
action=add
 
[AP--Purchase Invoice]
module=ir.pl
action=add
type=invoice
 
[AP--Reports]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[AP--Reports--Transactions]
module=ap.pl
action=search
nextsub=ap_transactions
 
[AP--Reports--AP Aging]
module=rp.pl
action=report
report=ap_aging
 
[AP--Reports--Tax paid]
module=rp.pl
action=report
report=tax_paid
 
[AP--Vendors]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[AP--Vendors--Add Vendor]
module=ct.pl
action=add
db=vendor
 
[AP--Vendors--Reports]
module=ct.pl
action=search
db=vendor
 
[Cash]
 
[Cash--Receipt]
module=cp.pl
action=payment
vc=customer
 
[Cash--Payment]
module=cp.pl
action=payment
vc=vendor
 
[Cash--Reports]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[Cash--Reports--Receipts]
module=rp.pl
action=report
report=receipts
 
[Cash--Reports--Payments]
module=rp.pl
action=report
report=payments
 
[Cash--Reconciliation]
module=rc.pl
action=reconciliation
 
[Order Entry]
 
[Order Entry--Sales Order]
module=oe.pl
action=add
type=sales_order
 
[Order Entry--Purchase Order]
module=oe.pl
action=add
type=purchase_order
 
[Order Entry--Reports]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[Order Entry--Reports--Sales Orders]
module=oe.pl
action=search
type=sales_order
 
[Order Entry--Reports--Purchase Orders]
module=oe.pl
action=search
type=purchase_order
 
[General Ledger]
 
[General Ledger--Add Transaction]
module=gl.pl
action=add
 
[General Ledger--Reports]
module=gl.pl
action=search
 
[Goods & Services]
 
[Goods & Services--Add Part]
module=ic.pl
action=add
item=part
 
[Goods & Services--Add Service]
module=ic.pl
action=add
item=service
 
[Goods & Services--Add Assembly]
module=ic.pl
action=add
item=assembly
 
[Goods & Services--Stock Assembly]
module=ic.pl
action=stock_assembly
 
[Goods & Services--Reports]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[Goods & Services--Reports--Parts]
module=ic.pl
action=search
searchitems=part
 
[Goods & Services--Reports--Services]
module=ic.pl
action=search
searchitems=service
 
[Goods & Services--Reports--Assemblies]
module=ic.pl
action=search
searchitems=assembly
 
[Projects]
 
[Projects--Add Project]
module=pe.pl
action=add
 
[Projects--Reports]
module=pe.pl
action=search
 
[Reports]
 
[Reports--Chart of Accounts]
module=ca.pl
action=chart_of_accounts
 
[Reports--Trial Balance]
module=rp.pl
action=report
report=trial_balance
 
[Reports--Income Statement]
module=rp.pl
action=report
report=income_statement
 
[Reports--Balance Sheet]
module=rp.pl
action=report
report=balance_sheet
 
[System]
 
[System--Chart of Accounts]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[System--Chart of Accounts--Add Account]
module=am.pl
action=add
 
[System--Chart of Accounts--List Accounts]
module=am.pl
action=list
 
[System--Chart of Accounts--Add GIFI]
module=am.pl
action=add_gifi
 
[System--Chart of Accounts--List GIFI]
module=am.pl
action=list_gifi
 
[System--HTML Templates]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[System--HTML Templates--Income Statement]
module=am.pl
action=display_form
file=templates=income_statement.html
 
[System--HTML Templates--Balance Sheet]
module=am.pl
action=display_form
file=templates=balance_sheet.html
 
[System--HTML Templates--Invoice]
module=am.pl
action=display_form
file=templates=invoice.html
 
[System--HTML Templates--Packing List]
module=am.pl
action=display_form
file=templates=packing_list.html
 
[System--HTML Templates--Sales Order]
module=am.pl
action=display_form
file=templates=sales_order.html
 
[System--HTML Templates--Purchase Order]
module=am.pl
action=display_form
file=templates=purchase_order.html
 
[System--HTML Templates--Statement]
module=am.pl
action=display_form
file=templates=statement.html
 
[System--LaTeX Templates]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[System--LaTeX Templates--Invoice]
module=am.pl
action=display_form
file=templates=invoice.tex
 
[System--LaTeX Templates--Packing List]
module=am.pl
action=display_form
file=templates=packing_list.tex
 
[System--LaTeX Templates--Sales Order]
module=am.pl
action=display_form
file=templates=sales_order.tex
 
[System--LaTeX Templates--Purchase Order]
module=am.pl
action=display_form
file=templates=purchase_order.tex
 
[System--LaTeX Templates--Statement]
module=am.pl
action=display_form
file=templates=statement.tex
 
[System--LaTeX Templates--Check]
module=am.pl
action=display_form
file=templates=check.tex
 
[System--LaTeX Templates--Receipt]
module=am.pl
action=display_form
file=templates=receipt.tex
 
[System--Stylesheet]
module=am.pl
action=display_stylesheet
 
[System--Backup]
module=menu.pl
action=acc_menu
target=acc_menu
submenu=1
 
[System--Backup--Send by E-Mail]
module=am.pl
action=backup
media=email
 
[System--Backup--Save to File]
module=am.pl
action=backup
media=file
 
[System--Audit Control]
module=am.pl
action=audit_control
 
[System--Preferences]
module=am.pl
action=config
 
[Version]
module=login.pl
action=company_logo
 
[Logout]
module=login.pl
action=logout
target=_top
 
/tags/release_2_0_6-2/VERSION
New file
0,0 → 1,0
2.0.6
/tags/release_2_0_6-2/css/sql-ledger.css
New file
0,0 → 1,113
/* stylesheet for sql-ledger */
 
/* general stuff */
A:link { color: #a0522d; text-decoration: none; }
A:visited { color: #a0522d; text-decoration: none; }
A:active { color: #a0522d; text-decoration: underline; }
A:hover { color: white;
background-color: rgb(187,187,187);
text-decoration: none;
}
 
body {
font-family: Verdana, Arial, Helvetica;
font-size: 10pt;
background-color: white;
color: black
}
 
td {
font-family: Verdana, Arial, Helvetica;
font-size: 10pt;
}
 
/* login and admin */
.login {
font-family: Verdana, Arial, Helvetica;
}
body.login {
background: #5a7d9b;
color: black;
}
h1.login {
font-size: 18pt;
}
table.login {
background-color: #FBFFE7;
padding: 20px;
}
td.login {
text-align: center;
}
th.login {
text-align: right;
}
 
body.admin {
background-color: #FBFFE7;
color: black;
}
 
body.menu {
background-color: #FBFFE7;
font-family: Verdana, Arial, Helvetica;
font-size: 10pt;
color: black;
}
 
 
.listtop { background-color: black; color: white; }
.listheading { background-color: #336666; color: white; }
A.listheading:link, A.listheading:active, A.listheading:visited {
color: white;
text-decoration: none; }
.listrow1 { background-color: #e6e6fa; color: black; vertical-align: top; }
.listrow0 { background-color: #ffe4e1; color: black; vertical-align: top; }
.listsubtotal { background-color: #5a7d9b; color: white; }
.listtotal { background-color: black; color: white; }
 
.submit {
font-size: 12pt
font-family: Verdana, Arial, Helvetica;
color: #000080;
}
.checkbox, .radio {
font-family: Verdana, Arial, Helvetica;
color: #778899;
}
 
.plus0 { /* font color for negative numbers */
color: red;
}
 
.plus1 {
color: green;
}
 
h2.confirm {
color: blue;
font-size: 14pt;
}
 
h2.error {
color: red;
font-size: 14pt;
}
 
 
/* media stuff */
 
@media screen {
.noscreen { /* items with this class won't display */
display: none;
}
}
 
@media print {
.noprint { /* items with this class won't print */
display: none;
}
}
 
 
 
/tags/release_2_0_6-2/css/Makefile
New file
0,0 → 1,12
PACKAGE = sql-ledger
 
FILES = sql-ledger.css
 
all:
 
clean:
 
install:
mkdir -p $(DESTDIR)/usr/lib/sql-ledger/SL
cp -r $(FILES) $(DESTDIR)/usr/lib/sql-ledger/SL
/tags/release_2_0_6-2/favicon.ico
New file
0,0 → 1,8
+{f‚‚‚^ƒ P5}‚‚‚DŸwb;‚‚]4L‚}(e=%8œC-#”‹‚!‚`/GN:ˆlRhI ˜.ž6$v H“Y‰Œqƒ‚X
+yU’?)Om9<†‚s&‚~_3™k@aÿþ ˜þœ†‡( @€ÿÿÿŒdNQ¾¾½``Zááڟ ™+. FF>ae0vvsvxQ‰Š„9:%µ·¢ÑÒÆ=Aœž}ððíWXFKN*hjIªª¬klebª¬VY!AE–—ŽÆÆɎ‘v}VY1ÕÕÕ58@A1ååèBE MNKÁ¯ÈÊ»or?klW÷øö¶¶¶tvf¬®Ÿ_`L25~U‚q23ž ‰OQ7”–‚££¤be@JMrt\ŒTTOppm<@
+FJ
+ȉ.óۇ-ë‰Ñ`¨½Üý Zù„zeB~Äͺ!¡“öÜ+uœª£›˜©>®Lèö3v´i·™3E„¤WÉ؈›kL~§Úá€äz¿ñ呛ӵ!âÙ·NɎ:{ݨÎçq´®F?xALKfðŠ‰9¿8:K•0=P޼숸Ži_Sm¤œ€Ç_ÆX,ÒmÆý]ÆDïz±—Wh0¤ãpMBזÅYäjb¤¤ºEäîá Kû¦Gszzæ$É
+’ö¤¾Uƒ|ÆzöôôüßcŽöÎ['ÄtX Š88¨¨ÔŠ[ÔöE ¢ŒmO#8,[&ÁD…aå^t11IúúbM¯¥T€øIƒ®öÖ\XS¶Hέ€JmVwgÝî[_æ¦à…ézô€Jm ;/Çnààz±g€J)öhsÏi@ËJoyJkô»J)㘢1JàOý6JòJ*ô»J)öc1Jš œz¡J‚zžJoô»J)xGJ¬SFJPÍGà|ô»Jœ%€†zô[ØÄ°g[iïô»J(ýdêÔÀíz à‹ô€JrN?8E8l2zŸµŽÑlQÁöh1à”Emf².C|Õи‹XŽ•5|7³âÿÿÿÿÿÿÿÿÿÿÿÿGŒ‡Ž#Ç€ÇÄÇÿŸÿÁÿÿÁÿÿÿÿü?ÿÿàÿÿ÷üÏàÀ„8À<¸À>Àà?€à?À?À? ‡À?Ä?€ÀÀðÿÿÿÿ
\ No newline at end of file
/tags/release_2_0_6-2/templates/Dutch-check.tex
New file
0,0 → 1,71
\documentclass[twoside]{scrartcl}
\usepackage[frame]{xy}
\usepackage{tabularx}
\usepackage[latin1]{inputenc}
\setlength{\voffset}{0.4cm}
\setlength{\hoffset}{-2.0cm}
\setlength{\topmargin}{0cm}
\setlength{\headheight}{0.0cm}
\setlength{\headsep}{1cm}
\setlength{\topskip}{0pt}
\setlength{\oddsidemargin}{1.0cm}
\setlength{\evensidemargin}{1.0cm}
\setlength{\textwidth}{19.2cm}
\setlength{\textheight}{24.5cm}
\setlength{\footskip}{1cm}
\setlength{\parindent}{0pt}
\renewcommand{\baselinestretch}{1}
\begin{document}
 
 
\fontfamily{cmss}\fontsize{9pt}{9pt}\selectfont
 
\parbox[t]{12cm}{
<%company%>
 
<%address%>}
\hfill
\parbox[t]{6cm}{\hfill <%source%>}
 
\vspace*{0.6cm}
 
<%text_amount%> \dotfill <%decimal%>/100 \makebox[0.5cm]{\hfill}
 
\vspace{0.5cm}
 
\hfill <%datepaid%> \makebox[2cm]{\hfill} <%amount%>
 
\vspace{0.5cm}
 
<%name%>
 
<%addr1%>
 
<%addr2%>
 
<%addr3%>
 
<%addr4%>
 
\vspace{2.8cm}
 
<%company%>
 
\vspace{0.5cm}
 
<%name%> \hfill <%datepaid%> \hfill <%source%>
 
\vspace{0.5cm}
\begin{tabularx}{\textwidth}{lXrr@{}}
\textbf{Invoice No.} & \textbf{Invoice Date}
& \textbf{Due} & \textbf{Applied} \\
<%foreach invnumber%>
<%invnumber%> & <%invdate%> \dotfill
& <%due%> & <%paid%> \\
<%end invnumber%>
\end{tabularx}
 
\vfill
 
\end{document}
 
/tags/release_2_0_6-2/templates/Dutch-balance_sheet.html
New file
0,0 → 1,104
 
<body bgcolor=ffffff>
 
<h2 align=center>
<%company%>
<br><%address%>
 
<p>BALANS
<br><%period%>
</h2>
 
<table border=0>
<tr>
<th align=left width=400 colspan=2>ACTIVA<br><hr align=left width=250 size=5 noshade></th>
<th><%this_period%></th>
<th><%last_period%></th>
</tr>
 
<%foreach asset_account%>
<tr>
<td> </td>
<td><%asset_account%></td>
<td align=right><%asset_this_period%></td>
<td align=right><%asset_last_period%></td>
</tr>
<%end asset_account%>
 
<tr>
<td colspan=2> </td>
<td><hr noshade size=1></td>
<td><hr noshade size=1></td>
</tr>
 
<tr valign=top>
<th align=left colspan=2>Totaal Activa</th>
<td align=right><%total_assets_this_period%><hr noshade size=2></td>
<td align=right><%total_assets_last_period%><hr noshade size=2></td>
</tr>
 
<tr>
<th align=left colspan=4>PASSIVA<b><hr align=left width=250 size=5 noshade></th>
</tr>
 
<%foreach liability_account%>
<tr>
<td></td>
<td><%liability_account%></td>
<td align=right><%liability_this_period%></td>
<td align=right><%liability_last_period%></td>
</tr>
<%end liability_account%>
 
<tr>
<td colspan=2> </td>
<td><hr noshade size=1></td>
<td><hr noshade size=1></td>
</tr>
 
<tr valign=top>
<td></td>
<th align=left>Totaal Passiva</th>
<td align=right><%total_liabilities_this_period%><br><hr noshade size=2</td>
<td align=right><%total_liabilities_last_period%><br><hr noshade size=2</td>
</tr>
 
<tr>
<th align=left colspan=4>ONVERDEELD RESULTAAT<br><hr align=left width=250 size=5 noshade></th>
</tr>
 
<%foreach equity_account%>
<tr>
<td></td>
<td><%equity_account%></td>
<td align=right><%equity_this_period%></td>
<td align=right><%equity_last_period%></td>
</tr>
<%end equity_account%>
 
<tr>
<td colspan=2> </td>
<td><hr noshade size=1></td>
<td><hr noshade size=1></td>
</tr>
 
<tr valign=top>
<td></td>
<th align=left>Totaal Opbrengst</th>
<td align=right><%total_equity_this_period%><br><hr noshade size=2</td>
<td align=right><%total_equity_last_period%><br><hr noshade size=2</td>
</tr>
 
<tr valign=top>
<th align=left colspan=2>TOTAAL PASSIVA & RESULTAAT</th>
<td align=right><%total_this_period%><br><hr noshade size=2></td>
<td align=right><%total_last_period%><br><hr noshade size=2></td>
</tr>
</table>
 
 
 
 
 
 
 
/tags/release_2_0_6-2/templates/Spanish_Letter-statement.tex
New file
0,0 → 1,137
\documentclass[twoside]{scrartcl}
\usepackage[frame]{xy}
\usepackage{tabularx}
\usepackage[latin1]{inputenc}
\setlength{\voffset}{0.5cm}
\setlength{\hoffset}{-2.0cm}
\setlength{\topmargin}{0cm}
\setlength{\headheight}{0.5cm}
\setlength{\headsep}{1cm}
\setlength{\topskip}{0pt}
\setlength{\oddsidemargin}{1.0cm}
\setlength{\evensidemargin}{1.0cm}
\setlength{\textwidth}{19.2cm}
\setlength{\textheight}{24.5cm}
\setlength{\footskip}{1cm}
\setlength{\parindent}{0pt}
\renewcommand{\baselinestretch}{1}
\begin{document}
 
\newlength{\descrwidth}\setlength{\descrwidth}{10cm}
 
\newsavebox{\hdr}
\sbox{\hdr}{
\fontfamily{cmss}\fontsize{10pt}{12pt}\selectfont
 
\parbox{\textwidth}{
\parbox[b]{12cm}{
<%company%>
 
<%address%>}\hfill
\begin{tabular}[b]{rrr@{}}
Tel & <%tel%>\\
Fax & <%fax%>
\end{tabular}
 
\rule[1.5ex]{\textwidth}{0.5pt}
}
}
 
\fontfamily{cmss}\fontshape{n}\selectfont
 
\markboth{<%company%>\hfill <%statementdate%>}{\usebox{\hdr}}
 
\pagestyle{myheadings}
%\thispagestyle{empty} use this with letterhead paper
 
<%pagebreak 90 27 48%>
\end{tabular*}
 
\rule{\textwidth}{2pt}
 
\hfill
\begin{tabularx}{7cm}{Xr@{}}
\textbf{Subtotal} & \textbf{<%sumcarriedforward%>} \\
\end{tabularx}
 
\newpage
 
\markright{<%company%>\hfill <%statementdate%>}
 
\vspace*{-12pt}
 
\begin{tabular*}{\textwidth}{@{}l@{\extracolsep\fill}ccrrrr@{}}
\textbf{Invoice \#} & \textbf{Date} & \textbf{Due} &
\textbf{Current} & \textbf{30} & \textbf{60} & \textbf{90+} \\
carried forward from <%lastpage%> & & & & & & <%sumcarriedforward%> \\
<%end pagebreak%>
 
 
\fontfamily{cmss}\fontsize{10pt}{12pt}\selectfont
 
\vspace*{1.5cm}
 
\parbox[t]{1cm}{\hfill}
\parbox[t]{10.5cm}{
<%name%>
 
<%addr1%>
 
<%addr2%>
 
<%addr3%>
 
<%addr4%>
 
}
\parbox[t]{7.5cm}{
<%if customerphone%>
Tel: <%customerphone%>
<%end customerphone%>
 
<%if customerfax%>
Fax: <%customerfax%>
<%end customerfax%>
 
<%email%>
}
\hfill
 
\vspace{1cm}
 
\textbf{S T A T E M E N T} \hfill
 
\hfill <%statementdate%>
 
\vspace{2cm}
 
\begin{tabular*}{\textwidth}{@{}l@{\extracolsep\fill}ccrrrr@{}}
\textbf{Invoice \#} & \textbf{Date} & \textbf{Due} &
\textbf{Current} & \textbf{30} & \textbf{60} & \textbf{90+} \\
<%foreach invnumber%>
<%invnumber%> & <%invdate%> & <%duedate%> &
<%c0%> & <%c30%> & <%c60%> & <%c90%> \\
<%end invnumber%>
\textbf{Subtotal} & & & <%c0total%> & <%c30total%> & <%c60total%> & <%c90total%>
\end{tabular*}
\rule{\textwidth}{1pt}
 
\vspace{1cm}
 
\hfill
\begin{tabularx}{7cm}{Xr@{}}
\textbf{Total outstanding} & <%total%>
\end{tabularx}
 
\vfill
 
Please make check payable to <%company%>
 
\renewcommand{\thefootnote}{\fnsymbol{footnote}}
 
\footnotetext[1]{\tiny
}
 
\end{document}
 
/tags/release_2_0_6-2/templates/Estonian-purchase_order.html
New file
0,0 → 1,195
<head>
<title>Ostutellimus</title>
</head>
 
<body bgcolor=ffffff>
 
<table width=100%>
<tr valign=bottom>
<td width=10>&nbsp;</td>
<td>
<table width=100%>
<tr>
<td>
<h4>
<%company%>
<br><%address%>
</h4>
</td>
 
<td align=right>
<h4>
Tel: <%tel%>
<br>Fax: <%fax%>
</h4>
</td>
</tr>
 
<tr>
<th colspan=3>
<h4>O S T U T E L L I M U S</h4>
</th>
</tr>
 
</table>
 
 
<table width=100% callspacing=0 cellpadding=0>
<tr>
<td align=right>
<table>
<tr>
<th align=right>Tellimuse Kpv</th><td width=10>&nbsp;</td><td><%orddate%></td>
</tr>
<tr>
<th align=right>Required by</th><td width=10>&nbsp;</td><td><%reqdate%></td>
</tr>
 
<tr>
<th align=right>Number</th><td>&nbsp;</td><td><%ordnumber%></td></tr>
</tr>
<tr>
<td>&nbsp;</td>
</tr>
</td>
</table>
</tr>
 
<tr>
<td>
<table width=100%>
<tr bgcolor=000000>
<th align=left><font color=ffffff>To:</th>
</tr>
 
<tr>
<td><%name%>
<br><%addr1%>
<br><%addr2%>
<br><%addr3%>
<br><%addr4%>
</td>
</tr>
</table>
</td>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>
<table width=100%>
<tr bgcolor=000000>
<!-- <th align=right><font color=ffffff>No.</th> -->
<th align=left><font color=ffffff>Number</th>
<th align=left><font color=ffffff>Description</th>
<th><font color=ffffff>Qt'y</th>
<th>&nbsp;</th>
<th><font color=ffffff>Price</th>
<th><font color=ffffff>Amount</th>
</tr>
 
<%foreach number%>
<tr valign=top>
<!-- <td align=right><%runningnumber%>.</td>
adjust the colspan if you include this to shift subtotal one to the right
-->
<td><%number%></td>
<td><%description%></td>
<td align=right><%qty%></td>
<td><%unit%></td>
<td align=right><%sellprice%></td>
<td align=right><%linetotal%></td>
</tr>
<%end number%>
 
<tr>
<td colspan=6><hr noshade></td>
</tr>
<tr>
<th colspan=4 align=right>Vahesumma</th>
<td colspan=2 align=right><%subtotal%></td>
</tr>
 
<%foreach tax%>
<tr>
<th colspan=4 align=right><%taxdescription%> @ <%taxrate%> %</th>
<td colspan=2 align=right><%tax%></td>
</tr>
<%end tax%>
 
<tr>
<td colspan=2>&nbsp;</td>
<td colspan=4><hr noshade></td>
</tr>
 
<tr>
<td colspan=2>Maksetähtaeg <b><%terms%></b> tööpäeva</td>
<th colspan=2 align=right>Kokku</th>
<th colspan=2 align=right><%total%></th>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
 
</table>
</td>
</tr>
 
<tr>
<td>
<table width=100%>
<tr valign=top>
<%if notes%>
<td>Märkused</td>
<td><pre><%notes%></pre></td>
<%end notes%>
<td align=right>
Kõik hinnad: <b><%currency%></b>
<br><%shippingpoint%>
</td>
</tr>
 
</table>
</td>
</tr>
 
<tr><td>&nbsp;</td></tr>
<tr>
<td>
<table width=100%>
<tr valign=top>
<td><font size=-3>
Maksetähtaeg <%terms%> päeva alates arve kuupäevast.
Intress tasumata summadelt on 1.5% kuus kuni arve täeliku tasumiseni.
Tagastatud toodetele kehtib 10% tagastamistasu. Enne toodete tagastamist on vajalik
<%company%> nõusolek. Tagastavad tooted peavad olema makstud ning kindlustatud,
<%company%> ei vastuta transpordi käigus tekkinud kahjude eest.
</font>
</td>
<td width=150>
X <hr noshade>
</td>
</tr>
</table>
</td>
</tr>
 
</table>
 
</td>
</tr>
</table>
 
</body>
</html>
 
/tags/release_2_0_6-2/templates/Spanish_Letter-purchase_order.tex
New file
0,0 → 1,107
\documentclass[letterpaper,oneside]{article}
\usepackage[frame]{xy}
\usepackage{tabularx}
\usepackage[latin1]{inputenc}
%\usepackage{marvosym} % Euro \EUR
\usepackage{fancyhdr}
\setlength{\topmargin}{0cm}
\setlength{\topskip}{0cm}
\setlength{\headheight}{0cm}
\setlength{\headsep}{0.5cm}
\setlength{\textheight}{24.2cm}
\setlength{\textwidth}{19cm}
\setlength{\oddsidemargin}{-1.4cm}
\setlength{\evensidemargin}{-1.4cm}
\setlength{\footskip}{1cm}
 
\setlength{\parindent}{0pt}
\renewcommand{\baselinestretch}{1}
\begin{document}
 
\newlength{\descrwidth}\setlength{\descrwidth}{13.0cm}
 
\newsavebox{\hdr}
 
\fontfamily{cmss}\fontshape{n}\selectfont
 
\sbox{\hdr}{
\begin{minipage}[t]{0.6\linewidth}
\vspace{2.2cm}
 
\begin{tabular}[t]{p{1.7cm}p{2.4cm}p{1.7cm}}\\
\centering{Número} & \centering{Fecha} & C. Cliente\\
\centering{<%ordnumber%>} & \centering{<%orddate%>} & \centering{<%vendor_id%>}
\end{tabular}
\end{minipage}
 
\begin{minipage}[t]{0.4\linewidth}
\textbf{O R D E N \quad D E \quad C O M P R A}
\vspace{1cm}
 
<%name%>
 
<%addr1%>
 
<%addr2%>
 
<%addr3%>
 
<%addr4%>
\end{minipage}
 
}
 
\pagestyle{fancy}
\renewcommand{\headrulewidth}{0cm}
\renewcommand{\footrulewidth}{0cm}
\cfoot{\thepage}
%\markboth{\usebox{\hdr}}{\usebox{\hdr}}
%\thispagestyle{empty} %use this with letterhead paper
 
<%pagebreak 90 27 48%>
\end{tabular*}
\newpage
\usebox{\hdr}
%\markboth{\usebox{\hdr}}{\usebox{\hdr}}
\vspace{0.5cm}
 
\begin{tabular*}{\textwidth}{rp{\descrwidth}rr}
\textbf{Cant.} & \textbf{Descripción} & \textbf{Precio} & \textbf{Importe} \\ \hline
<%end pagebreak%>
 
\fontfamily{cmss}\fontsize{10pt}{12pt}\selectfont
 
\usebox{\hdr}
\vspace{0.5cm}
 
\begin{tabular*}{\textwidth}{rp{\descrwidth}rr}
\textbf{Cant.} & \textbf{Descripción} & \textbf{Precio} & \textbf{Importe} \\ \hline
<%foreach number%>
<%qty%> & <%description%> & <%sellprice%> & <%linetotal%> \\
<%end number%>
\end{tabular*}
 
\parbox{\textwidth}{
\vspace{12pt}
<%if notes%>
<%notes%>
<%end if%>
}
 
\vfill
 
\begin{flushright}
\begin{tabularx}{10cm}{Xr@{}}
\textbf{Base imponible} & \textbf{<%subtotal%>} \\
<%foreach tax%>
IVA (<%taxrate%>\%) sobre <%taxbase%> & <%tax%> \\
<%end tax%>
\hline
\textbf{Total} & \textbf{<%ordtotal%>} \\
\end{tabularx}
\end{flushright}
 
%\renewcommand{\thefootnote}{\fnsymbol{footnote}}
 
\end{document}
 
/tags/release_2_0_6-2/templates/Spanish_A4-sales_order.html
New file
0,0 → 1,153
<head>
<title>Presupuesto de Instalaciones Industriales San José</title>
</head>
 
<body bgcolor="ffffff">
<!-- Cabecera -->
<table width="100%">
<tr valign=bottom>
<td width="10">&nbsp;</td>
<td>
<table width=100%>
<tr>
<th colspan="4"> </th>
<th align="left">
<h4>P R E S U P U E S T O</h4>
</th>
</tr>
<tr>
<td colspan="5"> </td>
</tr>
<tr>
<td colspan="4"> </td>
<td align="left"><%name%></td>
</tr>
<tr>
<td>Número</td>
<td>Fecha</td>
<td>Cód. Cliente</td>
<td width="10%"> </td>
<td><%addr1%></td>
</tr>
<tr>
<td><b><%ordnumber%></b></td>
<td><b><%orddate%></b></td>
<td><b><%customer_id%></b></td>
<td> </td>
<td><%addr2%></td>
</tr>
<tr>
<td colspan="4">
<td><%addr3%></td>
</tr>
<tr>
<td colspan="4">
<td><%addr4%></td>
</tr>
</table>
</table>
 
<!-- Cuerpo -->
<table width=100% cellspacing=0 cellpadding=0>
<tr>
<td>
<table width=100%>
<tr bgcolor=000000>
<!-- <th align=left><font color=ffffff>Número</th> -->
<!-- <th><font color=ffffff>Cant.</th> -->
<th align="left"><font color="ffffff">Cant.</th>
<th align="left"><font color="ffffff">Descripción</th>
<th align="left"><font color="ffffff">Precio</th>
<!-- <th align="left"><font color="ffffff">Dto.</th> -->
<th align="left"><font color="ffffff">Importe</th>
</tr>
 
<tr>
<td colspan="4"><hr noshade></td>
</tr>
<%foreach number%>
<tr valign=top>
<!-- <td><%number%></td> -->
<!-- <td><%unit%></td> -->
<td align="right"><%qty%></td>
<td align="left"><%description%></td>
<td align="right"><%sellprice%></td>
<!-- <td align=right><%discount%></td> -->
<td align="right"><%linetotal%></td>
</tr>
<%end number%>
<tr>
<td colspan="4"><hr noshade></td>
</tr>
</table>
<!-- Subtotales, impuestos y totales -->
<table width="100%">
<tr>
<%if taxincluded%>
<th align=right>Total</th>
<td align=right><%ordtotal%></td>
<%end taxincluded%>
<%if not taxincluded%>
<th align="right">Base imponible</th>
<td align="right"><%subtotal%> &euro;</td>
<%end taxincluded%>
</tr>
 
<%foreach tax%>
<tr>
<th align="right">IVA (<%taxrate%>%) sobre <%taxbase%>:</th>
<td align="right"><%tax%> &euro;</td>
</tr>
<%end tax%>
<%if paid%>
<tr>
<th align="right">Pagado:</th>
<td align="right"><%paid%> &euro;</td>
</tr>
<%end paid%>
<tr>
<td>&nbsp;</td>
<td><hr noshade></td>
</tr>
 
<tr>
<th align="right">Total:</th>
<th align="right"><%ordtotal%> &euro;</th>
</tr>
<tr>
<td colspan="4">&nbsp;</td>
</tr>
</table>
 
 
<!-- Pie -->
<table width="100%">
<tr valign=top>
<%if notes%>
<td>Notas</td>
<td><%notes%></td>
<%end notes%>
</tr>
<%if taxincluded%>
<tr>
<th colspan="2" align="left"><font size=-2>Los precios incluyen impuestos.</th>
</tr>
<%end taxincluded%>
</table>
 
 
</body>
</html>
 
/tags/release_2_0_6-2/templates/Danish-receipt.tex
New file
0,0 → 1,71
\documentclass[twoside]{scrartcl}
\usepackage[frame]{xy}
\usepackage{tabularx}
\usepackage[latin1]{inputenc}
\setlength{\voffset}{0.4cm}
\setlength{\hoffset}{-2.0cm}
\setlength{\topmargin}{0cm}
\setlength{\headheight}{0.0cm}
\setlength{\headsep}{1cm}
\setlength{\topskip}{0pt}
\setlength{\oddsidemargin}{1.0cm}
\setlength{\evensidemargin}{1.0cm}
\setlength{\textwidth}{19.2cm}
\setlength{\textheight}{24.5cm}
\setlength{\footskip}{1cm}
\setlength{\parindent}{0pt}
\renewcommand{\baselinestretch}{1}
\begin{document}
 
 
\fontfamily{cmss}\fontsize{9pt}{9pt}\selectfont
 
\parbox[t]{12cm}{
<%company%>
 
<%address%>}
\hfill
\parbox[t]{6cm}{\hfill <%source%>}
 
\vspace*{0.6cm}
 
<%text_amount%> \dotfill <%decimal%>/100 \makebox[0.5cm]{\hfill}
 
\vspace{0.5cm}
 
\hfill <%datepaid%> \makebox[2cm]{\hfill} <%amount%>
 
\vspace{0.5cm}
 
<%name%>
 
<%addr1%>
 
<%addr2%>
 
<%addr3%>
 
<%addr4%>
 
\vspace{2.8cm}
 
<%company%>
 
\vspace{0.5cm}
 
<%name%> \hfill <%datepaid%> \hfill <%source%>
 
\vspace{0.5cm}
\begin{tabularx}{\textwidth}{lXrr@{}}
\textbf{Invoice No.} & \textbf{Invoice Date}
& \textbf{Due} & \textbf{Applied} \\
<%foreach invnumber%>
<%invnumber%> & <%invdate%> \dotfill
& <%due%> & <%paid%> \\
<%end invnumber%>
\end{tabularx}
 
\vfill
 
\end{document}
 
/tags/release_2_0_6-2/templates/Danish-invoice.tex
New file
0,0 → 1,152
\documentclass[a4paper,twoside]{scrartcl}
\usepackage[frame]{xy}
\usepackage{tabularx}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[danish]{babel}
\setlength{\voffset}{0.5cm}
\setlength{\hoffset}{-2.0cm}
\setlength{\topmargin}{0cm}
\setlength{\headheight}{0.5cm}
\setlength{\headsep}{1cm}
\setlength{\topskip}{0pt}
\setlength{\oddsidemargin}{1.0cm}
\setlength{\evensidemargin}{1.0cm}
\setlength{\textwidth}{19.2cm}
\setlength{\textheight}{24.5cm}
\setlength{\footskip}{1cm}
\setlength{\parindent}{0pt}
\renewcommand{\baselinestretch}{1}
\begin{document}
 
\newlength{\descrwidth}\setlength{\descrwidth}{10cm}
 
\newsavebox{\hdr}
\sbox{\hdr}{
\fontfamily{cmss}\fontsize{10pt}{12pt}\selectfont
 
\parbox{\textwidth}{
\parbox[b]{12cm}{
<%company%>
<%address%>}\hfill
\begin{tabular}[b]{rr@{}}
Tlf. & <%tel%>\\
Fax & <%fax%>
\end{tabular}
 
\rule[1.5ex]{\textwidth}{0.5pt}
}
}
\fontfamily{cmss}\fontshape{n}\selectfont
 
\markboth{<%company%>\hfill <%invnumber%>}{\usebox{\hdr}}
 
\pagestyle{myheadings}
%\thispagestyle{empty} use this with letterhead paper
 
<%pagebreak 90 27 48%>
\end{tabular*}
 
\rule{\textwidth}{2pt}
\hfill
\begin{tabularx}{7cm}{Xr@{}}
\textbf{Subtotal} & \textbf{<%sumcarriedforward%>} \\
\end{tabularx}
 
\newpage
 
\markright{<%company%>\hfill <%invnumber%>}
 
\vspace*{-12pt}
 
\begin{tabular*}{\textwidth}{@{}lp{\descrwidth}@{\extracolsep\fill}rlrrr@{}}
\textbf{Nummer} & \textbf{Beskrivelse} & \textbf{Antal} &
\textbf{Enhed} & \textbf{Pris} & \textbf{Rabat} & \textbf{Beløb} \\
& overført fra side <%lastpage%> & & & & & <%sumcarriedforward%> \\
<%end pagebreak%>
 
 
\fontfamily{cmss}\fontsize{10pt}{12pt}\selectfont
 
\vspace*{2cm}
 
<%name%>
 
<%addr1%>
 
<%addr2%>
 
<%addr3%>
 
<%addr4%>
 
\vspace{3.5cm}
 
\textbf{F A K T U R A}
\hfill
\begin{tabular}[t]{l@{\hspace{0.3cm}}l}
\textbf{Dato} & <%invdate%> \\
\textbf{Nummer} & <%invnumber%> \\
\textbf{Kunde} & <%customer_id%>
\end{tabular}
 
\vspace{1cm}
 
\begin{tabular*}{\textwidth}{@{}lp{\descrwidth}@{\extracolsep\fill}rlrrr@{}}
\textbf{Nummer} & \textbf{Beskrivelse} & \textbf{Antal} &
\textbf{Enhed} & \textbf{Pris} & \textbf{Rabat} & \textbf{Beløb} \\
<%foreach number%>
<%number%> & <%description%> & <%qty%> &
<%unit%> & <%sellprice%> & <%discount%> & <%linetotal%> \\
<%end number%>
\end{tabular*}
 
 
\parbox{\textwidth}{
\rule{\textwidth}{2pt}
 
\vspace{0.2cm}
 
\hfill
\begin{tabularx}{7cm}{Xr@{}}
\textbf{Subtotal} & \textbf{<%subtotal%>} \\
<%foreach tax%>
<%taxdescription%> på <%taxbase%> & <%tax%> \\
<%end tax%>
<%if paid%>
\textbf{Betalt} & - <%paid%> \\
<%end paid%>
\hline
\textbf{At betale} & \textbf{<%total%>} \\
\end{tabularx}
 
\vspace{0.3cm}
 
\hfill
Alle priser i \textbf{<%currency%>}.
 
\vspace{12pt}
 
<%if notes%>
<%notes%>
<%end if%>
 
}
 
\vfill
\centerline{\textbf{Tak for handelen!}}
 
\renewcommand{\thefootnote}{\fnsymbol{footnote}}
 
\footnotetext[1]{\tiny
Betalingsfrist <%terms%> dage fra fakturadato. Betaling herefter påregnes
1.5\% per påbegyndt måned startende <%duedate%> og indtil det fulde beløb
er betalt. Returnerede varer modregnes 10\% i ekspeditionsgebyr.
Et returnummer skal tildeles af <%company%> før varer returneres.
Returvarer skal forsendes forudbetalt og forsvarligt forsikret.
<%company%> kan ikke drages til ansvar for skade under transport.}
 
\end{document}
/tags/release_2_0_6-2/templates/Brazilian_Portuguese-sales_order.html
New file
0,0 → 1,221
 
<body bgcolor=ffffff>
 
<table width=100%>
<tr valign=bottom>
<td width=10>&nbsp;</td>
<td>
<table width=100%>
<tr>
<td>
<h4>
<%company%>
<br><%address%>
</h4>
</td>
 
<td align=right>
<h4> Telefone:
<%tel%>
<br>
Fax:
<%fax%>
</h4>
</td>
</tr>
 
<tr>
<th colspan=3>
<h4>ORDEM DE VENDA</h4>
</th>
</tr>
 
</table>
 
 
<table width=100% callspacing=0 cellpadding=0>
<tr>
<td align=right>
<table>
<tr>
<th align=right>Data</th>
<td width=10>&nbsp;</td><td><%orddate%></td>
</tr>
<tr>
<th align=right>Requerido por</th>
<td width=10>&nbsp;</td><td><%reqdate%></td>
</tr>
 
<tr>
<th align=right>N&uacute;mero</th>
<td>&nbsp;</td><td><%ordnumber%></td></tr>
</table></tr>
<tr>
<td>&nbsp;</td>
</tr>
</table></td>
</table>
 
<tr>
<td>
<table width=100%>
<tr bgcolor=000000>
<th align=left><font color="ffffff">Para:</font></th>
<th align=left><font color="ffffff">Transportar para:</font></th>
</tr>
 
<tr>
<td><%name%>
<br><%addr1%>
<br><%addr2%>
<br><%addr3%>
<br><%addr4%>
</td>
 
<td><%shiptoname%>
<br><%shiptoaddr1%>
<br><%shiptoaddr2%>
<br><%shiptoaddr3%>
<br><%shiptoaddr4%>
</td>
</tr>
</table>
</td>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>
<table width=100%>
<tr bgcolor=000000>
<!-- <th align=right><font color=ffffff>No.</th> -->
<th align=left><font color=ffffff>N&uacute;mero</font></th>
<th align=left><font color=ffffff>Descri&ccedil;&atilde;o</font></th>
<th><font color=ffffff>Quant.</font></th>
<th>&nbsp;</th>
<th><font color=ffffff>Pre&ccedil;o</font></th>
<th><font color=ffffff>Disc.</font></th>
<th><font color="ffffff">Total</font></th>
</tr>
 
<%foreach number%>
<tr valign=top>
<!-- <td align=right><%runningnumber%>.</td>
adjust the colspan if you include this to shift subtotal one to the right
-->
<td><%number%></td>
<td><%description%></td>
<td align=right><%qty%></td>
<td><%unit%></td>
<td align=right><%sellprice%></td>
<td align=right><%discount%></td>
<td align=right><%linetotal%></td>
</tr>
<%end number%>
 
<tr>
<td colspan=7><hr noshade></td>
</tr>
<tr>
<%if taxincluded%>
<th colspan=5 align=right>Total</th>
<td colspan=2 align=right><%ordtotal%></td>
<%end taxincluded%>
 
<%if not taxincluded%>
<th colspan=5 align=right>Subtotal</th>
<td colspan=2 align=right><%subtotal%></td>
<%end taxincluded%>
</tr>
 
<%foreach tax%>
<tr>
<th colspan=5 align=right>
<%taxdescription%>
em
<%taxbase%>
@
<%taxrate%>
%</th>
<td colspan=2 align=right><%tax%></td>
</tr>
<%end tax%>
 
<tr>
<td colspan=2>&nbsp;</td>
<td colspan=5><hr noshade></td>
</tr>
 
<tr>
<td colspan=3>Faturar para<b>
<%terms%>
</b> dias</td>
<th colspan=2 align=right>Total</th>
<th colspan=2 align=right><%ordtotal%></th>
</tr>
<%if taxincluded%>
<tr>
<td colspan=3>Impostos inclusos do total</td>
</tr>
<%end taxincluded%>
 
<tr>
<td>&nbsp;</td>
</tr>
 
</table>
</td>
</tr>
 
<tr>
<td>
<table width=100%>
<tr valign=top>
<%if notes%>
<td>Obs.:</td>
<td><pre><%notes%></pre></td>
<%end notes%>
<td align=right> Pre&ccedil;os em<b>
<%currency%>
</b><br>
<%shippingpoint%>
</td>
</tr>
 
</table>
</td>
</tr>
 
<tr><td>&nbsp;</td></tr>
<tr>
<td>
<table width=100%>
<tr valign=top>
<td><font size=-3> </font> </td>
<td width=150>
X <hr noshade>
</td>
</tr>
</table>
</td>
</tr>
 
 
 
 
 
 
 
</body>
</html>
 
/tags/release_2_0_6-2/templates/French-invoice.html
New file
0,0 → 1,309
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional">
 
<html>
 
<head>
 
<title>A2A <%invnumber%> <%name%></title>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-15">
 
</head>
 
<body bgcolor="ffffff">
 
<table width="100%">
<tr valign=bottom>
<td width=10>&nbsp;</td>
<td>
<table width="100%">
<tr>
<td>
<h4>
<%company%>
<br><%address%>
</h4>
</td>
 
<td align=right>
<h4>
Tél&nbsp;: <%tel%>
<br>Fax&nbsp;: <%fax%>
</h4>
</td>
</tr>
 
<tr>
<th colspan=3>
<h4>F A C T U R E</h4>
</th>
</tr>
 
</table>
 
 
<table width="100%" cellspacing=0 cellpadding=0>
<tr>
<td align=right>
<table>
<tr>
<th align=right>Date de facture</th><td width=10>&nbsp;</td><td><%invdate%></td>
</tr>
<tr>
<th align=right>Date d'échéance</th><td width=10>&nbsp;</td><td><%duedate%></td>
</tr>
 
<tr>
<th align=right>N° de facture</th><td>&nbsp;</td><td><%invnumber%></td></tr>
</tr>
<!--
<tr>
<th align=right>Correspondant</th><td>&amp;nbsp;</td><td><%employee%></td>
</tr>
-->
 
<tr>
<td>&nbsp;</td>
</tr>
</td>
</table>
</tr>
 
<tr>
<td>
<table width="100%">
<tr bgcolor="000000">
<th align=left><font color=ffffff>Adresse de facturation</font></th>
<th align=left><font color=ffffff>Adresse d'envoi</font></th>
</tr>
 
<!--
d'autres variables pouvant être utilisées ici :
contact, shiptocontact, shiptophone, shiptofax
-->
 
<tr valign=top>
<td><%name%>
<br><%addr1%>
<br><%addr2%>
<br><%addr3%>
<br><%addr4%>
</td>
<td><%shiptoname%>
<br><%shiptoaddr1%>
<br><%shiptoaddr2%>
<br><%shiptoaddr3%>
<br><%shiptoaddr4%>
</td>
</tr>
</table>
</td>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>
<table width="100%">
<tr bgcolor="000000">
<!-- <th align=right><font color="ffffff">N°</font></th> -->
<th align=left><font color="ffffff">N°</font></th>
<th align=left><font color="ffffff">Description</font></th>
<th><font color="ffffff">Qté</font></th>
<th>&nbsp;</th>
<th><font color="ffffff">Prix</font></th>
<th><font color="ffffff">Remise</font></th>
<th><font color="ffffff">Montant</font></th>
</tr>
 
<%foreach number%>
<tr valign=top>
<!-- <td align=right><%runningnumber%>.</td>
veuillez adapter le colspan si vous comptez inclure ce poste.
ceci permettra de décaler le poste sous-total vers la gauche.
-->
<td><%number%></td>
<td><%description%></td>
<td align=right><%qty%></td>
<td><%unit%></td>
<td align=right><%sellprice%></td>
<td align=right><%discount%></td>
<td align=right><%linetotal%></td>
</tr>
<%end number%>
 
<!--
vous pouvez également utiliser netprice à la place de sellprice
si vous ne voulez pas afficher la remise
netprice = sellprice - discount
-->
 
<tr>
<td colspan=7><hr noshade></td>
</tr>
<tr>
<%if taxincluded%>
<th colspan=5 align=right>Total</th>
<td colspan=2 align=right><%invtotal%></td>
<%end taxincluded%>
<%if not taxincluded%>
<th colspan=5 align=right>Sous-total</th>
<td colspan=2 align=right><%subtotal%></td>
<%end taxincluded%>
</tr>
 
<%foreach tax%>
<tr>
<th colspan=5 align=right><%taxdescription%></th>
<td colspan=2 align=right><%tax%></td>
</tr>
<%end tax%>
 
<%if paid%>
<tr>
<th colspan=5 align=right>Déjà payé</th>
<td colspan=2 align=right>- <%paid%></td>
</tr>
<%end paid%>
 
<tr>
<td colspan=3>&nbsp;</td>
<td colspan=4><hr noshade></td>
</tr>
 
<tr>
<td colspan=3>À régler dans <b><%terms%></b> jours au plus tard.</td>
<th colspan=2 align=right>Solde à régler</th>
<th colspan=2 align=right><%total%></th>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
 
</table>
</td>
</tr>
 
<tr>
<td>
<table width="100%">
<tr valign=top>
<%if notes%>
<td>À noter&nbsp;:</td>
<td><%notes%></td>
<%end notes%>
<td align=right>
Tous prix indiqués en <b><%currency%></b>
<br><%shippingpoint%>
</td>
</tr>
 
</table>
</td>
</tr>
 
<tr><td>&nbsp;</td></tr>
 
<%if paid%>
<tr>
<td colspan=7>
<table width="60%">
<tr>
<th align=left>Détail règlements</th>
</tr>
<tr>
<td colspan=4>
<hr noshade>
</td>
</tr>
<tr>
<th align=left>Date</th>
<th align=left>Compte</th>
<th align=left>Source</th>
<th align=left>Montant</th>
</tr>
<%end paid%>
 
<%foreach payment%>
<tr>
<td><%paymentdate%></td>
<td><%paymentaccount%></td>
<td><%paymentsource%></td>
<td><%payment%></td>
</tr>
<%end payment%>
 
<%if paid%>
</table>
</td>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
<%end paid%>
 
<tr>
<th colspan=7>
<!-- <br>Merci beaucoup&amp;nbsp;! -->
</th>
</tr>
 
<tr><td>&nbsp;</td></tr>
 
<tr>
<td>
<table width="100%">
<tr valign=top>
<td><font size=-3>
&nbsp;
</td>
<td width=150>
X <hr noshade>
</td>
</tr>
</table>
</td>
</tr>
 
<!-- <%foreach tax%>
<tr>
<th colspan=7 align=left><font size=-2><%taxdescription%> Numéro de TVA <%taxnumber%></font></th>
</tr>
<%end tax%> -->
 
<%if taxincluded%>
<tr>
<th colspan=7 align=left><font size=-2>Les taxes affichés sont inclus dans le prix.</font></th>
</tr>
<%end taxincluded%>
 
<!-- business number
<tr>
<th colspan=7 align=left><font size=-2>Régistre de Commerce&amp;nbsp;: <%businessnumber%></font></th>
</tr>
-->
 
<!-- information banquaire -->
<tr><td>
<h6><center>N° TVA&nbsp;: &nbsp;&nbsp;Banque&nbsp;: &nbsp;&nbsp;N° de compte&nbsp;: &nbsp;&nbsp;Code SWIFT&nbsp;: </center>
</h6>
</td>
</tr>
 
</table>
 
</td>
</tr>
</table>
 
</body>
</html>
/tags/release_2_0_6-2/templates/Danish-invoice.html
New file
0,0 → 1,273
 
<body bgcolor=ffffff>
 
<table width=100%>
<tr valign=bottom>
<td width=10>&nbsp;</td>
<td>
<table width=100%>
<tr>
<td>
<h4>
<%company%>
<br><%address%>
</h4>
</td>
 
<td align=right>
<h4>
Tlf.: <%tel%>
<br>Fax: <%fax%>
</h4>
</td>
</tr>
 
<tr>
<th colspan=3>
<h4>F A K T U R A</h4>
</th>
</tr>
 
</table>
 
 
<table width=100% callspacing=0 cellpadding=0>
<tr>
<td align=right>
<table>
<tr>
<th align=right>Fakturadato</th><td width=10>&nbsp;</td><td><%invdate%></td>
</tr>
<tr>
<th align=right>Betalingsdato</th><td width=10>&nbsp;</td><td><%duedate%></td>
</tr>
 
<tr>
<th align=right>Fakturanummer</th><td>&nbsp;</td><td><%invnumber%></td></tr>
</tr>
<!--
<tr>
<th align=right>Ekspederet af:</th><td>&nbsp;</td><td><%username%></td>
</tr>
-->
 
<tr>
<td>&nbsp;</td>
</tr>
</td>
</table>
</tr>
 
<tr>
<td>
<table width=100%>
<tr bgcolor=000000>
<th align=left><font color=ffffff>Faktureringsadresse:</th>
<%if shiptoname%>
<th align=left><font color=ffffff>Leveringsadresse:</th>
<%end shiptoname%>
</tr>
 
<!--
other variables which can be use:
contact, shiptocontact, shiptophone, shiptofax
-->
 
<tr>
<td><%name%>
<br><%addr1%>
<br><%addr2%>
<br><%addr3%>
<br><%addr4%>
</td>
<%if shiptoname%>
<td><%shiptoname%>
<br><%shiptoaddr1%>
<br><%shiptoaddr2%>
<br><%shiptoaddr3%>
<br><%shiptoaddr4%>
</td>
<%end shiptoname%>
</tr>
</table>
</td>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
<tr>
<td>
<table width=100%>
<tr bgcolor=000000>
<!-- <th align=right><font color=ffffff>No.</th> -->
<th align=left><font color=ffffff>Varenummer</th>
<th align=left><font color=ffffff>Beskrivelse</th>
<th><font color=ffffff>Antal</th>
<th>&nbsp;</th>
<th><font color=ffffff>Pris</th>
<th><font color=ffffff>Rabat</th>
<th><font color=ffffff>Beløb</th>
</tr>
 
<%foreach number%>
<tr valign=top>
<!-- <td align=right><%runningnumber%>.</td>
adjust the colspan if you include this to shift subtotal one to the right
-->
<td><%number%></td>
<td><%description%></td>
<td align=right><%qty%></td>
<td><%unit%></td>
<td align=right><%sellprice%></td>
<td align=right><%discount%></td>
<td align=right><%linetotal%></td>
</tr>
<%end number%>
 
<!--
you can also use netprice instead of sellprice if you
don't want to show the discount
netprice = sellprice - discount
-->
 
<tr>
<td colspan=7><hr noshade></td>
</tr>
<tr>
<%if taxincluded%>
<th colspan=5 align=right>Total</th>
<td colspan=2 align=right><%invtotal%></td>
<%end taxincluded%>
<%if not taxincluded%>
<th colspan=5 align=right>Subtotal</th>
<td colspan=2 align=right><%subtotal%></td>
<%end taxincluded%>
</tr>
 
<%foreach tax%>
<tr>
<th colspan=5 align=right><%taxdescription%> på <%taxbase%> @ <%taxrate%> %</th>
<td colspan=2 align=right><%tax%></td>
</tr>
<%end tax%>
 
<%if paid%>
<tr>
<th colspan=5 align=right>Allerede betalt</th>
<td colspan=2 align=right>- <%paid%></td>
</tr>
<%end paid%>
 
<tr>
<td colspan=3>&nbsp;</td>
<td colspan=4><hr noshade></td>
</tr>
 
<tr>
<td colspan=3>Betalingsfrist <b><%terms%></b> dage</td>
<th colspan=2 align=right>At betale</th>
<th colspan=2 align=right><%total%></th>
</tr>
 
<tr>
<td>&nbsp;</td>
</tr>
 
</table>
</td>
</tr>
 
<tr>
<td>
<table width=100%>
<tr valign=top>
<%if notes%>
<td>Bemærkninger</td>
<td><%notes%></td>
<%end notes%>
<td align=right>
Alle priser i <b><%currency%></b>.
<br><%shippingpoint%>
</td>
</tr>
 
</table>
</td>
</tr>
 
<tr><td>&nbsp;</td></tr>
<tr>
<th colspan=7>
<br>Tak for handelen!
</th>
</tr>
 
<tr><td>&nbsp;</td></tr>
 
<tr>
<td>
<table width=100%>
<tr valign=top>
<td><font size=-3>
Betalingsfrist <%terms%> dage fra fakturadato. Betaling herefter påregnes
1.5% per påbegyndt måned startende <%duedate%> og indtil det fulde beløb
er betalt. Returnerede varer modregnes 10% i ekspeditionsgebyr.
Et returnummer skal tildeles af <%company%> før varer returneres.
Returvarer skal forsendes forudbetalt og forsvarligt forsikret.
<%company%> kan ikke drages til ansvar for skade under transport.
</font>
</td>
<td width=150>
X <hr noshade>
</td>
</tr>
</table>
</td>
</tr>
 
<%foreach tax%>
<tr>
<th colspan=7 align=left><font size=-2><%taxdescription%> noteret som <%taxnumber%></th>
</tr>
<%end tax%>
 
<%if taxincluded%>
<tr>
<th colspan=7 align=left><font size=-2>Alle beløb er inklusive moms.</th>
</tr>
<%end taxincluded%>
 
<!-- business number
<tr>
<th colspan=7 align=left><font size=-2>CVR-nummer: <%businessnumber%></font></th>
</tr>
-->
 
<!-- banking information
<tr>
<th colspan=7 align=left>Bank-oplysninger:
<br>Bank
<br>Banknummer
<br>Kontonummer
</td>
</tr>
-->
 
</table>
 
</td>
</tr>
</table>
 
</body>
</html>
 
/tags/release_2_0_6-2/templates/German-invoice.html
New file
0,0 → 1,265
 
<body bgcolor=ffffff>
 
<table width=100%>
<tr valign=bottom>
<td width=10>&nbsp;</td>
<td>
<table width=100%>
<tr>
<td>
<h4>
<%company%>
<br><%address%>
</h4>
</td>