View | Details | Raw Unified | Return to bug 37334
Collapse All | Expand All

(-)a/Koha/Item.pm (+51 lines)
Lines 1435-1440 sub columns_to_str { Link Here
1435
    return $values;
1435
    return $values;
1436
}
1436
}
1437
1437
1438
sub _status {
1439
    my ($self) = @_;
1440
1441
    my @statuses;
1442
    if ( my $checkout = $self->checkout ) {
1443
        unless ( $checkout->onsite_checkout ) {
1444
            push @statuses, "checked_out";
1445
        } else {
1446
            push @statuses, "local_use";
1447
        }
1448
    } elsif ( my $transfer = $self->transfer ) {
1449
        if ( $transfer->datesent ) {
1450
            push @statuses, "in_transit";
1451
        } else {
1452
            push @statuses, "transit_pending";
1453
        }
1454
    }
1455
    if ( $self->itemlost ) {
1456
        push @statuses, 'lost';
1457
    }
1458
    if ( $self->withdrawn ) {
1459
        push @statuses, 'withdrawn';
1460
    }
1461
    if ( $self->damaged ) {
1462
        push @statuses, 'damaged';
1463
    }
1464
    if ( $self->notforloan || $self->item_type->notforloan ) {
1465
1466
        # TODO on a big Koha::Items loop we are going to join with item_type too often, use a cache
1467
        push @statuses, 'not_for_loan';
1468
    }
1469
    if ( $self->first_hold ) {
1470
        push @statuses, 'on_hold';
1471
    }
1472
    if ( C4::Context->preference('UseRecalls') && $self->recall ) {
1473
        push @statuses, 'recalled';
1474
    }
1475
1476
    unless (@statuses) {
1477
        push @statuses, 'available';
1478
    }
1479
1480
    if ( $self->restricted ) {
1481
        push @statuses, 'restricted';
1482
    }
1483
1484
    # TODO in_bundle?
1485
1486
    return join ',', @statuses;
1487
}
1488
1438
=head3 additional_attributes
1489
=head3 additional_attributes
1439
1490
1440
    my $attributes = $item->additional_attributes;
1491
    my $attributes = $item->additional_attributes;
(-)a/api/v1/swagger/definitions/item.yaml (-1 / +6 lines)
Lines 322-325 properties: Link Here
322
      - object
322
      - object
323
      - "null"
323
      - "null"
324
    description: A return claims object if one exists that's unresolved
324
    description: A return claims object if one exists that's unresolved
325
additionalProperties: false
325
  _status:
326
    type:
327
      - string
328
      - "null"
329
    description: The status of the item
330
additionalProperties: false
(-)a/api/v1/swagger/paths/biblios.yaml (-1 / +2 lines)
Lines 458-463 Link Here
458
          type: string
458
          type: string
459
          enum:
459
          enum:
460
            - +strings
460
            - +strings
461
            - _status
461
            - home_library
462
            - home_library
462
            - holding_library
463
            - holding_library
463
            - biblio.title
464
            - biblio.title
Lines 918-921 Link Here
918
      "503":
919
      "503":
919
        description: Under maintenance
920
        description: Under maintenance
920
        schema:
921
        schema:
921
          $ref: "../swagger.yaml#/definitions/error"
922
          $ref: "../swagger.yaml#/definitions/error"
(-)a/koha-tmpl/intranet-tmpl/prog/en/includes/html_helpers/tables/items/catalogue_detail.inc (-68 / +69 lines)
Lines 240-246 Link Here
240
        [%# In case or SeparateHoldings we may need to display the number of biblios in each tab %]
240
        [%# In case or SeparateHoldings we may need to display the number of biblios in each tab %]
241
        [%# Do we need separate/new endpoints or do we hack the somewhere client-side? %]
241
        [%# Do we need separate/new endpoints or do we hack the somewhere client-side? %]
242
        let item_table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?";
242
        let item_table_url = "/api/v1/biblios/[% biblio.biblionumber | uri %]/items?";
243
        let embed = ["+strings,home_library,holding_library,checkout,checkout.patron,transfer,transfer+strings,first_hold,first_hold+strings,first_hold.patron,first_hold.desk"];
243
        let embed = ["+strings,_status,home_library,holding_library,checkout,checkout.patron,transfer,transfer+strings,first_hold,first_hold+strings,first_hold.patron,first_hold.desk"];
244
        [% IF Koha.Preference('LocalCoverImages') %]
244
        [% IF Koha.Preference('LocalCoverImages') %]
245
            embed.push('cover_image_ids');
245
            embed.push('cover_image_ids');
246
        [% END %]
246
        [% END %]
Lines 485-566 Link Here
485
                    }
485
                    }
486
                },
486
                },
