From 385048f27ccb5eaeeac2e90130d621305a537960 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=utf8 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 Signed-off-by: Katrin Fischer --- 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 f677abac76..b3fc8d5652 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 5cb91b83a3..4e74c1bbad 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 bb5a96ffb5..1c816f21b2 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 a15997e3ba..101fa172ed 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 73499267ce..d05b58c37b 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.39.5