#!/usr/bin/perl

# Copyright PTFS Europe 2016
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.

use Modern::Perl;

use DateTime;
use DateTime::Duration;
use Koha::Database;
use Koha::DateUtils qw( dt_from_string );
use Koha::Item::Transfer;

use Test::Warn;
use t::lib::TestBuilder;
use t::lib::Mocks;

use Test::More tests => 9;

my $schema = Koha::Database->new->schema;

use_ok('Koha::StockRotationItems');
use_ok('Koha::StockRotationItem');

my $builder = t::lib::TestBuilder->new;

subtest 'Basic object tests' => sub {

    plan tests => 5;

    $schema->storage->txn_begin;

    my $itm = $builder->build_sample_item;
    my $stage = $builder->build({ source => 'Stockrotationstage' });

    my $item = $builder->build({
        source => 'Stockrotationitem',
        value  => {
            itemnumber_id => $itm->itemnumber,
            stage_id      => $stage->{stage_id},
        },
    });

    my $sritem = Koha::StockRotationItems->find($item->{itemnumber_id});
    isa_ok(
        $sritem,
        'Koha::StockRotationItem',
        "Correctly create and load a stock rotation item."
    );

    # Relationship to rota
    isa_ok( $sritem->item, 'Koha::Item', "Fetched related item." );
    is( $sritem->item->itemnumber, $itm->itemnumber, "Related rota OK." );

    # Relationship to stage
    isa_ok( $sritem->stage, 'Koha::StockRotationStage', "Fetched related stage." );
    is( $sritem->stage->stage_id, $stage->{stage_id}, "Related stage OK." );


    $schema->storage->txn_rollback;
};

subtest 'Tests for needs_repatriating' => sub {

    plan tests => 4;

    $schema->storage->txn_begin;

    # Setup a pristine stockrotation context.
    my $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value =>
              { itemnumber_id => $builder->build_sample_item->itemnumber }
        }
    );
    my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    $dbitem->item->homebranch($dbitem->stage->branchcode_id);
    $dbitem->item->holdingbranch($dbitem->stage->branchcode_id);
    $dbitem->stage->position(1);

    my $dbrota = $dbitem->stage->rota;
    my $newstage = $builder->build({
        source => 'Stockrotationstage',
        value => {
            rota_id => $dbrota->rota_id,
            position => 2,
        }
    });

    # - homebranch == holdingbranch [0]
    is(
        $dbitem->needs_repatriating, 0,
        "Homebranch == Holdingbranch."
    );

    my $branch = $builder->build({ source => 'Branch' });
    $dbitem->item->holdingbranch($branch->{branchcode});

    # - homebranch != holdingbranch [1]
    is(
        $dbitem->needs_repatriating, 1,
        "Homebranch != holdingbranch."
    );

    # Set to incorrect homebranch.
    $dbitem->item->holdingbranch($dbitem->stage->branchcode_id);
    $dbitem->item->homebranch($branch->{branchcode});
    # - homebranch != stockrotationstage.branch & not in transit [1]
    is(
        $dbitem->needs_repatriating, 1,
        "Homebranch != StockRotationStage.Branchcode_id & not in transit."
    );

    # Set to in transit (by implication).
    $dbitem->stage($newstage->{stage_id});
    # - homebranch != stockrotaitonstage.branch & in transit [0]
    is(
        $dbitem->needs_repatriating, 1,
        "homebranch != stockrotaitonstage.branch & in transit."
    );

    $schema->storage->txn_rollback;
};

