brmbar/brmbar3/BrmBar/Shop.pm
Petr Baudis 945ee705c3 Initial implementation of brmbar v3 - brmbar v1 emulator brmbar-cli.pl
Uses PostgreSQL to store accounts and transactions, and Perl + Moose
for the implementation.

The schema is somewhat complicated, but brmburo-compatible; accounting
design by TMA.
2012-08-29 03:52:30 +02:00

73 lines
2.1 KiB
Perl

package BrmBar::Shop;
use strict;
use warnings;
use v5.10;
use utf8;
use encoding::warnings;
use open qw(:encoding(UTF-8));
use Moose;
use Carp;
use BrmBar::Currency;
use BrmBar::Account;
has 'db' => (is => 'ro', isa => 'DBI::db', required => 1);
has 'currency' => (is => 'rw', isa => 'BrmBar::Currency');
has 'profits' => (is => 'ro', isa => 'BrmBar::Account'); # income account for our margins
has 'cash' => (is => 'ro', isa => 'BrmBar::Account'); # our operational ("wallet") cash account
sub new_with_defaults {
my ($class, %opts) = @_;
return $class->new(
db => $opts{db},
currency => BrmBar::Currency->default(db => $opts{db}),
profits => BrmBar::Account->load(db => $opts{db}, name => 'BrmBar Profits'),
cash => BrmBar::Account->load(db => $opts{db}, name => 'BrmBar Cash')
);
}
sub sell {
my ($self, %opts) = @_;
my ($item, $user, $amount) = @opts{'item', 'user', 'amount'};
$amount ||= 1;
my ($buy, $sell) = $item->currency()->rates($self->currency());
my $cost = $amount * $sell;
my $profit = $amount * ($sell - $buy);
$self->db()->begin_work();
my $tr = $self->_transaction(responsible => $user, description => 'BrmBar sale of '.$amount.'x '.$item->name().' to '.$user->name());
$item->credit($tr, $amount, $user->name());
$user->debit($tr, $cost, $item->name()); # debit (increase) on a _debt_ account
$self->profits()->debit($tr, $profit, "Margin on ".$item->name());
$self->db()->commit();
return $cost;
}
sub add_credit {
my ($self, %opts) = @_;
my ($credit, $user) = @opts{'credit', 'user'};
$self->db()->begin_work();
my $tr = $self->_transaction(responsible => $user, description => 'BrmBar credit replenishment for '.$user->name());
$self->cash()->debit($tr, $credit, $user->name());
$user->credit($tr, $credit, 'Credit replenishment');
$self->db()->commit();
}
# This is for internal usage of the business logic
sub _transaction {
my ($self, %opts) = @_;
my ($responsible, $description) = @opts{'responsible', 'description'};
$self->db()->prepare('INSERT INTO transactions (responsible, description) VALUES (?, ?)')->execute($responsible->id(), $description);
}
1;