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

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/reserve/request.tt (+234 lines)
Lines 1235-1240 Link Here
1235
                            </select>
1235
                            </select>
1236
                        [% END %]
1236
                        [% END %]
1237
                    </fieldset>
1237
                    </fieldset>
1238
                    [% IF ( CAN_user_reserveforothers_alter_hold_targets ) %]
1239
                        <div class="btn-group">
1240
                            <a class="btn btn-default btn-xs dropdown-toggle move_selected_holds" id="item_record_choice" role="button" data-bs-toggle="dropdown" href="#" aria-expanded="false"></a>
1241
                            <ul class="dropdown-menu" role="menu" aria-labelledby="item_record_choice" style="">
1242
                                <li><a class="dropdown-item move_hold_item" href="#">Item level holds to a different item</a></li>
1243
                                <li><a class="dropdown-item move_hold_record" href="#">Record level holds to a different record</a></li>
1244
                            </ul>
1245
                        </div>
1246
                    [% END %]
1238
                </div>
1247
                </div>
1239
                <div class="page-section">
1248
                <div class="page-section">
1240
                    [% FOREACH biblioloo IN biblioloop %]
1249
                    [% FOREACH biblioloo IN biblioloop %]
Lines 1416-1421 Link Here
1416
        </div>
1425
        </div>
1417
    </div>
1426
    </div>
1418
</div>
1427
</div>
1428
<div id="moveHoldItemModal" class="modal modal-lg" tabindex="-1" role="dialog" aria-hidden="true">
1429
    <div class="modal-dialog">
1430
        <div class="modal-content">
1431
            <div class="modal-header">
1432
                <h1 class="modal-title">Move hold(s) to a different item</h1>
1433
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1434
            </div>
1435
            <div class="modal-body">
1436
                <div id="move_hold_item_selection">
1437
                    <h3>1. Review holds to move</h3>
1438
                    <table class="table table-striped">
1439
                        <thead>
1440
                            <tr>
1441
                                <th>Hold ID</th>
1442
                                <th>Original hold</th>
1443
                                <th>Problem</th>
1444
                            </tr>
1445
                        </thead>
1446
                        <tbody> </tbody>
1447
                    </table>
1448
                </div>
1449
                <hr />
1450
                <div id="move_hold_item_search" class="alert alert-danger" style="display:none;"></div>
1451
                <form id="itemSearchForm">
1452
                    <div id="move_hold_item_searchform">
1453
                        <h3>2. Enter the item barcode of new hold target: </h3>
1454
                        <fieldset class="action">
1455
                            <input type="text" class="form-control" name="external_id" id="external_id" required />
1456
                            <button type="submit" class="btn btn-default mt-3">Search</button>
1457
                        </fieldset>
1458
                    </div>
1459
                </form>
1460
                <form id="move_hold_item_form" method="post" action="request.pl">
1461
                    <div id="itemResultMessage" class="mt-3"> </div>
1462
                    <div id="move_hold_item_confirm" style="display:none;">
1463
                        <h3>3. Confirm moving of holds:</h3>
1464
                        [% INCLUDE 'csrf-token.inc' %]
1465
                        <input type="hidden" name="op" value="cud-move_hold_item" />
1466
                        <button type="submit" class="btn btn-primary mt-3">Move selected holds</button>
1467
                        <input type="hidden" name="original_biblionumber" value="[% biblio.biblionumber %]" />
1468
                    </div>
1469
                </form>
1470
            </div>
1471
            <div class="modal-footer">
1472
                <button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel</button>
1473
            </div>
1474
        </div>
1475
    </div>
1476
</div>
1477
<div id="moveHoldBiblioModal" class="modal modal-lg" tabindex="-1" role="dialog" aria-hidden="true">
1478
    <div class="modal-dialog">
1479
        <div class="modal-content">
1480
            <div class="modal-header">
1481
                <h1 class="modal-title">Move hold(s) to a different record</h1>
1482
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
1483
            </div>
1484
            <div class="modal-body">
1485
                <div id="move_hold_item_selection">
1486
                    <h3>1. Review holds to move</h3>
1487
                    <table class="table table-striped">
1488
                        <thead>
