View | Details | Raw Unified | Return to bug 12164
Collapse All | Expand All

(-)a/C4/Acquisition.pm (+6 lines)
Lines 1723-1728 sub SearchOrders { Link Here
1723
    my $owner = $params->{owner};
1723
    my $owner = $params->{owner};
1724
    my $pending = $params->{pending};
1724
    my $pending = $params->{pending};
1725
    my $ordered = $params->{ordered};
1725
    my $ordered = $params->{ordered};
1726
    my $budget_id = $params->{budget_id};
1726
1727
1727
    my $dbh = C4::Context->dbh;
1728
    my $dbh = C4::Context->dbh;
1728
    my @args = ();
1729
    my @args = ();
Lines 1812-1817 sub SearchOrders { Link Here
1812
        push @args, $userenv->{'number'};
1813
        push @args, $userenv->{'number'};
1813
    }
1814
    }
1814
1815
1816
    if ( $budget_id ) {
1817
        $query .= ' AND aqorders.budget_id = ?';
1818
        push @args, $budget_id;
1819
    }
1820
1815
    $query .= ' ORDER BY aqbasket.basketno';
1821
    $query .= ' ORDER BY aqbasket.basketno';
1816
1822
1817
    my $sth = $dbh->prepare($query);
1823
    my $sth = $dbh->prepare($query);
(-)a/C4/Budgets.pm (+78 lines)
Lines 1021-1026 sub CloneBudgetPeriod { Link Here
1021
1021
1022
    $budget_period->{budget_period_startdate} = $budget_period_startdate;
1022
    $budget_period->{budget_period_startdate} = $budget_period_startdate;
1023
    $budget_period->{budget_period_enddate}   = $budget_period_enddate;
1023
    $budget_period->{budget_period_enddate}   = $budget_period_enddate;
1024
    # The new budget (budget_period) should be active by default
1025
    $budget_period->{budget_period_active}    = 1;
1024
    my $original_budget_period_id = $budget_period->{budget_period_id};
1026
    my $original_budget_period_id = $budget_period->{budget_period_id};
1025
    delete $budget_period->{budget_period_id};
1027
    delete $budget_period->{budget_period_id};
1026
    my $new_budget_period_id = AddBudgetPeriod( $budget_period );
1028
    my $new_budget_period_id = AddBudgetPeriod( $budget_period );
Lines 1100-1105 sub CloneBudgetHierarchy { Link Here
1100
    }
1102
    }
1101
}
1103
}
1102
1104
1105
=head2 MoveOrders
1106
1107
  my $report = MoveOrders({
1108
    from_budget_period_id => $from_budget_period_id,
1109
    to_budget_period_id   => $to_budget_period_id,
1110
  });
