Files
pmgr/scripts/sitelink2pmgr.pl

1566 lines
57 KiB
Perl

#perl -w
use strict;
use DBI;
use Data::Dumper;
use File::Copy;
my $use_ir = 1;
# Internally adjust all numbers coming from the database to
# be in inches. Not necessary to go to this detail, but the
# actual units used is irrelevant, provided everything is to
# scale, and this factor ensures that any fractional units
# become whole (e.g. 7.5 "feet" becomes 90 "units")
my $internal_adjustment_factor = 12;
my $schema_file = shift || die("Must specify schema file\n");
my $slink_file = shift || die("Must specify sitelink file\n");
my $slink_file = ";Data Source=$slink_file";
my $slink_pass = ";Jet OLEDB:Database Password=2web";
my $sdsn="Provider=Microsoft.Jet.OLEDB.4.0$slink_pass$slink_file";
my $sdbh = DBI->connect("dbi:ADO:$sdsn", undef, undef, {PrintError => 1,
RaiseError => 1});
# Connect to the database.
my($hostname, $database, $user, $password) = ('localhost',
'property_manager',
'pmgr', 'pmgruser');
my $db_handle = DBI->connect("DBI:mysql:database=$database;host=$hostname",
$user, $password,
{'PrintError' => 1,
'RaiseError' => 0});
$SIG{__DIE__} = \&Die;
my ($query, $result, $nrows, $row);
my (%newdb) = ( 'schema' => [],
'tables' => {},
'ids' => {},
'lookup' => {'state' => { 1=>'AK', 14=>'ID', 48=>'WA' }} );
######################################################################
######################################################################
## Die
sub Die {
my @text = @_;
warn "----------------------------------------------------------\n";
warn "FATAL ERROR: @text\n";
my $count = 0;
{
my ($package, $filename, $line, $sub) = caller($count);
last unless defined $line;
warn sprintf("%02i %5i %-35s %-20s\n", $count++, $line, $sub,
$filename);
redo;
}
exit 1;
}
######################################################################
######################################################################
## addRow
sub addRow {
my ($table, $cols, $noid) = @_;
die unless $table;
die unless ref($cols) eq 'HASH';
die "Table `$table` is unknown!"
unless defined $newdb{'tables'}{$table};
my $id;
if ($noid) {
$id = $cols->{'id'};
}
if (!defined $id) {
$id = ++$newdb{'tables'}{$table}{'autoid'};
}
$cols->{'id'} = $id
unless ($noid);
# For debug purposes
my $line = (caller())[2];
$cols->{'--LINE--'} = "addRow called from line: $line";
$newdb{'tables'}{$table}{'rows'}[$id] = $cols;
return $id;
}
######################################################################
######################################################################
## updateRow
sub updateRow {
my ($table, $id, $cols) = @_;
die unless $table;
die unless $id;
die unless ref($cols) eq 'HASH';
die "Table `$table` is unknown!"
unless defined $newdb{'tables'}{$table};
die "Table `$table` : ID `$id` does not exist!"
unless $newdb{'tables'}{$table}{'rows'}[$id];
# For debug purposes
my $line = (caller())[2];
$cols->{'--UPDATE-LINE--'} = [] unless $cols->{'--UPDATE-LINE--'};
push(@{$cols->{'--UPDATE-LINE--'}}, "updateRow called from line: $line");
#$newdb{'tables'}{$table}{'rows'}[$id] = $cols;
return $id;
}
######################################################################
######################################################################
## query
sub query {
my ($dbh, $sql, $data, $ignore) = @_;
#print("$sql\n\n"); #return [ { 'id' => 7 } ];
#print("$sql\n\n") if $sql =~ /^\s*UPDATE/i;
#return 1 unless $sql =~ /^\s*SELECT/i;
my ($sth, $result);
if ($sql =~ /^\s*SELECT/i) {
$sth = $dbh->prepare($sql);
$sth->execute();
$result = $sth->fetchall_arrayref({});
} else {
$result = $dbh->do($sql);
}
if (!$result && !$ignore) {
print STDERR "SQL Query FAILED:\n";
print STDERR "$sql\n\n";
print STDERR Dumper $data
if defined $data;
die;
}
return ($sth, $result);
}
######################################################################
######################################################################
## executeSchema
sub executeSchema {
foreach (@{$newdb{'schema'}}) {
query($db_handle, $_);
}
foreach my $table (values %{$newdb{'tables'}}) {
foreach (@{$table->{'schema'}}) {
query($db_handle, $_);
}
}
}
######################################################################
######################################################################
## buildTables
sub buildTables {
foreach my $table (values %{$newdb{'tables'}}) {
my $count = 0;
foreach (@{$table->{'rows'}}) {
next unless defined $_;
++$count;
}
printf(STDERR "%-30s : %d rows\n", $table->{'name'}, $count);
foreach (@{$table->{'rows'}}) {
next unless defined $_;
my %row = %$_;
delete $row{'--LINE--'};
my $query;
$query = "INSERT INTO " . $table->{'name'};
$query .= " (" . join(", ", map({"`$_`"} keys(%row))) . ")";
$query .= " VALUES (" . join(", ", map({s/'/''/g if defined $_;
defined $_
? (/^\w+\(.*\)$/
? $_
: "'$_'" )
: "NULL" }
values(%row))) . ")";
query($db_handle, $query, $_);
}
}
}
######################################################################
######################################################################
## helper functions
sub sizeCode {
my ($width, $depth) = @_;
return "YARD"
if ($width == 12 && $depth == 40);
return "APARTMENT"
if ($width == 20 && $depth == 30);
return sprintf("%02dx%02d", $width, $depth);
}
sub datefmt {
my ($dt) = @_;
return undef unless $dt;
my @dt = split(/\/|\s/, $dt);
#print("$dt : " . sprintf("%04d-%02d-%02d", $dt[2], $dt[0], $dt[1]) . "\n");
return sprintf("%04d-%02d-%02d%s", $dt[2], $dt[0], $dt[1], $dt[3] ? ' '.$dt[3] : "");
}
######################################################################
######################################################################
######################################################################
######################################################################
## BUILD THE DATABASE
open(SCHEMA, "<$schema_file") || die ("Can't open schema ($!)\n");
my $schema_query = "";
my $table;
while (<SCHEMA>) {
next if /^\s*--/;
if (/DROP\s+TABLE\s.*`?(pmgr_(\w+))/i) {
$table = $2;
$newdb{'tables'}{$table} = { 'name' => $1,
'schema' => [],
'autoid' => 0,
'rows' => [] };
}
$schema_query .= $_;
if (/;\s*$/) {
$schema_query =~ s/^\s+//;
$schema_query =~ s/\s*;\s*$//;
if (!$table) {
push(@{$newdb{'schema'}}, $schema_query);
} else {
push(@{$newdb{'tables'}{$table}{'schema'}}, $schema_query);
}
$schema_query = "";
}
}
close(SCHEMA);
executeSchema();
#################################################################
## Test Contact
addRow('contacts',
{ 'first_name' => 'Abijah',
'middle_name' => 'M',
'last_name' => 'Perkins' });
addRow('contact_addresses',
{ 'address' => '1324 N Liberty Lake Rd\nPMB 263',
'city' => 'Liberty Lake',
'state' => 'WA',
'postcode' => '99019',
'country' => 'USA' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'},
'method' => 'POST',
'type' => 'MAIN',
'preference' => 'PRIMARY' },
1);
addRow('contact_addresses',
{ 'address' => '5221 W Myrtlewood Ct',
'city' => 'Spokane',
'state' => 'WA',
'postcode' => '99208',
'country' => 'USA' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'},
'method' => 'POST',
'type' => 'HOME',
'preference' => 'ALTERNATE' },
1);
addRow('contact_addresses',
{ 'address' => 'PO Box 69',
'city' => 'Granger',
'state' => 'WA',
'postcode' => '98932',
'country' => 'USA' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'},
'method' => 'POST',
'type' => 'HOME',
'preference' => 'ALTERNATE' },
1);
addRow('contact_phones',
{ 'type' => 'MOBILE',
'phone' => '5098445573' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'MAIN',
'preference' => 'PRIMARY' },
1);
addRow('contact_phones',
{ 'type' => 'MOBILE',
'phone' => '5098445973' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'MAIN',
'preference' => 'ALTERNATE' },
1);
addRow('contact_phones',
{ 'type' => 'VIRTUAL',
'phone' => '5095901112' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'BUSINESS',
'preference' => 'WORK' },
1);
addRow('contact_phones',
{ 'type' => 'LANDLINE',
'phone' => '5098541491' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'HOME',
'preference' => 'ALTERNATE' },
1);
addRow('contact_phones',
{ 'type' => 'VIRTUAL',
'phone' => '8774488664' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'BUSINESS',
'preference' => 'WORK' },
1);
addRow('contact_phones',
{ 'type' => 'FAX',
'phone' => '8662960131' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'BUSINESS',
'preference' => 'WORK' },
1);
addRow('contact_emails',
{ 'email' => 'abijah\@PerkinsHouse.com' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'},
'method' => 'EMAIL',
'type' => 'HOME',
'preference' => 'PRIMARY' },
1);
addRow('contact_emails',
{ 'email' => 'abijah\@PerkinsREI.com' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'},
'method' => 'EMAIL',
'type' => 'HOME',
'preference' => 'WORK' },
1);
addRow('contact_emails',
{ 'email' => 'abijah\@ValleyStorage.com' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'},
'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'},
'method' => 'EMAIL',
'type' => 'BUSINESS',
'preference' => 'WORK' },
1);
#################################################################
## GROUPS
addRow('groups',
{ 'code' => 'Owner',
'name' => 'Owner Group' });
addRow('group_permissions',
{ 'group_id' => $newdb{'tables'}{'groups'}{'autoid'},
'name' => 'EVERYTHING',
'access' => 'FORCED' },
1);
#################################################################
## USERS
addRow('users',
{ 'code' => 'AP',
'login' => 'abijah',
'contact_id' => $newdb{'tables'}{'contacts'}{'autoid'} });
#################################################################
## SITES
addRow('sites',
{ 'code' => 'VSS',
'name' => 'Valley Storage' });
addRow('site_memberships',
{ 'site_id' => $newdb{'tables'}{'sites'}{'autoid'},
'user_id' => $newdb{'tables'}{'users'}{'autoid'},
'group_id' => $newdb{'tables'}{'groups'}{'autoid'} },
1);
addRow('site_areas',
{ 'site_id' => $newdb{'tables'}{'sites'}{'autoid'},
'code' => 'Main',
'name' => 'Main Facility Area' });
#################################################################
## LEASES
addRow('lease_types',
{ 'code' => 'SL',
'name' => 'Storage Lease' });
#################################################################
## LEDGERS
$newdb{'lookup'}{'account'} = {};
$query = "SELECT * FROM pmgr_accounts";
$result = query($db_handle, $query);
foreach $row (@$result) {
addRow('ledgers',
{ 'account_id' => $row->{'id'},
'comment' => undef });
$newdb{'lookup'}{'account'}{$row->{'name'}}
= {'account_id' => $row->{'id'},
'tillable' => $row->{'tillable'},
'ledger_id' => $newdb{'tables'}{'ledgers'}{'autoid'} };
if ((!defined $newdb{'tables'}{'accounts'}{'autoid'}) ||
$row->{'id'} > $newdb{'tables'}{'accounts'}{'autoid'}) {
$newdb{'tables'}{'accounts'}{'autoid'} = $row->{'id'};
}
}
# For compatibility, while deciding on account names
if (!defined $newdb{'lookup'}{'account'}{'Cash'}) {
$newdb{'lookup'}{'account'}{'Cash'}
= $newdb{'lookup'}{'account'}{'Till'};
}
$newdb{'lookup'}{'charge_type'} = {};
$newdb{'lookup'}{'charge_type'}{'Rent'} =
$newdb{'lookup'}{'account'}{'Rent'};
$newdb{'lookup'}{'charge_type'}{'Late Fee'} =
$newdb{'lookup'}{'account'}{'Late Charge'};
$newdb{'lookup'}{'charge_type'}{'Security Deposit'} =
$newdb{'lookup'}{'account'}{'Security Deposit'};
#################################################################
## MONETARY
$newdb{'lookup'}{'monetary_type'} = {};
$query = "SELECT * FROM pmgr_monetary_types";
$result = query($db_handle, $query);
foreach $row (@$result) {
$newdb{'lookup'}{'monetary_type'}{$row->{'name'}}
= {'id' => $row->{'id'} };
}
$newdb{'lookup'}{'payment_type'} = {};
$newdb{'lookup'}{'payment_type'}{1}
= { 'name' => 'Cash', 'account_name' => 'Cash', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Cash'} };
$newdb{'lookup'}{'payment_type'}{2}
= { 'name' => 'Check', 'account_name' => 'Check', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Check'} };
$newdb{'lookup'}{'payment_type'}{3}
= { 'name' => 'Money Order', 'account_name' => 'Money Order', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Money Order'} };
$newdb{'lookup'}{'payment_type'}{4}
= { 'name' => 'ACH', 'account_name' => 'Bank', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'ACH'} };
$newdb{'lookup'}{'payment_type'}{12}
= { 'name' => 'Concession', 'account_name' => 'Concession', 'monetary_type' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'} };
$newdb{'ids'}{'monetary_source'} = {};
$newdb{'ids'}{'monetary_source'}{'internal'} = undef;
addRow('monetary_sources',
{ 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Cash'}{'id'},
'name' => 'Cash',
'comment' => 'Monetary source used for any cash transaction' });
$newdb{'ids'}{'monetary_source'}{'Cash'} =
$newdb{'tables'}{'monetary_sources'}{'autoid'};
addRow('monetary_sources',
{ 'monetary_type_id' => $newdb{'lookup'}{'monetary_type'}{'Other Non-Tillable'}{'id'},
'name' => 'Closing',
'comment' => 'Credited at the closing table' });
$newdb{'ids'}{'monetary_source'}{'Closing'} =
$newdb{'tables'}{'monetary_sources'}{'autoid'};
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
##
## UNITS
##
my @unit_sort_order =
qw(
A01 A02 A03 A04 A05 A06
B01 B02 B03 B04 B05 B06 B07
C01 C02 C03 C04 C05 C06 C07 C08 C09
10 11 12 13 14 15 16 17 18 19 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
D01 D02 D03 D04 D05 D06 D07 D08 D09 D10 D11
APT
Y01 Y02 Y03 Y04 Y05 Y06 Y07 Y08 Y09 Y10
);
my $unit_sort_order = 0;
my %unit_sort_order;
foreach (@unit_sort_order) {
$unit_sort_order += 1; # use 100 for later insertion
$unit_sort_order{$_} = $unit_sort_order;
}
my @unit_walk_order =
qw(
19 18 17 16 15 14 13 12 11 10
C01 C02 C03 C04 C05 C06 C07 C08 C09
APT
38 37 36 35 34 33 32 31 30 29 28
B01 B02 B03 B04 B05 B06 B07
A01 A02 A03 A04 A05 A06
27 26 25 24 23 22
D11 D10 D09 D08 D07 D06 D05 D04 D03 D02 D01
45 44 43 42 41 40 39
Y01 Y02 Y03 Y04 Y05 Y06 Y07 Y08 Y09 Y10
);
my $unit_walk_order = 0;
my %unit_walk_order;
foreach (@unit_walk_order) {
$unit_walk_order += 1; # use 100 for later insertion
$unit_walk_order{$_} = $unit_walk_order;
}
######################################################################
## Unit Types
$newdb{'lookup'}{'unit_type'} = {};
$query = "SELECT * FROM UnitType ORDER BY TypeID";
foreach $row (@{query($sdbh, $query)}) {
addRow('unit_types',
{ 'code' => 'xxx',
'name' => $row->{'UnitType'} });
$newdb{'lookup'}{'unit_type'}{$row->{'TypeID'}} =
$newdb{'tables'}{'unit_types'}{'autoid'};
}
######################################################################
## Unit Sizes
$newdb{'lookup'}{'unit_size'} = {};
$query = "SELECT * FROM UnitInfo WHERE UnitID <> 'POS\$' ORDER BY UnitID";
foreach $row (@{query($sdbh, $query)}) {
my $sz = sizeCode($row->{'Width'}, $row->{'Depth'});
next if defined $newdb{'lookup'}{'unit_size'}{$sz};
addRow('unit_sizes',
{ 'unit_type_id' => $row->{'Type'},
'code' => $sz,
'name' => $sz,
'width' => $internal_adjustment_factor * $row->{'Width'},
'depth' => $internal_adjustment_factor * $row->{'Depth'},
'deposit' => $row->{'StdSecDep'},
'rent' => $row->{'StdRent'} });
$newdb{'lookup'}{'unit_size'}{$sz}
= { 'id' => $newdb{'tables'}{'unit_sizes'}{'autoid'},
'rent' => $row->{'StdRent'},
'dep' => $row->{'StdSecDep'} };
}
######################################################################
## Units
$newdb{'lookup'}{'unit'} = {};
foreach $row (@{query($sdbh, $query)}) {
my $sz = sizeCode($row->{'Width'}, $row->{'Depth'});
my $szid = $newdb{'lookup'}{'unit_size'}{$sz}{'id'};
addRow('units',
{ 'unit_size_id' => $szid,
'code' => $row->{'UnitID'},
'name' => $row->{'UnitID'},
'status' => $row->{'Rented'} ?'OCCUPIED' :($row->{'Rentable'} ?'VACANT' :'UNAVAILABLE'),
'sort_order' => $unit_sort_order{$row->{'UnitID'}},
'walk_order' => $unit_walk_order{$row->{'UnitID'}},
'deposit' => $row->{'StdSecDep'},
'rent' => $row->{'StdRent'} });
$newdb{'lookup'}{'unit'}{$row->{'UnitID'}}
= { 'id' => $newdb{'tables'}{'units'}{'autoid'} };
}
######################################################################
## Map
my %info = ('extents' => {}, 'units' => {});
# Get the overall site limits
$query = "SELECT MIN(M.Top) AS mintop, MIN(M.Left) AS minlft,";
$query .= " MAX(M.Top + IIF(M.reverseWL, U.Width, U.Depth)) AS bot,";
$query .= " MAX(M.Left + IIF(M.reverseWL, U.Depth, U.Width)) AS rgt";
$query .= ' FROM UnitInfo U INNER JOIN mapUnitsV2 M ON M.unitID = U.UnitID';
$result = query($sdbh, $query);
# Fetch and verify the result
my $row = shift(@$result);
die("MIN query failed!") unless $row;
# Compute the actual boundaries, adjusting for a (0,0) origin
my $top_adjustment = 0 - $row->{'mintop'};
my $left_adjustment = 0 - $row->{'minlft'};
$info{'extents'}{'top'} = 0;
$info{'extents'}{'left'} = 0;
$info{'extents'}{'bottom'} = $internal_adjustment_factor * ($top_adjustment + $row->{'bot'} + 0);
$info{'extents'}{'right'} = $internal_adjustment_factor * ($left_adjustment + $row->{'rgt'} + 0);
addRow('maps',
{ 'name' => 'Main Facility Map',
'site_area_id' => $newdb{'tables'}{'site_areas'}{'autoid'},
'width' => $info{'extents'}{'right'} - $info{'extents'}{'left'},
'depth' => $info{'extents'}{'bottom'} - $info{'extents'}{'top'} });
# Get list of units and positions
$query = "SELECT U.UnitID, U.UnitID as name,";
$query .= " ($top_adjustment + M.Top) AS pt_t,";
$query .= " ($left_adjustment + M.Left) AS pt_l,";
$query .= " IIF(M.reverseWL, U.Depth, U.Width) AS Width,";
$query .= " IIF(M.reverseWL, U.Width, U.Depth) AS Depth,";
$query .= " M.reverseWL, U.Rented, U.Rentable";
$query .= " FROM UnitInfo U INNER JOIN mapUnitsV2 M ON M.unitID = U.UnitID";
# Go through each one, calculating the map location
foreach $row (@{query($sdbh, $query)}) {
addRow('maps_units',
{ 'map_id' => $newdb{'tables'}{'maps'}{'autoid'},
'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'},
'pt_top' => $internal_adjustment_factor * ($row->{'pt_t'}),
'pt_left' => $internal_adjustment_factor * ($row->{'pt_l'}),
'transpose' => $row->{'reverseWL'} });
}
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
##
## TENANTS
##
######################################################################
## Tenants
$newdb{'lookup'}{'tenant'} = {};
$query = "SELECT * FROM TenantInfo WHERE FirstName <> 'POS' ORDER BY TenantID";
foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}
= { 'name' => "$row->{'LastName'}, $row->{'FirstName'}" };
addRow('contacts',
{ 'first_name' => $row->{'FirstName'},
'middle_name' => $row->{'MiddleName'},
'last_name' => $row->{'LastName'},
'id_local' => $row->{'IDNum'} || undef,
'id_local_state' => $row->{'IDNum'} ? $newdb{'lookup'}{'state'}{$row->{'DLStateID'}} : undef });
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'} =
$newdb{'tables'}{'contacts'}{'autoid'};
addRow('customers',
{ 'name' => "$row->{'LastName'}, $row->{'FirstName'}",
'primary_contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'},
});
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} =
$newdb{'tables'}{'customers'}{'autoid'};
addRow('contacts_customers',
{ 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'},
'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'},
'type' => 'TENANT' },
1);
if ($row->{'City'}) {
addRow('contact_addresses',
{ 'address' => $row->{'HomeAddress'} . ($row->{'HomeAddr2'} ? "\n".$row->{'HomeAddr2'} : "") || undef,
'city' => $row->{'City'},
'state' => $newdb{'lookup'}{'state'}{$row->{'StateID'}},
'postcode' => $row->{'Zip'} || undef,
'country' => 'USA' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'},
'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'},
'method' => 'POST',
'type' => 'HOME',
'preference' => 'PRIMARY' },
1);
}
foreach ({'type' => 'LANDLINE', 'preference' => 'PRIMARY', 'phone' => $row->{'Phone'}},
{'type' => 'LANDLINE', 'preference' => 'WORK',
'phone' => $row->{'BusinessPhone'}, 'ext' => $row->{'BusinessExt'}},
{'type' => 'FAX', 'preference' => 'PRIMARY', 'phone' => $row->{'FAX'}},
{'type' => 'PAGER', 'preference' => 'PRIMARY', 'phone' => $row->{'Pager'}},
{'type' => 'MOBILE', 'preference' => 'ALTERNATE', 'phone' => $row->{'CellPhone'}})
{
if ($_->{'phone'}) {
addRow('contact_phones',
{ 'type' => $_->{'type'},
'phone' => $_->{'phone'},
'ext' => $_->{'ext'} });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'MAIN',
'preference' => $_->{'preference'} },
1);
}
}
if ($row->{'Email'}) {
addRow('contact_emails',
{ 'email' => $row->{'Email'} });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'id'},
'method_id' => $newdb{'tables'}{'contact_emails'}{'autoid'},
'method' => 'EMAIL',
'type' => 'MAIN',
'preference' => 'PRIMARY' },
1);
}
next unless $row->{'AltFirstName'} || $row->{'AltLastName'} || $row->{'AltAddress'} || $row->{'AltPhone'};
addRow('contacts',
{ 'first_name' => $row->{'AltFirstName'} || undef,
'middle_name' => $row->{'AltMI'} || undef,
'last_name' => $row->{'AltLastName'} || undef });
$newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'} =
$newdb{'tables'}{'contacts'}{'autoid'};
addRow('contacts_customers',
{ 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'},
'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'},
'type' => 'ALTERNATE' },
1);
if ($row->{'AltCity'}) {
addRow('contact_addresses',
{ 'address' => $row->{'AltAddress'} . ($row->{'AltAddr2'} ? "\n".$row->{'AltAddr2'} : ""),
'city' => $row->{'AltCity'},
'state' => $newdb{'lookup'}{'state'}{$row->{'AltStateID'}},
'postcode' => $row->{'AltZip'},
'country' => 'USA' });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'},
'method_id' => $newdb{'tables'}{'contact_addresses'}{'autoid'},
'method' => 'POST',
'type' => 'MAIN',
'preference' => 'PRIMARY' },
1);
}
if ($row->{'AltPhone'}) {
addRow('contact_phones',
{ 'type' => 'LANDLINE',
'phone' => $row->{'AltPhone'},
'ext' => undef });
addRow('contacts_methods',
{ 'contact_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'alt'},
'method_id' => $newdb{'tables'}{'contact_phones'}{'autoid'},
'method' => 'PHONE',
'type' => 'MAIN',
'preference' => 'PRIMARY' },
1);
}
}
######################################################################
## Tenant Leases
$newdb{'lookup'}{'ledger'} = {};
$query = "SELECT L.*, A.TenantID FROM TenantLedger L LEFT JOIN `Access` A ON A.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' ORDER BY L.DateIn";
foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}
= { 'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'} };
addRow('leases',
{ 'number' => $newdb{'tables'}{'leases'}{'autoid'}+1,
#'number' => $row->{'LedgerID'},
'lease_type_id' => $newdb{'tables'}{'lease_types'}{'autoid'},
'unit_id' => $newdb{'lookup'}{'unit'}{$row->{'UnitID'}}{'id'},
'customer_id' => $newdb{'lookup'}{'tenant'}{$row->{'TenantID'}}{'customer_id'},
'lease_date' => datefmt($row->{'DateIn'}),
'movein_date' => datefmt($row->{'DateIn'}),
'moveout_date' => datefmt($row->{'DateOut'}),
'close_date' => datefmt($row->{'DateClosed'}),
'rent' => $row->{'Rent'} });
$newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'} =
$newdb{'tables'}{'leases'}{'autoid'};
}
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
##
## TRANSACTIONS
##
######################################################################
## Invoices
$newdb{'lookup'}{'charge'} = {};
$query = "SELECT *, ChargeAmount+TaxAmount AS InvoiceAmount FROM Charges ORDER BY ChargeID";
foreach $row (@{query($sdbh, $query)}) {
addRow('transactions',
{ 'stamp' => datefmt($row->{'ChargeDate'}),
'through_date' => datefmt($row->{'EndDate'}) });
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}
= { 'invoice' =>
{ 'tx' => $newdb{'tables'}{'transactions'}{'autoid'},
'lease_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'},
'customer_id' => $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'},
'amount' => $row->{'InvoiceAmount'},
} };
addRow('transactions',
{ 'stamp' => datefmt($row->{'ChargeDate'}),
'through_date' => datefmt($row->{'EndDate'}) });
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'}
= $newdb{'tables'}{'transactions'}{'autoid'};
# Invoice must debit the A/R ledger...
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'}
= $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'};
# ...and credit the Invoice ledger.
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'}
= $newdb{'lookup'}{'account'}{'Invoice'}{'ledger_id'};
# Create the invoice entry
# debit: A/R credit: Invoice
addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'},
'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'customer_id'},
'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'lease_id'},
'amount' => $row->{'InvoiceAmount'},
'comment' => "Invoice: Charge: $row->{'ChargeID'}" });
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
}
######################################################################
## Charges
$query = "SELECT * FROM Charges ORDER BY ChargeID";
foreach $row (@{query($sdbh, $query)}) {
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'}
= $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'charge_tx'};
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'}
= $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'customer_id'};
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'}
= $newdb{'lookup'}{'ledger'}{$row->{'LedgerID'}}{'lease_id'};
# Charge must credit the invoice ledger...
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'}
= $newdb{'lookup'}{'charge_type'}{$row->{'ChargeDescription'}}{'ledger_id'};
# ...and debit the A/R ledger.
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'}
= $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'credit_ledger_id'};
# Add the charge entry
# debit: Invoice credit: Rent/LateCharge/Etc
addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'credit_ledger_id'},
'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'},
'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'},
'amount' => $row->{'ChargeAmount'},
'comment' => "Charge: $row->{'ChargeID'}; Ledger: $row->{'LedgerID'}" });
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
# Reconcile the Invoice account. Our two entries look like:
# debit: Invoice credit: Rent/LateCharge/Etc
# debit: A/R credit: Invoice
# Since this is from the perspective of the Invoice account,
# the credit entry is the Invoice<->A/R, and the debit
# entry is the actual charge ledger entry.
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'ledger_entry_id'},
'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'},
'amount' => $row->{'ChargeAmount'},
});
next unless $row->{'TaxAmount'};
# Add the tax charge entry
# debit: Invoice credit: Tax
addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'},
'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'},
'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'},
'amount' => $row->{'TaxAmount'},
'comment' => "Tax for ChargeID:$row->{'ChargeID'}" });
$newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
# Reconcile the Invoice account. Our two entries look like:
# debit: Invoice credit: Tax
# debit: A/R credit: Invoice
# Since this is from the perspective of the Invoice account,
# the credit entry is the Invoice<->A/R, and the debit
# entry is the actual tax ledger entry.
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'tax_ledger_entry_id'},
'credit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'},
'amount' => $row->{'TaxAmount'},
});
}
######################################################################
## Receipts
$newdb{'lookup'}{'receipt'} = {};
############################################################
############################################################
############################################################
# REVISIT <AP> 20090630
# Handling of receipts is all backwards. The way things
# _should_ look if someone provides Cash and Check to pay
# rent & tax for two units (50 on UnitA and 40 UnitB):
#
# RENT TAX INVOICE A/R RECEIPT CASH CHECK
# ------- ------- ------- ------- ------- ------- -------
# |50 | 50| | | | |
# | | 5 5| | | | |
# | | |55 55| | | |
# |40 | 40| | | | |
# | | 4 4| | | | |
# | | |44 44| | | |
# | | | | |79 | 79|
# | | | | |20 20| |
# | | | |99 99| | |
# | | | | | | |
#
# HOWEVER,
# Our current implementation MUST match LedgerEntry to
# LedgerEntry for reconcile purposes. Thus, although there
# is a way to reconcile that $50 was received, there is no
# way to flag the payment as being for UnitA, unless we
# either rely on the charge to determine the fact (a
# solution that has proven very messy), or we add it to
# the reconciliations table. The hope, for simplicity's
# sake, was to ensure there was a single ledger entry in
# A/R for each payment that could correspond to a lease/unit,
# so that no A/R ledger entry ever represented payment for
# more than one lease. However, to do so, our ledgers
# appear like this instead:
#
# RENT TAX INVOICE A/R RECEIPT CASH CHECK
# ------- ------- ------- ------- ------- ------- -------
# |50 | 50| | | | |
# | | 5 5| | | | |
# | | |55 55| | | |
# |40 | 40| | | | |
# | | 4 4| | | | |
# | | |44 44| | | |
# | | | | |79 | 79|
# | | | | |20 20| |
# | | | |50 50| | |
# | | | | 5 5| | |
# | | | |40 40| | |
# | | | | 4 4| | |
# | | | | | | |
#
# There is another possible solution, although it is
# very probably ledger overkill (even invoice/receipt
# already fall into the overkill category).
#
# RENT TAX INVOICE A/R MERGE RECEIPT CASH CHECK
# ------- ------- ------- ------- ------- ------- ------- -------
# |50 | 50| | | | | |
# | | 5 5| | | | | |
# | | |55 55| | | | |
# |40 | 40| | | | | |
# | | 4 4| | | | | |
# | | |44 44| | | | |
# | | | | | |79 | 79|
# | | | | | |20 20| |
# | | | | |50 50| | |
# | | | | | 5 5| | |
# | | | | |40 40| | |
# | | | | | 4 4| | |
# | | | |99 99| | | |
# | | | | | | | |
#
# I might opt for this last option, but ultimately, none
# of these are really correct. We need a better solution.
# Until then, I'll go with the easiest.
############################################################
############################################################
############################################################
# Sitelink splits one physical payment into multiple "payments" to match each charge.
# The solution here is kludgy, but for our cases at least, it brings those pseudo-payments
# back into a single one. This presumes there is only one PaymentType per receipt.
$query =
"SELECT R.ReceiptNum, R.ReceiptDate, P.PaymentType, P.CheckNum, SUM(P.PaymentAmount) AS ReceiptAmount" .
" FROM Receipts R, Payments P" .
" WHERE P.ReceiptNum = R.ReceiptNum" .
" GROUP BY R.ReceiptNum, R.ReceiptDate, P.PaymentType, P.CheckNum" .
" ORDER BY R.ReceiptNum, P.PaymentType";
foreach $row (@{query($sdbh, $query)}) {
# if ($newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}) {
# next;
# }
if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}) {
addRow('transactions',
{ 'stamp' => datefmt($row->{'ReceiptDate'}),
'through_date' => undef });
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}
= {'tx' => $newdb{'tables'}{'transactions'}{'autoid'},
'date' => datefmt($row->{'ReceiptDate'}),
};
addRow('transactions',
{ 'stamp' => datefmt($row->{'ReceiptDate'}),
'through_date' => undef });
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'payment_tx'}
= $newdb{'tables'}{'transactions'}{'autoid'};
}
if ($row->{'ReceiptDate'} =~ m%3/25/2009%) {
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}
= $newdb{'ids'}{'monetary_source'}{'Closing'};
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'}
= 'Bank';
}
else {
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}
= $newdb{'ids'}{'monetary_source'}{
$newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'}
};
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'}
= $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'account_name'};
}
# Set up a monetary source for the receipt,
if (!$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}) {
my $name = $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'name'};
my $data1;
if ($name eq 'Check') {
$name = 'Check #' . $row->{'CheckNum'};
$data1 = $row->{'CheckNum'};
}
addRow('monetary_sources',
{ 'monetary_type_id' => $newdb{'lookup'}{'payment_type'}{$row->{'PaymentType'}}{'monetary_type'}{'id'},
'name' => $name,
'data1' => $data1,
'comment' => "Receipt:$row->{'ReceiptNum'}; Payment:$row->{'PaymentType'}; Check:$row->{'CheckNum'}" });
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'}
= $newdb{'tables'}{'monetary_sources'}{'autoid'};
}
# Receipt must debit the "money" asset (bank, cash, check, etc)...
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'}
= $newdb{'lookup'}{'account'}{
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'account_name'}
}{'ledger_id'};
# ...and credit the Receipt ledger
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'}
= $newdb{'lookup'}{'account'}{'Receipt'}{'ledger_id'};
# NOTE THE ABOVE LARGE COMMENT BLOCK
# The choice of credit/debit ledgers does not mirror the
# choices for invoice. This _should_ be A/R to Receipt,
# but it is Money to Receipt instead.
# debit: Cash/Check/Etc credit: Receipt
addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'monetary_source_id'},
'transaction_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'},
'amount' => $row->{'ReceiptAmount'},
'comment' => "Receipt: $row->{'ReceiptNum'}; " });
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
}
######################################################################
## Payments
$newdb{'lookup'}{'payment'} = {};
$query = "SELECT * FROM Payments ORDER BY PaymentID";
foreach $row (@{query($sdbh, $query)})
{
# addRow('transactions',
# { 'stamp' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'date'},
# 'through_date' => undef });
# $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}
# = {'tx' => $newdb{'tables'}{'transactions'}{'autoid'} };
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}
= { 'tx' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'payment_tx'} };
# NOTE THE ABOVE LARGE COMMENT BLOCK
# The choice of credit/debit ledgers does not mirror the
# choices for charges. This _should_ be Money to Receipt,
# but it is A/R to Receipt instead.
# Ensure Receipt has the right customer
$newdb{'tables'}{'ledger_entries'}{'rows'}[
$newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'}
]{'customer_id'} = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'};
# Payment must debit the associated receipt ledger (which should be Receipt)...
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'}
= $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'credit_ledger_id'};
# ...and credit the A/R ledger.
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'}
= $newdb{'lookup'}{'account'}{'A/R'}{'ledger_id'};
# Add the payment entry
# debit: Receipt credit: A/R
addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'tx'},
'debit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'debit_ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'credit_ledger_id'},
'customer_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'customer_id'},
'lease_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'lease_id'},
'amount' => $row->{'PaymentAmount'},
'comment' => "Receipt: $row->{'ReceiptNum'}; Charge: $row->{'ChargeID'}; Payment: $row->{'PaymentID'}" });
$newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'}
= $newdb{'tables'}{'ledger_entries'}{'autoid'};
# Reconcile the Receipt account. Our two entries look like:
# debit: Cash/Check/Etc credit: Receipt
# debit: Receipt credit: A/R
# Since this is from the perspective of the Receipt account,
# the debit entry is the Receipt<->A/R, and the credit
# entry is the actual receipt ledger entry.
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'},
'credit_ledger_entry_id' => $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{$row->{'PaymentType'}}{'ledger_entry_id'},
'amount' => $row->{'PaymentAmount'},
});
# Figure out how much of the charge can be reconciled
my $reconcile_amount = $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'amount'};
#print STDERR Dumper($newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}); exit;
$reconcile_amount = $row->{'PaymentAmount'} if $row->{'PaymentAmount'} <= $reconcile_amount;
# Reconcile the A/R account. Our two entries look like:
# debit: Receipt credit: A/R
# debit: A/R credit: Invoice
# Since this is from the perspective of the A/R account,
# the debit entry is the Invoice<->A/R, and the credit
# entry is the Receipt<->A/R.
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $newdb{'lookup'}{'charge'}{$row->{'ChargeID'}}{'invoice'}{'ledger_entry_id'},
'credit_ledger_entry_id' => $newdb{'lookup'}{'payment'}{$row->{'PaymentID'}}{'ledger_entry_id'},
'amount' => $reconcile_amount,
});
# Update the transaction to use the memo from this payment
if ($row->{'Memo'}) {
my $txid = $newdb{'lookup'}{'receipt'}{$row->{'ReceiptNum'}}{'tx'};
$newdb{'tables'}{'transactions'}{'rows'}[$txid]{'comment'} = $row->{'Memo'};
}
}
######################################################################
## Fake Data for Testing
my %fake =
('customer_id' => 4,
'ledger_id' => 4,
'invoice' => [ { 'id' => 1000,
'date' => '2009-05-05',
'entry' => [ { 'id' => 2100,
'account_name' => 'Security Deposit',
'amount' => 10,
'tax' => 0 },
],
},
{ 'id' => 1001,
'date' => '2009-05-01',
'thru' => '2009-05-31',
'entry' => [ { 'id' => 2110,
'account_name' => 'Rent',
'amount' => 100,
'tax' => 5 },
],
},
{ 'id' => 1002,
'date' => '2009-05-11',
'entry' => [ { 'id' => 2120,
'account_name' => 'Late Charge',
'amount' => 25,
'tax' => 0 },
],
},
],
'receipt' => [ { 'id' => 2000,
'date' => '2009-05-15',
'entry' => [ { 'id' => 2200,
'track' => [ { 'debit'=>2100, 'amount'=>10 },
{ 'debit'=>2110, 'amount'=>5 } ],
'type' => 1,
'amount' => 15 },
{ 'id' => 2201,
'track' => [ { 'debit'=>2110, 'amount'=>10 } ],
'type' => 2,
'amount' => 10 },
{ 'id' => 2202,
'track' => [ { 'debit'=>2110, 'amount'=>5 } ],
'type' => 3,
'amount' => 5 },
],
},
{ 'id' => 2001,
'date' => '2009-05-18',
'entry' => [ { 'id' => 2210,
'track' => [ { 'debit'=>2110, 'amount'=>30 } ],
'type' => 5,
'amount' => 30 },
{ 'id' => 2211,
'track' => [ { 'debit'=>2110, 'amount'=>20 } ],
'type' => 6,
'amount' => 20 },
],
},
{ 'id' => 2002,
'date' => '2009-05-22',
'entry' => [ { 'id' => 2220,
'track' => [ { 'debit'=>2110, 'amount'=>10 } ],
'type' => 1,
'amount' => 10 },
{ 'id' => 2221,
'track' => [ { 'debit'=>2110, 'amount'=>5 } ],
'type' => 2,
'amount' => 5 },
{ 'id' => 2222,
'track' => [ { 'debit'=>2110, 'amount'=>15 },
{ 'debit'=>2111, 'amount'=>5 },
{ 'debit'=>2120, 'amount'=>5 } ],
'type' => 7,
'amount' => 25 },
{ 'id' => 2223,
'track' => [ { 'debit'=>2120, 'amount'=>20 } ],
'type' => 8,
'amount' => 30 },
],
},
],
);
sub fakeTesting {
$newdb{'ids'}{'ledger'}{'Cash-Old'} =
$newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'};
addRow('ledgers',
{ 'account_id' => $newdb{'lookup'}{'account'}{'Cash'}{'account_id'},
'open_stamp' => 'NOW()',
'sequence' => 2,
'comment' => 'Opened new ledger for testing' });
$newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'} =
$newdb{'tables'}{'ledgers'}{'autoid'};
my $balance = 0;
foreach $row (@{$newdb{'tables'}{'ledger_entries'}{'rows'}}) {
next unless defined $row;
$balance += $row->{'amount'}
if $row->{'debit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'};
$balance -= $row->{'amount'}
if $row->{'credit_ledger_id'} == $newdb{'ids'}{'ledger'}{'Cash-Old'};
}
addRow('transactions',
{ 'stamp' => '2009-04-30' });
addRow('ledger_entries',
{ 'monetary_source_id' => $newdb{'ids'}{'monetary_source'}{'internal'},
'transaction_id' => $newdb{'tables'}{'transactions'}{'autoid'},
'debit_ledger_id' => $newdb{'lookup'}{'account'}{'Cash'}{'ledger_id'},
'credit_ledger_id' => $newdb{'ids'}{'ledger'}{'Cash-Old'},
'amount' => $balance,
'name' => "Close Out ($newdb{'ids'}{'ledger'}{'Cash-Old'} -> $newdb{'tables'}{'transactions'}{'autoid'})",
'comment' => "Carrying forward old ledger balance onto new ledger" });
# NOTE: no tracking for the Cash account
$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'closed'} = 1;
$newdb{'tables'}{'ledgers'}{'rows'}[$newdb{'ids'}{'ledger'}{'Cash-Old'}]{'close_stamp'} = 'NOW()';
foreach my $ir ('invoice', 'receipt') {
foreach my $tx (@{$fake{$ir}}) {
#print Dumper ${%$tx{'date'}};
#exit;
addRow('transactions',
{ 'id' => $tx->{'id'},
'stamp' => $tx->{'date'},
'through_date' => $tx->{'thru'},
'comment' => "Fake $ir" },
1);
foreach my $e (@{$tx->{'entry'}}) {
my $ircrdr = ($ir eq 'invoice') ? 'Invoice' : 'Receipt';
my $dr = ($ir eq 'invoice') ? 'A/R' : 'Cash';
my $cr = ($ir eq 'invoice') ? $e->{'account_name'} : 'A/R';
my $crdr;
my $monetary_source_id;
if (defined $e->{'type'}) {
addRow('monetary_sources',
{ 'monetary_type_id' => $e->{'type'},
'name' => "Money of type " . $e->{'type'},
'comment' => "Fake Money For " . $e->{'id'} });
$monetary_source_id = $newdb{'tables'}{'monetary_sources'}{'autoid'};
}
else {
$monetary_source_id = $newdb{'ids'}{'monetary_source'}{'internal'};
}
$crdr = $dr;
if ($use_ir) {
$crdr = $ircrdr;
addRow('ledger_entries',
{ 'id' => $e->{'id'}+10000,
'monetary_source_id' => ($ir eq 'invoice' ? undef : $monetary_source_id),
'transaction_id' => $tx->{'id'},
'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
'customer_id' => $fake{'customer_id'},
#'lease_id' => $fake{'lease_id'},
'amount' => $e->{'amount'},
'comment' => "Fake $ir entry" },
1);
}
addRow('ledger_entries',
{ 'id' => $e->{'id'},
'monetary_source_id' => ($ir eq 'invoice' ? $monetary_source_id : undef),
'transaction_id' => $tx->{'id'},
'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{$cr}{'ledger_id'},
'customer_id' => $fake{'customer_id'},
'lease_id' => $fake{'lease_id'},
'amount' => $e->{'amount'},
'comment' => "Fake Entry" },
1);
if ($use_ir) {
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 10000 : 0),
'credit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 0 : 10000),
'amount' => $e->{'amount'},
});
}
foreach my $t (@{$e->{'track'}}) {
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $t->{'debit'},
'credit_ledger_entry_id' => $e->{'id'},
'amount' => $t->{'amount'}
});
}
next unless $e->{'tax'};
$crdr = $dr;
if ($use_ir) {
$crdr = $ircrdr;
addRow('ledger_entries',
{ 'id' => $e->{'id'}+10001,
'monetary_source_id' => ($ir eq 'invoice' ? undef : $monetary_source_id),
'transaction_id' => $tx->{'id'},
'debit_ledger_id' => $newdb{'lookup'}{'account'}{$dr}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
'customer_id' => $fake{'customer_id'},
#'lease_id' => $fake{'lease_id'},
'amount' => $e->{'tax'},
'comment' => "Fake Tax Invoice Entry" },
1);
}
addRow('ledger_entries',
{ 'id' => $e->{'id'}+1,
'monetary_source_id' => ($ir eq 'invoice' ? $monetary_source_id : undef),
'transaction_id' => $tx->{'id'},
'debit_ledger_id' => $newdb{'lookup'}{'account'}{$crdr}{'ledger_id'},
'credit_ledger_id' => $newdb{'lookup'}{'account'}{'Tax'}{'ledger_id'},
'customer_id' => $fake{'customer_id'},
'lease_id' => $fake{'lease_id'},
'amount' => $e->{'tax'},
'comment' => "Fake Tax Entry" },
1);
if ($use_ir) {
addRow('reconciliations',
{ 'debit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 10001 : 1),
'credit_ledger_entry_id' => $e->{'id'} + ($ir eq 'invoice' ? 1 : 10001),
'amount' => $e->{'tax'},
});
}
}
}
}
}
#fakeTesting();
$Data::Dumper::Sortkeys = 1;
print Dumper \%newdb;
# exit;
buildTables();
######################################################################
## Security Deposits
$query = "SELECT L.LedgerID, L.UnitID, C.ChargeAmount FROM TenantLedger L INNER JOIN Charges C ON C.LedgerID = L.LedgerID WHERE L.UnitID <> 'POS\$' AND C.ChargeDescription = 'Security Deposit' ORDER BY UnitID";
foreach $row (@{query($sdbh, $query)}) {
#my $uid = $newdb{'lookup'}{'unit'}{$row->{'UnitID'}};
$query = "UPDATE pmgr_leases
SET deposit = $row->{'ChargeAmount'}
WHERE `number` = '$row->{'LedgerID'}'";
query($db_handle, $query, $row);
}
######################################################################
## Ledger Assignments
# $query =
# "UPDATE pmgr_accounts A, pmgr_ledgers L SET A.ledger_id = L.id" .
# " WHERE A.id = L.account_id";
# query($db_handle, $query);
######################################################################
## Unit Lease Assignments
$query = "UPDATE pmgr_units U, pmgr_leases L
SET U.`current_lease_id` = L.id
WHERE L.unit_id = U.id AND L.close_date IS NULL";
query($db_handle, $query);