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

(-)a/C4/Suggestions.pm (+42 lines)
Lines 27-32 use C4::Context; Link Here
27
use C4::Output;
27
use C4::Output;
28
use C4::Debug;
28
use C4::Debug;
29
use C4::Letters;
29
use C4::Letters;
30
use C4::Biblio qw( GetMarcFromKohaField );
30
use Koha::DateUtils;
31
use Koha::DateUtils;
31
32
32
use List::MoreUtils qw(any);
33
use List::MoreUtils qw(any);
Lines 47-52 our @EXPORT = qw( Link Here
47
  SearchSuggestion
48
  SearchSuggestion
48
  DelSuggestionsOlderThan
49
  DelSuggestionsOlderThan
49
  GetUnprocessedSuggestions
50
  GetUnprocessedSuggestions
51
  MarcRecordFromNewSuggestion
50
);
52
);
51
53
52
=head1 NAME
54
=head1 NAME
Lines 620-625 sub GetUnprocessedSuggestions { Link Here
620
    return $s;
622
    return $s;
621
}
623
}
622
624
625
=head2 MarcRecordFromNewSuggestion
626
627
    $record = MarcRecordFromNewSuggestion ( $suggestion )
628
629
This function build a marc record object from a suggestion
630
631
=cut
632
633
sub MarcRecordFromNewSuggestion {
634
    my ($suggestion) = @_;
635
    my $record = MARC::Record->new();
636
637
    my ($title_tag, $title_subfield) = GetMarcFromKohaField('biblio.title', '');
638
    $record->append_fields(
639
        MARC::Field->new($title_tag, ' ', ' ', $title_subfield => $suggestion->{title})
640
    );
641
642
    my ($author_tag, $author_subfield) = GetMarcFromKohaField('biblio.author', '');
643
    if ($record->field( $author_tag )) {
644
        $record->field( $author_tag )->add_subfields( $author_subfield => $suggestion->{author} );
645
    }
646
    else {
647
        $record->append_fields(
648
            MARC::Field->new($author_tag, ' ', ' ', $author_subfield => $suggestion->{author})
649
        );
650
    }
651
652
    my ($it_tag, $it_subfield) = GetMarcFromKohaField('biblioitems.itemtype', '');
653
    if ($record->field( $it_tag )) {
654
        $record->field( $it_tag )->add_subfields( $it_subfield => $suggestion->{itemtype} );
655
    }
656
    else {
657
        $record->append_fields(
658
            MARC::Field->new($it_tag, ' ', ' ', $it_subfield => $suggestion->{author})
659
        );
660
    }
661
662
    return $record;
663
}
664
623
1;
665
1;
624
__END__
666
__END__
625
667
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-suggestions.tt (-11 / +26 lines)
Lines 38-57 Link Here
38
                            <p>Please fill out this form to make a purchase suggestion. You will receive an email when the library processes your suggestion.</p>
38
                            <p>Please fill out this form to make a purchase suggestion. You will receive an email when the library processes your suggestion.</p>
39
                            <p>Only certain fields (marked in red) are required, but the more information you enter the easier it will be for the librarians to find the title you're requesting. The "Notes" field can be used to provide any additional information.</p>
39
                            <p>Only certain fields (marked in red) are required, but the more information you enter the easier it will be for the librarians to find the title you're requesting. The "Notes" field can be used to provide any additional information.</p>
40
40
41
                            [% FOR m IN messages %]
42
                                <div class="alert alert-[% m.type %]">
43
                                    [% SWITCH m.code %]
44
                                    [% CASE 'biblio_exists' %]
45
                                        A similar document already exists: <a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% m.id %]">[% m.title %]</a>. Click on "Confirm your suggestion" to ignore this message.
46
                                    [% CASE %]
47
                                        [% m.code %]
48
                                    [% END %]
49
                                </div>
50
                            [% END %]
