forked from brmlab/brmbar-github

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.
73 lines
2.1 KiB
Perl
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;
|