1111
1112
Clone a budget hierarchy.
1113
1114
=cut
1115
1116
sub MoveOrders {
1117
    my ($params)              = @_;
1118
    my $from_budget_period_id = $params->{from_budget_period_id};
1119
    my $to_budget_period_id   = $params->{to_budget_period_id};
1120
    return
1121
      if not $from_budget_period_id
1122
          or not $to_budget_period_id
1123
          or $from_budget_period_id == $to_budget_period_id;
1124
1125
    # Can't move orders to an inactive budget (budgetperiod)
1126
    my $budget_period = GetBudgetPeriod($to_budget_period_id);
1127
    return unless $budget_period->{budget_period_active};
1128
1129
    my @report;
1130
    my $dbh     = C4::Context->dbh;
1131
    my $sth_update_aqorders = $dbh->prepare(
1132
        q|
1133
            UPDATE aqorders
1134
            SET budget_id = ?
1135
            WHERE ordernumber = ?
1136
        |
1137
    );
1138
    my $from_budgets = GetBudgetHierarchy($from_budget_period_id);
1139
    for my $from_budget (@$from_budgets) {
1140
        my $new_budget_id = $dbh->selectcol_arrayref(
1141
            q|
1142
                SELECT budget_id
1143
                FROM aqbudgets
1144
                WHERE budget_period_id = ?
1145
                    AND budget_code = ?
1146
            |, {}, $to_budget_period_id, $from_budget->{budget_code}
1147
        );
1148
        $new_budget_id = $new_budget_id->[0];
1149
        my $new_budget = GetBudget( $new_budget_id );
1150
        unless ( $new_budget ) {
1151
            push @report,
1152
              {
1153
                moved       => 0,
1154
                budget_code => $from_budget->{budget_code},
1155
                error       => 'budget_code_not_exists',
1156
              };
1157
            next;
1158
        }
1159
        my $orders_to_move = C4::Acquisition::SearchOrders(
1160
            {
1161
                budget_id => $from_budget->{budget_id},
1162
                pending   => 1,
1163
            }
1164
        );
1165
1166
        my @orders_moved;
1167
        for my $order (@$orders_to_move) {
1168
            $sth_update_aqorders->execute( $new_budget->{budget_id}, $order->{ordernumber} );
1169
            push @orders_moved, $order->{ordernumber};
1170
        }
1171
1172
        push @report,
1173
          {
1174
            budget => $new_budget,
1175
            orders_moved  => \@orders_moved,
1176
            moved         => 1,
1177
          };
1178
    }
1179
    return \@report;
1180
}
1103
1181
1104
END { }    # module clean-up code here (global destructor)
1182
END { }    # module clean-up code here (global destructor)
1105
1183
(-)a/admin/aqbudgetperiods.pl (-2 / +48 lines)
Lines 45-52 script to administer the budget periods table Link Here
45
=cut
45
=cut
46
46
47
## modules
47
## modules
48
use strict;
48
use Modern::Perl;
49
#use warnings; FIXME - Bug 2505
50
use Number::Format qw(format_price);
49
use Number::Format qw(format_price);
51
use CGI;
50
use CGI;
52
use List::Util qw/min/;
51
use List::Util qw/min/;
Lines 202-207 elsif ( $op eq 'duplicate_budget' ){ Link Here
202
    $op = 'else';
201
    $op = 'else';
203
}
202
}
204
203
204
elsif ( $op eq 'close_form' ) {
205
206
    my $budget_period = GetBudgetPeriod($budget_period_id);
207
208
    my $active_budget_periods =
209
      C4::Budgets::GetBudgetPeriods( { active => 1 } );
210
211
    # Remove the budget period from the list
212
    $active_budget_periods =
213
      [ map { ( $_->{budget_period_id} == $budget_period_id ) ? () : $_ }
214
          @$active_budget_periods ];
215
216
    my $budgets_to_move = GetBudgetHierarchy($budget_period_id);
217
218
    # C4::Context->userenv->{branchcode}, $show_mine ? $borrower_id : '')
219
220
    my $number_of_unreceived_orders = 0;
221
    for my $budget (@$budgets_to_move) {
222
223
        # We want to move funds from this budget
224
        my $unreceived_orders = C4::Acquisition::SearchOrders(
225
            { budget_id => $budget->{budget_id}, } );
226
        $budget->{unreceived_orders} = $unreceived_orders;
227
        $number_of_unreceived_orders += scalar(@$unreceived_orders);
228
    }
229
230
    $template->param(
231
        close_form       => 1,
232
        budget_period_id => $budget_period_id,
233
        budget_period_description =>
234
          $budget_period->{budget_period_description},
235
        budget_periods              => $active_budget_periods,
236
        budgets_to_move             => $budgets_to_move,
237
        number_of_unreceived_orders => $number_of_unreceived_orders,
238
    );
239
}
240
241
elsif ( $op eq 'close_confirmed' ) {
242
    my $to_budget_period_id = $input->param('to_budget_period_id');
243
    my $report              = C4::Budgets::MoveOrders(
244
        {
245
            from_budget_period_id => $budget_period_id,
246
            to_budget_period_id   => $to_budget_period_id,
247
        }
248
    );
249
}
250
205
# DEFAULT - DISPLAY AQPERIODS TABLE
251
# DEFAULT - DISPLAY AQPERIODS TABLE
206
# -------------------------------------------------------------------
252
# -------------------------------------------------------------------
207
# display the list of budget periods
253
# display the list of budget periods
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgetperiods.tt (-2 / +89 lines)
Lines 4-9 Link Here
4
[% INCLUDE 'doc-head-close.inc' %]
4
[% INCLUDE 'doc-head-close.inc' %]
5
[% INCLUDE 'calendar.inc' %]
5
[% INCLUDE 'calendar.inc' %]
6
[% INCLUDE 'datatables.inc' %]
6
[% INCLUDE 'datatables.inc' %]
7
[% IF close_form %]
8
    <link href="[% interface %]/lib/jquery/plugins/treetable/stylesheets/jquery.treetable.css" rel="stylesheet" type="text/css" />
