1 package C4
::Suggestions
;
3 # Copyright 2000-2002 Katipo Communications
4 # Parts Copyright Biblibre 2011
6 # This file is part of Koha.
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.
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.
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>.
23 #use warnings; FIXME - Bug 2505
30 use C4
::Biblio
qw( GetMarcFromKohaField );
32 use Koha
::Suggestions
;
34 use List
::MoreUtils
qw(any);
35 use base
qw(Exporter);
38 ConnectSuggestionAndBiblio
43 GetSuggestionFromBiblionumber
44 GetSuggestionInfoFromBiblionumber
50 DelSuggestionsOlderThan
51 GetUnprocessedSuggestions
52 MarcRecordFromNewSuggestion
57 C4::Suggestions - Some useful functions for dealings with aqorders.
65 The functions in this module deal with the aqorders in OPAC and in librarian interface
67 A suggestion is done in the OPAC. It has the status "ASKED"
69 When a librarian manages the suggestion, they can set the status to "REJECTED" or "ACCEPTED".
71 When the book is ordered, the suggestion status becomes "ORDERED"
73 When a book is ordered and arrived in the library, the status becomes "AVAILABLE"
75 All aqorders of a borrower can be seen by the borrower itself.
76 Suggestions done by other borrowers can be seen when not "AVAILABLE"
80 =head2 SearchSuggestion
82 (\@array) = &SearchSuggestion($suggestionhashref_to_search)
84 searches for a suggestion
87 C<\@array> : the aqorders found. Array of hash.
88 Note the status is stored twice :
90 * as parameter ( for example ASKED => 1, or REJECTED => 1) . This is for template & translation purposes.
94 sub SearchSuggestion
{
95 my ($suggestion) = @_;
96 my $dbh = C4
::Context
->dbh;
100 SELECT suggestions.*,
101 U1.branchcode AS branchcodesuggestedby,
102 B1.branchname AS branchnamesuggestedby,
103 U1.surname AS surnamesuggestedby,
104 U1.firstname AS firstnamesuggestedby,
105 U1.cardnumber AS cardnumbersuggestedby,
106 U1.email AS emailsuggestedby,
107 U1.borrowernumber AS borrnumsuggestedby,
108 U1.categorycode AS categorycodesuggestedby,
109 C1.description AS categorydescriptionsuggestedby,
110 U2.surname AS surnamemanagedby,
111 U2.firstname AS firstnamemanagedby,
112 B2.branchname AS branchnamesuggestedby,
113 U2.email AS emailmanagedby,
114 U2.branchcode AS branchcodemanagedby,
115 U2.borrowernumber AS borrnummanagedby,
116 BU.budget_name AS budget_name
118 LEFT JOIN borrowers AS U1 ON suggestedby=U1.borrowernumber
119 LEFT JOIN branches AS B1 ON B1.branchcode=U1.branchcode
120 LEFT JOIN categories AS C1 ON C1.categorycode=U1.categorycode
121 LEFT JOIN borrowers AS U2 ON managedby=U2.borrowernumber
122 LEFT JOIN branches AS B2 ON B2.branchcode=U2.branchcode
123 LEFT JOIN categories AS C2 ON C2.categorycode=U2.categorycode
124 LEFT JOIN aqbudgets AS BU ON budgetid=BU.budget_id
129 # filter on biblio informations
131 qw( title author isbn publishercode copyrightdate collectiontitle ))
133 if ( $suggestion->{$field} ) {
134 push @sql_params, '%' . $suggestion->{$field} . '%';
135 push @query, qq{ AND suggestions
.$field LIKE ?
};
139 # filter on user branch
140 if ( C4
::Context
->preference('IndependentBranches')
141 && !C4
::Context
->IsSuperLibrarian() )
143 # If IndependentBranches is set and the logged in user is not superlibrarian
144 # Then we want to filter by the user's library (i.e. cannot see suggestions from other libraries)
145 my $userenv = C4
::Context
->userenv;
148 push @sql_params, $$userenv{branch
};
150 AND (suggestions.branchcode=? OR suggestions.branchcode='')
155 elsif (defined $suggestion->{branchcode
}
156 && $suggestion->{branchcode
}
157 && $suggestion->{branchcode
} ne '__ANY__' )
159 # If IndependentBranches is not set OR the logged in user is not superlibrarian
160 # AND the branchcode filter is passed and not '__ANY__'
161 # Then we want to filter using this parameter
162 push @sql_params, $suggestion->{branchcode
};
163 push @query, qq{ AND suggestions
.branchcode
=?
};
166 # filter on nillable fields
168 qw( STATUS itemtype suggestedby managedby acceptedby budgetid biblionumber )
171 if ( exists $suggestion->{$field}
172 and defined $suggestion->{$field}
173 and $suggestion->{$field} ne '__ANY__'
175 $suggestion->{$field} ne q
||
176 or $field eq 'STATUS'
179 if ( $suggestion->{$field} eq '__NONE__' ) {
180 push @query, qq{ AND
(suggestions
.$field = '' OR suggestions
.$field IS NULL
) };
183 push @sql_params, $suggestion->{$field};
184 push @query, qq{ AND suggestions
.$field = ?
};
189 # filter on date fields
190 foreach my $field (qw( suggesteddate manageddate accepteddate )) {
191 my $from = $field . "_from";
192 my $to = $field . "_to";
194 $from_dt = eval { dt_from_string
( $suggestion->{$from} ) } if ( $suggestion->{$from} );
195 my $from_sql = '0000-00-00';
196 $from_sql = output_pref
({ dt
=> $from_dt, dateformat
=> 'iso', dateonly
=> 1 })
198 $debug && warn "SQL for start date ($field): $from_sql";
199 if ( $suggestion->{$from} || $suggestion->{$to} ) {
200 push @query, qq{ AND suggestions
.$field BETWEEN ? AND ?
};
201 push @sql_params, $from_sql;
203 output_pref
({ dt
=> dt_from_string
( $suggestion->{$to} ), dateformat
=> 'iso', dateonly
=> 1 }) || output_pref
({ dt
=> dt_from_string
, dateformat
=> 'iso', dateonly
=> 1 });
207 $debug && warn "@query";
208 my $sth = $dbh->prepare("@query");
209 $sth->execute(@sql_params);
212 # add status as field
213 while ( my $data = $sth->fetchrow_hashref ) {
214 $data->{ $data->{STATUS
} } = 1;
215 push( @results, $data );
218 return ( \
@results );
223 \%sth = &GetSuggestion($suggestionid)
225 this function get the detail of the suggestion $suggestionid (input arg)
228 the result of the SQL query as a hash : $sth->fetchrow_hashref.
233 my ($suggestionid) = @_;
234 my $dbh = C4
::Context
->dbh;
240 my $sth = $dbh->prepare($query);
241 $sth->execute($suggestionid);
242 return ( $sth->fetchrow_hashref );
245 =head2 GetSuggestionFromBiblionumber
247 $ordernumber = &GetSuggestionFromBiblionumber($biblionumber)
249 Get a suggestion from it's biblionumber.
252 the id of the suggestion which is related to the biblionumber given on input args.
256 sub GetSuggestionFromBiblionumber
{
257 my ($biblionumber) = @_;
261 WHERE biblionumber=? LIMIT 1
263 my $dbh = C4
::Context
->dbh;
264 my $sth = $dbh->prepare($query);
265 $sth->execute($biblionumber);
266 my ($suggestionid) = $sth->fetchrow;
267 return $suggestionid;
270 =head2 GetSuggestionInfoFromBiblionumber
272 Get a suggestion and borrower's informations from it's biblionumber.
275 all informations (suggestion and borrower) of the suggestion which is related to the biblionumber given.
279 sub GetSuggestionInfoFromBiblionumber
{
280 my ($biblionumber) = @_;
282 SELECT suggestions.*,
283 U1.surname AS surnamesuggestedby,
284 U1.firstname AS firstnamesuggestedby,
285 U1.borrowernumber AS borrnumsuggestedby
287 LEFT JOIN borrowers AS U1 ON suggestedby=U1.borrowernumber
291 my $dbh = C4
::Context
->dbh;
292 my $sth = $dbh->prepare($query);
293 $sth->execute($biblionumber);
294 return $sth->fetchrow_hashref;
297 =head2 GetSuggestionInfo
299 Get a suggestion and borrower's informations from it's suggestionid
302 all informations (suggestion and borrower) of the suggestion which is related to the suggestionid given.
306 sub GetSuggestionInfo
{
307 my ($suggestionid) = @_;
309 SELECT suggestions.*,
310 U1.surname AS surnamesuggestedby,
311 U1.firstname AS firstnamesuggestedby,
312 U1.borrowernumber AS borrnumsuggestedby
314 LEFT JOIN borrowers AS U1 ON suggestedby=U1.borrowernumber
318 my $dbh = C4
::Context
->dbh;
319 my $sth = $dbh->prepare($query);
320 $sth->execute($suggestionid);
321 return $sth->fetchrow_hashref;
324 =head2 GetSuggestionByStatus
326 $aqorders = &GetSuggestionByStatus($status,[$branchcode])
328 Get a suggestion from it's status
331 all the suggestion with C<$status>
335 sub GetSuggestionByStatus
{
337 my $branchcode = shift;
338 my $dbh = C4
::Context
->dbh;
339 my @sql_params = ($status);
341 SELECT suggestions.*,
342 U1.surname AS surnamesuggestedby,
343 U1.firstname AS firstnamesuggestedby,
344 U1.branchcode AS branchcodesuggestedby,
345 B1.branchname AS branchnamesuggestedby,
346 U1.borrowernumber AS borrnumsuggestedby,
347 U1.categorycode AS categorycodesuggestedby,
348 C1.description AS categorydescriptionsuggestedby,
349 U2.surname AS surnamemanagedby,
350 U2.firstname AS firstnamemanagedby,
351 U2.borrowernumber AS borrnummanagedby
353 LEFT JOIN borrowers AS U1 ON suggestedby=U1.borrowernumber
354 LEFT JOIN borrowers AS U2 ON managedby=U2.borrowernumber
355 LEFT JOIN categories AS C1 ON C1.categorycode=U1.categorycode
356 LEFT JOIN branches AS B1 on B1.branchcode=U1.branchcode
361 if ( C4
::Context
->preference("IndependentBranches") || $branchcode ) {
362 my $userenv = C4
::Context
->userenv;
364 unless ( C4
::Context
->IsSuperLibrarian() ) {
365 push @sql_params, $userenv->{branch
};
366 $query .= q{ AND (U1.branchcode = ? OR U1.branchcode ='') };
370 push @sql_params, $branchcode;
371 $query .= q{ AND (U1.branchcode = ? OR U1.branchcode ='') };
375 my $sth = $dbh->prepare($query);
376 $sth->execute(@sql_params);
378 $results = $sth->fetchall_arrayref( {} );
382 =head2 CountSuggestion
384 &CountSuggestion($status)
386 Count the number of aqorders with the status given on input argument.
387 the arg status can be :
391 =item * ASKED : asked by the user, not dealed by the librarian
393 =item * ACCEPTED : accepted by the librarian, but not yet ordered
395 =item * REJECTED : rejected by the librarian (definitive status)
397 =item * ORDERED : ordered by the librarian (acquisition module)
402 the number of suggestion with this status.
406 sub CountSuggestion
{
408 my $dbh = C4
::Context
->dbh;
410 my $userenv = C4
::Context
->userenv;
411 if ( C4
::Context
->preference("IndependentBranches")
412 && !C4
::Context
->IsSuperLibrarian() )
417 LEFT JOIN borrowers ON borrowers.borrowernumber=suggestions.suggestedby
419 AND (suggestions.branchcode='' OR suggestions.branchcode=?)
421 $sth = $dbh->prepare($query);
422 $sth->execute( $status, $userenv->{branch
} );
430 $sth = $dbh->prepare($query);
431 $sth->execute($status);
433 my ($result) = $sth->fetchrow;
440 &NewSuggestion($suggestion);
442 Insert a new suggestion on database with value given on input arg.
447 my ($suggestion) = @_;
449 $suggestion->{STATUS
} = "ASKED" unless $suggestion->{STATUS
};
451 $suggestion->{suggesteddate
} = dt_from_string
unless $suggestion->{suggesteddate
};
453 delete $suggestion->{branchcode
} if $suggestion->{branchcode
} eq '';
455 my $suggestion_object = Koha
::Suggestion
->new( $suggestion )->store;
456 my $suggestion_id = $suggestion_object->suggestionid;
458 my $emailpurchasesuggestions = C4
::Context
->preference("EmailPurchaseSuggestions");
459 if ($emailpurchasesuggestions) {
460 my $full_suggestion = GetSuggestion
( $suggestion_id); # We should not need to refetch it!
462 my $letter = C4
::Letters
::GetPreparedLetter
(
463 module
=> 'suggestions',
464 letter_code
=> 'NEW_SUGGESTION',
466 'branches' => $full_suggestion->{branchcode
},
467 'borrowers' => $full_suggestion->{suggestedby
},
468 'suggestions' => $full_suggestion,
474 if ( $emailpurchasesuggestions eq "BranchEmailAddress" ) {
476 Koha
::Libraries
->find( $full_suggestion->{branchcode
} );
478 $library->branchreplyto
479 || $library->branchemail
480 || C4
::Context
->preference('ReplytoDefault')
481 || C4
::Context
->preference('KohaAdminEmailAddress');
483 elsif ( $emailpurchasesuggestions eq "KohaAdminEmailAddress" ) {
484 $toaddress = C4
::Context
->preference('ReplytoDefault')
485 || C4
::Context
->preference('KohaAdminEmailAddress');
489 C4
::Context
->preference($emailpurchasesuggestions)
490 || C4
::Context
->preference('ReplytoDefault')
491 || C4
::Context
->preference('KohaAdminEmailAddress');
494 C4
::Letters
::EnqueueLetter
(
497 borrowernumber
=> $full_suggestion->{suggestedby
},
498 suggestionid
=> $full_suggestion->{suggestionid
},
499 to_address
=> $toaddress,
500 message_transport_type
=> 'email',
502 ) or warn "can't enqueue letter $letter";
506 return $suggestion_id;
511 &ModSuggestion($suggestion)
513 Modify the suggestion according to the hash passed by ref.
514 The hash HAS to contain suggestionid
515 Data not defined is not updated unless it is a note or sort1
516 Send a mail to notify the user that did the suggestion.
518 Note that there is no function to modify a suggestion.
523 my ($suggestion) = @_;
524 return unless( $suggestion and defined($suggestion->{suggestionid
}) );
526 my $suggestion_object = Koha
::Suggestions
->find( $suggestion->{suggestionid
} );
527 eval { # FIXME Must raise an exception instead
528 $suggestion_object->set($suggestion)->store;
532 if ( $suggestion->{STATUS
} ) {
534 # fetch the entire updated suggestion so that we can populate the letter
535 my $full_suggestion = GetSuggestion
( $suggestion->{suggestionid
} );
536 my $patron = Koha
::Patrons
->find( $full_suggestion->{suggestedby
} );
538 my $transport = (C4
::Context
->preference("FallbackToSMSIfNoEmail")) && ($patron->smsalertnumber) && (!$patron->email) ?
'sms' : 'email';
541 my $letter = C4
::Letters
::GetPreparedLetter
(
542 module
=> 'suggestions',
543 letter_code
=> $full_suggestion->{STATUS
},
544 branchcode
=> $full_suggestion->{branchcode
},
545 lang
=> $patron->lang,
547 'branches' => $full_suggestion->{branchcode
},
548 'borrowers' => $full_suggestion->{suggestedby
},
549 'suggestions' => $full_suggestion,
550 'biblio' => $full_suggestion->{biblionumber
},
555 C4
::Letters
::EnqueueLetter
(
558 borrowernumber
=> $full_suggestion->{suggestedby
},
559 suggestionid
=> $full_suggestion->{suggestionid
},
560 LibraryName
=> C4
::Context
->preference("LibraryName"),
561 message_transport_type
=> $transport,
563 ) or warn "can't enqueue letter $letter";
566 return 1; # No useful if the exception is raised earlier
569 =head2 ConnectSuggestionAndBiblio
571 &ConnectSuggestionAndBiblio($ordernumber,$biblionumber)
573 connect a suggestion to an existing biblio
577 sub ConnectSuggestionAndBiblio
{
578 my ( $suggestionid, $biblionumber ) = @_;
579 my $dbh = C4
::Context
->dbh;
585 my $sth = $dbh->prepare($query);
586 $sth->execute( $biblionumber, $suggestionid );
591 &DelSuggestion($borrowernumber,$ordernumber)
593 Delete a suggestion. A borrower can delete a suggestion only if they are its owner.
598 my ( $borrowernumber, $suggestionid, $type ) = @_;
599 my $dbh = C4
::Context
->dbh;
601 # check that the suggestion comes from the suggestor
607 my $sth = $dbh->prepare($query);
608 $sth->execute($suggestionid);
609 my ($suggestedby) = $sth->fetchrow;
610 if ( $type eq 'intranet' || $suggestedby eq $borrowernumber ) {
612 DELETE FROM suggestions
615 $sth = $dbh->prepare($queryDelete);
616 my $suggestiondeleted = $sth->execute($suggestionid);
617 return $suggestiondeleted;
621 =head2 DelSuggestionsOlderThan
622 &DelSuggestionsOlderThan($days)
624 Delete all suggestions older than TODAY-$days , that have be accepted or rejected.
625 We do now allow a negative number. If you want to delete all suggestions, just use Koha::Suggestions->delete or so.
629 sub DelSuggestionsOlderThan
{
631 return unless $days && $days > 0;
632 my $dbh = C4
::Context
->dbh;
633 my $sth = $dbh->prepare(
635 DELETE FROM suggestions
636 WHERE STATUS<>'ASKED'
637 AND date < ADDDATE(NOW(), ?)
640 $sth->execute("-$days");
643 sub GetUnprocessedSuggestions
{
644 my ( $number_of_days_since_the_last_modification ) = @_;
646 $number_of_days_since_the_last_modification ||= 0;
648 my $dbh = C4
::Context
->dbh;
650 my $s = $dbh->selectall_arrayref(q
|
653 WHERE STATUS
= 'ASKED'
654 AND budgetid IS NOT NULL
655 AND CAST
(NOW
() AS DATE
) - INTERVAL ? DAY
= CAST
(suggesteddate AS DATE
)
656 |, { Slice
=> {} }, $number_of_days_since_the_last_modification );
660 =head2 MarcRecordFromNewSuggestion
662 $record = MarcRecordFromNewSuggestion ( $suggestion )
664 This function build a marc record object from a suggestion
668 sub MarcRecordFromNewSuggestion
{
669 my ($suggestion) = @_;
670 my $record = MARC
::Record
->new();
672 my ($title_tag, $title_subfield) = GetMarcFromKohaField
('biblio.title', '');
673 $record->append_fields(
674 MARC
::Field
->new($title_tag, ' ', ' ', $title_subfield => $suggestion->{title
})
677 my ($author_tag, $author_subfield) = GetMarcFromKohaField
('biblio.author', '');
678 if ($record->field( $author_tag )) {
679 $record->field( $author_tag )->add_subfields( $author_subfield => $suggestion->{author
} );
682 $record->append_fields(
683 MARC
::Field
->new($author_tag, ' ', ' ', $author_subfield => $suggestion->{author
})
687 my ($it_tag, $it_subfield) = GetMarcFromKohaField
('biblioitems.itemtype', '');
688 if ($record->field( $it_tag )) {
689 $record->field( $it_tag )->add_subfields( $it_subfield => $suggestion->{itemtype
} );
692 $record->append_fields(
693 MARC
::Field
->new($it_tag, ' ', ' ', $it_subfield => $suggestion->{itemtype
})
706 Koha Development Team <http://koha-community.org/>