revbank/plugins/repeat

127 lines
3.6 KiB
Perl

#!perl
HELP "<N>x, <N>*" => "Set quantity of previous/next product";
HELP "-<N>, +<N>, *<N>, x<N>" => "Change quantity of previous product";
my $err_stacked = "Stacked repetition is not supported.";
my $err_pfand = "Plugins 'pfand' and 'repeat' cannot be combined.";
my $err_nope = "Entry does not support repetition.";
my $err_postfix = "Addition/substraction is only supported the other way around.";
my $limit = 200;
my $err_limit = "Repetition is limited at $limit items.";
sub command($self, $cart, $command, @) {
my ($lhs, $op, $rhs) = $command =~ /^(\d+)?([x*+-])(\d+)?$/
or return NEXT;
return ABORT, $err_pfand if $cart->entries('is_pfand');
my $last = $cart->selected;
return NEXT if $lhs and $rhs; # 123x123 -> invalid, likely user or product
if ($lhs) {
return REJECT, $err_postfix if $op eq '+' or $op eq '-';
$lhs = abs $lhs; # withdrawal is negative
return REJECT, $err_limit if $lhs > $limit;
$cart
->add(0, "? (The next thing you add will be multiplied.)", { _repeat => 1, refuse_checkout => 1 })
->quantity($lhs);
return ACCEPT;
}
return ABORT, "Can't modify an empty transaction." if not $cart->size;
return REJECT, $err_nope if $last->attribute('no_repeat');
if ($rhs) {
return REJECT, $err_limit if $rhs > $limit;
if ($op eq '+') {
my $new = $last->quantity + $rhs;
return REJECT, $err_limit if $new > $limit;
$last->quantity($new);
return ACCEPT;
}
if ($op eq '-') {
my $new = $last->quantity - $rhs;
if ($new > 0) {
$last->quantity($new);
} else {
$cart->delete($last);
print "Deleted.\n";
}
return ACCEPT;
}
# $op is not + or -, so it must be * (or x).
return REJECT, $err_stacked if $last->multiplied;
$last->quantity($rhs);
return ACCEPT;
}
if ($op eq '+' or $op eq '-') {
$self->{op} = $op;
return "$op how many?", \&plusminus;
}
# $op is not + or -, so it must be * (or x).
return REJECT, $err_stacked if $last->multiplied;
return "Multiply previous product by", \&repeat;
}
sub repeat($self, $cart, $arg, @) {
$arg =~ /^\d+$/ and $arg > 0
or return REJECT, "Invalid value.";
return REJECT, $err_limit if $arg > $limit;
$cart->selected->quantity($arg);
return ACCEPT;
}
sub plusminus($self, $cart, $arg, @) {
$arg =~ /^\d+$/ and $arg > 0
or return REJECT, "Invalid value.";
my $last = $cart->selected;
my $new = $last->quantity;
$new += $arg if $self->{op} eq '+';
$new -= $arg if $self->{op} eq '-';
return REJECT, $err_limit if $new > $limit;
if ($new < 0) {
$cart->delete($last);
print "Deleted.\n";
} else {
$cart->selected->quantity($new);
}
return ACCEPT;
}
sub hook_added_entry($class, $cart, $entry, @) {
$cart->size >= 2 or return;
my @entries = $cart->entries;
my @planned = $cart->entries('_repeat');
return if not @planned;
return ABORT, "Multiple repeats queued; I'm confused." if @planned > 1;
return ABORT, $err_pfand if $cart->entries('is_pfand');
return if $planned[0] == $entries[-1];
return ABORT, "Queued repeat is not the penultimate item; I'm confused"
if $entries[-2] != $planned[0];
my $num = $planned[0]->quantity;
if ($entries[-1]->attribute('no_repeat')) {
print $err_nope, "\n";
$num = 1;
}
$cart->delete($planned[0]);
$entries[-1]->quantity($num);
}