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

(-)a/Koha/MarcOrder.pm (+766 lines)
Line 0 Link Here
1
package Koha::MarcOrder;
2
3
# Copyright 2023, PTFS-Europe Ltd
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it
8
# under the terms of the GNU General Public License as published by
9
# the Free Software Foundation; either version 3 of the License, or
10
# (at your option) any later version.
11
#
12
# Koha is distributed in the hope that it will be useful, but
13
# WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License
18
# along with Koha; if not, see <http://www.gnu.org/licenses>.
19
20
use Modern::Perl;
21
use Try::Tiny qw( catch try );
22
use Net::FTP;
23
24
use base qw(Koha::Object);
25
26
use C4::Matcher;
27
use C4::ImportBatch qw(
28
    RecordsFromMARCXMLFile
29
    RecordsFromISO2709File
30
    RecordsFromMarcPlugin
31
    BatchStageMarcRecords
32
    BatchFindDuplicates
33
    SetImportBatchMatcher
34
    SetImportBatchOverlayAction
35
    SetImportBatchNoMatchAction
36
    SetImportBatchItemAction
37
    SetImportBatchStatus
38
);
39
use C4::Search qw( FindDuplicate );
40
use C4::Acquisition qw( NewBasket );
41
use C4::Biblio qw(
42
    AddBiblio
43
    GetMarcFromKohaField
44
    TransformHtmlToXml
45
);
46
use C4::Items qw( AddItemFromMarc );
47
use C4::Budgets qw( GetBudgetByCode );
48
49
use Koha::Database;
50
use Koha::ImportBatchProfiles;
51
use Koha::ImportBatches;
52
use Koha::Import::Records;
53
use Koha::Acquisition::Currencies;
54
use Koha::Acquisition::Booksellers;
55
use Koha::Acquisition::Baskets;
56
57
=head1 NAME
58
59
Koha::MarcOrder - Koha Marc Order Object class
60
61
=head1 API
62
63
=head2 Class methods
64
65
=cut
66
67
=head3 create_order_lines_from_file
68
69
    my $result = Koha::MarcOrder->create_order_lines_from_file($args);
70
71
    Controller for file staging, basket creation and order line creation when using the cronjob in marc_ordering_process.pl
72
73
=cut
74
75
sub create_order_lines_from_file {
76
    my ( $self, $args ) = @_;
77
78
    my $filename = $args->{filename};
79
    my $filepath = $args->{filepath};
80
    my $profile  = $args->{profile};
81
    my $agent    = $args->{agent};
82
83
    my $success;
84
    my $error;
85
86
    my $vendor_id = $profile->vendor_id;
87
    my $budget_id = $profile->budget_id;
88
89
    my $vendor_record = Koha::Acquisition::Booksellers->find({ id => $vendor_id });
90
91
    my $basket_id = _create_basket_for_file({
92
        filename  => $filename,
93
        vendor_id => $vendor_id
94
    });
95
96
    my $format = index($filename, '.mrc') != -1 ? 'ISO2709' : 'MARCXML';
97
    my $params = {
98
        record_type                => $profile->record_type,
99
        encoding                   => $profile->encoding,
100
        format                     => $format,
101
        filepath                   => $filepath,
102
        filename                   => $filename,
103
        comments                   => undef,
104
        parse_items                => $profile->parse_items,
105
        matcher_id                 => $profile->matcher_id,
106
        overlay_action             => $profile->overlay_action,
107
        nomatch_action             => $profile->nomatch_action,
108
        item_action                => $profile->item_action,
109
    };
110
111
    try {
112
        my $import_batch_id = _stage_file($params);
113
114
        my $import_records = Koha::Import::Records->search({
115
            import_batch_id => $import_batch_id,
116
        });
117
118
        while( my $import_record = $import_records->next ){
119
            my $result = add_biblios_from_import_record({
120
                import_batch_id => $import_batch_id,
121
                import_record   => $import_record,
122
                matcher_id      => $params->{matcher_id},
123
                overlay_action  => $params->{overlay_action},
124
                agent           => $agent,
125
            });
126
            warn "Duplicates found in $result->{duplicates_in_batch}, record was skipped." if $result->{duplicates_in_batch};
127
            next if $result->{skip};
128
129
            my $order_line_details = add_items_from_import_record({
130
                record_result   => $result->{record_result},
131
                basket_id       => $basket_id,
132
                vendor          => $vendor_record,
133
                budget_id       => $budget_id,
134
                agent           => $agent,
135
            });
136
137
            my $order_lines = create_order_lines({
138
                order_line_details => $order_line_details
139
            });
140
        };
141
        SetImportBatchStatus( $import_batch_id, 'imported' )
142
            if Koha::Import::Records->search({import_batch_id => $import_batch_id, status => 'imported' })->count
143
            == Koha::Import::Records->search({import_batch_id => $import_batch_id})->count;
144
145
        $success = 1;
146
    } catch {
147
        $success = 0;
148
        $error = $_;
149
    };
150
151
    return $success ? { success => 1, error => ''} : { success => 0, error => $error };
152
}
153
154
=head3 import_record_and_create_order_lines
155
156
    my $result = Koha::MarcOrder->import_record_and_create_order_lines($args);
157
158
    Controller for record import and order line creation when using the interface in addorderiso2709.pl
159
160
=cut
161
162
sub import_record_and_create_order_lines {
163
    my ( $self, $args ) = @_;
164
165
    my $import_batch_id           = $args->{import_batch_id};
166
    my @import_record_id_selected = $args->{import_record_id_selected} || ();
167
    my $matcher_id                = $args->{matcher_id};
168
    my $overlay_action            = $args->{overlay_action};
169
    my $import_record             = $args->{import_record};
170
    my $client_item_fields        = $args->{client_item_fields};
171
    my $agent                     = $args->{agent};
172
    my $basket_id                 = $args->{basket_id};
173
    my $budget_id                 = $args->{budget_id};
174
    my $vendor                    = $args->{vendor};
175
176
    my $result = add_biblios_from_import_record({
177
        import_batch_id           => $import_batch_id,
178
        import_record             => $import_record,
179
        matcher_id                => $matcher_id,
180
        overlay_action            => $overlay_action,
181
        agent                     => $agent,
182
        import_record_id_selected => @import_record_id_selected,
183
    });
184
185
    return {
186
        duplicates_in_batch => $result->{duplicates_in_batch},
187
        skip                => $result->{skip}
188
    } if $result->{skip};
189
190
    my $order_line_details = add_items_from_import_record({
191
        record_result      => $result->{record_result},
192
        basket_id          => $basket_id,
193
        vendor             => $vendor,
194
        budget_id          => $budget_id,
195
        agent              => $agent,
196
        client_item_fields => $client_item_fields
197
    });
198
199
    my $order_lines = create_order_lines({
200
        order_line_details => $order_line_details
201
    });
202
203
    return {
204
        duplicates_in_batch => 0,
205
        skip                => 0
206
    }
207
}
208
209
=head3 _create_basket_for_file
210
211
    my $basket_id = _create_basket_for_file({
212
        filename  => $filename,
213
        vendor_id => $vendor_id
214
    });
