Bug 15184: Add the ability to duplicate existing order lines
authorJonathan Druart <jonathan.druart@bugs.koha-community.org>
Fri, 27 Jul 2018 18:48:31 +0000 (15:48 -0300)
committerNick Clemens <nick@bywatersolutions.com>
Thu, 8 Nov 2018 15:52:57 +0000 (15:52 +0000)
This patchset adds the ability to duplicate existing order lines to a
given basket. It will help acquisitions of serials of when the same
publication is ordered frequently.

The workflow will be:
- Create a new basket
- Use the "Add to basket" button
- Select the new entry "From existing orders (copy)"
- Search and select the order you want to duplicate
- Define some default values for these orders
- Duplicate!

Sponsored-by: BULAC - http://www.bulac.fr/

Signed-off-by: Josef Moravec <josef.moravec@gmail.com>

Signed-off-by: Séverine QUEUNE <severine.queune@bulac.fr>

Signed-off-by: Katrin Fischer <katrin.fischer.83@web.de>

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>

Koha/Acquisition/Order.pm
acqui/duplicate_orders.pl [new file with mode: 0644]
koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-add-to-basket.inc
koha-tmpl/intranet-tmpl/prog/en/includes/blocking_errors.inc
koha-tmpl/intranet-tmpl/prog/en/includes/filter-orders.inc
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/duplicate_orders.tt [new file with mode: 0644]

index 5620cf6..0619fc1 100644 (file)
@@ -22,9 +22,10 @@ use Carp qw( croak );
 use Koha::Acquisition::Baskets;
 use Koha::Acquisition::Funds;
 use Koha::Acquisition::Invoices;
-use Koha::Subscriptions;
 use Koha::Database;
 use Koha::DateUtils qw( dt_from_string output_pref );
+use Koha::Items;
+use Koha::Subscriptions;
 
 use base qw(Koha::Object);
 
@@ -167,6 +168,65 @@ sub subscription {
     return Koha::Subscription->_new_from_dbic( $subscription_rs );
 }
 
+sub items {
+    my ( $self )  = @_;
+    # aqorders_items is not a join table
+    # There is no FK on items (may have been deleted)
+    my $items_rs = $self->_result->aqorders_items;
+    my @itemnumbers = $items_rs->get_column( 'itemnumber' )->all;
+    return Koha::Items->search({ itemnumber => \@itemnumbers });
+}
+
+sub duplicate_to {
+    my ( $self, $basket, $default_values ) = @_;
+    my $new_order;
+    $default_values //= {};
+    Koha::Database->schema->txn_do(
+        sub {
+            my $order_info = $self->unblessed;
+            undef $order_info->{ordernumber};
+            for my $field (
+                qw(
+                ordernumber
+                received_on
+                datereceived
+                datecancellationprinted
+                cancellationreason
+                purchaseordernumber
+                claims_count
+                claimed_date
+                parent_ordernumber
+                )
+              )
+            {
+                undef $order_info->{$field};
+            }
+            $order_info->{placed_on}        = dt_from_string;
+            $order_info->{entrydate}        = dt_from_string;
+            $order_info->{orderstatus}      = 'new';
+            $order_info->{quantityreceived} = 0;
+            while ( my ( $field, $value ) = each %$default_values ) {
+                $order_info->{$field} = $value;
+            }
+
+            # FIXME $order_info->{created_by} = logged_in_user?
+            $order_info->{basketno} = $basket->basketno;
+
+            $new_order = Koha::Acquisition::Order->new($order_info)->store;
+            my $items = $self->items;
+            while ( my ($item) = $items->next ) {
+                my $item_info = $item->unblessed;
+                undef $item_info->{itemnumber};
+                undef $item_info->{barcode};
+                my $new_item = Koha::Item->new($item_info)->store;
+                $new_order->add_item( $new_item->itemnumber );
+            }
+        }
+    );
+    return $new_order;
+}
+
+
 =head2 Internal methods
 
 =head3 _type