9
    <script type="text/javascript" src="[% interface %]/lib/jquery/plugins/treetable/jquery.treetable.js"></script>
10
[% END %]
7
<script type="text/javascript" src="[% themelang %]/js/acq.js"></script>
11
<script type="text/javascript" src="[% themelang %]/js/acq.js"></script>
8
<script type="text/javascript">
12
<script type="text/javascript">
9
// #################################################################################
13
// #################################################################################
Lines 84-91 Link Here
84
                { "aTargets": [ -1 ], "bSortable": false, "bSearchable": false },
88
                { "aTargets": [ -1 ], "bSortable": false, "bSearchable": false },
85
                { "sType": "title-string", "aTargets" : [ "title-string" ] }
89
                { "sType": "title-string", "aTargets" : [ "title-string" ] }
86
            ],
90
            ],
87
            "bPaginate": false
91
            "bPaginate": false,
92
            'bAutoWidth': false
88
        } ) );
93
        } ) );
94
95
        [% IF close_form %]
96
          $("#budgeth").dataTable($.extend(true, {}, dataTablesDefaults, {
97
            sDom: "t"
98
          }));
99
          $("#move_form").submit(function(){
100
            var budget_from = "[% budget_period_description %]";
101
            var budget_to = $("#budget_period").find("option:selected").html();
102
            var alert_message = _("You have chosen to move all unreceived orders from '%s' to '%s'.").format(budget_from, budget_to);
103
            alert_message += _("\nThis action cannot be reversed. Do you wish to continue?");
104
            return confirm ( alert_message );
105
          });
106
        [% END %]
89
    });
107
    });
90
</script>
108
</script>
91
109
Lines 106-111 Link Here
106
    [% IF ( delete_confirmed ) %]&rsaquo;
124
    [% IF ( delete_confirmed ) %]&rsaquo;
107
        Data deleted
125
        Data deleted
108
    [% END %]
126
    [% END %]
127
    [% IF close_form %]&rsaquo;
128
      Close budget [% budget_period_description %]
129
    [% END %]
109
</title>
130
</title>
110
131
111
132
Lines 150-155 Link Here
150
    [% IF ( duplicate_form ) %]
171
    [% IF ( duplicate_form ) %]
151
        <a href="/cgi-bin/koha/admin/aqbudgetperiods.pl">Budgets</a> &rsaquo; Duplicate budget
172
        <a href="/cgi-bin/koha/admin/aqbudgetperiods.pl">Budgets</a> &rsaquo; Duplicate budget
152
    [% END %]
173
    [% END %]
174
175
    <!-- close a budget -->
176
    [% IF close_form %]
177
        <a href="/cgi-bin/koha/admin/aqbudgetperiods.pl">Budgets</a> &rsaquo;
178
        Close budget <a href="cgi-bin/koha/admin/aqbudgets.pl?budget_period_id=[% budget_period_id %]">[% budget_period_description %]</a>
179
    [% END %]
153
    <!-- display budget periods list -->
180
    <!-- display budget periods list -->
154
    <!-- ########################################## -->
181
    <!-- ########################################## -->