51
41
                            <form action="/cgi-bin/koha/opac-suggestions.pl" method="post" id="add_suggestion_form">
52
                            <form action="/cgi-bin/koha/opac-suggestions.pl" method="post" id="add_suggestion_form">
42
                                <fieldset class="rows">
53
                                <fieldset class="rows">
43
                                    <ol>
54
                                    <ol>
44
                                        <li><label for="title">Title:</label><input type="text" id="title" name="title" class="span6" maxlength="255" /></li>
55
                                        <li><label for="title">Title:</label><input type="text" id="title" name="title" class="span6" maxlength="255" value="[% title %]" /></li>
45
                                        <li><label for="author">Author:</label><input type="text" id="author" name="author" class="span6" maxlength="80" /></li>
56
                                        <li><label for="author">Author:</label><input type="text" id="author" name="author" class="span6" maxlength="80" value="[% author %]" /></li>
46
                                        <li>
57
                                        <li>
47
                                            <div title="Copyright or publication year, for example: 2016">
58
                                            <div title="Copyright or publication year, for example: 2016">
48
                                            <label for="copyrightdate">Copyright date:</label><input type="text" id="copyrightdate" name="copyrightdate" pattern="[12]\d{3}" size="4" maxlength="4" />
59
                                                <label for="copyrightdate">Copyright date:</label><input type="text" id="copyrightdate" name="copyrightdate" size="4" maxlength="4" value="[% copyrightdate %]" /></li>
49
                                            </div>
60
                                            </div>
50
                                        </li>
61
                                        <li><label for="isbn">Standard number (ISBN, ISSN or other):</label><input type="text" id="isbn" name="isbn"  maxlength="80" value="[% isbn %]" /></li>
51
                                        <li><label for="isbn">Standard number (ISBN, ISSN or other):</label><input type="text" id="isbn" name="isbn"  maxlength="80" /></li>
62
                                        <li><label for="publishercode">Publisher:</label><input type="text" id="publishercode" name="publishercode" class="span6" maxlength="80" value="[% publishercode %]"/></li>
52
                                        <li><label for="publishercode">Publisher:</label><input type="text" id="publishercode" name="publishercode" class="span6" maxlength="80" /></li>
63
                                        <li><label for="collectiontitle">Collection title:</label><input type="text" id="collectiontitle" name="collectiontitle" class="span6" maxlength="80" value="[% collectiontitle %]"/></li>
53
                                        <li><label for="collectiontitle">Collection title:</label><input type="text" id="collectiontitle" name="collectiontitle" class="span6" maxlength="80" /></li>
64
                                        <li><label for="place">Publication place:</label><input type="text" id="place" name="place"  maxlength="80" valu="[% place %]" /></li>
54
                                        <li><label for="place">Publication place:</label><input type="text" id="place" name="place"  maxlength="80" /></li>
55
                                        <li><label for="itemtype">Item type:</label>
65
                                        <li><label for="itemtype">Item type:</label>
56
                                            [% PROCESS 'av-build-dropbox.inc' name="itemtype", category="SUGGEST_FORMAT", size = 20 %]
66
                                            [% PROCESS 'av-build-dropbox.inc' name="itemtype", category="SUGGEST_FORMAT", size = 20 %]
57
                                        </li>
67
                                        </li>
Lines 75-81 Link Here
75
                                        [% END %]
85
                                        [% END %]
76
                                        <li>
86
                                        <li>
77
                                            <label for="note">Notes:</label>
87
                                            <label for="note">Notes:</label>
78
                                            <textarea name="note" id="note" rows="5" cols="40"></textarea>
88
                                            <textarea name="note" id="note" rows="5" cols="40">[% note %]</textarea>
79
                                        </li>
89
                                        </li>
80
90
81
                                        <!--  Add a hidden 'negcap' field -->
91
                                        <!--  Add a hidden 'negcap' field -->
Lines 87-94 Link Here
87
                                </fieldset>
97
                                </fieldset>
