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

(-)a/Koha/Cash/Register.pm (-5 / +5 lines)
Lines 289-298 sub start_cashup { Link Here
289
        Koha::Exceptions::Object::DuplicateID->throw( error => "A cashup is already in progress for this register" );
289
        Koha::Exceptions::Object::DuplicateID->throw( error => "A cashup is already in progress for this register" );
290
    }
290
    }
291
291
292
    my $expected_amount = abs( $self->outstanding_accountlines->total( { payment_type => [ 'CASH', 'SIP00' ] } ) );
292
    my $expected_amount = $self->outstanding_accountlines->total( { payment_type => [ 'CASH', 'SIP00' ] } ) * -1;
293
293
294
    # Prevent starting a cashup when there are no cash transactions
294
    # Prevent starting a cashup when there are no cash transactions
295
    unless ( $expected_amount > 0 ) {
295
    unless ( $expected_amount != 0 ) {
296
        Koha::Exceptions::Object::BadValue->throw(
296
        Koha::Exceptions::Object::BadValue->throw(
297
            error => "Cannot start cashup with zero cash transactions",
297
            error => "Cannot start cashup with zero cash transactions",
298
            type  => 'amount',
298
            type  => 'amount',
Lines 345-354 sub add_cashup { Link Here
345
    }
345
    }
346
    my $manager_id = $params->{manager_id};
346
    my $manager_id = $params->{manager_id};
347
347
348
    # Validate amount should always be a positive value
348
    # Validate amount is a non-zero number
349
    my $amount = $params->{amount};
349
    my $amount = $params->{amount};
350
    unless ( looks_like_number($amount) && $amount > 0 ) {
350
    unless ( looks_like_number($amount) && $amount != 0 ) {
351
        Koha::Exceptions::Account::AmountNotPositive->throw( error => 'Cashup amount passed is not positive number' );
351
        Koha::Exceptions::Account::AmountNotPositive->throw( error => 'Cashup amount must be a non-zero number' );
352
    }
352
    }
353
353
354
    # Sanitize reconciliation note - treat empty/whitespace-only as undef
354
    # Sanitize reconciliation note - treat empty/whitespace-only as undef
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/pos/register.tt (-3 / +11 lines)
Lines 447-453 Link Here
447
                            <li>
447
                            <li>
448
                                <span class="label">
448
                                <span class="label">
449
                                    [% IF cashup_in_progress %]
449
                                    [% IF cashup_in_progress %]
450
                                        Expected cashup amount:
450
                                        [% IF cashup_in_progress.amount < 0 %]
451
                                            Expected amount to add:
452
                                        [% ELSE %]
453
                                            Expected cashup amount:
454
                                        [% END %]
451
                                    [% ELSE %]
455
                                    [% ELSE %]
452
                                        Expected amount to remove:
456
                                        Expected amount to remove:
453
                                    [% END %]
457
                                    [% END %]
Lines 457-468 Link Here
457
                            <li>
461
                            <li>
458
                                <label class="required" for="amount">
462
                                <label class="required" for="amount">
459
                                    [% IF cashup_in_progress %]
463
                                    [% IF cashup_in_progress %]
460
                                        Actual cashup amount counted:
464
                                        [% IF cashup_in_progress.amount < 0 %]
465
                                            Actual amount added to register:
466
                                        [% ELSE %]
467
                                            Actual cashup amount counted:
468
                                        [% END %]
461
                                    [% ELSE %]
469
                                    [% ELSE %]
462
                                        Actual amount removed from register:
470
                                        Actual amount removed from register:
463
                                    [% END %]
471
                                    [% END %]
464
                                </label>
472
                                </label>
465
                                <input type="text" inputmode="decimal" pattern="^\d+(\.\d{2})?$" id="amount" name="amount" required="required" />
473
                                <input type="text" inputmode="decimal" pattern="^-?\d+(\.\d{2})?$" id="amount" name="amount" required="required" />
466
                                <span class="required">Required</span>
474
                                <span class="required">Required</span>
467
                            </li>
475
                            </li>
468
                            <li id="reconciliation_display" style="display: none;">
476
                            <li id="reconciliation_display" style="display: none;">
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/pos/registers.tt (-16 / +67 lines)
Lines 272-289 Link Here
272
                <div class="modal-body">
272
                <div class="modal-body">
273
                    <p><strong>Choose how to proceed with the cashup:</strong></p>
273
                    <p><strong>Choose how to proceed with the cashup:</strong></p>
274
                    <p><strong>Start cashup</strong></p>
274
                    <p><strong>Start cashup</strong></p>
275
                    <ul>
275
                    <ul id="start_cashup_instructions">
276
                        <li>Remove cash from the register for counting</li>
276
                        <!-- JavaScript will populate this based on positive/negative amount -->
277
                        <li>The register can continue operating during counting</li>
278
                        <li>Complete the cashup once counted</li>
279
                    </ul>
277
                    </ul>
280
                    <p><strong>Quick cashup</strong></p>
278
                    <p><strong>Quick cashup</strong></p>
281
                    <ul>
279
                    <ul id="quick_cashup_instructions">
282
                        <li>Confirm you have removed <span id="expected_amount_display"></span> cash from the register to bank immediately</li>
280
                        <!-- JavaScript will populate this based on positive/negative amount -->
283
                    </ul>
281
                    </ul>
284
                    <p
282
                    <p id="float_reminder_text">
285
                        >Remember to leave the float amount of <strong><span id="float_amount_display"></span></strong> in the register.</p
283
                        <!-- JavaScript will populate this based on positive/negative amount -->
286
                    >
284
                    </p>
287
                </div>
285
                </div>
288
                <div class="modal-footer">
286
                <div class="modal-footer">
289
                    <input type="hidden" name="registerid" id="register_id_field" value="" />
287
                    <input type="hidden" name="registerid" id="register_id_field" value="" />
Lines 377-388 Link Here
377
                    <fieldset class="rows">
375
                    <fieldset class="rows">
378
                        <ol>
376
                        <ol>
379
                            <li>
377
                            <li>
380
                                <span class="label"> Expected cashup amount: </span>
378
                                <span class="label" id="expected_amount_label">Expected cashup amount:</span>
381
                                <span id="cashc" class="expected-amount"></span>
379
                                <span id="cashc" class="expected-amount"></span>
382
                            </li>
380
                            </li>
383
                            <li>
381
                            <li>
384
                                <label class="required" for="amount"> Actual cashup amount counted: </label>
382
                                <label class="required" for="amount" id="actual_amount_label">Actual cashup amount counted:</label>
385
                                <input type="text" inputmode="decimal" pattern="^\d+(\.\d{2})?$" id="amount" name="amount" required="required" />
383
                                <input type="text" inputmode="decimal" pattern="^-?\d+(\.\d{2})?$" id="amount" name="amount" required="required" />
386
                                <span class="required">Required</span>
384
                                <span class="required">Required</span>
387
                            </li>
385
                            </li>
388
                            <li id="reconciliation_display" style="display: none;">
386
                            <li id="reconciliation_display" style="display: none;">
Lines 518-523 Link Here
518
               $("#registerc").text(register);
516
               $("#registerc").text(register);
519
               var expected = button.data('expected');
517
               var expected = button.data('expected');
520
               $("#cashc").text(expected);
518
               $("#cashc").text(expected);
519
520
               // Parse expected amount to check if negative
521
               var expectedAmount = expected.replace(/[^0-9.-]/g, '');
522
               var isNegative = parseFloat(expectedAmount) < 0;
523
524
               // Update labels based on sign
525
               if (isNegative) {
526
                   $("#expected_amount_label").text(_("Expected amount to add:"));
527
                   $("#actual_amount_label").text(_("Actual amount added to register:"));
528
               } else {
529
                   $("#expected_amount_label").text(_("Expected cashup amount:"));
530
                   $("#actual_amount_label").text(_("Actual cashup amount counted:"));
531
               }
532
521
               var rfloat = button.data('float');
533
               var rfloat = button.data('float');
522
               $('#floatc').text(rfloat);
534
               $('#floatc').text(rfloat);
523
               var rid = button.data('registerid');
535
               var rid = button.data('registerid');
Lines 534-547 Link Here
534
               var register = button.data('register');
546
               var register = button.data('register');
535
               $("#register_desc").text(register);
547
               $("#register_desc").text(register);
536
               var bankable = button.data('bankable');
548
               var bankable = button.data('bankable');
537
               $("#expected_amount_display").text(bankable);
538
               var rfloat = button.data('float');
549
               var rfloat = button.data('float');
539
               $('#float_amount_display').text(rfloat);
540
               var rid = button.data('registerid');
550
               var rid = button.data('registerid');
541
               $('#register_id_field').val(rid);
551
               $('#register_id_field').val(rid);
542
552
553
               // Parse bankable amount (remove currency formatting)
554
               var bankableAmount = bankable.replace(/[^0-9.-]/g, '');
555
               var isNegative = parseFloat(bankableAmount) < 0;
556
               var absAmountFormatted = bankable.replace('-', '');
557
558
               // Update Start cashup instructions
559
               if (isNegative) {
560
                   $("#start_cashup_instructions").html(
561
                       '<li>' + _("Count cash in the register") + '</li>' +
562
                       '<li>' + _("The register can continue operating during counting") + '</li>' +
563
                       '<li>' + _("Complete the cashup by adding cash to restore the float") + '</li>'
564
                   );
565
               } else {
566
                   $("#start_cashup_instructions").html(
567
                       '<li>' + _("Remove cash from the register for counting") + '</li>' +
568
                       '<li>' + _("The register can continue operating during counting") + '</li>' +
569
                       '<li>' + _("Complete the cashup once counted") + '</li>'
570
                   );
571
               }
572
573
               // Update Quick cashup instructions
574
               if (isNegative) {
575
                   $("#quick_cashup_instructions").html(
576
                       '<li>' + _("Top up the register with %s to restore the float").format(absAmountFormatted) + '</li>'
577
                   );
578
               } else {
579
                   $("#quick_cashup_instructions").html(
580
                       '<li>' + _("Confirm you have removed %s cash from the register to bank immediately").format(bankable) + '</li>'
581
                   );
582
               }
583
584
               // Update float reminder
585
               if (isNegative) {
586
                   $("#float_reminder_text").html(
587
                       _("This will bring the register back to the expected float of <strong>%s</strong>").format(rfloat)
588
                   );
589
               } else {
590
                   $("#float_reminder_text").html(
591
                       _("Remember to leave the float amount of <strong>%s</strong> in the register.").format(rfloat)
592
                   );
593
               }
594
543
               // Store bankable amount for quick cashup
595
               // Store bankable amount for quick cashup
544
               $('#triggerCashupModalRegister').data('bankable-amount', bankable.replace(/[^0-9.-]/g, ''));
596
               $('#triggerCashupModalRegister').data('bankable-amount', bankableAmount);
545
            });
597
            });
546
598
547
            // Handle Quick cashup button click
599
            // Handle Quick cashup button click
548
- 

Return to bug 40445