added ORM api and some tests

This commit is contained in:
Florian "flowdy" Heß 2016-06-26 17:49:12 +02:00
parent dbbada8307
commit 57556d252b
11 changed files with 294 additions and 0 deletions

26
TrsrDB.pm Normal file
View File

@ -0,0 +1,26 @@
use strict;
package TrsrDB;
use base qw/DBIx::Class::Schema/;
use Carp qw/croak/;
__PACKAGE__->load_classes(qw|
Account Debit Credit Transfer CurrentDebts AvailableCredits
Balance ReconstructedBankStatement History
|);
sub import {
my ($class, $dbh_ref, $filename) = @_;
return if @_ == 1;
croak "use TrsrDB \$your_db_handle missing" if !defined $dbh_ref;
$$dbh_ref = $class->connect(
"DBI:SQLite:" . ($filename // ":memory:"),
"", "", {
sqlite_unicode => 1,
on_connect_call => 'use_foreign_keys',
on_connect_do => 'PRAGMA recursive_triggers = 1',
}
);
}
1;

34
TrsrDB/Account.pm Normal file
View File

@ -0,0 +1,34 @@
use strict;
package TrsrDB::Account;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('Account');
__PACKAGE__->add_columns(qw/ID type altId IBAN/);
__PACKAGE__->set_primary_key('ID');
__PACKAGE__->has_many(
statement_rows => 'TrsrDB::ReconstructedBankStatement',
{ 'foreign.account' => 'self.ID' }
);
__PACKAGE__->has_many(
debts => 'TrsrDB::Debit',
{ 'foreign.debtor' => 'self.ID' }
);
__PACKAGE__->has_many(
current_debts => 'TrsrDB::CurrentDebts',
{ 'foreign.debtor' => 'self.ID' }
);
__PACKAGE__->has_many(
credits => 'TrsrDB::Credit',
{ 'foreign.account' => 'self.ID' }
);
__PACKAGE__->has_many(
available_credits => 'TrsrDB::AvailableCredits',
{ 'foreign.account' => 'self.ID' }
);
__PACKAGE__->has_one(
balance => 'TrsrDB::Balance', 'ID'
);
1;

View File

@ -0,0 +1,19 @@
use strict;
package TrsrDB::AvailableCredits;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('AvailableCredits');
__PACKAGE__->add_columns(qw/ Id account date purpose difference /);
__PACKAGE__->set_primary_key("Id");
__PACKAGE__->belongs_to(
account => 'TrsrDB::Account',
{ 'foreign.ID' => 'self.account' }
);
__PACKAGE__->many_to_many(
suggested_to_pay => account => 'current_debts'
);
1;

14
TrsrDB/Balance.pm Normal file
View File

@ -0,0 +1,14 @@
use strict;
package TrsrDB::Balance;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table("Balance");
__PACKAGE__->add_columns(qw/ID credit promised debt/);
__PACKAGE__->set_primary_key("ID");
__PACKAGE__->belongs_to(
account => 'TrsrDB::Account', 'ID'
);
1;

29
TrsrDB/Credit.pm Normal file
View File

@ -0,0 +1,29 @@
use strict;
package TrsrDB::Credit;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('Credit');
__PACKAGE__->add_column("Id" => { data_type => 'INTEGER' });
__PACKAGE__->add_column("account");
__PACKAGE__->add_column("date" => { data_type => 'DATE' });
__PACKAGE__->add_column("purpose");
__PACKAGE__->add_column("value" => { data_type => 'INTEGER' });
__PACKAGE__->add_column("spent" => { data_type => 'INTEGER', default => 0 });
__PACKAGE__->set_primary_key("Id");
__PACKAGE__->belongs_to(
account => 'TrsrDB::Account',
{ 'foreign.ID' => 'self.account' }
);
__PACKAGE__->has_many(
outgoings => 'TrsrDB::Transfer',
{ 'foreign.fromCredit' => 'self.Id' }
);
__PACKAGE__->many_to_many(
paid_bills => 'outgoings' => 'debit'
);
1;

19
TrsrDB/CurrentDebts.pm Normal file
View File

@ -0,0 +1,19 @@
use strict;
package TrsrDB::CurrentDebts;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('CurrentDebts');
__PACKAGE__->add_columns(qw/billId debtor targetCredit date purpose difference/);
__PACKAGE__->set_primary_key("billId");
__PACKAGE__->belongs_to(
account => 'TrsrDB::Account',
{ 'foreign.ID' => 'self.account' }
);
__PACKAGE__->many_to_many(
payable_with => account => 'available_credits'
);
1;

29
TrsrDB/Debit.pm Normal file
View File

@ -0,0 +1,29 @@
use strict;
package TrsrDB::Debit;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('Debit');
__PACKAGE__->add_column("billId");
__PACKAGE__->add_column("debtor");
__PACKAGE__->add_column("targetCredit" => { data_type => 'INTEGER' });
__PACKAGE__->add_column("date" => { data_type => 'DATE' });
__PACKAGE__->add_column("purpose");
__PACKAGE__->add_column("value" => { data_type => 'INTEGER' });
__PACKAGE__->add_column("paid" => { data_type => 'INTEGER', default => 0 });
__PACKAGE__->set_primary_key("billId");
__PACKAGE__->belongs_to(
account => 'TrsrDB::Account',
{ 'foreign.ID' => 'self.debtor' }
);
__PACKAGE__->has_many(
incomings => 'TrsrDB::Transfer', 'billId'
);
__PACKAGE__->many_to_many(
paid_with => incomings => 'credit'
);
1;

14
TrsrDB/History.pm Normal file
View File

@ -0,0 +1,14 @@
use strict;
package TrsrDB::History;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('History');
__PACKAGE__->add_columns(qw/date purpose account credit debit contra billId/);
__PACKAGE__->belongs_to(
account => 'TrsrDB::Account',
{ 'foreign.ID' => 'self.account' }
);
1;

View File

@ -0,0 +1,9 @@
use strict;
package TrsrDB::ReconstructedBankStatement;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('ReconstructedBankStatement');
__PACKAGE__->add_columns(qw/date purpose account credit debit/);
1;

22
TrsrDB/Transfer.pm Normal file
View File

@ -0,0 +1,22 @@
use strict;
package TrsrDB::Transfer;
use base qw/DBIx::Class::Core/;
__PACKAGE__->table('Transfer');
__PACKAGE__->add_column("timestamp" => { data_type => 'TIMESTAMP' });
__PACKAGE__->add_column("billId");
__PACKAGE__->add_column("fromCredit");
__PACKAGE__->add_column("amount" => { data_type => 'INTEGER', nullable => 1 });
__PACKAGE__->set_primary_key("billId", "fromCredit");
__PACKAGE__->belongs_to(
credit => 'TrsrDB::Credit',
{ 'foreign.Id' => 'self.fromCredit' }
);
__PACKAGE__->belongs_to(
debit => 'TrsrDB::Credit', 'billId'
);
1;

79
t/schema.t Normal file
View File

@ -0,0 +1,79 @@
use strict;
my $db;
use TrsrDB \$db => 'trsr.db';
use Test::More;
$db->resultset("Account")->create({ ID => "Club", altId => 1, type => 'eV' });
$db->resultset("Account")->create({ ID => "john", altId => 44, type => 'Member' });
$db->resultset("Account")->create({
ID => "alex", altId => 6, type => 'Member',
IBAN => 'DE1234567890123456' # used for verification in outgoing bank transfers
});
is_deeply
[ $db->resultset("Account")->search(
{}, { -order_by => { asc => ['ID'] } }
)->get_column('ID')->all
],
[ qw/ Club alex john / ],
"Registering new accounts"
;
$db->resultset("Credit")->create($_) for
{ account => "Club", date => "2016-01-01",
purpose => "Membership fees May 2016 until incl. April 2017",
value => 0
},
{ account => "john", date => "2016-04-23",
purpose => "Membership fee 2016f.",
value => 7200
},
{ account => "alex", date => "2016-01-15",
purpose => "Payment for Server Hosting 2016",
value => 0,
}
;
is_deeply [ map { $db->resultset("Account")->find($_)->credits->count() } qw(Club john alex) ],
[ 1, 1, 1 ], "Entering one credit per account";
my %months = (
'05' => 'May 2016', '06' => 'June 2016', '07' => 'July 2016', '08' => 'August 2016',
'09' => 'September 2016', '10' => 'October 2016', '11' => 'November 2016', '12' => 'December 2016',
'01' => 'January 2017', '02' => 'February 2017', '03' => 'March 2017', '04' => 'April 2017',
);
while ( my ($num, $month) = each %months ) {
my $yy = substr $month, -2;
$db->resultset("Debit")->create({
billId => "MB$yy$num-john",
debtor => "john",
targetCredit => 1,
date => "16-05-01",
purpose => "Membership fee $month",
value => 600
});
}
is $db->resultset("Account")->find("john")->current_debts->count(), 12,
"Entering outstanding member fees for john";
$db->resultset("Account")->find("Club")->add_to_debts({
billId => "TWX2016/123",
targetCredit => 3,
date => "2016-01-15",
purpose => "Server Hosting 2016",
value => 23450
});
is $db->resultset("Debit")->search({ debtor => 'Club' })->single->billId, "TWX2016/123", "Invoicing server hosting for club";
is_deeply { map { $_->ID => {$_->get_columns} } $db->resultset("Balance")->all },
{ john => { ID => 'john', credit => 7200, debt => 7200, promised => 0 },
Club => { ID => 'Club', credit => 0, debt => 23450, promised => 7200 },
alex => { ID => 'alex', credit => 0, debt => 0, promised => 23450 },
},
"Get balances"
;
done_testing();