Bugzilla – Attachment 169899 Details for
Bug 34355
Automated MARC record ordering process
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 34355: Add cronjob and required methods
Bug-34355-Add-cronjob-and-required-methods.patch (text/plain), 29.12 KB, created by
Matt Blenkinsop
on 2024-07-31 15:10:37 UTC
(
hide
)
Description:
Bug 34355: Add cronjob and required methods
Filename:
MIME Type:
Creator:
Matt Blenkinsop
Created:
2024-07-31 15:10:37 UTC
Size:
29.12 KB
patch
obsolete
>From 55e569269533ced78ceda08f46a90fef6d3a0bad Mon Sep 17 00:00:00 2001 >From: Matt Blenkinsop <matt.blenkinsop@ptfs-europe.com> >Date: Mon, 24 Jul 2023 13:53:22 +0000 >Subject: [PATCH] Bug 34355: Add cronjob and required methods > >This patch adds a cronjob to take a marc file from the Koha file directory system and import it before creating order lines > >Test plan: > >This test plan involves running a cronjob, not sure how easy this is in the sandboxes > >1) In system preferences, click Search and then select the Acquisitions option from the left hand menu >2) Enable MarcOrderingAutomation >3) Paste the following into MarcFieldsToOrder >price: 975$p >quantity: 975$q >budget_code: 975$h >4) Paste the following into MarcItemFieldsToOrder >homebranch: 949$a >holdingbranch: 949$b >itype: 949$y >nonpublic_note: 949$x >public_note: 949$z >loc: 949$c >ccode: 949$8 >notforloan: 949$7 >uri: 949$u >copyno: 949$t >price: 949$g >replacementprice: 949$v >itemcallnumber: 949$o >quantity: 949$k >budget_code: 949$l >Now save the sysprefs >5) In the administration homepage, under Acquisition parameters there should now be a link called "MARC order accounts" >6) Click on this and click the New account button >7) Choose a vendor and a budget >8) Enter a description >9) Enter the following in download directory - "/var/lib/koha/kohadev/tmp/koha_kohadev_upload" >10) Select any record matching settings you want (not important for the test plan, this uses the same code as the marc file staging that already exists in Koha) >11) Check Yes under Check for embedded item record data >12) Click submit >13) We now need to upload a MARC file into the directory that we put in the account. The easiest way to do this is through the marc staging tool >14) Navigate to Cataloging > Stage MARC records for import >15) Upload the file attached to this bug using the Choose file button >16) Click Upload file. >17) Leave the page without completing the new form that appears, we don't want to stage this file. The file we uploaded is now in the directory ready for the cronjob to process as if it had been transferred via SFTP. >18) In the CLI run, perl misc/cronjobs/marc_ordering_process.pl -v -c >19) The logging should show that the file has been processed for that account >20) Navigate to Acquisitions >21) Search for the Vendor that you put in the MARC ordering account >22) There should be a basket created on the vendor with the name of the file you uploaded (there will also be a reference at the start e.g. ea2323966faef2c59a6056dbd1f7d658_filename.marcxml. This is because we used the marc staging tool to upload the file and that adds a reference to filenames. This will not appear when using files from an SFTP location). >23) Click in the basket >24) There should be three orderlines, complete with accounting details that have been mapped from the file. >One line should have a fund of Fund 1_2, quantity of 4 and a replacement price of 6.75, one should have Secondary fund, 2, 6.40 and one should have Main fund,2, 6.30 >--- > Koha/MarcOrder.pm | 418 +++++++++++++++++++++---- > misc/cronjobs/marc_ordering_process.pl | 131 ++++++++ > 2 files changed, 484 insertions(+), 65 deletions(-) > create mode 100755 misc/cronjobs/marc_ordering_process.pl > >diff --git a/Koha/MarcOrder.pm b/Koha/MarcOrder.pm >index 4bb58c41cf0..525ae442a64 100644 >--- a/Koha/MarcOrder.pm >+++ b/Koha/MarcOrder.pm >@@ -19,6 +19,7 @@ package Koha::MarcOrder; > > use Modern::Perl; > use Try::Tiny qw( catch try ); >+use Net::FTP; > > use base qw(Koha::Object); > >@@ -47,7 +48,6 @@ use C4::Biblio qw( > AddBiblio > GetMarcFromKohaField > TransformHtmlToXml >- GetMarcQuantity > ); > use C4::Items qw( AddItemFromMarc ); > use C4::Budgets qw( GetBudgetByCode ); >@@ -70,6 +70,98 @@ Koha::MarcOrder - Koha Marc Order Object class > > =cut > >+=head3 create_order_lines_from_file >+ >+ my $result = Koha::MarcOrder->create_order_lines_from_file($args); >+ >+ Controller for file staging, basket creation and order line creation when using the cronjob in marc_ordering_process.pl >+ >+=cut >+ >+sub create_order_lines_from_file { >+ my ( $self, $args ) = @_; >+ >+ my $filename = $args->{filename}; >+ my $filepath = $args->{filepath}; >+ my $profile = $args->{profile}; >+ my $agent = $args->{agent}; >+ >+ my $success; >+ my $error; >+ >+ my $vendor_id = $profile->vendor_id; >+ my $budget_id = $profile->budget_id; >+ >+ my $vendor_record = Koha::Acquisition::Booksellers->find( { id => $vendor_id } ); >+ >+ my $basket_id = _create_basket_for_file( >+ { >+ filename => $filename, >+ vendor_id => $vendor_id >+ } >+ ); >+ >+ my $format = index( $filename, '.mrc' ) != -1 ? 'ISO2709' : 'MARCXML'; >+ my $params = { >+ record_type => $profile->record_type, >+ encoding => $profile->encoding, >+ format => $format, >+ filepath => $filepath, >+ filename => $filename, >+ comments => undef, >+ parse_items => $profile->parse_items, >+ matcher_id => $profile->matcher_id, >+ overlay_action => $profile->overlay_action, >+ nomatch_action => $profile->nomatch_action, >+ item_action => $profile->item_action, >+ }; >+ >+ try { >+ my $import_batch_id = _stage_file($params); >+ >+ my $import_records = Koha::Import::Records->search( >+ { >+ import_batch_id => $import_batch_id, >+ } >+ ); >+ >+ while ( my $import_record = $import_records->next ) { >+ my $result = add_biblio_from_import_record( >+ { >+ import_batch_id => $import_batch_id, >+ import_record => $import_record, >+ matcher_id => $params->{matcher_id}, >+ overlay_action => $params->{overlay_action}, >+ agent => $agent, >+ } >+ ); >+ warn "Duplicates found in $result->{duplicates_in_batch}, record was skipped." >+ if $result->{duplicates_in_batch}; >+ next if $result->{skip}; >+ >+ my $order_line_details = add_items_from_import_record( >+ { >+ record_result => $result->{record_result}, >+ basket_id => $basket_id, >+ vendor => $vendor_record, >+ budget_id => $budget_id, >+ agent => $agent, >+ } >+ ); >+ } >+ SetImportBatchStatus( $import_batch_id, 'imported' ) >+ if Koha::Import::Records->search( { import_batch_id => $import_batch_id, status => 'imported' } )->count == >+ Koha::Import::Records->search( { import_batch_id => $import_batch_id } )->count; >+ >+ $success = 1; >+ } catch { >+ $success = 0; >+ $error = $_; >+ }; >+ >+ return $success ? { success => 1, error => '' } : { success => 0, error => $error }; >+} >+ > =head3 import_record_and_create_order_lines > > my $result = Koha::MarcOrder->import_record_and_create_order_lines($args); >@@ -82,7 +174,7 @@ sub import_record_and_create_order_lines { > my ( $self, $args ) = @_; > > my $import_batch_id = $args->{import_batch_id}; >- my $import_record_id_selected = $args->{import_record_id_selected} || (); >+ my @import_record_id_selected = $args->{import_record_id_selected} || (); > my $matcher_id = $args->{matcher_id}; > my $overlay_action = $args->{overlay_action}; > my $import_record = $args->{import_record}; >@@ -125,6 +217,121 @@ sub import_record_and_create_order_lines { > }; > } > >+=head3 _create_basket_for_file >+ >+ my $basket_id = _create_basket_for_file({ >+ filename => $filename, >+ vendor_id => $vendor_id >+ }); >+ >+ Creates a basket ready to receive order lines based on the imported file >+ >+=cut >+ >+sub _create_basket_for_file { >+ my ($args) = @_; >+ >+ my $filename = $args->{filename}; >+ my $vendor_id = $args->{vendor_id}; >+ >+ # aqbasketname.basketname has a max length of 50 characters so long file names will need to be truncated >+ my $basketname = length($filename) > 50 ? substr( $filename, 0, 50 ) : $filename; >+ >+ my $basketno = NewBasket( >+ $vendor_id, 0, $basketname, q{}, >+ q{} . q{} >+ ); >+ >+ return $basketno; >+} >+ >+=head3 _stage_file >+ >+ $file->_stage_file($params) >+ >+ Stages a file directly using parameters from a marc ordering account and without using the background job >+ This function is a mirror of Koha::BackgroundJob::StageMARCForImport->process but with the background job functionality removed >+ >+=cut >+ >+sub _stage_file { >+ my ($args) = @_; >+ >+ my $record_type = $args->{record_type}; >+ my $encoding = $args->{encoding}; >+ my $format = $args->{format}; >+ my $filepath = $args->{filepath}; >+ my $filename = $args->{filename}; >+ my $marc_modification_template = $args->{marc_modification_template}; >+ my $comments = $args->{comments}; >+ my $parse_items = $args->{parse_items}; >+ my $matcher_id = $args->{matcher_id}; >+ my $overlay_action = $args->{overlay_action}; >+ my $nomatch_action = $args->{nomatch_action}; >+ my $item_action = $args->{item_action}; >+ >+ my ( $batch_id, $num_valid, $num_items, @import_errors ); >+ my $num_with_matches = 0; >+ my $checked_matches = 0; >+ my $matcher_failed = 0; >+ my $matcher_code = ""; >+ >+ my $schema = Koha::Database->new->schema; >+ try { >+ $schema->storage->txn_begin; >+ >+ my ( $errors, $marcrecords ); >+ if ( $format eq 'MARCXML' ) { >+ ( $errors, $marcrecords ) = C4::ImportBatch::RecordsFromMARCXMLFile( $filepath, $encoding ); >+ } elsif ( $format eq 'ISO2709' ) { >+ ( $errors, $marcrecords ) = C4::ImportBatch::RecordsFromISO2709File( >+ $filepath, $record_type, >+ $encoding >+ ); >+ } else { # plugin based >+ $errors = []; >+ $marcrecords = C4::ImportBatch::RecordsFromMarcPlugin( >+ $filepath, $format, >+ $encoding >+ ); >+ } >+ >+ ( $batch_id, $num_valid, $num_items, @import_errors ) = BatchStageMarcRecords( >+ $record_type, $encoding, >+ $marcrecords, $filename, >+ $marc_modification_template, $comments, >+ '', $parse_items, >+ 0 >+ ); >+ >+ if ($matcher_id) { >+ my $matcher = C4::Matcher->fetch($matcher_id); >+ if ( defined $matcher ) { >+ $checked_matches = 1; >+ $matcher_code = $matcher->code(); >+ $num_with_matches = BatchFindDuplicates( $batch_id, $matcher, 10 ); >+ SetImportBatchMatcher( $batch_id, $matcher_id ); >+ SetImportBatchOverlayAction( $batch_id, $overlay_action ); >+ SetImportBatchNoMatchAction( $batch_id, $nomatch_action ); >+ SetImportBatchItemAction( $batch_id, $item_action ); >+ $schema->storage->txn_commit; >+ } else { >+ $matcher_failed = 1; >+ $schema->storage->txn_rollback; >+ } >+ } else { >+ $schema->storage->txn_commit; >+ } >+ >+ return $batch_id; >+ } catch { >+ warn $_; >+ $schema->storage->txn_rollback; >+ die "Something terrible has happened!" >+ if ( $_ =~ /Rollback failed/ ); # TODO Check test: Rollback failed >+ }; >+} >+ > =head3 _get_syspref_mappings > > my $syspref_info = _get_syspref_mappings( $marcrecord, $syspref_name ); >@@ -210,6 +417,7 @@ sub _verify_number_of_fields { > $tags_count; # All counts of various fields should be equal if they exist > } > } >+ > return { error => 0, count => $tags_count }; > } > >@@ -234,7 +442,7 @@ sub add_biblio_from_import_record { > my ($args) = @_; > > my $import_batch_id = $args->{import_batch_id}; >- my $import_record_id_selected = $args->{import_record_id_selected} || (); >+ my @import_record_id_selected = $args->{import_record_id_selected} || (); > my $matcher_id = $args->{matcher_id}; > my $overlay_action = $args->{overlay_action}; > my $import_record = $args->{import_record}; >@@ -247,7 +455,7 @@ sub add_biblio_from_import_record { > record_result => 0, > duplicates_in_batch => 0, > skip => 1 >- } if not grep { $_ eq $import_record->import_record_id } @{$import_record_id_selected}; >+ } if not grep { $_ eq $import_record->import_record_id } @import_record_id_selected; > } > > my $marcrecord = $import_record->get_marc_record || die "Couldn't translate marc information"; >@@ -333,29 +541,13 @@ sub add_items_from_import_record { > my $marc_fields_to_order = _get_syspref_mappings( $marcrecord, 'MarcFieldsToOrder' ); > my $marc_item_fields_to_order = _get_syspref_mappings( $marcrecord, 'MarcItemFieldsToOrder' ); > >- my $item_fields = { >- homebranch => $marc_item_fields_to_order->{homebranch}, >- holdingbranch => $marc_item_fields_to_order->{holdingbranch}, >- itype => $marc_item_fields_to_order->{itype}, >- nonpublic_note => $marc_item_fields_to_order->{nonpublic_note}, >- public_note => $marc_item_fields_to_order->{public_note}, >- loc => $marc_item_fields_to_order->{loc}, >- ccode => $marc_item_fields_to_order->{ccode}, >- notforloan => $marc_item_fields_to_order->{notforloan}, >- uri => $marc_item_fields_to_order->{uri}, >- copyno => $marc_item_fields_to_order->{copyno}, >- quantity => $marc_item_fields_to_order->{quantity}, >- price => $marc_item_fields_to_order->{price}, >- replacementprice => $marc_item_fields_to_order->{replacementprice}, >- itemcallnumber => $marc_item_fields_to_order->{itemcallnumber}, >- budget_code => $marc_item_fields_to_order->{budget_code}, >- c_quantity => $marc_fields_to_order->{quantity}, >- c_budget_code => $marc_fields_to_order->{budget_code}, >- c_price => $marc_fields_to_order->{price}, >- c_discount => $marc_fields_to_order->{discount}, >- c_sort1 => $marc_fields_to_order->{sort1}, >- c_sort2 => $marc_fields_to_order->{sort2}, >- }; >+ my $item_fields = _create_item_fields_from_syspref( >+ { >+ marc_fields_to_order => $marc_fields_to_order, >+ marc_item_fields_to_order => $marc_item_fields_to_order, >+ budget_id => $budget_id >+ } >+ ); > > my $order_line_fields = parse_input_into_order_line_fields( > { >@@ -405,6 +597,7 @@ sub add_items_from_import_record { > } > } > >+ > =head3 import_batches_list > > Fetches import batches matching the batch to be added to the basket and returns these to the template >@@ -668,7 +861,6 @@ my $order_line_fields = parse_input_into_order_line_fields( > } > ); > >- > =cut > > sub parse_input_into_order_line_fields { >@@ -682,48 +874,45 @@ sub parse_input_into_order_line_fields { > my $fields = $args->{fields}; > my $marcrecord = $args->{marcrecord}; > >- my $quantity = $fields->{quantity} || 1; >- my @homebranches = $client ? @{ $fields->{homebranches} } : ( ( $fields->{homebranch} ) x $quantity ); >- my @holdingbranches = $client ? @{ $fields->{holdingbranches} } : ( ( $fields->{holdingbranch} ) x $quantity ); >- my @itypes = $client ? @{ $fields->{itypes} } : ( ( $fields->{itype} ) x $quantity ); >- my @nonpublic_notes = $client ? @{ $fields->{nonpublic_notes} } : ( ( $fields->{nonpublic_note} ) x $quantity ); >- my @public_notes = $client ? @{ $fields->{public_notes} } : ( ( $fields->{public_note} ) x $quantity ); >- my @locs = $client ? @{ $fields->{locs} } : ( ( $fields->{loc} ) x $quantity ); >- my @ccodes = $client ? @{ $fields->{ccodes} } : ( ( $fields->{ccode} ) x $quantity ); >- my @notforloans = $client ? @{ $fields->{notforloans} } : ( ( $fields->{notforloan} ) x $quantity ); >- my @uris = $client ? @{ $fields->{uris} } : ( ( $fields->{uri} ) x $quantity ); >- my @copynos = $client ? @{ $fields->{copynos} } : ( ( $fields->{copyno} ) x $quantity ); >- my @itemprices = $client ? @{ $fields->{itemprices} } : ( ( $fields->{price} ) x $quantity ); >- my @replacementprices = >- $client ? @{ $fields->{replacementprices} } : ( ( $fields->{replacementprice} ) x $quantity ); >- my @itemcallnumbers = $client ? @{ $fields->{itemcallnumbers} } : ( ( $fields->{itemcallnumber} ) x $quantity ); >+ my $quantity = $fields->{quantity} || 1; >+ my @homebranches = $fields->{homebranches} ? @{ $fields->{homebranches} } : (); >+ my @holdingbranches = $fields->{holdingbranches} ? @{ $fields->{holdingbranches} } : (); >+ my @itypes = $fields->{itypes} ? @{ $fields->{itypes} } : (); >+ my @nonpublic_notes = $fields->{nonpublic_notes} ? @{ $fields->{nonpublic_notes} } : (); >+ my @public_notes = $fields->{public_notes} ? @{ $fields->{public_notes} } : (); >+ my @locs = $fields->{locs} ? @{ $fields->{locs} } : (); >+ my @ccodes = $fields->{ccodes} ? @{ $fields->{ccodes} } : (); >+ my @notforloans = $fields->{notforloans} ? @{ $fields->{notforloans} } : (); >+ my @uris = $fields->{uris} ? @{ $fields->{uris} } : (); >+ my @copynos = $fields->{copynos} ? @{ $fields->{copynos} } : (); >+ my @itemprices = $fields->{itemprices} ? @{ $fields->{itemprices} } : (); >+ my @replacementprices = $fields->{replacementprices} ? @{ $fields->{replacementprices} } : (); >+ my @itemcallnumbers = $fields->{itemcallnumbers} ? @{ $fields->{itemcallnumbers} } : (); > my @coded_location_qualifiers = >- $client ? @{ $fields->{coded_location_qualifiers} } : ( ( $fields->{coded_location_qualifier} ) x $quantity ); >- my @barcodes = $client ? @{ $fields->{barcodes} } : ( ( $fields->{barcode} ) x $quantity ); >- my @enumchrons = $client ? @{ $fields->{enumchrons} } : ( ( $fields->{enumchron} ) x $quantity ); >- my $c_quantity = $client ? $fields->{c_quantity} : $fields->{c_quantity}; >- my $c_budget_id = $client ? $fields->{c_budget_id} : $fields->{c_budget_id}; >- my $c_discount = $client ? $fields->{c_discount} : $fields->{c_discount}; >- my $c_sort1 = $client ? $fields->{c_sort1} : $fields->{c_sort1}; >- my $c_sort2 = $client ? $fields->{c_sort2} : $fields->{c_sort2}; >- my $c_replacement_price = $client ? $fields->{c_replacement_price} : $fields->{c_replacement_price}; >- my $c_price = $client ? $fields->{c_price} : $fields->{c_price}; >+ $fields->{coded_location_qualifiers} ? @{ $fields->{coded_location_qualifiers} } : (); >+ my @barcodes = $fields->{barcodes} ? @{ $fields->{barcodes} } : (); >+ my @enumchrons = $fields->{enumchrons} ? @{ $fields->{enumchrons} } : (); >+ my @budget_codes = $fields->{budget_codes} ? @{ $fields->{budget_codes} } : (); >+ my $c_quantity = $fields->{c_quantity}; >+ my $c_budget_id = $fields->{c_budget_id}; >+ my $c_discount = $fields->{c_discount}; >+ my $c_sort1 = $fields->{c_sort1}; >+ my $c_sort2 = $fields->{c_sort2}; >+ my $c_replacement_price = $fields->{c_replacement_price}; >+ my $c_price = $fields->{c_price}; > > # If using the cronjob, we want to default to the account budget if not mapped on the record >- my $item_budget_id; >- if ( !$client && ( $fields->{budget_code} || $fields->{c_budget_code} ) ) { >- my $budget_code = $fields->{budget_code} || $fields->{c_budget_code}; >- my $item_budget = GetBudgetByCode($budget_code); >- if ($item_budget) { >- $item_budget_id = $item_budget->{budget_id}; >- } else { >- $item_budget_id = $budget_id; >+ if ( !$client && ( !@budget_codes || scalar(@budget_codes) == 0 ) ) { >+ for ( 1 .. $quantity ) { >+ my $item_budget = GetBudgetByCode($c_budget_id); >+ if ($item_budget) { >+ push( @budget_codes, $item_budget ); >+ } else { >+ push( @budget_codes, $budget_id ); >+ } > } >- } else { >- $item_budget_id = $budget_id; > } >- my @budget_codes = $client ? @{ $fields->{budget_codes} } : ($item_budget_id); >- my $loop_limit = $client ? scalar(@homebranches) : $quantity; >+ my $loop_limit = $quantity; > > my $order_line_fields = { > biblionumber => $biblionumber, >@@ -959,4 +1148,103 @@ sub _format_price_to_CurrencyFormat_syspref { > return $price; > } > >+=head3 _create_item_fields_from_syspref >+ >+Takes the two sysprefs and returns the item fields required to process and create orderlines >+ >+my $item_fields = _create_item_fields_from_syspref( >+ { >+ marc_fields_to_order => $marc_fields_to_order, >+ marc_item_fields_to_order => $marc_item_fields_to_order >+ } >+); >+ >+=cut >+ >+sub _create_item_fields_from_syspref { >+ my ($args) = @_; >+ >+ my $marc_item_fields_to_order = $args->{marc_item_fields_to_order}; >+ my $marc_fields_to_order = $args->{marc_fields_to_order}; >+ my $budget_id = $args->{budget_id}; >+ >+ my @homebranches = (); >+ my @holdingbranches = (); >+ my @itypes = (); >+ my @nonpublic_notes = (); >+ my @public_notes = (); >+ my @locs = (); >+ my @ccodes = (); >+ my @notforloans = (); >+ my @uris = (); >+ my @copynos = (); >+ my @budget_codes = (); >+ my @itemprices = (); >+ my @replacementprices = (); >+ my @itemcallnumbers = (); >+ >+ foreach my $infoset (@$marc_item_fields_to_order) { >+ my $quantity = $infoset->{quantity} || 1; >+ for ( my $i = 0 ; $i < $quantity ; $i++ ) { >+ my $budget_code; >+ if ( !$infoset->{budget_code} ) { >+ if ( $marc_fields_to_order->{budget_code} ) { >+ $budget_code = $marc_fields_to_order->{budget_code}; >+ } >+ } else { >+ $budget_code = $infoset->{budget_code}; >+ } >+ >+ my $item_budget_id; >+ my $item_budget = GetBudgetByCode($budget_code); >+ if ($item_budget) { >+ $item_budget_id = $item_budget->{budget_id}; >+ } else { >+ $item_budget_id = $budget_id; >+ } >+ >+ push @homebranches, $infoset->{homebranch}; >+ push @holdingbranches, $infoset->{holdingbranch}; >+ push @itypes, $infoset->{itype}; >+ push @nonpublic_notes, $infoset->{nonpublic_note}; >+ push @public_notes, $infoset->{public_note}; >+ push @locs, $infoset->{loc}; >+ push @ccodes, $infoset->{ccode}; >+ push @notforloans, $infoset->{notforloan}; >+ push @uris, $infoset->{uri}; >+ push @copynos, $infoset->{copyno}; >+ push @budget_codes, $item_budget_id; >+ push @itemprices, $infoset->{itemprice}; >+ push @replacementprices, $infoset->{replacementprice}; >+ push @itemcallnumbers, $infoset->{itemcallnumber}; >+ } >+ } >+ >+ my $item_fields = { >+ quantity => scalar(@homebranches), >+ homebranches => \@homebranches, >+ holdingbranches => \@holdingbranches, >+ itypes => \@itypes, >+ nonpublic_notes => \@nonpublic_notes, >+ public_notes => \@public_notes, >+ locs => \@locs, >+ ccodes => \@ccodes, >+ notforloans => \@notforloans, >+ uris => \@uris, >+ copynos => \@copynos, >+ budget_codes => \@budget_codes, >+ itemprices => \@itemprices, >+ replacementprices => \@replacementprices, >+ itemcallnumbers => \@itemcallnumbers, >+ c_quantity => $marc_fields_to_order->{quantity}, >+ c_budget_code => $marc_fields_to_order->{budget_code}, >+ c_price => $marc_fields_to_order->{price}, >+ c_discount => $marc_fields_to_order->{discount}, >+ c_sort1 => $marc_fields_to_order->{sort1}, >+ c_sort2 => $marc_fields_to_order->{sort2}, >+ }; >+ >+ return $item_fields; >+} >+ > 1; >diff --git a/misc/cronjobs/marc_ordering_process.pl b/misc/cronjobs/marc_ordering_process.pl >new file mode 100755 >index 00000000000..1491fa440d4 >--- /dev/null >+++ b/misc/cronjobs/marc_ordering_process.pl >@@ -0,0 +1,131 @@ >+ >+#!/usr/bin/perl >+ >+# This file is part of Koha. >+# >+# Copyright (C) 2023 PTFS Europe Ltd >+# >+# Koha is free software; you can redistribute it and/or modify it >+# under the terms of the GNU General Public License as published by >+# the Free Software Foundation; either version 3 of the License, or >+# (at your option) any later version. >+# >+# Koha is distributed in the hope that it will be useful, but >+# WITHOUT ANY WARRANTY; without even the implied warranty of >+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >+# GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License >+# along with Koha; if not, see <http://www.gnu.org/licenses>. >+ >+=head1 NAME >+ >+marc_ordering_process.pl - cron script to retrieve marc files and create order lines >+ >+=head1 SYNOPSIS >+ >+./marc_ordering_process.pl [-c|--confirm] [-v|--verbose] >+ >+or, in crontab: >+# Once every day >+0 3 * * * marc_ordering_process.pl -c >+ >+=head1 DESCRIPTION >+ >+This script searches for new marc files in an SFTP location >+If there are new files, it stages those files, adds bilbios/items and creates order lines >+ >+=head1 OPTIONS >+ >+=over >+ >+=item B<-v|--verbose> >+ >+Print report to standard out. >+ >+=item B<-c|--confirm> >+ >+Without this parameter no changes will be made >+ >+=back >+ >+=cut >+ >+use Modern::Perl; >+use Pod::Usage qw( pod2usage ); >+use Getopt::Long qw( GetOptions ); >+use File::Copy qw( copy move ); >+ >+use Koha::Script -cron; >+use Koha::MarcOrder; >+use Koha::MarcOrderAccounts; >+ >+use C4::Log qw( cronlogaction ); >+ >+my $command_line_options = join( " ", @ARGV ); >+ >+my ( $help, $verbose, $confirm ); >+GetOptions( >+ 'h|help' => \$help, >+ 'v|verbose' => \$verbose, >+ 'c|confirm' => \$confirm, >+) || pod2usage(1); >+ >+pod2usage(0) if $help; >+ >+cronlogaction( { info => $command_line_options } ); >+ >+$verbose = 1 unless $verbose or $confirm; >+print "Test run only\n" unless $confirm; >+ >+print "Fetching marc ordering accounts\n" if $verbose; >+my @accounts = Koha::MarcOrderAccounts->search( >+ {}, >+ { join => [ 'vendor', 'budget' ] } >+)->as_list; >+ >+if ( scalar(@accounts) == 0 ) { >+ print "No accounts found - you must create a Marc order account for this cronjob to run\n" if $verbose; >+} >+ >+foreach my $acct (@accounts) { >+ if ($verbose) { >+ say sprintf "Starting marc ordering process for %s", $acct->vendor->name; >+ say sprintf "Looking for new files in %s", $acct->download_directory; >+ } >+ >+ my $working_dir = $acct->download_directory; >+ opendir my $dir, $working_dir or die "Can't open filepath"; >+ my @files = grep { /\.(mrc|marcxml|mrk)/i } readdir $dir; >+ closedir $dir; >+ >+ foreach my $filename (@files) { >+ my $full_path = "$working_dir/$filename"; >+ my $args = { >+ filename => $filename, >+ filepath => $full_path, >+ profile => $acct, >+ agent => 'cron' >+ }; >+ if ( $acct->match_field && $acct->match_value ) { >+ my $file_match = Koha::MarcOrder->match_file_to_account($args); >+ next if !$file_match; >+ } >+ if ($confirm) { >+ say sprintf "Creating order lines from file %s", $filename if $verbose; >+ my $result = Koha::MarcOrder->create_order_lines_from_file($args); >+ if ( $result->{success} ) { >+ $files_processed++; >+ say sprintf "Successfully processed file: %s", $filename if $verbose; >+ unlink $full_path; >+ } else { >+ say sprintf "Error processing file: %s", $filename if $verbose; >+ say sprintf "Error message: %s", $result->{error} if $verbose; >+ } >+ } >+ } >+ print "All files completed\n"; >+ print "Moving to next account\n\n"; >+} >+print "Process complete\n"; >+cronlogaction( { action => 'End', info => "COMPLETED" } ); >-- >2.39.3 (Apple Git-146)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 34355
:
154705
|
154706
|
154707
|
154708
|
154709
|
154710
|
157092
|
157093
|
157094
|
157095
|
157096
|
157097
|
157098
|
157099
|
157100
|
160858
|
160859
|
160860
|
160861
|
160862
|
160863
|
160864
|
160865
|
160866
|
160867
|
160868
|
160869
|
160870
|
160871
|
160872
|
160873
|
160874
|
160875
|
169896
|
169897
|
169898
|
169899
|
169900
|
169901
|
169902
|
169903
|
169904
|
170395
|
170401
|
170402
|
170403
|
170404
|
170405
|
170406
|
170407
|
170408
|
170409
|
173054
|
173055
|
173056
|
173057
|
173058
|
173059
|
173060
|
173061
|
173062
|
173063
|
173064
|
173065
|
173066
|
173709
|
173805
|
173806
|
173809
|
173824
|
173825
|
173993
|
173994
|
173995
|
173996
|
173997
|
173998
|
173999
|
174000
|
174001
|
174002
|
174003
|
174004
|
174005
|
174006
|
174007
|
174008
|
174009
|
174010
|
174362
|
174363
|
174364
|
174365
|
174366
|
174367
|
174368
|
174369
|
174370
|
174371
|
174372
|
174373
|
174374
|
174375
|
174376
|
174377
|
174378
|
174379
|
174380
|
174382
|
174383