Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 430216b9

Von Moritz Bunkus vor fast 10 Jahren hinzugefügt

  • ID 430216b97bf4096f8770626125127168ed63c5a0
  • Vorgänger b3b80856
  • Nachfolger b2becee7

Wiederkehrende Rechnungen: Berechnung für Auftragswertperiodizität angepasst

Unterschiede anzeigen:

SL/BackgroundJob/CreatePeriodicInvoices.pm
66 66
}
67 67

  
68 68
sub _log_msg {
69
  my $message  = join('', @_);
69
  my $message  = join('', 'SL::BackgroundJob::CreatePeriodicInvoices: ', @_);
70 70
  $message    .= "\n" unless $message =~ m/\n$/;
71 71
  $::lxdebug->message(LXDebug::DEBUG1(), $message);
72 72
}
......
142 142
  $params{object}->$sub($str);
143 143
}
144 144

  
145
sub _adjust_sellprices_for_period_lengths {
146
  my (%params) = @_;
147

  
148
  my $billing_len     = $params{config}->get_billing_period_length;
149
  my $order_value_len = $params{config}->get_order_value_period_length;
150

  
151
  return if $billing_len == $order_value_len;
152

  
153
  my $is_last_invoice_in_cycle = $params{config}->is_last_bill_date_in_order_value_cycle(date => $params{period_start_date});
154

  
155
  _log_msg("_adjust_sellprices_for_period_lengths: period_start_date $params{period_start_date} is_last_invoice_in_cycle $is_last_invoice_in_cycle billing_len $billing_len order_value_len $order_value_len");
156

  
157
  if ($order_value_len < $billing_len) {
158
    my $num_orders_per_invoice = $billing_len / $order_value_len;
159

  
160
    $_->sellprice($_->sellprice * $num_orders_per_invoice) for @{ $params{invoice}->items };
161

  
162
    return;
163
  }
164

  
165
  my $num_invoices_in_cycle = $order_value_len / $billing_len;
166

  
167
  foreach my $item (@{ $params{invoice}->items }) {
168
    my $sellprice_one_invoice = $::form->round_amount($item->sellprice * $billing_len / $order_value_len, 2);
169

  
170
    if ($is_last_invoice_in_cycle) {
171
      $item->sellprice($item->sellprice - ($num_invoices_in_cycle - 1) * $sellprice_one_invoice);
172

  
173
    } else {
174
      $item->sellprice($sellprice_one_invoice);
175
    }
176
  }
177
}
178

  
145 179
sub _create_periodic_invoice {
146 180
  $main::lxdebug->enter_sub();
147 181

  
......
174 208
      _replace_vars(object => $item, vars => $time_period_vars, attribute => $_, attribute_format => ($_ eq 'longdescription' ? 'html' : 'text')) for qw(description longdescription);
175 209
    }
176 210

  
211
    _adjust_sellprices_for_period_lengths(invoice => $invoice, config => $config, period_start_date => $period_start_date);
212

  
177 213
    $invoice->post(ar_id => $config->ar_chart_id) || die;
178 214

  
179 215
    # like $form->add_shipto, but we don't need to check for a manual exception,
......
210 246
                                 period_start_date => $period_start_date)
211 247
      ->save;
212 248

  
249
    _log_msg("_create_invoice created for period start date $period_start_date id " . $invoice->id . " number " . $invoice->invnumber . " netamount " . $invoice->netamount . " amount " . $invoice->amount);
250

  
213 251
    # die $invoice->transaction_description;
214 252
  })) {
215 253
    $::lxdebug->message(LXDebug->WARN(), "_create_invoice failed: " . join("\n", (split(/\n/, $self->{db_obj}->db->error))[0..2]));
SL/DB/PeriodicInvoicesConfig.pm
28 28
}
29 29

  
30 30
sub _log_msg {
31
  $::lxdebug->message(LXDebug->DEBUG1(), join('', @_));
31
  $::lxdebug->message(LXDebug->DEBUG1(), join('', 'SL::DB::PeriodicInvoicesConfig: ', @_));
32 32
}
33 33

  
34 34
sub handle_automatic_extension {
......
87 87
  my ($self, %params) = @_;
88 88

  
89 89
  my $period_len = $self->get_billing_period_length;
90
  my $cur_date   = $self->first_billing_date || $self->start_date;
90
  my $cur_date   = ($self->first_billing_date || $self->start_date)->clone;
91 91
  my $end_date   = $self->terminated ? $self->end_date : undef;
92 92
  $end_date    //= DateTime->today_local->add(years => 100);
93
  my $start_date = $params{past_dates} ? undef                       : $self->get_previous_billed_period_start_date;
94
  $start_date    = $start_date         ? $start_date->add(days => 1) : $cur_date->clone;
93
  my $start_date = $params{past_dates} ? undef                              : $self->get_previous_billed_period_start_date;
94
  $start_date    = $start_date         ? $start_date->clone->add(days => 1) : $cur_date->clone;
95 95

  
96 96
  $start_date    = max($start_date, $params{start_date}) if $params{start_date};
97 97
  $end_date      = min($end_date,   $params{end_date})   if $params{end_date};
......
107 107
  return @dates;
108 108
}
109 109

  
110
sub is_last_bill_date_in_order_value_cycle {
111
  my ($self, %params)    = @_;
112

  
113
  my $months_billing     = $self->get_billing_period_length;
114
  my $months_order_value = $self->get_order_value_period_length;
115

  
116
  return 1 if $months_billing >= $months_order_value;
117

  
118
  my $next_billing_date = $params{date}->clone->add(months => $months_billing);
119
  my $date_itr          = max($self->start_date, $self->first_billing_date || $self->start_date)->clone;
120

  
121
  _log_msg("is_last_billing_date_in_order_value_cycle start: id " . $self->id . " date_itr $date_itr start " . $self->start_date);
122

  
123
  $date_itr->add(months => $months_order_value) while $date_itr < $next_billing_date;
124

  
125
  _log_msg("is_last_billing_date_in_order_value_cycle end: refdate $params{date} next_billing_date $next_billing_date date_itr $date_itr months_billing $months_billing months_order_value $months_order_value result "
126
           . ($date_itr == $next_billing_date));
127

  
128
  return $date_itr == $next_billing_date;
129
}
130

  
110 131
1;
111 132
__END__
112 133

  
......
192 213
will be set to 1, and the configuration will be saved. In this case
193 214
C<undef> will be returned.
194 215

  
216
=item C<is_last_billing_date_in_order_value_cycle %params>
217

  
218
Determines whether or not the mandatory parameter C<date>, an instance
219
of L<DateTime>, is the last billing date within the cycle given by the
220
order value periodicity. Returns a truish value if this is the case
221
and a falsish value otherwise.
222

  
223
This check is always true if the billing periodicity is longer than or
224
equal to the order value periodicity. For example, if you have an
225
order whose value is given for three months and you bill every six
226
months and you have twice the order value on each invoice, meaning
227
each invoice is itself the last invoice for not only one but two order
228
value cycles.
229

  
230
Otherwise (if the order value periodicity is longer than the billing
231
periodicity) this function iterates over all eligible dates starting
232
with C<first_billing_date> (or C<start_date> if C<first_billing_date>
233
is unset) and adding the order value length with each step. If the
234
date given by the C<date> parameter plus the billing period length
235
equals one of those dates then the given date is indeed the date of
236
the last invoice in that particular order value cycle.
237

  
195 238
=back
196 239

  
197 240
=head1 BUGS

Auch abrufbar als: Unified diff