X-Git-Url: http://koha-dev.rot13.org:8081/gitweb/?a=blobdiff_plain;f=C4%2FAcquisition.pm;h=ebbe44b1066737430e39cdc952e73f75b7019057;hb=bd3b1c1a33e4bb14bbcd10a0fcf871b39362430d;hp=31af6e5623124124f2b6acbd06118536fc64faa2;hpb=1c1e6b11f7d09efb18b5f26a5bf45b64bbbfbe18;p=koha_ffzg diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index 31af6e5623..ebbe44b106 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -29,9 +29,13 @@ use C4::Debug; use C4::Templates qw(gettemplate); use Koha::DateUtils qw( dt_from_string output_pref ); use Koha::Acquisition::Order; -use Koha::Acquisition::Bookseller; +use Koha::Acquisition::Booksellers; +use Koha::Biblios; +use Koha::Items; use Koha::Number::Price; use Koha::Libraries; +use Koha::CsvProfiles; +use Koha::Patrons; use C4::Koha; @@ -276,7 +280,7 @@ $cgi parameter is needed for column name translation =cut sub GetBasketAsCSV { - my ($basketno, $cgi) = @_; + my ($basketno, $cgi, $csv_profile_id) = @_; my $basket = GetBasket($basketno); my @orders = GetOrders($basketno); my $contract = GetContract({ @@ -284,48 +288,95 @@ sub GetBasketAsCSV { }); my $template = C4::Templates::gettemplate("acqui/csv/basket.tt", "intranet", $cgi); - my @rows; - foreach my $order (@orders) { - my $bd = GetBiblioData( $order->{'biblionumber'} ); - my $row = { - contractname => $contract->{'contractname'}, - ordernumber => $order->{'ordernumber'}, - entrydate => $order->{'entrydate'}, - isbn => $order->{'isbn'}, - author => $bd->{'author'}, - title => $bd->{'title'}, - publicationyear => $bd->{'publicationyear'}, - publishercode => $bd->{'publishercode'}, - collectiontitle => $bd->{'collectiontitle'}, - notes => $order->{'order_vendornote'}, - quantity => $order->{'quantity'}, - rrp => $order->{'rrp'}, - }; - for my $place ( qw( deliveryplace billingplace ) ) { - if ( my $library = Koha::Libraries->find( $row->{deliveryplace} ) ) { - $row->{$place} = $library->branchname + if ($csv_profile_id) { + my $csv_profile = Koha::CsvProfiles->find( $csv_profile_id ); + die "There is no valid csv profile given" unless $csv_profile; + + my $csv = Text::CSV_XS->new({'quote_char'=>'"','escape_char'=>'"','sep_char'=>$csv_profile->csv_separator,'binary'=>1}); + my $csv_profile_content = $csv_profile->content; + my ( @headers, @fields ); + while ( $csv_profile_content =~ / + ([^=\|]+) # header + =? + ([^\|]*) # fieldname (table.row or row) + \|? /gxms + ) { + my $header = $1; + my $field = ($2 eq '') ? $1 : $2; + + $header =~ s/^\s+|\s+$//g; # Trim whitespaces + push @headers, $header; + + $field =~ s/[^\.]*\.{1}//; # Remove the table name if exists. + $field =~ s/^\s+|\s+$//g; # Trim whitespaces + push @fields, $field; + } + for my $order (@orders) { + my @row; + my $biblio = Koha::Biblios->find( $order->{biblionumber} ); + my $biblioitem = $biblio->biblioitem; + $order = { %$order, %{ $biblioitem->unblessed } }; + if ($contract) { + $order = {%$order, %$contract}; } + $order = {%$order, %$basket, %{ $biblio->unblessed }}; + for my $field (@fields) { + push @row, $order->{$field}; + } + push @rows, \@row; } - foreach(qw( - contractname author title publishercode collectiontitle notes - deliveryplace billingplace - ) ) { - # Double the quotes to not be interpreted as a field end - $row->{$_} =~ s/"/""/g if $row->{$_}; + my $content = join( $csv_profile->csv_separator, @headers ) . "\n"; + for my $row ( @rows ) { + $csv->combine(@$row); + my $string = $csv->string; + $content .= $string . "\n"; } - push @rows, $row; + return $content; } + else { + foreach my $order (@orders) { + my $biblio = Koha::Biblios->find( $order->{biblionumber} ); + my $biblioitem = $biblio->biblioitem; + my $row = { + contractname => $contract->{'contractname'}, + ordernumber => $order->{'ordernumber'}, + entrydate => $order->{'entrydate'}, + isbn => $order->{'isbn'}, + author => $biblio->author, + title => $biblio->title, + publicationyear => $biblioitem->publicationyear, + publishercode => $biblioitem->publishercode, + collectiontitle => $biblioitem->collectiontitle, + notes => $order->{'order_vendornote'}, + quantity => $order->{'quantity'}, + rrp => $order->{'rrp'}, + }; + for my $place ( qw( deliveryplace billingplace ) ) { + if ( my $library = Koha::Libraries->find( $row->{deliveryplace} ) ) { + $row->{$place} = $library->branchname + } + } + foreach(qw( + contractname author title publishercode collectiontitle notes + deliveryplace billingplace + ) ) { + # Double the quotes to not be interpreted as a field end + $row->{$_} =~ s/"/""/g if $row->{$_}; + } + push @rows, $row; + } - @rows = sort { - if(defined $a->{publishercode} and defined $b->{publishercode}) { - $a->{publishercode} cmp $b->{publishercode}; - } - } @rows; + @rows = sort { + if(defined $a->{publishercode} and defined $b->{publishercode}) { + $a->{publishercode} cmp $b->{publishercode}; + } + } @rows; - $template->param(rows => \@rows); + $template->param(rows => \@rows); - return $template->output; + return $template->output; + } } @@ -351,32 +402,33 @@ sub GetBasketGroupAsCSV { my $contract = GetContract({ contractnumber => $basket->{contractnumber} }); - my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $basket->{booksellerid} }); + my $bookseller = Koha::Acquisition::Booksellers->find( $basket->{booksellerid} ); my $basketgroup = GetBasketgroup( $$basket{basketgroupid} ); foreach my $order (@orders) { - my $bd = GetBiblioData( $order->{'biblionumber'} ); + my $biblio = Koha::Biblios->find( $order->{biblionumber} ); + my $biblioitem = $biblio->biblioitem; my $row = { - clientnumber => $bookseller->{accountnumber}, + clientnumber => $bookseller->accountnumber, basketname => $basket->{basketname}, ordernumber => $order->{ordernumber}, - author => $bd->{author}, - title => $bd->{title}, - publishercode => $bd->{publishercode}, - publicationyear => $bd->{publicationyear}, - collectiontitle => $bd->{collectiontitle}, + author => $biblio->author, + title => $biblio->title, + publishercode => $biblioitem->publishercode, + publicationyear => $biblioitem->publicationyear, + collectiontitle => $biblioitem->collectiontitle, isbn => $order->{isbn}, quantity => $order->{quantity}, rrp_tax_included => $order->{rrp_tax_included}, rrp_tax_excluded => $order->{rrp_tax_excluded}, - discount => $bookseller->{discount}, + discount => $bookseller->discount, ecost_tax_included => $order->{ecost_tax_included}, ecost_tax_excluded => $order->{ecost_tax_excluded}, notes => $order->{order_vendornote}, entrydate => $order->{entrydate}, - booksellername => $bookseller->{name}, - bookselleraddress => $bookseller->{address1}, - booksellerpostal => $bookseller->{postal}, + booksellername => $bookseller->name, + bookselleraddress => $bookseller->address1, + booksellerpostal => $bookseller->postal, contractnumber => $contract->{contractnumber}, contractname => $contract->{contractname}, }; @@ -749,7 +801,7 @@ AcqViewBaskets, user permissions and basket properties (creator, users list, branch). First parameter can be either a borrowernumber or a hashref as returned by -C4::Members::GetMember. +Koha::Patron->unblessed Second parameter can be either a basketno or a hashref as returned by C4::Acquisition::GetBasket. @@ -766,7 +818,10 @@ sub CanUserManageBasket { my ($borrower, $basket, $userflags) = @_; if (!ref $borrower) { - $borrower = C4::Members::GetMember(borrowernumber => $borrower); + # FIXME This needs to be replaced + # We should not accept both scalar and array + # Tests need to be updated + $borrower = Koha::Patrons->find( $borrower )->unblessed; } if (!ref $basket) { $basket = GetBasket($basket); @@ -804,8 +859,8 @@ sub CanUserManageBasket { if ($AcqViewBaskets eq 'user' && $basket->{authorisedby} != $borrowernumber - && grep($borrowernumber, GetBasketUsers($basketno)) == 0) { - return 0; + && ! grep { $borrowernumber eq $_ } GetBasketUsers($basketno)) { + return 0; } if ($AcqViewBaskets eq 'branch' && defined $basket->{branch} @@ -1380,8 +1435,14 @@ sub ModReceiveOrder { ); } + my $result_set = $dbh->selectrow_arrayref( + q{SELECT aqbasket.is_standing + FROM aqbasket + WHERE basketno=?},{ Slice => {} }, $order->{basketno}); + my $is_standing = $result_set->[0]; # we assume we have a unique basket + my $new_ordernumber = $order->{ordernumber}; - if ( $order->{quantity} > $quantrec ) { + if ( $is_standing || $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 @@ -1395,15 +1456,30 @@ sub ModReceiveOrder { my $sth = $dbh->prepare($query); $sth->execute( - $order->{quantity} - $quantrec, + ( $is_standing ? 1 : ($order->{quantity} - $quantrec) ), ( defined $order->{order_internalnote} ? $order->{order_internalnote} : () ), $order->{ordernumber} ); + # Recalculate tax_value + $dbh->do(q| + UPDATE aqorders + SET + tax_value_on_ordering = quantity * ecost_tax_excluded * tax_rate_on_ordering, + tax_value_on_receiving = quantity * unitprice_tax_excluded * tax_rate_on_receiving + WHERE ordernumber = ? + |, undef, $order->{ordernumber}); + delete $order->{ordernumber}; $order->{budget_id} = ( $budget_id || $order->{budget_id} ); $order->{quantity} = $quantrec; $order->{quantityreceived} = $quantrec; + $order->{ecost_tax_excluded} //= 0; + $order->{tax_rate_on_ordering} //= 0; + $order->{unitprice_tax_excluded} //= 0; + $order->{tax_rate_on_receiving} //= 0; + $order->{tax_value_on_ordering} = $order->{quantity} * $order->{ecost_tax_excluded} * $order->{tax_rate_on_ordering}; + $order->{tax_value_on_receiving} = $order->{quantity} * $order->{unitprice_tax_excluded} * $order->{tax_rate_on_receiving}; $order->{datereceived} = $datereceived; $order->{invoiceid} = $invoice->{invoiceid}; $order->{orderstatus} = 'complete'; @@ -1429,12 +1505,12 @@ sub ModReceiveOrder { | if defined $order->{unitprice}; $query .= q| - , rrp = ?, rrp_tax_included = ?, rrp_tax_excluded = ? - | if defined $order->{rrp}; + ,tax_value_on_receiving = ? + | if defined $order->{tax_value_on_receiving}; $query .= q| - , ecost = ?, ecost_tax_included = ?, ecost_tax_excluded = ? - | if defined $order->{ecost}; + ,tax_rate_on_receiving = ? + | if defined $order->{tax_rate_on_receiving}; $query .= q| , order_internalnote = ? @@ -1443,17 +1519,20 @@ sub ModReceiveOrder { $query .= q| where biblionumber=? and ordernumber=?|; my $sth = $dbh->prepare( $query ); - my @params = ( $quantrec, $datereceived, $invoice->{invoiceid}, $budget_id ); + my @params = ( $quantrec, $datereceived, $invoice->{invoiceid}, ( $budget_id ? $budget_id : $order->{budget_id} ) ); if ( defined $order->{unitprice} ) { push @params, $order->{unitprice}, $order->{unitprice_tax_included}, $order->{unitprice_tax_excluded}; } - if ( defined $order->{rrp} ) { - push @params, $order->{rrp}, $order->{rrp_tax_included}, $order->{rrp_tax_excluded}; + + if ( defined $order->{tax_value_on_receiving} ) { + push @params, $order->{tax_value_on_receiving}; } - if ( defined $order->{ecost} ) { - push @params, $order->{ecost}, $order->{ecost_tax_included}, $order->{ecost_tax_excluded}; + + if ( defined $order->{tax_rate_on_receiving} ) { + push @params, $order->{tax_rate_on_receiving}; } + if ( defined $order->{order_internalnote} ) { push @params, $order->{order_internalnote}; } @@ -1556,6 +1635,16 @@ sub CancelReceipt { " receipt"; return; } + + # Recalculate tax_value + $dbh->do(q| + UPDATE aqorders + SET + tax_value_on_ordering = quantity * ecost_tax_excluded * tax_rate_on_ordering, + tax_value_on_receiving = quantity * unitprice_tax_excluded * tax_rate_on_receiving + WHERE ordernumber = ? + |, undef, $parent_ordernumber); + _cancel_items_receipt( $ordernumber, $parent_ordernumber ); # Delete order line $query = qq{ @@ -1571,17 +1660,17 @@ sub CancelReceipt { my @affects = split q{\|}, C4::Context->preference("AcqItemSetSubfieldsWhenReceiptIsCancelled"); if ( @affects ) { for my $in ( @itemnumbers ) { - my $biblionumber = C4::Biblio::GetBiblionumberFromItemnumber( $in ); - my $frameworkcode = GetFrameworkCode($biblionumber); - my ( $itemfield ) = GetMarcFromKohaField( 'items.itemnumber', $frameworkcode ); - my $item = C4::Items::GetMarcItem( $biblionumber, $in ); + my $item = Koha::Items->find( $in ); + my $biblio = $item->biblio; + my ( $itemfield ) = GetMarcFromKohaField( 'items.itemnumber', $biblio->frameworkcode ); + my $item_marc = C4::Items::GetMarcItem( $biblio->biblionumber, $in ); for my $affect ( @affects ) { my ( $sf, $v ) = split q{=}, $affect, 2; - foreach ( $item->field($itemfield) ) { + foreach ( $item_marc->field($itemfield) ) { $_->update( $sf => $v ); } } - C4::Items::ModItemFromMarc( $item, $biblionumber, $in ); + C4::Items::ModItemFromMarc( $item_marc, $biblio->biblionumber, $in ); } } } @@ -1621,17 +1710,22 @@ sub _cancel_items_receipt { @results = &SearchOrders({ ordernumber => $ordernumber, search => $search, - biblionumber => $biblionumber, ean => $ean, booksellerid => $booksellerid, basketno => $basketno, + basketname => $basketname, + basketgroupname => $basketgroupname, owner => $owner, pending => $pending ordered => $ordered + biblionumber => $biblionumber, + budget_id => $budget_id }); -Searches for orders. +Searches for orders filtered by criteria. +C<$ordernumber> Finds matching orders or transferred orders by ordernumber. +C<$search> Finds orders matching %$search% in title, author, or isbn. C<$owner> Finds order for the logged in user. C<$pending> Finds pending orders. Ignores completed and cancelled orders. C<$ordered> Finds orders to receive only (status 'ordered' or 'partial'). @@ -1666,6 +1760,8 @@ sub SearchOrders { biblio.*, biblioitems.isbn, biblioitems.biblioitemnumber, + biblioitems.publishercode, + biblioitems.publicationyear, aqbasket.authorisedby, aqbasket.booksellerid, aqbasket.closedate, @@ -1817,7 +1913,8 @@ sub DelOrder { if($delete_biblio) { # We get the number of remaining items - my $itemcount = C4::Items::GetItemsCount($bibnum); + my $biblio = Koha::Biblios->find( $bibnum ); + my $itemcount = $biblio->items->count; # If there are no items left, if ( $itemcount == 0 ) { @@ -2053,11 +2150,7 @@ sub GetLateOrders { $from .= " AND (closedate <= DATE_SUB(CAST(now() AS date),INTERVAL ? DAY)) " ; push @query_params, $delay; } - $having = " - HAVING quantity <> 0 - AND unitpricesupplier <> 0 - AND unitpricelib <> 0 - "; + $having = "HAVING quantity <> 0"; } else { # FIXME: account for IFNULL as above $select .= " @@ -2580,6 +2673,7 @@ sub GetInvoiceDetails { SELECT aqorders.*, biblio.*, biblio.copyrightdate, + biblioitems.isbn, biblioitems.publishercode, biblioitems.publicationyear, aqbasket.basketname, @@ -2834,7 +2928,7 @@ sub populate_order_with_prices { my $booksellerid = $params->{booksellerid}; return unless $booksellerid; - my $bookseller = Koha::Acquisition::Bookseller->fetch({ id => $booksellerid }); + my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid ); my $receiving = $params->{receiving}; my $ordering = $params->{ordering}; @@ -2842,12 +2936,13 @@ sub populate_order_with_prices { $discount /= 100 if $discount > 1; if ($ordering) { - if ( $bookseller->{listincgst} ) { + $order->{tax_rate_on_ordering} //= $order->{tax_rate}; + if ( $bookseller->listincgst ) { # The user entered the rrp tax included $order->{rrp_tax_included} = $order->{rrp}; # rrp tax excluded = rrp tax included / ( 1 + tax rate ) - $order->{rrp_tax_excluded} = $order->{rrp_tax_included} / ( 1 + $order->{tax_rate} ); + $order->{rrp_tax_excluded} = $order->{rrp_tax_included} / ( 1 + $order->{tax_rate_on_ordering} ); # ecost tax excluded = rrp tax excluded * ( 1 - discount ) $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount ); @@ -2860,7 +2955,7 @@ sub populate_order_with_prices { $order->{rrp_tax_excluded} = $order->{rrp}; # rrp tax included = rrp tax excluded * ( 1 - tax rate ) - $order->{rrp_tax_included} = $order->{rrp_tax_excluded} * ( 1 + $order->{tax_rate} ); + $order->{rrp_tax_included} = $order->{rrp_tax_excluded} * ( 1 + $order->{tax_rate_on_ordering} ); # ecost tax excluded = rrp tax excluded * ( 1 - discount ) $order->{ecost_tax_excluded} = $order->{rrp_tax_excluded} * ( 1 - $discount ); @@ -2868,32 +2963,47 @@ sub populate_order_with_prices { # ecost tax included = rrp tax excluded * ( 1 - tax rate ) * ( 1 - discount ) $order->{ecost_tax_included} = $order->{rrp_tax_excluded} * - ( 1 + $order->{tax_rate} ) * + ( 1 + $order->{tax_rate_on_ordering} ) * ( 1 - $discount ); } # tax value = quantity * ecost tax excluded * tax rate - $order->{tax_value} = $order->{quantity} * $order->{ecost_tax_excluded} * $order->{tax_rate}; + $order->{tax_value_on_ordering} = + $order->{quantity} * $order->{ecost_tax_excluded} * $order->{tax_rate_on_ordering}; } if ($receiving) { - if ( $bookseller->{invoiceincgst} ) { + $order->{tax_rate_on_receiving} //= $order->{tax_rate}; + if ( $bookseller->invoiceincgst ) { + # Trick for unitprice. If the unit price rounded value is the same as the ecost rounded value + # we need to keep the exact ecost value + if ( Koha::Number::Price->new( $order->{unitprice} )->round == Koha::Number::Price->new( $order->{ecost_tax_included} )->round ) { + $order->{unitprice} = $order->{ecost_tax_included}; + } + # The user entered the unit price tax included $order->{unitprice_tax_included} = $order->{unitprice}; # unit price tax excluded = unit price tax included / ( 1 + tax rate ) - $order->{unitprice_tax_excluded} = $order->{unitprice_tax_included} / ( 1 + $order->{tax_rate} ); + $order->{unitprice_tax_excluded} = $order->{unitprice_tax_included} / ( 1 + $order->{tax_rate_on_receiving} ); } else { + # Trick for unitprice. If the unit price rounded value is the same as the ecost rounded value + # we need to keep the exact ecost value + if ( Koha::Number::Price->new( $order->{unitprice} )->round == Koha::Number::Price->new( $order->{ecost_tax_excluded} )->round ) { + $order->{unitprice} = $order->{ecost_tax_excluded}; + } + # The user entered the unit price tax excluded $order->{unitprice_tax_excluded} = $order->{unitprice}; + # unit price tax included = unit price tax included * ( 1 + tax rate ) - $order->{unitprice_tax_included} = $order->{unitprice_tax_excluded} * ( 1 + $order->{tax_rate} ); + $order->{unitprice_tax_included} = $order->{unitprice_tax_excluded} * ( 1 + $order->{tax_rate_on_receiving} ); } # tax value = quantity * unit price tax excluded * tax rate - $order->{tax_value} = $order->{quantity} * $order->{unitprice_tax_excluded} * $order->{tax_rate}; + $order->{tax_value_on_receiving} = $order->{quantity} * $order->{unitprice_tax_excluded} * $order->{tax_rate_on_receiving}; } return $order; @@ -2971,16 +3081,17 @@ sub NotifyOrderUsers { my $order = GetOrder( $ordernumber ); for my $borrowernumber (@borrowernumbers) { - my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber ); - my $library = Koha::Libraries->find( $borrower->{branchcode} )->unblessed; - my $biblio = C4::Biblio::GetBiblio( $order->{biblionumber} ); + my $patron = Koha::Patrons->find( $borrowernumber ); + my $library = $patron->library->unblessed; + my $biblio = Koha::Biblios->find( $order->{biblionumber} )->unblessed; my $letter = C4::Letters::GetPreparedLetter( module => 'acquisition', letter_code => 'ACQ_NOTIF_ON_RECEIV', branchcode => $library->{branchcode}, + lang => $patron->lang, tables => { 'branches' => $library, - 'borrowers' => $borrower, + 'borrowers' => $patron->unblessed, 'biblio' => $biblio, 'aqorders' => $order, },