Bug 7308: Show ordered amount in aqbudgets.pl
[koha.git] / C4 / Budgets.pm
1 package C4::Budgets;
2
3 # Copyright 2000-2002 Katipo Communications
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 use strict;
21 #use warnings; FIXME - Bug 2505
22 use C4::Context;
23 use C4::Dates qw(format_date format_date_in_iso);
24 use C4::SQLHelper qw<:all>;
25 use C4::Debug;
26
27 use vars qw($VERSION @ISA @EXPORT);
28
29 BEGIN {
30         # set the version for version checking
31     $VERSION = 3.07.00.049;
32         require Exporter;
33         @ISA    = qw(Exporter);
34         @EXPORT = qw(
35
36         &GetBudget
37         &GetBudgetByOrderNumber
38         &GetBudgets
39         &GetBudgetHierarchy
40             &AddBudget
41         &ModBudget
42         &DelBudget
43         &GetBudgetSpent
44         &GetBudgetOrdered
45         &GetBudgetName
46         &GetPeriodsCount
47         &GetChildBudgetsSpent
48
49         &GetBudgetUsers
50         &ModBudgetUsers
51         &CanUserUseBudget
52         &CanUserModifyBudget
53
54             &GetBudgetPeriod
55         &GetBudgetPeriods
56         &ModBudgetPeriod
57         &AddBudgetPeriod
58             &DelBudgetPeriod
59
60         &GetAuthvalueDropbox
61
62         &ModBudgetPlan
63
64         &GetCurrency
65         &GetCurrencies
66         &ModCurrencies
67         &ConvertCurrency
68         
69                 &GetBudgetsPlanCell
70         &AddBudgetPlanValue
71         &GetBudgetAuthCats
72         &BudgetHasChildren
73         &CheckBudgetParent
74         &CheckBudgetParentPerm
75
76         &HideCols
77         &GetCols
78         );
79 }
80
81 # ----------------------------BUDGETS.PM-----------------------------";
82
83
84 =head1 FUNCTIONS ABOUT BUDGETS
85
86 =cut
87
88 sub HideCols {
89     my ( $authcat, @hide_cols ) = @_;
90     my $dbh = C4::Context->dbh;
91
92     my $sth1 = $dbh->prepare(
93         qq|
94         UPDATE aqbudgets_planning SET display = 0 
95         WHERE authcat = ? 
96         AND  authvalue = ? |
97     );
98     foreach my $authvalue (@hide_cols) {
99 #        $sth1->{TraceLevel} = 3;
100         $sth1->execute(  $authcat, $authvalue );
101     }
102 }
103
104 sub GetCols {
105     my ( $authcat, $authvalue ) = @_;
106
107     my $dbh = C4::Context->dbh;
108     my $sth = $dbh->prepare(
109         qq|
110         SELECT count(display) as cnt from aqbudgets_planning
111         WHERE  authcat = ? 
112         AND authvalue = ? and display  = 0   |
113     );
114
115 #    $sth->{TraceLevel} = 3;
116     $sth->execute( $authcat, $authvalue );
117     my $res  = $sth->fetchrow_hashref;
118
119     return  $res->{cnt} > 0 ? 0: 1
120
121 }
122
123 sub CheckBudgetParentPerm {
124     my ( $budget, $borrower_id ) = @_;
125     my $depth = $budget->{depth};
126     my $parent_id = $budget->{budget_parent_id};
127     while ($depth) {
128         my $parent = GetBudget($parent_id);
129         $parent_id = $parent->{budget_parent_id};
130         if ( $parent->{budget_owner_id} == $borrower_id ) {
131             return 1;
132         }
133         $depth--
134     }
135     return 0;
136 }
137
138 sub AddBudgetPeriod {
139     my ($budgetperiod) = @_;
140         return InsertInTable("aqbudgetperiods",$budgetperiod);
141 }
142 # -------------------------------------------------------------------
143 sub GetPeriodsCount {
144     my $dbh = C4::Context->dbh;
145     my $sth = $dbh->prepare("
146         SELECT COUNT(*) AS sum FROM aqbudgetperiods ");
147     $sth->execute();
148     my $res = $sth->fetchrow_hashref;
149     return $res->{'sum'};
150 }
151
152 # -------------------------------------------------------------------
153 sub CheckBudgetParent {
154     my ( $new_parent, $budget ) = @_;
155     my $new_parent_id = $new_parent->{'budget_id'};
156     my $budget_id     = $budget->{'budget_id'};
157     my $dbh           = C4::Context->dbh;
158     my $parent_id_tmp = $new_parent_id;
159
160     # check new-parent is not a child (or a child's child ;)
161     my $sth = $dbh->prepare(qq|
162         SELECT budget_parent_id FROM
163             aqbudgets where budget_id = ? | );
164     while (1) {
165         $sth->execute($parent_id_tmp);
166         my $res = $sth->fetchrow_hashref;
167         if ( $res->{'budget_parent_id'} == $budget_id ) {
168             return 1;
169         }
170         if ( not defined $res->{'budget_parent_id'} ) {
171             return 0;
172         }
173         $parent_id_tmp = $res->{'budget_parent_id'};
174     }
175 }
176
177 # -------------------------------------------------------------------
178 sub BudgetHasChildren {
179     my ( $budget_id  ) = @_;
180     my $dbh = C4::Context->dbh;
181     my $sth = $dbh->prepare(qq|
182        SELECT count(*) as sum FROM  aqbudgets
183         WHERE budget_parent_id = ?   | );
184     $sth->execute( $budget_id );
185     my $sum = $sth->fetchrow_hashref;
186     return $sum->{'sum'};
187 }
188
189 # -------------------------------------------------------------------
190 sub GetBudgetsPlanCell {
191     my ( $cell, $period, $budget ) = @_;
192     my ($actual, $sth);
193     my $dbh = C4::Context->dbh;
194     if ( $cell->{'authcat'} eq 'MONTHS' ) {
195         # get the actual amount
196         $sth = $dbh->prepare( qq|
197
198             SELECT SUM(ecost) AS actual FROM aqorders
199                 WHERE    budget_id = ? AND
200                 entrydate like "$cell->{'authvalue'}%"  |
201         );
202         $sth->execute( $cell->{'budget_id'} );
203     } elsif ( $cell->{'authcat'} eq 'BRANCHES' ) {
204         # get the actual amount
205         $sth = $dbh->prepare( qq|
206
207             SELECT SUM(ecost) FROM aqorders
208                 LEFT JOIN aqorders_items
209                 ON (aqorders.ordernumber = aqorders_items.ordernumber)
210                 LEFT JOIN items
211                 ON (aqorders_items.itemnumber = items.itemnumber)
212                 WHERE budget_id = ? AND homebranch = ? |          );
213
214         $sth->execute( $cell->{'budget_id'}, $cell->{'authvalue'} );
215     } elsif ( $cell->{'authcat'} eq 'ITEMTYPES' ) {
216         # get the actual amount
217         $sth = $dbh->prepare(  qq|
218
219             SELECT SUM( ecost *  quantity) AS actual
220                 FROM aqorders JOIN biblioitems
221                 ON (biblioitems.biblionumber = aqorders.biblionumber )
222                 WHERE aqorders.budget_id = ? and itemtype  = ? |
223         );
224         $sth->execute(  $cell->{'budget_id'},
225                         $cell->{'authvalue'} );
226     }
227     # ELSE GENERIC ORDERS SORT1/SORT2 STAT COUNT.
228     else {
229         # get the actual amount
230         $sth = $dbh->prepare( qq|
231
232         SELECT  SUM(ecost * quantity) AS actual
233             FROM aqorders
234             JOIN aqbudgets ON (aqbudgets.budget_id = aqorders.budget_id )
235             WHERE  aqorders.budget_id = ? AND
236                 ((aqbudgets.sort1_authcat = ? AND sort1 =?) OR
237                 (aqbudgets.sort2_authcat = ? AND sort2 =?))    |
238         );
239         $sth->execute(  $cell->{'budget_id'},
240                         $budget->{'sort1_authcat'},
241                         $cell->{'authvalue'},
242                         $budget->{'sort2_authcat'},
243                         $cell->{'authvalue'}
244         );
245     }
246     $actual = $sth->fetchrow_array;
247
248     # get the estimated amount
249     $sth = $dbh->prepare( qq|
250
251         SELECT estimated_amount AS estimated, display FROM aqbudgets_planning
252             WHERE budget_period_id = ? AND
253                 budget_id = ? AND
254                 authvalue = ? AND
255                 authcat = ?         |
256     );
257     $sth->execute(  $cell->{'budget_period_id'},
258                     $cell->{'budget_id'},
259                     $cell->{'authvalue'},
260                     $cell->{'authcat'},
261     );
262
263
264     my $res  = $sth->fetchrow_hashref;
265   #  my $display = $res->{'display'};
266     my $estimated = $res->{'estimated'};
267
268
269     return $actual, $estimated;
270 }
271
272 # -------------------------------------------------------------------
273 sub ModBudgetPlan {
274     my ( $budget_plan, $budget_period_id, $authcat ) = @_;
275     my $dbh = C4::Context->dbh;
276     foreach my $buds (@$budget_plan) {
277         my $lines = $buds->{lines};
278         my $sth = $dbh->prepare( qq|
279                 DELETE FROM aqbudgets_planning
280                     WHERE   budget_period_id   = ? AND
281                             budget_id   = ? AND
282                             authcat            = ? |
283         );
284     #delete a aqplan line of cells, then insert new cells, 
285     # these could be UPDATES rather than DEL/INSERTS...
286         $sth->execute( $budget_period_id,  $lines->[0]{budget_id}   , $authcat );
287
288         foreach my $cell (@$lines) {
289             my $sth = $dbh->prepare( qq|
290
291                 INSERT INTO aqbudgets_planning
292                      SET   budget_id     = ?,
293                      budget_period_id  = ?,
294                      authcat          = ?,
295                      estimated_amount  = ?,
296                      authvalue       = ?  |
297             );
298             $sth->execute(
299                             $cell->{'budget_id'},
300                             $cell->{'budget_period_id'},
301                             $cell->{'authcat'},
302                             $cell->{'estimated_amount'},
303                             $cell->{'authvalue'},
304             );
305         }
306     }
307 }
308
309 # -------------------------------------------------------------------
310 sub GetBudgetSpent {
311         my ($budget_id) = @_;
312         my $dbh = C4::Context->dbh;
313         my $sth = $dbh->prepare(qq|
314         SELECT SUM( COALESCE(unitprice, ecost) * quantity ) AS sum FROM aqorders
315             WHERE budget_id = ? AND
316             quantityreceived > 0 AND
317             datecancellationprinted IS NULL
318     |);
319         $sth->execute($budget_id);
320         my $sum =  $sth->fetchrow_array;
321
322     $sth = $dbh->prepare(qq|
323         SELECT SUM(shipmentcost) AS sum
324         FROM aqinvoices
325         WHERE shipmentcost_budgetid = ?
326           AND closedate IS NOT NULL
327     |);
328     $sth->execute($budget_id);
329     my ($shipmentcost_sum) = $sth->fetchrow_array;
330     $sum += $shipmentcost_sum;
331
332         return $sum;
333 }
334
335 # -------------------------------------------------------------------
336 sub GetBudgetOrdered {
337         my ($budget_id) = @_;
338         my $dbh = C4::Context->dbh;
339         my $sth = $dbh->prepare(qq|
340         SELECT SUM(ecost *  quantity) AS sum FROM aqorders
341             WHERE budget_id = ? AND
342             quantityreceived = 0 AND
343             datecancellationprinted IS NULL
344     |);
345         $sth->execute($budget_id);
346         my $sum =  $sth->fetchrow_array;
347
348     $sth = $dbh->prepare(qq|
349         SELECT SUM(shipmentcost) AS sum
350         FROM aqinvoices
351         WHERE shipmentcost_budgetid = ?
352           AND closedate IS NULL
353     |);
354     $sth->execute($budget_id);
355     my ($shipmentcost_sum) = $sth->fetchrow_array;
356     $sum += $shipmentcost_sum;
357
358         return $sum;
359 }
360
361 =head2 GetBudgetName
362
363   my $budget_name = &GetBudgetName($budget_id);
364
365 get the budget_name for a given budget_id
366
367 =cut
368
369 sub GetBudgetName {
370     my ( $budget_id ) = @_;
371     my $dbh         = C4::Context->dbh;
372     my $sth         = $dbh->prepare(
373         qq|
374         SELECT budget_name
375         FROM aqbudgets
376         WHERE budget_id = ?
377     |);
378
379     $sth->execute($budget_id);
380     return $sth->fetchrow_array;
381 }
382
383 # -------------------------------------------------------------------
384 sub GetBudgetAuthCats  {
385     my ($budget_period_id) = shift;
386     # now, populate the auth_cats_loop used in the budget planning button
387     # we must retrieve all auth values used by at least one budget
388     my $dbh = C4::Context->dbh;
389     my $sth=$dbh->prepare("SELECT sort1_authcat,sort2_authcat FROM aqbudgets WHERE budget_period_id=?");
390     $sth->execute($budget_period_id);
391     my %authcats;
392     while (my ($sort1_authcat,$sort2_authcat) = $sth->fetchrow) {
393         $authcats{$sort1_authcat}=1;
394         $authcats{$sort2_authcat}=1;
395     }
396     my @auth_cats_loop;
397     foreach (sort keys %authcats) {
398         push @auth_cats_loop,{ authcat => $_ };
399     }
400     return \@auth_cats_loop;
401 }
402
403 # -------------------------------------------------------------------
404 sub GetAuthvalueDropbox {
405     my ( $authcat, $default ) = @_;
406     my $branch_limit = C4::Context->userenv ? C4::Context->userenv->{"branch"} : "";
407     my $dbh = C4::Context->dbh;
408
409     my $query = qq{
410         SELECT *
411         FROM authorised_values
412     };
413     $query .= qq{
414           LEFT JOIN authorised_values_branches ON ( id = av_id )
415     } if $branch_limit;
416     $query .= qq{
417         WHERE category = ?
418     };
419     $query .= " AND ( branchcode = ? OR branchcode IS NULL )" if $branch_limit;
420     $query .= " GROUP BY lib ORDER BY category, lib, lib_opac";
421     my $sth = $dbh->prepare($query);
422     $sth->execute( $authcat, $branch_limit ? $branch_limit : () );
423
424
425     my $option_list = [];
426     my @authorised_values = ( q{} );
427     while (my $av = $sth->fetchrow_hashref) {
428         push @{$option_list}, {
429             value => $av->{authorised_value},
430             label => $av->{lib},
431             default => ($default eq $av->{authorised_value}),
432         };
433     }
434
435     if ( @{$option_list} ) {
436         return $option_list;
437     }
438     return;
439 }
440
441 # -------------------------------------------------------------------
442 sub GetBudgetPeriods {
443         my ($filters,$orderby) = @_;
444     return SearchInTable("aqbudgetperiods",$filters, $orderby, undef,undef, undef, "wide");
445 }
446 # -------------------------------------------------------------------
447 sub GetBudgetPeriod {
448         my ($budget_period_id) = @_;
449         my $dbh = C4::Context->dbh;
450         ## $total = number of records linked to the record that must be deleted
451         my $total = 0;
452         ## get information about the record that will be deleted
453         my $sth;
454         if ($budget_period_id) {
455                 $sth = $dbh->prepare( qq|
456               SELECT      *
457                 FROM aqbudgetperiods
458                 WHERE budget_period_id=? |
459                 );
460                 $sth->execute($budget_period_id);
461         } else {         # ACTIVE BUDGET
462                 $sth = $dbh->prepare(qq|
463                           SELECT      *
464                 FROM aqbudgetperiods
465                 WHERE budget_period_active=1 |
466                 );
467                 $sth->execute();
468         }
469         my $data = $sth->fetchrow_hashref;
470         return $data;
471 }
472
473 # -------------------------------------------------------------------
474 sub DelBudgetPeriod{
475         my ($budget_period_id) = @_;
476         my $dbh = C4::Context->dbh;
477           ; ## $total = number of records linked to the record that must be deleted
478     my $total = 0;
479
480         ## get information about the record that will be deleted
481         my $sth = $dbh->prepare(qq|
482                 DELETE 
483          FROM aqbudgetperiods
484          WHERE budget_period_id=? |
485         );
486         return $sth->execute($budget_period_id);
487 }
488
489 # -------------------------------------------------------------------
490 sub ModBudgetPeriod {
491         my ($budget_period_information) = @_;
492         return UpdateInTable("aqbudgetperiods",$budget_period_information);
493 }
494
495 # -------------------------------------------------------------------
496 sub GetBudgetHierarchy {
497     my ( $budget_period_id, $branchcode, $owner ) = @_;
498     my @bind_params;
499     my $dbh   = C4::Context->dbh;
500     my $query = qq|
501                     SELECT aqbudgets.*, aqbudgetperiods.budget_period_active
502                     FROM aqbudgets 
503                     JOIN aqbudgetperiods USING (budget_period_id)|;
504                         
505         my @where_strings;
506     # show only period X if requested
507     if ($budget_period_id) {
508         push @where_strings," aqbudgets.budget_period_id = ?";
509         push @bind_params, $budget_period_id;
510     }
511         # show only budgets owned by me, my branch or everyone
512     if ($owner) {
513         if ($branchcode) {
514             push @where_strings,
515             qq{ (budget_owner_id = ? OR budget_branchcode = ? OR ((budget_branchcode IS NULL or budget_branchcode="") AND (budget_owner_id IS NULL OR budget_owner_id="")))};
516             push @bind_params, ( $owner, $branchcode );
517         } else {
518             push @where_strings, ' (budget_owner_id = ? OR budget_owner_id IS NULL or budget_owner_id ="") ';
519             push @bind_params, $owner;
520         }
521     } else {
522         if ($branchcode) {
523             push @where_strings," (budget_branchcode =? or budget_branchcode is NULL)";
524             push @bind_params, $branchcode;
525         }
526     }
527         $query.=" WHERE ".join(' AND ', @where_strings) if @where_strings;
528         $debug && warn $query,join(",",@bind_params);
529         my $sth = $dbh->prepare($query);
530         $sth->execute(@bind_params);
531         my $results = $sth->fetchall_arrayref({});
532         my @res     = @$results;
533         my $i = 0;
534         while (1) {
535                 my $depth_cnt = 0;
536                 foreach my $r (@res) {
537                         my @child;
538                         # look for children
539                         $r->{depth} = '0' if !defined $r->{budget_parent_id};
540                         foreach my $r2 (@res) {
541                                 if (defined $r2->{budget_parent_id}
542                                         && $r2->{budget_parent_id} == $r->{budget_id}) {
543                                         push @child, $r2->{budget_id};
544                                         $r2->{depth} = ($r->{depth} + 1) if defined $r->{depth};
545                                 }
546                         }
547                         $r->{child} = \@child if scalar @child > 0;    # add the child
548                         $depth_cnt++ if !defined $r->{'depth'};
549                 }
550                 last if ($depth_cnt == 0 || $i == 100);
551                 $i++;
552         }
553
554         # look for top parents 1st
555         my (@sort, $depth_count);
556         ($i, $depth_count) = 0;
557         while (1) {
558                 my $children = 0;
559                 foreach my $r (@res) {
560                         if ($r->{depth} == $depth_count) {
561                                 $children++ if (ref $r->{child} eq 'ARRAY');
562
563                                 # find the parent id element_id and insert it after
564                                 my $i2 = 0;
565                                 my $parent;
566                                 if ($depth_count > 0) {
567
568                                         # add indent
569                                         my $depth = $r->{depth} * 2;
570                                         $r->{budget_code_indent} = $r->{budget_code};
571                                         $r->{budget_name_indent} = $r->{budget_name};
572                                         foreach my $r3 (@sort) {
573                                                 if ($r3->{budget_id} == $r->{budget_parent_id}) {
574                                                         $parent = $i2;
575                                                         last;
576                                                 }
577                                                 $i2++;
578                                         }
579                                 } else {
580                                         $r->{budget_code_indent} = $r->{budget_code};
581                                         $r->{budget_name_indent} = $r->{budget_name};
582                                 }
583                 
584                                 if (defined $parent) {
585                                         splice @sort, ($parent + 1), 0, $r;
586                                 } else {
587                                         push @sort, $r;
588                                 }
589                         }
590
591                         $i++;
592                 }    # --------------foreach
593                 $depth_count++;
594                 last if $children == 0;
595         }
596
597 # add budget-percent and allocation, and flags for html-template
598         foreach my $r (@sort) {
599                 my $subs_href = $r->{'child'};
600         my @subs_arr = ();
601         if ( defined $subs_href ) {
602             @subs_arr = @{$subs_href};
603         }
604
605         my $moo = $r->{'budget_code_indent'};
606         $moo =~ s/\ /\&nbsp\;/g;
607         $r->{'budget_code_indent'} =  $moo;
608
609         $moo = $r->{'budget_name_indent'};
610         $moo =~ s/\ /\&nbsp\;/g;
611         $r->{'budget_name_indent'} = $moo;
612
613         $r->{'budget_spent'}       = GetBudgetSpent( $r->{'budget_id'} );
614         $r->{budget_ordered} = GetBudgetOrdered( $r->{budget_id} );
615
616         $r->{'budget_amount_total'} =  $r->{'budget_amount'};
617
618         # foreach sub-levels
619         my $unalloc_count ;
620
621                 foreach my $sub (@subs_arr) {
622                         my $sub_budget = GetBudget($sub);
623
624                         $r->{budget_spent_sublevel} +=    GetBudgetSpent( $sub_budget->{'budget_id'} );
625                         $unalloc_count +=   $sub_budget->{'budget_amount'};
626                 }
627         }
628         return \@sort;
629 }
630
631 # -------------------------------------------------------------------
632
633 sub AddBudget {
634     my ($budget) = @_;
635         return InsertInTable("aqbudgets",$budget);
636 }
637
638 # -------------------------------------------------------------------
639 sub ModBudget {
640     my ($budget) = @_;
641         return UpdateInTable("aqbudgets",$budget);
642 }
643
644 # -------------------------------------------------------------------
645 sub DelBudget {
646         my ($budget_id) = @_;
647         my $dbh         = C4::Context->dbh;
648         my $sth         = $dbh->prepare("delete from aqbudgets where budget_id=?");
649         my $rc          = $sth->execute($budget_id);
650         return $rc;
651 }
652
653
654 =head2 GetBudget
655
656   &GetBudget($budget_id);
657
658 get a specific budget
659
660 =cut
661
662 # -------------------------------------------------------------------
663 sub GetBudget {
664     my ( $budget_id ) = @_;
665     my $dbh = C4::Context->dbh;
666     my $query = "
667         SELECT *
668         FROM   aqbudgets
669         WHERE  budget_id=?
670         ";
671     my $sth = $dbh->prepare($query);
672     $sth->execute( $budget_id );
673     my $result = $sth->fetchrow_hashref;
674     return $result;
675 }
676
677 =head2 GetBudgetByOrderNumber
678
679   &GetBudgetByOrderNumber($ordernumber);
680
681 get a specific budget by order number
682
683 =cut
684
685 # -------------------------------------------------------------------
686 sub GetBudgetByOrderNumber {
687     my ( $ordernumber ) = @_;
688     my $dbh = C4::Context->dbh;
689     my $query = "
690         SELECT aqbudgets.*
691         FROM   aqbudgets, aqorders
692         WHERE  ordernumber=?
693         AND    aqorders.budget_id = aqbudgets.budget_id
694         ";
695     my $sth = $dbh->prepare($query);
696     $sth->execute( $ordernumber );
697     my $result = $sth->fetchrow_hashref;
698     return $result;
699 }
700
701 =head2 GetChildBudgetsSpent
702
703   &GetChildBudgetsSpent($budget-id);
704
705 gets the total spent of the level and sublevels of $budget_id
706
707 =cut
708
709 # -------------------------------------------------------------------
710 sub GetChildBudgetsSpent {
711     my ( $budget_id ) = @_;
712     my $dbh = C4::Context->dbh;
713     my $query = "
714         SELECT *
715         FROM   aqbudgets
716         WHERE  budget_parent_id=?
717         ";
718     my $sth = $dbh->prepare($query);
719     $sth->execute( $budget_id );
720     my $result = $sth->fetchall_arrayref({});
721     my $total_spent = GetBudgetSpent($budget_id);
722     if ($result){
723         $total_spent += GetChildBudgetsSpent($_->{"budget_id"}) foreach @$result;    
724     }
725     return $total_spent;
726 }
727
728 =head2 GetBudgets
729
730   &GetBudgets($filter, $order_by);
731
732 gets all budgets
733
734 =cut
735
736 # -------------------------------------------------------------------
737 sub GetBudgets {
738     my $filters = shift;
739     my $orderby = shift || 'budget_name';
740     return SearchInTable("aqbudgets",$filters, $orderby, undef,undef, undef, "wide");
741 }
742
743 =head2 GetBudgetUsers
744
745     my @borrowernumbers = &GetBudgetUsers($budget_id);
746
747 Return the list of borrowernumbers linked to a budget
748
749 =cut
750
751 sub GetBudgetUsers {
752     my ($budget_id) = @_;
753
754     my $dbh = C4::Context->dbh;
755     my $query = qq{
756         SELECT borrowernumber
757         FROM aqbudgetborrowers
758         WHERE budget_id = ?
759     };
760     my $sth = $dbh->prepare($query);
761     $sth->execute($budget_id);
762
763     my @borrowernumbers;
764     while (my ($borrowernumber) = $sth->fetchrow_array) {
765         push @borrowernumbers, $borrowernumber
766     }
767
768     return @borrowernumbers;
769 }
770
771 =head2 ModBudgetUsers
772
773     &ModBudgetUsers($budget_id, @borrowernumbers);
774
775 Modify the list of borrowernumbers linked to a budget
776
777 =cut
778
779 sub ModBudgetUsers {
780     my ($budget_id, @budget_users_id) = @_;
781
782     return unless $budget_id;
783
784     my $dbh = C4::Context->dbh;
785     my $query = "DELETE FROM aqbudgetborrowers WHERE budget_id = ?";
786     my $sth = $dbh->prepare($query);
787     $sth->execute($budget_id);
788
789     $query = qq{
790         INSERT INTO aqbudgetborrowers (budget_id, borrowernumber)
791         VALUES (?,?)
792     };
793     $sth = $dbh->prepare($query);
794     foreach my $borrowernumber (@budget_users_id) {
795         next unless $borrowernumber;
796         $sth->execute($budget_id, $borrowernumber);
797     }
798 }
799
800 sub CanUserUseBudget {
801     my ($borrower, $budget, $userflags) = @_;
802
803     if (not ref $borrower) {
804         $borrower = C4::Members::GetMember(borrowernumber => $borrower);
805     }
806     if (not ref $budget) {
807         $budget = GetBudget($budget);
808     }
809
810     return 0 unless ($borrower and $budget);
811
812     if (not defined $userflags) {
813         $userflags = C4::Auth::getuserflags($borrower->{flags},
814             $borrower->{userid});
815     }
816
817     unless ($userflags->{superlibrarian}
818     || (ref $userflags->{acquisition}
819         && $userflags->{acquisition}->{budget_manage_all})
820     || (!ref $userflags->{acquisition} && $userflags->{acquisition}))
821     {
822         if (not exists $userflags->{acquisition}) {
823             return 0;
824         }
825
826         if (!ref $userflags->{acquisition} && !$userflags->{acquisition}) {
827             return 0;
828         }
829
830         # Budget restricted to owner
831         if ($budget->{budget_permission} == 1
832         && $budget->{budget_owner_id}
833         && $budget->{budget_owner_id} != $borrower->{borrowernumber}) {
834             return 0;
835         }
836
837         my @budget_users = GetBudgetUsers($budget->{budget_id});
838
839         # Budget restricted to owner, users and library
840         if ($budget->{budget_permission} == 2
841         && $budget->{budget_owner_id}
842         && $budget->{budget_owner_id} != $borrower->{borrowernumber}
843         && (0 == grep {$borrower->{borrowernumber} == $_} @budget_users)
844         && defined $budget->{budget_branchcode}
845         && $budget->{budget_branchcode} ne C4::Context->userenv->{branch}) {
846             return 0;
847         }
848
849         # Budget restricted to owner and users
850         if ($budget->{budget_permission} == 3
851         && $budget->{budget_owner_id}
852         && $budget->{budget_owner_id} != $borrower->{borrowernumber}
853         && (0 == grep {$borrower->{borrowernumber} == $_} @budget_users)) {
854             return 0;
855         }
856     }
857
858     return 1;
859 }
860
861 sub CanUserModifyBudget {
862     my ($borrower, $budget, $userflags) = @_;
863
864     if (not ref $borrower) {
865         $borrower = C4::Members::GetMember(borrowernumber => $borrower);
866     }
867     if (not ref $budget) {
868         $budget = GetBudget($budget);
869     }
870
871     return 0 unless ($borrower and $budget);
872
873     if (not defined $userflags) {
874         $userflags = C4::Auth::getuserflags($borrower->{flags},
875             $borrower->{userid});
876     }
877
878     unless ($userflags->{superlibrarian}
879     || (ref $userflags->{acquisition}
880         && $userflags->{acquisition}->{budget_manage_all})
881     || (!ref $userflags->{acquisition} && $userflags->{acquisition}))
882     {
883         if (!CanUserUseBudget($borrower, $budget, $userflags)) {
884             return 0;
885         }
886
887         if (ref $userflags->{acquisition}
888         && !$userflags->{acquisition}->{budget_modify}) {
889             return 0;
890         }
891     }
892
893     return 1;
894 }
895
896 # -------------------------------------------------------------------
897
898 =head2 GetCurrencies
899
900   @currencies = &GetCurrencies;
901
902 Returns the list of all known currencies.
903
904 C<$currencies> is a array; its elements are references-to-hash, whose
905 keys are the fields from the currency table in the Koha database.
906
907 =cut
908
909 sub GetCurrencies {
910     my $dbh   = C4::Context->dbh;
911     my $query = "
912         SELECT *
913         FROM   currency
914     ";
915     my $sth = $dbh->prepare($query);
916     $sth->execute;
917     my @results = ();
918     while ( my $data = $sth->fetchrow_hashref ) {
919         push( @results, $data );
920     }
921     return @results;
922 }
923
924 # -------------------------------------------------------------------
925
926 sub GetCurrency {
927     my $dbh   = C4::Context->dbh;
928     my $query = "
929         SELECT * FROM currency where active = '1'    ";
930     my $sth = $dbh->prepare($query);
931     $sth->execute;
932     my $r = $sth->fetchrow_hashref;
933     return $r;
934 }
935
936 =head2 ModCurrencies
937
938 &ModCurrencies($currency, $newrate);
939
940 Sets the exchange rate for C<$currency> to be C<$newrate>.
941
942 =cut
943
944 sub ModCurrencies {
945     my ( $currency, $rate ) = @_;
946     my $dbh   = C4::Context->dbh;
947     my $query = qq|
948         UPDATE currency
949         SET    rate=?
950         WHERE  currency=? |;
951     my $sth = $dbh->prepare($query);
952     $sth->execute( $rate, $currency );
953 }
954
955 # -------------------------------------------------------------------
956
957 =head2 ConvertCurrency
958
959   $foreignprice = &ConvertCurrency($currency, $localprice);
960
961 Converts the price C<$localprice> to foreign currency C<$currency> by
962 dividing by the exchange rate, and returns the result.
963
964 If no exchange rate is found, e is one to one.
965
966 =cut
967
968 sub ConvertCurrency {
969     my ( $currency, $price ) = @_;
970     my $dbh   = C4::Context->dbh;
971     my $query = "
972         SELECT rate
973         FROM   currency
974         WHERE  currency=?
975     ";
976     my $sth = $dbh->prepare($query);
977     $sth->execute($currency);
978     my $cur = ( $sth->fetchrow_array() )[0];
979     unless ($cur) {
980         $cur = 1;
981     }
982     return ( $price / $cur );
983 }
984
985 END { }    # module clean-up code here (global destructor)
986
987 1;
988 __END__
989
990 =head1 AUTHOR
991
992 Koha Development Team <http://koha-community.org/>
993
994 =cut