Bug 38689: Improve test coverage
This patch drastically enhances the existing tests. We add tests for the various codepaths for handling EDI QUOTES including LIN segment splitting for multi-fund orders. Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
This commit is contained in:
parent
be9d6b7469
commit
13caf0dec9
|
|
@ -20,7 +20,7 @@
|
|||
use Modern::Perl;
|
||||
use FindBin qw( $Bin );
|
||||
|
||||
use Test::More tests => 3;
|
||||
use Test::More tests => 2;
|
||||
use Test::Warn;
|
||||
use Test::MockModule;
|
||||
|
||||
|
|
@ -30,305 +30,617 @@ use t::lib::TestBuilder;
|
|||
|
||||
use Koha::EDI qw(process_quote process_invoice);
|
||||
use Koha::Edifact::Transport;
|
||||
use Koha::Edifact::File::Errors;
|
||||
use Koha::DateUtils qw(dt_from_string);
|
||||
|
||||
my $schema = Koha::Database->new->schema;
|
||||
my $builder = t::lib::TestBuilder->new;
|
||||
my $logger = t::lib::Mocks::Logger->new();
|
||||
|
||||
subtest 'process_quote' => sub {
|
||||
plan tests => 16;
|
||||
plan tests => 5;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# Add our test quote file to the database for testing against
|
||||
my $account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'test vendor', transport => 'FILE',
|
||||
}
|
||||
}
|
||||
);
|
||||
my $dirname = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
|
||||
my $filename = 'QUOTES_SMALL.CEQ';
|
||||
ok( -e $dirname . $filename, 'File QUOTES_SMALL.CEQ found' );
|
||||
|
||||
my $trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
|
||||
my $mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
|
||||
my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
|
||||
# Test quote expects REF to be a valid and active fund code
|
||||
# Common setup for all test cases
|
||||
my $test_san = '5013546098818';
|
||||
my $dirname = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
|
||||
my $active_period = $builder->build(
|
||||
{
|
||||
source => 'Aqbudgetperiod',
|
||||
value => { budget_period_active => 1 }
|
||||
}
|
||||
);
|
||||
my $fund = $builder->build(
|
||||
{
|
||||
source => 'Aqbudget',
|
||||
value => {
|
||||
budget_code => 'REF',
|
||||
budget_period_id => $active_period->{budget_period_id}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# The quote expects a ROT1 stock rotation roata to exist
|
||||
my $rota = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::StockRotationRotas',
|
||||
value => { title => 'ROT1' }
|
||||
}
|
||||
);
|
||||
$builder->build(
|
||||
{
|
||||
source => 'Stockrotationstage',
|
||||
value => { rota_id => $rota->rota_id },
|
||||
}
|
||||
);
|
||||
|
||||
t::lib::Mocks::mock_preference( 'CataloguingLog', 0 );
|
||||
|
||||
# Process the test quote file
|
||||
my $error;
|
||||
eval {
|
||||
process_quote($quote);
|
||||
1;
|
||||
} or do {
|
||||
$error = $@;
|
||||
# Test 1: Basic Quote Processing
|
||||
subtest 'basic_quote_processing' => sub {
|
||||
plan tests => 27;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'test vendor',
|
||||
transport => 'FILE',
|
||||
plugin => '',
|
||||
san => $test_san,
|
||||
orders_enabled => 1,
|
||||
auto_orders => 0,
|
||||
}
|
||||
}
|
||||
);
|
||||
my $ean = $builder->build(
|
||||
{
|
||||
source => 'EdifactEan',
|
||||
value => {
|
||||
description => 'test ean',
|
||||
branchcode => undef,
|
||||
ean => $test_san
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $filename = 'QUOTES_SMALL.CEQ';
|
||||
ok( -e $dirname . $filename, 'File QUOTES_SMALL.CEQ found' );
|
||||
|
||||
# Setup the fund code
|
||||
my $fund = $builder->build(
|
||||
{
|
||||
source => 'Aqbudget',
|
||||
value => {
|
||||
budget_code => 'REF',
|
||||
budget_period_id => $active_period->{budget_period_id}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# Setup stock rotation
|
||||
my $rota = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::StockRotationRotas',
|
||||
value => { title => 'ROT1' }
|
||||
}
|
||||
);
|
||||
$builder->build(
|
||||
{
|
||||
source => 'Stockrotationstage',
|
||||
value => { rota_id => $rota->rota_id },
|
||||
}
|
||||
);
|
||||
|
||||
my $trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
|
||||
my $mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
|
||||
my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
|
||||
ok( $quote, 'Quote message created in database' );
|
||||
is( $quote->status, 'new', 'Initial quote status is new' );
|
||||
|
||||
t::lib::Mocks::mock_preference( 'AcqCreateItem', 'ordering' );
|
||||
|
||||
# Process quote and check results
|
||||
my $die;
|
||||
eval {
|
||||
process_quote($quote);
|
||||
1;
|
||||
} or do {
|
||||
$die = $@;
|
||||
};
|
||||
ok( !$die, 'Basic quote processed without dying' );
|
||||
|
||||
# Test for expected logs for the passed quote file
|
||||
is( $logger->count, 8, "8 log lines recorded for passed quote file" );
|
||||
|
||||
#$logger->diag();
|
||||
$logger->trace_like(
|
||||
qr/Created basket:.*/,
|
||||
"Trace recorded adding basket"
|
||||
)->trace_like(
|
||||
qr/Checking db for matches.*/,
|
||||
"Trace recorded checking db for matches"
|
||||
)->trace_like(
|
||||
qr/Added biblio:.*/,
|
||||
"Trace recoded adding new biblio"
|
||||
)->trace_like(
|
||||
qr/Order created:.*/,
|
||||
"Trace recorded adding order"
|
||||
)->trace_like(
|
||||
qr/Added item:.*/,
|
||||
"Trace recorded adding new item"
|
||||
)->trace_like(
|
||||
qr/Item added to rota.*/,
|
||||
"Trace recrded adding item to rota"
|
||||
)->debug_like(
|
||||
qr/.*specialUpdate biblioserver$/,
|
||||
"Trace recorded biblioserver index"
|
||||
)->clear();
|
||||
|
||||
# No errors expected for QUOTE_SMALL
|
||||
my $errors = Koha::Edifact::File::Errors->search();
|
||||
is( $errors->count, 0, '0 errors recorded for simple quote' );
|
||||
|
||||
# Status changed to received
|
||||
$quote->get_from_storage;
|
||||
is( $quote->status, 'received', 'Quote status set to received' );
|
||||
|
||||
# Generate basket
|
||||
my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
is( $baskets->count, 1, "One basket created for single message quote file" );
|
||||
|
||||
my $basket = $baskets->next;
|
||||
is( $basket->basketname, $filename, "Basket uses EDI filename for name" );
|
||||
|
||||
# Order lines
|
||||
my $orders = $basket->orders;
|
||||
is( $orders->count, 1, "One order line created for single record quote file" );
|
||||
|
||||
my $order = $orders->next;
|
||||
ok( $order->biblionumber, 'Biblionumber assigned to order' );
|
||||
is( $order->entrydate, dt_from_string()->ymd(), 'Entry date set correctly' );
|
||||
|
||||
# Fund allocation
|
||||
$fund = $order->fund;
|
||||
ok( $fund, 'Fund allocated to order' );
|
||||
is( $fund->budget_code, 'REF', 'Correct fund allocated for order' );
|
||||
|
||||
# Test 008 handling
|
||||
my $biblio = $order->biblio;
|
||||
my $record = $biblio->record;
|
||||
my $record_field = $record->field('008');
|
||||
is( exists( $record_field->{_data} ), 1, '008 field added when missing from quote' );
|
||||
|
||||
# Item allocation
|
||||
my $items = $order->items;
|
||||
is(
|
||||
$items->count, 1,
|
||||
"One item created when AcqCreateItem is set to 'ordering' for single record, single quantity quote file"
|
||||
);
|
||||
|
||||
# Test stock rotation handling
|
||||
my $item = $items->next;
|
||||
my $on_rota = Koha::StockRotationItems->search( { itemnumber_id => $item->itemnumber } );
|
||||
is( $on_rota->count, 1, "Item added to rotation" );
|
||||
is( $on_rota->next->stage->rota->id, $rota->id, "Correct rotation assigned" );
|
||||
|
||||
# Confirm no ORDER message generated for 'auto_orders => 0'
|
||||
is( $basket->closedate, undef, 'Basket left open for auto_orders disabled' );
|
||||
my $edi_orders = $schema->resultset('EdifactMessage')->search(
|
||||
{
|
||||
message_type => 'ORDERS',
|
||||
basketno => $basket->basketno,
|
||||
}
|
||||
);
|
||||
is( $edi_orders->count, 0, 'ORDER message not created for auto_orders disabled' );
|
||||
|
||||
$logger->clear();
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
ok( !$error, 'process_quote completed without dying' );
|
||||
|
||||
# Test for expected warnings for the passed quote file
|
||||
is( $logger->count, 8, "8 log lines recorded for passed quote file" );
|
||||
# Test 2: Auto Orders Processing
|
||||
subtest 'auto_orders_processing' => sub {
|
||||
plan tests => 7;
|
||||
|
||||
#$logger->diag();
|
||||
$logger->trace_like(
|
||||
qr/Created basket:.*/,
|
||||
"Trace recorded adding basket"
|
||||
)->trace_like(
|
||||
qr/Checking db for matches.*/,
|
||||
"Trace recorded checking db for matches"
|
||||
)->trace_like(
|
||||
qr/New biblio added.*/,
|
||||
"Trace recoded adding new biblio"
|
||||
)->trace_like(
|
||||
qr/Order created:.*/,
|
||||
"Trace recorded adding order"
|
||||
)->trace_like(
|
||||
qr/Added item:.*/,
|
||||
"Trace recorded adding new item"
|
||||
)->trace_like(
|
||||
qr/Item added to rota.*/,
|
||||
"Trace recrded adding item to rota"
|
||||
)->debug_like(
|
||||
qr/.*specialUpdate biblioserver$/,
|
||||
"Trace recorded biblioserver index"
|
||||
)->clear();
|
||||
$schema->storage->txn_begin;
|
||||
my $account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'auto order vendor',
|
||||
transport => 'FILE',
|
||||
plugin => '',
|
||||
san => $test_san,
|
||||
orders_enabled => 1,
|
||||
auto_orders => 1,
|
||||
}
|
||||
}
|
||||
);
|
||||
my $ean = $builder->build(
|
||||
{
|
||||
source => 'EdifactEan',
|
||||
value => {
|
||||
description => 'test ean',
|
||||
branchcode => undef,
|
||||
ean => $test_san
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# Test for quote status change
|
||||
$quote->get_from_storage;
|
||||
is( $quote->status, 'received', 'Quote status was set to received' );
|
||||
# Setup the fund
|
||||
$builder->build(
|
||||
{
|
||||
source => 'Aqbudget',
|
||||
value => {
|
||||
budget_code => 'REF',
|
||||
budget_period_id => $active_period->{budget_period_id}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# Tests for generated basket for passed quote file
|
||||
my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
is( $baskets->count, 1, "1 basket created for a single quote file" );
|
||||
my $basket = $baskets->next;
|
||||
my $filename = 'QUOTES_SMALL.CEQ';
|
||||
my $trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
|
||||
my $orders = $basket->orders;
|
||||
is( $orders->count, 1, "1 order line attached to basket when only 1 order is in the edi message" );
|
||||
my $order = $orders->next;
|
||||
my $mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
|
||||
my $biblio = $order->biblio;
|
||||
my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
|
||||
my $items = $order->items;
|
||||
is( $items->count, 1, "1 item added when AcqCreateItem eq ordering and 1 item is in the EDI quote" );
|
||||
my $item = $items->next;
|
||||
# Process quote and check results
|
||||
my $die;
|
||||
eval {
|
||||
process_quote($quote);
|
||||
1;
|
||||
} or do {
|
||||
$die = $@;
|
||||
};
|
||||
ok( !$die, 'Basic quote processed, with auto_orders enabled, without dying' );
|
||||
|
||||
# Test that item is added to rota appropriately
|
||||
my $on_rota = Koha::StockRotationItems->search( { itemnumber_id => $item->itemnumber } );
|
||||
is( $on_rota->count, 1, "Item added to stockrotation rota" );
|
||||
my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
is( $baskets->count, 1, "Basket created" );
|
||||
|
||||
my $rota_item = $on_rota->next;
|
||||
is( $rota_item->stage->rota->id, $rota->id, "Item is on correct rota" );
|
||||
my $basket = $baskets->next;
|
||||
ok( $basket->closedate, 'Basket automatically closed for auto_orders' );
|
||||
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
my $orders = $basket->orders;
|
||||
is( $orders->count, 1, "One order created" );
|
||||
|
||||
subtest '_handle_008_field' => sub {
|
||||
plan tests => 4;
|
||||
my $order = $orders->next;
|
||||
ok( $order->biblionumber, 'Biblionumber assigned to order' );
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
# Check EDI order generation
|
||||
my $edi_orders = $schema->resultset('EdifactMessage')->search(
|
||||
{
|
||||
message_type => 'ORDERS',
|
||||
basketno => $basket->basketno,
|
||||
}
|
||||
);
|
||||
is( $edi_orders->count, 1, 'EDI order message created' );
|
||||
is( $edi_orders->next->status, 'Pending', 'EDI order status is Pending' );
|
||||
|
||||
# Add our test quote file to the database for testing against
|
||||
my $account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'test vendor', transport => 'FILE',
|
||||
$logger->clear();
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
# Test 3: Multiple item quote
|
||||
subtest 'multi-item quote' => sub {
|
||||
plan tests => 18;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# Create vendor EDI account
|
||||
my $account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'multi-item vendor',
|
||||
transport => 'FILE',
|
||||
plugin => '',
|
||||
}
|
||||
}
|
||||
);
|
||||
my $ean = $builder->build(
|
||||
{
|
||||
source => 'EdifactEan',
|
||||
value => {
|
||||
description => 'test ean',
|
||||
branchcode => undef,
|
||||
ean => $test_san
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# Setup multiple funds
|
||||
my %funds;
|
||||
for my $code (qw(REF LOAN)) {
|
||||
$funds{$code} = $builder->build(
|
||||
{
|
||||
source => 'Aqbudget',
|
||||
value => {
|
||||
budget_code => $code,
|
||||
budget_period_id => $active_period->{budget_period_id}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
# Setup multiple rota
|
||||
my %rota;
|
||||
for my $title (qw(TEST FAST SLOW)) {
|
||||
$rota{$title} = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::StockRotationRotas',
|
||||
value => { title => $title }
|
||||
}
|
||||
);
|
||||
$builder->build(
|
||||
{
|
||||
source => 'Stockrotationstage',
|
||||
value => { rota_id => $rota{$title}->rota_id },
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
my $description = <<~"END";
|
||||
Loaded QUOTE file with 1 Message that contains 2 LIN segments with the first
|
||||
consistent of 1 item and the second with 3 items with 2 different funds.
|
||||
END
|
||||
diag($description);
|
||||
|
||||
my $filename = 'QUOTES_MULTI.CEQ';
|
||||
my $trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
my $mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
|
||||
my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
process_quote($quote);
|
||||
|
||||
#$logger->diag();
|
||||
|
||||
my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
is( $baskets->count, 1, "One basket created for quote" );
|
||||
|
||||
my $basket = $baskets->next;
|
||||
my $orders = $basket->orders;
|
||||
is( $orders->count, 3, "Three order lines created for quote" );
|
||||
|
||||
my %biblios;
|
||||
my $orderline = 0;
|
||||
while ( my $order = $orders->next ) {
|
||||
$orderline++;
|
||||
diag( "Looking at order: " . $orderline );
|
||||
if ( $orderline == 1 ) {
|
||||
|
||||
# Fund allocation
|
||||
my $fund = $order->fund;
|
||||
is( $fund->budget_code, 'REF', 'Correct fund allocated for first orderline' );
|
||||
|
||||
# Check biblio
|
||||
ok( $order->biblionumber, 'Biblionumber assigned to order' );
|
||||
$biblios{ $order->biblionumber }++;
|
||||
|
||||
# Check items created
|
||||
my $items = $order->items;
|
||||
is( $items->count, 1, 'One item created for the first orderline' );
|
||||
|
||||
# Check first order GIR details
|
||||
my $item = $items->next;
|
||||
my $rota = $item->stockrotationitem;
|
||||
ok( $rota, 'Item was assigned to a rota' );
|
||||
is( $rota->stage->rota->title, 'TEST', "Item was assigned to the correct rota" );
|
||||
|
||||
} elsif ( $orderline == 2 ) {
|
||||
|
||||
# Fund allocation
|
||||
my $fund = $order->fund;
|
||||
is( $fund->budget_code, 'LOAN', 'Correct fund allocated for second orderline' );
|
||||
|
||||
# Check biblio
|
||||
ok( $order->biblionumber, 'Biblionumber assigned to order' );
|
||||
$biblios{ $order->biblionumber }++;
|
||||
|
||||
# Check items created
|
||||
my $items = $order->items;
|
||||
is( $items->count, 2, 'Two items created for the second orderline' );
|
||||
|
||||
# Check second order GIR details
|
||||
my %rotas;
|
||||
while ( my $item = $items->next ) {
|
||||
my $rota = $item->stockrotationitem;
|
||||
ok( $rota, 'Item was assigned to a rota' );
|
||||
$rotas{ $rota->stage->rota->title }++;
|
||||
}
|
||||
is( $rotas{'FAST'}, 1, "One item added to 'FAST' rota" );
|
||||
is( $rotas{'SLOW'}, 1, "One item added to 'SLOW' rota" );
|
||||
} elsif ( $orderline == 3 ) {
|
||||
diag("Second LIN split into 2 Orderlines, one for each Fund");
|
||||
|
||||
# Fund allocation
|
||||
my $fund = $order->fund;
|
||||
is( $fund->budget_code, 'REF', 'Correct fund allocated for third orderline' );
|
||||
|
||||
# Check biblio
|
||||
ok( $order->biblionumber, 'Biblionumber assigned to order' );
|
||||
$biblios{ $order->biblionumber }++;
|
||||
|
||||
# Check items created
|
||||
my $items = $order->items;
|
||||
is( $items->count, 1, 'One item created for the third orderline' );
|
||||
|
||||
# Check first order GIR details
|
||||
my $item = $items->next;
|
||||
my $rota = $item->stockrotationitem;
|
||||
ok( !$rota, 'Item was not assigned to a rota' );
|
||||
}
|
||||
}
|
||||
);
|
||||
my $dirname = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
|
||||
my $filename = 'QUOTES_SMALL.CEQ';
|
||||
ok( -e $dirname . $filename, 'File QUOTES_SMALL.CEQ found' );
|
||||
|
||||
my $trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
$logger->clear();
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
my $mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
# Test 4: Invalid Fund Error Handling
|
||||
subtest 'invalid_fund_handling' => sub {
|
||||
plan tests => 21;
|
||||
|
||||
my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
# Test quote expects REF to be a valid and active fund code
|
||||
my $active_period = $builder->build(
|
||||
{
|
||||
source => 'Aqbudgetperiod',
|
||||
value => { budget_period_active => 1 }
|
||||
}
|
||||
);
|
||||
my $fund = $builder->build(
|
||||
{
|
||||
source => 'Aqbudget',
|
||||
value => {
|
||||
budget_code => 'REF',
|
||||
budget_period_id => $active_period->{budget_period_id}
|
||||
my $account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'error test vendor',
|
||||
transport => 'FILE',
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# The quote expects a ROT1 stock rotation roata to exist
|
||||
my $rota = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::StockRotationRotas',
|
||||
value => { title => 'ROT1' }
|
||||
}
|
||||
);
|
||||
$builder->build(
|
||||
{
|
||||
source => 'Stockrotationstage',
|
||||
value => { rota_id => $rota->rota_id },
|
||||
}
|
||||
);
|
||||
|
||||
# Process the test quote file
|
||||
process_quote($quote);
|
||||
|
||||
$quote->get_from_storage;
|
||||
|
||||
# Tests for generated basket for passed quote file
|
||||
my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
my $basket = $baskets->next;
|
||||
|
||||
my $orders = $basket->orders;
|
||||
my $order = $orders->next;
|
||||
|
||||
my $biblio = $order->biblio;
|
||||
my $record = $biblio->record;
|
||||
my $record_field = $record->field('008');
|
||||
|
||||
is( exists( $record_field->{_data} ), 1, 'Field has been added' );
|
||||
|
||||
# Test without calling the 008 handler
|
||||
$account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'test vendor', transport => 'FILE',
|
||||
);
|
||||
my $ean = $builder->build(
|
||||
{
|
||||
source => 'EdifactEan',
|
||||
value => {
|
||||
description => 'test ean',
|
||||
branchcode => undef,
|
||||
ean => $test_san
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
$dirname = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
|
||||
$filename = 'QUOTES_SMALL_2.CEQ';
|
||||
ok( -e $dirname . $filename, 'File QUOTES_SMALL_2.CEQ found' );
|
||||
);
|
||||
|
||||
$trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
my $description = <<~"END";
|
||||
Loading QUOTE file with 1 Message that contains 2 LIN segments with the first
|
||||
consistent of 1 item and the second with 3 items with 2 different undefined funds.
|
||||
END
|
||||
diag($description);
|
||||
|
||||
$mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
my $filename = 'QUOTES_MULTI.CEQ';
|
||||
my $trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
|
||||
$quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
my $mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
|
||||
# Test quote expects REF to be a valid and active fund code
|
||||
$active_period = $builder->build(
|
||||
{
|
||||
source => 'Aqbudgetperiod',
|
||||
value => { budget_period_active => 1 }
|
||||
}
|
||||
);
|
||||
$fund = $builder->build(
|
||||
{
|
||||
source => 'Aqbudget',
|
||||
value => {
|
||||
budget_code => 'REF2',
|
||||
budget_period_id => $active_period->{budget_period_id}
|
||||
my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
|
||||
process_quote($quote);
|
||||
|
||||
#$logger->diag();
|
||||
$logger->trace_like(
|
||||
qr/Created basket:.*/,
|
||||
"Trace recorded basket added"
|
||||
)->trace_is(
|
||||
qq/Checking db for matches with 9781529923766/,
|
||||
"Trace recorded isbn lookup"
|
||||
)->trace_like(
|
||||
qr/Added biblio:.*/,
|
||||
"Trace recorded adding new biblio"
|
||||
)->trace_is(
|
||||
qq/Skipping orderline with invalid budget: REF/,
|
||||
"Trace recorded skipping orderline with invalid fund"
|
||||
)->trace_is(
|
||||
qq/Checking db for matches with 9781785044342/,
|
||||
"Trace recorded isbn lookup"
|
||||
)->trace_like(
|
||||
qr/Added biblio:.*/,
|
||||
"Trace recorded adding new biblio"
|
||||
)->trace_is(
|
||||
qq/Skipping item with invalid budget: LOAN/,
|
||||
"Trace recorded skipping item with invalid fund"
|
||||
)->trace_is(
|
||||
qq/Skipping item with invalid budget: REF/,
|
||||
"Trace recorded skipping item with invalid fund"
|
||||
)->trace_is(
|
||||
qq/Skipping item with invalid budget: LOAN/,
|
||||
"Trace recorded skipping item with invalid fund"
|
||||
);
|
||||
|
||||
# Errors should be recorded for skipped sections
|
||||
my $errors = Koha::Edifact::File::Errors->search();
|
||||
is( $errors->count, 4, '4 errors recorded for missing funds in quote' );
|
||||
|
||||
my $error = $errors->next;
|
||||
ok( $error->section, 'First error section is present' );
|
||||
is( $error->details, 'Skipped orderline line with invalid budget: REF', 'First error details is correct' );
|
||||
|
||||
$error = $errors->next;
|
||||
ok( $error->section, 'Second error section is present' );
|
||||
is( $error->details, 'Skipped GIR line with invalid budget: LOAN', 'Second error details is correct' );
|
||||
|
||||
$error = $errors->next;
|
||||
ok( $error->section, 'Third error section is present' );
|
||||
is( $error->details, 'Invalid budget REF found', 'Third error details is correct' );
|
||||
|
||||
$error = $errors->next;
|
||||
ok( $error->section, 'Fourth error section is present' );
|
||||
is( $error->details, 'Invalid budget LOAN found', 'Fourth error details is correct' );
|
||||
|
||||
$quote->get_from_storage;
|
||||
is( $quote->status, 'error', 'Quote status set to error for invalid fund' );
|
||||
|
||||
my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
is( $baskets->count, 1, 'Basket still created despite errors' );
|
||||
|
||||
my $orders = $baskets->next->orders;
|
||||
is( $orders->count, 0, 'No orders created with invalid fund' );
|
||||
|
||||
$logger->clear();
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
# Test 5: Multiple message quote file
|
||||
subtest 'multiple_message_handling' => sub {
|
||||
plan tests => 3;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
my $account = $builder->build(
|
||||
{
|
||||
source => 'VendorEdiAccount',
|
||||
value => {
|
||||
description => 'error test vendor',
|
||||
transport => 'FILE',
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
my $ean = $builder->build(
|
||||
{
|
||||
source => 'EdifactEan',
|
||||
value => {
|
||||
description => 'test ean',
|
||||
branchcode => undef,
|
||||
ean => $test_san
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
# The quote expects a ROT1 stock rotation roata to exist
|
||||
$rota = $builder->build_object(
|
||||
{
|
||||
class => 'Koha::StockRotationRotas',
|
||||
value => { title => 'ROT2' }
|
||||
}
|
||||
);
|
||||
$builder->build(
|
||||
{
|
||||
source => 'Stockrotationstage',
|
||||
value => { rota_id => $rota->rota_id },
|
||||
}
|
||||
);
|
||||
my $description = <<~"END";
|
||||
Loading QUOTE file with 2 messages
|
||||
END
|
||||
diag($description);
|
||||
|
||||
# Process the test quote file
|
||||
my $edi_module = Test::MockModule->new('Koha::EDI');
|
||||
$edi_module->mock(
|
||||
'_check_for_existing_bib',
|
||||
sub {
|
||||
my $bib_record = shift;
|
||||
return;
|
||||
}
|
||||
);
|
||||
$edi_module->mock(
|
||||
'_handle_008_field',
|
||||
sub {
|
||||
my $bib_record = shift;
|
||||
return $bib_record;
|
||||
}
|
||||
);
|
||||
process_quote($quote);
|
||||
my $filename = 'QUOTES_BIG.CEQ';
|
||||
my $trans = Koha::Edifact::Transport->new( $account->{id} );
|
||||
$trans->working_directory($dirname);
|
||||
|
||||
$quote->get_from_storage;
|
||||
my $mhash = $trans->message_hash();
|
||||
$mhash->{message_type} = 'QUOTE';
|
||||
$trans->ingest( $mhash, $filename );
|
||||
|
||||
# Tests for generated basket for passed quote file
|
||||
$baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
$basket = $baskets->next;
|
||||
my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
|
||||
$orders = $basket->orders;
|
||||
$order = $orders->next;
|
||||
process_quote($quote);
|
||||
|
||||
$biblio = $order->biblio;
|
||||
$record = $biblio->record;
|
||||
$record_field = $record->field('008');
|
||||
#$logger->diag();
|
||||
|
||||
is( $record_field->{_data}, undef, 'Field has not been added' );
|
||||
my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
|
||||
is( $baskets->count, 2, 'Two baskets added for file containing 2 messages' );
|
||||
|
||||
# First basket
|
||||
my $basket = $baskets->next;
|
||||
is( $basket->basketname, $filename, "Basket uses EDI filename for name" );
|
||||
|
||||
# Second basket
|
||||
$basket = $baskets->next;
|
||||
is( $basket->basketname, $filename, "Basket uses EDI filename for name" );
|
||||
|
||||
$logger->clear();
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
# Clean up
|
||||
$logger->clear();
|
||||
$schema->storage->txn_rollback;
|
||||
};
|
||||
|
||||
subtest 'process_invoice' => sub {
|
||||
plan tests => 19;
|
||||
plan tests => 32;
|
||||
|
||||
$schema->storage->txn_begin;
|
||||
|
||||
|
|
@ -392,8 +704,8 @@ subtest 'process_invoice' => sub {
|
|||
|
||||
my $invoice_message = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
|
||||
my $raw_msg = $invoice_message->raw_msg;
|
||||
$raw_msg =~ s/P12345/$ordernumber1/g;
|
||||
$raw_msg =~ s/P54321/$ordernumber2/g;
|
||||
$raw_msg =~ s/ORDERNUMBER1/$ordernumber1/g;
|
||||
$raw_msg =~ s/ORDERNUMBER2/$ordernumber2/g;
|
||||
$invoice_message->update( { raw_msg => $raw_msg } );
|
||||
|
||||
# Process the test invoice file
|
||||
|
|
@ -403,6 +715,7 @@ subtest 'process_invoice' => sub {
|
|||
1;
|
||||
} or do {
|
||||
$error = $@;
|
||||
diag($error);
|
||||
};
|
||||
ok( !$error, 'process_invoice completed without dying' );
|
||||
|
||||
|
|
@ -453,6 +766,49 @@ subtest 'process_invoice' => sub {
|
|||
'Warn recorded for unmatched item'
|
||||
)->clear();
|
||||
|
||||
# Errors should be recorded for skipped sections
|
||||
my $errors = Koha::Edifact::File::Errors->search();
|
||||
is( $errors->count, 6, '6 errors recorded for invoice' );
|
||||
|
||||
my @expected_errors = (
|
||||
{
|
||||
'section' =>
|
||||
"QTY+47:5\nGIR+001+DIT:LLO+34148000123456:LAC+P28837:LCO+DITATB:LFN\nPRI+AAA:9.99\nPRI+AAB:12.99\nMOA+203:49.95\nMOA+52:15.00",
|
||||
'details' => 'Skipped invoice line 1, missing ordernumber'
|
||||
},
|
||||
{
|
||||
'section' =>
|
||||
"QTY+47:5\nGIR+001+HLE:LLO+34148000123457:LAC+P28838:LCO+HLEATB:LFN\nPRI+AAA:9.99\nPRI+AAB:12.99\nMOA+203:49.95\nMOA+52:15.00\nRFF+LI:P28837",
|
||||
'details' => 'Skipped invoice line 2, cannot find order with ordernumber P28837'
|
||||
},
|
||||
{
|
||||
'section' =>
|
||||
"QTY+47:10\nGIR+001+RUN:LLO+34148000123458:LAC+P28839:LCO+RUNATB:LFN\nPRI+AAA:15.00\nPRI+AAB:18.00\nMOA+203:150.00\nMOA+52:30.00\nRFF+LI:$ordernumber1",
|
||||
'details' => "Skipped invoice line 3, cannot find biblio for ordernumber $ordernumber1"
|
||||
},
|
||||
{
|
||||
'section' =>
|
||||
"QTY+47:1\nGIR+001+WID:LLO+34148000123459:LAC+P28840:LCO+WIDATB:LFN\nPRI+AAA:30.00\nPRI+AAB:35.00\nMOA+203:600.00\nMOA+52:5.00\nRFF+LI:$ordernumber2",
|
||||
'details' => 'No matching item found for invoice line 4:0 at branch WID'
|
||||
},
|
||||
{
|
||||
'section' =>
|
||||
"QTY+47:1\nGIR+001+DIT:LLO+34148000123460:LAC+P54322:LCO+DITATB:LFN\nPRI+AAA:5.00\nPRI+AAB:6.00\nMOA+203:5.00\nMOA+52:1.00\nRFF+LI:$ordernumber2",
|
||||
'details' => 'No matching item found for invoice line 5:0 at branch DIT'
|
||||
},
|
||||
{
|
||||
'section' => "NAD+SU+9999999999999",
|
||||
'details' => 'Skipped invoice INV00002 with unmatched vendor san: 9999999999999'
|
||||
}
|
||||
);
|
||||
|
||||
my $index = 0;
|
||||
while ( my $error = $errors->next ) {
|
||||
is( $error->section, $expected_errors[$index]->{section}, "Error $index section is correct" );
|
||||
is( $error->details, $expected_errors[$index]->{details}, "Error $index details is correct" );
|
||||
$index++;
|
||||
}
|
||||
|
||||
my $invoice3 = Koha::Acquisition::Invoices->search( { invoicenumber => 'INV00003' }, { rows => 1 } )->single;
|
||||
ok( $invoice3, "Invoice added to database" );
|
||||
is( $invoice3->booksellerid, $account->{vendor_id}, 'Invoice has test booksellerid' );
|
||||
|
|
|
|||
|
|
@ -1,2 +1 @@
|
|||
UNA:+.? 'UNB+UNOC:3+5013546027173+5013546098818+230101:0000+0000000002'UNH+00003+INVOIC:D:96A:UN'BGM+380+INV00003+9'DTM+137:20231210:102'NAD+BY+12345::9'NAD+SU+5013546027173::9'LIN+1++987654321:EN'QTY+47:5'PRI+AAA:9.99'MOA+203:49.95'LIN+2++987654321:EN'QTY+47:5'PRI+AAA:9.99'MOA+203:49.95'RFF+LI:P28837'LIN+3++999999999:EN'QTY+47:10'PRI+AAA:15.00'MOA+203:150.00'RFF+LI:P12345'LIN+4++123456789:EN'QTY+47:1'PRI+AAA:30.00'MOA+203:600.00'RFF+LI:P54321'LIN+5++987654123:EN'QTY+47:1'PRI+AAA:5.00'MOA+203:5.00'RFF+LI:P54321'UNS+S'CNT+4:4'UNT+15+00003'UNZ+1+0000000002'
|
||||
UNA:+.? 'UNB+UNOC:3+9999999999999+5013546098818+230101:0000+0000000001'UNH+00002+INVOIC:D:96A:UN'BGM+380+INV00002+9'DTM+137:20231210:102'NAD+BY+54321::9'NAD+SU+9999999999999::9'UNS+S'CNT+1:1'UNT+11+00002'
|
||||
UNA:+.? 'UNB+UNOC:3+5013546027173+5013546098818+230101:0000+0000000002'UNH+00003+INVOIC:D:96A:UN'BGM+380+INV00003+9'DTM+137:20231210:102'NAD+BY+12345::9'NAD+SU+5013546027173::9'LIN+1++987654321:EN'QTY+47:5'GIR+001+DIT:LLO+34148000123456:LAC+P28837:LCO+DITATB:LFN'PRI+AAA:9.99'PRI+AAB:12.99'MOA+203:49.95'MOA+52:15.00'LIN+2++987654321:EN'QTY+47:5'GIR+001+HLE:LLO+34148000123457:LAC+P28838:LCO+HLEATB:LFN'PRI+AAA:9.99'PRI+AAB:12.99'MOA+203:49.95'MOA+52:15.00'RFF+LI:P28837'LIN+3++999999999:EN'QTY+47:10'GIR+001+RUN:LLO+34148000123458:LAC+P28839:LCO+RUNATB:LFN'PRI+AAA:15.00'PRI+AAB:18.00'MOA+203:150.00'MOA+52:30.00'RFF+LI:ORDERNUMBER1'LIN+4++123456789:EN'QTY+47:1'GIR+001+WID:LLO+34148000123459:LAC+P28840:LCO+WIDATB:LFN'PRI+AAA:30.00'PRI+AAB:35.00'MOA+203:600.00'MOA+52:5.00'RFF+LI:ORDERNUMBER2'LIN+5++987654123:EN'QTY+47:1'GIR+001+DIT:LLO+34148000123460:LAC+P54322:LCO+DITATB:LFN'PRI+AAA:5.00'PRI+AAB:6.00'MOA+203:5.00'MOA+52:1.00'RFF+LI:ORDERNUMBER2'UNS+S'CNT+4:4'MOA+79:854.90'MOA+129:854.90'MOA+122:854.90'UNT+15+00003'UNZ+1+0000000002''UNA:+.? 'UNB+UNOC:3+9999999999999+5013546098818+230101:0000+0000000001'UNH+00002+INVOIC:D:96A:UN'BGM+380+INV00002+9'DTM+137:20231210:102'NAD+BY+54321::9'NAD+SU+9999999999999::9'UNS+S'CNT+1:1'UNT+11+00002'''
|
||||
|
|
@ -0,0 +1 @@
|
|||
UNA:+.? 'UNB+UNOC:3+5013546027173+5013546098818+240123:0945+1044416+ASKEDI:+QUOTES++++'UNH+1044416001+QUOTES:D:96A:UN:EAN002'BGM+31C::28+WO0800131+9'DTM+137:20240123:102'RFF+ON:orders 23/1'CUX+2:GBP:12'NAD+BY+5013546098818::9'NAD+SU+5013546027173::9'LIN+1++9781529923766:EN'PIA+5+152992376X:IB'IMD+L+010+:::Thompson'IMD+L+011+:::Louise'IMD+L+050+:::Lucky'IMD+L+060+:::learning to live again'IMD+L+120+:::Ebury Spotlight'IMD+L+170+:::2024'IMD+L+180+:::304'IMD+L+220+:::Hbk'IMD+L+230+:::791.45'IMD+L+250+:::AN'QTY+1:1'GIR+001+BOOK:LST+ANF:LSQ+CPL:LLO+REF:LFN+791.45:LCL'GIR+001+22.00:LCV'GIR+001+ROT1:LRP'PRI+AAE:22.00'RFF+QLI:WO0800131000001'UNS+S'CNT+2:1'UNT+27+1044416001'UNZ+1+1044416'UNA:+.? 'UNB+UNOC:3+5013546027173+5013546098818+230713:1031+1044417+ASKEDI+QUOTES++++'UNH+1+QUOTES:D:96A:UN:EAN002'BGM+31C::28+WO0800132+9'DTM+137:20230713:102'NAD+BY+5412345000013::9'NAD+SU+4012345000094::9'CUX+2:GBP:9'LIN+1++9781529923766:EN'PIA+1+152992376X:SA'IMD+L+010+:::Thompson'IMD+L+011+:::Louise'IMD+L+050+:::Lucky'IMD+L+060+:::Learning to live again'GIR+001+BOOK:LST+ANF:LSQ+CPL:LLO+REF:LFN+791.45:LCL'GIR+001+22.00:LCV'GIR+001+TEST:LRP'QTY+21:1:PCE'MOA+203:25.99'RFF+ABO:REF'LIN+2++9781785044342:EN'PIA+5+1785044346:IB'IMD+L+010+:::Hansen'IMD+L+011+:::Anders'IMD+L+050+:::The attention fix'IMD+L+060+:::how to focus in a world that wants to distract you'QTY+1:3'GIR+001+BOOK:LST+ANF:LSQ+CPL:LLO+LOAN:LFN+153.733:LCL'GIR+001+14.99:LCV'GIR+001+FAST:LRP'GIR+002+BOOK:LST+ANF:LSQ+FFL:LLO+REF:LFN+153.733:LCL'GIR+002+14.99:LCV'GIR+003+BOOK:LST+ANF:LSQ+FPL:LLO+LOAN:LFN+153.733:LCL'GIR+003+14.99:LCV'GIR+003+SLOW:LRP'PRI+AAE:14.99'RFF+QLI:WO0774049000002'UNS+S'MOA+86:87.97'UNT+34+1'UNZ+1+1'
|
||||
|
|
@ -0,0 +1 @@
|
|||
UNA:+.? 'UNB+UNOC:3+5013546027173+5013546098818+230713:1031+1044417+ASKEDI+QUOTES++++'UNH+1+QUOTES:D:96A:UN:EAN002'BGM+31C::28+WO0800132+9'DTM+137:20230713:102'NAD+BY+5412345000013::9'NAD+SU+4012345000094::9'CUX+2:GBP:9'LIN+1++9781529923766:EN'PIA+1+152992376X:SA'IMD+L+010+:::Thompson'IMD+L+011+:::Louise'IMD+L+050+:::Lucky'IMD+L+060+:::Learning to live again'GIR+001+BOOK:LST+ANF:LSQ+CPL:LLO+REF:LFN+791.45:LCL'GIR+001+22.00:LCV'GIR+001+TEST:LRP'QTY+21:1:PCE'MOA+203:25.99'RFF+ABO:REF'LIN+2++9781785044342:EN'PIA+5+1785044346:IB'IMD+L+010+:::Hansen'IMD+L+011+:::Anders'IMD+L+050+:::The attention fix'IMD+L+060+:::how to focus in a world that wants to distract you'QTY+1:3'GIR+001+BOOK:LST+ANF:LSQ+CPL:LLO+LOAN:LFN+153.733:LCL'GIR+001+14.99:LCV'GIR+001+FAST:LRP'GIR+002+BOOK:LST+ANF:LSQ+FFL:LLO+REF:LFN+153.733:LCL'GIR+002+14.99:LCV'GIR+003+BOOK:LST+ANF:LSQ+FPL:LLO+LOAN:LFN+153.733:LCL'GIR+003+14.99:LCV'GIR+003+SLOW:LRP'PRI+AAE:14.99'RFF+QLI:WO0774049000002'UNS+S'MOA+86:87.97'UNT+34+1'UNZ+1+1'
|
||||
Loading…
Reference in New Issue