revbank/lib/RevBank/Users.pm
Juerd Waalboer ccae71021a Get 'cash' working again
Now implemented via a hidden user called '-cash'.

This also introduces the concept of hidden accounts, that begin with '+' or
'-', for result accounts and balance accounts. Future versions can further
use this for more detailed bookkeeping. The idea behind the sign is that
'-' accounts should be inverted to get the intuitive value. So if the account
'-cash' has -13.37, that means there should be +13.37 in the cash box (or,
well, once the rest of this is implemented and the initial values are then set
correctly.)
2022-06-11 16:58:20 +02:00

92 lines
2.3 KiB
Perl

package RevBank::Users;
use v5.28;
use warnings;
use feature qw(signatures);
no warnings qw(experimental::signatures);
use RevBank::Global;
use RevBank::Plugins;
my $filename = "revbank.accounts";
sub _read() {
my @users;
open my $fh, $filename or die $!;
/\S/ and push @users, [split " "] while readline $fh;
close $fh;
return { map { lc($_->[0]) => $_ } @users };
}
sub names() {
return map $_->[0], values %{ _read() };
}
sub balance($username) {
return _read()->{ lc $username }->[1];
}
sub since($username) {
return _read()->{ lc $username }->[3];
}
sub create($username) {
open my $fh, '>>', $filename or die $!;
my $now = now();
print {$fh} "$username 0.00 $now\n" or die $!;
close $fh or die $!;
RevBank::Plugins::call_hooks("user_created", $username);
return $username;
}
sub update($username, $delta, $transaction_id) {
open my $in, 'revbank.accounts' or die $!;
open my $out, ">.revbank.$$" or die $!;
my $old = RevBank::Amount->new(0);
my $new = RevBank::Amount->new(0);
while (defined (my $line = readline $in)) {
my @a = split " ", $line;
if (lc $a[0] eq lc $username) {
$old = RevBank::Amount->parse_string($a[1]);
die "Fatal error: invalid balance in revbank:accounts:$.\n"
if not defined $old;
$new = $old + $delta;
my $since = $a[3] // "";
my $newc = $new->cents;
my $oldc = $old->cents;
$since = "+\@" . now() if $newc > 0 and (!$since or $oldc <= 0);
$since = "-\@" . now() if $newc < 0 and (!$since or $oldc >= 0);
$since = "0\@" . now() if $newc == 0 and (!$since or $oldc != 0);
printf {$out} "%-16s %9s %s %s\n", (
$username, $new->string("+"), now(), $since
) or die $!;
} else {
print {$out} $line or die $!;
}
}
close $out or die $!;
close $in;
rename ".revbank.$$", "revbank.accounts" or die $!;
RevBank::Plugins::call_hooks(
"user_balance", $username, $old, $delta, $new, $transaction_id
);
}
sub parse_user($username) {
my $users = _read();
return undef if not exists $users->{ lc $username };
return $users->{ lc $username }->[0];
}
sub is_hidden($username) {
return $username =~ /^[-+]/;
}
1;