Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 82ff5451

Von Moritz Bunkus vor etwa 9 Jahren hinzugefügt

  • ID 82ff5451c8babb72b4963f8d3bbb4b604a3b4675
  • Vorgänger 326fa24a
  • Nachfolger b3b80856

Wiederkehrende Rechnungen: Auftragswerts-Periodizität setzen können

Noch keine Anpassung der eigentlichen Berechnung. Wohl aber
Dokumentation von SL::DB::PeriodicInvoicesConfig.

Unterschiede anzeigen:

SL/BackgroundJob/CreatePeriodicInvoices.pm
74 74
sub _generate_time_period_variables {
75 75
  my $config            = shift;
76 76
  my $period_start_date = shift;
77
  my $period_end_date   = $period_start_date->clone->truncate(to => 'month')->add(months => $config->get_period_length)->subtract(days => 1);
77
  my $period_end_date   = $period_start_date->clone->truncate(to => 'month')->add(months => $config->get_billing_period_length)->subtract(days => 1);
78 78

  
79 79
  my @month_names       = ('',
80 80
                           $::locale->text('January'), $::locale->text('February'), $::locale->text('March'),     $::locale->text('April'),   $::locale->text('May'),      $::locale->text('June'),
SL/Controller/FinancialControllingReport.pm
148 148
    $cur_date->add(years => 1);
149 149
  }
150 150

  
151
  return $num_years * $order->netamount * (12 / $order->periodic_invoices_config->get_period_length);
151
  return $num_years * $order->netamount * (12 / $order->periodic_invoices_config->get_billing_period_length);
152 152
}
153 153

  
154 154
sub sum_items {
SL/Controller/FinancialOverview.pm
148 148
  return if $params{config}->start_date > $params{end_date};
149 149

  
150 150
  my $first_date = $params{config}->start_date->clone->set_year($self->year);
151
  my $net        = $params{config}->order->netamount * (12 / $params{config}->get_period_length);
151
  my $net        = $params{config}->order->netamount * (12 / $params{config}->get_billing_period_length);
152 152
  my $sord       = $self->data->{sales_orders};
153 153

  
154 154
  $sord->{months  }->[ $first_date->month   - 1 ] += $net;
SL/DB/MetaSetup/PeriodicInvoicesConfig.pm
17 17
  first_billing_date      => { type => 'date' },
18 18
  id                      => { type => 'integer', not_null => 1, sequence => 'id' },
19 19
  oe_id                   => { type => 'integer', not_null => 1 },
20
  periodicity             => { type => 'varchar', length => 10, not_null => 1 },
20
  order_value_periodicity => { type => 'varchar', length => 1, not_null => 1 },
21
  periodicity             => { type => 'varchar', length => 1, not_null => 1 },
21 22
  print                   => { type => 'boolean', default => 'false' },
22 23
  printer_id              => { type => 'integer' },
23 24
  start_date              => { type => 'date' },
SL/DB/PeriodicInvoicesConfig.pm
11 11
# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all.
12 12
__PACKAGE__->meta->make_manager_class;
13 13

  
14
our @PERIODICITIES  = qw(m q f b y);
15
our %PERIOD_LENGTHS = ( m => 1, q => 3, f => 4, b => 6, y => 12 );
14
our %PERIOD_LENGTHS             = ( m => 1, q => 3, b => 6, y => 12 );
15
our %ORDER_VALUE_PERIOD_LENGTHS = ( %PERIOD_LENGTHS, 2 => 24, 3 => 36, 4 => 48, 5 => 60 );
16
our @PERIODICITIES              = keys %PERIOD_LENGTHS;
17
our @ORDER_VALUE_PERIODICITIES  = keys %ORDER_VALUE_PERIOD_LENGTHS;
16 18

  
17
sub get_period_length {
19
sub get_billing_period_length {
18 20
  my $self = shift;
19 21
  return $PERIOD_LENGTHS{ $self->periodicity } || 1;
20 22
}
21 23

  
24
sub get_order_value_period_length {
25
  my $self = shift;
26
  return $self->get_billing_period_length if $self->order_value_periodicity eq 'p';
27
  return $ORDER_VALUE_PERIOD_LENGTHS{ $self->order_value_periodicity } || 1;
28
}
29

  
22 30
sub _log_msg {
23 31
  $::lxdebug->message(LXDebug->DEBUG1(), join('', @_));
24 32
}
......
78 86
sub calculate_invoice_dates {
79 87
  my ($self, %params) = @_;
80 88

  
81
  my $period_len = $self->get_period_length;
89
  my $period_len = $self->get_billing_period_length;
82 90
  my $cur_date   = $self->first_billing_date || $self->start_date;
83 91
  my $end_date   = $self->terminated ? $self->end_date : undef;
84 92
  $end_date    //= DateTime->today_local->add(years => 100);
......
100 108
}
101 109

  
102 110
1;
111
__END__
112

  
113
=pod
114

  
115
=encoding utf8
116

  
117
=head1 NAME
118

  
119
SL::DB::PeriodicInvoicesConfig - DB model for the configuration for periodic invoices
120

  
121
=head1 FUNCTIONS
122

  
123
=over 4
124

  
125
=item C<calculate_invoice_dates %params>
126

  
127
Calculates dates for which invoices will have to be created. Returns a
128
list of L<DateTime> objects.
129

  
130
This function looks at the configuration settings and at the list of
131
invoices that have already been created for this configuration. The
132
date range for which dates are created are controlled by several
133
values:
134

  
135
=over 2
136

  
137
=item * The properties C<first_billing_date> and C<start_date>
138
determine the start date.
139

  
140
=item * The properties C<end_date> and C<terminated> determine the end
141
date.
142

  
143
=item * The optional parameter C<past_dates> determines whether or not
144
dates for which invoices have already been created will be included in
145
the list. The default is not to include them.
146

  
147
=item * The optional parameters C<start_date> and C<end_date> override
148
the start and end dates from the configuration.
149

  
150
=item * If no end date is set or implied via the configuration and no
151
C<end_date> parameter is given then the function will use 100 years
152
in the future as the end date.
153

  
154
=back
155

  
156
=item C<get_billing_period_length>
157

  
158
Returns the number of months corresponding to the billing
159
periodicity. This means that a new invoice has to be created every x
160
months starting with the value in C<first_billing_date> (or
161
C<start_date> if C<first_billing_date> is unset).
162

  
163
=item C<get_order_value_period_length>
164

  
165
Returns the number of months the order's value refers to. This looks
166
at the C<order_value_periodicity>.
167

  
168
Each invoice's value is calculated as C<order value *
169
billing_period_length / order_value_period_length>.
170

  
171
=item C<get_previous_billed_period_start_date>
172

  
173
Returns the highest date (as an instance of L<DateTime>) for which an
174
invoice has been created from this configuration.
175

  
176
=item C<handle_automatic_extension>
177

  
178
Configurations which haven't been terminated and which have an end
179
date set may be eligible for automatic extension by a certain number
180
of months. This what the function implements.
181

  
182
If the configuration is not eligible or if the C<end_date> hasn't been
183
reached yet then nothing is done and C<undef> is returned. Otherwise
184
its behavior is determined by the C<extend_automatically_by> property.
185

  
186
If the property C<extend_automatically_by> is not 0 then the
187
C<end_date> will be extended by C<extend_automatically_by> months, and
188
the configuration will be saved. In this case the new end date will be
189
returned.
190

  
191
Otherwise (if C<extend_automatically_by> is 0) the property C<active>
192
will be set to 1, and the configuration will be saved. In this case
193
C<undef> will be returned.
194

  
195
=back
196

  
197
=head1 BUGS
198

  
199
Nothing here yet.
200

  
201
=head1 AUTHOR
202

  
203
Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
204

  
205
=cut
SL/OE.pm
738 738
    my $config_obj = SL::DB::Manager::PeriodicInvoicesConfig->find_by(oe_id => $form->{id});
739 739

  
740 740
    if ($config_obj) {
741
      my $config = { map { $_ => $config_obj->$_ } qw(active terminated periodicity start_date_as_date end_date_as_date first_billing_date_as_date extend_automatically_by ar_chart_id
741
      my $config = { map { $_ => $config_obj->$_ } qw(active terminated periodicity order_value_periodicity start_date_as_date end_date_as_date first_billing_date_as_date extend_automatically_by ar_chart_id
742 742
                                                      print printer_id copies) };
743 743
      $form->{periodic_invoices_config} = YAML::Dump($config);
744 744
    }
bin/mozilla/oe.pl
2000 2000
  $config = YAML::Load($::form->{periodic_invoices_config}) if $::form->{periodic_invoices_config};
2001 2001

  
2002 2002
  if ('HASH' ne ref $config) {
2003
    $config =  { periodicity             => 'y',
2003
    $config =  { periodicity             => 'm',
2004
                 order_value_periodicity => 'p', # = same as periodicity
2004 2005
                 start_date_as_date      => $::form->{transdate} || $::form->current_date,
2005 2006
                 extend_automatically_by => 12,
2006 2007
                 active                  => 1,
2007 2008
               };
2008 2009
  }
2009 2010

  
2010
  $config->{periodicity} = 'm' if none { $_ eq $config->{periodicity} } qw(m q b y);
2011
  $config->{periodicity}             = 'm' if none { $_ eq $config->{periodicity}             }       @SL::DB::PeriodicInvoicesConfig::PERIODICITIES;
2012
  $config->{order_value_periodicity} = 'p' if none { $_ eq $config->{order_value_periodicity} } ('p', @SL::DB::PeriodicInvoicesConfig::ORDER_VALUE_PERIODICITIES);
2011 2013

  
2012 2014
  $::form->get_lists(printers => "ALL_PRINTERS",
2013 2015
                     charts   => { key       => 'ALL_CHARTS',
......
2033 2035

  
2034 2036
  my $config = { active                  => $::form->{active}     ? 1 : 0,
2035 2037
                 terminated              => $::form->{terminated} ? 1 : 0,
2036
                 periodicity             => (any { $_ eq $::form->{periodicity} } qw(m q b y)) ? $::form->{periodicity} : 'm',
2038
                 periodicity             => (any { $_ eq $::form->{periodicity}             }       @SL::DB::PeriodicInvoicesConfig::PERIODICITIES)              ? $::form->{periodicity}             : 'm',
2039
                 order_value_periodicity => (any { $_ eq $::form->{order_value_periodicity} } ('p', @SL::DB::PeriodicInvoicesConfig::ORDER_VALUE_PERIODICITIES)) ? $::form->{order_value_periodicity} : 'p',
2037 2040
                 start_date_as_date      => $::form->{start_date_as_date},
2038 2041
                 end_date_as_date        => $::form->{end_date_as_date},
2039 2042
                 first_billing_date_as_date => $::form->{first_billing_date_as_date},
locale/de/all
35 35
  '...on the TODO list'         => '...auf der Aufgabenliste',
36 36
  '0% tax with taxkey'          => '0% Steuer mit Steuerschl&uuml;ssel ',
37 37
  '1. Quarter'                  => '1. Quartal',
38
  '2 years'                     => '2 Jahre',
38 39
  '2. Quarter'                  => '2. Quartal',
40
  '3 years'                     => '3 Jahre',
39 41
  '3. Quarter'                  => '3. Quartal',
42
  '4 years'                     => '4 Jahre',
40 43
  '4. Quarter'                  => '4. Quartal',
44
  '5 years'                     => '5 Jahre',
41 45
  '<b> I DO CARE!</b> Please check create warehouse and bins and define a name for the warehouse (Bins will be created automatically) and then continue' => '<b>ICH KÜMMER MICH</b> Bitte haken Sie Lager und Lagerplätze erzeugen an (Automatisches Zuweisen der Lagerplätze) und vergeben einen Namen für dieses Lager (Lagerpl&auml;tze werden automatisch übernommen). Danach auf weiter.',
42 46
  '<b> I DO CARE!</b> Please click back and cancel the update and come back after there has been at least one warehouse defined with bin(s).:' => '<b>ICH KÜMMER MICH</b> Brechen Sie das Update ab und legen selber mindestens ein Lager mit Lagerplätzen unter dem Menü System / Lager an.',
43 47
  '<b> I DO NOT CARE</b> Please click continue and the following data (see list) will be deleted:' => '<b>IST MIR EGAL</b> Mit einem Klick auf Weiter (rot) werden keine Daten übernommen, bzw. migriert und die folgende Information in der untenstehenden Liste wird gelöscht.',
......
354 358
  'Billed amount'               => 'Abgerechneter Betrag',
355 359
  'Billed extra expenses'       => 'Abgerechnete Nebenkosten',
356 360
  'Billing Address'             => 'Rechnungsadresse',
361
  'Billing Periodicity'         => 'Abrechnungsperiodizität',
357 362
  'Billing/shipping address (city)' => 'Rechnungsadresse (Stadt)',
358 363
  'Billing/shipping address (country)' => 'Rechnungsadresse (Land)',
359 364
  'Billing/shipping address (street)' => 'Rechnungsadresse (Straße)',
......
1731 1736
  'Order deleted!'              => 'Auftrag gelöscht!',
1732 1737
  'Order probability'           => 'Auftragswahrscheinlichkeit',
1733 1738
  'Order probability & expected billing date' => 'Auftragswahrscheinlichkeit & vorrauss. Abrechnungsdatum',
1739
  'Order value periodicity'     => 'Auftragswert basiert auf Periodizität',
1734 1740
  'Order/Item row name'         => 'Name der Auftrag-/Positions-Zeilen',
1735 1741
  'OrderItem'                   => 'Position',
1736 1742
  'Ordered'                     => 'Von Kunden bestellt',
......
1821 1827
  'Periodic inventory'          => 'Aufwandsmethode',
1822 1828
  'Periodic invoices active'    => 'Wiederkehrende Rechnungen aktiv',
1823 1829
  'Periodic invoices inactive'  => 'Wiederkehrende Rechnungen inaktiv',
1824
  'Periodicity'                 => 'Periodizität',
1825 1830
  'Perpetual inventory'         => 'Bestandsmethode',
1826 1831
  'Person'                      => 'Person',
1827 1832
  'Personal settings'           => 'Pers&ouml;nliche Einstellungen',
......
3240 3245
  'sales_order'                 => 'Kundenauftrag',
3241 3246
  'sales_order_list'            => 'auftragsliste',
3242 3247
  'sales_quotation'             => 'Verkaufsangebot',
3248
  'same as periodicity'         => 'stimmt mit Abrechnungsperiodizität überein',
3243 3249
  'saved'                       => 'gespeichert',
3244 3250
  'saved!'                      => 'gespeichert',
3245 3251
  'saving data'                 => 'Speichere Daten',
sql/Pg-upgrade2/periodic_invoices_order_value_periodicity.sql
1
-- @tag: periodic_invoices_order_value_periodicity
2
-- @description: Wiederkehrende Rechnungen: Einstellung für Periode, auf die sich der Auftragswert bezieht
3
-- @depends: release_3_1_0
4

  
5
-- Spalte »periodicity«: nur ein Zeichen, und Check auf gültige Werte
6
ALTER TABLE periodic_invoices_configs
7
ADD CONSTRAINT periodic_invoices_configs_valid_periodicity
8
CHECK (periodicity IN ('m', 'q', 'b', 'y'));
9

  
10
ALTER TABLE periodic_invoices_configs
11
ALTER COLUMN periodicity TYPE varchar(1);
12

  
13
-- Neue Spalte »order_value_periodicity«
14
ALTER TABLE periodic_invoices_configs
15
ADD COLUMN order_value_periodicity varchar(1);
16

  
17
UPDATE periodic_invoices_configs
18
SET order_value_periodicity = 'p';
19

  
20
ALTER TABLE periodic_invoices_configs
21
ALTER COLUMN order_value_periodicity
22
SET NOT NULL;
23

  
24
ALTER TABLE periodic_invoices_configs
25
ADD CONSTRAINT periodic_invoices_configs_valid_order_value_periodicity
26
CHECK (order_value_periodicity IN ('p', 'm', 'q', 'b', 'y', '2', '3', '4', '5'));
templates/webpages/oe/edit_periodic_invoices_config.html
1 1
[% USE HTML %]
2 2
[% USE LxERP %]
3 3
[% USE L %]
4
[% SET style="width: 400px" %]
4 5
<h1>[% title %]</h1>
5 6

  
6 7
 <form name="Form" action="oe.pl" method="post">
......
20 21
    </tr>
21 22

  
22 23
    <tr>
23
     <th align="right" valign="top">[%- LxERP.t8('Periodicity') %]</th>
24
     <th align="right" valign="top">[%- LxERP.t8('Billing Periodicity') %]</th>
24 25
     <td valign="top">
25
      [% L.radio_button_tag("periodicity", value => "m", label => LxERP.t8("monthly"),   checked => periodicity == 'm') %]
26
      <br>
27
      [% L.radio_button_tag("periodicity", value => "q", label => LxERP.t8("every third month"), checked => periodicity == 'q') %]
28
      <br>
29
      [% L.radio_button_tag("periodicity", value => "b", label => LxERP.t8("semiannually"), checked => periodicity == 'b') %]
30
      <br>
31
      [% L.radio_button_tag("periodicity", value => "y", label => LxERP.t8("yearly"),    checked => periodicity == 'y') %]
26
      [% L.select_tag("periodicity", [ [ "m", LxERP.t8("monthly") ], [ "q", LxERP.t8("every third month") ], [ "b", LxERP.t8("semiannually") ], [ "y", LxERP.t8("yearly") ] ], default=periodicity, style=style) %]
27
     </td>
28
    </tr>
29

  
30
    <tr>
31
     <th align="right" valign="top">[%- LxERP.t8('Order value periodicity') %]</th>
32
     <td valign="top">
33
      [% L.select_tag("order_value_periodicity",
34
                      [ [ "p", LxERP.t8("same as periodicity") ], [ "m", LxERP.t8("monthly") ], [ "q", LxERP.t8("every third month") ], [ "b", LxERP.t8("semiannually") ], [ "y", LxERP.t8("yearly") ],
35
                        [ "2", LxERP.t8("2 years") ], [ "3", LxERP.t8("3 years") ], [ "4", LxERP.t8("4 years") ], [ "5", LxERP.t8("5 years") ], ],
36
                      default=order_value_periodicity, style=style) %]
32 37
     </td>
33 38
    </tr>
34 39

  
......
63 68
    <tr>
64 69
     <th align="right">[%- LxERP.t8('Record in') %]</th>
65 70
     <td valign="top">
66
      [% L.select_tag("ar_chart_id", AR, title_key => 'description', default => ar_chart_id) %]
71
      [% L.select_tag("ar_chart_id", AR, title_key => 'description', default => ar_chart_id, style=style) %]
67 72
     </td>
68 73
    </tr>
69 74

  
......
77 82
    <tr>
78 83
     <th align="right">[%- LxERP.t8('Printer') %]</th>
79 84
     <td valign="top">
80
      [% L.select_tag("printer_id", ALL_PRINTERS, title_key = 'printer_description', default = printer_id, disabled = !print) %]
85
      [% L.select_tag("printer_id", ALL_PRINTERS, title_key = 'printer_description', default = printer_id, disabled = !print, style=style) %]
81 86
     </td>
82 87
    </tr>
83 88

  

Auch abrufbar als: Unified diff