88
                                <fieldset class="action">
98
                                <fieldset class="action">
89
                                    <input type="hidden" name="suggested_by_anyone" value="[% suggested_by_anyone %]" />
99
                                    <input type="hidden" name="suggested_by_anyone" value="[% suggested_by_anyone %]" />
90
                                    <input type="hidden" name="op" value="add_confirm" />
100
                                    <input type="hidden" name="op" value="add_validate" />
91
                                    <input type="submit" class="btn" value="Submit your suggestion" /> <a class="action" href="/cgi-bin/koha/opac-suggestions.pl">Cancel</a>
101
                                    [% IF ( need_confirm ) %]
102
                                    <input type="submit" onclick="this.form.op.value = 'add_confirm'; this.form.submit();" class="btn" value="Confirm your suggestion" />
103
                                    [% ELSE %]
104
                                    <input type="submit" onclick="Check(this.form); return false;" class="btn" value="Submit your suggestion" />
105
                                    [% END %]
106
                                    <a class="action" href="/cgi-bin/koha/opac-suggestions.pl">Cancel</a>
92
                                </fieldset>
107
                                </fieldset>
93
                            </form>
108
                            </form>
94
                            [% END %]
109
                            [% END %]
(-)a/opac/opac-suggestions.pl (-1 / +15 lines)
Lines 27-32 use C4::Output; Link Here
27
use C4::Suggestions;
27
use C4::Suggestions;
28
use C4::Koha;
28
use C4::Koha;
29
use C4::Scrubber;
29
use C4::Scrubber;
30
use C4::Search qw( FindDuplicate );
30
31
31
use Koha::AuthorisedValues;
32
use Koha::AuthorisedValues;
32
use Koha::Libraries;
33
use Koha::Libraries;
Lines 38-43 my $op = $input->param('op'); Link Here
38
my $suggestion      = $input->Vars;
39
my $suggestion      = $input->Vars;
39
my $negcaptcha      = $input->param('negcap');
40
my $negcaptcha      = $input->param('negcap');
40
my $suggested_by_anyone = $input->param('suggested_by_anyone') || 0;
41
my $suggested_by_anyone = $input->param('suggested_by_anyone') || 0;
42
my $need_confirm    = 0;
41
43
42
# If a spambot accidentally populates the 'negcap' field in the sugesstions form, then silently skip and return.
44
# If a spambot accidentally populates the 'negcap' field in the sugesstions form, then silently skip and return.
43
if ($negcaptcha ) {
45
if ($negcaptcha ) {
Lines 55-61 if ( ! C4::Context->preference('suggestion') ) { Link Here
55
    exit;
57
    exit;
56
}
58
}
57
59
58
delete $suggestion->{$_} foreach qw<op suggested_by_anyone>;
60
delete $suggestion->{$_} foreach qw<op suggested_by_anyone confirm>;
59
$op = 'else' unless $op;
61
$op = 'else' unless $op;
60
62
61
my ( $template, $borrowernumber, $cookie, @messages );
63
my ( $template, $borrowernumber, $cookie, @messages );
Lines 113-118 if ( $op eq 'else' ) { Link Here
113
    }
115
    }