1489
                            <tr>
1490
                                <th>Hold ID</th>
1491
                                <th>Original hold</th>
1492
                                <th>Problem</th>
1493
                            </tr>
1494
                        </thead>
1495
                        <tbody> </tbody>
1496
                    </table>
1497
                </div>
1498
                <hr />
1499
                <div id="move_hold_biblio_search" class="alert alert-danger" style="display:none;"></div>
1500
                <form id="biblioSearchForm">
1501
                    <div id="move_hold_item_searchform">
1502
                        <h3>2. Enter the bibloinumber of the new hold target: </h3>
1503
                        <fieldset class="action">
1504
                            <input type="text" class="form-control" name="biblio_id" id="biblio_id" required />
1505
                            <button type="submit" class="btn btn-default mt-3">Search</button>
1506
                        </fieldset>
1507
                    </div>
1508
                </form>
1509
                <form id="move_hold_biblio_form" method="post" action="request.pl">
1510
                    <div id="biblioResultMessage" class="mt-3"> </div>
1511
                    <div id="move_hold_biblio_confirm" style="display:none;">
1512
                        <h3>3. Confirm moving of holds:</h3>
1513
                        [% INCLUDE 'csrf-token.inc' %]
1514
                        <input type="hidden" name="op" value="cud-move_hold_biblio" />
1515
                        <button type="submit" class="btn btn-primary mt-3">Move selected holds</button>
1516
                        <input type="hidden" name="original_biblionumber" value="[% biblio.biblionumber %]" />
1517
                    </div>
1518
                </form>
1519
            </div>
1520
            <div class="modal-footer">
1521
                <button type="button" class="btn btn-default" data-bs-dismiss="modal">Cancel</button>
1522
            </div>
1523
        </div>
1524
    </div>
1525
</div>
1419
<div id="hold-actions">
1526
<div id="hold-actions">
1420
    <form id="hold-actions-form"> [% INCLUDE 'csrf-token.inc' %] </form>
1527
    <form id="hold-actions-form"> [% INCLUDE 'csrf-token.inc' %] </form>
1421
</div>
1528
</div>
Lines 1730-1735 Link Here
1730
        }
1837
        }