subtest "Tests for repatriate." => sub {
    plan tests => 9;
    $schema->storage->txn_begin;

    my $sritem_1 = $builder->build_object(
        {
            class => 'Koha::StockRotationItems',
            value  => {
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    my $item_id = $sritem_1->item->itemnumber;
    my $srstage_1 = $sritem_1->stage;
    $sritem_1->discard_changes;
    $sritem_1->stage->position(1);
    $sritem_1->stage->duration(50);
    my $branch = $builder->build({ source => 'Branch' });
    $sritem_1->item->holdingbranch($branch->{branchcode});

    # Test a straight up repatriate
    ok($sritem_1->repatriate, "Repatriation done.");
    my $intransfer = $sritem_1->item->get_transfer;
    is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
    is($intransfer->tobranch, $sritem_1->stage->branchcode_id, "Target Correct.");

    # Reset
    $intransfer->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($branch->{branchcode});

    # Setup a conflicting manual transfer
    my $item = Koha::Items->find($item_id);
    $item->request_transfer({ to => $srstage_1->branchcode, reason => "Manual" });
    $intransfer = $item->get_transfer;
    is (ref($intransfer), 'Koha::Item::Transfer', "Conflicting transfer added");
    is ($intransfer->reason, 'Manual', "Conflicting transfer reason is 'Manual'");

    # Stockrotation should handle transfer clashes
    is($sritem_1->repatriate, 0, "Repatriation skipped if transfer in progress.");

    # Reset
    $intransfer->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($branch->{branchcode});

    # Confirm that stockrotation ignores transfer limits
    t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
    t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
    my $limit = Koha::Item::Transfer::Limit->new(
        {
            fromBranch => $branch->{branchcode},
            toBranch   => $srstage_1->branchcode_id,
            itemtype   => $sritem_1->item->effective_itemtype,
        }
    )->store;

    # Stockrotation should overrule transfer limits
    ok($sritem_1->repatriate, "Repatriation done regardless of transfer limits.");
    $intransfer = $sritem_1->item->get_transfer;
    is($intransfer->frombranch, $branch->{branchcode}, "Origin correct.");
    is($intransfer->tobranch, $sritem_1->stage->branchcode_id, "Target Correct.");

    $schema->storage->txn_rollback;
};

subtest "Tests for needs_advancing." => sub {
    plan tests => 8;
    $schema->storage->txn_begin;

    # Test behaviour of item freshly added to rota.
    my $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                'fresh'       => 1,
                itemnumber_id => $builder->build_sample_item->itemnumber
            },
        }
    );
    my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    is($dbitem->needs_advancing, 1, "An item that is fresh will always need advancing.");

    # Setup a pristine stockrotation context.
    $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                'fresh'       => 0,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    $dbitem->item->homebranch($dbitem->stage->branchcode_id);
    $dbitem->item->holdingbranch($dbitem->stage->branchcode_id);
    $dbitem->stage->position(1);
    $dbitem->stage->duration(50);

    my $dbtransfer = Koha::Item::Transfer->new({
        'itemnumber'  => $dbitem->itemnumber_id,
        'frombranch'  => $dbitem->stage->branchcode_id,
        'tobranch'    => $dbitem->stage->branchcode_id,
        'datesent'    => dt_from_string(),
        'datearrived' => undef,
        'reason'      => "StockrotationAdvance",
    })->store;

    # Test item will not be advanced if in transit.
    is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer.");
    # Test item will not be advanced if in transit even if fresh.
    $dbitem->fresh(1)->store;
    is($dbitem->needs_advancing, 0, "Not ready to advance: in transfer (fresh).");
    $dbitem->fresh(0)->store;

    # Test item will not be advanced if it has not spent enough time.
    $dbtransfer->datearrived(dt_from_string())->store;
    is($dbitem->needs_advancing, 0, "Not ready to advance: Not spent enough time.");
    # Test item will be advanced if it has not spent enough time, but is fresh.
    $dbitem->fresh(1)->store;
    is($dbitem->needs_advancing, 1, "Advance: Not spent enough time, but fresh.");
    $dbitem->fresh(0)->store;

    # Test item will be advanced if it has spent enough time.
    $dbtransfer->datesent(      # Item was sent 100 days ago...
        dt_from_string() - DateTime::Duration->new( days => 100 )
    )->store;
    $dbtransfer->datearrived(   # And arrived 75 days ago.
        dt_from_string() - DateTime::Duration->new( days => 75 )
    )->store;
    is($dbitem->needs_advancing, 1, "Ready to be advanced.");

    # Bug 30518: Confirm that DST boundaries do not explode.
    # mock_config does not work here, because of tz vs timezone subroutines
    my $context = Test::MockModule->new('C4::Context');
    $context->mock( 'tz', sub {
        'Europe/London';
    });
    my $bad_date = dt_from_string("2020-09-29T01:15:30", 'iso');
    $dbtransfer->datesent($bad_date)->store;
    $dbtransfer->datearrived($bad_date)->store;
    $dbitem->stage->duration(180)->store;
    is( $dbitem->needs_advancing, 1, "DST boundary doesn't cause failure." );
    $context->unmock('tz');

    # Test that missing historical branch transfers do not crash
    $dbtransfer->delete;
    warning_is {$dbitem->needs_advancing} "We have no historical branch transfer for item " . $dbitem->item->itemnumber . "; This should not have happened!", "Missing transfer is warned.";

    $schema->storage->txn_rollback;
};