114
}
116
}
115
117
118
if ( $op eq "add_validate" ) {
119
    $op = 'add_confirm';
120
    my $biblio = MarcRecordFromNewSuggestion($suggestion);
121
    if ( my ($duplicatebiblionumber, $duplicatetitle) = FindDuplicate($biblio) ) {
122
        push @messages, { type => 'error', code => 'biblio_exists', id => $duplicatebiblionumber, title => $duplicatetitle };
123
        $need_confirm = 1;
124
        $op = 'add';
125
    }
126
}
127
116
my $patrons_pending_suggestions_count = 0;
128
my $patrons_pending_suggestions_count = 0;
117
if ( $borrowernumber && C4::Context->preference("MaxOpenSuggestions") ne '' ) {
129
if ( $borrowernumber && C4::Context->preference("MaxOpenSuggestions") ne '' ) {
118
    $patrons_pending_suggestions_count = scalar @{ SearchSuggestion( { suggestedby => $borrowernumber, STATUS => 'ASKED' } ) } ;
130
    $patrons_pending_suggestions_count = scalar @{ SearchSuggestion( { suggestedby => $borrowernumber, STATUS => 'ASKED' } ) } ;
Lines 163-168 if ( $op eq "add_confirm" ) { Link Here
163
    $op = 'else';
175
    $op = 'else';
164
}
176
}
165
177
178
my $suggestions_loop = &SearchSuggestion({suggestedby => $suggestion->{suggestedby}});
166
if ( $op eq "delete_confirm" ) {
179
if ( $op eq "delete_confirm" ) {
167
    my @delete_field = $input->multi_param("delete_field");
180
    my @delete_field = $input->multi_param("delete_field");
168
    foreach my $delete_field (@delete_field) {
181
    foreach my $delete_field (@delete_field) {
Lines 225-230 $template->param( Link Here
225
    suggested_by_anyone   => $suggested_by_anyone,
238
    suggested_by_anyone   => $suggested_by_anyone,
226
    mandatoryfields       => $mandatoryfields,
239
    mandatoryfields       => $mandatoryfields,
227
    patrons_pending_suggestions_count => $patrons_pending_suggestions_count,
240
    patrons_pending_suggestions_count => $patrons_pending_suggestions_count,
241
    need_confirm => $need_confirm,
228
);
242
);
229
243
230
output_html_with_http_headers $input, $cookie, $template->output;
244
output_html_with_http_headers $input, $cookie, $template->output;
(-)a/t/db_dependent/Suggestions.t (-2 / +19 lines)
Lines 28-34 use Koha::Library; Link Here
28
use Koha::Libraries;
28
use Koha::Libraries;
29
29
30
use DateTime::Duration;
30
use DateTime::Duration;
31
use Test::More tests => 102;
31
use Test::More tests => 105;
32
use Test::Warn;
32
use Test::Warn;
33
33
34
BEGIN {
34
BEGIN {
Lines 359-364 ModSuggestion( $my_suggestion ); Link Here
359
$suggestion = GetSuggestion($my_suggestionid_test_budgetid);
359
$suggestion = GetSuggestion($my_suggestionid_test_budgetid);
360
is( $suggestion->{budgetid}, undef, 'NewSuggestion Should set budgetid to NULL if equals an empty string' );
360
is( $suggestion->{budgetid}, undef, 'NewSuggestion Should set budgetid to NULL if equals an empty string' );
361
361
362
my $suggestion2 = {
363
    title => "Cuisine d'automne",
364
    author => "Catherine",
365
    itemtype => "LIV"
366
};
367
368
my $record = MarcRecordFromNewSuggestion($suggestion2);
369
370
is("MARC::Record", ref($record), "MarcRecordFromNewSuggestion should return a MARC::Record object");
371
372
my ($title_tag, $title_subfield) = C4::Biblio::GetMarcFromKohaField('biblio.title', '');
373
374
is($record->field( $title_tag )->subfield( $title_subfield ), "Cuisine d'automne", "Record from suggestion title should be 'Cuisine d'automne'");
375
376
my ($author_tag, $author_subfield) = C4::Biblio::GetMarcFromKohaField('biblio.author', '');
377
378
is($record->field( $author_tag )->subfield( $author_subfield ), "Catherine", "Record from suggestion author should be 'Catherine'");
379
362
subtest 'GetUnprocessedSuggestions' => sub {
380
subtest 'GetUnprocessedSuggestions' => sub {
363
    plan tests => 11;
381
    plan tests => 11;
364
    $dbh->do(q|DELETE FROM suggestions|);
382
    $dbh->do(q|DELETE FROM suggestions|);
365
- 

Return to bug 14973