diff --git a/acqui/duplicate_orders.pl b/acqui/duplicate_orders.pl
new file mode 100644 (file)
index 0000000..549c8b4
--- /dev/null
@@ -0,0 +1,177 @@
+#!/usr/bin/perl
+
+# Copyright 2018 Koha Development Team
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# Koha is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
+
+use Modern::Perl;
+
+use CGI qw ( -utf8 );
+
+use C4::Auth;
+use C4::Output;
+use C4::Acquisition qw(GetHistory);
+use C4::Budgets qw(GetBudgetPeriods GetBudgetHierarchy CanUserUseBudget);
+use Koha::Acquisition::Baskets;
+use Koha::Acquisition::Currencies;
+use Koha::Acquisition::Orders;
+use Koha::DateUtils qw(dt_from_string output_pref);
+
+my $input    = new CGI;
+my $basketno = $input->param('basketno');
+my $op       = $input->param('op') || 'search';    # search, select, batch_edit
+
+my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user(
+    {
+        template_name   => "acqui/duplicate_orders.tt",
+        query           => $input,
+        type            => "intranet",
+        authnotrequired => 0,
+        flagsrequired   => { acquisition => 'order_manage' },
+    }
+);
+
+my $basket = Koha::Acquisition::Baskets->find($basketno);
+
+output_and_exit( $input, $cookie, $template, 'unknown_basket' )
+  unless $basket;
+
+my $vendor = $basket->bookseller;
+my $patron = Koha::Patrons->find($loggedinuser)->unblessed;
+
+my $filters = {
+    basket                  => scalar $input->param('basket'),
+    title                   => scalar $input->param('title'),
+    author                  => scalar $input->param('author'),
+    isbn                    => scalar $input->param('isbn'),
+    name                    => scalar $input->param('name'),
+    ean                     => scalar $input->param('ean'),
+    basketgroupname         => scalar $input->param('basketgroupname'),
+    booksellerinvoicenumber => scalar $input->param('booksellerinvoicenumber'),
+    budget                  => scalar $input->param('budget'),
+    orderstatus             => scalar $input->param('orderstatus'),
+    ordernumber             => scalar $input->param('ordernumber'),
+    search_children_too     => scalar $input->param('search_children_too'),
+    created_by              => scalar $input->multi_param('created_by'),
+};
+my $from_placed_on =
+  eval { dt_from_string( scalar $input->param('from') ) } || dt_from_string;
+my $to_placed_on =
+  eval { dt_from_string( scalar $input->param('to') )   } || dt_from_string;
+
+unless ( $input->param('from') ) {
+    # Fill the form with year-1
+    $from_placed_on->subtract( years => 1 );
+}
+$filters->{from_placed_on} =
+  output_pref( { dt => $from_placed_on, dateformat => 'iso', dateonly => 1 } ),
+  $filters->{to_placed_on} =
+  output_pref( { dt => $to_placed_on, dateformat => 'iso', dateonly => 1 } ),
+
+  my ( @result_order_loop, @selected_order_loop );
+my @ordernumbers = split ',', scalar $input->param('ordernumbers') || '';
+if ( $op eq 'select' ) {
+    @result_order_loop = map {
+        my $order = $_;
+        ( grep { /^$order->{ordernumber}$/ } @ordernumbers ) ? () : $order
+    } @{ C4::Acquisition::GetHistory(%$filters) };
+
+    @selected_order_loop =
+      scalar @ordernumbers
+      ? @{ C4::Acquisition::GetHistory( ordernumbers => \@ordernumbers ) }
+      : ();
+}
+elsif ( $op eq 'batch_edit' ) {
+    @ordernumbers = $input->multi_param('ordernumber');
+
+    # build budget list
+    my $budget_loop       = [];
+    my $budgets_hierarchy = GetBudgetHierarchy;
+    foreach my $r ( @{$budgets_hierarchy} ) {
+        next
+          unless ( C4::Budgets::CanUserUseBudget( $patron, $r, $userflags ) );
+        if ( !defined $r->{budget_amount} || $r->{budget_amount} == 0 ) {
+            next;
+        }
+        push @{$budget_loop},
+          {
+            b_id            => $r->{budget_id},
+            b_txt           => $r->{budget_name},
+            b_code          => $r->{budget_code},
+            b_sort1_authcat => $r->{'sort1_authcat'},
+            b_sort2_authcat => $r->{'sort2_authcat'},
+            b_active        => $r->{budget_period_active},
+          };
+    }
+    @{$budget_loop} =
+      sort { uc( $a->{b_txt} ) cmp uc( $b->{b_txt} ) } @{$budget_loop};
+
+    my @currencies = Koha::Acquisition::Currencies->search;
+    $template->param(
+        currencies  => \@currencies,
+        budget_loop => $budget_loop,
+    );
+}
+elsif ( $op eq 'do_duplicate' ) {
+    my @fields_to_copy = $input->multi_param('copy_existing_value');
+
+    my $default_values;
+    for my $field (
+        qw(currency budget_id order_internalnote order_vendornote sort1 sort2 ))
+    {
+        next if grep { /^$field$/ } @fields_to_copy;
+        $default_values->{$field} = $input->param("all_$field");
+    }
+
+    @ordernumbers = $input->multi_param('ordernumber');
+    my @new_ordernumbers;
+    for my $ordernumber (@ordernumbers) {
+        my $original_order = Koha::Acquisition::Orders->find($ordernumber);
+        next unless $original_order;
+        my $new_order =
+          $original_order->duplicate_to( $basket, $default_values );
+        push @new_ordernumbers, $new_order->ordernumber;
+    }
+
+    my $new_orders =
+      C4::Acquisition::GetHistory( ordernumbers => \@new_ordernumbers );
+    $template->param( new_orders => $new_orders );
+    $op = 'duplication_done';
+}
+
+my $budgetperiods = C4::Budgets::GetBudgetPeriods;
+my $bp_loop       = $budgetperiods;
+for my $bp ( @{$budgetperiods} ) {
+    my $hierarchy = C4::Budgets::GetBudgetHierarchy( $$bp{budget_period_id} );
+    for my $budget ( @{$hierarchy} ) {
+        $$budget{budget_display_name} =
+          sprintf( "%s", ">" x $$budget{depth} . $$budget{budget_name} );
+    }
+    $$bp{hierarchy} = $hierarchy;
+}
+
+$template->param(
+    basket              => $basket,
+    vendor              => $vendor,
+    filters             => $filters,
+    result_order_loop   => \@result_order_loop,
+    selected_order_loop => \@selected_order_loop,
+    bp_loop             => $bp_loop,
+    ordernumbers        => \@ordernumbers,
+    op                  => $op,
+);
+
+output_html_with_http_headers $input, $cookie, $template->output;
index 1e29433..6e5698f 100644 (file)
@@ -15,6 +15,7 @@
         <li><a href="/cgi-bin/koha/acqui/newordersuggestion.pl?booksellerid=[% booksellerid | uri %]&amp;basketno=[% basketno | uri %]">From a suggestion</a></li>
         <li><a href="/cgi-bin/koha/acqui/newordersubscription.pl?booksellerid=[% booksellerid | uri %]&amp;basketno=[% basketno | uri %]">From a subscription</a></li>
         <li><a href="/cgi-bin/koha/acqui/neworderempty.pl?booksellerid=[% booksellerid | uri %]&amp;basketno=[% basketno | uri %]">From a new (empty) record</a></li>