155
    [% IF ( else ) %]
182
    [% IF ( else ) %]
Lines 162-168 Link Here
162
<div id="yui-main">
189
<div id="yui-main">
163
<div class="yui-b">
190
<div class="yui-b">
164
191
165
[% INCLUDE 'budgets-admin-toolbar.inc' %]
192
[% UNLESS close_form %]
193
  [% INCLUDE 'budgets-admin-toolbar.inc' %]
194
[% END %]
166
195
167
[% IF ( duplicate_form ) %]
196
[% IF ( duplicate_form ) %]
168
<h3>Duplicate budget</h3>
197
<h3>Duplicate budget</h3>
Lines 309-314 Link Here
309
338
310
    </div>
339
    </div>
311
[% END %]
340
[% END %]
341
342
[% IF close_form %]
343
  [% IF budget_periods.size == 0 %]
344
    You cannot move funds of this budget, there is no active budget.
345
    Please create a new active budget and retry.
346
    <a href="/cgi-bin/koha/admin/aqbudgetperiods.pl">Back</a>
347
  [% ELSIF number_of_unreceived_orders == 0 %]
348
    There is no unreceived orders for this budget.
349
    <a href="/cgi-bin/koha/admin/aqbudgetperiods.pl">Back</a>
350
  [% ELSE %]
351
    <h3>Choose the funds you want to move unreceived orders:</h3>
352
      Fund list of budget <a href="cgi-bin/koha/admin/aqbudgets.pl?budget_period_id=[% budget_period_id %]">[% budget_period_description %]</a>:
353
    <table id="budgeth">
354
      <thead>
355
        <tr>
356
            <th>Fund id</th>
357
            <th>Fund code</th>
358
            <th>Fund name</th>
359
            <th>Unreceived orders</th>
360
        </tr>
361
      </thead>
362
      <tbody>
363
        [% FOREACH budget IN budgets_to_move %]
364
          <tr>
365
            <td>[% budget.budget_id %]</td>
366
            <td>[% budget.budget_code_indent %]</td>
367
            <td>[% budget.budget_name %]</td>
368
            <td>[% budget.unreceived_orders.size %]</td>
369
          </tr>
370
        [% END %]
371
      </tbody>
372
    </table>
373
    <form action="/cgi-bin/koha/admin/aqbudgetperiods.pl" name="f" method="post" id="move_form">
374
      <fieldset class="rows">
375
        <ol>
376
          <li>
377
            <label class="required" for="to_budget_period_id">Select a budget</label>
378
            <select name="to_budget_period_id" id="to_budget_period_id" required="required">
379
              <option value=""></option>
380
              [% FOR budget_period IN budget_periods %]
381
                <option value="[% budget_period.budget_period_id %]">[% budget_period.budget_period_description %]</option>
382
              [% END %]
383
            </select>
384
          </li>
385
        </ol>
386
      </fieldset>
387
      <fieldset class="action">
388
          <input type="hidden" name="op" value="close_confirmed" />
389
          <input type="hidden" name="budget_period_id" value="[% budget_period_id %]" />
390
          <input type="submit" value="Move unreceive orders" />
391
          <a class="cancel" href="/cgi-bin/koha/admin/aqbudgetperiods.pl">Cancel</a>
392
      </fieldset>
393
    </form>
394
  [% END %]
395
[% END %]
396
312
<!--  DEFAULT  display budget periods list -->
397
<!--  DEFAULT  display budget periods list -->
313
[% IF ( else ) %]
398
[% IF ( else ) %]
314
  <h2>Budgets administration</h2>
399
  <h2>Budgets administration</h2>
Lines 350-355 Link Here
350
                  <a href="[% script_name %]?op=add_form&amp;budget_period_id=[% period_active.budget_period_id |html %]">Edit</a>
435
                  <a href="[% script_name %]?op=add_form&amp;budget_period_id=[% period_active.budget_period_id |html %]">Edit</a>
