@@ -, +, @@ ------------- ------------- - to explain a little bit more why it happend and re-word the message for non technical people (not everybody understands 'parent' the same way) - prevent the situation to happen (e.g. forbid order lines to be deleted if they are already received) - but that would be in the scope of an other bug, I think. --- C4/Acquisition.pm | 180 ++++++++++++++++---- acqui/finishreceive.pl | 24 ++- acqui/parcel.pl | 14 +- installer/data/mysql/kohastructure.sql | 1 + installer/data/mysql/updatedatabase.pl | 15 ++ .../intranet-tmpl/prog/en/modules/acqui/parcel.tt | 19 +++ 6 files changed, 213 insertions(+), 40 deletions(-) --- a/C4/Acquisition.pm +++ a/C4/Acquisition.pm @@ -56,7 +56,7 @@ BEGIN { &NewOrder &DelOrder &ModOrder &GetPendingOrders &GetOrder &GetOrders &GetOrderNumber &GetLateOrders &GetOrderFromItemnumber &SearchOrder &GetHistory &GetRecentAcqui - &ModReceiveOrder &ModOrderBiblioitemNumber + &ModReceiveOrder &CancelReceipt &ModOrderBiblioitemNumber &GetCancelledOrders &NewOrderItem &ModOrderItem &ModItemOrder @@ -1042,6 +1042,14 @@ sub NewOrder { } my $ordernumber=InsertInTable("aqorders",$orderinfo); + if (not $orderinfo->{parent_ordernumber}) { + my $sth = $dbh->prepare(" + UPDATE aqorders + SET parent_ordernumber = ordernumber + WHERE ordernumber = ? + "); + $sth->execute($ordernumber); + } return ( $orderinfo->{'basketno'}, $ordernumber ); } @@ -1259,6 +1267,7 @@ sub ModReceiveOrder { $invoiceno, $freight, $rrp, $budget_id, $datereceived, $received_items ) = @_; + my $dbh = C4::Context->dbh; $datereceived = C4::Dates->output('iso') unless $datereceived; my $suggestionid = GetSuggestionFromBiblionumber( $biblionumber ); @@ -1277,40 +1286,37 @@ sub ModReceiveOrder { my $order = $sth->fetchrow_hashref(); $sth->finish(); + my $new_ordernumber = $ordernumber; if ( $order->{quantity} > $quantrec ) { + # Split order line in two parts: the first is the original order line + # without received items (the quantity is decreased), + # the second part is a new order line with quantity=quantityrec + # (entirely received) $sth=$dbh->prepare(" UPDATE aqorders - SET quantityreceived=? - , datereceived=? - , booksellerinvoicenumber=? - , unitprice=? - , freight=? - , rrp=? - , quantity=? - WHERE biblionumber=? AND ordernumber=?"); - - $sth->execute($quantrec,$datereceived,$invoiceno,$cost,$freight,$rrp,$quantrec,$biblionumber,$ordernumber); + SET quantity = ? + WHERE ordernumber = ? + "); + + $sth->execute($order->{quantity} - $quantrec, $ordernumber); $sth->finish; - # create a new order for the remaining items, and set its bookfund. - foreach my $orderkey ( "linenumber", "allocation" ) { - delete($order->{'$orderkey'}); - } - $order->{'quantity'} -= $quantrec; - $order->{'quantityreceived'} = 0; - my $newOrder = NewOrder($order); - # Change ordernumber in aqorders_items for items not received - my @orderitems = GetItemnumbersFromOrder( $order->{'ordernumber'} ); - my $count = scalar @orderitems; - - for (my $i=0; $i<$count; $i++){ - foreach (@$received_items){ - splice (@orderitems, $i, 1) if ($orderitems[$i] == $_); + delete $order->{'ordernumber'}; + $order->{'quantity'} = $quantrec; + $order->{'quantityreceived'} = $quantrec; + $order->{'datereceived'} = $datereceived; + $order->{'booksellerinvoicenumber'} = $invoiceno; + $order->{'unitprice'} = $cost; + $order->{'freight'} = $freight; + $order->{'rrp'} = $rrp; + $order->{'orderstatus'} = 3; # totally received + $new_ordernumber = NewOrder($order); + + if ($received_items) { + foreach my $itemnumber (@$received_items) { + ModItemOrder($itemnumber, $new_ordernumber); } } - foreach (@orderitems) { - ModItemOrder($_, $newOrder); - } } else { $sth=$dbh->prepare("update aqorders set quantityreceived=?,datereceived=?,booksellerinvoicenumber=?, @@ -1319,8 +1325,123 @@ sub ModReceiveOrder { $sth->execute($quantrec,$datereceived,$invoiceno,$cost,$freight,$rrp,$biblionumber,$ordernumber); $sth->finish; } - return $datereceived; + return ($datereceived, $new_ordernumber); } + +=head3 CancelReceipt + + my $parent_ordernumber = CancelReceipt($ordernumber); + + Cancel an order line receipt and update the parent order line, as if no + receipt was made. + If items are created at receipt (AcqCreateItem = receiving) then delete + these items. + +=cut + +sub CancelReceipt { + my $ordernumber = shift; + + return unless $ordernumber; + + my $dbh = C4::Context->dbh; + my $query = qq{ + SELECT datereceived, parent_ordernumber, quantity + FROM aqorders + WHERE ordernumber = ? + }; + my $sth = $dbh->prepare($query); + $sth->execute($ordernumber); + my $order = $sth->fetchrow_hashref; + unless($order) { + warn "CancelReceipt: order $ordernumber does not exist"; + return; + } + unless($order->{'datereceived'}) { + warn "CancelReceipt: order $ordernumber is not received"; + return; + } + + my $parent_ordernumber = $order->{'parent_ordernumber'}; + + if($parent_ordernumber == $ordernumber || not $parent_ordernumber) { + # The order line has no parent, just mark it as not received + $query = qq{ + UPDATE aqorders + SET quantityreceived = ?, + datereceived = ?, + booksellerinvoicenumber = ? + WHERE ordernumber = ? + }; + $sth = $dbh->prepare($query); + $sth->execute(0, undef, undef, $ordernumber); + } else { + # The order line has a parent, increase parent quantity and delete + # the order line. + $query = qq{ + SELECT quantity, datereceived + FROM aqorders + WHERE ordernumber = ? + }; + $sth = $dbh->prepare($query); + $sth->execute($parent_ordernumber); + my $parent_order = $sth->fetchrow_hashref; + unless($parent_order) { + warn "Parent order $parent_ordernumber does not exist."; + return; + } + if($parent_order->{'datereceived'}) { + warn "CancelReceipt: parent order is received.". + " Can't cancel receipt."; + return; + } + $query = qq{ + UPDATE aqorders + SET quantity = ? + WHERE ordernumber = ? + }; + $sth = $dbh->prepare($query); + my $rv = $sth->execute( + $order->{'quantity'} + $parent_order->{'quantity'}, + $parent_ordernumber + ); + unless($rv) { + warn "Cannot update parent order line, so do not cancel". + " receipt"; + return; + } + if(C4::Context->preference('AcqCreateItem') eq 'receiving') { + # Remove items that were created at receipt + $query = qq{ + DELETE FROM items, aqorders_items + USING items, aqorders_items + WHERE items.itemnumber = ? AND aqorders_items.itemnumber = ? + }; + $sth = $dbh->prepare($query); + my @itemnumbers = GetItemnumbersFromOrder($ordernumber); + foreach my $itemnumber (@itemnumbers) { + $sth->execute($itemnumber, $itemnumber); + } + } else { + # Update items + my @itemnumbers = GetItemnumbersFromOrder($ordernumber); + foreach my $itemnumber (@itemnumbers) { + ModItemOrder($itemnumber, $parent_ordernumber); + } + } + # Delete order line + $query = qq{ + DELETE FROM aqorders + WHERE ordernumber = ? + }; + $sth = $dbh->prepare($query); + $sth->execute($ordernumber); + + } + + return $parent_ordernumber; +} + #------------------------------------------------------------# =head3 SearchOrder @@ -1464,6 +1585,7 @@ sub GetParcel { firstname, aqorders.biblionumber, aqorders.ordernumber, + aqorders.parent_ordernumber, aqorders.quantity, aqorders.quantityreceived, aqorders.unitprice, --- a/acqui/finishreceive.pl +++ a/acqui/finishreceive.pl @@ -58,6 +58,20 @@ my $note = $input->param("note"); #need old recievedate if we update the order, parcel.pl only shows the right parcel this way FIXME if ($quantityrec > $origquantityrec ) { + my @received_items = (); + if(C4::Context->preference('AcqCreateItem') eq 'ordering') { + @received_items = $input->param('items_to_receive'); + } + + my $new_ordernumber = $ordernumber; + # save the quantity received. + if ( $quantityrec > 0 ) { + ($datereceived, $new_ordernumber) = ModReceiveOrder( + $biblionumber, $ordernumber, $quantityrec, $user, $unitprice, + $invoiceno, $freight, $replacement, undef, $datereceived, + \@received_items); + } + # now, add items if applicable if (C4::Context->preference('AcqCreateItem') eq 'receiving') { @@ -91,17 +105,9 @@ if ($quantityrec > $origquantityrec ) { $itemhash{$item}->{'indicator'},'ITEM'); my $record=MARC::Record::new_from_xml($xml, 'UTF-8'); my (undef,$bibitemnum,$itemnumber) = AddItemFromMarc($record,$biblionumber); - NewOrderItem($itemnumber, $ordernumber); + NewOrderItem($itemnumber, $new_ordernumber); } } - - my @received_items = (); - if(C4::Context->preference('AcqCreateItem') eq 'ordering') { - @received_items = $input->param('items_to_receive'); - } - - # save the quantity received. - $datereceived = ModReceiveOrder($biblionumber,$ordernumber, $quantityrec ,$user,$unitprice,$invoiceno,$freight,$replacement,undef,$datereceived, \@received_items); } update_item( $_ ) foreach GetItemnumbersFromOrder( $ordernumber ); --- a/acqui/parcel.pl +++ a/acqui/parcel.pl @@ -78,8 +78,10 @@ my $invoice=$input->param('invoice') || ''; my $freight=$input->param('freight'); my $input_gst = ($input->param('gst') eq '' ? undef : $input->param('gst')); my $gst= $input_gst // $bookseller->{gstrate} // C4::Context->preference("gist") // 0; -my $datereceived = ($input->param('op') eq ('new' or "search")) ? C4::Dates->new($input->param('datereceived')) - : C4::Dates->new($input->param('datereceived'), 'iso'); +my $op = $input->param('op') // ''; +my $datereceived = ($op eq ('new' or 'search' ) + ? C4::Dates->new($input->param('datereceived')) + : C4::Dates->new($input->param('datereceived'), 'iso'); $datereceived = C4::Dates->new() unless $datereceived; my $code = $input->param('code'); my @rcv_err = $input->param('error'); @@ -98,6 +100,14 @@ my ($template, $loggedinuser, $cookie) debug => 1, }); +if($op eq 'cancelreceipt') { + my $ordernumber = $input->param('ordernumber'); + my $parent_ordernumber = CancelReceipt($ordernumber); + unless($parent_ordernumber) { + $template->param(error_cancelling_receipt => 1); + } +} + # If receiving error, report the error (coming from finishrecieve.pl(sic)). if( scalar(@rcv_err) ) { my $cnt=0; --- a/installer/data/mysql/kohastructure.sql +++ a/installer/data/mysql/kohastructure.sql @@ -2773,6 +2773,7 @@ CREATE TABLE `aqorders` ( -- information related to the basket line items `uncertainprice` tinyint(1), -- was this price uncertain (1 for yes, 0 for no) `claims_count` int(11) default 0, -- count of claim letters generated `claimed_date` date default NULL, -- last date a claim was generated + parent_ordernumber int(11) default NULL, -- ordernumber of parent order line, or same as ordernumber if no parent PRIMARY KEY (`ordernumber`), KEY `basketno` (`basketno`), KEY `biblionumber` (`biblionumber`), --- a/installer/data/mysql/updatedatabase.pl +++ a/installer/data/mysql/updatedatabase.pl @@ -5696,6 +5696,21 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { SetVersion($DBversion); } +$DBversion = "XXX"; +if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) { + $dbh->do(" + ALTER TABLE aqorders + ADD parent_ordernumber int(11) DEFAULT NULL + "); + $dbh->do(" + UPDATE aqorders + SET parent_ordernumber = ordernumber; + "); + print "Upgrade to $DBversion done (Adding parent_ordernumber in aqorders)\n"; + SetVersion($DBversion); +} + + =head1 FUNCTIONS =head2 TableExists($table) --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcel.tt +++ a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcel.tt @@ -161,6 +161,20 @@ [% END %] [% END %] + [% IF (error_cancelling_receipt) %] +
+ Cannot cancel receipt. Possible reasons : + +
+ [% END %] +

Invoice number: [% invoice %] Received by: [% loggedinusername %] On: [% formatteddatereceived %]

@@ -269,6 +283,7 @@

Already received

+ [% IF ( loop_received ) %]
@@ -282,6 +297,7 @@ + @@ -290,6 +306,7 @@ + [% IF ( totalfreight ) %] @@ -317,6 +334,7 @@ + @@ -339,6 +357,7 @@ + [% END %] --
Est cost Actual cost TOTAL
  [% totalprice %] [% tototal %]
[% totalquantity %]   [% grandtot %]
[% loop_receive.ecost %] [% loop_receive.unitprice %] [% loop_receive.total %]Cancel receipt