215
216
    Creates a basket ready to receive order lines based on the imported file
217
218
=cut
219
220
sub _create_basket_for_file {
221
    my ( $args ) = @_;
222
223
    my $filename = $args->{filename};
224
    my $vendor_id = $args->{vendor_id};
225
226
    # aqbasketname.basketname has a max length of 50 characters so long file names will need to be truncated
227
    my $basketname = length($filename) > 50 ? substr( $filename, 0, 50 ): $filename;
228
229
    my $basketno =
230
        NewBasket( $vendor_id, 0, $basketname, q{},
231
        q{} . q{} );
232
    
233
    return $basketno;
234
}
235
236
=head3 _stage_file
237
238
    $file->_stage_file($params)
239
240
    Stages a file directly using parameters from a marc ordering account and without using the background job
241
    This function is a mirror of Koha::BackgroundJob::StageMARCForImport->process but with the background job functionality removed
242
243
=cut
244
245
sub _stage_file {
246
    my ( $args ) = @_;
247
248
    my $record_type                = $args->{record_type};
249
    my $encoding                   = $args->{encoding};
250
    my $format                     = $args->{format};
251
    my $filepath                   = $args->{filepath};
252
    my $filename                   = $args->{filename};
253
    my $marc_modification_template = $args->{marc_modification_template};
254
    my $comments                   = $args->{comments};
255
    my $parse_items                = $args->{parse_items};
256
    my $matcher_id                 = $args->{matcher_id};
257
    my $overlay_action             = $args->{overlay_action};
258
    my $nomatch_action             = $args->{nomatch_action};
259
    my $item_action                = $args->{item_action};
260
    
261
    my @messages;
262
    my ( $batch_id, $num_valid, $num_items, @import_errors );
263
    my $num_with_matches = 0;
264
    my $checked_matches  = 0;
265
    my $matcher_failed   = 0;
266
    my $matcher_code     = "";
267
268
    my $schema = Koha::Database->new->schema;
269
    try {
270
        $schema->storage->txn_begin;
271
272
        my ( $errors, $marcrecords );
273
        if ( $format eq 'MARCXML' ) {
274
            ( $errors, $marcrecords ) =
275
              C4::ImportBatch::RecordsFromMARCXMLFile( $filepath, $encoding );
276
        }
277
        elsif ( $format eq 'ISO2709' ) {
278
            ( $errors, $marcrecords ) =
279
              C4::ImportBatch::RecordsFromISO2709File( $filepath, $record_type,
280
                $encoding );
281
        }
282
        else {    # plugin based
283
            $errors = [];
284
            $marcrecords =
285
              C4::ImportBatch::RecordsFromMarcPlugin( $filepath, $format,
286
                $encoding );
287
        }
288
289
        ( $batch_id, $num_valid, $num_items, @import_errors ) = BatchStageMarcRecords(
290
            $record_type,                $encoding,
291
            $marcrecords,                $filename,
292
            $marc_modification_template, $comments,
293
            '',                          $parse_items,
294
            0
295
        );
296
297
        if ($matcher_id) {
298
            my $matcher = C4::Matcher->fetch($matcher_id);
299
            if ( defined $matcher ) {
300
                $checked_matches = 1;
301
                $matcher_code    = $matcher->code();
302
                $num_with_matches =
303
                  BatchFindDuplicates( $batch_id, $matcher, 10);
304
                SetImportBatchMatcher( $batch_id, $matcher_id );
305
                SetImportBatchOverlayAction( $batch_id, $overlay_action );
306
                SetImportBatchNoMatchAction( $batch_id, $nomatch_action );
307
                SetImportBatchItemAction( $batch_id, $item_action );
308
                $schema->storage->txn_commit;
309
            }
310
            else {
311
                $matcher_failed = 1;
312
                $schema->storage->txn_rollback;
313
            }
314
        } else {
315
            $schema->storage->txn_commit;
316
        }
317
318
        return $batch_id;
319
    }
320
    catch {
321
        warn $_;
322
        $schema->storage->txn_rollback;
323
        die "Something terrible has happened!"
324
          if ( $_ =~ /Rollback failed/ );    # TODO Check test: Rollback failed
325
    };
326
}
327
328
=head3 _get_MarcItemFieldsToOrder_syspref_data
329
330
    my $marc_item_fields_to_order = _get_MarcItemFieldsToOrder_syspref_data('MarcItemFieldsToOrder', $marcrecord, $fields);
331
332
    Fetches data from a marc record based on the mappings in the syspref MarcItemFieldsToOrder using the fields selected in $fields (array).
333
334
=cut
335
336
sub _get_MarcItemFieldsToOrder_syspref_data {
337
    my ($syspref_name, $record, $field_list) = @_;
338
    my $syspref = C4::Context->preference($syspref_name);
339
    $syspref = "$syspref\n\n";
340
    my $yaml = eval {
341
        YAML::XS::Load(Encode::encode_utf8($syspref));
342
    };
343
    if ( $@ ) {
344
        warn "Unable to parse $syspref syspref : $@";
345
        return ();
346
    }
347
    my @result;
348
    my @tags_list;
349
350
    # Check tags in syspref definition
351
    for my $field_name ( @$field_list ) {
352
        next unless exists $yaml->{$field_name};
353
        my @fields = split /\|/, $yaml->{$field_name};
354
        for my $field ( @fields ) {
355
            my ( $f, $sf ) = split /\$/, $field;
356
            next unless $f and $sf;
357
            push @tags_list, $f;
358
        }
359
    }
360
    @tags_list = List::MoreUtils::uniq(@tags_list);
361
362
    die "System preference MarcItemFieldsToOrder has not been filled in. Please set the mapping values to use this cron script." if scalar(@tags_list == 0);
363
364
    my $tags_count = _verify_number_of_fields(\@tags_list, $record);
365
    # Return if the number of these fields in the record is not the same.
366
    die "Invalid number of fields detected on field $tags_count->{key}, please check this file" if $tags_count->{error};
367
368
    # Gather the fields
369
    my $fields_hash;
370
    foreach my $tag (@tags_list) {
371
        my @tmp_fields;
372
        foreach my $field ($record->field($tag)) {
373
            push @tmp_fields, $field;
374
        }
375
        $fields_hash->{$tag} = \@tmp_fields;
376
    }
377
378
    for (my $i = 0; $i < $tags_count->{count}; $i++) {
379
        my $r;
380
        for my $field_name ( @$field_list ) {
381
            next unless exists $yaml->{$field_name};
382
            my @fields = split /\|/, $yaml->{$field_name};
383
            for my $field ( @fields ) {
384
                my ( $f, $sf ) = split /\$/, $field;
385
                next unless $f and $sf;
386
                my $v = $fields_hash->{$f}[$i] ? $fields_hash->{$f}[$i]->subfield( $sf ) : undef;
387
                $r->{$field_name} = $v if (defined $v);
388
                last if $yaml->{$field};
389
            }
390
        }
391
        push @result, $r;
392
    }
393
    return $result[0];
394
}
395
396
=head3 _verify_number_of_fields
397
398
    my $tags_count = _verify_number_of_fields(\@tags_list, $record);