487
                {
487
                {
488
                    data: "me.lost_status",
488
                    data: "me._status",
489
                    className: "status",
489
                    className: "status",
490
                    searchable: false, // FIXME We are losing the ability to search on the status
490
                    searchable: false, // FIXME We are losing the ability to search on the status
491
                    orderable: false,
491
                    orderable: false,
492
                    render: function (data, type, row, meta) {
492
                    render: function (data, type, row, meta) {
493
                        let nodes = "";
493
                        let nodes = "";
494
                        if ( row.checkout ) {
494
                        row._status.split(",").forEach( status => {
495
                            [%# Hacky for patron_to_html in case we simply want to display the patron's library name %]
495
                            if ( status == 'checked_out' || status == 'local_use') {
496
                            row.checkout.patron.library = { name: libraries_names.get(row.checkout.patron.library_id) };
496
                                nodes += '<span>';
497
497
498
                            nodes += '<span>';
498
                                [%# Hacky for patron_to_html in case we simply want to display the patron's library name %]
499
                            if ( row.checkout.onsite_checkout ) {
499
                                row.checkout.patron.library = { name: libraries_names.get(row.checkout.patron.library_id) };
500
                                let patron_to_html = $patron_to_html(row.checkout.patron, { url: true, display_cardnumber: true, hide_patron_name });
500
                                let patron_to_html = $patron_to_html(row.checkout.patron, { url: true, display_cardnumber: true, hide_patron_name });
501
                                nodes += _("Currently in local use by %s").format(patron_to_html);
501
502
                            } else {
502
                                if ( status == 'local_use' ) {
503
                                nodes += '<span class="holding_status datedue">';
503
                                    nodes += _("Currently in local use by %s").format(patron_to_html);
504
                                let patron_to_html = $patron_to_html(row.checkout.patron, { url: true, display_cardnumber: true, hide_patron_name });
504
                                } else {
505
                                nodes += _("Checked out to %s").format(patron_to_html);
505
                                    nodes += '<span class="datedue">';
506
                                    nodes += _("Checked out to %s").format(patron_to_html);
507
                                }
508
                                nodes += ': ';
509
                                nodes += _("due %s").format($date(row.checkout.due_date, { as_due_date: true }));
510
                                nodes += "</span>"
511
506
                            }
512
                            }
507
                            nodes += ': ';
513
                            if ( status == 'in_transit' ) {
508
                            nodes += _("due %s").format($date(row.checkout.due_date, { as_due_date: true }));
514
                                nodes += '<span class="intransit">%s</span>'.format(_("In transit from %s to %s since %s").format(escape_str(row.transfer._strings.from_library.str), escape_str(row.transfer._strings.to_library.str), $date(row.transfer.datesent)));
509
                            nodes += "</span>"
510
                        } else if ( row.transfer ) {
511
                            if ( row.transfer.datesent ) {
512
                                nodes += '<span class="holding_status intransit">%s</span>'.format(_("In transit from %s to %s since %s").format(escape_str(row.transfer._strings.from_library.str), escape_str(row.transfer._strings.to_library.str), $date(row.transfer.datesent)));
513
                            } else {
514
                                nodes += '<span class="holding_status transitrequested">%s</span>'.format(_("Transit pending from %s to %s since %s").format(escape_str(row.transfer._strings.from_library.str), escape_str(row.transfer._strings.to_library.str), $date(row.transfer.daterequested)));
515
                            }
515
                            }
516
                        }
517
516
518
                        if ( row.lost_status ) {
517
                            if ( status == 'transit_pending' ) {
519
                            let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing");
518
                                nodes += '<span class="transitrequested">%s</span>'.format(_("Transit pending from %s to %s since %s").format(escape_str(row.transfer._strings.from_library.str), escape_str(row.transfer._strings.to_library.str), $date(row.transfer.daterequested)));
520
                            nodes += '<span class="holding_status lost">%s</span>'.format(escape_str(lost_lib));
519
                            }
521
                            [% IF Koha.Preference('ClaimReturnedLostValue') %]
520
522
                                const hasReturnClaims = row.return_claims.filter(rc => !rc.resolution).length > 0 ? true : false
521
                            if ( status == 'lost' ) {
522
                                let lost_lib = av_lost.get(row.lost_status.toString()) || _("Unavailable (lost or missing");
523
                                nodes += '<span class="lost">%s</span>'.format(escape_str(lost_lib));
524
525
                                const hasReturnClaims = row.return_claims && row.return_claims.filter(rc => !rc.resolution).length > 0 ? true : false
523
                                if(hasReturnClaims) {
526
                                if(hasReturnClaims) {
524
                                    nodes += '<span class="holding_status claimed_returned">' + _("(Claimed returned)") + '</span>';
527
                                    nodes += '<span class="holding_status claimed_returned">' + _("(Claimed returned)") + '</span>';
525
                                }
528
                                }
526
                            [% END %]
529
                            }
527
                        }
528
530
529
                        if ( row.withdrawn ) {
531
                            if ( status == 'withdrawn' ) {
530
                            let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn");
532
                                let withdrawn_lib = av_withdrawn.get(row.withdrawn.toString()) || _("Withdrawn");
531
                            nodes += '<span class="holding_status wdn">%s</span>'.format(escape_str(withdrawn_lib));
533
                                nodes += '<span class="wdn">%s</span>'.format(escape_str(withdrawn_lib));
532
                        }
534
                            }
533
535
534
                        if ( row.damaged_status ) {
536
                            if ( status == 'damaged' ) {
535
                            let damaged_lib = av_damaged.get(row.damaged_status.toString()) || _("Damaged");
537
                                let damaged_lib = av_damaged.get(row.damaged_status.toString()) || _("Damaged");
536
                            nodes += '<span class="holding_status dmg">%s</span>'.format(escape_str(damaged_lib));
538
                                nodes += '<span class="dmg">%s</span>'.format(escape_str(damaged_lib));
537
                        }
539
                            }
538
540
539
                        if ( row.not_for_loan_status || item_types_notforloan.get(row.item_type_id) ) {
541
                            if ( status == 'not_for_loan' ) {
540
                            let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString());
542
                                let not_for_loan_lib = av_not_for_loan.get(row.not_for_loan_status.toString());
541
                            nodes += '<span class="holding_status notforloan">%s'.format(_("Not for loan")) + ( not_for_loan_lib ? '<span class="reason"> (%s)</span>'.format(escape_str(not_for_loan_lib)) : '' ) + '</span>';
543
                                nodes += '<span class="notforloan">%s'.format(_("Not for loan")) + ( not_for_loan_lib ? '<span class="reason"> (%s)</span>'.format(escape_str(not_for_loan_lib)) : '' ) + '</span>';
542
                        }
544
                            }
543
545
544
                        if ( row.first_hold ) {
546
                            if ( status == 'on_hold') {
545
                            if ( row.first_hold.waiting_date ) {
547
                                if ( row.first_hold.waiting_date ) {
546
                                if ( row.first_hold.desk ) {
548
                                    if ( row.first_hold.desk ) {
547
                                    nodes += '<span class="holding_status waitingat">%s</span>'.format(_("Waiting at %s, %s since %s.").format(row.first_hold._strings.pickup_library_id.str, row.first_hold.desk.desk_name, $date(row.first_hold.waiting_date)));
549
                                        nodes += '<span class="waitingat">%s</span>'.format(_("Waiting at %s, %s since %s.".format(row.first_hold._strings.pickup_library_id.str, row.first_hold.desk.desk_name, $date(row.first_hold.waiting_date))));
550
                                    } else {
551
                                        nodes += '<span class="waitingat">%s</span>'.format(_("Waiting at %s since %s.".format(row.first_hold._strings.pickup_library_id.str, $date(row.first_hold.waiting_date))));
552
                                    }
553
                                    [% IF Koha.Preference('canreservefromotherbranches') %]
554
                                        if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) {
555
                                            [%# Hacky for patron_to_html in case we simply want to display the patron's library name %]
556
                                            row.first_hold.patron.library = { name: libraries_names.get(row.first_hold.patron.library_id) };
557
558
                                            let patron_to_html = $patron_to_html(row.first_hold.patron, { url: true, display_cardnumber: true, hide_patron_name });
559
                                            nodes += ' <span class="heldfor">%s</span>'.format(_("Hold for: %s").format(patron_to_html));
560
                                        }
561
                                    [% END %]
548
                                } else {
562
                                } else {
549
                                    nodes += '<span class="holding_status waitingat">%s</span>'.format(_("Waiting at %s since %s.").format(row.first_hold._strings.pickup_library_id.str, $date(row.first_hold.waiting_date)));
563
                                    nodes += ' <span class="holdonitem">%s</span>'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority));
550
                                }
564
                                }
551
                                [% IF Koha.Preference('canreservefromotherbranches') %]
552
                                    if ( row.first_hold.waiting_date || row.first_hold.priority == 1 ) {
553
                                        [%# Hacky for patron_to_html in case we simply want to display the patron's library name %]
554
                                        row.first_hold.patron.library = { name: libraries_names.get(row.first_hold.patron.library_id) };
555
556
                                        let patron_to_html = $patron_to_html(row.first_hold.patron, { url: true, display_cardnumber: true, hide_patron_name });
557
                                        nodes += ' <span class="holding_status heldfor">%s</span>'.format(_("Hold for: %s").format(patron_to_html));
558
                                    }
559
                                [% END %]
560
                            } else {
561
                                nodes += ' <span class="holding_status holdonitem">%s</span>'.format(_("There is an item level hold on this item (priority = %s).").format(row.first_hold.priority));
562
                            }
565
                            }
563
                        }
564
566
565
                        [% IF Koha.Preference('UseRecalls') %]
567
                        [% IF Koha.Preference('UseRecalls') %]
566
                            if ( row.recall && ( row.item_id === row.recall.item_id ) ) {
568
                            if ( row.recall && ( row.item_id === row.recall.item_id ) ) {
Lines 575-592 Link Here
575
                                }
577
                                }
576
                            }
578
                            }
577
                        [% END %]
579
                        [% END %]
580
                            if ( status == 'available' ) {
581
                                nodes += ' <span>%s</span>'.format(_("Available"))
582
                            }
578
583
579
                        if ( ! ( row.not_for_loan_status || item_types_notforloan.get(row.item_type_id) || row.checked_out_date || row.lost_status || row.withdrawn || row.damaged_status || row.transfer || row.first_hold || ( row.recall && ( row.item_id === row.recall.item_id ) ) )) {
584
                            if ( status == 'restricted') {
580
                            nodes += ' <span class="holding_status available">%s</span>'.format(_("Available"))
585
                                nodes += '<span class="restricted">(%s)</span>'.format(escape_str(av_restricted.get(row.restricted_status.toString())));
581
                        }
586
                            }
582
583
                        if ( row.restricted_status ) {
584
                            nodes += '<span class="holding_status restricted">(%s)</span>'.format(escape_str(av_restricted.get(row.restricted_status.toString())));
585
                        }
586
587
587
                        if ( row.in_bundle ) {
588
                            if ( status == 'restricted') {
588
                            nodes += '<span class="holding_status bundled">%s</span>'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true })));
589
                                nodes += '<span class="bundled">%s</span>'.format(_("In bundle: %s").format($biblio_to_html(row.bundle_host.biblio, { link: true })));
589
                        }
590
                            }
591
                        });
590
                        return nodes;
592
                        return nodes;
591
                    }
593
                    }
592
                },
594
                },
593
- 

Return to bug 37334