Bugzilla – Attachment 41921 Details for
Bug 14224
patron notes about item shown at check in
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 14224: Allow patron notes about item shown at check in
Bug-14224-Allow-patron-notes-about-item-shown-at-c.patch (text/plain), 22.94 KB, created by
Martin Stenberg
on 2015-08-25 14:23:23 UTC
(
hide
)
Description:
Bug 14224: Allow patron notes about item shown at check in
Filename:
MIME Type:
Creator:
Martin Stenberg
Created:
2015-08-25 14:23:23 UTC
Size:
22.94 KB
patch
obsolete
>From 76e0ddd512351e7afb9f90682aeb6e36aa0c91c4 Mon Sep 17 00:00:00 2001 >From: Martin Stenberg <martin@xinxidi.net> >Date: Sun, 23 Aug 2015 18:22:50 +0200 >Subject: [PATCH] Bug 14224: Allow patron notes about item shown at check in > >This patch adds a "Note" input field to checked out items in the "your summery" >section. The field allows patrons to write notes about the item checked out, >such as "this DVD is scratched", "the binding was torn", etc. The note will be >emailed to the library and displayed on item check in. > >Patch adds two fields to the "issues" table - "note" and "notedate". >Patch adds syspref "AllowIssueNotes" - default off. > >Test Plan: >1) Apply this patch >2) Run updatedatabase >3) Make sure the branch has an email address specified >4) Check out an item to a patron >5) Log in with the patron you checked out the item for >6) In "your summery", write a message in the new "Note" field for the item > checked out. Hit ENTER to save/send. >7) Success message should be seen and an email sent to the email address > specified for the branch which the item was checked out from. >8) Log in with staff account and check in the item >9) The note should be shown > >The note can be changed by the patron at any time while the item is checked out. >Each change will send a new email to the branch. Only the latest note version >will be shown on check in. > >Obsoletes: 41801 - Bug 14224: Allow patron notes about item shown at check in >--- > C4/Circulation.pm | 42 ++++++- > circ/returns.pl | 3 + > .../bug_14224-add_new_issue_columns.sql | 2 + > .../atomicupdate/bug_14224-issue_notes_syspref.sql | 1 + > installer/data/mysql/kohastructure.sql | 2 + > installer/data/mysql/sysprefs.sql | 1 + > .../en/modules/admin/preferences/circulation.pref | 6 + > .../intranet-tmpl/prog/en/modules/circ/returns.tt | 10 ++ > .../bootstrap/en/modules/opac-sendissuenote.tt | 21 ++++ > .../opac-tmpl/bootstrap/en/modules/opac-user.tt | 96 +++++++++++++++ > opac/opac-user.pl | 131 ++++++++++++++++++++- > 11 files changed, 311 insertions(+), 4 deletions(-) > create mode 100644 installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql > create mode 100644 installer/data/mysql/atomicupdate/bug_14224-issue_notes_syspref.sql > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendissuenote.tt > >diff --git a/C4/Circulation.pm b/C4/Circulation.pm >index 7813e33..5d4957d 100644 >--- a/C4/Circulation.pm >+++ b/C4/Circulation.pm >@@ -92,6 +92,7 @@ BEGIN { > &GetBranchItemRule > &GetBiblioIssues > &GetOpenIssue >+ &SetIssueNote > &AnonymiseIssueHistory > &CheckIfIssuedToPatron > &IsItemIssued >@@ -2450,7 +2451,7 @@ sub GetOpenIssue { > =head2 GetIssues > > $issues = GetIssues({}); # return all issues! >- $issues = GetIssues({ borrowernumber => $borrowernumber, biblionumber => $biblionumber }); >+ $issues = GetIssues({ borrowernumber => $borrowernumber, biblionumber => $biblionumber, issue_id => $issue_id }); > > Returns all pending issues that match given criteria. > Returns a arrayref or undef if an error occurs. >@@ -2465,6 +2466,8 @@ Allowed criteria are: > > =item * itemnumber > >+=item * issue_id >+ > =back > > =cut >@@ -2474,7 +2477,7 @@ sub GetIssues { > > # Build filters > my @filters; >- my @allowed = qw(borrowernumber biblionumber itemnumber); >+ my @allowed = qw(borrowernumber biblionumber itemnumber issue_id); > foreach (@allowed) { > if (defined $criteria->{$_}) { > push @filters, { >@@ -3968,6 +3971,41 @@ sub GetPendingOnSiteCheckouts { > |, { Slice => {} } ); > } > >+=head2 SetIssueNote >+ >+ &SetIssueNote($issue_id, $note); >+ >+Sets a note to the issuenotes table for the given issue. >+ >+=over 4 >+ >+=item C<$issue_id> is the id of the issue for which to set the note >+ >+=item C<$note> is the note to set >+ >+=back >+ >+Returns: >+ True on success >+ False on failure >+ >+=cut >+ >+sub SetIssueNote { >+ my ( $issue_id, $note) = @_; >+ >+ my $dbh = C4::Context->dbh; >+ >+ unless ( $issue_id =~ /\d+/ ) { >+ return; >+ } >+ >+ my $query = "UPDATE issues SET notedate=NOW(),note=? WHERE issue_id=?"; >+ my $sth = $dbh->prepare($query); >+ return $sth->execute( $note, $issue_id ); >+} >+ >+ > __END__ > > =head1 AUTHOR >diff --git a/circ/returns.pl b/circ/returns.pl >index 8084727..ac95f92 100755 >--- a/circ/returns.pl >+++ b/circ/returns.pl >@@ -269,6 +269,8 @@ if ($barcode) { > my $hbr = GetBranchItemRule($biblio->{'homebranch'}, $itemtype)->{'returnbranch'} || "homebranch"; > my $returnbranch = $biblio->{$hbr} ; > >+ my $issue = GetItemIssue($itemnumber); >+ > $template->param( > title => $biblio->{'title'}, > homebranch => $biblio->{'homebranch'}, >@@ -281,6 +283,7 @@ if ($barcode) { > biblionumber => $biblio->{'biblionumber'}, > borrower => $borrower, > additional_materials => $biblio->{'materials'}, >+ issue => $issue, > ); > > my %input = ( >diff --git a/installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql b/installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql >new file mode 100644 >index 0000000..0b4340e >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug_14224-add_new_issue_columns.sql >@@ -0,0 +1,2 @@ >+ALTER IGNORE TABLE issues ADD COLUMN `note` mediumtext default NULL; -- issue note text >+ALTER IGNORE TABLE issues ADD COLUMN `notedate` datetime default NULL; -- datetime of issue note (yyyy-mm-dd hh:mm::ss) >diff --git a/installer/data/mysql/atomicupdate/bug_14224-issue_notes_syspref.sql b/installer/data/mysql/atomicupdate/bug_14224-issue_notes_syspref.sql >new file mode 100644 >index 0000000..e619b21 >--- /dev/null >+++ b/installer/data/mysql/atomicupdate/bug_14224-issue_notes_syspref.sql >@@ -0,0 +1 @@ >+INSERT IGNORE INTO systempreferences (`variable`, `value`, `options`, `explanation`,`type`) VALUES ('AllowIssueNotes', '0', NULL, 'Allow patrons to submit notes about checked out items.','YesNo'); >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 13b6a6a..b2487b8 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -1156,6 +1156,8 @@ CREATE TABLE `issues` ( -- information related to check outs or issues > `timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, -- the date and time this record was last touched > `issuedate` datetime default NULL, -- date the item was checked out or issued > `onsite_checkout` int(1) NOT NULL default 0, -- in house use flag >+ `note` mediumtext default NULL, -- issue note text >+ `notedate` datetime default NULL, -- datetime of issue note (yyyy-mm-dd hh:mm::ss) > PRIMARY KEY (`issue_id`), > KEY `issuesborridx` (`borrowernumber`), > KEY `itemnumber_idx` (`itemnumber`), >diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql >index ac79f44..7447458 100644 >--- a/installer/data/mysql/sysprefs.sql >+++ b/installer/data/mysql/sysprefs.sql >@@ -25,6 +25,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` > ('AllowMultipleIssuesOnABiblio',1,'Allow/Don\'t allow patrons to check out multiple items from one biblio','','YesNo'), > ('AllowNotForLoanOverride','0','','If ON, Koha will allow the librarian to loan a not for loan item.','YesNo'), > ('AllowOfflineCirculation','0','','If on, enables HTML5 offline circulation functionality.','YesNo'), >+('AllowIssueNotes', '0', NULL, 'Allow patrons to submit notes about checked out items.','YesNo'), > ('AllowPKIAuth','None','None|Common Name|emailAddress','Use the field from a client-side SSL certificate to look a user in the Koha database','Choice'), > ('AllowPurchaseSuggestionBranchChoice','0','1','Allow user to choose branch when making a purchase suggestion','YesNo'), > ('AllowRenewalIfOtherItemsAvailable','0',NULL,'If enabled, allow a patron to renew an item with unfilled holds if other available items can fill that hold.','YesNo'), >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >index f9cd822..3323c4c 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref >@@ -136,6 +136,12 @@ Circulation: > yes: Enable > no: "Do not enable" > - "offline circulation on regular circulation computers. (NOTE: This system preference does not affect the Firefox plugin or the desktop application)" >+ - >+ - pref: AllowIssueNotes >+ choices: >+ yes: Allow >+ no: "Don't allow" >+ - patrons to submit notes about checked out items. > > Checkout Policy: > - >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >index f710cdb..b5d0dbc 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/circ/returns.tt >@@ -123,6 +123,16 @@ $(document).ready(function () { > <div id="rotating-collection" class="dialog message">This item is part of a rotating collection and needs to be transferred to [% collectionBranch %]</div> > [% END %] > >+<!-- Patron has added an issue note --> >+[% IF ( issue.note) %] >+ <div class="dialog message"> >+ <h1>Patron note</h1> >+ <p>[% issue.notedate %]</p> >+ <p><a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% itembiblionumber %]"> [% title |html %]</a> [% author %]</p> >+ <p>[% issue.note %]</p> >+ </div> >+[% END %] >+ > <!-- Patron has fines --> > [% IF ( fines ) %] > <div class="dialog alert"> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendissuenote.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendissuenote.tt >new file mode 100644 >index 0000000..e4a655b >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-sendissuenote.tt >@@ -0,0 +1,21 @@ >+<SUBJECT> >+Issue note for [% title %] [% author %] >+<END_SUBJECT> >+ >+[% USE HtmlToText %] >+ >+<HEADER> >+[% FILTER html2text %] >+ <p>Hi,</p> >+ <p>[% MEMBER.firstname %] [% MEMBER.surname %] sent you the following note related to the check out of >+ <p>[% title %] [% author %].</p> >+[% END %] >+ >+<END_HEADER> >+ >+<MESSAGE> >+[% FILTER html2text %] >+ [% note %] >+[% END %] >+ >+<END_MESSAGE> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >index b5bc8d2..d6f39c0 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-user.tt >@@ -98,6 +98,8 @@ > </div> > [% END # / IF patron_flagged %] > >+ <div class="alert alert-info" id="notesaved" style="display:none"></div> >+ > [% SET OPACMySummaryNote = Koha.Preference('OPACMySummaryNote') %] > [% IF OPACMySummaryNote %][% OPACMySummaryNote %][% END %] > >@@ -142,6 +144,9 @@ > [% IF ( OPACMySummaryHTML ) %] > <th class="nosort">Links</th> > [% END %] >+ [% IF ( AllowIssueNotes ) %] >+ <th class="nosort">Note</th> >+ [% END %] > </tr> > </thead> > <tbody> >@@ -254,6 +259,20 @@ > [% IF ( OPACMySummaryHTML ) %] > <td class="links">[% ISSUE.MySummaryHTML %]</td> > [% END %] >+ [% IF ( AllowIssueNotes ) %] >+ <td class="note"> >+ <input type="text" >+ name="note" >+ data-issue_id="[% ISSUE.issue_id%]" >+ data-origvalue="[% ISSUE.note %]" >+ value="[% ISSUE.note %]"> >+ </input> >+ <a class="btn" >+ name="submitnote" >+ id="save_[% ISSUE.issue_id %]" >+ style="display:none;">Submit note</a> >+ </td> >+ [% END %] > </tr> > [% END # /FOREACH ISSUES %] > </tbody> >@@ -732,6 +751,83 @@ > [% END %] > [% END %] > >+ [% IF ( AllowIssueNotes ) %] >+ $("input[name='note']").keyup(function(e){ >+ /* prevent submitting of renewselected form */ >+ if(e.which == 13) >+ e.preventDefault(); >+ >+ var $btn_save = $('#save_'+$(this).data('issue_id')); >+ var origvalue = $(this).data('origvalue'); >+ var value = $(this).val(); >+ >+ if(origvalue != value) { >+ if(origvalue != "") >+ $btn_save.text('Submit changes'); >+ else >+ $btn_save.text('Submit note'); >+ $btn_save.show(); >+ } else { >+ $btn_save.hide(); >+ } >+ }); >+ >+ $("a[name='submitnote']").click(function(e){ >+ var $self = $(this); >+ var title = $(this).parent().siblings('.title').html(); >+ var $noteinput = $(this).siblings('input[name="note"]').first(); >+ >+ var ajaxData = { >+ 'action': 'issuenote', >+ 'issue_id': $noteinput.data('issue_id'), >+ 'note': $noteinput.val(), >+ }; >+ >+ $.ajax({ >+ url: '/cgi-bin/koha/opac-user.pl', >+ type: 'POST', >+ dataType: 'json', >+ data: ajaxData, >+ }) >+ .done(function(data) { >+ var message = ""; >+ if(data.status == 'saved') { >+ $("#notesaved").removeClass("alert-error"); >+ $("#notesaved").addClass("alert-info"); >+ $noteinput.data('origvalue', data.note); >+ $noteinput.val(data.note); >+ message = "<p>Your note about " + title + " was saved and have been sent to the library.</p>"; >+ $self.hide(); >+ } else if(data.status == 'removed') { >+ $("#notesaved").removeClass("alert-error"); >+ $("#notesaved").addClass("alert-info"); >+ $noteinput.data('origvalue', ""); >+ $noteinput.val(""); >+ message = "<p>Your note about " + title + " was removed.</p>"; >+ $self.hide(); >+ } else { >+ $("#notesaved").removeClass("alert-info"); >+ $("#notesaved").addClass("alert-error"); >+ message = "<p>Your note about " + title + " could not be saved.</p>" + >+ "<p style=\"font-weight:bold;\">" + data.error + "</p>"; >+ } >+ >+ message += "<p style=\"font-style:italic;\">" + data.note + "</p>"; >+ $("#notesaved").html(message); >+ }) >+ .fail(function(data) { >+ $("#notesaved").removeClass("alert-info"); >+ $("#notesaved").addClass("alert-error"); >+ var message = "<p>Your note about " + title + " could not be saved.</p>" + >+ "<p style=\"font-weight:bold;\">Ajax request has failed.</p>"; >+ $("#notesaved").html(message); >+ }) >+ .always(function() { >+ $("#notesaved").show(); >+ }); >+ }); >+ [% END %] >+ > $( ".suspend-until" ).datepicker({ minDate: 1 }); // Require that "until date" be in the future > }); > //]]> >diff --git a/opac/opac-user.pl b/opac/opac-user.pl >index d4fbbe3..6f85e40 100755 >--- a/opac/opac-user.pl >+++ b/opac/opac-user.pl >@@ -22,18 +22,24 @@ use strict; > > use CGI qw ( -utf8 ); > >-use C4::Auth; >+use Mail::Sendmail; >+use MIME::QuotedPrint; >+use Carp; >+use C4::Auth qw(:DEFAULT check_cookie_auth); > use C4::Koha; > use C4::Circulation; > use C4::Reserves; > use C4::Members; > use C4::Members::AttributeTypes; > use C4::Members::Attributes qw/GetBorrowerAttributeValue/; >-use C4::Output; >+use CGI::Cookie; # need to check cookies before having CGI parse the POST request >+use C4::Output qw(:DEFAULT :ajax); >+use C4::Scrubber; > use C4::Biblio; > use C4::Items; > use C4::Letters; > use C4::Branch; # GetBranches >+use Koha::Email; > use Koha::DateUtils; > use Koha::Borrower::Debarments qw(IsDebarred); > >@@ -54,6 +60,126 @@ BEGIN { > } > } > >+sub ajax_auth_cgi { # returns CGI object >+ my $needed_flags = shift; >+ my %cookies = fetch CGI::Cookie; >+ my $input = CGI->new; >+ my $sessid = $cookies{'CGISESSID'}->value; >+ my ($auth_status, $auth_sessid) = check_cookie_auth($sessid, $needed_flags); >+ if ($auth_status ne "ok") { >+ output_with_http_headers $input, undef, >+ "window.alert('Your CGI session cookie ($sessid) is not current. " . >+ "Please refresh the page and try again.');\n", 'js'; >+ exit 0; >+ } >+ return $input; >+} >+ >+# AJAX requests >+my $is_ajax = is_ajax(); >+my $query = ($is_ajax) ? &ajax_auth_cgi({}) : CGI->new(); >+if ($is_ajax) { >+ my $action = $query->param('action'); >+ >+ # Issue Note >+ if ( $action == 'issuenote' && C4::Context->preference('AllowIssueNotes') ) { >+ my $scrubber = C4::Scrubber->new(); >+ my $note = $query->param('note'); >+ my $issue_id = $query->param('issue_id'); >+ my $clean_note = $scrubber->scrub($note); >+ my $status = "saved"; >+ my $error = ""; >+ my ($error, $member, $issue); >+ >+ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >+ { >+ template_name => "opac-sendissuenote.tt", >+ query => $query, >+ type => "opac", >+ authnotrequired => 1, >+ } >+ ); >+ >+ # verify issue_id >+ if ( $issue_id =~ /\d+/ ) { >+ $member = GetMember(borrowernumber => $borrowernumber); >+ ($issue) = @{C4::Circulation::GetIssues({issue_id => $issue_id})}; >+ >+ if ( $issue->{'borrowernumber'} != $borrowernumber ) { >+ $status = "fail"; >+ $error = "Invalid issue id!"; >+ } >+ } else { >+ $status = "fail"; >+ $error = "Invalid issue id!"; >+ } >+ >+ if ( (not $error) && SetIssueNote($issue_id, $clean_note) ) { >+ if($clean_note) { # only send email if note not empty >+ my $branch = GetBranchDetail($issue->{'branchcode'}); >+ >+ if ( $branch->{'branchemail'} ) { >+ my $biblio = GetBiblioFromItemNumber($issue->{'itemnumber'}); >+ my $message = Koha::Email->new(); >+ my %mail = $message->create_message_headers(); >+ >+ $template->param( >+ author => $biblio->{'author'}, >+ title => $biblio->{'title'}, >+ MEMBER => $member, >+ note => $clean_note, >+ ); >+ >+ # Getting template result >+ my $template_res = $template->output(); >+ my $body; >+ >+ # Analysing information and getting mail properties >+ if ( $template_res =~ /<SUBJECT>(.*)<END_SUBJECT>/s ) { >+ $mail{subject} = $1; >+ $mail{subject} =~ s|\n?(.*)\n?|$1|; >+ } >+ else { $mail{'subject'} = "no subject"; } >+ $mail{subject} = Encode::encode("UTF-8", $mail{subject}); >+ >+ my $email_header = ""; >+ if ( $template_res =~ /<HEADER>(.*)<END_HEADER>/s ) { >+ $email_header = $1; >+ $email_header =~ s|\n?(.*)\n?|$1|; >+ $email_header = encode_qp(Encode::encode("UTF-8", $email_header)); >+ } >+ >+ if ( $template_res =~ /<MESSAGE>(.*)<END_MESSAGE>/s ) { >+ $body = $1; >+ $body =~ s|\n?(.*)\n?|$1|; >+ $body = encode_qp(Encode::encode("UTF-8", $body)); >+ } >+ >+ $mail{to} = $branch->{'branchemail'}; >+ $mail{from} = $member->{'email'} || ($branch->{'branchemail'}=~s/^.+@/noreply@/ && $branch->{'branchemail'}); >+ $mail{body} = $email_header . $body; >+ >+ unless ( sendmail(%mail) ) { >+ $status = "fail"; >+ $error = "Could not send message to library. Message will still show at check in."; >+ carp "Error sending mail: $Mail::Sendmail::error \n"; >+ } >+ } >+ } else { # note empty, i.e removed >+ $status = "removed"; >+ } >+ } else { >+ $status = "fail"; >+ $error = "Perhaps the item has already been check in?"; >+ } >+ >+ my $response = "{\"status\": \"$status\", \"note\": \"$clean_note\", \"issue_id\": \"$issue_id\", \"error\": \"$error\"}"; >+ output_with_http_headers($query, undef, $response, 'js'); >+ exit; >+ } # END Issue Note >+} >+ >+ > my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > { > template_name => "opac-user.tt", >@@ -244,6 +370,7 @@ if ($issues){ > } > } > } >+$template->param( AllowIssueNotes => C4::Context->preference('AllowIssueNotes') ); > $template->param( ISSUES => \@issuedat ); > $template->param( issues_count => $count ); > $template->param( canrenew => $canrenew ); >-- >2.5.0
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 14224
:
41801
|
41921
|
56682
|
57440
|
57577
|
57763
|
57802
|
57829
|
57853
|
58277
|
58325
|
58326
|
58372
|
58606
|
58622
|
59469
|
59637
|
59641
|
59761
|
59779
|
59780
|
59781
|
59782
|
59783
|
59784
|
59785
|
59786
|
59787
|
59788
|
59796
|
59798
|
59799
|
59800
|
59801
|
59802
|
59803
|
59804
|
59805
|
59806
|
61847
|
61848
|
61849
|
61850
|
61851
|
61852
|
61853
|
61854
|
61855
|
61856
|
62196
|
62197
|
62198
|
62199
|
62200
|
62201
|
62202
|
62203
|
62204
|
62205
|
62206
|
62633
|
62634
|
62635
|
62636
|
62637
|
62638
|
62639
|
62640
|
62641
|
62642
|
62643
|
62644