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

(-)a/Koha/MarcOrder.pm (-2 / +31 lines)
Lines 661-666 sub create_order_lines { Link Here
661
    return;
661
    return;
662
}
662
}
663
663
664
=head3 import_batches_list
665
666
Fetches import batches matching the batch to be added to the basket and adds these to the $template
667
668
Koha::MarcOrder->import_batches_list($template);
669
670
=cut
671
664
sub import_batches_list {
672
sub import_batches_list {
665
    my ( $self, $template ) = @_;
673
    my ( $self, $template ) = @_;
666
    my $batches = GetImportBatchRangeDesc();
674
    my $batches = GetImportBatchRangeDesc();
Lines 699-704 sub import_batches_list { Link Here
699
    $template->param( num_results => $num_batches );
707
    $template->param( num_results => $num_batches );
700
}
708
}
701
709
710
=head3
711
712
For an import batch, this function reads the files and creates all the relevant data pertaining to that file
713
It then passes this to the $template variable to be shown in the UI
714
715
Koha::MarcOrder->import_biblios_list( $template, $cgiparams->{'import_batch_id'} );
716
717
=cut
718
702
sub import_biblios_list {
719
sub import_biblios_list {
703
    my ( $self, $template, $import_batch_id ) = @_;
720
    my ( $self, $template, $import_batch_id ) = @_;
704
    my $batch = GetImportBatch( $import_batch_id, 'staged' );
721
    my $batch = GetImportBatch( $import_batch_id, 'staged' );
Lines 797-803 sub import_biblios_list { Link Here
797
                'uri',        'copyno',        'price', 'replacementprice', 'itemcallnumber', 'quantity', 'budget_code'
814
                'uri',        'copyno',        'price', 'replacementprice', 'itemcallnumber', 'quantity', 'budget_code'
798
            ]
815
            ]
799
        );
816
        );
