Bug 5349: add ability to transfer order lines from one basket to another
authorJulian Maurice <julian.maurice@biblibre.com>
Fri, 6 Apr 2012 14:57:12 +0000 (16:57 +0200)
committerGalen Charlton <gmc@esilibrary.com>
Sun, 8 Sep 2013 22:38:19 +0000 (22:38 +0000)
On basket.pl and parcel.pl there is a 'Transfer' link which allow you to
transfer order lines from a basket to another.

The link leads to a new page which allow you to search for a bookseller,
then display this bookseller's baskets. Then you can pick a basket and
the transfer will be done.

Signed-off-by: Marc Veron <veron@veron.ch>
Signed-off-by: Mathieu Saby <mathieu.saby@univ-rennes2.fr>
Signed-off-by: sonia <koha@univ-lyon3.fr>
Signed-off-by: Chris Cormack <chris@bigballofwax.co.nz>
Signed-off-by: Galen Charlton <gmc@esilibrary.com>
C4/Acquisition.pm
acqui/transferorder.pl [new file with mode: 0755]
installer/data/mysql/kohastructure.sql
installer/data/mysql/updatedatabase.pl
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/basket.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcel.tt
koha-tmpl/intranet-tmpl/prog/en/modules/acqui/transferorder.tt [new file with mode: 0644]

