From 1c4ea60e0e446dcdc5a6524a8c1cb1c0c9bf9537 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Tue, 18 Apr 2023 14:09:47 +0200 Subject: [PATCH] Bug 33568: Status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FIXME We need tests here! See the FIXME in the code, we are losing the ability to search on the status, but this is really impossible to implement if we are not storing the status (DB or search engine). Signed-off-by: Owen Leonard Signed-off-by: Laurence Rault Signed-off-by: Emily Lamancusa Signed-off-by: Tomás Cohen Arazi --- Koha/Item.pm | 12 ++ Koha/Template/Plugin/AuthorisedValues.pm | 4 +- api/v1/swagger/definitions/item.yaml | 28 +++++ api/v1/swagger/paths/biblios.yaml | 10 ++ .../prog/en/modules/catalogue/detail.tt | 109 +++++++++++++++++- 5 files changed, 155 insertions(+), 8 deletions(-) diff --git a/Koha/Item.pm b/Koha/Item.pm index f677abac769..b3fc8d56525 100644 --- a/Koha/Item.pm +++ b/Koha/Item.pm @@ -767,6 +767,10 @@ sub get_transfer { return Koha::Item::Transfer->_new_from_dbic($transfer) if $transfer; } +sub transfer { + return shift->get_transfer(@_); +} + =head3 get_transfers my $transfer = $item->get_transfers; @@ -1049,6 +1053,11 @@ sub current_holds { return Koha::Holds->_new_from_dbic($hold_rs); } +sub first_hold { + my ( $self ) = @_; + return $self->current_holds->next; +} + =head3 stockrotationitem my $sritem = Koha::Item->stockrotationitem; @@ -1744,6 +1753,9 @@ sub itemtype { return Koha::ItemTypes->find( $self->effective_itemtype ); } +sub item_type { + return shift->itemtype; +} =head3 orders diff --git a/Koha/Template/Plugin/AuthorisedValues.pm b/Koha/Template/Plugin/AuthorisedValues.pm index 5cb91b83a3c..4e74c1bbad5 100644 --- a/Koha/Template/Plugin/AuthorisedValues.pm +++ b/Koha/Template/Plugin/AuthorisedValues.pm @@ -69,8 +69,8 @@ sub GetCategories { sub GetDescriptionsByKohaField { my ( $self, $params ) = @_; - return Koha::AuthorisedValues->get_descriptions_by_koha_field( - { kohafield => $params->{kohafield} } ); + return [ Koha::AuthorisedValues->get_descriptions_by_koha_field( + { kohafield => $params->{kohafield} } ) ]; } sub GetDescriptionByKohaField { diff --git a/api/v1/swagger/definitions/item.yaml b/api/v1/swagger/definitions/item.yaml index bb5a96ffb5e..1c816f21b27 100644 --- a/api/v1/swagger/definitions/item.yaml +++ b/api/v1/swagger/definitions/item.yaml @@ -242,6 +242,34 @@ properties: type: - object - "null" + checkout: + type: + - object + - "null" + transfer: + type: + - object + - "null" + first_hold: + type: + - object + - "null" + recall: + type: + - object + - "null" + item_type: + type: + - object + - "null" + in_bundle: + type: + - boolean + - "null" + bundle_host: + type: + - object + - "null" _strings: type: - object diff --git a/api/v1/swagger/paths/biblios.yaml b/api/v1/swagger/paths/biblios.yaml index a15997e3ba7..101fa172ed0 100644 --- a/api/v1/swagger/paths/biblios.yaml +++ b/api/v1/swagger/paths/biblios.yaml @@ -423,6 +423,16 @@ type: string enum: - +strings + - checkout + - checkout.patron + - transfer + - first_hold + - first_hold.patron + - recall + - recall.patron + - item_type + - in_bundle + - bundle_host - cover_image_ids - item_group_item.item_group.description - serialitem.serial diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt index 73499267cee..d05b58c37be 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -2485,11 +2485,16 @@ }); [% END %] - const can_edit_items_from = [% To.json(can_edit_items_from) | $raw %]; + const can_edit_items_from = [% To.json(can_edit_items_from || {}) | $raw %]; const item_type_image_locations = [% To.json(item_type_image_locations) | $raw %]; const av_loc = new Map([% To.json(AuthorisedValues.Get('LOC')) | $raw %].map( av => [av.authorised_value, av.lib])); + const av_lost = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.itemlost' })) | $raw %].map( av => [av.authorised_value, av.lib])); + const av_withdrawn = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.withdrawn' })) | $raw %].map( av => [av.authorised_value, av.lib])); + const av_damaged = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.damaged' })) | $raw %].map( av => [av.authorised_value, av.lib])); + const av_not_for_loan= new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.notforloan' })) | $raw %].map( av => [av.authorised_value, av.lib])); + const av_restricted = new Map([% To.json(AuthorisedValues.GetDescriptionsByKohaField({ kohafield => 'items.restricted' })) | $raw %].map( av => [av.authorised_value, av.lib])); let table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?"; - let embed = ["+strings"]; + let embed = ["+strings,checkout,checkout.patron,transfer,first_hold,first_hold.patron,item_type"]; [% IF Koha.Preference('LocalCoverImages') %] embed.push('cover_image_ids'); [% END %] @@ -2499,6 +2504,10 @@ [% IF biblio.serial %] embed.push('serialitem.serial'); [% END %] + [% IF Koha.Preference('UseRecalls') %] + embed.push('recall', 'recall.patron') + [% END %] + embed.push('in_bundle', 'bundle_host'); let table_settings = [% TablesSettings.GetTableSettings('catalogue', 'detail','holdings_table','json') | $raw %]; var items_table = $("#table_items").kohaTable({ ajax: { url: table_url }, @@ -2659,12 +2668,100 @@ } }, { - data: "", + data: "me.lost_status", className: "status", - searchable: false, // FIXME - orderable: true, + searchable: false, // FIXME We are losing the ability to search on the status + orderable: false, render: function (data, type, row, meta) { - return "status"; // FIXME Display status + let nodes = ""; + if ( row.checkout ) { + nodes += ''; + if ( row.checkout.onsite_checkout ) { + if ( can_edit_items_from[row.holding_library_id] ){ + let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %] + nodes += _("Currently in local use by %s").format(patron_to_html); + } else { + nodes += _("Currently in local use"); + } + } else { + nodes += ''; + if ( can_edit_items_from[row.holding_library_id] ){ + let patron_to_html = $patron_to_html(row.checkout.patron); [%# FIXME What about hide_patron_infos_if_needed?? %] + nodes += _("Checked out to %s").format(patron_to_html); + } else { + nodes += _("Checked out"); + } + } + nodes += ': '; + nodes += _("due %s").format($date(row.checkout.due_date)); [%# FIXME Missing due date formatting here, $date do not have as_due_date option %] + nodes += "" + } else if ( row.transfer ) { + if ( row.transfer.datesent ) { + nodes += '%s'.format(_("In transit from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.datesent))); [%# FIXME display library names, not codes, do we use _strings here? %] + } else { + nodes += '%s'.format(_("Transit pending from %s to %s since %s").format(row.transfer.frombranch, row.transfer.tobranch, $date(row.transfer.daterequested))); [%# FIXME See above %] + } + } + + if ( row.lost_status ) { + let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing"); + nodes += '%s'.format(lost_lib); + } + + if ( row.withdrawn ) { + let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn"); + nodes += '%s'.format(withdrawn_lib); + } + + if ( row.damaged ) { + let damaged_lib = av_damaged.get(row.damaged.toString()) || _("Damaged"); + nodes += '%s'.format(damaged_lib); + } + + if ( row.not_for_loan_status || row.item_type.notforloan ) { + let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString()); + nodes += '%s'.format(_("Not for loan")) + ( not_for_loan_lib ? ' (%s)'.format(not_for_loan_lib) : '' ) + ''; + } + + if ( row.first_hold ) { + if ( row.first_hold.waiting_date ) { + [%# FIXME Display library names instead of codes %] + [%# FIXME We lost the desk name, we need an additional embed %] + nodes += '%s'.format(_("Waiting at %s since %s.".format(row.first_hold.pickup_library_id, $date(row.first_hold.waiting_date)))); + [% IF Koha.Preference('canreservefromotherbranches') %] + if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) { + let patron_to_html = $patron_to_html(row.first_hold.patron); [%# FIXME What about hide_patron_infos_if_needed?? %] + nodes += ' %s'.format(_("Hold for: %s").format(patron_to_html)); + } + [% END %] + } else { + nodes += '%s'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority)); + } + } + + [% IF Koha.Preference('UseRecalls') %] + if ( row.recall ) { + if ( row.recall.waiting_date ) { + nodes += '%s'.format(_("Waiting at %s since %s").format(row.recall.pickup_library_id, $date(row.recall.waiting_date))); # FIXME Display library names instead of codes + } else { + let patron_to_html = $patron_to_html(row.recall.patron); + nodes += '%s'.format(_("recalled by %s on %s").format(patron_to_html, row.recall.created_date)); + } + } + [% END %] + + if ( ! ( row.not_for_loan_status || row.item_type.notforloan || row.checked_out_date || row.lost_status || row.withdrawn || row.damaged || row.transfer || row.first_hold || row.recall ) ) { + nodes += ' %s'.format(_("Available")) + } + + if ( row.restricted_status ) { + nodes += '(%s)'.format(av_restricted.get(row.restricted_status.toString())); + } + + if ( row.in_bundle ) { + nodes += '%s'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true }))); + } + return nodes; } }, { -- 2.34.1