399
400
    Verifies that the number of fields in the record is consistent for each field
401
402
=cut
403
404
sub _verify_number_of_fields {
405
    my ($tags_list, $record) = @_;
406
    my $tag_fields_count;
407
    for my $tag (@$tags_list) {
408
        my @fields = $record->field($tag);
409
        $tag_fields_count->{$tag} = scalar @fields;
410
    }
411
412
    my $tags_count;
413
    foreach my $key ( keys %$tag_fields_count ) {
414
        if ( $tag_fields_count->{$key} > 0 ) { # Having 0 of a field is ok
415
            $tags_count //= $tag_fields_count->{$key}; # Start with the count from the first occurrence
416
            return { error => 1, key => $key } if $tag_fields_count->{$key} != $tags_count; # All counts of various fields should be equal if they exist
417
        }
418
    }
419
420
    return { error => 0, count => $tags_count };
421
}
422
423
=head3 add_biblios_from_import_record
424
425
    my ($record_results, $duplicates_in_batch) = add_biblios_from_import_record({
426
        import_record             => $import_record,
427
        matcher_id                => $matcher_id,
428
        overlay_action            => $overlay_action,
429
        import_record_id_selected => $import_record_id_selected,
430
        agent                     => $agent,
431
        import_batch_id           => $import_batch_id
432
    });
433
434
    Takes a set of import records and adds biblio records based on the file content.
435
    Params matcher_id and overlay_action are taken from the marc ordering account.
436
    Returns the new or matched biblionumber and the marc record for each import record.
437
438
=cut
439
440
sub add_biblios_from_import_record {
441
    my ( $args ) = @_;
442
443
    my $import_batch_id           = $args->{import_batch_id};
444
    my @import_record_id_selected = $args->{import_record_id_selected} || ();
445
    my $matcher_id                = $args->{matcher_id};
446
    my $overlay_action            = $args->{overlay_action};
447
    my $import_record             = $args->{import_record};
448
    my $agent                     = $args->{agent} || "";
449
    my $duplicates_in_batch;
450
451
    my $duplicates_found = 0;
452
    if($agent eq 'client') {
453
        return {
454
            record_result       => 0,
455
            duplicates_in_batch => 0,
456
            skip                => 1
457
        } if not grep { $_ eq $import_record->import_record_id } @import_record_id_selected;
458
    }
459
460
    my $marcrecord   = $import_record->get_marc_record || die "Couldn't translate marc information";
461
    my $matches      = $import_record->get_import_record_matches({ chosen => 1 });
462
    my $match        = $matches->count ? $matches->next : undef;
463
    my $biblionumber = $match ? $match->candidate_match_id : 0;
464
465
    if ( $biblionumber ) {
466
        $import_record->status('imported')->store;
467
        if( $overlay_action eq 'replace' ){
468
            my $biblio = Koha::Biblios->find( $biblionumber );
469
            $import_record->replace({ biblio => $biblio });
470
        }
471
    } else {
472
        if ($matcher_id) {
473
            if ( $matcher_id eq '_TITLE_AUTHOR_' ) {
474
                my @matches = FindDuplicate($marcrecord);
475
                $duplicates_found = 1 if @matches;
476
            }
477
            else {
478
                my $matcher = C4::Matcher->fetch($matcher_id);
479
                my @matches = $matcher->get_matches( $marcrecord, my $max_matches = 1 );
480
                $duplicates_found = 1 if @matches;
481
            }
482
            return {
483
                record_result       => 0,
484
                duplicates_in_batch => $import_batch_id,
485
                skip                => 1
486
            } if $duplicates_found;
487
        }
488
489
        # add the biblio if no matches were found
490
        if( !$duplicates_found ) {
491
            ( $biblionumber, undef ) = AddBiblio( $marcrecord, '' );
492
            $import_record->status('imported')->store;
493
        }
494
    }
495
    $import_record->import_biblio->matched_biblionumber($biblionumber)->store;
496
497
    my $record_result = {
498
        biblionumber     => $biblionumber,
499
        marcrecord       => $marcrecord,
500
        import_record_id => $import_record->import_record_id,
501
    };
502
503
    return {
504
        record_result       => $record_result,
505
        duplicates_in_batch => $duplicates_in_batch,
506
        skip                => 0
507
    };
508
}
509
510
=head3 add_items_from_import_record
511
512
    my $order_line_details = add_items_from_import_record({
513
        record_result      => $record_result,
514
        basket_id          => $basket_id,
515
        vendor             => $vendor,
516
        budget_id          => $budget_id,
517
        agent              => $agent,
518
        client_item_fields => $client_item_fields
519
    });
520
521
    Adds items to biblio records based on mappings in MarcItemFieldsToOrder.
522
    Returns an array of order line details based on newly added items.
523
    If being called from addorderiso2709.pl then client_item_fields is a hash of all the UI form inputs needed by the script.
