Bug 11243: make vendor list distinguish between active and canceled items
[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
615         $r->{'budget_amount_total'} =  $r->{'budget_amount'};
616
617         # foreach sub-levels
618         my $unalloc_count ;
619
620                 foreach my $sub (@subs_arr) {
621                         my $sub_budget = GetBudget($sub);
622
623                         $r->{budget_spent_sublevel} +=    GetBudgetSpent( $sub_budget->{'budget_id'} );
624                         $unalloc_count +=   $sub_budget->{'budget_amount'};
625                 }
626         }
627         return \@sort;
628 }
629
630 # -------------------------------------------------------------------
631
632 sub AddBudget {
633     my ($budget) = @_;
634         return InsertInTable("aqbudgets",$budget);
635 }
636
637 # -------------------------------------------------------------------
638 sub ModBudget {
639     my ($budget) = @_;
640         return UpdateInTable("aqbudgets",$budget);
641 }
642
643 # -------------------------------------------------------------------
644 sub DelBudget {
645         my ($budget_id) = @_;
646         my $dbh         = C4::Context->dbh;
647         my $sth         = $dbh->prepare("delete from aqbudgets where budget_id=?");
648         my $rc          = $sth->execute($budget_id);
649         return $rc;
650 }
651
652
653 =head2 GetBudget
654
655   &GetBudget($budget_id);
656
657 get a specific budget
658
659 =cut
660
661 # -------------------------------------------------------------------
662 sub GetBudget {
663     my ( $budget_id ) = @_;
664     my $dbh = C4::Context->dbh;
665     my $query = "
666         SELECT *
667         FROM   aqbudgets
668         WHERE  budget_id=?
669         ";
670     my $sth = $dbh->prepare($query);
671     $sth->execute( $budget_id );
672     my $result = $sth->fetchrow_hashref;
673     return $result;
674 }
675
676 =head2 GetBudgetByOrderNumber
677
678   &GetBudgetByOrderNumber($ordernumber);
679
680 get a specific budget by order number
681
682 =cut
683
684 # -------------------------------------------------------------------
685 sub GetBudgetByOrderNumber {
686     my ( $ordernumber ) = @_;
687     my $dbh = C4::Context->dbh;
688     my $query = "
689         SELECT aqbudgets.*
690         FROM   aqbudgets, aqorders
691         WHERE  ordernumber=?
692         AND    aqorders.budget_id = aqbudgets.budget_id
693         ";
694     my $sth = $dbh->prepare($query);
695     $sth->execute( $ordernumber );
696     my $result = $sth->fetchrow_hashref;
697     return $result;
698 }
699
700 =head2 GetChildBudgetsSpent
701
702   &GetChildBudgetsSpent($budget-id);
703
704 gets the total spent of the level and sublevels of $budget_id
705
706 =cut
707
708 # -------------------------------------------------------------------
709 sub GetChildBudgetsSpent {
710     my ( $budget_id ) = @_;
711     my $dbh = C4::Context->dbh;
712     my $query = "
713         SELECT *
714         FROM   aqbudgets
715         WHERE  budget_parent_id=?
716         ";
717     my $sth = $dbh->prepare($query);
718     $sth->execute( $budget_id );
719     my $result = $sth->fetchall_arrayref({});
720     my $total_spent = GetBudgetSpent($budget_id);
721     if ($result){
722         $total_spent += GetChildBudgetsSpent($_->{"budget_id"}) foreach @$result;    
723     }
724     return $total_spent;
725 }
726
727 =head2 GetBudgets
728
729   &GetBudgets($filter, $order_by);
730
731 gets all budgets
732
733 =cut
734
735 # -------------------------------------------------------------------
736 sub GetBudgets {
737     my $filters = shift;
738     my $orderby = shift || 'budget_name';
739     return SearchInTable("aqbudgets",$filters, $orderby, undef,undef, undef, "wide");
740 }
741
742 =head2 GetBudgetUsers
743
744     my @borrowernumbers = &GetBudgetUsers($budget_id);
745
746 Return the list of borrowernumbers linked to a budget
747
748 =cut
749
750 sub GetBudgetUsers {
751     my ($budget_id) = @_;
752
753     my $dbh = C4::Context->dbh;
754     my $query = qq{
755         SELECT borrowernumber
756         FROM aqbudgetborrowers
757         WHERE budget_id = ?
758     };
759     my $sth = $dbh->prepare($query);
760     $sth->execute($budget_id);
761
762     my @borrowernumbers;
763     while (my ($borrowernumber) = $sth->fetchrow_array) {
764         push @borrowernumbers, $borrowernumber
765     }
766
767     return @borrowernumbers;
768 }
769
770 =head2 ModBudgetUsers
771
772     &ModBudgetUsers($budget_id, @borrowernumbers);
773
774 Modify the list of borrowernumbers linked to a budget
775
776 =cut
777
778 sub ModBudgetUsers {
779     my ($budget_id, @budget_users_id) = @_;
780
781     return unless $budget_id;
782
783     my $dbh = C4::Context->dbh;
784     my $query = "DELETE FROM aqbudgetborrowers WHERE budget_id = ?";
785     my $sth = $dbh->prepare($query);
786     $sth->execute($budget_id);
787
788     $query = qq{
789         INSERT INTO aqbudgetborrowers (budget_id, borrowernumber)
790         VALUES (?,?)
791     };
792     $sth = $dbh->prepare($query);
793     foreach my $borrowernumber (@budget_users_id) {
794         next unless $borrowernumber;
795         $sth->execute($budget_id, $borrowernumber);
796     }
797 }
798
799 sub CanUserUseBudget {
800     my ($borrower, $budget, $userflags) = @_;
801
802     if (not ref $borrower) {
803         $borrower = C4::Members::GetMember(borrowernumber => $borrower);
804     }
805     if (not ref $budget) {
806         $budget = GetBudget($budget);
807     }
808
809     return 0 unless ($borrower and $budget);
810
811     if (not defined $userflags) {
812         $userflags = C4::Auth::getuserflags($borrower->{flags},
813             $borrower->{userid});
814     }
815
816     unless ($userflags->{superlibrarian}
817     || (ref $userflags->{acquisition}
818         && $userflags->{acquisition}->{budget_manage_all})
819     || (!ref $userflags->{acquisition} && $userflags->{acquisition}))
820     {
821         if (not exists $userflags->{acquisition}) {
822             return 0;
823         }
824
825         if (!ref $userflags->{acquisition} && !$userflags->{acquisition}) {
826             return 0;
827         }
828
829         # Budget restricted to owner
830         if ($budget->{budget_permission} == 1
831         && $budget->{budget_owner_id}
832         && $budget->{budget_owner_id} != $borrower->{borrowernumber}) {
833             return 0;
834         }
835
836         my @budget_users = GetBudgetUsers($budget->{budget_id});
837
838         # Budget restricted to owner, users and library
839         if ($budget->{budget_permission} == 2
840         && $budget->{budget_owner_id}
841         && $budget->{budget_owner_id} != $borrower->{borrowernumber}
842         && (0 == grep {$borrower->{borrowernumber} == $_} @budget_users)
843         && defined $budget->{budget_branchcode}
844         && $budget->{budget_branchcode} ne C4::Context->userenv->{branch}) {
845             return 0;
846         }
847
848         # Budget restricted to owner and users
849         if ($budget->{budget_permission} == 3
850         && $budget->{budget_owner_id}
851         && $budget->{budget_owner_id} != $borrower->{borrowernumber}
852         && (0 == grep {$borrower->{borrowernumber} == $_} @budget_users)) {
853             return 0;
854         }
855     }
856
857     return 1;
858 }
859
860 sub CanUserModifyBudget {
861     my ($borrower, $budget, $userflags) = @_;
862
863     if (not ref $borrower) {
864         $borrower = C4::Members::GetMember(borrowernumber => $borrower);
865     }
866     if (not ref $budget) {
867         $budget = GetBudget($budget);
868     }
869
870     return 0 unless ($borrower and $budget);
871
872     if (not defined $userflags) {
873         $userflags = C4::Auth::getuserflags($borrower->{flags},
874             $borrower->{userid});
875     }
876
877     unless ($userflags->{superlibrarian}
878     || (ref $userflags->{acquisition}
879         && $userflags->{acquisition}->{budget_manage_all})
880     || (!ref $userflags->{acquisition} && $userflags->{acquisition}))
881     {
882         if (!CanUserUseBudget($borrower, $budget, $userflags)) {
883             return 0;
884         }
885
886         if (ref $userflags->{acquisition}
887         && !$userflags->{acquisition}->{budget_modify}) {
888             return 0;
889         }
890     }
891
892     return 1;
893 }
894
895 # -------------------------------------------------------------------
896
897 =head2 GetCurrencies
898
899   @currencies = &GetCurrencies;
900
901 Returns the list of all known currencies.
902
903 C<$currencies> is a array; its elements are references-to-hash, whose
904 keys are the fields from the currency table in the Koha database.
905
906 =cut
907
908 sub GetCurrencies {
909     my $dbh   = C4::Context->dbh;
910     my $query = "
911         SELECT *
912         FROM   currency
913     ";
914     my $sth = $dbh->prepare($query);
915     $sth->execute;
916     my @results = ();
917     while ( my $data = $sth->fetchrow_hashref ) {
918         push( @results, $data );
919     }
920     return @results;
921 }
922
923 # -------------------------------------------------------------------
924
925 sub GetCurrency {
926     my $dbh   = C4::Context->dbh;
927     my $query = "
928         SELECT * FROM currency where active = '1'    ";
929     my $sth = $dbh->prepare($query);
930     $sth->execute;
931     my $r = $sth->fetchrow_hashref;
932     return $r;
933 }
934
935 =head2 ModCurrencies
936
937 &ModCurrencies($currency, $newrate);
938
939 Sets the exchange rate for C<$currency> to be C<$newrate>.
940
941 =cut
942
943 sub ModCurrencies {
944     my ( $currency, $rate ) = @_;
945     my $dbh   = C4::Context->dbh;
946     my $query = qq|
947         UPDATE currency
948         SET    rate=?
949         WHERE  currency=? |;
950     my $sth = $dbh->prepare($query);
951     $sth->execute( $rate, $currency );
952 }
953
954 # -------------------------------------------------------------------
955
956 =head2 ConvertCurrency
957
958   $foreignprice = &ConvertCurrency($currency, $localprice);
959
960 Converts the price C<$localprice> to foreign currency C<$currency> by
961 dividing by the exchange rate, and returns the result.
962
963 If no exchange rate is found, e is one to one.
964
965 =cut
966
967 sub ConvertCurrency {
968     my ( $currency, $price ) = @_;
969     my $dbh   = C4::Context->dbh;
970     my $query = "
971         SELECT rate
972         FROM   currency
973         WHERE  currency=?
974     ";
975     my $sth = $dbh->prepare($query);
976     $sth->execute($currency);
977     my $cur = ( $sth->fetchrow_array() )[0];
978     unless ($cur) {
979         $cur = 1;
980     }
981     return ( $price / $cur );
982 }
983
984 END { }    # module clean-up code here (global destructor)
985
986 1;
987 __END__
988
989 =head1 AUTHOR
990
991 Koha Development Team <http://koha-community.org/>
992
993 =cut