index 74aae85..d17c7cf 100644 (file)
@@ -57,7 +57,7 @@ BEGIN {
         &GetLateOrders &GetOrderFromItemnumber
         &SearchOrder &GetHistory &GetRecentAcqui
         &ModReceiveOrder &CancelReceipt
-        &GetCancelledOrders
+        &GetCancelledOrders &TransferOrder
         &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid
         &NewOrderItem &ModItemOrder
 
@@ -1596,6 +1596,77 @@ sub DelOrder {
     
 }
 
+=head3 TransferOrder
+
+    my $newordernumber = TransferOrder($ordernumber, $basketno);
+
+Transfer an order line to a basket.
+Mark $ordernumber as cancelled with an internal note 'Cancelled and transfered
+to BOOKSELLER on DATE' and create new order with internal note
+'Transfered from BOOKSELLER on DATE'.
+Move all attached items to the new order.
+Received orders cannot be transfered.
+Return the ordernumber of created order.
+
+=cut
+
+sub TransferOrder {
+    my ($ordernumber, $basketno) = @_;
+
+    return unless $ordernumber or $basketno;
+
+    my $order = GetOrder( $ordernumber );
+    return if $order->{datereceived};
+
+    my $today = C4::Dates->new()->output("iso");
+    my $query = qq{
+        SELECT aqbooksellers.name
+        FROM aqorders
+            LEFT JOIN aqbasket ON aqorders.basketno = aqbasket.basketno
+            LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
+        WHERE aqorders.ordernumber = ?
+    };
+    my $dbh = C4::Context->dbh;
+    my $sth = $dbh->prepare($query);
+    $sth->execute($ordernumber);
+    my ($booksellerfromname) = $sth->fetchrow_array;
+
+    $query = qq{
+        SELECT aqbooksellers.name
+        FROM aqbasket
+            LEFT JOIN aqbooksellers ON aqbasket.booksellerid = aqbooksellers.id
+        WHERE aqbasket.basketno = ?
+    };
+    $sth = $dbh->prepare($query);
+    $sth->execute($basketno);
+    my ($booksellertoname) = $sth->fetchrow_array;
+
+    $query = qq{
+        UPDATE aqorders
+        SET datecancellationprinted = CAST(NOW() AS date),
+            internalnotes = ?
+        WHERE ordernumber = ?
+    };
+    $sth = $dbh->prepare($query);
+    $sth->execute("Cancelled and transfered to $booksellertoname on $today", $ordernumber);
+
+    delete $order->{'ordernumber'};
+    $order->{'basketno'} = $basketno;
+    $order->{'internalnotes'} = "Transfered from $booksellerfromname on $today";
+    my $newordernumber;
+    (undef, $newordernumber) = NewOrder($order);
+
+    $query = qq{
+        UPDATE aqorders_items
+        SET ordernumber = ?
+        WHERE ordernumber = ?
+    };
+    $sth = $dbh->prepare($query);
+    $sth->execute($newordernumber, $ordernumber);
+
+    return $newordernumber;
+}
+
 =head2 FUNCTIONS ABOUT PARCELS
 
 =cut
diff --git a/acqui/transferorder.pl b/acqui/transferorder.pl
new file mode 100755 (executable)
index 0000000..27c4509
--- /dev/null
@@ -0,0 +1,145 @@
+#!/usr/bin/perl
+
+# Script to move an order from a bookseller to another
+
+# Copyright 2011 BibLibre SARL
+#
+# 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 2 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, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+use Modern::Perl;
+use CGI;
+
+use C4::Auth;
+use C4::Output;
+use C4::Context;
+use C4::Acquisition;
+use C4::Bookseller qw/GetBookSellerFromId GetBookSeller/;
+use C4::Members;
+use C4::Dates qw/format_date_in_iso/;
+use Date::Calc qw/Today/;
+
+my $input = new CGI;
+my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
+    {   template_name   => "acqui/transferorder.tmpl",
+        query           => $input,
+        type            => "intranet",
+        authnotrequired => 1,
+        flagsrequired   => { acquisition => 'order_manage' },
+        debug           => 1,
+    }
+);
+
+my $dbh = C4::Context->dbh;
+
+my $bookselleridfrom    = $input->param('bookselleridfrom');
+my $ordernumber     = $input->param('ordernumber');
+my $bookselleridto  = $input->param('bookselleridto');
+my $basketno        = $input->param('basketno');
+my $op              = $input->param('op');
+my $query           = $input->param('query');
+
+my $order = GetOrder($ordernumber);
+if($order) {
+    my $basket = GetBasket($order->{basketno});
+    $bookselleridfrom = $basket->{booksellerid} if $basket;
+}
+
+my $booksellerfrom = GetBookSellerFromId($bookselleridfrom);
+my $booksellerfromname;
+if($booksellerfrom){
+    $booksellerfromname = $booksellerfrom->{name};
+}
+my $booksellerto = GetBookSellerFromId($bookselleridto);
+my $booksellertoname;
+if($booksellerto){
+    $booksellertoname = $booksellerto->{name};
+}
+
+if( $basketno && $ordernumber) {
+    # Transfer order and exit
+    my $order = GetOrder( $ordernumber );
+    my $basket = GetBasket($order->{basketno});
+    my $booksellerfrom = GetBookSellerFromId($basket->{booksellerid});
+    my $bookselleridfrom = $booksellerfrom->{id};
+
+    TransferOrder($ordernumber, $basketno);
+
+    my $referrer = $input->param('referrer');
+    print $input->redirect($referrer);
+    exit;
+} elsif ( $bookselleridto && $ordernumber) {
+    # Show open baskets for this bookseller
+    my $order = GetOrder( $ordernumber );
+    my $basketfrom = GetBasket( $order->{basketno} );
+    my $booksellerfrom = GetBookSellerFromId( $basketfrom->{booksellerid} );
+    $booksellerfromname = $booksellerfrom->{name};
+    my $baskets = GetBasketsByBookseller( $bookselleridto );
+    my $basketscount = scalar @$baskets;
+    my @basketsloop = ();
+    for( my $i = 0 ; $i < $basketscount ; $i++ ){
+        my %line;
+        %line = %{ $baskets->[$i] };
+        my $createdby = GetMember(borrowernumber => $line{authorisedby});
+        $line{createdby} = "$createdby->{surname}, $createdby->{firstname}";
+        push @basketsloop, \%line unless $line{closedate};
+    }
+    $template->param(
+        show_baskets => 1,
+        basketsloop => \@basketsloop,
+        basketfromname => $basketfrom->{basketname},
+    );
+} elsif ( $bookselleridfrom && !defined $ordernumber) {
+    # Show pending orders
+    my $pendingorders = GetPendingOrders($bookselleridfrom);
+    my $orderscount = scalar @$pendingorders;
+    my @ordersloop = ();
+    for( my $i = 0 ; $i < $orderscount ; $i++ ){
+        my %line;
+        %line = %{ $pendingorders->[$i] };
+        push @ordersloop, \%line;
+    }
+    $template->param(
+        ordersloop  => \@ordersloop,
+    );
+} else {
+    # Search for booksellers to transfer from/to
+    $op = '' unless $op;
+    if( $op eq "do_search" ) {
+        my @booksellers = GetBookSeller($query);
+        $template->param(
+            query => $query,
+            do_search => 1,
+            booksellersloop => \@booksellers,
+        );
+    } else {
+        $template->param(
+            search_form => 1,
+        );
+    }
+}
+
+$template->param(
+    bookselleridfrom    => $bookselleridfrom,
+    booksellerfromname  => $booksellerfromname,
+    bookselleridto      => $bookselleridto,
+    booksellertoname    => $booksellertoname,
+    ordernumber         => $ordernumber,
+    basketno            => $basketno,
+    referrer            => $input->param('referrer')
+);
+
+output_html_with_http_headers $input, $cookie, $template->output;
+
index 3214ad9..c885b55 100644 (file)
@@ -2911,6 +2911,7 @@ CREATE TABLE `aqorders` ( -- information related to the basket line items
   `cancelledby` varchar(10) default NULL, -- not used? always NULL
   `datecancellationprinted` date default NULL, -- the date the line item was deleted
   `notes` mediumtext, -- notes related to this order line
+  internalnotes mediumtext DEFAULT NULL, -- used by Koha to store some informations, not editable by librarians
   `supplierreference` mediumtext, -- not used? always NULL
   `purchaseordernumber` mediumtext, -- not used? always NULL
   `basketno` int(11) default NULL, -- links this order line to a specific basket (aqbasket.basketno)
index ddcc455..3d1699f 100755 (executable)
@@ -7104,6 +7104,17 @@ if ( CheckVersion($DBversion) ) {
     SetVersion($DBversion);
 }
 
+$DBversion = "XXX";
+if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
+    $dbh->do(qq{
+        ALTER TABLE aqorders
+        ADD COLUMN internalnotes MEDIUMTEXT DEFAULT NULL AFTER notes
+    });
+    print "Upgrade to $DBversion done (Add internalnotes field in aqorders table)\n";
+    SetVersion($DBversion);
+}
+
+
 =head1 FUNCTIONS
 
 =head2 TableExists($table)