1731
1838
1732
         $(document).ready(function() {
1839
         $(document).ready(function() {
1840
            $("#itemSearchForm").on("submit", function (event) {
1841
                event.preventDefault();
1842
1843
                let externalID = $("#external_id").val();
1844
                let apiUrl = `/api/v1/items?external_id=${encodeURIComponent(externalID)}`;
1845
1846
                $.ajax({
1847
                    url: apiUrl,
1848
                    method: "GET",
1849
                    dataType: "json",
1850
                    success: function (data) {
1851
                        if (data.length > 0) {
1852
                            let resultHtml = "";
1853
                            $.each(data, function (index, item) {
1854
                                resultHtml += `
1855
                                    <div class="alert alert-success">
1856
                                        <strong>Biblionumber:</strong> ${item.biblio_id} <br>
1857
                                        <strong>Item:</strong> ${item.external_id} <br>
1858
                                        <input id="new_itemnumber_${item.item_id}" name="new_itemnumber" type="checkbox" value="${item.item_id}">
1859
                                        <label for="new_itemnumber_${item.item_id}">Move all selected item level holds to this item</label>
1860
                                        <input id="new_biblionumber_${item.item_id}" name="new_biblionumber" type="hidden" value="${item.biblio_id}">
1861
                                    </div>
1862
                                    <hr />
1863
                                `;
1864
                            });
1865
                            $("#itemResultMessage").html(resultHtml);
1866
                        } else {
1867
                            $("#itemResultMessage").html(`
1868
                                <div class="alert alert-warning">No item found with barcode: ${externalID}.</div>
1869
                            `);
1870
                        }
1871
                    },
1872
                });
1873
            });
1874
1875
            $("#biblioSearchForm").on("submit", function (event) {
1876
                event.preventDefault();
1877
1878
                let biblioID = $("#biblio_id").val();
1879
                let apiUrl = `/api/v1/items?q={"biblio_id":"${encodeURIComponent(biblioID)}"}`;
1880
1881
                $.ajax({
1882
                    url: apiUrl,
1883
                    method: "GET",
1884
                    dataType: "json",
1885
                    success: function (data) {
1886
                        if (data.length > 0) {
1887
                            let resultHtml = "";
1888
                            $.each(data, function (index, item) {
1889
                                resultHtml += `
1890
                                    <div class="alert alert-success">
1891
                                        <strong>Biblionumber:</strong> ${item.biblio_id} <br>
1892
                                        <input id="new_biblionumber_${item.biblio_id}" name="new_biblionumber" type="checkbox" value="${item.biblio_id}">
1893
                                        <label for="new_biblionumber_${item.biblio_id}">Move all selected record level holds to this record</label>
1894
                                    </div>
1895
                                    <hr />
1896
                                `;
1897
                            });
1898
                            $("#biblioResultMessage").html(resultHtml);
1899
                        } else {
1900
                            $("#biblioResultMessage").html(`
1901
                                <div class="alert alert-warning">No item found with barcode: ${biblioID}.</div>
1902
                            `);
1903
                        }
1904
                    },
1905
                });
1906
            });
1907
1908
            $(document).on("change", 'input[name="new_itemnumber"]', function() {
1909
                $('input[name="new_itemnumber"]').not(this).prop("checked", false);
1910
                if ( $('input[name="new_itemnumber"]:checked').length ){
1911
                    $('#move_hold_item_confirm').show();
1912
                } else {
1913
                    $('#move_hold_item_confirm').hide();
1914
                }
1915
            });
1916
1917
            $(document).on("change", 'input[name="new_biblionumber"]', function() {
1918
                $('input[name="new_biblionumber"]').not(this).prop("checked", false);
1919
                if ( $('input[name="new_biblionumber"]:checked').length ){
1920
                    $('#move_hold_biblio_confirm').show();
1921
                } else {
1922
                    $('#move_hold_biblio_confirm').hide();
1923
                }
1924
            });
1733
1925
1734
            $("#always_show_holds").change(function(){
1926
            $("#always_show_holds").change(function(){
1735
                if( $(this).prop('checked') ){
1927
                if( $(this).prop('checked') ){
Lines 1855-1860 Link Here
1855
                localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
2047
                localStorage.selectedHolds = $('.holds_table .select_hold:checked').toArray().map(el => $(el).data('id'));
1856
            });
2048
            });
1857
2049
2050
            $('.move_hold_item').click(function(e) {
2051
                e.preventDefault();
2052
                if($('.holds_table .select_hold:checked').length) {
2053
                    $('#itemResultMessage').empty();
2054
                    $('#move_hold_item_selection table tbody').empty();
2055
                    $('#moveHoldItemModal').modal('show');
2056
                    $('.select_hold:checked').each( function() {
2057
                        let reserve_id = $(this).data('id');
2058
                        let reserve_biblionumber = $(this).data('biblionumber');
2059
                        let reserve_itemnumber = $(this).data('itemnumber');
2060
                        let item_level_hold = $(this).data('item_level_hold');
2061
                        let error_message = $(this).data('item_level_hold') ? "" : _("Cannot move a waiting or record level hold");
2062
                        let found_status = $(this).data('found');
2063
                        $('#move_hold_item_selection table').append(`<tr><td>${reserve_id}</td><td>Biblionumber: <a target="_blank" href="/cgi-bin/koha/reserve/request.pl?biblionumber=${reserve_biblionumber}">${reserve_biblionumber}</a> Itemnumber: <a target="_blank" href="/cgi-bin/koha/catalogue/moredetail.pl?biblionumber=${reserve_biblionumber}#item${reserve_itemnumber}">${reserve_itemnumber}</a></td><td>${error_message}</td></tr>`)
2064
                        if ( item_level_hold ) {
2065
                            $('#move_hold_item_form').append(`<input type="hidden" name="hold_id" value="${reserve_id}">`);
2066
                        }
2067
                    });
2068
                }
2069
            });
2070
2071
            $('.move_hold_record').click(function(e) {
2072
                e.preventDefault();
2073
                if($('.holds_table .select_hold:checked').length) {
2074
                    $('#biblioResultMessage').empty();
2075
                    $('#move_hold_item_selection table tbody').empty();
2076
                    $('#moveHoldBiblioModal').modal('show');
2077
                    $('.select_hold:checked').each( function() {
2078
                        let reserve_id = $(this).data('id');
2079
                        let reserve_biblionumber = $(this).data('biblionumber');
2080
                        let reserve_itemnumber = $(this).data('itemnumber');
2081
                        let item_level_hold = $(this).data('item_level_hold');
2082
                        let error_message = $(this).data('item_level_hold') ? _("Cannot move a waiting or item level hold") : "";
2083
                        let found_status = $(this).data('found');
2084
                        $('#move_hold_item_selection table').append(`<tr><td>${reserve_id}</td><td>Biblionumber: <a target="_blank" href="/cgi-bin/koha/reserve/request.pl?biblionumber=${reserve_biblionumber}">${reserve_biblionumber}</a></td><td>${error_message}</td></tr>`)
2085
                        if ( !item_level_hold ) {
2086
                            $('#move_hold_biblio_form').append(`<input type="hidden" name="hold_id" value="${reserve_id}">`);
2087
                        }
2088
                    });
2089
                }
2090
            });
2091
1858
            $('.cancel_selected_holds').click(function(e) {
2092
            $('.cancel_selected_holds').click(function(e) {
1859
                e.preventDefault();
2093
                e.preventDefault();
1860
                if($('.holds_table .select_hold:checked').length) {
2094
                if($('.holds_table .select_hold:checked').length) {
(-)a/reserve/request.pl (-1 / +54 lines)
Lines 110-115 if ( $op eq 'cud-move' ) { Link Here
110
            $next_priority, $first_priority, $last_priority
110
            $next_priority, $first_priority, $last_priority
111
        );
111
        );
112
    }
112
    }
113
} elsif ( $op eq 'cud-move_hold_item' or $op eq 'cud-move_hold_biblio' ) {
114
    my @hold_ids              = $input->multi_param('hold_id');
115
    my $original_biblionumber = $input->param('original_biblionumber');
116
    my @moving_holds          = Koha::Holds->search(
117
        { reserve_id => \@hold_ids },
118
        { order_by   => { -asc => 'priority' } }
119
    )->as_list;
120
121
    my $new_biblionumber = $input->param('new_biblionumber');
122
    my $target_biblio    = Koha::Biblios->find($new_biblionumber);
123
124
    my %args = (
125
        new_biblionumber => $new_biblionumber,
126
    );
127
128
    # Only pass new_itemnumber if this is an item level move
129
    if ( $op eq 'cud-move_hold_item' ) {
130
        $args{new_itemnumber} = $input->param('new_itemnumber');
131
    }
132
133
    my @success_messages;
134
    my @error_messages;
135
136
    foreach my $hold (@moving_holds) {
137
        my $original_biblio = Koha::Biblios->find( $hold->biblionumber );
138
139
        my $result = $hold->move_hold( \%args );
140
141
        if ( $result->{success} ) {
142
            push @success_messages, {
143
                hold_id         => $hold->id,
144
                success         => 1,
145
                original_biblio => $original_biblio,
146
                target_biblio   => $target_biblio,
147
            };
148
        } else {
149
            push @error_messages, {
150
                hold_id         => $hold->id,
151
                success         => 0,
152
                original_biblio => $original_biblio,
153
                target_biblio   => $target_biblio,
154
                error           => $result->{error},
155
            };
156
        }
157
    }
158
159
    #Fix the priority on the original record
160
    C4::Reserves::_FixPriority( { biblionumber => $original_biblionumber } );
161
162
    $template->param(
163
        hold_move_successes => \@success_messages,
164
        hold_move_failures  => \@error_messages,
165
    );
166
113
} elsif ( $op eq 'cud-cancel' ) {
167
} elsif ( $op eq 'cud-cancel' ) {
114
    my $reserve_id          = $input->param('reserve_id');
168
    my $reserve_id          = $input->param('reserve_id');
115
    my $cancellation_reason = $input->param("cancellation-reason");
169
    my $cancellation_reason = $input->param("cancellation-reason");
116
- 

Return to bug 31698