4 # This file is part of Koha.
6 # Koha is free software; you can redistribute it and/or modify it
7 # under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # Koha is distributed in the hope that it will be useful, but
12 # WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with Koha; if not, see <http://www.gnu.org/licenses>.
21 use List
::MoreUtils
qw(uniq);
30 use Koha
::Biblioitems
;
32 use Koha
::CsvProfiles
;
33 use Koha
::Exporter
::Record
;
34 use Koha
::DateUtils
qw( dt_from_string output_pref );
49 $starting_biblionumber,
61 'format=s' => \
$output_format,
62 'date=s' => \
$timestamp,
63 'dont_export_items' => \
$dont_export_items,
64 'csv_profile_id=s' => \
$csv_profile_id,
65 'deleted_barcodes' => \
$deleted_barcodes,
67 'filename=s' => \
$filename,
68 'record-type=s' => \
$record_type,
69 'id_list_file=s' => \
$id_list_file,
70 'starting_authid=s' => \
$starting_authid,
71 'ending_authid=s' => \
$ending_authid,
72 'authtype=s' => \
$authtype,
73 'starting_biblionumber=s' => \
$starting_biblionumber,
74 'ending_biblionumber=s' => \
$ending_biblionumber,
75 'itemtype=s' => \
$itemtype,
76 'starting_callnumber=s' => \
$starting_callnumber,
77 'ending_callnumber=s' => \
$ending_callnumber,
78 'start_accession=s' => \
$start_accession,
79 'end_accession=s' => \
$end_accession,
80 'marc_conditions=s' => \
$marc_conditions,
88 $filename ||= 'koha.mrc';
89 $output_format ||= 'iso2709';
90 $record_type ||= 'bibs';
92 # Retrocompatibility for the format parameter
93 $output_format = 'iso2709' if $output_format eq 'marc';
95 if ( $output_format eq 'csv' and $record_type eq 'auths' ) {
96 pod2usage
(q
|CSV output is only available
for biblio records
|);
99 if ( $output_format eq 'csv' and not $csv_profile_id ) {
100 pod2usage
(q
|Define a csv profile to export
in CSV
|);
103 if ( $timestamp and $record_type ne 'bibs' ) {
104 pod2usage
(q
|--timestamp can only be used with biblios
|);
107 if ( $record_type ne 'bibs' and $record_type ne 'auths' ) {
108 pod2usage
(q
|--record_type is
not valid
|);
111 if ( $deleted_barcodes and $record_type ne 'bibs' ) {
112 pod2usage
(q
|--deleted_barcodes can only be used with biblios
|);
115 $start_accession = dt_from_string
( $start_accession ) if $start_accession;
116 $end_accession = dt_from_string
( $end_accession ) if $end_accession;
118 # Parse marc conditions
120 if ($marc_conditions) {
121 foreach my $condition (split(/,\s*/, $marc_conditions)) {
122 if ($condition =~ /^(\d{3})([\w\d]?)(=|(?:!=)|>|<)([^,]+)$/) {
123 push @marc_conditions, [$1, $2, $3, $4];
125 elsif ($condition =~ /^(exists|not_exists)\((\d{3})([\w\d]?)\)$/) {
126 push @marc_conditions, [$2, $3, $1 eq 'exists' ?
'?' : '!?'];
129 die("Invalid condititon: $condition");
134 my $dbh = C4
::Context
->dbh;
137 open STDOUT
, '>', $filename if $filename;
142 $timestamp = ($timestamp) ? output_pref
({ dt
=> dt_from_string
($timestamp), dateformat
=> 'iso', dateonly
=> 0, }): '';
144 if ( $record_type eq 'bibs' ) {
146 if (!$dont_export_items) {
147 push @record_ids, $_->{biblionumber
} for @
{
148 $dbh->selectall_arrayref(q
| (
149 SELECT biblio_metadata
.biblionumber
151 LEFT JOIN items USING
(biblionumber
)
152 WHERE biblio_metadata
.timestamp
>= ?
153 OR items
.timestamp
>= ?
155 SELECT biblio_metadata
.biblionumber
157 LEFT JOIN deleteditems USING
(biblionumber
)
158 WHERE biblio_metadata
.timestamp
>= ?
159 OR deleteditems
.timestamp
>= ?
160 ) |, { Slice
=> {} }, ( $timestamp ) x
4 );
163 push @record_ids, $_->{biblionumber
} for @
{
164 $dbh->selectall_arrayref(q
| (
165 SELECT biblio_metadata
.biblionumber
167 WHERE biblio_metadata
.timestamp
>= ?
168 ) |, { Slice
=> {} }, $timestamp );
173 ( $starting_biblionumber or $ending_biblionumber )
175 "me.biblionumber" => {
176 ( $starting_biblionumber ?
( '>=' => $starting_biblionumber ) : () ),
177 ( $ending_biblionumber ?
( '<=' => $ending_biblionumber ) : () ),
181 ( $starting_callnumber or $ending_callnumber )
184 ( $starting_callnumber ?
( '>=' => $starting_callnumber ) : () ),
185 ( $ending_callnumber ?
( '<=' => $ending_callnumber ) : () ),
189 ( $start_accession or $end_accession )
192 ( $start_accession ?
( '>=' => $start_accession ) : () ),
193 ( $end_accession ?
( '<=' => $end_accession ) : () ),
199 C4
::Context
->preference('item-level_itypes')
200 ?
( 'items.itype' => $itemtype )
201 : ( 'me.itemtype' => $itemtype )
206 my $biblioitems = Koha
::Biblioitems
->search( $conditions, { join => 'items' } );
207 while ( my $biblioitem = $biblioitems->next ) {
208 push @record_ids, $biblioitem->biblionumber;
212 elsif ( $record_type eq 'auths' ) {
214 ( $starting_authid or $ending_authid )
217 ( $starting_authid ?
( '>=' => $starting_authid ) : () ),
218 ( $ending_authid ?
( '<=' => $ending_authid ) : () ),
222 ( $authtype ?
( authtypecode
=> $authtype ) : () ),
224 # Koha::MetadataRecord::Authority is not a Koha::Object...
225 my $authorities = Koha
::Database
->new->schema->resultset('AuthHeader')->search( $conditions );
226 @record_ids = map { $_->authid } $authorities->all;
229 @record_ids = uniq
@record_ids;
230 if ( @record_ids and $id_list_file ) {
231 open my $fh, '<', $id_list_file or die "Cannot open file $id_list_file ($!)";
232 my @filter_record_ids = <$fh>;
233 @filter_record_ids = map { my $id = $_; $id =~ s/[\r\n]*$//; $id } @filter_record_ids;
235 my %record_ids = map { $_ => 1 } @record_ids;
236 @record_ids = grep $record_ids{$_}, @filter_record_ids;
239 if ($deleted_barcodes) {
240 for my $record_id ( @record_ids ) {
241 my $barcode = $dbh->selectall_arrayref(q
|
242 SELECT DISTINCT barcode
244 WHERE deleteditems
.biblionumber
= ?
245 AND barcode IS NOT NULL AND barcode
!= ''
246 |, { Slice
=> {} }, $record_id );
247 say $_->{barcode
} for @
$barcode;
251 Koha
::Exporter
::Record
::export
(
252 { record_type
=> $record_type,
253 record_ids
=> \
@record_ids,
254 record_conditions
=> @marc_conditions ? \
@marc_conditions : undef,
255 format
=> $output_format,
256 csv_profile_id
=> $csv_profile_id,
257 export_items
=> (not $dont_export_items),
258 clean
=> $clean || 0,
267 export records - This script exports record (biblios or authorities)
271 export_records.pl [-h|--help] [--format=format] [--date=datetime] [--record-type=TYPE] [--dont_export_items] [--deleted_barcodes] [--clean] [--id_list_file=PATH] --filename=outputfile
279 Print a brief help message.
283 --format=FORMAT FORMAT is either 'xml', 'csv' (biblio records only) or 'marc' (default).
287 --date=DATETIME DATETIME should be entered as the 'dateformat' syspref is
288 set (dd/mm/yyyy[ hh:mm:ss] for metric, yyyy-mm-dd[ hh:mm:ss] for iso,
289 mm/dd/yyyy[ hh:mm:ss] for us) records exported are the ones that
290 have been modified since DATETIME.
292 =item B<--record-type>
294 --record-type=TYPE TYPE is 'bibs' or 'auths'.
296 =item B<--dont_export_items>
298 --dont_export_items If enabled, the item infos won't be exported.
300 =item B<--csv_profile_id>
302 --csv_profile_id=ID Generate a CSV file with the given CSV profile id (see tools/csv-profiles.pl)
303 This can only be used to export biblio records.
305 =item B<--deleted_barcodes>
307 --deleted_barcodes If used, a list of barcodes of items deleted since DATE
308 is produced (or from all deleted items if no date is
309 specified). Used only if TYPE is 'bibs'.
313 --clean removes NSE/NSB.
315 =item B<--id_list_file>
317 --id_list_file=PATH PATH is a path to a file containing a list of
318 IDs (biblionumber or authid) with one ID per line.
319 This list works as a filter; it is compatible with
320 other parameters for selecting records.
324 --filename=FILENAME FILENAME used to export the data.
326 =item B<--starting_authid>
328 --starting_authid=ID Export authorities with authid >= ID
330 =item B<--ending_authid>
332 --ending_authid=ID Export authorities with authid <= ID
336 --authtype=AUTHTYPE Export authorities from the given AUTHTYPE
338 =item B<--starting_biblionumber>
340 --starting_biblionumber=ID Export biblio with biblionumber >= ID
342 =item B<--ending_biblionumber>
344 --ending_biblionumber=ID Export biblio with biblionumber <= ID
348 --itemtype=ITEMTYPE Export biblio from the given ITEMTYPE
350 =item B<--starting_callnumber>
352 --starting_callnumber=CALLNUMBER Export biblio with callnumber >=CALLNUMBER
354 =item B<--ending_callnumber>
356 --ending_callnumber=CALLNUMBER Export biblio with callnumber <=CALLNUMBER
358 =item B<--start_accession>
360 --starting_accession=DATE Export biblio with an item accessionned after DATE
362 =item B<--end_accession>
364 --end_accession=DATE Export biblio with an item accessionned after DATE
366 =item B<--marc_conditions>
368 --marc_conditions=CONDITIONS Only include biblios with MARC data matching CONDITIONS.
369 CONDITIONS is on the format: <marc_target><binary_operator><value>,
370 or <unary_operation>(<marc_target>).
371 with multiple conditions separated by commas (,).
372 For example: --marc_conditions="035a!=(EXAMPLE)123,041a=swe".
373 Multiple conditions are all required to match.
374 If <marc_target> has multiple values all values
375 are also required to match.
376 Valid operators are: = (equal to), != (not equal to),
377 > (great than) and < (less than).
379 Two unary operations are also supported:
380 exists(<marc_target>) and not_exists(<marc_target>).
381 For example: --marc_conditions="exists(035a)".
383 "exists(<marc_target)" will include marc records where
384 <marc_target> exists regardless of target value, and
385 "exists(<marc_target>)" will include marc records where
386 no <marc_target> exists.
392 Koha Development Team
400 This file is part of Koha.
402 # Koha is free software; you can redistribute it and/or modify it
403 # under the terms of the GNU General Public License as published by
404 # the Free Software Foundation; either version 3 of the License, or
405 # (at your option) any later version.
407 # Koha is distributed in the hope that it will be useful, but
408 # WITHOUT ANY WARRANTY; without even the implied warranty of
409 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
410 # GNU General Public License for more details.
412 # You should have received a copy of the GNU General Public License
413 # along with Koha; if not, see <http://www.gnu.org/licenses>.