index ccc97d5..ea7f5d0 100644 (file)
                                 [% ELSE %]
                                     <p>[<a href="/cgi-bin/koha/acqui/modordernotes.pl?ordernumber=[% books_loo.ordernumber %]">Add note</a>]</p>
                                 [% END %]
+                            <p>[% books_loo.internalnotes %]</p>
                         </td>
                         <td class="number gste [% IF books_loo.rrpgste.search('^0') %]error[% END %]">[% books_loo.rrpgste %]</td>
                         <td class="number gste [% IF books_loo.ecostgste.search('^0') %]error[% END %]">[% books_loo.ecostgste %]</td>
                             [% UNLESS ( closedate ) %]
                             <td>
                                 <a href="neworderempty.pl?ordernumber=[% books_loo.ordernumber %]&amp;booksellerid=[% booksellerid %]&amp;basketno=[% basketno %]">Modify</a>
+                                [% UNLESS (books_loo.order_received) %]
+                                    <br />
+                                    <a href="/cgi-bin/koha/acqui/transferorder.pl?ordernumber=[% books_loo.ordernumber %]&referrer=[% "/cgi-bin/koha/acqui/basket.pl?basketno=$basketno" | uri %]">Transfer</a>
+                                [% END %]
                             </td>
                             <td>
                             [% IF ( books_loo.left_holds_on_order ) %]
                         [% IF ( order.publicationyear ) %], [% order.publicationyear %][% END %]
                         [% IF ( books_loo.editionstatement ) %], [% books_loo.editionstatement %][% END %]
                       </p>
+                      <p>[% order.internalnotes %]</p>
                     </td>
                     <td class="number gste">[% order.rrpgste %]</td>
                     <td class="number gste">[% order.ecostgste %]</td>
index d0c6e27..6725948 100644 (file)
                 <td>[% loop_order.budget_name %]</td>
                                <td>
                               <a href="orderreceive.pl?ordernumber=[% loop_order.ordernumber %]&amp;invoiceid=[% invoiceid %]">Receive</a>
