From 93bfda6089ef1ff850fe48091d6c1b4f77fc04ea Mon Sep 17 00:00:00 2001 From: Agustin Moyano Date: Fri, 9 Oct 2020 13:38:46 -0300 Subject: [PATCH] Bug 8179: Receive multiple orders This patch implements the code to allow a patron to receive multiple orders at the same time in /cgi-bin/koha/acqui/orderreceive.pl page To test: 1. apply all patches 2. updatedatabase 3. Go to system preferences and allow AcqReceiveMultipleOrderLines 4. In acquisitions module, create a vendor if you don't have one and add 3 baskets.. one with create items on ordering, one with create items on receiving and finally one with create items when cataloguing 5. Fill baskets with orders (There should be at least 15 orders in total). There should be a mix of orders created by suggestions, others by subscriptions and others by neither of those methods. 6. Close all baskets and receive shipment. CHECK => in /cgi-bin/koha/acqui/parcel.pl page, in top table there is a column with checkboxes, and a button that says "Receive selected" 7. If all orders from all baskets are shown in the table, set the rows per page to 10, so table has more than one page 8. Check some of the checkboxes CHECK => "Receive selected" button shows how many rows are selected 9. Go to the next page and select some more rows CHECK => Changing page does not modify how many rows where selected 10. Go back to previous page CHECK => Previously selected rows are still selected 11. Reload the page to deselect all rows 12. Select only one row and click on "Receive selected" button CHECK => the page /cgi-bin/koha/acqui/orderreceive.pl behaves just the same as if the "receive" link in the selected row would have been clicked. 13. Click on cancel to go back to parcel.pl page 14. Select all rows (even the ones from the next page of the table) and click on "Receive selected" CHECH => In orderreceive.pl page there is a table with all selected rows 15. Ensure table has more than one page, as in step 7 16. Click on the "edit" link in the last row of the current page CHECK => A modal window is displayed with 4 tabs within: Info, Accounting, Receipt history and Items CHECK => Modal has 4 buttons at the bottom, 'Previous' to go to previos order, 'Cancel' to close the modal without keeping modifications, 'Save' to close modal keeping modifications and 'Next' to go to the next order CHECK => Even that we are at the end of the current page, 'Next' button is still available 17. Click on 'Next' button CHECK => The table behind the modal now displays the next page, and the modal was not closed 18. Click on 'Previous' CHECK => The table behind the modal went back to the first page, and the modal was not closed 19. Click on 'Previous' button till you reach the first row of the first page CHECK => Only when you reach the first row of the first page 'Previous' button gets disabled 20. Click on 'Next' button till you reach the last row of the last page CHECK => Only when you reach the last button of the last page 'Next' button gets disabled 21. Check that behaviour for the different types of order are still the same a. For orders that where created through suggestion, check that the suggestion info is present in Info tab. If when suggestion was accepted you set a reason, a dropdown to change the reason shoul display also. b. For orders that where created through subscriptions, check that the Items tab is disabled, and the Receipt history is enabled. On accounting tab you should be able to change quantity ordered. If there were less items received than ordered, the next time you receive this order the child order generated from this one shoul appear in receipt history. c. For orders that don't come from subscription and creates there items on ordering, Receipt history should be disabled, and a table with prefilled items shold appear in the Items tab. You can edit them and the changes should appear in the item's row. d. For orders that don't come from subscription and creates there items on receiving, Receipt history should be disabled, and a form to create the items should appear in Items tab. When you add an item a table should appear. e. For orders that don't come from subscription and creates there ites on cataloguing, Receipt history and Items tabs should be disabled. f. Any changes made in quantity (received or ordered) or funds in the modal should be reflected in the table if you click save from the modal. 22. Once you've done all you checking and verifications click save 23. While saving a progress bar should appear 24. If no error was detected, you should be redirected back to parcel.pl page 25. If an error or warning was detected (like there is an order with 0 items to receive) the save button should be disabled and warnings are dispayed. 26. prove t/db_dependent/Koha/Acquisition/Fund.t t/db_dependent/Koha/Acquisitoin/Order.t t/db_dependent/Koha/Item.t Sponsored-by: Virginia Polytechnic Institute and State University --- Koha/Acquisition/Fund.pm | 2 +- Koha/Acquisition/Order.pm | 15 + Koha/Item.pm | 27 + Koha/REST/V1/Acquisitions/Orders.pm | 7 +- Koha/REST/V1/Items.pm | 7 +- Koha/Schema/Result/Aqorder.pm | 20 + acqui/finishreceive.pl | 2 + acqui/orderreceive.pl | 98 +- api/v1/swagger/definitions/item.json | 12 + api/v1/swagger/definitions/order.json | 9 + api/v1/swagger/paths/acquisitions_orders.json | 7 +- api/v1/swagger/paths/items.json | 7 +- .../lib/datatables/dataTables.select.min.js | 38 + .../lib/datatables/select.dataTables.min.css | 1 + .../prog/en/includes/datatables.inc | 1 + .../prog/en/includes/doc-head-close.inc | 1 + .../prog/en/modules/acqui/orderreceive.tt | 1131 ++++++++++++++++- .../prog/en/modules/acqui/parcel.tt | 70 +- 18 files changed, 1394 insertions(+), 61 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/lib/datatables/dataTables.select.min.js create mode 100644 koha-tmpl/intranet-tmpl/lib/datatables/select.dataTables.min.css diff --git a/Koha/Acquisition/Fund.pm b/Koha/Acquisition/Fund.pm index 80ef0b2f4a..c1b28f036d 100644 --- a/Koha/Acquisition/Fund.pm +++ b/Koha/Acquisition/Fund.pm @@ -17,8 +17,8 @@ package Koha::Acquisition::Fund; use Modern::Perl; -use Koha::Acquisition::Budgets; use Koha::Database; +use Koha::Acquisition::Budget; use base qw(Koha::Object); diff --git a/Koha/Acquisition/Order.pm b/Koha/Acquisition/Order.pm index 07dea68939..f07629c265 100644 --- a/Koha/Acquisition/Order.pm +++ b/Koha/Acquisition/Order.pm @@ -32,6 +32,7 @@ use Koha::Exceptions::Object; use Koha::Biblios; use Koha::Holds; use Koha::Items; +use Koha::Patron; use Koha::Subscriptions; use base qw(Koha::Object); @@ -394,6 +395,20 @@ sub claimed_date { return $last_claim->claimed_on; } +=head3 creator + +my $creator = $order->creator; + +Retrieves patron that created this order. + +=cut + +sub creator { + my ( $self ) = @_; + my $creator_rs = $self->_result->creator; + return Koha::Patron->_new_from_dbic( $creator_rs ); +} + =head3 duplicate_to my $duplicated_order = $order->duplicate_to($basket, [$default_values]); diff --git a/Koha/Item.pm b/Koha/Item.pm index 5c9d86e49a..174fd69d0e 100644 --- a/Koha/Item.pm +++ b/Koha/Item.pm @@ -45,6 +45,8 @@ use Koha::Plugins; use Koha::Libraries; use Koha::StockRotationItem; use Koha::StockRotationRotas; +use Koha::MarcSubfieldStructures; +use Koha::AuthorisedValues; use base qw(Koha::Object); @@ -1076,6 +1078,31 @@ sub _after_item_action_hooks { ); } +=head3 _fetch_authorised_values + +Retrieves for each column name the unblessed authorised value. + +=cut + +sub _fetch_authorised_values { + my ($self, $av_expand) = @_; + + my $columns_info = $self->_result->result_source->columns_info; + my $framworkcode = $self->biblio->frameworkcode; + # Handle not null and default values for integers and dates + my $avs = {}; + foreach my $col ( keys %{$columns_info} ) { + next unless defined $self->$col; + my $field = $self->_result->result_source->name.'.'.$col; + my $mss = Koha::MarcSubfieldStructures->find({frameworkcode => $framworkcode, kohafield => $field}); + if ($mss && $mss->authorised_value) { + my $av = Koha::AuthorisedValues->find({category => $mss->authorised_value, authorised_value => $self->$col}); + $avs->{$col} = $av->unblessed if $av; + }; + } + return $avs; +} + =head3 _type =cut diff --git a/Koha/REST/V1/Acquisitions/Orders.pm b/Koha/REST/V1/Acquisitions/Orders.pm index e104ce5dea..0bdf3c7cca 100644 --- a/Koha/REST/V1/Acquisitions/Orders.pm +++ b/Koha/REST/V1/Acquisitions/Orders.pm @@ -130,7 +130,10 @@ sub list { for my $f ( qw( isbn ean publisher ) ) { $reserved_params->{$q} =~ s|"biblio.$f":|"biblio.biblioitem.$f":|g; } - push @query_params_array, $reserved_params->{$q}; + push @query_params_array, $q eq 'query' + ? $reserved_params->{$q} + : decode_json( $reserved_params->{$q} ); + } if(scalar(@query_params_array) > 1) { @@ -157,7 +160,7 @@ sub list { return $c->render( status => 200, - openapi => $orders->to_api({ embed => $embed }) + openapi => $orders->to_api({ embed => $embed, av_expand => $c->req->headers->header('x-koha-av') }) ); } catch { diff --git a/Koha/REST/V1/Items.pm b/Koha/REST/V1/Items.pm index 4781024b36..1fb0738adf 100644 --- a/Koha/REST/V1/Items.pm +++ b/Koha/REST/V1/Items.pm @@ -66,16 +66,19 @@ sub get { my $c = shift->openapi->valid_input or return; try { - my $item = Koha::Items->find($c->validation->param('item_id')); + my $items_set = Koha::Items->new; + my $id = $c->validation->param('item_id'); + my $item = $c->objects->find( $items_set, $id ); unless ( $item ) { return $c->render( status => 404, openapi => { error => 'Item not found'} ); } - return $c->render( status => 200, openapi => $item->to_api ); + return $c->render( status => 200, openapi => $item ); } catch { + print $_->message; $c->unhandled_exception($_); }; } diff --git a/Koha/Schema/Result/Aqorder.pm b/Koha/Schema/Result/Aqorder.pm index 58cbdd1897..b2dcc3a529 100644 --- a/Koha/Schema/Result/Aqorder.pm +++ b/Koha/Schema/Result/Aqorder.pm @@ -800,6 +800,26 @@ __PACKAGE__->belongs_to( }, ); +=head2 creator + +Type: belongs_to + +Related object: L + +=cut + +__PACKAGE__->belongs_to( + "creator", + "Koha::Schema::Result::Borrower", + { borrowernumber => "created_by" }, + { + is_deferrable => 1, + join_type => "LEFT", + on_delete => "SET NULL", + on_update => "CASCADE", + }, +); + __PACKAGE__->belongs_to( "subscription", "Koha::Schema::Result::Subscription", diff --git a/acqui/finishreceive.pl b/acqui/finishreceive.pl index 961e3d566f..362eb61ef3 100755 --- a/acqui/finishreceive.pl +++ b/acqui/finishreceive.pl @@ -73,6 +73,7 @@ if (C4::Context->preference("CurrencyFormat") eq 'FR') { $unitprice = Koha::Number::Price->new( $unitprice )->unformat(); $replacementprice = Koha::Number::Price->new( $replacementprice )->unformat(); my $order_obj = Koha::Acquisition::Orders->find( $ordernumber ); + my $basket = $order_obj->basket; #need old receivedate if we update the order, parcel.pl only shows the right parcel this way FIXME @@ -116,6 +117,7 @@ if ($quantityrec > $origquantityrec ) { # Quantity can only be modified if linked to a subscription $order->{quantity} = $quantity; # quantityrec will be deduced from this value in ModReceiveOrder } + ( $datereceived, $new_ordernumber ) = ModReceiveOrder( { biblionumber => $biblionumber, diff --git a/acqui/orderreceive.pl b/acqui/orderreceive.pl index 9d9028c64f..3e1552ac77 100755 --- a/acqui/orderreceive.pl +++ b/acqui/orderreceive.pl @@ -87,6 +87,7 @@ my $invoice = GetInvoice($invoiceid); my $booksellerid = $invoice->{booksellerid}; my $freight = $invoice->{shipmentcost}; my $ordernumber = $input->param('ordernumber'); +my $multiple_orders = $input->param('multiple_orders'); my $bookseller = Koha::Acquisition::Booksellers->find( $booksellerid ); my $order = Koha::Acquisition::Orders->find( $ordernumber ); @@ -101,13 +102,61 @@ my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user( } ); -unless ( $order ) { +unless ( $order || $multiple_orders ) { output_html_with_http_headers $input, $cookie, $template->output; exit; } -# prepare the form for receiving -my $basket = $order->basket; +my $budget; +if( $order ) { + # prepare the form for receiving + my $creator = Koha::Patrons->find( $order->created_by ); + + $budget = GetBudget( $order->budget_id ); + + my $datereceived = $order->datereceived ? dt_from_string( $order->datereceived ) : dt_from_string; + + my $order_internalnote = $order->order_internalnote; + my $order_vendornote = $order->order_vendornote; + if ( $order->subscriptionid ) { + # Order from a subscription, we will display an history of what has been received + my $orders = Koha::Acquisition::Orders->search( + { + subscriptionid => $order->subscriptionid, + parent_ordernumber => $order->ordernumber, + ordernumber => { '!=' => $order->ordernumber } + } + ); + if ( $order->parent_ordernumber != $order->ordernumber ) { + my $parent_order = Koha::Acquisition::Orders->find($order->parent_ordernumber); + $order_internalnote = $parent_order->order_internalnote; + $order_vendornote = $parent_order->order_vendornote; + } + $template->param( + orders => $orders, + ); + } + + my $suggestion = GetSuggestionInfoFromBiblionumber($order->biblionumber); + + if ( $suggestion ) { + $template->param( suggestion => $suggestion ); + } + + $template->param( + order => $order, + creator => $creator, + bookfund => $budget->{budget_name}, + datereceived => $datereceived, + order_internalnote => $order_internalnote, + order_vendornote => $order_vendornote, + ); +} + +if( $multiple_orders ) { + $template->param(multiple_orders => $multiple_orders); +} + my $currencies = Koha::Acquisition::Currencies->search; my $active_currency = $currencies->get_active; @@ -117,66 +166,27 @@ unless($acq_fw) { $template->param('NoACQframework' => 1); } - -my $creator = Koha::Patrons->find( $order->created_by ); - -my $budget = GetBudget( $order->budget_id ); - -my $datereceived = $order->datereceived ? dt_from_string( $order->datereceived ) : dt_from_string; - # get option values for TaxRates syspref my @gst_values = map { option => $_ + 0.0 }, split( '\|', C4::Context->preference("TaxRates") ); -my $order_internalnote = $order->order_internalnote; -my $order_vendornote = $order->order_vendornote; -if ( $order->subscriptionid ) { - # Order from a subscription, we will display an history of what has been received - my $orders = Koha::Acquisition::Orders->search( - { - subscriptionid => $order->subscriptionid, - parent_ordernumber => $order->ordernumber, - ordernumber => { '!=' => $order->ordernumber } - } - ); - if ( $order->parent_ordernumber != $order->ordernumber ) { - my $parent_order = Koha::Acquisition::Orders->find($order->parent_ordernumber); - $order_internalnote = $parent_order->order_internalnote; - $order_vendornote = $parent_order->order_vendornote; - } - $template->param( - orders => $orders, - ); -} - $template->param( - order => $order, freight => $freight, name => $bookseller->name, active_currency => $active_currency, currencies => scalar $currencies->search({ rate => { '!=' => 1 } }), invoiceincgst => $bookseller->invoiceincgst, - bookfund => $budget->{budget_name}, - creator => $creator, invoiceid => $invoice->{invoiceid}, invoice => $invoice->{invoicenumber}, - datereceived => $datereceived, - order_internalnote => $order_internalnote, - order_vendornote => $order_vendornote, gst_values => \@gst_values, ); -my $suggestion = GetSuggestionInfoFromBiblionumber($order->{biblionumber}); -if ( $suggestion ) { - $template->param( suggestion => $suggestion ); -} - my $patron = Koha::Patrons->find( $loggedinuser )->unblessed; my @budget_loop; my $periods = GetBudgetPeriods( ); foreach my $period (@$periods) { - if ($period->{'budget_period_id'} == $budget->{'budget_period_id'}) { + if ($budget && $period->{'budget_period_id'} == $budget->{'budget_period_id'}) { $template->{'VARS'}->{'budget_period_description'} = $period->{'budget_period_description'}; } next if $period->{'budget_period_locked'} || !$period->{'budget_period_description'}; @@ -191,7 +201,7 @@ foreach my $period (@$periods) { { b_id => $r->{budget_id}, b_txt => $r->{budget_name}, - b_sel => ( $r->{budget_id} == $order->{budget_id} ) ? 1 : 0, + b_sel => ( $order && $r->{budget_id} == $order->{budget_id} ) ? 1 : 0, }; } diff --git a/api/v1/swagger/definitions/item.json b/api/v1/swagger/definitions/item.json index 14c110714e..53111bb9bd 100644 --- a/api/v1/swagger/definitions/item.json +++ b/api/v1/swagger/definitions/item.json @@ -180,6 +180,18 @@ "exclude_from_local_holds_priority": { "type": "boolean", "description": "Exclude this item from local holds priority." + }, + "home_branch": { + "type": ["object", "null"] + }, + "holding_branch": { + "type": ["object", "null"] + }, + "itemtype": { + "type": ["object", "null"] + }, + "_authorised_values": { + "type": ["object", "null"] } }, "additionalProperties": false, diff --git a/api/v1/swagger/definitions/order.json b/api/v1/swagger/definitions/order.json index 482decb1f1..f5fa90e62f 100644 --- a/api/v1/swagger/definitions/order.json +++ b/api/v1/swagger/definitions/order.json @@ -329,6 +329,15 @@ "object", "null" ] + }, + "creator": { + "type": [ + "object", + "null" + ] + }, + "_authorised_values": { + "type": "object" } }, "additionalProperties": false diff --git a/api/v1/swagger/paths/acquisitions_orders.json b/api/v1/swagger/paths/acquisitions_orders.json index 3812f2cf66..95858d7763 100644 --- a/api/v1/swagger/paths/acquisitions_orders.json +++ b/api/v1/swagger/paths/acquisitions_orders.json @@ -124,10 +124,15 @@ "biblio.items+count", "biblio.suggestions.suggester", "fund", + "fund.budget", "current_item_level_holds+count", "invoice", "items", - "subscription" + "items.home_branch", + "items.holding_branch", + "items.itemtype", + "subscription", + "creator" ] }, "post": { diff --git a/api/v1/swagger/paths/items.json b/api/v1/swagger/paths/items.json index 86197eadf1..2f3569d01b 100644 --- a/api/v1/swagger/paths/items.json +++ b/api/v1/swagger/paths/items.json @@ -122,7 +122,12 @@ "permissions": { "catalogue": "1" } - } + }, + "x-koha-embed": [ + "itemtype", + "home_branch", + "holding_branch" + ] } } } diff --git a/koha-tmpl/intranet-tmpl/lib/datatables/dataTables.select.min.js b/koha-tmpl/intranet-tmpl/lib/datatables/dataTables.select.min.js new file mode 100644 index 0000000000..3765f6ce5d --- /dev/null +++ b/koha-tmpl/intranet-tmpl/lib/datatables/dataTables.select.min.js @@ -0,0 +1,38 @@ +/*! + Copyright 2015-2019 SpryMedia Ltd. + + This source file is free software, available under the following license: + MIT license - http://datatables.net/license/mit + + This source file 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 license files for details. + + For details please refer to: http://www.datatables.net/extensions/select + Select for DataTables 1.3.1 + 2015-2019 SpryMedia Ltd - datatables.net/license/mit +*/ +(function(f){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(k){return f(k,window,document)}):"object"===typeof exports?module.exports=function(k,p){k||(k=window);p&&p.fn.dataTable||(p=require("datatables.net")(k,p).$);return f(p,k,k.document)}:f(jQuery,window,document)})(function(f,k,p,h){function z(a,b,c){var d=function(c,b){if(c>b){var d=b;b=c;c=d}var e=!1;return a.columns(":visible").indexes().filter(function(a){a===c&&(e=!0);return a===b?(e=!1,!0):e})};var e= +function(c,b){var d=a.rows({search:"applied"}).indexes();if(d.indexOf(c)>d.indexOf(b)){var e=b;b=c;c=e}var f=!1;return d.filter(function(a){a===c&&(f=!0);return a===b?(f=!1,!0):f})};a.cells({selected:!0}).any()||c?(d=d(c.column,b.column),c=e(c.row,b.row)):(d=d(0,b.column),c=e(0,b.row));c=a.cells(c,d).flatten();a.cells(b,{selected:!0}).any()?a.cells(c).deselect():a.cells(c).select()}function v(a){var b=a.settings()[0]._select.selector;f(a.table().container()).off("mousedown.dtSelect",b).off("mouseup.dtSelect", +b).off("click.dtSelect",b);f("body").off("click.dtSelect"+a.table().node().id.replace(/[^a-zA-Z0-9\-_]/g,"-"))}function A(a){var b=f(a.table().container()),c=a.settings()[0],d=c._select.selector,e;b.on("mousedown.dtSelect",d,function(a){if(a.shiftKey||a.metaKey||a.ctrlKey)b.css("-moz-user-select","none").one("selectstart.dtSelect",d,function(){return!1});k.getSelection&&(e=k.getSelection())}).on("mouseup.dtSelect",d,function(){b.css("-moz-user-select","")}).on("click.dtSelect",d,function(c){var b= +a.select.items();if(e){var d=k.getSelection();if((!d.anchorNode||f(d.anchorNode).closest("table")[0]===a.table().node())&&d!==e)return}d=a.settings()[0];var l=f.trim(a.settings()[0].oClasses.sWrapper).replace(/ +/g,".");if(f(c.target).closest("div."+l)[0]==a.table().container()&&(l=a.cell(f(c.target).closest("td, th")),l.any())){var g=f.Event("user-select.dt");m(a,g,[b,l,c]);g.isDefaultPrevented()||(g=l.index(),"row"===b?(b=g.row,w(c,a,d,"row",b)):"column"===b?(b=l.index().column,w(c,a,d,"column", +b)):"cell"===b&&(b=l.index(),w(c,a,d,"cell",b)),d._select_lastCell=g)}});f("body").on("click.dtSelect"+a.table().node().id.replace(/[^a-zA-Z0-9\-_]/g,"-"),function(b){!c._select.blurable||f(b.target).parents().filter(a.table().container()).length||0===f(b.target).parents("html").length||f(b.target).parents("div.DTE").length||r(c,!0)})}function m(a,b,c,d){if(!d||a.flatten().length)"string"===typeof b&&(b+=".dt"),c.unshift(a),f(a.table().node()).trigger(b,c)}function B(a){var b=a.settings()[0];if(b._select.info&& +b.aanFeatures.i&&"api"!==a.select.style()){var c=a.rows({selected:!0}).flatten().length,d=a.columns({selected:!0}).flatten().length,e=a.cells({selected:!0}).flatten().length,l=function(b,c,d){b.append(f('').append(a.i18n("select."+c+"s",{_:"%d "+c+"s selected",0:"",1:"1 "+c+" selected"},d)))};f.each(b.aanFeatures.i,function(b,a){a=f(a);b=f('');l(b,"row",c);l(b,"column",d);l(b,"cell",e);var g=a.children("span.select-info");g.length&&g.remove(); +""!==b.text()&&a.append(b)})}}function D(a){var b=new g.Api(a);a.aoRowCreatedCallback.push({fn:function(b,d,e){d=a.aoData[e];d._select_selected&&f(b).addClass(a._select.className);b=0;for(e=a.aoColumns.length;bg){var u=g;g=d;d=u}e.splice(g+1,e.length);e.splice(0,d)}else e.splice(f.inArray(c,e)+1,e.length);a[b](c,{selected:!0}).any()?(e.splice(f.inArray(c,e),1),a[b+"s"](e).deselect()):a[b+"s"](e).select()}function r(a,b){if(b||"single"===a._select.style)a=new g.Api(a),a.rows({selected:!0}).deselect(),a.columns({selected:!0}).deselect(),a.cells({selected:!0}).deselect()}function w(a,b,c,d,e){var f=b.select.style(),g=b.select.toggleable(),h=b[d](e,{selected:!0}).any();if(!h||g)"os"===f?a.ctrlKey|| +a.metaKey?b[d](e).select(!h):a.shiftKey?"cell"===d?z(b,e,c._select_lastCell||null):C(b,d,e,c._select_lastCell?c._select_lastCell[d]:null):(a=b[d+"s"]({selected:!0}),h&&1===a.flatten().length?b[d](e).deselect():(a.deselect(),b[d](e).select())):"multi+shift"==f?a.shiftKey?"cell"===d?z(b,e,c._select_lastCell||null):C(b,d,e,c._select_lastCell?c._select_lastCell[d]:null):b[d](e).select(!h):b[d](e).select(!h)}function t(a,b){return function(c){return c.i18n("buttons."+a,b)}}function x(a){a=a._eventNamespace; +return"draw.dt.DT"+a+" select.dt.DT"+a+" deselect.dt.DT"+a}function E(a,b){return-1!==f.inArray("rows",b.limitTo)&&a.rows({selected:!0}).any()||-1!==f.inArray("columns",b.limitTo)&&a.columns({selected:!0}).any()||-1!==f.inArray("cells",b.limitTo)&&a.cells({selected:!0}).any()?!0:!1}var g=f.fn.dataTable;g.select={};g.select.version="1.3.1";g.select.init=function(a){var b=a.settings()[0],c=b.oInit.select,d=g.defaults.select;c=c===h?d:c;d="row";var e="api",l=!1,u=!0,k=!0,m="td, th",p="selected",n=!1; +b._select={};!0===c?(e="os",n=!0):"string"===typeof c?(e=c,n=!0):f.isPlainObject(c)&&(c.blurable!==h&&(l=c.blurable),c.toggleable!==h&&(u=c.toggleable),c.info!==h&&(k=c.info),c.items!==h&&(d=c.items),e=c.style!==h?c.style:"os",n=!0,c.selector!==h&&(m=c.selector),c.className!==h&&(p=c.className));a.select.selector(m);a.select.items(d);a.select.style(e);a.select.blurable(l);a.select.toggleable(u);a.select.info(k);b._select.className=p;f.fn.dataTable.ext.order["select-checkbox"]=function(b,a){return this.api().column(a, +{order:"index"}).nodes().map(function(a){return"row"===b._select.items?f(a).parent().hasClass(b._select.className):"cell"===b._select.items?f(a).hasClass(b._select.className):!1})};!n&&f(a.table().node()).hasClass("selectable")&&a.select.style("os")};f.each([{type:"row",prop:"aoData"},{type:"column",prop:"aoColumns"}],function(a,b){g.ext.selector[b.type].push(function(a,d,e){d=d.selected;var c=[];if(!0!==d&&!1!==d)return e;for(var f=0,g=e.length;ftr.selected,table.dataTable tbody>tr>.selected{background-color:#B0BED9}table.dataTable.stripe tbody>tr.odd.selected,table.dataTable.stripe tbody>tr.odd>.selected,table.dataTable.display tbody>tr.odd.selected,table.dataTable.display tbody>tr.odd>.selected{background-color:#acbad4}table.dataTable.hover tbody>tr.selected:hover,table.dataTable.hover tbody>tr>.selected:hover,table.dataTable.display tbody>tr.selected:hover,table.dataTable.display tbody>tr>.selected:hover{background-color:#aab7d1}table.dataTable.order-column tbody>tr.selected>.sorting_1,table.dataTable.order-column tbody>tr.selected>.sorting_2,table.dataTable.order-column tbody>tr.selected>.sorting_3,table.dataTable.order-column tbody>tr>.selected,table.dataTable.display tbody>tr.selected>.sorting_1,table.dataTable.display tbody>tr.selected>.sorting_2,table.dataTable.display tbody>tr.selected>.sorting_3,table.dataTable.display tbody>tr>.selected{background-color:#acbad5}table.dataTable.display tbody>tr.odd.selected>.sorting_1,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_1{background-color:#a6b4cd}table.dataTable.display tbody>tr.odd.selected>.sorting_2,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_2{background-color:#a8b5cf}table.dataTable.display tbody>tr.odd.selected>.sorting_3,table.dataTable.order-column.stripe tbody>tr.odd.selected>.sorting_3{background-color:#a9b7d1}table.dataTable.display tbody>tr.even.selected>.sorting_1,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_1{background-color:#acbad5}table.dataTable.display tbody>tr.even.selected>.sorting_2,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_2{background-color:#aebcd6}table.dataTable.display tbody>tr.even.selected>.sorting_3,table.dataTable.order-column.stripe tbody>tr.even.selected>.sorting_3{background-color:#afbdd8}table.dataTable.display tbody>tr.odd>.selected,table.dataTable.order-column.stripe tbody>tr.odd>.selected{background-color:#a6b4cd}table.dataTable.display tbody>tr.even>.selected,table.dataTable.order-column.stripe tbody>tr.even>.selected{background-color:#acbad5}table.dataTable.display tbody>tr.selected:hover>.sorting_1,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_1{background-color:#a2aec7}table.dataTable.display tbody>tr.selected:hover>.sorting_2,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_2{background-color:#a3b0c9}table.dataTable.display tbody>tr.selected:hover>.sorting_3,table.dataTable.order-column.hover tbody>tr.selected:hover>.sorting_3{background-color:#a5b2cb}table.dataTable.display tbody>tr:hover>.selected,table.dataTable.display tbody>tr>.selected:hover,table.dataTable.order-column.hover tbody>tr:hover>.selected,table.dataTable.order-column.hover tbody>tr>.selected:hover{background-color:#a2aec7}table.dataTable tbody td.select-checkbox,table.dataTable tbody th.select-checkbox{position:relative}table.dataTable tbody td.select-checkbox:before,table.dataTable tbody td.select-checkbox:after,table.dataTable tbody th.select-checkbox:before,table.dataTable tbody th.select-checkbox:after{display:block;position:absolute;top:1.2em;left:50%;width:12px;height:12px;box-sizing:border-box}table.dataTable tbody td.select-checkbox:before,table.dataTable tbody th.select-checkbox:before{content:' ';margin-top:-6px;margin-left:-6px;border:1px solid black;border-radius:3px}table.dataTable tr.selected td.select-checkbox:after,table.dataTable tr.selected th.select-checkbox:after{content:'\2714';margin-top:-11px;margin-left:-4px;text-align:center;text-shadow:1px 1px #B0BED9, -1px -1px #B0BED9, 1px -1px #B0BED9, -1px 1px #B0BED9}div.dataTables_wrapper span.select-info,div.dataTables_wrapper span.select-item{margin-left:0.5em}@media screen and (max-width: 640px){div.dataTables_wrapper span.select-info,div.dataTables_wrapper span.select-item{margin-left:0;display:block}} diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc index a545868ce7..b411a7b60e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc @@ -2,4 +2,5 @@ [% USE Asset %] [% INCLUDE 'format_price.inc' %] [% Asset.js("lib/datatables/datatables.min.js") | $raw %] +[% Asset.js("lib/datatables/dataTables.select.min.js") | $raw %] [% Asset.js("js/datatables.js") | $raw %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc index c2833e3009..4e03000b0a 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc @@ -18,6 +18,7 @@ [% Asset.css("lib/bootstrap/bootstrap-theme.min.css") | $raw %] [% Asset.css("lib/font-awesome/css/font-awesome.min.css") | $raw %] [% Asset.css("lib/datatables/datatables.min.css") | $raw %] +[% Asset.css("lib/datatables/select.dataTables.min.css") | $raw %] [% Asset.css("css/print.css", { media = "print" }) | $raw %] [% INCLUDE intranetstylesheet.inc %] [% IF ( bidi ) %][% Asset.css("css/right-to-left.css") | $raw %][% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt index ae3a49e5a8..f3b76219d9 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/orderreceive.tt @@ -15,17 +15,17 @@ [% INCLUDE 'header.inc' %] [% INCLUDE 'acquisitions-search.inc' %] - +
- [% AcqCreateItem = order.basket.effective_create_items %]
-

Receive items from : [% name | html %] [% IF ( invoice ) %][[% invoice | html %]] [% END %] (order #[% order.ordernumber | html %])

+

Receive items from : [% name | html %] [% IF ( invoice ) %][[% invoice | html %]] [% END %] (order #[% order.ordernumber || multiple_orders | html %])

[% IF ( order ) %] + [% AcqCreateItem = order.basket.effective_create_items %]
@@ -289,7 +289,7 @@ [% IF ( order.items.count ) %] [% ELSE %] - + [% END %] [% END %] @@ -350,7 +350,7 @@
  • - + [% IF currencies.count %] Cancel
  • +[% ELSIF multiple_orders %] + + + + + + + + + + + + +
    Order + TitleAuthorISBNDate receivedFundQuantity 
    + +
    +
    + + Return +
    +
    Job progress:
    0%
    +
    +
    + + [% ELSE %] This ordernumber does not exist. [% END %] @@ -387,10 +658,48 @@
    [% MACRO jsinclude BLOCK %] [% Asset.js("js/acquisitions-menu.js") | $raw %] -[% INCLUDE 'calendar.inc' %] + [% INCLUDE 'calendar.inc' %] [% Asset.js("js/additem.js") | $raw %] [% Asset.js("js/cataloging.js") | $raw %] + [% INCLUDE 'datatables.inc' %] + [% INCLUDE 'js-date-format.inc' %] + [% INCLUDE 'format_price.inc' %] + [% Asset.js("lib/jquery/plugins/jquery.dataTables.columnFilter.js") | $raw %] + [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcel.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcel.tt index 855b044d50..c1634aabd5 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcel.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcel.tt @@ -102,6 +102,9 @@ + [% IF Koha.Preference('AcqReceiveMultipleOrderLines') %] + + [% END %] @@ -117,6 +120,11 @@
    Basket Basket group Order line
    + [% IF Koha.Preference('AcqReceiveMultipleOrderLines') %] +
    + +
    + [% END %]
    [% ELSE %]

    @@ -330,8 +338,10 @@ [% Asset.js("lib/jquery/plugins/jquery.dataTables.columnFilter.js") | $raw %] [% Asset.js("lib/jquery/plugins/jquery.cookie.min.js") | $raw %] +