Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 06ceb72f

Von Kivitendo Admin vor mehr als 1 Jahr hinzugefügt

  • ID 06ceb72f9dbed14b5cbd12f45b2cfaa9ddec81d4
  • Vorgänger 1e218446
  • Nachfolger 63517dfe

Konten ausziffern - Ausziffergruppen erstellen und löschen

Unterschiede anzeigen:

SL/Clearing.pm
1
package SL::Clearing;
2

  
3
use strict;
4
use warnings;
5

  
6
use SL::DB::Employee;
7
use SL::DB::Cleared;
8
use SL::DB::ClearedGroup;
9
use SL::DBUtils;
10

  
11
sub create_cleared_group {
12
  my ($acc_trans_ids) = @_;
13

  
14
  my @acc_trans_ids = @$acc_trans_ids;
15

  
16
  die "need at least 2 acc_trans entries" unless scalar @acc_trans_ids > 1;
17

  
18
  my $db = SL::DB->client;
19

  
20
  $db->with_transaction(sub {
21
    # check that
22
    # * sum of selected acc_trans amounts is 0
23
    # * there is more than 1 acc_trans
24
    # * they are all for the same chart
25
    # * and the chart is configured for clearing
26
    # * none of the transactions have been cleared yet
27
    #
28
    # to save db calls or later calculations in code, do this is all with one query
29

  
30
    my $query = <<SQL;
31
with selected_acc_trans as (
32
  select a.amount, a.chart_id,
33
         c.clearing,
34
         cl.cleared_group_id
35
    from acc_trans a
36
         left join chart c on (c.id = a.chart_id)
37
         left join cleared cl on (cl.acc_trans_id = a.acc_trans_id)
38
   where a.acc_trans_id = any(?)
39
),
40
sum_and_count as (
41
  select count(amount) as count,
42
         sum(amount)   as sum
43
    from selected_acc_trans
44
),
45
all_transactions_uncleared as (
46
  select case when count(*) > 0
47
              then false
48
              else true
49
              end as all_transactions_uncleared
50
    from selected_acc_trans
51
   where cleared_group_id is not null
52
),
53
distinct_charts as (
54
  select count(distinct chart_id) as number_of_distinct_charts
55
    from selected_acc_trans
56
),
57
all_charts_have_clearing as (
58
  select case when count(*) > 0
59
              then false
60
              else true
61
              end as all_charts_have_clearing
62
    from selected_acc_trans
63
   where clearing is false
64
)
65
select ( select sum from sum_and_count ),
66
       ( select count from sum_and_count ),
67
       ( select all_transactions_uncleared from all_transactions_uncleared ),
68
       ( select number_of_distinct_charts from distinct_charts ),
69
       ( select all_charts_have_clearing from all_charts_have_clearing )
70
SQL
71
    my ($sum, $count, $all_transactions_uncleared, $number_of_distinct_charts, $all_charts_have_clearing)
72
      = selectfirst_array_query($::form, $db->dbh, $query, \@acc_trans_ids);
73

  
74
    die "clearing error: sum isn't 0" unless $sum == 0;
75
    die "clearing error: need to select more than one transaction" unless $count > 1;
76
    die "clearing error: no acc_trans selected" unless $count > 1;
77
    die "clearing error: some bookings have already been cleared" unless $all_transactions_uncleared;
78
    die "clearing error: all bookings must be for the same chart" unless $number_of_distinct_charts == 1;
79
    die "clearing error: can only clear bookings for charts that are configured for clearing" unless $all_charts_have_clearing;
80

  
81
    my $cg = SL::DB::ClearedGroup->new(
82
      employee_id => SL::DB::Manager::Employee->current->id,
83
    )->save;
84

  
85
    foreach my $acc_trans_id ( @acc_trans_ids ) {
86
      SL::DB::Cleared->new(
87
        acc_trans_id     => $acc_trans_id,
88
        cleared_group_id => $cg->id,
89
      )->save;
90
    }
91
    return $cg;
92
  }) or do {
93
    die "error while saving cleared_group: " . $@;
94
  };
95
}
96

  
97
sub remove_cleared_group {
98
  my ($cleared_group_id) = @_;
99

  
100
  my $result = SL::DB::ClearedGroup->new(id => $cleared_group_id)->delete;
101
  $result ? return 1 : die "error while deleting cleared_group";
102
}
103

  
104
sub load_chart_transactions {
105
  my ($params) = @_;
106

  
107
  # possible params:
108
  #
109
  # chart_id  (necessary)
110
  # fromdate
111
  # todate
112
  # project_id
113
  # department_id
114
  # load_cleared
115

  
116
  die "missing chart_id param" unless $params->{chart_id};
117
  my $dbh = SL::DB->client->dbh;
118

  
119
  my %params = %{$params};
120

  
121
  my @sql_params = delete $params{"chart_id"};
122

  
123
  my $WHERE = '';
124

  
125
  # only load cleared bookings if this is explicitly desired
126
  if ( $params{"load_cleared"} ) {
127
    delete $params{"load_cleared"};
128
  } else {
129
    $WHERE .= ' and cl.cleared_group_id is null ';
130
  };
131

  
132
  if ( $params{"fromdate"} && ref($params{"fromdate"}) eq 'DateTime' ) {
133
    push(@sql_params, delete $params{"fromdate"});
134
    $WHERE .= ' and a.transdate >= ? '
135
  }
136

  
137
  if ( $params{"todate"} && ref($params{"todate"}) eq 'DateTime' ) {
138
    push(@sql_params, delete $params{"todate"});
139
    $WHERE .= ' and a.transdate <= ? '
140
  }
141

  
142
  my $PROJECT_WHERE = '';
143
  if ( $params{"project_id"} ) {
144
    $PROJECT_WHERE = ' and coalesce(a.project_id, ap.globalproject_id, ar.globalproject_id) = ? ';
145
    push(@sql_params, delete $params{"project_id"});
146
  }
147

  
148
  my $DEPARTMENT_WHERE = '';
149
  if ( $params{"department_id"} ) {
150
    $DEPARTMENT_WHERE = ' and coalesce(ap.department_id, ar.department_id, gl.department_id) = ? ';
151
    push(@sql_params, delete $params{"department_id"});
152
  }
153

  
154
  # if ( keys %params) {
155
  #   # hash not empty, log it
156
  #   $main::lxdebug->dump(0, "found illegal params in Clearing load_data", \%params);
157
  # }
158

  
159
  # limit number of transactions to be loaded, so you don't overwhelm the
160
  # interface if you forget to set dates
161
  my $LIMIT = 1500; # TODO: better way of dealing with limit.
162

  
163
  my $sql = <<"SQL";
164
select a.acc_trans_id,
165
       a.itime,
166
       a.amount, a.transdate,
167
       case when a.amount > 0 then a.amount      else null end as credit,
168
       case when a.amount < 0 then a.amount * -1 else null end as debit,
169
       c.accno, c.description,
170
       p.id as project_id, p.projectnumber, p.description as projectdescription,
171
       case when cl.acc_trans_id is not null then true else false end as cleared,
172
       cl.cleared_group_id,
173
       e.name as employee,
174
       e.id as employee_id,
175
       coalesce(gl.reference, ar.invnumber, ap.invnumber) as reference,
176
       case when gl.id is not null then 'gl'
177
            when ar.id is not null then 'ar'
178
                                   else 'ap'
179
            end as record_type,
180
       gegen_chart_accnos.accnos as gegen_chart_accnos
181
  from acc_trans a
182
       left join chart c on (c.id = a.chart_id)
183
       left join gl on (gl.id = a.trans_id)
184
       left join ar on (ar.id = a.trans_id)
185
       left join ap on (ap.id = a.trans_id)
186
       left join project p on (p.id = coalesce(a.project_id, ap.globalproject_id, ar.globalproject_id))
187
       left join employee e on (coalesce(gl.employee_id, ar.employee_id, ap.employee_id) = e.id)
188
       left join cleared cl on (cl.acc_trans_id = a.acc_trans_id)
189
       left join lateral (
190
                           select string_agg(chart.accno, ', ' ) as accnos
191
                             from acc_trans
192
                                  left join chart on (chart.id = acc_trans.chart_id)
193
                            where trans_id = a.trans_id and acc_trans_id != a.acc_trans_id
194
                              and sign(a.amount) != sign(amount)  -- ignore charts of opposite sign
195
                         ) gegen_chart_accnos on true
196
 where c.id = ?
197
       $WHERE
198
       $PROJECT_WHERE
199
       $DEPARTMENT_WHERE
200
order by a.transdate
201
limit $LIMIT
202
SQL
203

  
204
  selectall_hashref_query($::form, $dbh, $sql, @sql_params);
205
}
206

  
207
sub load_cleared_group_transactions_by_group_id {
208
  my ($cleared_group_id) = @_;
209

  
210
  my $dbh = SL::DB->client->dbh;
211

  
212
  my $sql = <<"SQL";
213
select a.acc_trans_id,
214
       a.amount, a.transdate,
215
       case when a.amount > 0 then a.amount      else null end as credit,
216
       case when a.amount < 0 then a.amount * -1 else null end as debit,
217
       c.accno, c.description,
218
       case when cl.acc_trans_id is not null then true else false end as cleared,
219
       cl.cleared_group_id,
220
       cg.itime,
221
       e.name as employee,
222
       e.id as employee_id,
223
       coalesce(gl.reference, ar.invnumber, ap.invnumber) as reference,
224
       case when gl.id is not null then 'gl'
225
            when ar.id is not null then 'ar'
226
                                   else 'ap'
227
            end as record_type,
228
       gegen_chart_accnos.accnos as gegen_chart_accnos
229
  from cleared cl
230
       left join cleared_group cg on (cg.id = cl.cleared_group_id)
231
       left join acc_trans a      on (cl.acc_trans_id = a.acc_trans_id)
232
       left join chart c          on (c.id = a.chart_id)
233
       left join gl               on (gl.id = a.trans_id)
234
       left join ar               on (ar.id = a.trans_id)
235
       left join ap               on (ap.id = a.trans_id)
236
       left join employee e       on (cg.employee_id = e.id )   -- employee is the employee who cleared it
237
       left join lateral (
238
                           select string_agg(chart.accno, ', ' ) as accnos
239
                             from acc_trans
240
                                  left join chart on (chart.id = acc_trans.chart_id)
241
                            where trans_id = a.trans_id and acc_trans_id != a.acc_trans_id
242
                              and sign(a.amount) != sign(amount)  -- ignore bookings of opposite sign
243
                         ) gegen_chart_accnos on true
244
 where cl.cleared_group_id = ?
245
order by a.transdate
246
SQL
247
  my $data = selectall_hashref_query($::form, $dbh, $sql, $cleared_group_id);
248
  return $data;
249
}
250

  
251
1;

Auch abrufbar als: Unified diff