351
                  <a href="[% script_name %]?op=delete_confirm&amp;budget_period_id=[% period_active.budget_period_id %]">Delete</a>
436
                  <a href="[% script_name %]?op=delete_confirm&amp;budget_period_id=[% period_active.budget_period_id %]">Delete</a>
352
                  <a href="[% script_name %]?op=duplicate_form&amp;budget_period_id=[% period_active.budget_period_id %]">Duplicate</a>
437
                  <a href="[% script_name %]?op=duplicate_form&amp;budget_period_id=[% period_active.budget_period_id %]">Duplicate</a>
438
                  <a href="[% script_name %]?op=close_form&amp;budget_period_id=[% period_active.budget_period_id %]">Close</a>
353
                  <a href="/cgi-bin/koha/admin/aqbudgets.pl?op=add_form&amp;budget_period_id=[% period_active.budget_period_id %]">Add fund</a>
439
                  <a href="/cgi-bin/koha/admin/aqbudgets.pl?op=add_form&amp;budget_period_id=[% period_active.budget_period_id %]">Add fund</a>
354
                </td>
440
                </td>
355
                </tr>
441
                </tr>
Lines 390-395 Link Here
390
                      <a href="[% script_name %]?op=add_form&amp;budget_period_id=[% period_loo.budget_period_id |html %]">Edit</a>
476
                      <a href="[% script_name %]?op=add_form&amp;budget_period_id=[% period_loo.budget_period_id |html %]">Edit</a>
391
                      <a href="[% script_name %]?op=delete_confirm&amp;budget_period_id=[% period_loo.budget_period_id %]">Delete</a>
477
                      <a href="[% script_name %]?op=delete_confirm&amp;budget_period_id=[% period_loo.budget_period_id %]">Delete</a>
392
                      <a href="[% script_name %]?op=duplicate_form&amp;budget_period_id=[% period_loo.budget_period_id %]">Duplicate</a>
478
                      <a href="[% script_name %]?op=duplicate_form&amp;budget_period_id=[% period_loo.budget_period_id %]">Duplicate</a>
479
                      <a href="[% script_name %]?op=close_form&amp;budget_period_id=[% period_loo.budget_period_id %]">Close</a>
393
                  <a href="/cgi-bin/koha/admin/aqbudgets.pl?op=add_form&amp;budget_period_id=[% period_loo.budget_period_id %]">Add fund</a>
480
                  <a href="/cgi-bin/koha/admin/aqbudgets.pl?op=add_form&amp;budget_period_id=[% period_loo.budget_period_id %]">Add fund</a>
394
                  </td>
481
                  </td>
395
                  </tr>
482
                  </tr>
