Revision 3e714a7f
Von Tamino Steinert vor 5 Monaten hinzugefügt
SL/DB/PeriodicInvoicesConfig.pm | ||
---|---|---|
7 | 7 |
|
8 | 8 |
use Params::Validate qw(:all); |
9 | 9 |
use List::Util qw(max min); |
10 |
use Rose::DB::Object::Helpers qw(clone); |
|
10 | 11 |
|
11 | 12 |
use SL::Helper::DateTime; |
12 | 13 |
|
... | ... | |
17 | 18 |
our @PERIODICITIES = keys %PERIOD_LENGTHS; |
18 | 19 |
our @ORDER_VALUE_PERIODICITIES = keys %ORDER_VALUE_PERIOD_LENGTHS; |
19 | 20 |
|
21 |
sub get_open_orders_for_period { |
|
22 |
my $self = shift; |
|
23 |
|
|
24 |
my %params = validate(@_, { |
|
25 |
start_date => { |
|
26 |
callbacks => { is_date => \&_is_date, }, |
|
27 |
default => $self->start_date, |
|
28 |
}, |
|
29 |
end_date => { |
|
30 |
callbacks => { is_date => \&_is_date, }, |
|
31 |
default => DateTime->today_local, |
|
32 |
}, |
|
33 |
}); |
|
34 |
return [] unless $self->active; |
|
35 |
|
|
36 |
my @start_dates = $self->calculate_invoice_dates(%params); |
|
37 |
return [] unless scalar @start_dates; |
|
38 |
|
|
39 |
my $orig_order = $self->order; |
|
40 |
|
|
41 |
my $next_period_start_date = $self->get_next_period_start_date; |
|
42 |
|
|
43 |
my @orders; |
|
44 |
foreach my $period_start_date (@start_dates) { |
|
45 |
my $new_order = clone($orig_order); |
|
46 |
$new_order->reqdate($period_start_date); |
|
47 |
$new_order->tax_point( |
|
48 |
add_months( |
|
49 |
$period_start_date, $self->get_billing_period_length |
|
50 |
)->add(days => -1) |
|
51 |
); |
|
52 |
my @items; |
|
53 |
for my $item ($orig_order->items) { |
|
54 |
next if $item->recurring_billing_mode eq 'never'; |
|
55 |
next if $item->recurring_billing_mode eq 'once' && ( |
|
56 |
$item->recurring_billing_invoice_id |
|
57 |
|| $period_start_date != $next_period_start_date |
|
58 |
); |
|
59 |
|
|
60 |
my $new_item = clone($item); |
|
61 |
|
|
62 |
$new_item = $self->_adjust_sellprices_for_period( |
|
63 |
order_item => $new_item, |
|
64 |
period_start_date => $period_start_date, |
|
65 |
); |
|
66 |
|
|
67 |
push @items, $new_item; |
|
68 |
} |
|
69 |
if (scalar @items) { # don't return empty orders |
|
70 |
$new_order->items(@items); |
|
71 |
$new_order->calculate_prices_and_taxes; |
|
72 |
push @orders, $new_order; |
|
73 |
} |
|
74 |
} |
|
75 |
return \@orders; |
|
76 |
} |
|
77 |
|
|
78 |
sub _adjust_sellprices_for_period { |
|
79 |
my $self = shift; |
|
80 |
|
|
81 |
my %params = validate(@_, { |
|
82 |
period_start_date => { callbacks => { is_date => \&_is_date, } }, |
|
83 |
order_item => { isa => 'SL::DB::OrderItem' }, |
|
84 |
}); |
|
85 |
my $item = $params{order_item}; |
|
86 |
|
|
87 |
my $config = $self; |
|
88 |
|
|
89 |
my $billing_len = $config->get_billing_period_length; |
|
90 |
my $order_value_len = $config->get_order_value_period_length; |
|
91 |
|
|
92 |
return $item if $billing_len == $order_value_len; |
|
93 |
return $item if $billing_len == 0; |
|
94 |
|
|
95 |
my $is_last_invoice_in_cycle = $config->is_last_bill_date_in_order_value_cycle(date => $params{period_start_date}); |
|
96 |
|
|
97 |
my $multiplier_per_invoice = $billing_len / $order_value_len; |
|
98 |
my $sellprice_one_invoice = $::form->round_amount($item->sellprice * $multiplier_per_invoice, 2); |
|
99 |
if ($multiplier_per_invoice < 1 && $is_last_invoice_in_cycle) { |
|
100 |
# add rounding difference on last cycle |
|
101 |
my $num_invoices_in_cycle = $order_value_len / $billing_len; |
|
102 |
$item->sellprice($item->sellprice - ($num_invoices_in_cycle - 1) * $sellprice_one_invoice); |
|
103 |
} else { |
|
104 |
$item->sellprice($sellprice_one_invoice); |
|
105 |
} |
|
106 |
|
|
107 |
return $item; |
|
108 |
} |
|
109 |
|
|
20 | 110 |
sub calculate_invoice_dates { |
21 | 111 |
my $self = shift; |
22 | 112 |
|
... | ... | |
84 | 174 |
return @start_dates; |
85 | 175 |
} |
86 | 176 |
|
177 |
sub get_next_period_start_date { |
|
178 |
my $self = shift; |
|
179 |
|
|
180 |
my $last_created_on_date = $self->get_previous_billed_period_start_date; |
|
181 |
|
|
182 |
return $self->first_billing_date || $self->start_date unless $last_created_on_date; |
|
183 |
|
|
184 |
my @dates = $self->calculate_invoice_dates( |
|
185 |
end_date => add_months($last_created_on_date, $self->get_billing_period_length) |
|
186 |
); |
|
187 |
|
|
188 |
return scalar @dates ? $dates[0] : undef; |
|
189 |
} |
|
190 |
|
|
87 | 191 |
sub get_billing_period_length { |
88 | 192 |
my $self = shift; |
89 | 193 |
return $PERIOD_LENGTHS{ $self->periodicity } || 1; |
Auch abrufbar als: Unified diff
S:D:PeriodicInvoicesConfig: Helferfunktion für Aufträge in Periode