subtest "Tests for advance." => sub {
    plan tests => 48;
    $schema->storage->txn_begin;

    my $sritem_1 = $builder->build_object(
        {
            class => 'Koha::StockRotationItems',
            value  => {
                'fresh'       => 1,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $sritem_1->discard_changes;
    $sritem_1->item->holdingbranch($sritem_1->stage->branchcode_id);
    my $item_id = $sritem_1->item->itemnumber;
    my $srstage_1 = $sritem_1->stage;
    $srstage_1->position(1)->duration(50)->store; # Configure stage.
    # Configure item
    $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;
    $sritem_1->item->homebranch($srstage_1->branchcode_id)->store;
    # Sanity check
    is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage sanity check.");

    # Test if an item is fresh, always move to first stage.
    is($sritem_1->fresh, 1, "Fresh is correct.");
    $sritem_1->advance;
    is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage is first stage after fresh advance.");
    is($sritem_1->fresh, 0, "Fresh reset after advance.");

    # Test cases of single stage
    $srstage_1->rota->cyclical(1)->store;         # Set Rota to cyclical.
    ok($sritem_1->advance, "Single stage cyclical advance done.");
    ## Refetch sritem_1
    $sritem_1->discard_changes;
    is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Single stage cyclical stage OK.");

    # Test with indemand advance
    $sritem_1->indemand(1)->store;
    ok($sritem_1->advance, "Indemand item advance done.");
    ## Refetch sritem_1
    $sritem_1->discard_changes;
    is($sritem_1->indemand, 0, "Indemand OK.");
    is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Indemand item advance stage OK.");

    # Multi stages
    my $srstage_2 = $builder->build_object({
        class => 'Koha::StockRotationStages',
        value => { duration => 50 }
    });
    $srstage_2->discard_changes;
    $srstage_2->move_to_group($sritem_1->stage->rota_id);
    $srstage_2->move_last;

    # Test a straight up advance
    ok($sritem_1->advance, "Advancement done.");
    ## Refetch sritem_1
    $sritem_1->discard_changes;
    ## Test results
    is($sritem_1->stage->stage_id, $srstage_2->stage_id, "Stage updated.");
    is(
        $sritem_1->item->homebranch,
        $srstage_2->branchcode_id,
        "Item homebranch updated"
    );
    my $transfer_request = $sritem_1->item->get_transfer;
    is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
    is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target Correct.");
    is($transfer_request->datesent, undef, "Transfer requested, but not sent.");

    # Arrive at new branch
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;

    # Test a cyclical advance
    ok($sritem_1->advance, "Cyclical advancement done.");
    ## Refetch sritem_1
    $sritem_1->discard_changes;
    ## Test results
    is($sritem_1->stage->stage_id, $srstage_1->stage_id, "Stage updated.");
    is(
        $sritem_1->item->homebranch,
        $srstage_1->branchcode_id,
        "Item homebranch updated"
    );
    $transfer_request = $sritem_1->item->get_transfer;
    is($transfer_request->frombranch, $srstage_2->branchcode_id, "Origin correct.");
    is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");

    # Arrive at new branch
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;

    # Confirm that stockrotation ignores transfer limits
    t::lib::Mocks::mock_preference('UseBranchTransferLimits', 1);
    t::lib::Mocks::mock_preference('BranchTransferLimitsType', 'itemtype');
    my $limit = Koha::Item::Transfer::Limit->new(
        {
            fromBranch => $srstage_1->branchcode_id,
            toBranch   => $srstage_2->branchcode_id,
            itemtype   => $sritem_1->item->effective_itemtype,
        }
    )->store;

    ok($sritem_1->advance, "Advancement overrules transfer limits.");
    ## Refetch sritem_1
    $sritem_1->discard_changes;
    ## Test results
    is($sritem_1->stage->stage_id, $srstage_2->stage_id, "Stage updated ignoring transfer limits.");
    is(
        $sritem_1->item->homebranch,
        $srstage_2->branchcode_id,
        "Item homebranch updated ignoring transfer limits"
    );
    $transfer_request = $sritem_1->item->get_transfer;
    is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct ignoring transfer limits.");
    is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target correct ignoring transfer limits.");

    # Arrive at new branch
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;

    # Setup a conflicting manual transfer
    my $item = Koha::Items->find($item_id);
    $item->request_transfer({ to => $srstage_1->branchcode, reason => "Manual" });
    $transfer_request = $item->get_transfer;
    is (ref($transfer_request), 'Koha::Item::Transfer', "Conflicting transfer added");
    is ($transfer_request->reason, 'Manual', "Conflicting transfer reason is 'Manual'");

    # Advance item whilst conflicting manual transfer exists
    ok($sritem_1->advance, "Advancement done.");
    ## Refetch sritem_1
    $sritem_1->discard_changes;

    ## Refetch conflicted transfer
    $transfer_request->discard_changes;

    # Conflicted transfer should have been cancelled
    isnt($transfer_request->datecancelled, undef, "Conflicting manual transfer was cancelled");

    # StockRotationAdvance transfer added
    $transfer_request = $sritem_1->item->get_transfer;
    is($transfer_request->reason, 'StockrotationAdvance', "StockrotationAdvance transfer added");
    is($transfer_request->frombranch, $srstage_2->branchcode_id, "Origin correct.");
    is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");

    # Arrive at new branch
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;

    # Setup a conflicting reserve transfer
    $item->request_transfer({ to => $srstage_2->branchcode, reason => "Reserve" });
    $transfer_request = $item->get_transfer;
    is (ref($transfer_request), 'Koha::Item::Transfer', "Conflicting transfer added");
    is ($transfer_request->reason, 'Reserve', "Conflicting transfer reason is 'Reserve'");

    # Advance item whilst conflicting reserve transfer exists
    ok($sritem_1->advance, "Advancement done.");
    ## Refetch sritem_1
    $sritem_1->discard_changes;

    ## Refetch conflicted transfer
    $transfer_request->discard_changes;

    # Conflicted transfer should not been cancelled
    is($transfer_request->datecancelled, undef, "Conflicting reserve transfer was not cancelled");

    # StockRotationAdvance transfer added
    my $transfer_requests = Koha::Item::Transfers->search(
        {
            itemnumber    => $sritem_1->item->itemnumber,
            datearrived   => undef,
            datecancelled => undef
        }
    );
    is($transfer_requests->count, '2', "StockrotationAdvance transfer queued");

    # Arrive at new branch
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;

    # StockRotationAdvance transfer added
    $transfer_request = $sritem_1->item->get_transfer;
    is($transfer_request->reason, 'StockrotationAdvance', "StockrotationAdvance transfer remains after reserve is met");
    is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
    is($transfer_request->tobranch, $srstage_2->branchcode_id, "Target correct.");

    # Arrive at new branch
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;

    # Checked out item, advanced to next stage, checkedout from next stage
    # transfer should be generated, but not initiated
    my $issue = $builder->build_object({
        class => 'Koha::Checkouts',
        value => {
             branchcode => $srstage_1->branchcode_id,
             itemnumber => $sritem_1->item->itemnumber,
             returndate => undef
        }
    });
    $sritem_1->item->holdingbranch($srstage_1->branchcode_id)->store;
    ok($sritem_1->advance, "Advancement done.");
    $transfer_request = $sritem_1->item->get_transfer;
    is($transfer_request->frombranch, $srstage_1->branchcode_id, "Origin correct.");
    is($transfer_request->tobranch, $srstage_1->branchcode_id, "Target correct.");
    is($transfer_request->datesent, undef, "Transfer waiting to initiate until return.");

    $issue->delete; #remove issue
    $sritem_1->advance; #advance back to second stage
    # Set arrived
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_2->branchcode_id)->store;


    $srstage_1->rota->cyclical(0)->store;         # Set Rota to non-cyclical.

    my $srstage_3 = $builder->build_object({
        class => 'Koha::StockRotationStages',
        value => { duration => 50 }
    });
    $srstage_3->discard_changes;
    $srstage_3->move_to_group($sritem_1->stage->rota_id);
    $srstage_3->move_last;

    # Advance again, to end of rota.
    ok($sritem_1->advance, "Non-cyclical advance to last stage.");

    # Arrive at new branch
    $transfer_request->datearrived(dt_from_string())->store;
    $sritem_1->item->holdingbranch($srstage_3->branchcode_id)->store;

    # Advance again, Remove from rota.
    ok($sritem_1->advance, "Non-cyclical advance.");
    ## Refetch sritem_1
    $sritem_1 = Koha::StockRotationItems->find({ itemnumber_id => $item_id });
    is($sritem_1, undef, "StockRotationItem has been removed.");
    $item = Koha::Items->find($item_id);
    is($item->homebranch, $srstage_3->branchcode_id, "Item homebranch remains");

    $schema->storage->txn_rollback;
};

subtest "Tests for investigate (singular)." => sub {
    plan tests => 7;
    $schema->storage->txn_begin;

    # Test brand new item's investigation ['initiation']
    my $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                fresh         => 1,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    is($dbitem->investigate->{reason}, 'initiation', "fresh item initiates.");

    # Test brand new item at stagebranch ['initiation']
    $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                fresh         => 1,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
    $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
    is($dbitem->investigate->{reason}, 'initiation', "fresh item at stagebranch initiates.");

    # Test item not at stagebranch with branchtransfer history ['repatriation']
    $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                'fresh'       => 0,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    my $dbtransfer = Koha::Item::Transfer->new({
        'itemnumber'  => $dbitem->itemnumber_id,
        'frombranch'  => $dbitem->item->homebranch,
        'tobranch'    => $dbitem->item->homebranch,
        'datesent'    => dt_from_string(),
        'datearrived' => dt_from_string(),
        'reason'      => "StockrotationAdvance",
    })->store;
    is($dbitem->investigate->{reason}, 'repatriation', "older item repatriates.");

    # Test item at stagebranch with branchtransfer history ['not-ready']
    $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                'fresh'       => 0,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    $dbtransfer = Koha::Item::Transfer->new({
        'itemnumber'  => $dbitem->itemnumber_id,
        'frombranch'  => $dbitem->item->homebranch,
        'tobranch'    => $dbitem->stage->branchcode_id,
        'datesent'    => dt_from_string(),
        'datearrived' => dt_from_string(),
        'reason'      => "StockrotationAdvance",
    })->store;
    $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
    $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
    is($dbitem->investigate->{reason}, 'not-ready', "older item at stagebranch not-ready.");

    # Test item due for advancement ['advancement']
    $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                fresh         => 0,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    $dbitem->indemand(0)->store;
    $dbitem->stage->duration(50)->store;
    my $sent_duration =  DateTime::Duration->new( days => 55);
    my $arrived_duration =  DateTime::Duration->new( days => 52);
    $dbtransfer = Koha::Item::Transfer->new({
        'itemnumber'  => $dbitem->itemnumber_id,
        'frombranch'  => $dbitem->item->homebranch,
        'tobranch'    => $dbitem->stage->branchcode_id,
        'datesent'    => dt_from_string() - $sent_duration,
        'datearrived' => dt_from_string() - $arrived_duration,
        'reason'      => "StockrotationAdvance",
    })->store;
    $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
    $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
    is($dbitem->investigate->{reason}, 'advancement',
       "Item ready for advancement.");

    # Test item due for advancement but in-demand ['in-demand']
    $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                fresh         => 0,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    $dbitem->indemand(1)->store;
    $dbitem->stage->duration(50)->store;
    $sent_duration =  DateTime::Duration->new( days => 55);
    $arrived_duration =  DateTime::Duration->new( days => 52);
    $dbtransfer = Koha::Item::Transfer->new({
        'itemnumber'  => $dbitem->itemnumber_id,
        'frombranch'  => $dbitem->item->homebranch,
        'tobranch'    => $dbitem->stage->branchcode_id,
        'datesent'    => dt_from_string() - $sent_duration,
        'datearrived' => dt_from_string() - $arrived_duration,
        'reason'      => "StockrotationAdvance",
    })->store;
    $dbitem->item->homebranch($dbitem->stage->branchcode_id)->store;
    $dbitem->item->holdingbranch($dbitem->stage->branchcode_id)->store;
    is($dbitem->investigate->{reason}, 'in-demand',
       "Item advances, but in-demand.");

    # Test item ready for advancement, but at wrong library ['repatriation']
    $sritem = $builder->build(
        {
            source => 'Stockrotationitem',
            value  => {
                fresh         => 0,
                itemnumber_id => $builder->build_sample_item->itemnumber
            }
        }
    );
    $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    $dbitem->indemand(0)->store;
    $dbitem->stage->duration(50)->store;
    $sent_duration =  DateTime::Duration->new( days => 55);
    $arrived_duration =  DateTime::Duration->new( days => 52);
    $dbtransfer = Koha::Item::Transfer->new({
        'itemnumber'  => $dbitem->itemnumber_id,
        'frombranch'  => $dbitem->item->homebranch,
        'tobranch'    => $dbitem->stage->branchcode_id,
        'datesent'    => dt_from_string() - $sent_duration,
        'datearrived' => dt_from_string() - $arrived_duration,
        'reason'      => "StockrotationAdvance",
    })->store;
    is($dbitem->investigate->{reason}, 'repatriation',
       "Item advances, but not at stage branch.");

    $schema->storage->txn_rollback;
};

subtest "Tests for toggle_indemand" => sub {
    plan tests => 15;
    $schema->storage->txn_begin;

    my $sritem = $builder->build({
        source => 'Stockrotationitem',
        value => { 'fresh' => 0, 'indemand' => 0 }
    });
    my $dbitem = Koha::StockRotationItems->find($sritem->{itemnumber_id});
    my $firstbranch = $dbitem->stage->branchcode_id;
    $dbitem->item->holdingbranch($firstbranch)->store;
    my $dbstage = $dbitem->stage;
    $dbstage->position(1)->duration(50)->store; # Configure stage.
    # Configure item
    $dbitem->item->holdingbranch($firstbranch)->store;
    $dbitem->item->homebranch($firstbranch)->store;
    # Sanity check
    is($dbitem->stage->stage_id, $dbstage->stage_id, "Stage sanity check.");

    # Test if an item is not in transfer, toggle always acts.
    is($dbitem->indemand, 0, "Item not in transfer starts with indemand disabled.");
    $dbitem->toggle_indemand;
    is($dbitem->indemand, 1, "Item not in transfer toggled correctly first time.");
    $dbitem->toggle_indemand;
    is($dbitem->indemand, 0, "Item not in transfer toggled correctly second time.");

    # Add stages
    my $srstage = $builder->build({
        source => 'Stockrotationstage',
        value => { duration => 50 }
    });
    my $dbstage2 = Koha::StockRotationStages->find($srstage->{stage_id});
    $dbstage2->move_to_group($dbitem->stage->rota_id);
    $dbstage2->position(2)->store;
    my $secondbranch = $dbstage2->branchcode_id;

    # Test an item in transfer, toggle cancels transfer and resets indemand.
    ok($dbitem->advance, "Advancement done.");
    $dbitem->get_from_storage;
    my $transfer = $dbitem->item->get_transfer;
    is(ref($transfer), 'Koha::Item::Transfer', 'Item set to in transfer as expected');
    is($transfer->frombranch, $firstbranch, 'Transfer from set correctly');
    is($transfer->tobranch, $secondbranch, 'Transfer to set correctly');
    is($transfer->datearrived, undef, 'Transfer datearrived not set');
    $dbitem->toggle_indemand;
    my $updated_transfer = $transfer->get_from_storage;
    is($updated_transfer->frombranch, $firstbranch, 'Transfer from retained correctly');
    is($updated_transfer->tobranch, $firstbranch, 'Transfer to updated correctly');
    isnt($updated_transfer->datearrived, undef, 'Transfer datearrived set as expected');
    is($dbitem->indemand, 0, "Item retains indemand as expected.");
    is($dbitem->stage_id, $dbstage->id, 'Item stage reset as expected.');
    is($dbitem->item->homebranch, $firstbranch, 'Item homebranch reset as expected.');

    $schema->storage->txn_rollback;
};

1;