+        <li><a href="/cgi-bin/koha/acqui/duplicate_orders.pl?basketno=[% basketno | uri %]">From existing orders (copy)</a></li>
         <li><a href="/cgi-bin/koha/acqui/z3950_search.pl?booksellerid=[% booksellerid | uri %]&amp;basketno=[% basketno | uri %]">From an external source</a></li>
         <li><a href="/cgi-bin/koha/tools/stage-marc-import.pl?basketno=[% basketno | uri %]&amp;booksellerid=[% booksellerid | uri %]"> From a new file</a></li>
         <li><a href="/cgi-bin/koha/acqui/addorderiso2709.pl?booksellerid=[% booksellerid | uri %]&amp;basketno=[% basketno | uri %]"> From a staged file</a></li>
index e803427..2666400 100644 (file)
@@ -9,6 +9,8 @@
         <div class="dialog message">This item does not exist.</div>
     [% CASE 'unknown_subscription' %]
         <div class="dialog message">This subscription does not exist.</div>
+    [% CASE 'unknown_basket' %]
+        <div class="dialog message">This basket does not exist.</div>
     [% CASE %][% blocking_error | html %]
     [% END %]
 
index 806551c..84c1bed 100644 (file)
@@ -1,4 +1,5 @@
 [% USE Koha %]
