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

(-)a/t/db_dependent/Koha/EDI.t (-237 / +593 lines)
Lines 20-26 Link Here
20
use Modern::Perl;
20
use Modern::Perl;
21
use FindBin qw( $Bin );
21
use FindBin qw( $Bin );
22
22
23
use Test::More tests => 3;
23
use Test::More tests => 2;
24
use Test::Warn;
24
use Test::Warn;
25
use Test::MockModule;
25
use Test::MockModule;
26
26
Lines 30-334 use t::lib::TestBuilder; Link Here
30
30
31
use Koha::EDI qw(process_quote process_invoice);
31
use Koha::EDI qw(process_quote process_invoice);
32
use Koha::Edifact::Transport;
32
use Koha::Edifact::Transport;
33
use Koha::Edifact::File::Errors;
34
use Koha::DateUtils qw(dt_from_string);
33
35
34
my $schema  = Koha::Database->new->schema;
36
my $schema  = Koha::Database->new->schema;
35
my $builder = t::lib::TestBuilder->new;
37
my $builder = t::lib::TestBuilder->new;
36
my $logger  = t::lib::Mocks::Logger->new();
38
my $logger  = t::lib::Mocks::Logger->new();
37
39
38
subtest 'process_quote' => sub {
40
subtest 'process_quote' => sub {
39
    plan tests => 16;
41
    plan tests => 5;
40
42
41
    $schema->storage->txn_begin;
43
    $schema->storage->txn_begin;
42
44
43
    # Add our test quote file to the database for testing against
45
    # Common setup for all test cases
44
    my $account = $builder->build(
46
    my $test_san      = '5013546098818';
45
        {
47
    my $dirname       = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
46
            source => 'VendorEdiAccount',
47
            value  => {
48
                description => 'test vendor', transport => 'FILE',
49
            }
50
        }
51
    );
52
    my $dirname  = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
53
    my $filename = 'QUOTES_SMALL.CEQ';
54
    ok( -e $dirname . $filename, 'File QUOTES_SMALL.CEQ found' );
55
56
    my $trans = Koha::Edifact::Transport->new( $account->{id} );
57
    $trans->working_directory($dirname);
58
59
    my $mhash = $trans->message_hash();
60
    $mhash->{message_type} = 'QUOTE';
61
    $trans->ingest( $mhash, $filename );
62
63
    my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
64
65
    # Test quote expects REF to be a valid and active fund code
66
    my $active_period = $builder->build(
48
    my $active_period = $builder->build(
67
        {
49
        {
68
            source => 'Aqbudgetperiod',
50
            source => 'Aqbudgetperiod',
69
            value  => { budget_period_active => 1 }
51
            value  => { budget_period_active => 1 }
70
        }
52
        }
71
    );
53
    );
72
    my $fund = $builder->build(
54
    t::lib::Mocks::mock_preference( 'CataloguingLog', 0 );
73
        {
74
            source => 'Aqbudget',
75
            value  => {
76
                budget_code      => 'REF',
77
                budget_period_id => $active_period->{budget_period_id}
78
            }
79
        }
80
    );
81
55
82
    # The quote expects a ROT1 stock rotation roata to exist
56
    # Test 1: Basic Quote Processing
83
    my $rota = $builder->build_object(
57
    subtest 'basic_quote_processing' => sub {
84
        {
58
        plan tests => 27;
85
            class => 'Koha::StockRotationRotas',
59
86
            value => { title => 'ROT1' }
60
        $schema->storage->txn_begin;
87
        }
61
88
    );
62
        my $account = $builder->build(
89
    $builder->build(
63
            {
90
        {
64
                source => 'VendorEdiAccount',
91
            source => 'Stockrotationstage',
65
                value  => {
92
            value  => { rota_id => $rota->rota_id },
66
                    description    => 'test vendor',
93
        }
67
                    transport      => 'FILE',
94
    );
68
                    plugin         => '',
69
                    san            => $test_san,
70
                    orders_enabled => 1,
71
                    auto_orders    => 0,
72
                }
73
            }
74
        );
75
        my $ean = $builder->build(
76
            {
77
                source => 'EdifactEan',
78
                value  => {
79
                    description => 'test ean',
80
                    branchcode  => undef,
81
                    ean         => $test_san
82
                }
83
            }
84
        );
85
86
        my $filename = 'QUOTES_SMALL.CEQ';
87
        ok( -e $dirname . $filename, 'File QUOTES_SMALL.CEQ found' );
88
89
        # Setup the fund code
90
        my $fund = $builder->build(
91
            {
92
                source => 'Aqbudget',
93
                value  => {
94
                    budget_code      => 'REF',
95
                    budget_period_id => $active_period->{budget_period_id}
96
                }
97
            }
98
        );
95
99
96
    t::lib::Mocks::mock_preference( 'CataloguingLog', 0 );
100
        # Setup stock rotation
101
        my $rota = $builder->build_object(
102
            {
103
                class => 'Koha::StockRotationRotas',
104
                value => { title => 'ROT1' }
105
            }
106
        );
107
        $builder->build(
108
            {
109
                source => 'Stockrotationstage',
110
                value  => { rota_id => $rota->rota_id },
111
            }
112
        );
113
114
        my $trans = Koha::Edifact::Transport->new( $account->{id} );
115
        $trans->working_directory($dirname);
116
117
        my $mhash = $trans->message_hash();
118
        $mhash->{message_type} = 'QUOTE';
119
        $trans->ingest( $mhash, $filename );
120
121
        my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
122
123
        ok( $quote, 'Quote message created in database' );
124
        is( $quote->status, 'new', 'Initial quote status is new' );
125
126
        t::lib::Mocks::mock_preference( 'AcqCreateItem', 'ordering' );
127
128
        # Process quote and check results
129
        my $die;
130
        eval {
131
            process_quote($quote);
132
            1;
133
        } or do {
134
            $die = $@;
135
        };
136
        ok( !$die, 'Basic quote processed without dying' );
137
138
        # Test for expected logs for the passed quote file
139
        is( $logger->count, 8, "8 log lines recorded for passed quote file" );
140
141
        #$logger->diag();
142
        $logger->trace_like(
143
            qr/Created basket:.*/,
144
            "Trace recorded adding basket"
145
        )->trace_like(
146
            qr/Checking db for matches.*/,
147
            "Trace recorded checking db for matches"
148
        )->trace_like(
149
            qr/Added biblio:.*/,
150
            "Trace recoded adding new biblio"
151
        )->trace_like(
152
            qr/Order created:.*/,
153
            "Trace recorded adding order"
154
        )->trace_like(
155
            qr/Added item:.*/,
156
            "Trace recorded adding new item"
157
        )->trace_like(
158
            qr/Item added to rota.*/,
159
            "Trace recrded adding item to rota"
160
        )->debug_like(
161
            qr/.*specialUpdate biblioserver$/,
162
            "Trace recorded biblioserver index"
163
        )->clear();
164
165
        # No errors expected for QUOTE_SMALL
166
        my $errors = Koha::Edifact::File::Errors->search();
167
        is( $errors->count, 0, '0 errors recorded for simple quote' );
168
169
        # Status changed to received
170
        $quote->get_from_storage;
171
        is( $quote->status, 'received', 'Quote status set to received' );
172
173
        # Generate basket
174
        my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
175
        is( $baskets->count, 1, "One basket created for single message quote file" );
176
177
        my $basket = $baskets->next;
178
        is( $basket->basketname, $filename, "Basket uses EDI filename for name" );
179
180
        # Order lines
181
        my $orders = $basket->orders;
182
        is( $orders->count, 1, "One order line created for single record quote file" );
183
184
        my $order = $orders->next;
185
        ok( $order->biblionumber, 'Biblionumber assigned to order' );
186
        is( $order->entrydate, dt_from_string()->ymd(), 'Entry date set correctly' );
187
188
        # Fund allocation
189
        $fund = $order->fund;
190
        ok( $fund, 'Fund allocated to order' );
191
        is( $fund->budget_code, 'REF', 'Correct fund allocated for order' );
192
193
        # Test 008 handling
194
        my $biblio       = $order->biblio;
195
        my $record       = $biblio->record;
196
        my $record_field = $record->field('008');
197
        is( exists( $record_field->{_data} ), 1, '008 field added when missing from quote' );
198
199
        # Item allocation
200
        my $items = $order->items;
201
        is(
202
            $items->count, 1,
203
            "One item created when AcqCreateItem is set to 'ordering' for single record, single quantity quote file"
204
        );
205
206
        # Test stock rotation handling
207
        my $item    = $items->next;
208
        my $on_rota = Koha::StockRotationItems->search( { itemnumber_id => $item->itemnumber } );
209
        is( $on_rota->count,                 1,         "Item added to rotation" );
210
        is( $on_rota->next->stage->rota->id, $rota->id, "Correct rotation assigned" );
211
212
        # Confirm no ORDER message generated for 'auto_orders => 0'
213
        is( $basket->closedate, undef, 'Basket left open for auto_orders disabled' );
214
        my $edi_orders = $schema->resultset('EdifactMessage')->search(
215
            {
216
                message_type => 'ORDERS',
217
                basketno     => $basket->basketno,
218
            }
219
        );
220
        is( $edi_orders->count, 0, 'ORDER message not created for auto_orders disabled' );
97
221
98
    # Process the test quote file
222
        $logger->clear();
99
    my $error;
223
        $schema->storage->txn_rollback;
100
    eval {
101
        process_quote($quote);
102
        1;
103
    } or do {
104
        $error = $@;
105
    };
224
    };
106
    ok( !$error, 'process_quote completed without dying' );
107
108
    # Test for expected warnings for the passed quote file
109
    is( $logger->count, 8, "8 log lines recorded for passed quote file" );
110
225
111
    #$logger->diag();
226
    # Test 2: Auto Orders Processing
112
    $logger->trace_like(
227
    subtest 'auto_orders_processing' => sub {
113
        qr/Created basket:.*/,
228
        plan tests => 7;
114
        "Trace recorded adding basket"
229
115
    )->trace_like(
230
        $schema->storage->txn_begin;
116
        qr/Checking db for matches.*/,
231
        my $account = $builder->build(
117
        "Trace recorded checking db for matches"
232
            {
118
    )->trace_like(
233
                source => 'VendorEdiAccount',
119
        qr/New biblio added.*/,
234
                value  => {
120
        "Trace recoded adding new biblio"
235
                    description    => 'auto order vendor',
121
    )->trace_like(
236
                    transport      => 'FILE',
122
        qr/Order created:.*/,
237
                    plugin         => '',
123
        "Trace recorded adding order"
238
                    san            => $test_san,
124
    )->trace_like(
239
                    orders_enabled => 1,
125
        qr/Added item:.*/,
240
                    auto_orders    => 1,
126
        "Trace recorded adding new item"
241
                }
127
    )->trace_like(
242
            }
128
        qr/Item added to rota.*/,
243
        );
129
        "Trace recrded adding item to rota"
244
        my $ean = $builder->build(
130
    )->debug_like(
245
            {
131
        qr/.*specialUpdate biblioserver$/,
246
                source => 'EdifactEan',
132
        "Trace recorded biblioserver index"
247
                value  => {
133
    )->clear();
248
                    description => 'test ean',
249
                    branchcode  => undef,
250
                    ean         => $test_san
251
                }
252
            }
253
        );
254
255
        # Setup the fund
256
        $builder->build(
257
            {
258
                source => 'Aqbudget',
259
                value  => {
260
                    budget_code      => 'REF',
261
                    budget_period_id => $active_period->{budget_period_id}
262
                }
263
            }
264
        );
134
265
135
    # Test for quote status change
266
        my $filename = 'QUOTES_SMALL.CEQ';
136
    $quote->get_from_storage;
267
        my $trans    = Koha::Edifact::Transport->new( $account->{id} );
137
    is( $quote->status, 'received', 'Quote status was set to received' );
268
        $trans->working_directory($dirname);
138
269
139
    # Tests for generated basket for passed quote file
270
        my $mhash = $trans->message_hash();
140
    my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
271
        $mhash->{message_type} = 'QUOTE';
141
    is( $baskets->count, 1, "1 basket created for a single quote file" );
272
        $trans->ingest( $mhash, $filename );
142
    my $basket = $baskets->next;
143
273
144
    my $orders = $basket->orders;
274
        my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
145
    is( $orders->count, 1, "1 order line attached to basket when only 1 order is in the edi message" );
146
    my $order = $orders->next;
147
275
148
    my $biblio = $order->biblio;
276
        # Process quote and check results
277
        my $die;
278
        eval {
279
            process_quote($quote);
280
            1;
281
        } or do {
282
            $die = $@;
283
        };
284
        ok( !$die, 'Basic quote processed, with auto_orders enabled, without dying' );
149
285
150
    my $items = $order->items;
286
        my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
151
    is( $items->count, 1, "1 item added when AcqCreateItem eq ordering and 1 item is in the EDI quote" );
287
        is( $baskets->count, 1, "Basket created" );
152
    my $item = $items->next;
153
288
154
    # Test that item is added to rota appropriately
289
        my $basket = $baskets->next;
155
    my $on_rota = Koha::StockRotationItems->search( { itemnumber_id => $item->itemnumber } );
290
        ok( $basket->closedate, 'Basket automatically closed for auto_orders' );
156
    is( $on_rota->count, 1, "Item added to stockrotation rota" );
157
291
158
    my $rota_item = $on_rota->next;
292
        my $orders = $basket->orders;
159
    is( $rota_item->stage->rota->id, $rota->id, "Item is on correct rota" );
293
        is( $orders->count, 1, "One order created" );
160
294
161
    $schema->storage->txn_rollback;
295
        my $order = $orders->next;
162
};
296
        ok( $order->biblionumber, 'Biblionumber assigned to order' );
163
297
164
subtest '_handle_008_field' => sub {
298
        # Check EDI order generation
165
    plan tests => 4;
299
        my $edi_orders = $schema->resultset('EdifactMessage')->search(
300
            {
301
                message_type => 'ORDERS',
302
                basketno     => $basket->basketno,
303
            }
304
        );
305
        is( $edi_orders->count,        1,         'EDI order message created' );
306
        is( $edi_orders->next->status, 'Pending', 'EDI order status is Pending' );
166
307
167
    $schema->storage->txn_begin;
308
        $logger->clear();
309
        $schema->storage->txn_rollback;
310
    };
168
311
169
    # Add our test quote file to the database for testing against
312
    # Test 3: Multiple item quote
170
    my $account = $builder->build(
313
    subtest 'multi-item quote' => sub {
171
        {
314
        plan tests => 18;
172
            source => 'VendorEdiAccount',
315
173
            value  => {
316
        $schema->storage->txn_begin;
174
                description => 'test vendor', transport => 'FILE',
317
318
        # Create vendor EDI account
319
        my $account = $builder->build(
320
            {
321
                source => 'VendorEdiAccount',
322
                value  => {
323
                    description => 'multi-item vendor',
324
                    transport   => 'FILE',
325
                    plugin      => '',
326
                }
327
            }
328
        );
329
        my $ean = $builder->build(
330
            {
331
                source => 'EdifactEan',
332
                value  => {
333
                    description => 'test ean',
334
                    branchcode  => undef,
335
                    ean         => $test_san
336
                }
175
            }
337
            }
338
        );
339
340
        # Setup multiple funds
341
        my %funds;
342
        for my $code (qw(REF LOAN)) {
343
            $funds{$code} = $builder->build(
344
                {
345
                    source => 'Aqbudget',
346
                    value  => {
347
                        budget_code      => $code,
348
                        budget_period_id => $active_period->{budget_period_id}
349
                    }
350
                }
351
            );
176
        }
352
        }
177
    );
178
    my $dirname  = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
179
    my $filename = 'QUOTES_SMALL.CEQ';
180
    ok( -e $dirname . $filename, 'File QUOTES_SMALL.CEQ found' );
181
353
182
    my $trans = Koha::Edifact::Transport->new( $account->{id} );
354
        # Setup multiple rota
183
    $trans->working_directory($dirname);
355
        my %rota;
356
        for my $title (qw(TEST FAST SLOW)) {
357
            $rota{$title} = $builder->build_object(
358
                {
359
                    class => 'Koha::StockRotationRotas',
360
                    value => { title => $title }
361
                }
362
            );
363
            $builder->build(
364
                {
365
                    source => 'Stockrotationstage',
366
                    value  => { rota_id => $rota{$title}->rota_id },
367
                }
368
            );
369
        }
184
370
185
    my $mhash = $trans->message_hash();
371
        my $description = <<~"END";
186
    $mhash->{message_type} = 'QUOTE';
372
            Loaded QUOTE file with 1 Message that contains 2 LIN segments with the first
187
    $trans->ingest( $mhash, $filename );
373
            consistent of 1 item and the second with 3 items with 2 different funds.
374
        END
375
        diag($description);
188
376
189
    my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
377
        my $filename = 'QUOTES_MULTI.CEQ';
378
        my $trans    = Koha::Edifact::Transport->new( $account->{id} );
379
        $trans->working_directory($dirname);
380
        my $mhash = $trans->message_hash();
381
        $mhash->{message_type} = 'QUOTE';
382
        $trans->ingest( $mhash, $filename );
190
383
191
    # Test quote expects REF to be a valid and active fund code
384
        my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
192
    my $active_period = $builder->build(
385
        process_quote($quote);
193
        {
386
194
            source => 'Aqbudgetperiod',
387
        #$logger->diag();
195
            value  => { budget_period_active => 1 }
388
196
        }
389
        my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
197
    );
390
        is( $baskets->count, 1, "One basket created for quote" );
198
    my $fund = $builder->build(
391
199
        {
392
        my $basket = $baskets->next;
200
            source => 'Aqbudget',
393
        my $orders = $basket->orders;
201
            value  => {
394
        is( $orders->count, 3, "Three order lines created for quote" );
202
                budget_code      => 'REF',
395
203
                budget_period_id => $active_period->{budget_period_id}
396
        my %biblios;
397
        my $orderline = 0;
398
        while ( my $order = $orders->next ) {
399
            $orderline++;
400
            diag( "Looking at order: " . $orderline );
401
            if ( $orderline == 1 ) {
402
403
                # Fund allocation
404
                my $fund = $order->fund;
405
                is( $fund->budget_code, 'REF', 'Correct fund allocated for first orderline' );
406
407
                # Check biblio
408
                ok( $order->biblionumber, 'Biblionumber assigned to order' );
409
                $biblios{ $order->biblionumber }++;
410
411
                # Check items created
412
                my $items = $order->items;
413
                is( $items->count, 1, 'One item created for the first orderline' );
414
415
                # Check first order GIR details
416
                my $item = $items->next;
417
                my $rota = $item->stockrotationitem;
418
                ok( $rota, 'Item was assigned to a rota' );
419
                is( $rota->stage->rota->title, 'TEST', "Item was assigned to the correct rota" );
420
421
            } elsif ( $orderline == 2 ) {
422
423
                # Fund allocation
424
                my $fund = $order->fund;
425
                is( $fund->budget_code, 'LOAN', 'Correct fund allocated for second orderline' );
426
427
                # Check biblio
428
                ok( $order->biblionumber, 'Biblionumber assigned to order' );
429
                $biblios{ $order->biblionumber }++;
430
431
                # Check items created
432
                my $items = $order->items;
433
                is( $items->count, 2, 'Two items created for the second orderline' );
434
435
                # Check second order GIR details
436
                my %rotas;
437
                while ( my $item = $items->next ) {
438
                    my $rota = $item->stockrotationitem;
439
                    ok( $rota, 'Item was assigned to a rota' );
440
                    $rotas{ $rota->stage->rota->title }++;
441
                }
442
                is( $rotas{'FAST'}, 1, "One item added to 'FAST' rota" );
443
                is( $rotas{'SLOW'}, 1, "One item added to 'SLOW' rota" );
444
            } elsif ( $orderline == 3 ) {
445
                diag("Second LIN split into 2 Orderlines, one for each Fund");
446
447
                # Fund allocation
448
                my $fund = $order->fund;
449
                is( $fund->budget_code, 'REF', 'Correct fund allocated for third orderline' );
450
451
                # Check biblio
452
                ok( $order->biblionumber, 'Biblionumber assigned to order' );
453
                $biblios{ $order->biblionumber }++;
454
455
                # Check items created
456
                my $items = $order->items;
457
                is( $items->count, 1, 'One item created for the third orderline' );
458
459
                # Check first order GIR details
460
                my $item = $items->next;
461
                my $rota = $item->stockrotationitem;
462
                ok( !$rota, 'Item was not assigned to a rota' );
204
            }
463
            }
205
        }
464
        }
206
    );
207
465
208
    # The quote expects a ROT1 stock rotation roata to exist
466
        $logger->clear();
209
    my $rota = $builder->build_object(
467
        $schema->storage->txn_rollback;
210
        {
468
    };
211
            class => 'Koha::StockRotationRotas',
212
            value => { title => 'ROT1' }
213
        }
214
    );
215
    $builder->build(
216
        {
217
            source => 'Stockrotationstage',
218
            value  => { rota_id => $rota->rota_id },
219
        }
220
    );
221
469
222
    # Process the test quote file
470
    # Test 4: Invalid Fund Error Handling
223
    process_quote($quote);
471
    subtest 'invalid_fund_handling' => sub {
472
        plan tests => 21;
224
473
225
    $quote->get_from_storage;
474
        $schema->storage->txn_begin;
226
475
227
    # Tests for generated basket for passed quote file
476
        my $account = $builder->build(
228
    my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
477
            {
229
    my $basket  = $baskets->next;
478
                source => 'VendorEdiAccount',
479
                value  => {
480
                    description => 'error test vendor',
481
                    transport   => 'FILE',
482
                }
483
            }
484
        );
485
        my $ean = $builder->build(
486
            {
487
                source => 'EdifactEan',
488
                value  => {
489
                    description => 'test ean',
490
                    branchcode  => undef,
491
                    ean         => $test_san
492
                }
493
            }
494
        );
230
495
231
    my $orders = $basket->orders;
496
        my $description = <<~"END";
232
    my $order  = $orders->next;
497
            Loading QUOTE file with 1 Message that contains 2 LIN segments with the first
498
            consistent of 1 item and the second with 3 items with 2 different undefined funds.
499
        END
500
        diag($description);
233
501
234
    my $biblio       = $order->biblio;
502
        my $filename = 'QUOTES_MULTI.CEQ';
235
    my $record       = $biblio->record;
503
        my $trans    = Koha::Edifact::Transport->new( $account->{id} );
236
    my $record_field = $record->field('008');
504
        $trans->working_directory($dirname);
237
505
238
    is( exists( $record_field->{_data} ), 1, 'Field has been added' );
506
        my $mhash = $trans->message_hash();
507
        $mhash->{message_type} = 'QUOTE';
508
        $trans->ingest( $mhash, $filename );
239
509
240
    # Test without calling the 008 handler
510
        my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
241
    $account = $builder->build(
242
        {
243
            source => 'VendorEdiAccount',
244
            value  => {
245
                description => 'test vendor', transport => 'FILE',
246
            }
247
        }
248
    );
249
    $dirname  = ( $Bin =~ /^(.*\/t\/)/ ? $1 . 'edi_testfiles/' : q{} );
250
    $filename = 'QUOTES_SMALL_2.CEQ';
251
    ok( -e $dirname . $filename, 'File QUOTES_SMALL_2.CEQ found' );
252
511
253
    $trans = Koha::Edifact::Transport->new( $account->{id} );
512
        process_quote($quote);
254
    $trans->working_directory($dirname);
255
513
256
    $mhash = $trans->message_hash();
514
        #$logger->diag();
257
    $mhash->{message_type} = 'QUOTE';
515
        $logger->trace_like(
258
    $trans->ingest( $mhash, $filename );
516
            qr/Created basket:.*/,
517
            "Trace recorded basket added"
518
        )->trace_is(
519
            qq/Checking db for matches with 9781529923766/,
520
            "Trace recorded isbn lookup"
521
        )->trace_like(
522
            qr/Added biblio:.*/,
523
            "Trace recorded adding new biblio"
524
        )->trace_is(
525
            qq/Skipping orderline with invalid budget: REF/,
526
            "Trace recorded skipping orderline with invalid fund"
527
        )->trace_is(
528
            qq/Checking db for matches with 9781785044342/,
529
            "Trace recorded isbn lookup"
530
        )->trace_like(
531
            qr/Added biblio:.*/,
532
            "Trace recorded adding new biblio"
533
        )->trace_is(
534
            qq/Skipping item with invalid budget: LOAN/,
535
            "Trace recorded skipping item with invalid fund"
536
        )->trace_is(
537
            qq/Skipping item with invalid budget: REF/,
538
            "Trace recorded skipping item with invalid fund"
539
        )->trace_is(
540
            qq/Skipping item with invalid budget: LOAN/,
541
            "Trace recorded skipping item with invalid fund"
542
        );
543
544
        # Errors should be recorded for skipped sections
545
        my $errors = Koha::Edifact::File::Errors->search();
546
        is( $errors->count, 4, '4 errors recorded for missing funds in quote' );
547
548
        my $error = $errors->next;
549
        ok( $error->section, 'First error section is present' );
550
        is( $error->details, 'Skipped orderline line with invalid budget: REF', 'First error details is correct' );
551
552
        $error = $errors->next;
553
        ok( $error->section, 'Second error section is present' );
554
        is( $error->details, 'Skipped GIR line with invalid budget: LOAN', 'Second error details is correct' );
555
556
        $error = $errors->next;
557
        ok( $error->section, 'Third error section is present' );
558
        is( $error->details, 'Invalid budget REF found', 'Third error details is correct' );
559
560
        $error = $errors->next;
561
        ok( $error->section, 'Fourth error section is present' );
562
        is( $error->details, 'Invalid budget LOAN found', 'Fourth error details is correct' );
563
564
        $quote->get_from_storage;
565
        is( $quote->status, 'error', 'Quote status set to error for invalid fund' );
566
567
        my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
568
        is( $baskets->count, 1, 'Basket still created despite errors' );
569
570
        my $orders = $baskets->next->orders;
571
        is( $orders->count, 0, 'No orders created with invalid fund' );
572
573
        $logger->clear();
574
        $schema->storage->txn_rollback;
575
    };
259
576
260
    $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
577
    # Test 5: Multiple message quote file
578
    subtest 'multiple_message_handling' => sub {
579
        plan tests => 3;
261
580
262
    # Test quote expects REF to be a valid and active fund code
581
        $schema->storage->txn_begin;
263
    $active_period = $builder->build(
582
264
        {
583
        my $account = $builder->build(
265
            source => 'Aqbudgetperiod',
584
            {
266
            value  => { budget_period_active => 1 }
585
                source => 'VendorEdiAccount',
267
        }
586
                value  => {
268
    );
587
                    description => 'error test vendor',
269
    $fund = $builder->build(
588
                    transport   => 'FILE',
270
        {
589
                }
271
            source => 'Aqbudget',
272
            value  => {
273
                budget_code      => 'REF2',
274
                budget_period_id => $active_period->{budget_period_id}
275
            }
590
            }
276
        }
591
        );
277
    );
592
        my $ean = $builder->build(
593
            {
594
                source => 'EdifactEan',
595
                value  => {
596
                    description => 'test ean',
597
                    branchcode  => undef,
598
                    ean         => $test_san
599
                }
600
            }
601
        );
278
602
279
    # The quote expects a ROT1 stock rotation roata to exist
603
        my $description = <<~"END";
280
    $rota = $builder->build_object(
604
            Loading QUOTE file with 2 messages
281
        {
605
        END
282
            class => 'Koha::StockRotationRotas',
606
        diag($description);
283
            value => { title => 'ROT2' }
284
        }
285
    );
286
    $builder->build(
287
        {
288
            source => 'Stockrotationstage',
289
            value  => { rota_id => $rota->rota_id },
290
        }
291
    );
292
607
293
    # Process the test quote file
608
        my $filename = 'QUOTES_BIG.CEQ';
294
    my $edi_module = Test::MockModule->new('Koha::EDI');
609
        my $trans    = Koha::Edifact::Transport->new( $account->{id} );
295
    $edi_module->mock(
610
        $trans->working_directory($dirname);
296
        '_check_for_existing_bib',
611
297
        sub {
612
        my $mhash = $trans->message_hash();
298
            my $bib_record = shift;
613
        $mhash->{message_type} = 'QUOTE';
299
            return;
614
        $trans->ingest( $mhash, $filename );
300
        }
301
    );
302
    $edi_module->mock(
303
        '_handle_008_field',
304
        sub {
305
            my $bib_record = shift;
306
            return $bib_record;
307
        }
308
    );
309
    process_quote($quote);
310
615
311
    $quote->get_from_storage;
616
        my $quote = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
312
617
313
    # Tests for generated basket for passed quote file
618
        process_quote($quote);
314
    $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
315
    $basket  = $baskets->next;
316
619
317
    $orders = $basket->orders;
620
        #$logger->diag();
318
    $order  = $orders->next;
319
621
320
    $biblio       = $order->biblio;
622
        my $baskets = Koha::Acquisition::Baskets->search( { booksellerid => $account->{vendor_id} } );
321
    $record       = $biblio->record;
623
        is( $baskets->count, 2, 'Two baskets added for file containing 2 messages' );
322
    $record_field = $record->field('008');
323
624
324
    is( $record_field->{_data}, undef, 'Field has not been added' );
625
        # First basket
626
        my $basket = $baskets->next;
627
        is( $basket->basketname, $filename, "Basket uses EDI filename for name" );
325
628
629
        # Second basket
630
        $basket = $baskets->next;
631
        is( $basket->basketname, $filename, "Basket uses EDI filename for name" );
632
633
        $logger->clear();
634
        $schema->storage->txn_rollback;
635
    };
636
637
    # Clean up
326
    $logger->clear();
638
    $logger->clear();
327
    $schema->storage->txn_rollback;
639
    $schema->storage->txn_rollback;
328
};
640
};
329
641
330
subtest 'process_invoice' => sub {
642
subtest 'process_invoice' => sub {
331
    plan tests => 19;
643
    plan tests => 32;
332
644
333
    $schema->storage->txn_begin;
645
    $schema->storage->txn_begin;
334
646
Lines 392-399 subtest 'process_invoice' => sub { Link Here
392
704
393
    my $invoice_message = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
705
    my $invoice_message = $schema->resultset('EdifactMessage')->find( { filename => $filename } );
394
    my $raw_msg         = $invoice_message->raw_msg;
706
    my $raw_msg         = $invoice_message->raw_msg;
395
    $raw_msg =~ s/P12345/$ordernumber1/g;
707
    $raw_msg =~ s/ORDERNUMBER1/$ordernumber1/g;
396
    $raw_msg =~ s/P54321/$ordernumber2/g;
708
    $raw_msg =~ s/ORDERNUMBER2/$ordernumber2/g;
397
    $invoice_message->update( { raw_msg => $raw_msg } );
709
    $invoice_message->update( { raw_msg => $raw_msg } );
398
710
399
    # Process the test invoice file
711
    # Process the test invoice file
Lines 403-408 subtest 'process_invoice' => sub { Link Here
403
        1;
715
        1;
404
    } or do {
716
    } or do {
405
        $error = $@;
717
        $error = $@;
718
        diag($error);
406
    };
719
    };
407
    ok( !$error, 'process_invoice completed without dying' );
720
    ok( !$error, 'process_invoice completed without dying' );
408
721
Lines 453-458 subtest 'process_invoice' => sub { Link Here
453
        'Warn recorded for unmatched item'
766
        'Warn recorded for unmatched item'
454
    )->clear();
767
    )->clear();
455
768
769
    # Errors should be recorded for skipped sections
770
    my $errors = Koha::Edifact::File::Errors->search();
771
    is( $errors->count, 6, '6 errors recorded for invoice' );
772
773
    my @expected_errors = (
774
        {
775
            'section' =>
776
                "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",
777
            'details' => 'Skipped invoice line 1, missing ordernumber'
778
        },
779
        {
780
            'section' =>
781
                "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",
782
            'details' => 'Skipped invoice line 2, cannot find order with ordernumber P28837'
783
        },
784
        {
785
            'section' =>
786
                "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",
787
            'details' => "Skipped invoice line 3, cannot find biblio for ordernumber $ordernumber1"
788
        },
789
        {
790
            'section' =>
791
                "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",
792
            'details' => 'No matching item found for invoice line 4:0 at branch WID'
793
        },
794
        {
795
            'section' =>
796
                "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",
797
            'details' => 'No matching item found for invoice line 5:0 at branch DIT'
798
        },
799
        {
800
            'section' => "NAD+SU+9999999999999",
801
            'details' => 'Skipped invoice INV00002 with unmatched vendor san: 9999999999999'
802
        }
803
    );
804
805
    my $index = 0;
806
    while ( my $error = $errors->next ) {
807
        is( $error->section, $expected_errors[$index]->{section}, "Error $index section is correct" );
808
        is( $error->details, $expected_errors[$index]->{details}, "Error $index details is correct" );
809
        $index++;
810
    }
811
456
    my $invoice3 = Koha::Acquisition::Invoices->search( { invoicenumber => 'INV00003' }, { rows => 1 } )->single;
812
    my $invoice3 = Koha::Acquisition::Invoices->search( { invoicenumber => 'INV00003' }, { rows => 1 } )->single;
457
    ok( $invoice3, "Invoice added to database" );
813
    ok( $invoice3, "Invoice added to database" );
458
    is( $invoice3->booksellerid, $account->{vendor_id}, 'Invoice has test booksellerid' );
814
    is( $invoice3->booksellerid, $account->{vendor_id}, 'Invoice has test booksellerid' );
(-)a/t/edi_testfiles/INVOICE.CEI (-2 / +1 lines)
Lines 1-2 Link Here
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'
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'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'''
2
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'
(-)a/t/edi_testfiles/QUOTES_BIG.CEQ (+1 lines)
Line 0 Link Here
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'
(-)a/t/edi_testfiles/QUOTES_MULTI.CEQ (-1 / +1 lines)
Line 0 Link Here
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'

Return to bug 38689