+                    <br />
+                    <a href="/cgi-bin/koha/acqui/transferorder.pl?ordernumber=[% loop_order.ordernumber %]&amp;referrer=[% "/cgi-bin/koha/acqui/parcel.pl?invoiceid=[% invoiceid %]" | uri %]">Transfer</a>
                                </td>
                                <td>
                         [% IF ( loop_order.left_holds_on_order ) %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/transferorder.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/transferorder.tt
new file mode 100644 (file)
index 0000000..f694c1f
--- /dev/null
@@ -0,0 +1,121 @@
+[% INCLUDE 'doc-head-open.inc' %]
+<title>Koha &rsaquo; Acquisitions &rsaquo; Transfer order</title>
+[% INCLUDE 'doc-head-close.inc' %]
+</head>
+<body>
+[% 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>
+    &rsaquo; Transfer order
+</div>
+
+<div id="doc3" class="yui-t2">
+<div id="bd">
+<div id="yui-main">
+    <div class="yui-b">
+        [% IF ( show_baskets ) %]
+            <h1>Baskets for [% booksellertoname %]</h1>
+            [% IF ( basketsloop ) %]
+                <table>
+                    <thead>
+                        <th>Basket (#)</th>
+                        <th>Created by</th>
+                        <th>Date</th>
+                        <th>&nbsp;</th>
+                    </thead>
+                    <tbody>
+                        [% FOREACH basket IN basketsloop %]
+                          <tr>
+                            <td>[% basket.basketname %] (#[% basket.basketno %])</td>
+                            <td>[% basket.createdby %]</td>
+                            <td>[% basket.creationdate %]</td>
+                            <td><a href="transferorder.pl?basketno=[% basket.basketno %]&ordernumber=[% ordernumber %][% IF (referrer) %]&referrer=[% referrer | uri %][% END %]" onclick="return confirm('Do you want to transfer order [% ordernumber %] from basket [% basketfromname %] ([% booksellerfromname %]) to basket [% basket.basketname %] ([% booksellertoname %]) ?');">Choose</a>
+                          </tr>
+                        [% END %]
+                    </tbody>
+                </table>
+            [% ELSE %]
+                <p>There is no open baskets for this supplier.</p>
+            [% END %]
+        [% END %]
+        [% IF ( ordersloop ) %]
+            <h1>Orders for [% booksellerfromname %]</h1>
+            <table>
+                <thead>
+                    <th>Order</th>
+                    <th>Summary</th>
+                    <th>&nbsp;</th>
+                </thead>
+                <tbody>
+                    [% FOREACH ordersloo IN ordersloop %]
+                      <tr>
+                        <td><a href="neworderempty.pl?ordernumber=[% ordersloo.ordernumber %]">[% ordersloo.ordernumber %]</a></td>
+                        <td>
+                            <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% ordersloo.biblionumber %]">[% ordersloo.title |html %]</a>
+                            [% IF ( ordersloo.author ) %] by [% ordersloo.author %][% END %]
+                            [% IF ( ordersloo.isbn ) %] &ndash; [% ordersloo.isbn %][% END %]
+                            [% IF ( ordersloo.publishercode ) %]<br />Publisher :[% ordersloo.publishercode %][% END %]
+                        </td>
+                        <td><a href="transferorder.pl?bookselleridfrom=[% ordersloo.bookselleridfrom %]&ordernumber=[% ordersloo.ordernumber %][% IF (referrer) %]&referrer=[% referrer | uri %][% END %]">Transfer</a></td>
+                      </tr>
+                    [% END %]
+                </tbody>
+            </table>
+        [% END %]
+        [% IF ( do_search ) %]
+            [% IF ( bookselleridfrom ) %]
+                <h1>Choose a vendor to transfer to</h1>
+            [% ELSE %]
+                <h1>Choose a vendor to transfer from</h1>
+            [% END %]
+            [% IF ( booksellersloop ) %]
+                <table>
+                    <thead>
+                        <th>Name</th>
+                        <th>&nbsp;</th>
+                    </thead>
+                    <tbody>
+                        [% FOREACH bookseller IN booksellersloop %]
+                          <tr>
+                            <td>[% bookseller.name %]</td>
+                            <td><a href="transferorder.pl?[% IF (bookselleridfrom) %]bookselleridto[% ELSE %]bookselleridfrom[% END %]=[% bookseller.id %][% IF (ordernumber) %]&ordernumber=[% ordernumber %][% END %][% IF (referrer) %]&referrer=[% referrer | uri %][% END %]">Choose</a></td>
+                          </tr>
+                        [% END %]
+                    </tbody>
+                 </table>
+            [% ELSE %]
+                <p>No results found.</p>
+            [% END %]
+        [% END %]
+        [% IF ( search_form ) %]
+            [% IF ( bookselleridfrom ) %]
+                <h1>Search for a vendor to transfer to</h1>
+            [% ELSE %]
+                <h1>Search for a vendor to transfer from</h1>
+            [% END %]
+            <form method="get" action="transferorder.pl">
+                <input type="hidden" name="op" value="do_search" />
+                <input type="hidden" name="referrer" value="[% referrer %]" />
+                [% IF ( ordernumber ) %]
+                    <input type="hidden" name="ordernumber" value="[% ordernumber %]" />
+                [% END %]
+                [% IF ( bookselleridfrom ) %]
+                    <input type="hidden" name="bookselleridfrom" value="[% bookselleridfrom %]" />
+                [% END %]
+                <label for="query">Vendor:</label>
+                <input type="text" name="query" />
+                <input type="submit" value="Search" />
+            </form>
+        [% END %]
+    </div>
+</div>
+
+<div class="yui-b">
+    [% INCLUDE 'acquisitions-menu.inc' %]
+</div>
+</div>
+</div>
+[% INCLUDE 'intranet-bottom.inc' %]