added ORM api and some tests
This commit is contained in:
		
							parent
							
								
									dbbada8307
								
							
						
					
					
						commit
						57556d252b
					
				
							
								
								
									
										26
									
								
								TrsrDB.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								TrsrDB.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										34
									
								
								TrsrDB/Account.pm
									
									
									
									
									
										Normal 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;
 | 
			
		||||
							
								
								
									
										19
									
								
								TrsrDB/AvailableCredits.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								TrsrDB/AvailableCredits.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										14
									
								
								TrsrDB/Balance.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										29
									
								
								TrsrDB/Credit.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										19
									
								
								TrsrDB/CurrentDebts.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										29
									
								
								TrsrDB/Debit.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										14
									
								
								TrsrDB/History.pm
									
									
									
									
									
										Normal 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;
 | 
			
		||||
							
								
								
									
										9
									
								
								TrsrDB/ReconstructedBankStatement.pm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								TrsrDB/ReconstructedBankStatement.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										22
									
								
								TrsrDB/Transfer.pm
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										79
									
								
								t/schema.t
									
									
									
									
									
										Normal 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();
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user