Revision c1c6288a
Von Martin Helmling martin.helmling@octosoft.eu vor etwa 8 Jahren hinzugefügt
SL/Controller/YearEndTransactions.pm | ||
---|---|---|
1 |
package SL::Controller::YearEndTransactions; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::Controller::Base); |
|
6 |
|
|
7 |
use DateTime; |
|
8 |
use SL::Locale::String qw(t8); |
|
9 |
use SL::ReportGenerator; |
|
10 |
use SL::Helper::Flash; |
|
11 |
use SL::DBUtils; |
|
12 |
|
|
13 |
use SL::DB::Chart; |
|
14 |
use SL::DB::GLTransaction; |
|
15 |
use SL::DB::AccTransaction; |
|
16 |
use SL::DB::Helper::AccountingPeriod qw(get_balance_starting_date); |
|
17 |
|
|
18 |
use Rose::Object::MakeMethods::Generic ( |
|
19 |
'scalar --get_set_init' => [ qw(charts charts9000 cbob_chart cb_date cb_startdate ob_date cb_reference ob_reference cb_description ob_description) ], |
|
20 |
); |
|
21 |
|
|
22 |
__PACKAGE__->run_before('check_auth'); |
|
23 |
|
|
24 |
sub action_filter { |
|
25 |
my ($self) = @_; |
|
26 |
|
|
27 |
$self->ob_date(DateTime->today->truncate(to => 'year')) if !$self->ob_date; |
|
28 |
$self->cb_date(DateTime->today->truncate(to => 'year')->add(days => -1)) if !$self->cb_date; |
|
29 |
$self->ob_reference(t8('OB Transaction')) if !$self->ob_reference; |
|
30 |
$self->cb_reference(t8('CB Transaction')) if !$self->cb_reference; |
|
31 |
$self->ob_description(t8('OB Transaction')) if !$self->ob_description; |
|
32 |
$self->cb_description(t8('CB Transaction')) if !$self->cb_description; |
|
33 |
$self->render('gl/yearend_filter', |
|
34 |
title => t8('CB/OB Transactions'), |
|
35 |
make_title_of_chart => sub { $_[0]->accno.' '.$_[0]->description } |
|
36 |
); |
|
37 |
|
|
38 |
} |
|
39 |
|
|
40 |
sub action_list { |
|
41 |
my ($self) = @_; |
|
42 |
$main::lxdebug->enter_sub(); |
|
43 |
|
|
44 |
my $report = SL::ReportGenerator->new(\%::myconfig, $::form); |
|
45 |
|
|
46 |
$self->prepare_report($report); |
|
47 |
|
|
48 |
$report->set_options( |
|
49 |
output_format => 'HTML', |
|
50 |
raw_top_info_text => $::form->parse_html_template('gl/yearend_top', { SELF => $self }), |
|
51 |
raw_bottom_info_text => $::form->parse_html_template('gl/yearend_bottom', { SELF => $self }), |
|
52 |
allow_pdf_export => 0, |
|
53 |
allow_csv_export => 0, |
|
54 |
title => $::locale->text('CB/OB Transactions'), |
|
55 |
); |
|
56 |
$report->generate_with_headers(); |
|
57 |
$main::lxdebug->leave_sub(); |
|
58 |
} |
|
59 |
|
|
60 |
sub action_generate { |
|
61 |
my ($self) = @_; |
|
62 |
|
|
63 |
my $cnt = $self->make_booking(); |
|
64 |
|
|
65 |
flash('info', $::locale->text('#1 CB transactions and #1 OB transactions generated.',$cnt)) if $cnt > 0; |
|
66 |
|
|
67 |
$self->action_list; |
|
68 |
} |
|
69 |
|
|
70 |
sub check_auth { |
|
71 |
$::auth->assert('general_ledger'); |
|
72 |
} |
|
73 |
|
|
74 |
# |
|
75 |
# helpers |
|
76 |
# |
|
77 |
|
|
78 |
sub make_booking { |
|
79 |
my ($self) = @_; |
|
80 |
$main::lxdebug->enter_sub(); |
|
81 |
my @ids = map { $::form->{"trans_id_$_"} } grep { $::form->{"multi_id_$_"} } (1..$::form->{rowcount}); |
|
82 |
my $cnt = 0; |
|
83 |
$main::lxdebug->message(LXDebug->DEBUG2(),"generate for ".$::form->{cbob_chart}." # ".scalar(@ids)." charts"); |
|
84 |
if (scalar(@ids) && $::form->{cbob_chart}) { |
|
85 |
my $carryoverchart = SL::DB::Manager::Chart->get_first( query => [ id => $::form->{cbob_chart} ] ); |
|
86 |
my $charts = SL::DB::Manager::Chart->get_all( query => [ id => \@ids ] ); |
|
87 |
foreach my $chart (@{ $charts }) { |
|
88 |
$main::lxdebug->message(LXDebug->DEBUG2(),"chart_id=".$chart->id." accno=".$chart->accno); |
|
89 |
my $balance = $self->get_balance($chart); |
|
90 |
if ( $balance != 0 ) { |
|
91 |
# SB |
|
92 |
$self->gl_booking($balance,$self->cb_date,$::form->{cb_reference},$::form->{cb_description},$chart,$carryoverchart,0,1); |
|
93 |
# EB |
|
94 |
$self->gl_booking($balance,$self->ob_date,$::form->{ob_reference},$::form->{ob_description},$carryoverchart,$chart,1,0); |
|
95 |
$cnt++; |
|
96 |
} |
|
97 |
} |
|
98 |
} |
|
99 |
$main::lxdebug->leave_sub(); |
|
100 |
return $cnt; |
|
101 |
} |
|
102 |
|
|
103 |
|
|
104 |
sub prepare_report { |
|
105 |
my ($self,$report) = @_; |
|
106 |
$main::lxdebug->enter_sub(); |
|
107 |
my $idx = 1; |
|
108 |
my $cgi = $::request->{cgi}; |
|
109 |
|
|
110 |
my %column_defs = ( |
|
111 |
'ids' => { 'text' => '<input type="checkbox" id="multi_all" value="1">', 'align' => 'center' }, |
|
112 |
'chart' => { 'text' => $::locale->text('Account'), }, |
|
113 |
'description' => { 'text' => $::locale->text('Description'), }, |
|
114 |
'saldo' => { 'text' => $::locale->text('Saldo'), 'align' => 'right'}, |
|
115 |
'sum_cb' => { 'text' => $::locale->text('Sum CB Transactions'), 'align' => 'right'}, ##close == Schluss |
|
116 |
'sum_ob' => { 'text' => $::locale->text('Sum OB Transactions'), 'align' => 'right'}, ##open == Eingang |
|
117 |
); |
|
118 |
my @columns = qw(ids chart description saldo sum_cb sum_ob); |
|
119 |
map { $column_defs{$_}->{visible} = 1 } @columns; |
|
120 |
my $ob_next_date = $::locale->parse_date_to_object($self->ob_date)->add(years => 1)->add(days => -1)->to_kivitendo; |
|
121 |
|
|
122 |
$self->cb_startdate($self->get_balance_starting_date($self->cb_date)); |
|
123 |
|
|
124 |
my @custom_headers = (); |
|
125 |
# Zeile 1: |
|
126 |
push @custom_headers, [ |
|
127 |
{ 'text' => ' ', 'colspan' => 3 }, |
|
128 |
{ 'text' => $::locale->text("Timerange")."<br />".$self->cb_startdate." - ".$self->cb_date, 'colspan' => 2, 'align' => 'center'}, |
|
129 |
{ 'text' => $::locale->text("Timerange")."<br />".$self->ob_date." - ".$ob_next_date, 'align' => 'center'}, |
|
130 |
]; |
|
131 |
|
|
132 |
# Zeile 2: |
|
133 |
my @line_2 = (); |
|
134 |
map { push @line_2 , $column_defs{$_} } grep { $column_defs{$_}->{visible} } @columns; |
|
135 |
push @custom_headers, [ @line_2 ]; |
|
136 |
|
|
137 |
$report->set_custom_headers(@custom_headers); |
|
138 |
$report->set_columns(%column_defs); |
|
139 |
$report->set_column_order(@columns); |
|
140 |
|
|
141 |
my $chart9actual = SL::DB::Manager::Chart->get_first( query => [ id => $self->cbob_chart ] ); |
|
142 |
$self->{cbob_chartaccno} = $chart9actual->accno.' '.$chart9actual->description; |
|
143 |
|
|
144 |
foreach my $chart (@{ $self->charts }) { |
|
145 |
my $balance = $self->get_balance($chart); |
|
146 |
if ( $balance != 0 ) { |
|
147 |
my $chart_id = $chart->id; |
|
148 |
my $row = { map { $_ => { 'data' => '' } } @columns }; |
|
149 |
$row->{ids} = { |
|
150 |
'raw_data' => $cgi->hidden('-name' => "trans_id_${idx}", '-value' => $chart_id) |
|
151 |
. $cgi->checkbox('-name' => "multi_id_${idx}",' id' => "multi_id_id_".$chart_id, '-value' => 1, '-label' => ''), |
|
152 |
'valign' => 'center', |
|
153 |
'align' => 'center', |
|
154 |
}; |
|
155 |
$row->{chart}->{data} = $chart->accno; |
|
156 |
$row->{description}->{data} = $chart->description; |
|
157 |
if ( $balance > 0 ) { |
|
158 |
$row->{saldo}->{data} = $::form->format_amount(\%::myconfig, $balance, 2)." H"; |
|
159 |
} elsif ( $balance < 0 ) { |
|
160 |
$row->{saldo}->{data} = $::form->format_amount(\%::myconfig,-$balance, 2)." S"; |
|
161 |
} else { |
|
162 |
$row->{saldo}->{data} = $::form->format_amount(\%::myconfig,0, 2)." "; |
|
163 |
} |
|
164 |
my $sum_cb = 0; |
|
165 |
foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id => $chart->id, cb_transaction => 't', |
|
166 |
transdate => { ge => $self->cb_startdate}, |
|
167 |
transdate => { le => $self->cb_date }]) }) { |
|
168 |
$sum_cb += $acc->amount; |
|
169 |
} |
|
170 |
my $sum_ob = 0; |
|
171 |
foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id => $chart->id, ob_transaction => 't', |
|
172 |
transdate => { ge => $self->ob_date}, |
|
173 |
transdate => { le => $ob_next_date }]) }) { |
|
174 |
$sum_ob += $acc->amount; |
|
175 |
} |
|
176 |
if ( $sum_cb > 0 ) { |
|
177 |
$row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig, $sum_cb, 2)." H"; |
|
178 |
} elsif ( $sum_cb < 0 ) { |
|
179 |
$row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,-$sum_cb, 2)." S"; |
|
180 |
} else { |
|
181 |
$row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,0, 2)." "; |
|
182 |
} |
|
183 |
if ( $sum_ob > 0 ) { |
|
184 |
$row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig, $sum_ob, 2)." H"; |
|
185 |
} elsif ( $sum_ob < 0 ) { |
|
186 |
$row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,-$sum_ob, 2)." S"; |
|
187 |
} else { |
|
188 |
$row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,0, 2)." "; |
|
189 |
} |
|
190 |
$report->add_data($row); |
|
191 |
} |
|
192 |
$idx++; |
|
193 |
} |
|
194 |
|
|
195 |
$self->{row_count} = $idx; |
|
196 |
$main::lxdebug->leave_sub(); |
|
197 |
} |
|
198 |
|
|
199 |
sub get_balance { |
|
200 |
$main::lxdebug->enter_sub(); |
|
201 |
my ($self,$chart) = @_; |
|
202 |
|
|
203 |
## eigene Abfrage da SL:DB:Chart->get_balance keine cb_transactions mitzählt |
|
204 |
## Alternative in Chart cb_transaction abfrage per neuem Parameter 'with_cb' disablen: |
|
205 |
# my %balance_params = ( fromdate => $self->startdate, |
|
206 |
# todate => $self->cb_date, |
|
207 |
# accounting_method => 'accrual', |
|
208 |
# with_cb => 1, ## in Chart cb_transaction abfrage disablen |
|
209 |
# ); |
|
210 |
# return $chart->get_balance(%balance_params); |
|
211 |
|
|
212 |
$main::lxdebug->message(LXDebug->DEBUG2(),"get_balance from=".$self->cb_startdate." to=".$self->cb_date); |
|
213 |
my $query = qq|SELECT SUM(amount) AS sum FROM acc_trans WHERE chart_id = ? | . |
|
214 |
qq| AND transdate >= ? AND transdate <= ? |; |
|
215 |
my @query_args = ( $chart->id, $self->cb_startdate, $self->cb_date); |
|
216 |
my ($balance) = selectfirst_array_query($::form, $chart->db->dbh, $query, @query_args); |
|
217 |
|
|
218 |
$main::lxdebug->leave_sub(); |
|
219 |
return 0 unless $balance != 0; |
|
220 |
return $balance; |
|
221 |
} |
|
222 |
|
|
223 |
sub gl_booking { |
|
224 |
my ($self, $amount, $transdate, $reference, $description, $konto, $gegenkonto, $ob, $cb) = @_; |
|
225 |
$::form->get_employee(); |
|
226 |
my $employee_id = $::form->{employee_id}; |
|
227 |
$main::lxdebug->message(LXDebug->DEBUG2(),"employee_id=".$employee_id." ob=".$ob." cb=".$cb); |
|
228 |
my $gl_entry = SL::DB::GLTransaction->new(); |
|
229 |
$gl_entry->assign_attributes( |
|
230 |
employee_id => $employee_id, |
|
231 |
transdate => $transdate, |
|
232 |
reference => $reference, |
|
233 |
description => $description, |
|
234 |
ob_transaction => $ob, |
|
235 |
cb_transaction => $cb, |
|
236 |
); |
|
237 |
$gl_entry->save; |
|
238 |
my $kto_trans1 = SL::DB::AccTransaction->new(); |
|
239 |
$kto_trans1->assign_attributes( |
|
240 |
trans_id => $gl_entry->id, |
|
241 |
transdate => $transdate, |
|
242 |
ob_transaction => $ob, |
|
243 |
cb_transaction => $cb, |
|
244 |
chart_id => $gegenkonto->id, |
|
245 |
chart_link => $konto->link, |
|
246 |
tax_id => 0, |
|
247 |
taxkey => 0, |
|
248 |
amount => $amount, |
|
249 |
); |
|
250 |
$kto_trans1->save; |
|
251 |
my $kto_trans2 = SL::DB::AccTransaction->new(); |
|
252 |
$kto_trans2->assign_attributes( |
|
253 |
trans_id => $gl_entry->id, |
|
254 |
transdate => $transdate, |
|
255 |
ob_transaction => $ob, |
|
256 |
cb_transaction => $cb, |
|
257 |
chart_id => $konto->id, |
|
258 |
chart_link => $konto->link, |
|
259 |
tax_id => 0, |
|
260 |
taxkey => 0, |
|
261 |
amount => -$amount, |
|
262 |
); |
|
263 |
$kto_trans2->save; |
|
264 |
} |
|
265 |
|
|
266 |
sub init_cbob_chart { $::form->{cbob_chart} } |
|
267 |
sub init_ob_date { $::form->{ob_date} } |
|
268 |
sub init_ob_reference { $::form->{ob_reference} } |
|
269 |
sub init_ob_description { $::form->{ob_description} } |
|
270 |
sub init_cb_startdate { $::form->{cb_startdate} } |
|
271 |
sub init_cb_date { $::form->{cb_date} } |
|
272 |
sub init_cb_reference { $::form->{cb_reference} } |
|
273 |
sub init_cb_description { $::form->{cb_description} } |
|
274 |
|
|
275 |
sub init_charts9000 { |
|
276 |
# wie geht prüfen von länge auf 4 in rose ? |
|
277 |
SL::DB::Manager::Chart->get_all( query => [ \ "accno like '9%' and length(accno) = 4"] ); |
|
278 |
#SL::DB::Manager::Chart->get_all( query => [ accno => { like => '9%'}] ); |
|
279 |
} |
|
280 |
|
|
281 |
sub init_charts { |
|
282 |
# wie geht 'not like' in rose ? |
|
283 |
SL::DB::Manager::Chart->get_all( query => [ \ "accno not like '9%'"], sort_by => 'accno ASC' ); |
|
284 |
} |
|
285 |
|
|
286 |
1; |
SL/Controller/YearlyTransactions.pm | ||
---|---|---|
1 |
package SL::Controller::YearlyTransactions; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use parent qw(SL::Controller::Base); |
|
6 |
|
|
7 |
use DateTime; |
|
8 |
use SL::Locale::String qw(t8); |
|
9 |
use SL::ReportGenerator; |
|
10 |
use SL::Helper::Flash; |
|
11 |
use SL::DBUtils; |
|
12 |
|
|
13 |
use SL::DB::Chart; |
|
14 |
use SL::DB::GLTransaction; |
|
15 |
use SL::DB::AccTransaction; |
|
16 |
use SL::DB::Helper::AccountingPeriod qw(get_balance_starting_date); |
|
17 |
|
|
18 |
use Rose::Object::MakeMethods::Generic ( |
|
19 |
'scalar --get_set_init' => [ qw(charts charts9000 cbob_chart cb_date cb_startdate ob_date cb_reference ob_reference cb_description ob_description) ], |
|
20 |
); |
|
21 |
|
|
22 |
__PACKAGE__->run_before('check_auth'); |
|
23 |
|
|
24 |
sub action_filter { |
|
25 |
my ($self) = @_; |
|
26 |
|
|
27 |
$self->ob_date(DateTime->today->truncate(to => 'year')) if !$self->ob_date; |
|
28 |
$self->cb_date(DateTime->today->truncate(to => 'year')->add(days => -1)) if !$self->cb_date; |
|
29 |
$self->ob_reference(t8('OB Transaction')) if !$self->ob_reference; |
|
30 |
$self->cb_reference(t8('CB Transaction')) if !$self->cb_reference; |
|
31 |
$self->ob_description(t8('OB Transaction')) if !$self->ob_description; |
|
32 |
$self->cb_description(t8('CB Transaction')) if !$self->cb_description; |
|
33 |
$self->render('gl/yearly_filter', |
|
34 |
title => t8('CB/OB Transactions'), |
|
35 |
make_title_of_chart => sub { $_[0]->accno.' '.$_[0]->description } |
|
36 |
); |
|
37 |
|
|
38 |
} |
|
39 |
|
|
40 |
sub action_list { |
|
41 |
my ($self) = @_; |
|
42 |
$main::lxdebug->enter_sub(); |
|
43 |
|
|
44 |
my $report = SL::ReportGenerator->new(\%::myconfig, $::form); |
|
45 |
|
|
46 |
$self->prepare_report($report); |
|
47 |
|
|
48 |
$report->set_options( |
|
49 |
output_format => 'HTML', |
|
50 |
raw_top_info_text => $::form->parse_html_template('gl/yearly_top', { SELF => $self }), |
|
51 |
raw_bottom_info_text => $::form->parse_html_template('gl/yearly_bottom', { SELF => $self }), |
|
52 |
allow_pdf_export => 0, |
|
53 |
allow_csv_export => 0, |
|
54 |
title => $::locale->text('CB/OB Transactions'), |
|
55 |
); |
|
56 |
$report->generate_with_headers(); |
|
57 |
$main::lxdebug->leave_sub(); |
|
58 |
} |
|
59 |
|
|
60 |
sub action_generate { |
|
61 |
my ($self) = @_; |
|
62 |
|
|
63 |
my $cnt = $self->make_booking(); |
|
64 |
|
|
65 |
flash('info', $::locale->text('#1 CB transactions and #1 OB transactions generated.',$cnt)) if $cnt > 0; |
|
66 |
|
|
67 |
$self->action_list; |
|
68 |
} |
|
69 |
|
|
70 |
sub check_auth { |
|
71 |
$::auth->assert('general_ledger'); |
|
72 |
} |
|
73 |
|
|
74 |
# |
|
75 |
# helpers |
|
76 |
# |
|
77 |
|
|
78 |
sub make_booking { |
|
79 |
my ($self) = @_; |
|
80 |
$main::lxdebug->enter_sub(); |
|
81 |
my @ids = map { $::form->{"trans_id_$_"} } grep { $::form->{"multi_id_$_"} } (1..$::form->{rowcount}); |
|
82 |
my $cnt = 0; |
|
83 |
$main::lxdebug->message(LXDebug->DEBUG2(),"generate for ".$::form->{cbob_chart}." # ".scalar(@ids)." charts"); |
|
84 |
if (scalar(@ids) && $::form->{cbob_chart}) { |
|
85 |
my $carryoverchart = SL::DB::Manager::Chart->get_first( query => [ id => $::form->{cbob_chart} ] ); |
|
86 |
my $charts = SL::DB::Manager::Chart->get_all( query => [ id => \@ids ] ); |
|
87 |
foreach my $chart (@{ $charts }) { |
|
88 |
$main::lxdebug->message(LXDebug->DEBUG2(),"chart_id=".$chart->id." accno=".$chart->accno); |
|
89 |
my $balance = $self->get_balance($chart); |
|
90 |
if ( $balance != 0 ) { |
|
91 |
# SB |
|
92 |
$self->gl_booking($balance,$self->cb_date,$::form->{cb_reference},$::form->{cb_description},$chart,$carryoverchart,0,1); |
|
93 |
# EB |
|
94 |
$self->gl_booking($balance,$self->ob_date,$::form->{ob_reference},$::form->{ob_description},$carryoverchart,$chart,1,0); |
|
95 |
$cnt++; |
|
96 |
} |
|
97 |
} |
|
98 |
} |
|
99 |
$main::lxdebug->leave_sub(); |
|
100 |
return $cnt; |
|
101 |
} |
|
102 |
|
|
103 |
|
|
104 |
sub prepare_report { |
|
105 |
my ($self,$report) = @_; |
|
106 |
$main::lxdebug->enter_sub(); |
|
107 |
my $idx = 1; |
|
108 |
my $cgi = $::request->{cgi}; |
|
109 |
|
|
110 |
my %column_defs = ( |
|
111 |
'ids' => { 'text' => '<input type="checkbox" id="multi_all" value="1">', 'align' => 'center' }, |
|
112 |
'chart' => { 'text' => $::locale->text('Account'), }, |
|
113 |
'description' => { 'text' => $::locale->text('Description'), }, |
|
114 |
'saldo' => { 'text' => $::locale->text('Saldo'), 'align' => 'right'}, |
|
115 |
'sum_cb' => { 'text' => $::locale->text('Sum CB Transactions'), 'align' => 'right'}, ##close == Schluss |
|
116 |
'sum_ob' => { 'text' => $::locale->text('Sum OB Transactions'), 'align' => 'right'}, ##open == Eingang |
|
117 |
); |
|
118 |
my @columns = qw(ids chart description saldo sum_cb sum_ob); |
|
119 |
map { $column_defs{$_}->{visible} = 1 } @columns; |
|
120 |
my $ob_next_date = $::locale->parse_date_to_object($self->ob_date)->add(years => 1)->add(days => -1)->to_kivitendo; |
|
121 |
|
|
122 |
$self->cb_startdate($self->get_balance_starting_date($self->cb_date)); |
|
123 |
|
|
124 |
my @custom_headers = (); |
|
125 |
# Zeile 1: |
|
126 |
push @custom_headers, [ |
|
127 |
{ 'text' => ' ', 'colspan' => 3 }, |
|
128 |
{ 'text' => $::locale->text("Timerange")."<br />".$self->cb_startdate." - ".$self->cb_date, 'colspan' => 2, 'align' => 'center'}, |
|
129 |
{ 'text' => $::locale->text("Timerange")."<br />".$self->ob_date." - ".$ob_next_date, 'align' => 'center'}, |
|
130 |
]; |
|
131 |
|
|
132 |
# Zeile 2: |
|
133 |
my @line_2 = (); |
|
134 |
map { push @line_2 , $column_defs{$_} } grep { $column_defs{$_}->{visible} } @columns; |
|
135 |
push @custom_headers, [ @line_2 ]; |
|
136 |
|
|
137 |
$report->set_custom_headers(@custom_headers); |
|
138 |
$report->set_columns(%column_defs); |
|
139 |
$report->set_column_order(@columns); |
|
140 |
|
|
141 |
my $chart9actual = SL::DB::Manager::Chart->get_first( query => [ id => $self->cbob_chart ] ); |
|
142 |
$self->{cbob_chartaccno} = $chart9actual->accno.' '.$chart9actual->description; |
|
143 |
|
|
144 |
foreach my $chart (@{ $self->charts }) { |
|
145 |
my $balance = $self->get_balance($chart); |
|
146 |
if ( $balance != 0 ) { |
|
147 |
my $chart_id = $chart->id; |
|
148 |
my $row = { map { $_ => { 'data' => '' } } @columns }; |
|
149 |
$row->{ids} = { |
|
150 |
'raw_data' => $cgi->hidden('-name' => "trans_id_${idx}", '-value' => $chart_id) |
|
151 |
. $cgi->checkbox('-name' => "multi_id_${idx}",' id' => "multi_id_id_".$chart_id, '-value' => 1, '-label' => ''), |
|
152 |
'valign' => 'center', |
|
153 |
'align' => 'center', |
|
154 |
}; |
|
155 |
$row->{chart}->{data} = $chart->accno; |
|
156 |
$row->{description}->{data} = $chart->description; |
|
157 |
if ( $balance > 0 ) { |
|
158 |
$row->{saldo}->{data} = $::form->format_amount(\%::myconfig, $balance, 2)." H"; |
|
159 |
} elsif ( $balance < 0 ) { |
|
160 |
$row->{saldo}->{data} = $::form->format_amount(\%::myconfig,-$balance, 2)." S"; |
|
161 |
} else { |
|
162 |
$row->{saldo}->{data} = $::form->format_amount(\%::myconfig,0, 2)." "; |
|
163 |
} |
|
164 |
my $sum_cb = 0; |
|
165 |
foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id => $chart->id, cb_transaction => 't', |
|
166 |
transdate => { ge => $self->cb_startdate}, |
|
167 |
transdate => { le => $self->cb_date }]) }) { |
|
168 |
$sum_cb += $acc->amount; |
|
169 |
} |
|
170 |
my $sum_ob = 0; |
|
171 |
foreach my $acc ( @{ SL::DB::Manager::AccTransaction->get_all(where => [ chart_id => $chart->id, ob_transaction => 't', |
|
172 |
transdate => { ge => $self->ob_date}, |
|
173 |
transdate => { le => $ob_next_date }]) }) { |
|
174 |
$sum_ob += $acc->amount; |
|
175 |
} |
|
176 |
if ( $sum_cb > 0 ) { |
|
177 |
$row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig, $sum_cb, 2)." H"; |
|
178 |
} elsif ( $sum_cb < 0 ) { |
|
179 |
$row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,-$sum_cb, 2)." S"; |
|
180 |
} else { |
|
181 |
$row->{sum_cb}->{data} = $::form->format_amount(\%::myconfig,0, 2)." "; |
|
182 |
} |
|
183 |
if ( $sum_ob > 0 ) { |
|
184 |
$row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig, $sum_ob, 2)." H"; |
|
185 |
} elsif ( $sum_ob < 0 ) { |
|
186 |
$row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,-$sum_ob, 2)." S"; |
|
187 |
} else { |
|
188 |
$row->{sum_ob}->{data} = $::form->format_amount(\%::myconfig,0, 2)." "; |
|
189 |
} |
|
190 |
$report->add_data($row); |
|
191 |
} |
|
192 |
$idx++; |
|
193 |
} |
|
194 |
|
|
195 |
$self->{row_count} = $idx; |
|
196 |
$main::lxdebug->leave_sub(); |
|
197 |
} |
|
198 |
|
|
199 |
sub get_balance { |
|
200 |
$main::lxdebug->enter_sub(); |
|
201 |
my ($self,$chart) = @_; |
|
202 |
|
|
203 |
## eigene Abfrage da SL:DB:Chart->get_balance keine cb_transactions mitzählt |
|
204 |
## Alternative in Chart cb_transaction abfrage per neuem Parameter 'with_cb' disablen: |
|
205 |
# my %balance_params = ( fromdate => $self->startdate, |
|
206 |
# todate => $self->cb_date, |
|
207 |
# accounting_method => 'accrual', |
|
208 |
# with_cb => 1, ## in Chart cb_transaction abfrage disablen |
|
209 |
# ); |
|
210 |
# return $chart->get_balance(%balance_params); |
|
211 |
|
|
212 |
$main::lxdebug->message(LXDebug->DEBUG2(),"get_balance from=".$self->cb_startdate." to=".$self->cb_date); |
|
213 |
my $query = qq|SELECT SUM(amount) AS sum FROM acc_trans WHERE chart_id = ? | . |
|
214 |
qq| AND transdate >= ? AND transdate <= ? |; |
|
215 |
my @query_args = ( $chart->id, $self->cb_startdate, $self->cb_date); |
|
216 |
my ($balance) = selectfirst_array_query($::form, $chart->db->dbh, $query, @query_args); |
|
217 |
|
|
218 |
$main::lxdebug->leave_sub(); |
|
219 |
return 0 unless $balance != 0; |
|
220 |
return $balance; |
|
221 |
} |
|
222 |
|
|
223 |
sub gl_booking { |
|
224 |
my ($self, $amount, $transdate, $reference, $description, $konto, $gegenkonto, $ob, $cb) = @_; |
|
225 |
$::form->get_employee(); |
|
226 |
my $employee_id = $::form->{employee_id}; |
|
227 |
$main::lxdebug->message(LXDebug->DEBUG2(),"employee_id=".$employee_id." ob=".$ob." cb=".$cb); |
|
228 |
my $gl_entry = SL::DB::GLTransaction->new(); |
|
229 |
$gl_entry->assign_attributes( |
|
230 |
employee_id => $employee_id, |
|
231 |
transdate => $transdate, |
|
232 |
reference => $reference, |
|
233 |
description => $description, |
|
234 |
ob_transaction => $ob, |
|
235 |
cb_transaction => $cb, |
|
236 |
); |
|
237 |
$gl_entry->save; |
|
238 |
my $kto_trans1 = SL::DB::AccTransaction->new(); |
|
239 |
$kto_trans1->assign_attributes( |
|
240 |
trans_id => $gl_entry->id, |
|
241 |
transdate => $transdate, |
|
242 |
ob_transaction => $ob, |
|
243 |
cb_transaction => $cb, |
|
244 |
chart_id => $gegenkonto->id, |
|
245 |
chart_link => $konto->link, |
|
246 |
tax_id => 0, |
|
247 |
taxkey => 0, |
|
248 |
amount => $amount, |
|
249 |
); |
|
250 |
$kto_trans1->save; |
|
251 |
my $kto_trans2 = SL::DB::AccTransaction->new(); |
|
252 |
$kto_trans2->assign_attributes( |
|
253 |
trans_id => $gl_entry->id, |
|
254 |
transdate => $transdate, |
|
255 |
ob_transaction => $ob, |
|
256 |
cb_transaction => $cb, |
|
257 |
chart_id => $konto->id, |
|
258 |
chart_link => $konto->link, |
|
259 |
tax_id => 0, |
|
260 |
taxkey => 0, |
|
261 |
amount => -$amount, |
|
262 |
); |
|
263 |
$kto_trans2->save; |
|
264 |
} |
|
265 |
|
|
266 |
sub init_cbob_chart { $::form->{cbob_chart} } |
|
267 |
sub init_ob_date { $::form->{ob_date} } |
|
268 |
sub init_ob_reference { $::form->{ob_reference} } |
|
269 |
sub init_ob_description { $::form->{ob_description} } |
|
270 |
sub init_cb_startdate { $::form->{cb_startdate} } |
|
271 |
sub init_cb_date { $::form->{cb_date} } |
|
272 |
sub init_cb_reference { $::form->{cb_reference} } |
|
273 |
sub init_cb_description { $::form->{cb_description} } |
|
274 |
|
|
275 |
sub init_charts9000 { |
|
276 |
# wie geht prüfen von länge auf 4 in rose ? |
|
277 |
SL::DB::Manager::Chart->get_all( query => [ \ "accno like '9%' and length(accno) = 4"] ); |
|
278 |
#SL::DB::Manager::Chart->get_all( query => [ accno => { like => '9%'}] ); |
|
279 |
} |
|
280 |
|
|
281 |
sub init_charts { |
|
282 |
# wie geht 'not like' in rose ? |
|
283 |
SL::DB::Manager::Chart->get_all( query => [ \ "accno not like '9%'"], sort_by => 'accno ASC' ); |
|
284 |
} |
|
285 |
|
|
286 |
1; |
menus/user/11-yearend-transactions.yaml | ||
---|---|---|
1 |
# This is the main menu config file for user space menu entries. |
|
2 |
# |
|
3 |
# opendynamic features |
|
4 |
# |
|
5 |
--- |
|
6 |
# |
|
7 |
# SB/EB-Buchungen |
|
8 |
# |
|
9 |
- parent: general_ledger |
|
10 |
id: general_ledger_cbob_transactions |
|
11 |
name: CB/OB Transactions |
|
12 |
icon: cbob |
|
13 |
order: 470 |
|
14 |
access: general_ledger |
|
15 |
params: |
|
16 |
action: YearEndTransactions/filter |
menus/user/11-yearly-transactions.yaml | ||
---|---|---|
1 |
# This is the main menu config file for user space menu entries. |
|
2 |
# |
|
3 |
# opendynamic features |
|
4 |
# |
|
5 |
--- |
|
6 |
# |
|
7 |
# SB/EB-Buchungen |
|
8 |
# |
|
9 |
- parent: general_ledger |
|
10 |
id: general_ledger_cbob_transactions |
|
11 |
name: CB/OB Transactions |
|
12 |
icon: cbob |
|
13 |
order: 470 |
|
14 |
access: general_ledger |
|
15 |
params: |
|
16 |
action: YearlyTransactions/filter |
t/bank/cb_ob_transactions.t | ||
---|---|---|
25 | 25 |
use SL::DB::PurchaseInvoice; |
26 | 26 |
use SL::DB::BankTransaction; |
27 | 27 |
use SL::DB::AccTransaction; |
28 |
use SL::Controller::YearlyTransactions;
|
|
28 |
use SL::Controller::YearEndTransactions;
|
|
29 | 29 |
use Data::Dumper; |
30 | 30 |
|
31 | 31 |
my ($customer, $vendor, $currency_id, @parts, $unit, $employee, $tax, $tax7, $tax_9, $taxzone, $payment_terms, $bank_account); |
... | ... | |
222 | 222 |
$ap_transaction = test_ap_transaction(invnumber => 'purchaseinv1'); |
223 | 223 |
my $ar_transaction_2 = test_ar_transaction(invnumber => 'salesinv_2'); |
224 | 224 |
|
225 |
my $yt_controller = SL::Controller::YearlyTransactions->new;
|
|
225 |
my $yt_controller = SL::Controller::YearEndTransactions->new;
|
|
226 | 226 |
my $report = SL::ReportGenerator->new(\%::myconfig, $::form); |
227 | 227 |
|
228 | 228 |
$::form->{"ob_date"} = DateTime->today->truncate(to => 'year')->add(years => 1)->to_kivitendo; |
templates/webpages/gl/yearend_bottom.html | ||
---|---|---|
1 |
[%- USE L %] |
|
2 |
[%- USE LxERP %] |
|
3 |
<table width="100%"> |
|
4 |
<tr><td> |
|
5 |
[%- L.hidden_tag("action","YearlyTransactions/dispatch") %] |
|
6 |
[%- L.hidden_tag("cb_date",SELF.cb_date) %] |
|
7 |
[%- L.hidden_tag("cb_startdate",SELF.cb_startdate) %] |
|
8 |
[%- L.hidden_tag("cb_reference",SELF.cb_reference) %] |
|
9 |
[%- L.hidden_tag("cb_description",SELF.cb_description) %] |
|
10 |
[%- L.hidden_tag("ob_date",SELF.ob_date) %] |
|
11 |
[%- L.hidden_tag("ob_reference",SELF.ob_reference) %] |
|
12 |
[%- L.hidden_tag("ob_description",SELF.ob_description) %] |
|
13 |
[%- L.hidden_tag("cbob_chart",SELF.cbob_chart) %] |
|
14 |
[%- L.hidden_tag("rowcount",SELF.row_count) %] |
|
15 |
[%- L.submit_tag("action_generate", LxERP.t8('generate cb/ob transactions for selected charts'), |
|
16 |
confirm=LxERP.t8('Are you sure to generate cb/ob transactions?')) %] |
|
17 |
[%- L.submit_tag("action_filter", LxERP.t8('back')) %] |
|
18 |
</td> |
|
19 |
</tr> |
|
20 |
</table></form> |
|
21 |
<script type='text/javascript'> |
|
22 |
$(function(){ |
|
23 |
$('#multi_all').checkall("input[name^='multi_id']"); |
|
24 |
}); |
|
25 |
</script> |
templates/webpages/gl/yearend_filter.html | ||
---|---|---|
1 |
[%- USE HTML %] |
|
2 |
[%- USE T8 %] |
|
3 |
[%- USE L %] |
|
4 |
[%- USE LxERP %] |
|
5 |
|
|
6 |
<h1>[% title | html %]</h1> |
|
7 |
|
|
8 |
[%- PROCESS 'common/flash.html' %] |
|
9 |
|
|
10 |
<form id='filter_form'> |
|
11 |
|
|
12 |
<table> |
|
13 |
<tr> |
|
14 |
<td width="20px"></td> |
|
15 |
<td align="left" colspan="5">[% 'Attention: Here will be generated a lot of CB/OB transactions.' | $T8 %]</td> |
|
16 |
</tr> |
|
17 |
<tr> |
|
18 |
<td><p></p></td> |
|
19 |
</tr> |
|
20 |
<tr> |
|
21 |
<th></th> |
|
22 |
<th width="400px" colspan="2" align="center">[% 'CB Transactions' | $T8 %]</th> |
|
23 |
<th width="400px"colspan="2" align="center">[% 'OB Transactions' | $T8 %]</th> |
|
24 |
<th> </th> |
|
25 |
</tr> |
|
26 |
<tr> |
|
27 |
<td></td> |
|
28 |
<td align="right">[% 'Date' | $T8 %]</td> |
|
29 |
<td>[% L.date_tag('cb_date', SELF.cb_date) %]</td> |
|
30 |
<td align="right">[% 'Date' | $T8 %]</td> |
|
31 |
<td>[% L.date_tag('ob_date', SELF.ob_date) %]</td> |
|
32 |
<td></td> |
|
33 |
</tr> |
|
34 |
<tr> |
|
35 |
<td></td> |
|
36 |
<td align="right">[% 'Reference' | $T8 %]</td> |
|
37 |
<td>[% L.input_tag('cb_reference', SELF.cb_reference) %]</td> |
|
38 |
<td align="right">[% 'Reference' | $T8 %]</td> |
|
39 |
<td>[% L.input_tag('ob_reference', SELF.ob_reference) %]</td> |
|
40 |
<td></td> |
|
41 |
</tr> |
|
42 |
<tr> |
|
43 |
<td></td> |
|
44 |
<td align="right">[% 'Description' | $T8 %]</td> |
|
45 |
<td>[% L.input_tag('cb_description', SELF.cb_description) %]</td> |
|
46 |
<td align="right">[% 'Description' | $T8 %]</td> |
|
47 |
<td>[% L.input_tag('ob_description', SELF.ob_description) %]</td> |
|
48 |
<td></td> |
|
49 |
</tr> |
|
50 |
<tr> |
|
51 |
<td><p></p></td> |
|
52 |
</tr> |
|
53 |
<tr> |
|
54 |
<th colspan="2"></th> |
|
55 |
<th align=right>[% 'close chart' | $T8 %]</th> |
|
56 |
<td colspan="3">[% L.select_tag('cbob_chart', SELF.charts9000, title_sub=\make_title_of_chart, default=SELF.cbob_chart, style="width: 400px") %]</td> |
|
57 |
</tr> |
|
58 |
</table> |
|
59 |
|
|
60 |
[% L.hidden_tag('action', 'YearlyTransactions/dispatch') %] |
|
61 |
<hr size=3 noshade><br> |
|
62 |
[% L.submit_tag('action_list', LxERP.t8('Continue')) %] |
|
63 |
|
|
64 |
</form> |
templates/webpages/gl/yearend_top.html | ||
---|---|---|
1 |
[%- USE LxERP %] |
|
2 |
[%- INCLUDE 'common/flash.html' %] |
|
3 |
<form method="post" action="controller.pl"> |
|
4 |
<table> |
|
5 |
<tr> |
|
6 |
<td width="20px"></td> |
|
7 |
<td colspan="6" align="left"> |
|
8 |
[%- LxERP.t8('Select charts for which the CB/OB transactions want to be posted.') %]<br> |
|
9 |
[%- LxERP.t8('There will be two transactions done:') %]<br> |
|
10 |
- [%- LxERP.t8('One SB-transaction') %] ( [% SELF.cb_date %], [% SELF.cb_reference %], [% SELF.cb_description %], [% SELF.cbob_chartaccno %] )<br> |
|
11 |
- [%- LxERP.t8('One OB-transaction') %] ( [% SELF.ob_date %], [% SELF.ob_reference %], [% SELF.ob_description %], [% SELF.cbob_chartaccno %] )<br> |
|
12 |
[%- LxERP.t8('No revert available.') %] |
|
13 |
</td> |
|
14 |
</tr> |
|
15 |
<tr> |
|
16 |
<td><p></p></td> |
|
17 |
</tr> |
|
18 |
<tr> |
|
19 |
<th></th> |
|
20 |
<th align="right">[% LxERP.t8('close chart') %]</th> |
|
21 |
<td>[% SELF.cbob_chartaccno %]</td> |
|
22 |
</tr> |
|
23 |
</table> |
templates/webpages/gl/yearly_bottom.html | ||
---|---|---|
1 |
[%- USE L %] |
|
2 |
[%- USE LxERP %] |
|
3 |
<table width="100%"> |
|
4 |
<tr><td> |
|
5 |
[%- L.hidden_tag("action","YearlyTransactions/dispatch") %] |
|
6 |
[%- L.hidden_tag("cb_date",SELF.cb_date) %] |
|
7 |
[%- L.hidden_tag("cb_startdate",SELF.cb_startdate) %] |
|
8 |
[%- L.hidden_tag("cb_reference",SELF.cb_reference) %] |
|
9 |
[%- L.hidden_tag("cb_description",SELF.cb_description) %] |
|
10 |
[%- L.hidden_tag("ob_date",SELF.ob_date) %] |
|
11 |
[%- L.hidden_tag("ob_reference",SELF.ob_reference) %] |
|
12 |
[%- L.hidden_tag("ob_description",SELF.ob_description) %] |
|
13 |
[%- L.hidden_tag("cbob_chart",SELF.cbob_chart) %] |
|
14 |
[%- L.hidden_tag("rowcount",SELF.row_count) %] |
|
15 |
[%- L.submit_tag("action_generate", LxERP.t8('generate cb/ob transactions for selected charts'), |
|
16 |
confirm=LxERP.t8('Are you sure to generate cb/ob transactions?')) %] |
|
17 |
[%- L.submit_tag("action_filter", LxERP.t8('back')) %] |
|
18 |
</td> |
|
19 |
</tr> |
|
20 |
</table></form> |
|
21 |
<script type='text/javascript'> |
|
22 |
$(function(){ |
|
23 |
$('#multi_all').checkall("input[name^='multi_id']"); |
|
24 |
}); |
|
25 |
</script> |
templates/webpages/gl/yearly_filter.html | ||
---|---|---|
1 |
[%- USE HTML %] |
|
2 |
[%- USE T8 %] |
|
3 |
[%- USE L %] |
|
4 |
[%- USE LxERP %] |
|
5 |
|
|
6 |
<h1>[% title | html %]</h1> |
|
7 |
|
|
8 |
[%- PROCESS 'common/flash.html' %] |
|
9 |
|
|
10 |
<form id='filter_form'> |
|
11 |
|
|
12 |
<table> |
|
13 |
<tr> |
|
14 |
<td width="20px"></td> |
|
15 |
<td align="left" colspan="5">[% 'Attention: Here will be generated a lot of CB/OB transactions.' | $T8 %]</td> |
|
16 |
</tr> |
|
17 |
<tr> |
|
18 |
<td><p></p></td> |
|
19 |
</tr> |
|
20 |
<tr> |
|
21 |
<th></th> |
|
22 |
<th width="400px" colspan="2" align="center">[% 'CB Transactions' | $T8 %]</th> |
|
23 |
<th width="400px"colspan="2" align="center">[% 'OB Transactions' | $T8 %]</th> |
|
24 |
<th> </th> |
|
25 |
</tr> |
|
26 |
<tr> |
|
27 |
<td></td> |
|
28 |
<td align="right">[% 'Date' | $T8 %]</td> |
|
29 |
<td>[% L.date_tag('cb_date', SELF.cb_date) %]</td> |
|
30 |
<td align="right">[% 'Date' | $T8 %]</td> |
|
31 |
<td>[% L.date_tag('ob_date', SELF.ob_date) %]</td> |
|
32 |
<td></td> |
|
33 |
</tr> |
|
34 |
<tr> |
|
35 |
<td></td> |
|
36 |
<td align="right">[% 'Reference' | $T8 %]</td> |
|
37 |
<td>[% L.input_tag('cb_reference', SELF.cb_reference) %]</td> |
|
38 |
<td align="right">[% 'Reference' | $T8 %]</td> |
|
39 |
<td>[% L.input_tag('ob_reference', SELF.ob_reference) %]</td> |
|
40 |
<td></td> |
|
41 |
</tr> |
|
42 |
<tr> |
|
43 |
<td></td> |
|
44 |
<td align="right">[% 'Description' | $T8 %]</td> |
|
45 |
<td>[% L.input_tag('cb_description', SELF.cb_description) %]</td> |
|
46 |
<td align="right">[% 'Description' | $T8 %]</td> |
|
47 |
<td>[% L.input_tag('ob_description', SELF.ob_description) %]</td> |
|
48 |
<td></td> |
|
49 |
</tr> |
|
50 |
<tr> |
|
51 |
<td><p></p></td> |
|
52 |
</tr> |
|
53 |
<tr> |
|
54 |
<th colspan="2"></th> |
|
55 |
<th align=right>[% 'close chart' | $T8 %]</th> |
|
56 |
<td colspan="3">[% L.select_tag('cbob_chart', SELF.charts9000, title_sub=\make_title_of_chart, default=SELF.cbob_chart, style="width: 400px") %]</td> |
|
57 |
</tr> |
|
58 |
</table> |
|
59 |
|
|
60 |
[% L.hidden_tag('action', 'YearlyTransactions/dispatch') %] |
|
61 |
<hr size=3 noshade><br> |
|
62 |
[% L.submit_tag('action_list', LxERP.t8('Continue')) %] |
|
63 |
|
|
64 |
</form> |
templates/webpages/gl/yearly_top.html | ||
---|---|---|
1 |
[%- USE LxERP %] |
|
2 |
[%- INCLUDE 'common/flash.html' %] |
|
3 |
<form method="post" action="controller.pl"> |
|
4 |
<table> |
|
5 |
<tr> |
|
6 |
<td width="20px"></td> |
|
7 |
<td colspan="6" align="left"> |
|
8 |
[%- LxERP.t8('Select charts for which the CB/OB transactions want to be posted.') %]<br> |
|
9 |
[%- LxERP.t8('There will be two transactions done:') %]<br> |
|
10 |
- [%- LxERP.t8('One SB-transaction') %] ( [% SELF.cb_date %], [% SELF.cb_reference %], [% SELF.cb_description %], [% SELF.cbob_chartaccno %] )<br> |
|
11 |
- [%- LxERP.t8('One OB-transaction') %] ( [% SELF.ob_date %], [% SELF.ob_reference %], [% SELF.ob_description %], [% SELF.cbob_chartaccno %] )<br> |
|
12 |
[%- LxERP.t8('No revert available.') %] |
|
13 |
</td> |
|
14 |
</tr> |
|
15 |
<tr> |
|
16 |
<td><p></p></td> |
|
17 |
</tr> |
|
18 |
<tr> |
|
19 |
<th></th> |
|
20 |
<th align="right">[% LxERP.t8('close chart') %]</th> |
|
21 |
<td>[% SELF.cbob_chartaccno %]</td> |
|
22 |
</tr> |
|
23 |
</table> |
Auch abrufbar als: Unified diff
Erstellen von Jahresabschluss-Buchungen(2)
Auf Wunsch exaktere Bezeichnung des Controllers etc,
also statt yearly ==> yearend