use Getopt::Long;
use Pod::Usage;
+use Koha::Script;
use C4::Auth;
use C4::Context;
-use C4::Csv;
use C4::Record;
use Koha::Biblioitems;
use Koha::Database;
+use Koha::CsvProfiles;
use Koha::Exporter::Record;
use Koha::DateUtils qw( dt_from_string output_pref );
-my ( $output_format, $timestamp, $dont_export_items, $csv_profile_id, $deleted_barcodes, $clean, $filename, $record_type, $id_list_file, $starting_authid, $ending_authid, $authtype, $starting_biblionumber, $ending_biblionumber, $itemtype, $starting_callnumber, $ending_callnumber, $start_accession, $end_accession, $help );
+my (
+ $output_format,
+ $timestamp,
+ $dont_export_items,
+ $csv_profile_id,
+ $deleted_barcodes,
+ $clean,
+ $filename,
+ $record_type,
+ $id_list_file,
+ $starting_authid,
+ $ending_authid,
+ $authtype,
+ $starting_biblionumber,
+ $ending_biblionumber,
+ $itemtype,
+ $starting_callnumber,
+ $ending_callnumber,
+ $start_accession,
+ $end_accession,
+ $marc_conditions,
+ $help
+);
+
GetOptions(
'format=s' => \$output_format,
'date=s' => \$timestamp,
'ending_callnumber=s' => \$ending_callnumber,
'start_accession=s' => \$start_accession,
'end_accession=s' => \$end_accession,
+ 'marc_conditions=s' => \$marc_conditions,
'h|help|?' => \$help
) || pod2usage(1);
pod2usage(q|CSV output is only available for biblio records|);
}
+if ( $output_format eq 'csv' and not $csv_profile_id ) {
+ pod2usage(q|Define a csv profile to export in CSV|);
+}
if ( $timestamp and $record_type ne 'bibs' ) {
pod2usage(q|--timestamp can only be used with biblios|);
$start_accession = dt_from_string( $start_accession ) if $start_accession;
$end_accession = dt_from_string( $end_accession ) if $end_accession;
+# Parse marc conditions
+my @marc_conditions;
+if ($marc_conditions) {
+ foreach my $condition (split(/,\s*/, $marc_conditions)) {
+ if ($condition =~ /^(\d{3})([\w\d]?)(=|(?:!=)|>|<)([^,]+)$/) {
+ push @marc_conditions, [$1, $2, $3, $4];
+ }
+ elsif ($condition =~ /^(exists|not_exists)\((\d{3})([\w\d]?)\)$/) {
+ push @marc_conditions, [$2, $3, $1 eq 'exists' ? '?' : '!?'];
+ }
+ else {
+ die("Invalid condititon: $condition");
+ }
+ }
+}
+
my $dbh = C4::Context->dbh;
# Redirect stdout
my @record_ids;
-$timestamp = ($timestamp) ? output_pref({ dt => dt_from_string($timestamp), dateformat => 'iso', dateonly => 1, }): '';
+$timestamp = ($timestamp) ? output_pref({ dt => dt_from_string($timestamp), dateformat => 'iso', dateonly => 0, }): '';
if ( $record_type eq 'bibs' ) {
if ( $timestamp ) {
- push @record_ids, $_->{biblionumber} for @{
- $dbh->selectall_arrayref(q| (
- SELECT biblionumber
- FROM biblioitems
- LEFT JOIN items USING(biblionumber)
- WHERE biblioitems.timestamp >= ?
- OR items.timestamp >= ?
- ) UNION (
- SELECT biblionumber
- FROM biblioitems
- LEFT JOIN deleteditems USING(biblionumber)
- WHERE biblioitems.timestamp >= ?
- OR deleteditems.timestamp >= ?
- ) |, { Slice => {} }, ( $timestamp ) x 4 );
- };
+ if (!$dont_export_items) {
+ push @record_ids, $_->{biblionumber} for @{
+ $dbh->selectall_arrayref(q| (
+ SELECT biblio_metadata.biblionumber
+ FROM biblio_metadata
+ LEFT JOIN items USING(biblionumber)
+ WHERE biblio_metadata.timestamp >= ?
+ OR items.timestamp >= ?
+ ) UNION (
+ SELECT biblio_metadata.biblionumber
+ FROM biblio_metadata
+ LEFT JOIN deleteditems USING(biblionumber)
+ WHERE biblio_metadata.timestamp >= ?
+ OR deleteditems.timestamp >= ?
+ ) |, { Slice => {} }, ( $timestamp ) x 4 );
+ };
+ } else {
+ push @record_ids, $_->{biblionumber} for @{
+ $dbh->selectall_arrayref(q| (
+ SELECT biblio_metadata.biblionumber
+ FROM biblio_metadata
+ WHERE biblio_metadata.timestamp >= ?
+ ) |, { Slice => {} }, $timestamp );
+ };
+ }
} else {
my $conditions = {
( $starting_biblionumber or $ending_biblionumber )
?
C4::Context->preference('item-level_itypes')
? ( 'items.itype' => $itemtype )
- : ( 'biblioitems.itemtype' => $itemtype )
+ : ( 'me.itemtype' => $itemtype )
: ()
),
if ($deleted_barcodes) {
for my $record_id ( @record_ids ) {
- my $q = q|
- |;
- my $barcode = $dbh->selectall_arrayref(q| (
+ my $barcode = $dbh->selectall_arrayref(q|
SELECT DISTINCT barcode
FROM deleteditems
WHERE deleteditems.biblionumber = ?
|, { Slice => {} }, $record_id );
- say $_->{barcode} for @$barcode
+ say $_->{barcode} for @$barcode;
}
}
else {
Koha::Exporter::Record::export(
{ record_type => $record_type,
record_ids => \@record_ids,
+ record_conditions => @marc_conditions ? \@marc_conditions : undef,
format => $output_format,
- csv_profile_id => ( $csv_profile_id || GetCsvProfileId( C4::Context->preference('ExportWithCsvProfile') ) || undef ),
+ csv_profile_id => $csv_profile_id,
export_items => (not $dont_export_items),
clean => $clean || 0,
}
=head1 SYNOPSIS
-export_records.pl [-h|--help] [--format=format] [--date=date] [--record-type=TYPE] [--dont_export_items] [--deleted_barcodes] [--clean] [--id_list_file=PATH] --filename=outputfile
+export_records.pl [-h|--help] [--format=format] [--date=datetime] [--record-type=TYPE] [--dont_export_items] [--deleted_barcodes] [--clean] [--id_list_file=PATH] --filename=outputfile
=head1 OPTIONS
=item B<--date>
- --date=DATE DATE should be entered as the 'dateformat' syspref is
- set (dd/mm/yyyy for metric, yyyy-mm-dd for iso,
- mm/dd/yyyy for us) records exported are the ones that
- have been modified since DATE.
+ --date=DATETIME DATETIME should be entered as the 'dateformat' syspref is
+ set (dd/mm/yyyy[ hh:mm:ss] for metric, yyyy-mm-dd[ hh:mm:ss] for iso,
+ mm/dd/yyyy[ hh:mm:ss] for us) records exported are the ones that
+ have been modified since DATETIME.
=item B<--record-type>
=item B<--csv_profile_id>
--csv_profile_id=ID Generate a CSV file with the given CSV profile id (see tools/csv-profiles.pl)
- Unless provided, the one defined in the system preference 'ExportWithCsvProfile' will be used.
This can only be used to export biblio records.
=item B<--deleted_barcodes>
--end_accession=DATE Export biblio with an item accessionned after DATE
+=item B<--marc_conditions>
+
+ --marc_conditions=CONDITIONS Only include biblios with MARC data matching CONDITIONS.
+ CONDITIONS is on the format: <marc_target><binary_operator><value>,
+ or <unary_operation>(<marc_target>).
+ with multiple conditions separated by commas (,).
+ For example: --marc_conditions="035a!=(EXAMPLE)123,041a=swe".
+ Multiple conditions are all required to match.
+ If <marc_target> has multiple values all values
+ are also required to match.
+ Valid operators are: = (equal to), != (not equal to),
+ > (great than) and < (less than).
+
+ Two unary operations are also supported:
+ exists(<marc_target>) and not_exists(<marc_target>).
+ For example: --marc_conditions="exists(035a)".
+
+ "exists(<marc_target)" will include marc records where
+ <marc_target> exists regardless of target value, and
+ "exists(<marc_target>)" will include marc records where
+ no <marc_target> exists.
+
=back
=head1 AUTHOR