revbank/plugins/repeat
Juerd Waalboer 5e5c27a203 Remove dead code
As a side effect of a7a5f14e, "123 x <product>" (with a space between the
number and the operator) is no longer supported. Breaking that was
unintentional, but since it was an undocumented feature and unintuitive
hack anyway, the feature won't come back.

When it still worked, it was implemented by *converting* a raw amount
(withdrawal or unlisted product, which you could still enter as just a
number -- since the aforementioned commit you need to be explicit and
use `withdraw` or `unlisted`) into a stub that would finally apply a
repetition when adding something else.
2023-01-29 22:52:02 +01:00

133 lines
3.8 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->entries)[-1];
return NEXT if $lhs and $rhs; # 123x123 -> invalid syntax
if ($rhs) {
return ABORT, "Can't modify an empty transaction." if not $cart->size;
return REJECT, $err_nope if $last->attribute('no_repeat');
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 (not $lhs and not $rhs) {
# Lone operator. Convert withdrawal into repetition.
return ABORT, "Can't modify an empty transaction." if not $cart->size;
if ($op eq '+' or $op eq '-') {
$self->{op} = $op;
return "$op how many?", \&plusminus;
}
}
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 REJECT, $err_stacked if $last->multiplied;
return REJECT, $err_nope if $last->attribute('no_repeat');
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->entries)[-1]->quantity($arg);
return ACCEPT;
}
sub plusminus($self, $cart, $arg, @) {
$arg =~ /^\d+$/ and $arg > 0
or return REJECT, "Invalid value.";
my $last = ($cart->entries)[-1];
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->entries)[-1]->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);
}