+[% USE KohaDates %]
 <ol>
     <li><label for="title">Title: </label> <input type="text" name="title" id="title" value="[% filters.title | html %]" /></li>
     <li><label for="author">Author: </label> <input type="text" name="author" id="author" value="[% filters.author | html %]" /></li>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/duplicate_orders.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/duplicate_orders.tt
new file mode 100644 (file)
index 0000000..e90933d
--- /dev/null
@@ -0,0 +1,428 @@
+[% USE Asset %]
+[% USE Koha %]
+[% USE KohaDates %]
+[% SET footerjs = 1 %]
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Acquisitions &rsaquo;
+[% UNLESS blocking_error %]
+Basket [% basket.basketno %] &rsaquo; Duplicate existing orders
+[% END %]
+</title>
+[% INCLUDE 'doc-head-close.inc' %]
+[% Asset.css("css/datatables.css") %]
+<style type="text/css">
+    .picked_to_duplicate > td { background-color: #bcdb89 !important; }
+</style>
+</head>
+
+<body id="acq_duplicate_orders" class="acq">
+
+[% INCLUDE 'header.inc' %]
+[% INCLUDE 'acquisitions-search.inc' %]
+
+<div id="breadcrumbs">
+    <a href="/cgi-bin/koha/mainpage.pl">Home</a>
+    &rsaquo; <a href="/cgi-bin/koha/acqui/acqui-home.pl">Acquisitions</a>
+    [% UNLESS blocking_error %]
+    &rsaquo; <a href="/cgi-bin/koha/acqui/supplier.pl?booksellerid=[% vendor.id %]">[% vendor.name %]</a>
+    &rsaquo; <a href="/cgi-bin/koha/acqui/basket.pl?basketno=[% basket.basketno %]">Basket [% basket.basketno %]</a>
+    &rsaquo; Duplicate existing orders
+    [% END %]
+</div>
+
+<div class="main container-fluid">
+    <div class="row">
+        <div class="col-sm-10 col-sm-push-2">
+            <main>
+
+[% INCLUDE 'blocking_errors.inc' %]
+
+<h2>Duplicate existing orders</h2>
+
+[% IF op == 'search' || op == 'select' %]
+<form action="/cgi-bin/koha/acqui/duplicate_orders.pl" method="post">
+    <fieldset class="rows">
+        <legend>
+            [% IF op == 'search' %]
+                <span>Search orders</span>
+            [% ELSE %]
+                <span>Refine search</span>
+            [% END %]
+            <span class="toggle_orders_filters" id="show_orders_filters"><a href="#">[+]</a></span>
+            <span class="toggle_orders_filters" id="hide_orders_filters"><a href="#">[-]</a></span>
+        </legend>
+        <div id="orders_filters">
+            [% INCLUDE 'filter-orders.inc' %]
+            <input type="hidden" name="op" value="select" />
+            <input type="hidden" name="basketno" value="[% basket.basketno %]" />
+
+            <input type="hidden" name="ordernumbers" value="[% ordernumbers.join(',') %]" />
+            <fieldset class="action"><input type="submit" value="Search" /></fieldset>
+        </div>
+    </fieldset>
+</form>
+[% END %]
+
+[% BLOCK display_order_line %]
+    [% IF selected %]
+    <tr class="picked_to_duplicate" data-ordernumber="[% order.ordernumber %]">
+    [% ELSE %]
+    <tr data-ordernumber="[% order.ordernumber %]">
+    [% END %]
+        <td>
+            [% IF selected %]
+                <input type="checkbox" name="ordernumber" value="[% order.ordernumber %]" checked="checked" />
+            [% ELSE %]
+                <input type="checkbox" name="ordernumber" value="[% order.ordernumber %]" />
+            [% END %]
+            [% order.ordernumber %]
+            [% IF order.ordernumber != order.parent_ordernumber %]([% order.parent_ordernumber %])[% END %]
+        </td>
+        <td>
+            [% SWITCH order.orderstatus %]
+                [% CASE 'new' %]New
+                [% CASE 'ordered' %]Ordered
+                [% CASE 'partial' %]Partially received
+                [% CASE 'complete' %]Received
+                [% CASE 'cancelled' %]Cancelled
+            [% END %]
+        </td>
+        <td>[% order.basketname %] (<a href="basket.pl?basketno=[% order.basketno %]">[% order.basketno %]</a>)</td>
+        <td>[% order.authorisedbyname %]</td>
+        <td>
+            [% IF ( order.basketgroupid ) %]
+                [% order.groupname %] (<a href="basketgroup.pl?op=add&booksellerid=[% order.id %]&basketgroupid=[% order.basketgroupid %]">[% order.basketgroupid %]</a>)
+            [% ELSE %]
+                &nbsp;
+            [% END %]
+        </td>
+        <td>[% IF ( order.invoicenumber ) %]
+                <a href="/cgi-bin/koha/acqui/parcel.pl?invoiceid=[% order.invoiceid %]">[% order.invoicenumber %]</a>
+            [% ELSE %]
+                &nbsp;
+            [% END %]
+        </td>
+        <td>
+            <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% order.biblionumber %]">[% order.title |html %]</a>
+            <br />[% order.author %] <br /> [% order.isbn %]
+        </td>
+        <td><a href="/cgi-bin/koha/acqui/supplier.pl?booksellerid=[% order.id %]">[% order.name %]</a></td>
+        <td><span title="[% order.creationdate %]">[% order.creationdate | $KohaDates %]</span></td>
+        <td>
+            [% IF order.datereceived %]
+                <span title="[% order.datereceived %]">[% order.datereceived | $KohaDates %]</span>
+            [% ELSE %]
+                <span title="0000-00-00"></span>
+            [% END %]
+        </td>
+        <td>[% order.quantityreceived %]</td>
+        <td>[% order.quantity %]</td>
+        <td>[% order.ecost %]</td>
+        <td>[% order.budget_name %]</td>
+    </tr>
+[% END %]
+
+
+[% IF op == 'select' && ( result_order_loop || selected_order_loop ) %]
+    <div id="xxx">
+        <form method="post" action="/cgi-bin/koha/acqui/duplicate_orders.pl">
+        <table id="table_orders">
+            <caption>
+                <span class="actions"><a href="#" id="select_all"><i class="fa fa-check"></i> Select all</a>
+                | <a href="#" id="clear_all"><i class="fa fa-remove"></i> Clear all</a></span>
+            </caption>
+
+            <thead>
+                    <tr>
+                    <th>Order line (parent)</th>
+                    <th>Status</th>
+                    <th>Basket</th>
+                    <th>Basket creator</th>
+                    <th>Basket group</th>
+                    <th>Invoice number</th>
+                    <th class="anti-the">Summary</th>
+                    <th>Vendor</th>
+                    <th class="title-string">Placed on</th>
+                    <th class="title-string">Received on</th>
+                    <th>Quantity received</th>
+                    <th>Pending order</th>
+                    <th>Unit cost</th>
+                    <th>Fund</th>
+                </tr>
+            </thead>
+            <tfoot>
+            [% FOREACH order IN selected_order_loop %]
+                [% INCLUDE display_order_line selected => 1 %]
+            [% END %]
+            </tfoot>
+            <tbody>
+            [% FOREACH order IN result_order_loop %]
+                [% INCLUDE display_order_line %]
+            [% END %]
+            </tbody>
+        </table>
+        <fieldset class="action">
+            <input type="hidden" name="op" value="batch_edit" />
+            <input type="hidden" name="basketno" value="[% basket.basketno %]" />
+            <button type="submit" class="btn btn-default go_to_batch_edit">Next <i class="fa fa-fw fa-arrow-right"></i></button>
+        </fieldset>
+        </form>
+    </div>
+
+[% ELSIF op == "batch_edit" %]
+
+<form method="post" action="/cgi-bin/koha/acqui/duplicate_orders.pl" id="batch_edit_form">
+    <div id="accounting_details">
+      <p>Duplicate all the orders with the following accounting details:</p>
+      <fieldset class="rows" style="float:none;">
+          <legend>Accounting details</legend>
+          <ol>
+              <li>
+                  <!-- origquantityrec only here for javascript compatibility (additem.js needs it, useless here, useful when receiveing an order -->
+                  <input id="origquantityrec" readonly="readonly" type="hidden" name="origquantityrec" value="1" />
+              </li>
+              <li>
+                      <li>
+                          <label for="all_currency">Currency:</label>
+                          <input type="checkbox" name="copy_existing_value" value="currency" title="Copy existing value" />
+                          <select name="all_currency" id="all_currency">
+                          [% FOREACH currency IN currencies %]
+                              [% IF currency.currency == vendor.listprice %]
+                                  <option value="[% currency.currency %]" selected="selected">[% currency.currency %]</option>
+                              [% ELSIF not currency.archived %]
+                                  <option value="[% currency.currency %]">[% currency.currency %]</option>
+                              [% END %]
+                          [% END %]
+                          </select>
+                          <span class="hint" id="hint_currency">The original currency value will be copied</span>
+                      </li>
+                      <li>
+                          <label for="all_budget_id">Fund: </label>
+                          <input type="checkbox" name="copy_existing_value" value="budget_id" title="Copy existing value" />
+                          <select id="all_budget_id" size="1" name="all_budget_id">
+                            <option value="">Select a fund</option>
+                          [% FOREACH budget_loo IN budget_loop %]
+                              [% IF ( budget_loo.b_active ) %]<option value="[% budget_loo.b_id %]" data-sort1-authcat="[% budget_loo.b_sort1_authcat %]" data-sort2-authcat="[% budget_loo.b_sort2_authcat %]">[% budget_loo.b_txt %]</option>
+                              [% ELSE %]<option value="[% budget_loo.b_id %]" class="b_inactive" data-sort1-authcat="[% budget_loo.b_sort1_authcat %]" data-sort2-authcat="[% budget_loo.b_sort2_authcat %]">[% budget_loo.b_txt %] (inactive)</option>
+                              [% END %]
+                          [% END %]
+                          </select>
+                          <label for="all_showallbudgets" style="float:none;width:auto;">&nbsp;Show inactive:</label>
+                          <input type="checkbox" id="all_showallbudgets" />
+                          <span class="hint" id="hint_budget_id">The original fund will be used</span>
+                      </li>
+              </li>
+              <li>
+                  <label for="all_order_internalnote">Internal note: </label>
+                  <input type="checkbox" name="copy_existing_value" value="order_internalnote" title="Copy existing value" />
+                  <textarea id="all_order_internalnote" cols="30" rows="3" name="all_order_internalnote"></textarea>
+                  <span class="hint" id="hint_order_internalnote">The original internal note will be used</span>
+              </li>
+              <li>
+                  <label for="all_order_vendornote">Vendor note: </label>
+                  <input type="checkbox" name="copy_existing_value" value="order_vendornote" title="Copy existing value" />
+                  <textarea id="all_order_vendornote" cols="30" rows="3" name="all_order_vendornote"></textarea>
+                  <span class="hint" id="hint_order_vendornote">The original vendor note will be used</span>
+              </li>
+              <li>
+                  <div class="hint">The 2 following fields are available for your own usage. They can be useful for statistical purposes</div>
+                  <label for="all_sort1">Statistic 1: </label>
+                  <input type="checkbox" name="copy_existing_value" value="sort1" title="Copy existing value" />
+                  <input type="text" id="all_sort1" size="20" name="all_sort1" value="" />
+                  <span class="hint" id="hint_sort1">The original statistic 1 will be used</span>
+
+              </li>
+              <li>
+                  <label for="all_sort2">Statistic 2: </label>
+                  <input type="checkbox" name="copy_existing_value" value="sort2" title="Copy existing value" />
+                  <input type="text" id="all_sort2" size="20" name="all_sort2" value="" />
+                  <span class="hint" id="hint_sort2">The original statistic 2 will be used</span>
+              </li>
+          </ol>
+      </fieldset>
+    </div>
+
+    <fieldset class="action">
+        [% FOREACH ordernumber IN ordernumbers %]
+            <input type="hidden" name="ordernumber" value="[% ordernumber %]" />
+        [% END %]
+        <input type="hidden" name="op" value="do_duplicate" />
+        <input type="hidden" name="basketno" value="[% basket.basketno %]" />
+        <button type="submit" class="btn btn-default">Duplicate orders</button>
+        <a class="cancel" href="/cgi-bin/koha/acqui/duplicate_orders.pl?basketno=[% basket.basketno %]">Cancel</a>
+    </fieldset>
+</form>
+
+[% ELSIF op == 'duplication_done' %]
+    [% IF new_orders %]
+        <table id="table_neworders">
+            <thead>
+                <tr>
+                    <th>Order line</th>
+                    <th>Status</th>
+                    <th>Basket</th>
+                    <th>Basket creator</th>
+                    <th>Basket group</th>
+                    <th>Invoice number</th>
+                    <th class="anti-the">Summary</th>
+                    <th>Vendor</th>
+                    <th class="title-string">Placed on</th>
+                    <th class="title-string">Received on</th>
+                    <th>Quantity received</th>
+                    <th>Pending order</th>
+                    <th>Unit cost</th>
+                    <th>Fund</th>
+                </tr>
+            </thead>
+            <tbody>
+            [% FOREACH order IN new_orders %]
+                [% INCLUDE display_order_line %]
+            [% END %]
+            </tbody>
+        </table>
+        <a class="btn btn-default" href="/cgi-bin/koha/acqui/basket.pl?basketno=[% basket.basketno %]"><i class="fa fa-fw fa-arrow-left"></i> Return to the basket</a
+    [% ELSE %]
+        <span>No order has been duplicated. Maybe something wrong happened?</span>
+    [% END %]
+[% END %]
+
+</main>
+</div> <!-- /.col-sm-10.col-sm-push-2 -->
+
+<div class="col-sm-2 col-sm-pull-10">
+    <aside>
+        [% INCLUDE 'acquisitions-menu.inc' %]
+    </aside>
+</div> <!-- /.col-sm-2.col-sm-pull-10 -->
+</div>
+
+[% MACRO jsinclude BLOCK %]
+    [% Asset.js("js/acquisitions-menu.js") %]
+    [% INCLUDE 'calendar.inc' %]
+    [% INCLUDE 'datatables.inc' %]
+    [% INCLUDE 'columns_settings.inc' %]
+    [% Asset.js("js/autocomplete/patrons.js") %]
+    [% Asset.js("js/acq.js") %]
+    [% Asset.js("js/funds_sorts.js") %]
+    [% Asset.js("lib/jquery/plugins/jquery.checkboxes.min.js") %]
+    <script>
+        function update_ordernumber_list(){
+            var ordernumbers = [];
+            $("input[name='ordernumber']").filter(":checked").each(function(){
+                ordernumbers.push($(this).val());
+            });
+            $("input[name='ordernumbers']").val(ordernumbers.join(','));
+        }
+
+        var MSG_REMOVE_PATRON = _("Remove");
+        var MSG_NO_ITEM_SELECTED = _("Nothing is selected.");
+        var MSG_NO_FUND_SELECTED = _("No fund selected.");
+        $(document).ready(function() {
+            $('.hint').hide();
+            var columns_settings;// = [% ColumnsSettings.GetColumns( 'acqui', 'histsearch', 'histsearcht', 'json' ) %];
+            KohaTable("table_orders", {
+                "aoColumnDefs": [
+                    { "sType": "anti-the", "aTargets" : [ "anti-the" ] },
+                    { "sType": "title-string", "aTargets" : [ "title-string" ] }
+                ],
+                "bPaginate": false
+            }, columns_settings );
+
+            [% IF op == 'search' OR op == 'select' %]
+                patron_autocomplete({
+                    patron_container: $("#basket_creators"),
+                    input_autocomplete: $("#find_patron"),
+                    patron_input_name: 'created_by',
+                    field_to_retrieve: 'borrowernumber'
+                });
+            [% END %]
+
+            $("#show_orders_filters, #hide_orders_filters").on('click', function(e) {
+                e.preventDefault();
+                $('#orders_filters').toggle();
+                $('.toggle_orders_filters').toggle();
+            });
+            [% IF op == 'search' OR op == 'select' AND NOT result_order_loop %]
+                $("#show_orders_filters").hide();
+                $("#orders_filters").show();
+            [% ELSE %]
+                $("#hide_orders_filters").hide();
+                $("#orders_filters").hide();
+            [% END %]
+
+            $("input[name='ordernumber']").on("change", function(){
+                if ( $(this).is(':checked') ) {
+                    $(this).parents("tr").addClass("picked_to_duplicate");
+                } else {
+                    $(this).parents("tr").removeClass("picked_to_duplicate");
+                }
+            }).on("click", function(e){
+                update_ordernumber_list();
+            });
+
+            $("#select_all").on("click",function(e){
+                e.preventDefault();
+                selectAll();
+                update_ordernumber_list();
+            });
+
+            $("#clear_all").on("click",function(e){
+                e.preventDefault();
+                clearAll();
+                update_ordernumber_list();
+            });
+            function selectAll () {
+                $("#table_orders").checkCheckboxes();
+                $("#table_orders").find("input[type='checkbox'][name='ordernumber']").each(function(){
+                    $(this).change();
+                } );
+                return false;
+            }
+            function clearAll () {
+                $("#table_orders").unCheckCheckboxes();
+                $("#table_orders").find("input[type='checkbox'][name='ordernumber']").each(function(){
+                    $(this).change();
+                } );
+                return false;
+            }
+
+            $(".go_to_batch_edit").on("click",function(e){
+                if ($("input[name='ordernumber']").filter(":checked").length == 0){
+                    alert(MSG_NO_ITEM_SELECTED);
+                    e.preventDefault();
+                }
+            });
+
+            $("#batch_edit_form").on("submit", function(e){
+                var budget_value_will_be_reused = $("input[name='copy_existing_value'][value='budget_id']").is(':checked');
+                if ( ! budget_value_will_be_reused ) {
+                    if ($("#all_budget_id").find("option:selected").attr("value") == "" ) {
+                        alert(MSG_NO_FUND_SELECTED);
+                        e.preventDefault();
+                    }
+                }
+            });
+            $("input[name='copy_existing_value']").click(function(){
+                render_disabled(this);
+            });
+
+            $("input[name='copy_existing_value']").each(function(){
+                render_disabled(this);
+            });
+        });
+        function render_disabled (elt) {
+            var field = $(elt).val();
+            var hint_node = $("#hint_" + field);
+            var input_element = $(elt).parent().find("[name='all_"+field+"']");
+            if ($(elt).is(":checked")) {
+                $(input_element).prop('disabled', true);
+                $(hint_node).show();
+            } else {
+                $(input_element).prop('disabled', false);
+                $(hint_node).hide();
+            }
+        }
+    </script>
+[% END %]
+
+[% INCLUDE 'intranet-bottom.inc' %]