
Activating statiegeld_tokens will limit the use of the statiegeld plugin for container deposit refunds to what was bought at this venue. Still needs documentation. Changes to 'statiegeld' and 'undo' were made to support the new plugin, specifically: - metadata (attributes) added in $cart->add, for the statiegeld_tokens plugin to use. - statiegeld plugin now shares a global variable (configuration). - undo can now be rolled back during hook_checkout.
101 lines
2.8 KiB
Perl
101 lines
2.8 KiB
Perl
#!perl
|
|
|
|
HELP1 "undo <transactionID>" => "Undo a transaction";
|
|
|
|
my $filename = ".revbank.undo";
|
|
|
|
my @TAB;
|
|
|
|
sub command :Tab(undo) ($self, $cart, $command, @) {
|
|
$command eq 'undo' or return NEXT;
|
|
|
|
$cart->size and return REJECT, "Undo is not available mid-transaction.";
|
|
|
|
my @log;
|
|
for my $line (slurp $filename) {
|
|
my ($tid, $user, $delta, $dt) = split " ", $line;
|
|
if (@log and $log[-1]{tid} eq $tid) {
|
|
push @{ $log[-1]{deltas} }, [ $user, $delta ];
|
|
} else {
|
|
push @log, { tid => $tid, dt => $dt, deltas => [ [ $user, $delta ] ] };
|
|
}
|
|
}
|
|
|
|
@TAB = ();
|
|
|
|
my $menu = "";
|
|
my $max = @log < 15 ? @log : 15;
|
|
for my $txn (@log[-$max .. -1]) {
|
|
$menu .= "ID: $txn->{tid} $txn->{dt} " . join(", ",
|
|
map { sprintf "%s:%+.2f", @$_ } @{ $txn->{deltas} }
|
|
) . "\n";
|
|
|
|
push @TAB, $txn->{tid};
|
|
}
|
|
|
|
return $menu . "Transaction ID", \&undo;
|
|
}
|
|
|
|
sub tab { @TAB }
|
|
|
|
my $doing_undo = 0; # Ugly but works, just like the rest of this plugin
|
|
|
|
sub undo :Tab(&tab) ($self, $cart, $tid, @) {
|
|
my $description = "Undo $tid";
|
|
my $entry;
|
|
my $found = 0;
|
|
my $aborted = 0;
|
|
|
|
with_lock {
|
|
my $backup = "$filename.bak.$$";
|
|
spurt $backup, slurp $filename; # copy for rollback
|
|
|
|
# Immediately remove from file, to avoid double undo when something
|
|
# crashes.
|
|
rewrite $filename, sub($line) {
|
|
if ($line =~ /^\Q$tid\E\s/) {
|
|
my (undef, $user, $delta) = split " ", $line;
|
|
|
|
$entry ||= $cart->add(0, $description, { undo_transaction_id => $tid });
|
|
$entry->{FORCE_UNBALANCED} = 1;
|
|
|
|
$entry->add_contra($user, $delta, "Undo $tid");
|
|
return undef; # remove line
|
|
} else {
|
|
return $line;
|
|
}
|
|
};
|
|
|
|
if ($cart->size) {
|
|
$found = 1;
|
|
$doing_undo = 1; # don't allow undoing undos
|
|
|
|
eval { $cart->checkout('-undo') };
|
|
|
|
if ($@ and $@ =~ "ROLLBACK_UNDO") {
|
|
# Undo the undo... :)
|
|
spurt $filename, slurp $backup;
|
|
|
|
# can't 'return ABORT' here; it would return from with_lock
|
|
$aborted = 1;
|
|
} elsif ($@) {
|
|
# Re-throw exception
|
|
die "(undo file BACKUP at $backup.)\n$@";
|
|
} else {
|
|
unlink $backup;
|
|
}
|
|
|
|
$doing_undo = 0;
|
|
}
|
|
};
|
|
|
|
return ABORT, "Undo prohibited." if $aborted;
|
|
return ACCEPT if $found;
|
|
return ABORT, "Transaction ID '$tid' not found in undo log.";
|
|
}
|
|
|
|
sub hook_user_balance($class, $username, $old, $delta, $new, $transaction_id, @) {
|
|
return if $doing_undo; # don't allow undoing undos
|
|
|
|
append $filename, join(" ", $transaction_id, $username, -$delta, now()), "\n";
|
|
}
|