(-)a/t/db_dependent/Budgets.t (-2 / +55 lines)
Lines 1-5 Link Here
1
use Modern::Perl;
1
use Modern::Perl;
2
use Test::More tests => 33;
2
use Test::More tests => 39;
3
3
4
BEGIN {use_ok('C4::Budgets') }
4
BEGIN {use_ok('C4::Budgets') }
5
use C4::Context;
5
use C4::Context;
Lines 16-21 $dbh->{RaiseError} = 1; Link Here
16
$dbh->do(q|DELETE FROM aqbudgetperiods|);
16
$dbh->do(q|DELETE FROM aqbudgetperiods|);
17
$dbh->do(q|DELETE FROM aqbudgets|);
17
$dbh->do(q|DELETE FROM aqbudgets|);
18
18
19
# Mock userenv
20
local $SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /redefined/ };
21
my $userenv;
22
*C4::Context::userenv = \&Mock_userenv;
23
$userenv = { flags => 1, id => 'my_userid', branch => 'CPL' };
24
19
#
25
#
20
# Budget Periods :
26
# Budget Periods :
21
#
27
#
Lines 263-268 my %budgets; Link Here
263
my $invoiceid = AddInvoice(invoicenumber => 'invoice_test_clone', booksellerid => $booksellerid, unknown => "unknown");
269
my $invoiceid = AddInvoice(invoicenumber => 'invoice_test_clone', booksellerid => $booksellerid, unknown => "unknown");
264
my $item_price = 10;
270
my $item_price = 10;
265
my $item_quantity = 2;
271
my $item_quantity = 2;
272
my $number_of_orders_to_move = 0;
266
for my $infos (@order_infos) {
273
for my $infos (@order_infos) {
267
    for ( 1 .. $infos->{pending_quantity} ) {
274
    for ( 1 .. $infos->{pending_quantity} ) {
268
        my ( undef, $ordernumber ) = C4::Acquisition::NewOrder(
275
        my ( undef, $ordernumber ) = C4::Acquisition::NewOrder(
Lines 284-289 for my $infos (@order_infos) { Link Here
284
            }
291
            }
285
        );
292
        );
286
        push @{ $budgets{$infos->{budget_id}} }, $ordernumber;
293
        push @{ $budgets{$infos->{budget_id}} }, $ordernumber;
294
        $number_of_orders_to_move++;
287
    }
295
    }
288
    for ( 1 .. $infos->{spent_quantity} ) {
296
    for ( 1 .. $infos->{spent_quantity} ) {
289
        my ( undef, $ordernumber ) = C4::Acquisition::NewOrder(
297
        my ( undef, $ordernumber ) = C4::Acquisition::NewOrder(
Lines 402-407 is( $number_of_budgets_not_reset, 0, Link Here
402
    'CloneBudgetPeriod has reset all budgets (funds)' );
410
    'CloneBudgetPeriod has reset all budgets (funds)' );
403
411
404
412
413
# MoveOrders
414
my $number_orders_moved = C4::Budgets::MoveOrders();
415
is( $number_orders_moved, undef, 'MoveOrders return undef if no arg passed' );
416
$number_orders_moved =
417
  C4::Budgets::MoveOrders( { from_budget_period_id => $budget_period_id } );
418
is( $number_orders_moved, undef,
419
    'MoveOrders return undef if only 1 arg passed' );
420
$number_orders_moved =
421
  C4::Budgets::MoveOrders( { to_budget_period_id => $budget_period_id } );
422
is( $number_orders_moved, undef,
423
    'MoveOrders return undef if only 1 arg passed' );
424
$number_orders_moved = C4::Budgets::MoveOrders(
425
    {
426
        from_budget_period_id => $budget_period_id,
427
        to_budget_period_id   => $budget_period_id
428
    }
429
);
430
is( $number_orders_moved, undef,
431
    'MoveOrders return undef if 2 budget period id are the same' );
432
433
$budget_period_id_cloned = C4::Budgets::CloneBudgetPeriod(
434
    {
435
        budget_period_id        => $budget_period_id,
436
        budget_period_startdate => '2014-01-01',
437
        budget_period_enddate   => '2014-12-31',
438
        reset_all_funds         => 1,
439
    }
440
);
441
442
my $report = C4::Budgets::MoveOrders(
443
    {
444
        from_budget_period_id => $budget_period_id,
445
        to_budget_period_id   => $budget_period_id_cloned,
446
    }
447
);
448
is( scalar( @$report ), 6 , "MoveOrders has processed 6 funds" );
449
450
my $number_of_orders_moved = 0;
451
$number_of_orders_moved += scalar( @{ $_->{orders_moved} } ) for @$report;
452
is( $number_of_orders_moved, $number_of_orders_to_move, "MoveOrders has moved $number_of_orders_to_move orders" );
453
405
sub _get_dependencies {
454
sub _get_dependencies {
406
    my ($budget_hierarchy) = @_;
455
    my ($budget_hierarchy) = @_;
407
    my $graph;
456
    my $graph;
Lines 426-428 sub _get_budgetname_by_id { Link Here
426
      @$budgets;
475
      @$budgets;
427
    return $budget_name;
476
    return $budget_name;
428
}
477
}
429
- 
478
479
# C4::Context->userenv
480
sub Mock_userenv {
481
    return $userenv;
482
}

Return to bug 12164