524
525
=cut
526
527
sub add_items_from_import_record {
528
    my ( $args ) = @_;
529
530
    my $record_result      = $args->{record_result};
531
    my $basket_id          = $args->{basket_id};
532
    my $budget_id          = $args->{budget_id};
533
    my $vendor             = $args->{vendor};
534
    my $agent              = $args->{agent};
535
    my $client_item_fields = $args->{client_item_fields} || undef;
536
    my $active_currency    = Koha::Acquisition::Currencies->get_active;
537
    my $biblionumber       = $record_result->{biblionumber};
538
    my $marcrecord         = $record_result->{marcrecord};
539
    my @order_line_details;
540
541
    if($agent eq 'cron') {
542
        my $marc_item_fields_to_order = _get_MarcItemFieldsToOrder_syspref_data('MarcItemFieldsToOrder', $marcrecord, ['homebranch', 'holdingbranch', 'itype', 'nonpublic_note', 'public_note', 'loc', 'ccode', 'notforloan', 'uri', 'copyno', 'price', 'replacementprice', 'itemcallnumber', 'quantity', 'budget_code']);
543
        my $item_homebranch           = $marc_item_fields_to_order->{homebranch};
544
        my $item_holdingbranch        = $marc_item_fields_to_order->{holdingbranch};
545
        my $item_itype                = $marc_item_fields_to_order->{itype};
546
        my $item_nonpublic_note       = $marc_item_fields_to_order->{nonpublic_note};
547
        my $item_public_note          = $marc_item_fields_to_order->{public_note};
548
        my $item_loc                  = $marc_item_fields_to_order->{loc};
549
        my $item_ccode                = $marc_item_fields_to_order->{ccode};
550
        my $item_notforloan           = $marc_item_fields_to_order->{notforloan};
551
        my $item_uri                  = $marc_item_fields_to_order->{uri};
552
        my $item_copyno               = $marc_item_fields_to_order->{copyno};
553
        my $item_quantity             = $marc_item_fields_to_order->{quantity};
554
        my $item_budget_code          = $marc_item_fields_to_order->{budget_code};
555
        my $item_budget_id;
556
        if ( $marc_item_fields_to_order->{budget_code} ) {
557
            my $item_budget = GetBudgetByCode( $marc_item_fields_to_order->{budget_code} );
558
            if ( $item_budget ) {
559
                $item_budget_id = $item_budget->{budget_id};
560
            } else {
561
                $item_budget_id = $budget_id;
562
            }
563
        } else {
564
            $item_budget_id = $budget_id;
565
        }
566
        my $item_price             = $marc_item_fields_to_order->{price};
567
        my $item_replacement_price = $marc_item_fields_to_order->{replacementprice};
568
        my $item_callnumber        = $marc_item_fields_to_order->{itemcallnumber};
569
570
        if(!$item_quantity) {
571
            my $isbn = $marcrecord->subfield( '020', "a" );
572
            warn "No quantity found for record with ISBN: $isbn. No items will be added.";
573
        }
574
575
        for (my $i = 0; $i < $item_quantity; $i++) {
576
            my $item = Koha::Item->new({
577
                biblionumber          => $biblionumber,
578
                homebranch            => $item_homebranch,
579
                holdingbranch         => $item_holdingbranch,
580
                itype                 => $item_itype,
581
                itemnotes_nonpublic   => $item_nonpublic_note,
582
                itemnotes             => $item_public_note,
583
                location              => $item_loc,
584
                ccode                 => $item_ccode,
585
                notforloan            => $item_notforloan,
586
                uri                   => $item_uri,
587
                copynumber            => $item_copyno,
588
                price                 => $item_price,
589
                replacementprice      => $item_replacement_price,
590
                itemcallnumber        => $item_callnumber,
591
            })->store;
592
593
            my %order_detail_hash = (
594
                biblionumber => $biblionumber,
595
                itemnumbers  => ($item->itemnumber),
596
                basketno     => $basket_id,
597
                quantity     => 1,
598
                budget_id    => $item_budget_id,
599
                currency     => $vendor->listprice,
600
            );
601
602
            if($item_price) {
603
                $order_detail_hash{tax_rate_on_ordering}  = $vendor->tax_rate;
604
                $order_detail_hash{tax_rate_on_receiving} = $vendor->tax_rate;
605
                $order_detail_hash{discount}              = $vendor->discount;
606
                $order_detail_hash{rrp}                   = $item_price;
607
                $order_detail_hash{ecost}                 = $vendor->discount ? $item_price * ( 1 - $vendor->discount / 100 ) : $item_price;
608
                $order_detail_hash{listprice}             = $order_detail_hash{rrp} / $active_currency->rate;
609
                $order_detail_hash{unitprice}             = $order_detail_hash{ecost};
610
            } else {
611
                $order_detail_hash{listprice} = 0;
612
            }
613
            $order_detail_hash{replacementprice} = $item_replacement_price || 0;
614
            $order_detail_hash{uncertainprice}   = 0 if $order_detail_hash{listprice};
615
616
            push @order_line_details, \%order_detail_hash;
617
        }
618
    }
619
620
    if($agent eq 'client') {
621
        my $homebranches      = $client_item_fields->{homebranches};
622
        my $count             = scalar @$homebranches;
623
        my $holdingbranches   = $client_item_fields->{holdingbranches};
624
        my $itypes            = $client_item_fields->{itypes};
625
        my $nonpublic_notes   = $client_item_fields->{nonpublic_notes};
626
        my $public_notes      = $client_item_fields->{public_notes};
627
        my $locs              = $client_item_fields->{locs};
628
        my $ccodes            = $client_item_fields->{ccodes};
629
        my $notforloans       = $client_item_fields->{notforloans};
630
        my $uris              = $client_item_fields->{uris};
631
        my $copynos           = $client_item_fields->{copynos};
632
        my $budget_codes      = $client_item_fields->{budget_codes};
633
        my $itemprices        = $client_item_fields->{itemprices};
634
        my $replacementprices = $client_item_fields->{replacementprices};
635
        my $itemcallnumbers   = $client_item_fields->{itemcallnumbers};
636
637
        my $itemcreation;
638
        for (my $i = 0; $i < $count; $i++) {
639
            $itemcreation = 1;
640
            my $item = Koha::Item->new(
641
                {
642
                    biblionumber        => $biblionumber,
643
                    homebranch          => @$homebranches[$i],
644
                    holdingbranch       => @$holdingbranches[$i],
645
                    itemnotes_nonpublic => @$nonpublic_notes[$i],
646
                    itemnotes           => @$public_notes[$i],
647
                    location            => @$locs[$i],
648
                    ccode               => @$ccodes[$i],
649
                    itype               => @$itypes[$i],
650
                    notforloan          => @$notforloans[$i],
651
                    uri                 => @$uris[$i],
652
                    copynumber          => @$copynos[$i],
653
                    price               => @$itemprices[$i],
654
                    replacementprice    => @$replacementprices[$i],
655
                    itemcallnumber      => @$itemcallnumbers[$i],
656
                }
657
            )->store;
658
659
            my %order_detail_hash = (
660
                biblionumber => $biblionumber,
661
                itemnumbers  => ($item->itemnumber),
662
                basketno     => $basket_id,
663
                quantity     => 1,
664
                budget_id    => @$budget_codes[$i] || $budget_id, # If no budget selected in the UI, default to the budget on the ordering account
665
                currency     => $vendor->listprice,
666
            );
667
668
            if(@$itemprices[$i]) {
669
                $order_detail_hash{tax_rate_on_ordering}  = $vendor->tax_rate;
670
                $order_detail_hash{tax_rate_on_receiving} = $vendor->tax_rate;
671
                my $order_discount                        = $client_item_fields->{c_discount} ? $client_item_fields->{c_discount} : $vendor->discount;
672
                $order_detail_hash{discount}              = $order_discount;
673
                $order_detail_hash{rrp}                   = @$itemprices[$i];
674
                $order_detail_hash{ecost}                 = $order_discount ? @$itemprices[$i] * ( 1 - $order_discount / 100 ) : @$itemprices[$i];
675
                $order_detail_hash{listprice}             = $order_detail_hash{rrp} / $active_currency->rate;
676
                $order_detail_hash{unitprice}             = $order_detail_hash{ecost};
677
            } else {
678
                $order_detail_hash{listprice} = 0;
679
            }
680
            $order_detail_hash{replacementprice} = @$replacementprices[$i] || 0;
681
            $order_detail_hash{uncertainprice}   = 0 if $order_detail_hash{listprice};
682
683
            push @order_line_details, \%order_detail_hash;
684
        }
685
686
        if(!$itemcreation) {
687
            my $quantity = GetMarcQuantity($marcrecord, C4::Context->preference('marcflavour')) || 1;
688
            my %order_detail_hash = (
689
                biblionumber       => $biblionumber,
690
                basketno           => $basket_id,
691
                quantity           => $client_item_fields->{c_quantity},
692
                budget_id          => $client_item_fields->{c_budget_id},
693
                uncertainprice     => 1,
694
                sort1              => $client_item_fields->{c_sort1},
695
                sort2              => $client_item_fields->{c_sort2},
696
                order_internalnote => $client_item_fields->{all_order_internalnote},
697
                order_vendornote   => $client_item_fields->{all_order_vendornote},
698
                currency           => $client_item_fields->{all_currency},
699
                replacementprice   => $client_item_fields->{c_replacement_price},
700
            );
701
            if ($client_item_fields->{c_price}){
702
                $order_detail_hash{tax_rate_on_ordering}  = $vendor->tax_rate;
703
                $order_detail_hash{tax_rate_on_receiving} = $vendor->tax_rate;
704
                my $order_discount                        = $client_item_fields->{c_discount} ? $client_item_fields->{c_discount} : $vendor->discount;
705
                $order_detail_hash{discount}              = $order_discount;
706
                $order_detail_hash{rrp}                   = $client_item_fields->{c_price};
707
                $order_detail_hash{ecost}                 = $order_discount ? $client_item_fields->{c_price} * ( 1 - $order_discount / 100 ) : $client_item_fields->{c_price};
708
                $order_detail_hash{listprice}             = $order_detail_hash{rrp} / $active_currency->rate;
709
                $order_detail_hash{unitprice}             = $order_detail_hash{ecost};
710
            } else {
711
                $order_detail_hash{listprice} = 0;
712
            }
713
714
            $order_detail_hash{uncertainprice} = 0 if $order_detail_hash{listprice};
715
716
            # Add items if applicable parsing the item sent by the form, and create an item just for the import_record_id we are dealing with
717
            my $basket = Koha::Acquisition::Baskets->find( $basket_id );
718
            $order_detail_hash{itemnumbers} = ();
719
            if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) {
720
                my @tags         = $client_item_fields->{tag};
721
                my @subfields    = $client_item_fields->{subfield};
722
                my @field_values = $client_item_fields->{field_value};
723
                my @serials      = $client_item_fields->{serial};
724
                my $xml          = TransformHtmlToXml( \@tags, \@subfields, \@field_values );
725
                my $record       = MARC::Record::new_from_xml( $xml, 'UTF-8' );
726
                for ( my $qtyloop=1; $qtyloop <= $client_item_fields->{c_quantity}; $qtyloop++ ) {
727
                    my ( $biblionumber, undef, $itemnumber ) = AddItemFromMarc( $record, $biblionumber );
728
                    push @{ $order_detail_hash{itemnumbers} }, $itemnumber;
729
                }
730
            }
731
            push @order_line_details, \%order_detail_hash;
732
        }
733
    }