800
        if ( %$alliteminfos != -1 ) {
817
        if ( !$alliteminfos || %$alliteminfos != -1 ) {
801
            my $item_homebranch     = $alliteminfos->{homebranch};
818
            my $item_homebranch     = $alliteminfos->{homebranch};
802
            my $item_holdingbranch  = $alliteminfos->{holdingbranch};
819
            my $item_holdingbranch  = $alliteminfos->{holdingbranch};
803
            my $item_itype          = $alliteminfos->{itype};
820
            my $item_itype          = $alliteminfos->{itype};
Lines 855-861 sub import_biblios_list { Link Here
855
        push @list, \%cellrecord;
872
        push @list, \%cellrecord;
856
873
857
        # If MarcItemFieldsToOrder is not set, we use MarcFieldsToOrder to populate the order form.
874
        # If MarcItemFieldsToOrder is not set, we use MarcFieldsToOrder to populate the order form.
858
        if ( %$alliteminfos == -1 ) {
875
        if ( $alliteminfos || %$alliteminfos == -1 ) {
859
            $cellrecord{price}            = $price            || '';
876
            $cellrecord{price}            = $price            || '';
860
            $cellrecord{replacementprice} = $replacementprice || '';
877
            $cellrecord{replacementprice} = $replacementprice || '';
861
            $cellrecord{quantity}         = $quantity         || '';
878
            $cellrecord{quantity}         = $quantity         || '';
Lines 896-901 sub import_biblios_list { Link Here
896
    _batch_info( $template, $batch );
913
    _batch_info( $template, $batch );
897
}
914
}
898
915
916
=head3
917
918
Creates a hash of information to be used about an import batch in the template
919
920
=cut
921
899
sub _batch_info {
922
sub _batch_info {
900
    my ( $template, $batch ) = @_;
923
    my ( $template, $batch ) = @_;
901
    $template->param(
924
    $template->param(
Lines 928-933 sub _batch_info { Link Here
928
    _add_matcher_list( $batch->{'matcher_id'}, $template );
951
    _add_matcher_list( $batch->{'matcher_id'}, $template );
929
}
952
}
930
953
954
=head3
955
956
Adds a list of available matchers based on an import batch
957
958
=cut
959
931
sub _add_matcher_list {
960
sub _add_matcher_list {
932
    my ( $current_matcher_id, $template ) = @_;
961
    my ( $current_matcher_id, $template ) = @_;
933
    my @matchers = C4::Matcher::GetMatcherList();
962
    my @matchers = C4::Matcher::GetMatcherList();
(-)a/acqui/addorderiso2709.pl (-546 / +59 lines)
Lines 30-36 use Scalar::Util qw( looks_like_number ); Link Here
30
use C4::Context;
30
use C4::Context;
31
use C4::Auth qw( get_template_and_user );
31
use C4::Auth qw( get_template_and_user );
32
use C4::Output qw( output_html_with_http_headers );
32
use C4::Output qw( output_html_with_http_headers );
33
use C4::ImportBatch qw( SetImportBatchStatus GetImportBatch GetImportBatchRangeDesc GetNumberOfNonZ3950ImportBatches GetImportBatchOverlayAction GetImportBatchNoMatchAction GetImportBatchItemAction );
33
use C4::ImportBatch qw( SetImportBatchStatus );
34
use C4::Matcher;
34
use C4::Matcher;
35
use C4::Search qw( FindDuplicate );
35
use C4::Search qw( FindDuplicate );
36
use C4::Biblio qw(
36
use C4::Biblio qw(
Lines 41-47 use C4::Biblio qw( Link Here
41
    TransformHtmlToXml
41
    TransformHtmlToXml
42
);
42
);
43
use C4::Items qw( PrepareItemrecordDisplay AddItemFromMarc );
43
use C4::Items qw( PrepareItemrecordDisplay AddItemFromMarc );
44
use C4::Budgets qw( GetBudget GetBudgets GetBudgetHierarchy CanUserUseBudget GetBudgetByCode );
44
use C4::Budgets qw( GetBudget GetBudgets GetBudgetHierarchy CanUserUseBudget );
45
use C4::Suggestions;    # GetSuggestion
45
use C4::Suggestions;    # GetSuggestion
46
use C4::Members;
46
use C4::Members;
47
47
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 90-96 my $basket = Koha::Acquisition::Baskets->find( $cgiparams->{basketno} ); Link Here
90
if ($op eq ""){
91
if ($op eq ""){
91
    $template->param("basketno" => $cgiparams->{'basketno'});
92
    $template->param("basketno" => $cgiparams->{'basketno'});
92
#display batches
93
#display batches
93
    import_batches_list($template);
94
    Koha::MarcOrder->import_batches_list($template);
94
#
95
#
95
# 2nd step = display the content of the chosen file
96
# 2nd step = display the content of the chosen file
96
#
97
#
Lines 104-110 if ($op eq ""){ Link Here
104
                     bookseller => $bookseller,
105
                     bookseller => $bookseller,
105
                     "allmatch" => $allmatch,
106
                     "allmatch" => $allmatch,
106
                     );
107
                     );
107
    import_biblios_list($template, $cgiparams->{'import_batch_id'});
108
    Koha::MarcOrder->import_biblios_list($template, $cgiparams->{'import_batch_id'});
108
    if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) {
109
    if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) {
109
        # prepare empty item form
110
        # prepare empty item form
110
        my $cell = PrepareItemrecordDisplay( '', '', undef, 'ACQ' );
111
        my $cell = PrepareItemrecordDisplay( '', '', undef, 'ACQ' );
Lines 146-381 if ($op eq ""){ Link Here
146
    my @import_record_id_selected = $input->multi_param("import_record_id");
147
    my @import_record_id_selected = $input->multi_param("import_record_id");
147
    my $matcher_id = $input->param('matcher_id');
148
    my $matcher_id = $input->param('matcher_id');
148
    my $active_currency = Koha::Acquisition::Currencies->get_active;
149
    my $active_currency = Koha::Acquisition::Currencies->get_active;
149
    my $biblio_count = 0;
150
    while( my $import_record = $import_records->next ){
150
    while( my $import_record = $import_records->next ){
151
        $biblio_count++;
151
        my $marcrecord        = $import_record->get_marc_record || die "couldn't translate marc information";
152
        my $duplifound = 0;
152
        my @homebranches      = $input->multi_param( 'homebranch_' . $import_record->import_record_id );
153
        # Check if this import_record_id was selected
153
        my @holdingbranches   = $input->multi_param( 'holdingbranch_' . $import_record->import_record_id );
154
        next if not grep { $_ eq $import_record->import_record_id } @import_record_id_selected;
154
        my @itypes            = $input->multi_param( 'itype_' . $import_record->import_record_id );
155
        my $marcrecord = $import_record->get_marc_record || die "couldn't translate marc information";
155
        my @nonpublic_notes   = $input->multi_param( 'nonpublic_note_' . $import_record->import_record_id );
156
        my $matches = $import_record->get_import_record_matches({ chosen => 1 });
156
        my @public_notes      = $input->multi_param( 'public_note_' . $import_record->import_record_id );
157
        my $match = $matches->count ? $matches->next : undef;
157
        my @locs              = $input->multi_param( 'loc_' . $import_record->import_record_id );
158
        my $biblionumber = $match ? $match->candidate_match_id : 0;
158
        my @ccodes            = $input->multi_param( 'ccode_' . $import_record->import_record_id );
159
        my $c_quantity =
159
        my @notforloans       = $input->multi_param( 'notforloan_' . $import_record->import_record_id );
160
               $input->param( 'quantity_' . $import_record->import_record_id )
160
        my @uris              = $input->multi_param( 'uri_' . $import_record->import_record_id );
161
            || GetMarcQuantity( $marcrecord, C4::Context->preference('marcflavour') )
161
        my @copynos           = $input->multi_param( 'copyno_' . $import_record->import_record_id );
162
            || 1;
162
        my @budget_codes      = $input->multi_param( 'budget_code_' . $import_record->import_record_id );
163
        my $c_budget_id =
164
               $input->param( 'budget_id_' . $import_record->import_record_id )
165
            || $input->param('all_budget_id')
166
            || $budget_id;
167
        my $c_discount = $input->param( 'discount_' . $import_record->import_record_id );
168
        my $c_sort1 = $input->param( 'sort1_' . $import_record->import_record_id ) || $input->param('all_sort1') || '';
169
        my $c_sort2 = $input->param( 'sort2_' . $import_record->import_record_id ) || $input->param('all_sort2') || '';
170
        my $c_replacement_price = $input->param( 'replacementprice_' . $import_record->import_record_id );
171
        my $c_price             = $input->param( 'price_' . $import_record->import_record_id );
172
        # Insert the biblio, or find it through matcher
173
        if ( $biblionumber ) { # If matched during staging we can continue
174
            $import_record->status('imported')->store;
175
            if( $overlay_action eq 'replace' ){
176
                my $biblio = Koha::Biblios->find( $biblionumber );
177
                $import_record->replace({ biblio => $biblio });
178
            }
179
        } else { # Otherwise we check for duplicates, and skip if they exist
180
            if ($matcher_id) {
181
                if ( $matcher_id eq '_TITLE_AUTHOR_' ) {
182
                    $duplifound = 1 if FindDuplicate($marcrecord);
183
                }
184
                else {
185
                    my $matcher = C4::Matcher->fetch($matcher_id);
186
                    my @matches = $matcher->get_matches( $marcrecord, my $max_matches = 1 );
187
                    $duplifound = 1 if @matches;
188
                }
189
190
                $duplinbatch = $import_batch_id and next if $duplifound;
191
            }
192
193
            # remove hyphens (-) from ISBN
194
            # FIXME: This should probably be optional
195
            my ( $isbnfield, $isbnsubfield ) = GetMarcFromKohaField( 'biblioitems.isbn' );
196
            if ( $marcrecord->field($isbnfield) ) {
197
                foreach my $field ( $marcrecord->field($isbnfield) ) {
198
                    foreach my $subfield ( $field->subfield($isbnsubfield) ) {
199
                        my $newisbn = $field->subfield($isbnsubfield);
200
                        $newisbn =~ s/-//g;
201
                        $field->update( $isbnsubfield => $newisbn );
202
                    }
203
                }
204
            }
205
206
            # add the biblio
207
            ( $biblionumber, undef ) = AddBiblio( $marcrecord, $cgiparams->{'frameworkcode'} || '' );
208
            $import_record->status('imported')->store;
209
        }
210
211
        $import_record->import_biblio->matched_biblionumber($biblionumber)->store;
212
213
        # Add items from MarcItemFieldsToOrder
214
        my @homebranches    = $input->multi_param( 'homebranch_' . $import_record->import_record_id );
215
        my $count           = scalar @homebranches;
216
        my @holdingbranches = $input->multi_param( 'holdingbranch_' . $import_record->import_record_id );
217
        my @itypes          = $input->multi_param( 'itype_' . $import_record->import_record_id );
218
        my @nonpublic_notes = $input->multi_param( 'nonpublic_note_' . $import_record->import_record_id );
219
        my @public_notes    = $input->multi_param( 'public_note_' . $import_record->import_record_id );
220
        my @locs            = $input->multi_param( 'loc_' . $import_record->import_record_id );
221
        my @ccodes          = $input->multi_param( 'ccode_' . $import_record->import_record_id );
222
        my @notforloans     = $input->multi_param( 'notforloan_' . $import_record->import_record_id );
223
        my @uris            = $input->multi_param( 'uri_' . $import_record->import_record_id );
224
        my @copynos         = $input->multi_param( 'copyno_' . $import_record->import_record_id );
225
        my @budget_ids =
226
            $input->multi_param( 'budget_code_' . $import_record->import_record_id ); # bad field name used in template!
227
        my @itemprices        = $input->multi_param( 'itemprice_' . $import_record->import_record_id );
163
        my @itemprices        = $input->multi_param( 'itemprice_' . $import_record->import_record_id );
228
        my @replacementprices = $input->multi_param( 'replacementprice_' . $import_record->import_record_id );
164
        my @replacementprices = $input->multi_param( 'replacementprice_' . $import_record->import_record_id );
229
        my @itemcallnumbers   = $input->multi_param( 'itemcallnumber_' . $import_record->import_record_id );
165
        my @itemcallnumbers   = $input->multi_param( 'itemcallnumber_' . $import_record->import_record_id );
230
        my @coded_location_qualifiers =
231
            $input->multi_param( 'coded_location_qualifier_' . $import_record->import_record_id );
232
        my @barcodes     = $input->multi_param( 'barcode_' . $import_record->import_record_id );
233
        my @enumchrons   = $input->multi_param( 'enumchron_' . $import_record->import_record_id );
234
        my $itemcreation = 0;
235
236
        my @itemnumbers;
237
        for (my $i = 0; $i < $count; $i++) {
238
            $itemcreation = 1;
239
            my $item = Koha::Item->new(
240
                {
241
                    biblionumber             => $biblionumber,
242
                    homebranch               => $homebranches[$i],
243
                    holdingbranch            => $holdingbranches[$i],
244
                    itemnotes_nonpublic      => $nonpublic_notes[$i],
245
                    itemnotes                => $public_notes[$i],
246
                    location                 => $locs[$i],
247
                    ccode                    => $ccodes[$i],
248
                    itype                    => $itypes[$i],
249
                    notforloan               => $notforloans[$i],
250
                    uri                      => $uris[$i],
251
                    copynumber               => $copynos[$i],
252
                    price                    => $itemprices[$i],
253
                    replacementprice         => $replacementprices[$i],
254
                    itemcallnumber           => $itemcallnumbers[$i],
255
                    coded_location_qualifier => $coded_location_qualifiers[$i],
256
                    barcode                  => $barcodes[$i],
257
                    enumchron                => $enumchrons[$i],
258
                }
259
            )->store;
260
            push( @itemnumbers, $item->itemnumber );
261
        }
262
        if ($itemcreation == 1) {
263
            # Group orderlines from MarcItemFieldsToOrder
264
            my $budget_hash;
265
            for (my $i = 0; $i < $count; $i++) {
266
                $budget_ids[$i] = $budget_id if !$budget_ids[$i];   # Use default budget if no budget selected in the UI
267
                $budget_hash->{ $budget_ids[$i] }->{quantity} += 1;
268
                $budget_hash->{ $budget_ids[$i] }->{price} = $itemprices[$i];
269
                $budget_hash->{ $budget_ids[$i] }->{replacementprice} =
270
                  $replacementprices[$i];
271
                $budget_hash->{ $budget_ids[$i] }->{itemnumbers} //= [];
272
                push @{ $budget_hash->{ $budget_ids[$i] }->{itemnumbers} },
273
                  $itemnumbers[$i];
274
            }
275
276
            # Create orderlines from MarcItemFieldsToOrder
277
            while(my ($budget_id, $infos) = each %$budget_hash) {
278
                if ($budget_id) {
279
                    my %orderinfo = (
280
                        biblionumber       => $biblionumber,
281
                        basketno           => $cgiparams->{'basketno'},
282
                        quantity           => $infos->{quantity},
283
                        budget_id          => $budget_id,
284
                        currency           => $cgiparams->{'all_currency'},
285
                    );
286
287
                    my $price = $infos->{price};
288
                    if ($price){
289
                        # in France, the cents separator is the , but sometimes, ppl use a .
290
                        # in this case, the price will be x100 when unformatted ! Replace the . by a , to get a proper price calculation
291
                        $price =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR";
292
                        $price = Koha::Number::Price->new($price)->unformat;
293
                        $orderinfo{tax_rate_on_ordering} = $bookseller->tax_rate;
294
                        $orderinfo{tax_rate_on_receiving} = $bookseller->tax_rate;
295
                        my $order_discount = $c_discount ? $c_discount : $bookseller->discount;
296
                        $orderinfo{discount} = $order_discount;
297
                        $orderinfo{rrp} = $price;
298
                        $orderinfo{ecost} = $order_discount ? $price * ( 1 - $order_discount / 100 ) : $price;
299
                        $orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate;
300
                        $orderinfo{unitprice} = $orderinfo{ecost};
301
                        $orderinfo{sort1} = $c_sort1;
302
                        $orderinfo{sort2} = $c_sort2;
303
                    } else {
304
                        $orderinfo{listprice} = 0;
305
                    }
306
                    $orderinfo{replacementprice} = $infos->{replacementprice} || 0;
307
308
                    # remove uncertainprice flag if we have found a price in the MARC record
309
                    $orderinfo{uncertainprice} = 0 if $orderinfo{listprice};
310
166
311
                    my $order = Koha::Acquisition::Order->new( \%orderinfo );
167
        my $client_item_fields = {
312
                    $order->populate_with_prices_for_ordering();
168
            homebranches      => \@homebranches,
313
                    $order->populate_with_prices_for_receiving();
169
            holdingbranches   => \@holdingbranches,
314
                    $order->store;
170
            itypes            => \@itypes,
315
                    $order->add_item( $_ ) for @{ $budget_hash->{$budget_id}->{itemnumbers} };
171
            nonpublic_notes   => \@nonpublic_notes,
316
                }
172
            public_notes      => \@public_notes,
317
            }
173
            locs              => \@locs,
318
        } else {
174
            ccodes            => \@ccodes,
319
            # 3rd add order
175
            notforloans       => \@notforloans,
320
            my $patron = Koha::Patrons->find( $loggedinuser );
176
            uris              => \@uris,
321
            # get quantity in the MARC record (1 if none)
177
            copynos           => \@copynos,
322
            my $quantity = GetMarcQuantity($marcrecord, C4::Context->preference('marcflavour')) || 1;
178
            budget_codes      => \@budget_codes,
323
            my %orderinfo = (
179
            itemprices        => \@itemprices,
324
                biblionumber       => $biblionumber,
180
            replacementprices => \@replacementprices,
325
                basketno           => $cgiparams->{'basketno'},
181
            itemcallnumbers   => \@itemcallnumbers,
326
                quantity           => $c_quantity,
182
            c_quantity        => shift(@quantities)
327
                branchcode         => $patron->branchcode,
183
                || GetMarcQuantity( $marcrecord, C4::Context->preference('marcflavour') )
328
                budget_id          => $c_budget_id,
184
                || 1,
329
                uncertainprice     => 1,
185
            c_budget_id         => shift(@budgets_id) || $input->param('all_budget_id') || $budget_id,
330
                sort1              => $c_sort1,
186
            c_discount          => shift(@discount),
331
                sort2              => $c_sort2,
187
            c_sort1             => shift(@sort1) || $input->param('all_sort1') || '',
332
                order_internalnote => $cgiparams->{'all_order_internalnote'},
188
            c_sort2             => shift(@sort2) || $input->param('all_sort2') || '',
333
                order_vendornote   => $cgiparams->{'all_order_vendornote'},
189
            c_replacement_price => shift(@orderreplacementprices),
334
                currency           => $cgiparams->{'all_currency'},
190
            c_price => shift(@prices) || GetMarcPrice( $marcrecord, C4::Context->preference('marcflavour') ),
335
                replacementprice   => $c_replacement_price,
191
        };
336
            );
192
337
            # get the price if there is one.
193
        my $args = {
338
            if ($c_price){
194
            import_batch_id           => $import_batch_id,
339
                # in France, the cents separator is the , but sometimes, ppl use a .
195
            import_record             => $import_record,
340
                # in this case, the price will be x100 when unformatted ! Replace the . by a , to get a proper price calculation
196
            matcher_id                => $matcher_id,
341
                $c_price =~ s/\./,/ if C4::Context->preference("CurrencyFormat") eq "FR";
197
            overlay_action            => $overlay_action,
342
                $c_price = Koha::Number::Price->new($c_price)->unformat;
198
            agent                     => 'client',
343
                $orderinfo{tax_rate_on_ordering} = $bookseller->tax_rate;
199
            import_record_id_selected => \@import_record_id_selected,
344
                $orderinfo{tax_rate_on_receiving} = $bookseller->tax_rate;
200
            client_item_fields        => $client_item_fields,
345
                my $order_discount = $c_discount ? $c_discount : $bookseller->discount;
201
            basket_id                 => $cgiparams->{'basketno'},
346
                $orderinfo{discount} = $order_discount;
202
            vendor                    => $bookseller,
347
                $orderinfo{rrp}   = $c_price;
203
            budget_id                 => $budget_id,
348
                $orderinfo{ecost} = $order_discount ? $c_price * ( 1 - $order_discount / 100 ) : $c_price;
204
        };
349
                $orderinfo{listprice} = $orderinfo{rrp} / $active_currency->rate;
205
        my $result = Koha::MarcOrder->import_record_and_create_order_lines($args);
350
                $orderinfo{unitprice} = $orderinfo{ecost};
206
351
            } else {
207
        $duplinbatch = $result->{duplicates_in_batch} if $result->{duplicates_in_batch};
352
                $orderinfo{listprice} = 0;
208
        next if $result->{skip};    # If a duplicate is found, or the import record wasn't selected it will be skipped
353
            }
354
209
355
            # remove uncertainprice flag if we have found a price in the MARC record
356
            $orderinfo{uncertainprice} = 0 if $orderinfo{listprice};
357
358
            my $order = Koha::Acquisition::Order->new( \%orderinfo );
359
            $order->populate_with_prices_for_ordering();
360
            $order->populate_with_prices_for_receiving();
361
            $order->store;
362
363
            # 4th, add items if applicable
364
            # parse the item sent by the form, and create an item just for the import_record_id we are dealing with
365
            # this is not optimised, but it's working !
366
            if ( $basket->effective_create_items eq 'ordering' && !$basket->is_standing ) {
367
                my @tags         = $input->multi_param('tag');
368
                my @subfields    = $input->multi_param('subfield');
369
                my @field_values = $input->multi_param('field_value');
370
                my @serials      = $input->multi_param('serial');
371
                my $xml = TransformHtmlToXml( \@tags, \@subfields, \@field_values );
372
                my $record = MARC::Record::new_from_xml( $xml, 'UTF-8' );
373
                for (my $qtyloop=1;$qtyloop <= $c_quantity;$qtyloop++) {
374
                    my ( $biblionumber, undef, $itemnumber ) = AddItemFromMarc( $record, $biblionumber );
375
                    $order->add_item( $itemnumber );
376
                }
377
            }
378
        }
379
        $imported++;
210
        $imported++;
380
    }
211
    }
381
212
Lines 421-740 foreach my $r ( @{$budgets_hierarchy} ) { Link Here
421
$template->param( budget_loop    => $budget_loop,);
252
$template->param( budget_loop    => $budget_loop,);
422
253
423
output_html_with_http_headers $input, $cookie, $template->output;
254
output_html_with_http_headers $input, $cookie, $template->output;
424
425
426
sub import_batches_list {
427
    my ($template) = @_;
428
    my $batches = GetImportBatchRangeDesc();
429
430
    my @list = ();
431
    foreach my $batch (@$batches) {
432
        if ( $batch->{'import_status'} =~ /^staged$|^reverted$/ && $batch->{'record_type'} eq 'biblio') {
433
            # check if there is at least 1 line still staged
434
            my $import_records_count = Koha::Import::Records->search({
435
                import_batch_id => $batch->{'import_batch_id'},
436
                status          => $batch->{import_status}
437
            })->count;
438
            if ( $import_records_count ) {
439
                push @list, {
440
                        import_batch_id => $batch->{'import_batch_id'},
441
                        num_records => $batch->{'num_records'},
442
                        num_items => $batch->{'num_items'},
443
                        staged_date => $batch->{'upload_timestamp'},
444
                        import_status => $batch->{'import_status'},
445
                        file_name => $batch->{'file_name'},
446
                        comments => $batch->{'comments'},
447
                };
448
            } else {
449
                # if there are no more line to includes, set the status to imported
450
                # FIXME This should be removed in the future.
451
                SetImportBatchStatus( $batch->{'import_batch_id'}, 'imported' );
452
            }
453
        }
454
    }
455
    $template->param(batch_list => \@list); 
456
    my $num_batches = GetNumberOfNonZ3950ImportBatches();
457
    $template->param(num_results => $num_batches);
458
}
459
460
sub import_biblios_list {
461
    my ($template, $import_batch_id) = @_;
462
    my $batch = GetImportBatch($import_batch_id,'staged');
463
    return () unless $batch and $batch->{import_status} =~ /^staged$|^reverted$/;
464
    my $import_records = Koha::Import::Records->search({
465
        import_batch_id => $import_batch_id,
466
        status => $batch->{import_status}
467
    });
468
    my @list = ();
469
    my $item_error = 0;
470
471
    my $ccodes = { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.ccode' } ) };
472
    my $locations = { map { $_->{authorised_value} => $_->{opac_description} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.location' } ) };
473
    my $notforloans = { map { $_->{authorised_value} => $_->{lib} } Koha::AuthorisedValues->get_descriptions_by_koha_field( { frameworkcode => '', kohafield => 'items.notforloan' } ) };
474
    # location list
475
    my @locations;
476
    foreach (sort keys %$locations) {
477
        push @locations, { code => $_, description => "$_ - " . $locations->{$_} };
478
    }
479
    my @ccodes;
480
    foreach (sort {$ccodes->{$a} cmp $ccodes->{$b}} keys %$ccodes) {
481
        push @ccodes, { code => $_, description => $ccodes->{$_} };
482
    }
483
    my @notforloans;
484
    foreach (sort {$notforloans->{$a} cmp $notforloans->{$b}} keys %$notforloans) {
485
        push @notforloans, { code => $_, description => $notforloans->{$_} };
486
    }
487
488
    my $biblio_count = 0;
489
    while ( my $import_record = $import_records->next ) {
490
        my $item_id = 1;
491
        $biblio_count++;
492
        my $matches = $import_record->get_import_record_matches({ chosen => 1 });
493
        my $match = $matches->count ? $matches->next : undef;
494
        my $match_biblio = $match ? Koha::Biblios->find({ biblionumber => $match->candidate_match_id }) : undef;
495
        my %cellrecord = (
496
            import_record_id => $import_record->import_record_id,
497
            import_biblio => $import_record->import_biblio,
498
            import  => 1,
499
            status => $import_record->status,
500
            record_sequence => $import_record->record_sequence,
501
            overlay_status => $import_record->overlay_status,
502
            match_biblionumber => $match ? $match->candidate_match_id : 0,
503
            match_citation     => $match_biblio ? ($match_biblio->title || '') . ' ' .( $match_biblio->author || ''): '',
504
            match_score => $match ? $match->score : 0,
505
        );
506
        my $marcrecord = $import_record->get_marc_record || die "couldn't translate marc information";
507
508
        my $infos = get_infos_syspref('MarcFieldsToOrder', $marcrecord, ['price', 'quantity', 'budget_code', 'discount', 'sort1', 'sort2','replacementprice']);
509
        my $price = looks_like_number($infos->{price}) ? $infos->{price} : GetMarcPrice( $marcrecord, C4::Context->preference('marcflavour') );
510
        my $replacementprice = $infos->{replacementprice};
511
        my $quantity = $infos->{quantity};
512
        my $budget_code = $infos->{budget_code};
513
        my $discount = $infos->{discount};
514
        my $sort1 = $infos->{sort1};
515
        my $sort2 = $infos->{sort2};
516
        my $budget_id;
517
518
        if ($budget_code) {
519
            my $biblio_budget = GetBudgetByCode($budget_code);
520
            if ($biblio_budget) {
521
                $budget_id = $biblio_budget->{budget_id};
522
            }
523
        }
524
525
        # Items
526
        my @itemlist = ();
527
        my $all_items_quantity = 0;
528
        my $alliteminfos = get_marc_item_fields_to_order($marcrecord);
529
        if ($alliteminfos != -1) {
530
            foreach my $iteminfos (@$alliteminfos) {
531
                # Quantity is required, default to one if not supplied
532
                my $quantity = delete $iteminfos->{quantity} || 1;
533
534
                # Handle incorrectly named original parameters for MarcItemFieldsToOrder
535
                $iteminfos->{location}   = delete $iteminfos->{loc}    if $iteminfos->{loc};
536
                $iteminfos->{copynumber} = delete $iteminfos->{copyno} if $iteminfos->{copyno};
537
                # Price is handled as "itemprice" in the UI form to distinguish from MarcFieldsToOrder
538
                $iteminfos->{itemprice}  = delete $iteminfos->{price}  if $iteminfos->{price};
539
540
                # Convert budge code to a budget id
541
                my $item_budget_code = delete $iteminfos->{budget_code};
542
                if ( $item_budget_code ) {
543
                    my $item_budget = GetBudgetByCode( $item_budget_code );
544
                    $iteminfos->{budget_id} = $item_budget->{budget_id} || $budget_id;
545
                }
546
547
                $iteminfos->{price} ||= $price;    # Fallback to order price if no item price was defined
548
549
                # Clone the item data for the needed quantity
550
                # Add the incremented item id for each item in that quantity
551
                for (my $i = 0; $i < $quantity; $i++) {
552
                    my $itemrecord = { %$iteminfos };
553
                    $itemrecord->{item_id} = $item_id++;
554
                    $all_items_quantity++;
555
                    push @itemlist, $itemrecord;
556
                }
557
            }
558
559
            $cellrecord{'iteminfos'} = \@itemlist;
560
        } else {
561
            $cellrecord{'item_error'} = 1;
562
        }
563
        push @list, \%cellrecord;
564
565
        # If MarcItemFieldsToOrder is not set, we use MarcFieldsToOrder to populate the order form.
566
        if ($alliteminfos == -1 || scalar(@$alliteminfos) == 0) {
567
            $cellrecord{price} = $price || '';
568
            $cellrecord{replacementprice} = $replacementprice || '';
569
            $cellrecord{quantity} = $quantity || '';
570
            $cellrecord{budget_id} = $budget_id || '';
571
        } else {
572
            # When using MarcItemFields to order we want the order to have the same quantity as total items
573
            $cellrecord{quantity} = $all_items_quantity;
574
        }
575
        # The fields discount, sort1, and sort2 only exist at the order level, so always use MarcItemFieldsToOrder
576
        $cellrecord{discount} = $discount || '';
577
        $cellrecord{sort1} = $sort1 || '';
578
        $cellrecord{sort2} = $sort2 || '';
579
580
    }
581
    my $num_records = $batch->{'num_records'};
582
    my $overlay_action = GetImportBatchOverlayAction($import_batch_id);
583
    my $nomatch_action = GetImportBatchNoMatchAction($import_batch_id);
584
    my $item_action = GetImportBatchItemAction($import_batch_id);
585
    $template->param(import_biblio_list => \@list,
586
                        num_results => $num_records,
587
                        import_batch_id => $import_batch_id,
588
                        "overlay_action_${overlay_action}" => 1,
589
                        overlay_action => $overlay_action,
590
                        "nomatch_action_${nomatch_action}" => 1,
591
                        nomatch_action => $nomatch_action,
592
                        "item_action_${item_action}" => 1,
593
                        item_action => $item_action,
594
                        item_error => $item_error,
595
                        libraries => Koha::Libraries->search,
596
                        locationloop => \@locations,
597
                        itemtypes => Koha::ItemTypes->search,
598
                        ccodeloop => \@ccodes,
599
                        notforloanloop => \@notforloans,
600
                    );
601
    batch_info($template, $batch);
602
}
603
604
sub batch_info {
605
    my ($template, $batch) = @_;
606
    $template->param(batch_info => 1,
607
                                      file_name => $batch->{'file_name'},
608
                                          comments => $batch->{'comments'},
609
                                          import_status => $batch->{'import_status'},
610
                                          upload_timestamp => $batch->{'upload_timestamp'},
611
                                          num_records => $batch->{'num_records'},
612
                                          num_items => $batch->{'num_items'});
613
    if ($batch->{'num_records'} > 0) {
614
        if ($batch->{'import_status'} eq 'staged' or $batch->{'import_status'} eq 'reverted') {
615
            $template->param(can_commit => 1);
616
        }
617
        if ($batch->{'import_status'} eq 'imported') {
618
            $template->param(can_revert => 1);
619
        }
620
    }
621
    if (defined $batch->{'matcher_id'}) {
622
        my $matcher = C4::Matcher->fetch($batch->{'matcher_id'});
623
        if (defined $matcher) {
624
            $template->param('current_matcher_id' => $batch->{'matcher_id'},
625
                                              'current_matcher_code' => $matcher->code(),
626
                                              'current_matcher_description' => $matcher->description());
627
        }
628
    }
629
    add_matcher_list($batch->{'matcher_id'}, $template);
630
}
631
632
sub add_matcher_list {
633
    my ($current_matcher_id, $template) = @_;
634
    my @matchers = C4::Matcher::GetMatcherList();
635
    if (defined $current_matcher_id) {
636
        for (my $i = 0; $i <= $#matchers; $i++) {
637
            if ($matchers[$i]->{'matcher_id'} == $current_matcher_id) {
638
                $matchers[$i]->{'selected'} = 1;
639
            }
640
        }
641
    }
642
    $template->param(available_matchers => \@matchers);
643
}
644
645
sub get_infos_syspref {
646
    my ($syspref_name, $record, $field_list) = @_;
647
    my $yaml = C4::Context->yaml_preference($syspref_name);
648
649
    my $r;
650
    for my $field_name ( @$field_list ) {
651
        next unless exists $yaml->{$field_name};
652
        my @fields = split /\|/, $yaml->{$field_name};
653
        for my $field ( @fields ) {
654
            my ( $f, $sf ) = split /\$/, $field;
655
            next unless $f and $sf;
656
            if ( my $v = $record->subfield( $f, $sf ) ) {
657
                $r->{$field_name} = $v;
658
            }
659
            last if $yaml->{$field};
660
        }
661
    }
662
    return $r;
663
}
664
665
sub equal_number_of_fields {
666
    my ($tags_list, $record) = @_;
667
    my $tag_fields_count;
668
    for my $tag (@$tags_list) {
669
        my @fields = $record->field($tag);
670
        $tag_fields_count->{$tag} = scalar @fields;
671
    }
672
673
    my $tags_count;
674
    foreach my $key ( keys %$tag_fields_count ) {
675
        if ( $tag_fields_count->{$key} > 0 ) { # Having 0 of a field is ok
676
            $tags_count //= $tag_fields_count->{$key}; # Start with the count from the first occurrence
677
            return -1 if $tag_fields_count->{$key} != $tags_count; # All counts of various fields should be equal if they exist
678
        }
679
    }
680
681
    return $tags_count;
682
}
683
684
sub get_marc_item_fields_to_order {
685
    my ($record) = @_;
686
687
    my $syspref = C4::Context->preference('MarcItemFieldsToOrder');
688
    $syspref = "$syspref\n\n"; # YAML is anal on ending \n. Surplus does not hurt
689
    my $yaml = eval {
690
        YAML::XS::Load(Encode::encode_utf8($syspref));
691
    };
692
    if ( $@ ) {
693
        warn "Unable to parse $syspref syspref : $@";
694
        return ();
695
    }
696
697
    my @result;
698
    my @tags_list;
699
700
    # Check tags in syspref definition
701
    for my $field_name ( keys %$yaml ) {
702
        my @fields = split /\|/, $yaml->{$field_name};
703
        for my $field ( @fields ) {
704
            my ( $f, $sf ) = split /\$/, $field;
705
            next unless $f and $sf;
706
            push @tags_list, $f;
707
        }
708
    }
709
    @tags_list = List::MoreUtils::uniq(@tags_list);
710
711
    my $tags_count = equal_number_of_fields(\@tags_list, $record);
712
    # Return if the number of these fields in the record is not the same.
713
    return -1 if $tags_count == -1;
714
715
    # Gather the fields
716
    my $fields_hash;
717
    foreach my $tag (@tags_list) {
718
        my @tmp_fields;
719
        foreach my $field ($record->field($tag)) {
720
            push @tmp_fields, $field;
721
        }
722
        $fields_hash->{$tag} = \@tmp_fields;
723
    }
724
725
    for (my $i = 0; $i < $tags_count; $i++) {
726
        my $r;
727
        for my $field_name ( keys %$yaml ) {
728
            my @fields = split /\|/, $yaml->{$field_name};
729
            for my $field ( @fields ) {
730
                my ( $f, $sf ) = split /\$/, $field;
731
                next unless $f and $sf;
732
                my $v = $fields_hash->{$f}[$i] ? $fields_hash->{$f}[$i]->subfield( $sf ) : undef;
733
                $r->{$field_name} = $v if (defined $v);
734
                last if $yaml->{$field};
735
            }
736
        }
737
        push @result, $r;
738
    }
739
    return \@result;
740
}
741
- 

Return to bug 35026