734
    return \@order_line_details;
735
}
736
737
=head3 create_order_lines
738
739
    my $order_lines = create_order_lines({
740
        order_line_details => $order_line_details
741
    });
742
743
    Creates order lines based on an array of order line details
744
745
=cut
746
747
sub create_order_lines {
748
    my ( $args ) = @_;
749
750
    my $order_line_details = $args->{order_line_details};
751
752
    foreach  my $order_detail ( @{ $order_line_details } ) {
753
        my @itemnumbers = $order_detail->{itemnumbers};
754
        delete($order_detail->{itemnumber});
755
        my $order = Koha::Acquisition::Order->new( \%{ $order_detail } );
756
        $order->populate_with_prices_for_ordering();
757
        $order->populate_with_prices_for_receiving();
758
        $order->store;
759
        foreach my $itemnumber ( @itemnumbers ) {
760
            $order->add_item( $itemnumber );
761
        }
762
    }
763
    return;
764
}
765
766
1;
(-)a/acqui/addorderiso2709.pl (-210 / +56 lines)
Lines 54-59 use Koha::Acquisition::Booksellers; Link Here
54
use Koha::ImportBatches;
54
use Koha::ImportBatches;
55
use Koha::Import::Records;
55
use Koha::Import::Records;
56
use Koha::Patrons;
56
use Koha::Patrons;
57
use Koha::MarcOrder;
57
58
58
my $input = CGI->new;
59
my $input = CGI->new;
59
my ($template, $loggedinuser, $cookie, $userflags) = get_template_and_user({
60
my ($template, $loggedinuser, $cookie, $userflags) = get_template_and_user({
Lines 153-370 if ($op eq ""){ Link Here
153
    my @sort2 = $input->multi_param('sort2');
154
    my @sort2 = $input->multi_param('sort2');
154
    my $matcher_id = $input->param('matcher_id');
155
    my $matcher_id = $input->param('matcher_id');
155
    my $active_currency = Koha::Acquisition::Currencies->get_active;
156
    my $active_currency = Koha::Acquisition::Currencies->get_active;
156
    my $biblio_count = 0;
157
    while( my $import_record = $import_records->next ){
157
    while( my $import_record = $import_records->next ){
158
        $biblio_count++;
158
        my $marcrecord        = $import_record->get_marc_record || die "couldn't translate marc information";
159
        my $duplifound = 0;
159
        my @homebranches      = $input->multi_param('homebranch_' . $import_record->import_record_id);
160
        # Check if this import_record_id was selected
160
        my @holdingbranches   = $input->multi_param('holdingbranch_' . $import_record->import_record_id);
161
        next if not grep { $_ eq $import_record->import_record_id } @import_record_id_selected;
161
        my @itypes            = $input->multi_param('itype_' . $import_record->import_record_id);
162
        my $marcrecord = $import_record->get_marc_record || die "couldn't translate marc information";
162
        my @nonpublic_notes   = $input->multi_param('nonpublic_note_' . $import_record->import_record_id);
163
        my $matches = $import_record->get_import_record_matches({ chosen => 1 });
163
        my @public_notes      = $input->multi_param('public_note_' . $import_record->import_record_id);
164
        my $match = $matches->count ? $matches->next : undef;
164
        my @locs              = $input->multi_param('loc_' . $import_record->import_record_id);
165
        my $biblionumber = $match ? $match->candidate_match_id : 0;
165
        my @ccodes            = $input->multi_param('ccode_' . $import_record->import_record_id);
166
        my $c_quantity = shift( @quantities ) || GetMarcQuantity($marcrecord, C4::Context->preference('marcflavour') ) || 1;
166
        my @notforloans       = $input->multi_param('notforloan_' . $import_record->import_record_id);
167
        my $c_budget_id = shift( @budgets_id ) || $input->param('all_budget_id') || $budget_id;
167
        my @uris              = $input->multi_param('uri_' . $import_record->import_record_id);
168
        my $c_discount = shift ( @discount);
168
        my @copynos           = $input->multi_param('copyno_' . $import_record->import_record_id);
169
        my $c_sort1 = shift( @sort1 ) || $input->param('all_sort1') || '';
169
        my @budget_codes      = $input->multi_param('budget_code_' . $import_record->import_record_id);
170
        my $c_sort2 = shift( @sort2 ) || $input->param('all_sort2') || '';
170
        my @itemprices        = $input->multi_param('itemprice_' . $import_record->import_record_id);
171
        my $c_replacement_price = shift( @orderreplacementprices );
172
        my $c_price = shift( @prices ) || GetMarcPrice($marcrecord, C4::Context->preference('marcflavour'));
173
174
        # Insert the biblio, or find it through matcher
175
        if ( $biblionumber ) { # If matched during staging we can continue
176
            $import_record->status('imported')->store;
177
            if( $overlay_action eq 'replace' ){
178
                my $biblio = Koha::Biblios->find( $biblionumber );
179
                $import_record->replace({ biblio => $biblio });
180
            }
181
        } else { # Otherwise we check for duplicates, and skip if they exist
182
            if ($matcher_id) {
183
                if ( $matcher_id eq '_TITLE_AUTHOR_' ) {
184
                    $duplifound = 1 if FindDuplicate($marcrecord);
185
                }
186
                else {
187
                    my $matcher = C4::Matcher->fetch($matcher_id);
188
                    my @matches = $matcher->get_matches( $marcrecord, my $max_matches = 1 );
189
                    $duplifound = 1 if @matches;
190
                }
191
192
                $duplinbatch = $import_batch_id and next if $duplifound;
193
            }
194
195
            # remove hyphens (-) from ISBN
196
            # FIXME: This should probably be optional
197
            my ( $isbnfield, $isbnsubfield ) = GetMarcFromKohaField( 'biblioitems.isbn' );
198
            if ( $marcrecord->field($isbnfield) ) {
199
                foreach my $field ( $marcrecord->field($isbnfield) ) {
200
                    foreach my $subfield ( $field->subfield($isbnsubfield) ) {
201
                        my $newisbn = $field->subfield($isbnsubfield);
202
                        $newisbn =~ s/-//g;
203
                        $field->update( $isbnsubfield => $newisbn );
204
                    }
205
                }
206
            }
207
208
            # add the biblio
209
            ( $biblionumber, undef ) = AddBiblio( $marcrecord, $cgiparams->{'frameworkcode'} || '' );
210
            $import_record->status('imported')->store;
211
        }
212
213
        $import_record->import_biblio->matched_biblionumber($biblionumber)->store;
214
215
        # Add items from MarcItemFieldsToOrder
216
        my @homebranches = $input->multi_param('homebranch_' . $import_record->import_record_id);
217
        my $count = scalar @homebranches;
218
        my @holdingbranches = $input->multi_param('holdingbranch_' . $import_record->import_record_id);
219
        my @itypes = $input->multi_param('itype_' . $import_record->import_record_id);
220
        my @nonpublic_notes = $input->multi_param('nonpublic_note_' . $import_record->import_record_id);
221
        my @public_notes = $input->multi_param('public_note_' . $import_record->import_record_id);
222
        my @locs = $input->multi_param('loc_' . $import_record->import_record_id);
223
        my @ccodes = $input->multi_param('ccode_' . $import_record->import_record_id);
224
        my @notforloans = $input->multi_param('notforloan_' . $import_record->import_record_id);
225
        my @uris = $input->multi_param('uri_' . $import_record->import_record_id);
226
        my @copynos = $input->multi_param('copyno_' . $import_record->import_record_id);
227
        my @budget_codes = $input->multi_param('budget_code_' . $import_record->import_record_id);
228
        my @itemprices = $input->multi_param('itemprice_' . $import_record->import_record_id);
229
        my @replacementprices = $input->multi_param('replacementprice_' . $import_record->import_record_id);
171
        my @replacementprices = $input->multi_param('replacementprice_' . $import_record->import_record_id);
230
        my @itemcallnumbers = $input->multi_param('itemcallnumber_' . $import_record->import_record_id);
172
        my @itemcallnumbers   = $input->multi_param('itemcallnumber_' . $import_record->import_record_id);
231
        my $itemcreation = 0;
173
        
232
174
        my $client_item_fields = {
233
        my @itemnumbers;
175
            homebranches        => \@homebranches,
234
        for (my $i = 0; $i < $count; $i++) {
176
            holdingbranches     => \@holdingbranches,
235
            $itemcreation = 1;
177
            itypes              => \@itypes,
236
            my $item = Koha::Item->new(
178
            nonpublic_notes     => \@nonpublic_notes,
237
                {
179
            public_notes        => \@public_notes,
238
                    biblionumber        => $biblionumber,
180
            locs                => \@locs,
239
                    homebranch          => $homebranches[$i],
181
            ccodes              => \@ccodes,
240
                    holdingbranch       => $holdingbranches[$i],
182
            notforloans         => \@notforloans,
241
                    itemnotes_nonpublic => $nonpublic_notes[$i],
183
            uris                => \@uris,
242
                    itemnotes           => $public_notes[$i],
184
            copynos             => \@copynos,
243
                    location            => $locs[$i],
185
            budget_codes        => \@budget_codes,
244
                    ccode               => $ccodes[$i],
186
            itemprices          => \@itemprices,
245
                    itype               => $itypes[$i],
187
            replacementprices   => \@replacementprices,
246
                    notforloan          => $notforloans[$i],
188
            itemcallnumbers     => \@itemcallnumbers,
247
                    uri                 => $uris[$i],
189
            c_quantity          => shift( @quantities ) || GetMarcQuantity($marcrecord, C4::Context->preference('marcflavour') ) || 1,
248
                    copynumber          => $copynos[$i],
190
            c_budget_id         => shift( @budgets_id ) || $input->param('all_budget_id') || $budget_id,
249
                    price               => $itemprices[$i],
191
            c_discount          => shift ( @discount),
250
                    replacementprice    => $replacementprices[$i],
192
            c_sort1             => shift( @sort1 ) || $input->param('all_sort1') || '',
251
                    itemcallnumber      => $itemcallnumbers[$i],
193
            c_sort2             => shift( @sort2 ) || $input->param('all_sort2') || '',
252
                }
194
            c_replacement_price => shift( @orderreplacementprices ),
253
            )->store;
195
            c_price             => shift( @prices ) || GetMarcPrice($marcrecord, C4::Context->preference('marcflavour')),
254
            push( @itemnumbers, $item->itemnumber );
196
        };
255
        }
197
256
        if ($itemcreation == 1) {
198
        my $args = {
257
            # Group orderlines from MarcItemFieldsToOrder
199
            import_batch_id           => $import_batch_id,
258
            my $budget_hash;
200
            import_record             => $import_record,
259
            for (my $i = 0; $i < $count; $i++) {
201
            matcher_id                => $matcher_id,
260
                $budget_hash->{$budget_codes[$i]}->{quantity} += 1;
202
            overlay_action            => $overlay_action,
261
                $budget_hash->{$budget_codes[$i]}->{price} = $itemprices[$i];
203
            agent                     => 'client',
262
                $budget_hash->{$budget_codes[$i]}->{replacementprice} = $replacementprices[$i];
204
            import_record_id_selected => @import_record_id_selected,
263
                $budget_hash->{$budget_codes[$i]}->{itemnumbers} //= [];
205
            client_item_fields        => $client_item_fields,
264
                push @{ $budget_hash->{$budget_codes[$i]}->{itemnumbers} }, $itemnumbers[$i];
206
            basket_id                 => $cgiparams->{'basketno'},
265
            }
207
            vendor                    => $bookseller,
266
208
            budget_id                 => $budget_id,
267
            # Create orderlines from MarcItemFieldsToOrder
209
        };
268
            while(my ($budget_id, $infos) = each %$budget_hash) {
210
        my $result = Koha::MarcOrder->import_record_and_create_order_lines($args);
269
                if ($budget_id) {
211
        
270
                    my %orderinfo = (
212
        $duplinbatch = $result->{duplicates_in_batch} if $result->{duplicates_in_batch};
271
                        biblionumber       => $biblionumber,
213
        next if $result->{skip}; # If a duplicate is found, or the import record wasn't selected it will be skipped
272
                        basketno           => $cgiparams->{'basketno'},
273
                        quantity           => $infos->{quantity},
274
                        budget_id          => $budget_id,
275
                        currency           => $cgiparams->{'all_currency'},
276
                    );
277
278
                    my $price = $infos->{price};
279
                    if ($price){
280
                        # in France, the cents separator is the , but sometimes, ppl use a .
281
                        # in this case, the price will be x100 when unformatted ! Replace the . by a , to get a proper price calculation
282
                        $price =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR";
283
                        $price = Koha::Number::Price->new($price)->unformat;
284
                        $orderinfo{tax_rate_on_ordering} = $bookseller->tax_rate;
285
                        $orderinfo{tax_rate_on_receiving} = $bookseller->tax_rate;
286
                        my $order_discount = $c_discount ? $c_discount : $bookseller->discount;
287
                        $orderinfo{discount} = $order_discount;
288
                        $orderinfo{rrp} = $price;
289
                        $orderinfo{ecost} = $order_discount ? $price * ( 1 - $order_discount / 100 ) : $price;
290
                        $orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate;
291
                        $orderinfo{unitprice} = $orderinfo{ecost};
292
                    } else {
293
                        $orderinfo{listprice} = 0;
294
                    }
295
                    $orderinfo{replacementprice} = $infos->{replacementprice} || 0;
296
297
                    # remove uncertainprice flag if we have found a price in the MARC record
298
                    $orderinfo{uncertainprice} = 0 if $orderinfo{listprice};
299
300
                    my $order = Koha::Acquisition::Order->new( \%orderinfo );
301
                    $order->populate_with_prices_for_ordering();
302
                    $order->populate_with_prices_for_receiving();
303
                    $order->store;
304
                    $order->add_item( $_ ) for @{ $budget_hash->{$budget_id}->{itemnumbers} };
305
                }
306
            }
307
        } else {
308
            # 3rd add order
309
            my $patron = Koha::Patrons->find( $loggedinuser );
310
            # get quantity in the MARC record (1 if none)
311
            my $quantity = GetMarcQuantity($marcrecord, C4::Context->preference('marcflavour')) || 1;
312
            my %orderinfo = (
313
                biblionumber       => $biblionumber,
314
                basketno           => $cgiparams->{'basketno'},
315
                quantity           => $c_quantity,
316
                branchcode         => $patron->branchcode,
317
                budget_id          => $c_budget_id,
318
                uncertainprice     => 1,
319
                sort1              => $c_sort1,
320
                sort2              => $c_sort2,
321
                order_internalnote => $cgiparams->{'all_order_internalnote'},
322
                order_vendornote   => $cgiparams->{'all_order_vendornote'},
323
                currency           => $cgiparams->{'all_currency'},
324
                replacementprice   => $c_replacement_price,
325
            );
326
            # get the price if there is one.
327
            if ($c_price){
328
                # in France, the cents separator is the , but sometimes, ppl use a .
329
                # in this case, the price will be x100 when unformatted ! Replace the . by a , to get a proper price calculation
330
                $c_price =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR";
331
                $c_price = Koha::Number::Price->new($c_price)->unformat;
332
                $orderinfo{tax_rate_on_ordering} = $bookseller->tax_rate;
333
                $orderinfo{tax_rate_on_receiving} = $bookseller->tax_rate;
334
                my $order_discount = $c_discount ? $c_discount : $bookseller->discount;
335
                $orderinfo{discount} = $order_discount;
336
                $orderinfo{rrp}   = $c_price;
337
                $orderinfo{ecost} = $order_discount ? $c_price * ( 1 - $order_discount / 100 ) : $c_price;
338
                $orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate;
339
                $orderinfo{unitprice} = $orderinfo{ecost};
340
            } else {
341
                $orderinfo{listprice} = 0;
342
            }
343
344
            # remove uncertainprice flag if we have found a price in the MARC record
345
            $orderinfo{uncertainprice} = 0 if $orderinfo{listprice};
346
347
            my $order = Koha::Acquisition::Order->new( \%orderinfo );
348
            $order->populate_with_prices_for_ordering();
349
            $order->populate_with_prices_for_receiving();
350
            $order->store;
351
352
            # 4th, add items if applicable
353
            # parse the item sent by the form, and create an item just for the import_record_id we are dealing with
354
            # this is not optimised, but it's working !
355
            if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) {
356
                my @tags         = $input->multi_param('tag');
357
                my @subfields    = $input->multi_param('subfield');
358
                my @field_values = $input->multi_param('field_value');
359
                my @serials      = $input->multi_param('serial');
360
                my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values );
361
                my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' );
362
                for (my $qtyloop=1;$qtyloop <= $c_quantity;$qtyloop++) {
363
                    my ( $biblionumber, undef, $itemnumber ) = AddItemFromMarc( $record, $biblionumber );
364
                    $order->add_item( $itemnumber );
365
                }
366
            }
367
        }
368
        $imported++;
214
        $imported++;
369
    }
215
    }
370
216
(-)a/misc/cronjobs/marc_ordering_process.pl (-1 / +129 lines)
Line 0 Link Here
0
- 
1
2
#!/usr/bin/perl
3
4
# This file is part of Koha.
5
#
6
# Copyright (C) 2023 PTFS Europe Ltd
7
#
8
# Koha is free software; you can redistribute it and/or modify it
9
# under the terms of the GNU General Public License as published by
10
# the Free Software Foundation; either version 3 of the License, or
11
# (at your option) any later version.
12
#
13
# Koha is distributed in the hope that it will be useful, but
14
# WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with Koha; if not, see <http://www.gnu.org/licenses>.
20
21
=head1 NAME
22
23
marc_ordering_process.pl - cron script to retrieve marc files and create order lines
24
25
=head1 SYNOPSIS
26
27
./marc_ordering_process.pl [-c|--confirm] [-v|--verbose]
28
29
or, in crontab:
30
# Once every day
31
0 3 * * * marc_ordering_process.pl -c
32
33
=head1 DESCRIPTION
34
35
This script searches for new marc files in an SFTP location
36
If there are new files, it stages those files, adds bilbios/items and creates order lines
37
38
=head1 OPTIONS
39
40
=over
41
42
=item B<-v|--verbose>
43
44
Print report to standard out.
45
46
=item B<-c|--confirm>
47
48
Without this parameter no changes will be made
49
50
=back
51
52
=cut
53
54
use Modern::Perl;
55
use Pod::Usage qw( pod2usage );
56
use Getopt::Long qw( GetOptions );
57
use File::Copy qw( copy move );
58
59
use Koha::Script -cron;
60
use Koha::MarcOrder;
61
use Koha::MarcOrderAccounts;
62
63
use C4::Log qw( cronlogaction );
64
65
my $command_line_options = join(" ",@ARGV);
66
67
my ( $help, $verbose, $confirm );
68
GetOptions(
69
    'h|help' => \$help,
70
    'v|verbose'    => \$verbose,
71
    'c|confirm'     => \$confirm,
72
) || pod2usage(1);
73
74
pod2usage(0) if $help;
75
76
cronlogaction({ info => $command_line_options });
77
78
$verbose = 1 unless $verbose or $confirm;
79
print "Test run only\n" unless $confirm;
80
81
print "Fetching marc ordering accounts\n" if $verbose;
82
my @accounts = Koha::MarcOrderAccounts->search(
83
    {},
84
    {
85
        join => ['vendor', 'budget']
86
    }
87
)->as_list;
88
89
if(scalar(@accounts) == 0) {
90
    print "No accounts found - you must create a Marc order account for this cronjob to run\n" if $verbose;
91
}
92
93
foreach my $acct ( @accounts ) {
94
    if($verbose) {
95
        say sprintf "Starting marc ordering process for %s", $acct->vendor->name;
96
        say sprintf "Looking for new files in %s", $acct->download_directory;
97
    }
98
99
    my $working_dir = $acct->download_directory;
100
    opendir my $dir, $working_dir or die "Can't open filepath";
101
    my @files = grep { /\.(mrc|marcxml|mrk)/i } readdir $dir;
102
    closedir $dir;
103
104
    foreach my $filename ( @files ) {
105
        say sprintf "Creating order lines from file %s", $filename if $verbose;
106
        if($confirm) {
107
            my $full_path = "$working_dir/$filename";
108
            my $args = {
109
                filename => $filename,
110
                filepath => $full_path,
111
                profile  => $acct,
112
                agent    => 'cron'
113
            };
114
            my $result = Koha::MarcOrder->create_order_lines_from_file($args);
115
            if($result->{success}) {
116
                say sprintf "Successfully processed file: %s", $filename if $verbose;
117
                unlink $full_path;
118
            } else {
119
                say sprintf "Error processing file: %s", $filename if $verbose;
120
                say sprintf "Error message: %s", $result->{error} if $verbose;
121
            };
122
        }
123
    }
124
    print "All files completed\n";
125
    print "Moving to next account\n\n";
126
}
127
print "Process complete\n";
128
cronlogaction({ action => 'End', info => "COMPLETED" });
129

Return to bug 34355