Bugzilla – Attachment 13293 Details for
Bug 9021
Add SMS via email as an alternative to SMS services via SMS::Send drivers
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 9021 - Add SMS via email as an alternative to SMS services via SMS::Send drivers
Bug-9021---Add-SMS-via-email-as-an-alternative-to-.patch (text/plain), 20.14 KB, created by
Kyle M Hall (khall)
on 2012-11-07 17:57:05 UTC
(
hide
)
Description:
Bug 9021 - Add SMS via email as an alternative to SMS services via SMS::Send drivers
Filename:
MIME Type:
Creator:
Kyle M Hall (khall)
Created:
2012-11-07 17:57:05 UTC
Size:
20.14 KB
patch
obsolete
>From 70d7181a10c6bd993676fceed0b2bc6acd83b602 Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >Date: Wed, 7 Nov 2012 08:21:13 -0500 >Subject: [PATCH] Bug 9021 - Add SMS via email as an alternative to SMS services via SMS::Send drivers >Content-Type: text/plain; charset="utf-8" > >--- > C4/Letters.pm | 11 ++- > C4/Members.pm | 6 +- > Koha/SMS/Provider.pm | 157 ++++++++++++++++++++ > admin/admin-home.pl | 5 +- > admin/sms_providers.pl | 59 ++++++++ > installer/data/mysql/kohastructure.sql | 18 ++- > installer/data/mysql/updatedatabase.pl | 19 +++ > .../prog/en/modules/admin/admin-home.tt | 18 ++- > .../prog/en/modules/admin/sms_providers.tt | 102 +++++++++++++ > .../prog/en/modules/members/memberentrygen.tt | 13 ++ > members/memberentry.pl | 7 + > 11 files changed, 406 insertions(+), 9 deletions(-) > create mode 100644 Koha/SMS/Provider.pm > create mode 100755 admin/sms_providers.pl > create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/admin/sms_providers.tt > >diff --git a/C4/Letters.pm b/C4/Letters.pm >index f646241..c476bd3 100644 >--- a/C4/Letters.pm >+++ b/C4/Letters.pm >@@ -30,6 +30,7 @@ use C4::Log; > use C4::SMS; > use C4::Debug; > use Date::Calc qw( Add_Delta_Days ); >+use Koha::SMS::Provider; > use Encode; > use Unicode::Normalize; > use Carp; >@@ -832,7 +833,14 @@ sub SendQueuedMessages { > _send_message_by_email( $message, $params->{'username'}, $params->{'password'}, $params->{'method'} ); > } > elsif ( lc( $message->{'message_transport_type'} ) eq 'sms' ) { >- _send_message_by_sms( $message ); >+ if ( C4::Context->preference('SMSSendDriver') eq 'Email' ) { >+ my $member = C4::Members::GetMember( 'borrowernumber' => $message->{'borrowernumber'} ); >+ my $sms_provider = Koha::SMS::Provider->find( $member->{'sms_provider_id'} ); >+ $message->{to_address} .= '@' . $sms_provider->domain(); >+ _send_message_by_email( $message, $params->{'username'}, $params->{'password'}, $params->{'method'} ); >+ } else { >+ _send_message_by_sms( $message ); >+ } > } > } > return scalar( @$unsent_messages ); >@@ -1051,6 +1059,7 @@ sub _send_message_by_email { > } > > _update_message_to_address($message->{'message_id'},$to_address) unless $message->{to_address}; #if initial message address was empty, coming here means that a to address was found and queue should be updated >+ > if ( sendmail( %sendmail_params ) ) { > _set_message_status( { message_id => $message->{'message_id'}, > status => 'sent' } ); >diff --git a/C4/Members.pm b/C4/Members.pm >index b2f45b9..a00fe26 100644 >--- a/C4/Members.pm >+++ b/C4/Members.pm >@@ -720,7 +720,11 @@ sub ModMember { > $data{password} = md5_base64($data{password}); > } > } >- my $execute_success=UpdateInTable("borrowers",\%data); >+ >+ $data{'sms_provider_id'} = undef unless ( $data{'sms_provider_id'} ); >+ >+ my $execute_success=UpdateInTable("borrowers",\%data); >+ > if ($execute_success) { # only proceed if the update was a success > # ok if its an adult (type) it may have borrowers that depend on it as a guarantor > # so when we update information for an adult we should check for guarantees and update the relevant part >diff --git a/Koha/SMS/Provider.pm b/Koha/SMS/Provider.pm >new file mode 100644 >index 0000000..ad4fd27 >--- /dev/null >+++ b/Koha/SMS/Provider.pm >@@ -0,0 +1,157 @@ >+package Koha::SMS::Provider; >+ >+# Copyright 2012 C & P Bibliography Services >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+=head1 NAME >+ >+Koha::SMS::Provider - class to manage sms providers >+ >+=head1 SYNOPSIS >+ >+Object-oriented class that encapsulates sms providers in Koha. >+ >+=head1 DESCRIPTION >+ >+SMS::Provider data. >+ >+=cut >+ >+use Modern::Perl; >+ >+use C4::Context; >+ >+use base qw(Class::Accessor); >+ >+__PACKAGE__->mk_accessors(qw( id name domain )); >+ >+=head2 new >+ >+ my $provider = Koha::SMS::Provider->new($data); >+ >+Create a new Koha::SMS::Provider object based on the provided record. >+ >+=cut >+ >+sub new { >+ my $class = shift; >+ my $data = shift; >+ >+ my $self = $class->SUPER::new($data); >+ >+ bless $self, $class; >+ return $self; >+} >+ >+=head2 store >+ >+ Creates or updates the object in the database >+ >+=cut >+ >+sub store { >+ my $self = shift; >+ >+ if ( $self->id ) { >+ return C4::Context->dbh->do( "UPDATE sms_providers SET name = ?, domain = ? WHERE id = ?", undef, ( $self->name, $self->domain, $self->id ) ); >+ } else { >+ return C4::Context->dbh->do( "INSERT INTO sms_providers ( name, domain ) VALUES ( ?, ? )", undef, ( $self->name, $self->domain ) ); >+ } >+} >+ >+=head2 delete >+ >+=cut >+ >+sub delete { >+ my $self = shift; >+ >+ return C4::Context->dbh->do( "DELETE FROM sms_providers WHERE id = ?", undef, ( $self->id ) ); >+} >+ >+=head2 all >+ >+ my $providers = Koha::SMS::Provider->all(); >+ >+=cut >+ >+sub all { >+ my $class = shift; >+ >+ my $query = "SELECT * FROM sms_providers ORDER BY name"; >+ my $sth = C4::Context->dbh->prepare($query); >+ $sth->execute(); >+ >+ my @providers; >+ while ( my $row = $sth->fetchrow_hashref() ) { >+ my $p = Koha::SMS::Provider->new($row); >+ push( @providers, $p ); >+ } >+ >+ return @providers; >+} >+ >+=head2 find >+ >+ my $provider = Koha::SMS::Provider->find( $id ); >+ >+=cut >+ >+sub find { >+ my $class = shift; >+ my $id = shift; >+ >+ my $query = "SELECT * FROM sms_providers WHERE ID = ?"; >+ my $sth = C4::Context->dbh->prepare($query); >+ $sth->execute($id); >+ >+ my $row = $sth->fetchrow_hashref(); >+ my $p = Koha::SMS::Provider->new($row); >+ >+ return $p; >+} >+ >+=head2 search >+ >+ my @providers = Koha::SMS::Provider->search({ [name => $name], [domain => $domain] }); >+ >+=cut >+ >+sub search { >+ my $class = shift; >+ my $params = shift; >+ >+ my $query = "SELECT * FROM sms_providers WHERE "; >+ >+ my @params = map( $params->{$_}, keys %$params ); >+ $query .= join( " AND ", map( "$_ = ?", keys %$params ) ); >+ >+ $query .= " ORDER BY name"; >+ >+ my $sth = C4::Context->dbh->prepare($query); >+ $sth->execute(@params); >+ >+ my @providers; >+ while ( my $row = $sth->fetchrow_hashref() ) { >+ my $p = Koha::SMS::Provider->new($row); >+ push( @providers, $p ); >+ } >+ >+ return @providers; >+} >+ >+1; >diff --git a/admin/admin-home.pl b/admin/admin-home.pl >index bf3d9af..d975abf 100755 >--- a/admin/admin-home.pl >+++ b/admin/admin-home.pl >@@ -34,6 +34,9 @@ my ($template, $loggedinuser, $cookie) > debug => 1, > }); > >-$template->param( SearchEngine => C4::Context->preference('SearchEngine') ); >+$template->param( >+ SearchEngine => C4::Context->preference('SearchEngine'), >+ SMSSendDriver => C4::Context->preference('SMSSendDriver'), >+); > > output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/admin/sms_providers.pl b/admin/sms_providers.pl >new file mode 100755 >index 0000000..c2cdcbd >--- /dev/null >+++ b/admin/sms_providers.pl >@@ -0,0 +1,59 @@ >+#!/usr/bin/perl >+ >+# Copyright 2012 ByWater Solutions >+# >+# This file is part of Koha. >+# >+# Koha is free software; you can redistribute it and/or modify it under the >+# terms of the GNU General Public License as published by the Free Software >+# Foundation; either version 2 of the License, or (at your option) any later >+# version. >+# >+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY >+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR >+# A PARTICULAR PURPOSE. See the GNU General Public License for more details. >+# >+# You should have received a copy of the GNU General Public License along >+# with Koha; if not, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use strict; >+use warnings; >+use CGI; >+ >+use C4::Context; >+use C4::Auth; >+use C4::Output; >+ >+use Koha::SMS::Provider; >+ >+my $cgi = new CGI; >+ >+my ( $template, $loggedinuser, $cookie ) = get_template_and_user( >+ { template_name => "admin/sms_providers.tmpl", >+ query => $cgi, >+ type => "intranet", >+ authnotrequired => 0, >+ flagsrequired => { parameters => 'parameters_remaining_permissions' }, >+ debug => 1, >+ } >+); >+ >+my $op = $cgi->param('op'); >+my $id = $cgi->param('id'); >+my $name = $cgi->param('name'); >+my $domain = $cgi->param('domain'); >+ >+if ( $op eq 'add_update' ) { >+ if ( $name && $domain ) { >+ Koha::SMS::Provider->new({ id => $id, name => $name, domain => $domain })->store(); >+ } >+} elsif ( $op eq 'delete' ) { >+ Koha::SMS::Provider->find( $id )->delete(); >+} >+ >+my @providers = Koha::SMS::Provider->all(); >+ >+$template->param( providers => \@providers ); >+ >+output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql >index 29ee782..d93d017 100644 >--- a/installer/data/mysql/kohastructure.sql >+++ b/installer/data/mysql/kohastructure.sql >@@ -262,6 +262,7 @@ CREATE TABLE `borrowers` ( -- this table includes information about your patrons > `altcontactcountry` text default NULL, -- the country for the alternate contact for the patron/borrower > `altcontactphone` varchar(50) default NULL, -- the phone number for the alternate contact for the patron/borrower > `smsalertnumber` varchar(50) default NULL, -- the mobile phone number where the patron/borrower would like to receive notices (if SNS turned on) >+ `sms_provider_id` int(11) DEFAULT NULL, -- the provider of the mobile phone number defined in smsalertnumber > `privacy` integer(11) DEFAULT '1' NOT NULL, -- patron/borrower's privacy settings related to their reading history > UNIQUE KEY `cardnumber` (`cardnumber`), > PRIMARY KEY `borrowernumber` (`borrowernumber`), >@@ -269,8 +270,10 @@ CREATE TABLE `borrowers` ( -- this table includes information about your patrons > KEY `branchcode` (`branchcode`), > KEY `userid` (`userid`), > KEY `guarantorid` (`guarantorid`), >+ KEY `sms_provider_id` (`sms_provider_id`) > CONSTRAINT `borrowers_ibfk_1` FOREIGN KEY (`categorycode`) REFERENCES `categories` (`categorycode`), >- CONSTRAINT `borrowers_ibfk_2` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`) >+ CONSTRAINT `borrowers_ibfk_2` FOREIGN KEY (`branchcode`) REFERENCES `branches` (`branchcode`), >+ CONSTRAINT `borrowers_ibfk_3` FOREIGN KEY (`sms_provider_id`) REFERENCES `sms_providers` (`id`) > ) ENGINE=InnoDB DEFAULT CHARSET=utf8; > > -- >@@ -1815,6 +1818,19 @@ CREATE TABLE sessions ( > ) ENGINE=InnoDB DEFAULT CHARSET=utf8; > > -- >+-- Table structure for table `sms_providers` >+-- >+ >+DROP TABLE IF EXISTS sessions; >+CREATE TABLE `sms_providers` ( >+ `id` int(11) NOT NULL AUTO_INCREMENT, >+ `name` varchar(255) NOT NULL, >+ `domain` varchar(255) NOT NULL, >+ PRIMARY KEY (`id`), >+ UNIQUE KEY `name` (`name`) >+) ENGINE=InnoDB DEFAULT CHARSET=utf8; >+ >+-- > -- Table structure for table `special_holidays` > -- > >diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl >index 7ab48ee..7512856 100755 >--- a/installer/data/mysql/updatedatabase.pl >+++ b/installer/data/mysql/updatedatabase.pl >@@ -6020,6 +6020,25 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) { > SetVersion ($DBversion); > } > >+$DBversion = "3.09.00.XXX"; >+if (C4::Context->preference("Version") < TransformToNum($DBversion)) { >+ $dbh->do(" >+ CREATE TABLE sms_providers ( >+ id INT( 11 ) NOT NULL AUTO_INCREMENT PRIMARY KEY , >+ name VARCHAR( 255 ) NOT NULL , >+ domain VARCHAR( 255 ) NOT NULL , >+ UNIQUE ( >+ name >+ ) >+ ) ENGINE = INNODB CHARACTER SET utf8; >+ "); >+ $dbh->do("ALTER TABLE borrowers ADD sms_provider_id INT( 11 ) NULL DEFAULT NULL AFTER smsalertnumber, ADD INDEX ( sms_provider_id )"); >+ $dbh->do("ALTER TABLE borrowers ADD FOREIGN KEY ( sms_provider_id ) REFERENCES sms_providers ( id )"); >+ >+ print "Upgrade to $DBversion done (Add SMS via Email feature)\n"; >+ SetVersion ($DBversion); >+} >+ > =head1 FUNCTIONS > > =head2 TableExists($table) >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >index cbf3b92..d6af0e0 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/admin-home.tt >@@ -101,14 +101,22 @@ > > <h3>Additional parameters</h3> > <dl> >- [% IF ( NoZebra ) %]<dt><a href="/cgi-bin/koha/admin/stopwords.pl">Stop words</a></dt> >- <dd>Words ignored during search.</dd>[% END %] >- <!-- <dt><a href="/cgi-bin/koha/admin/printers.pl">Network Printers</a></dt> >- <dd>Printers (UNIX paths).</dd> --> >+ [% IF ( NoZebra ) %]<dt><a href="/cgi-bin/koha/admin/stopwords.pl">Stop words</a></dt> >+ <dd>Words ignored during search.</dd> >+ [% END %] >+ <!-- <dt><a href="/cgi-bin/koha/admin/printers.pl">Network Printers</a></dt> >+ <dd>Printers (UNIX paths).</dd> --> >+ > <dt><a href="/cgi-bin/koha/admin/z3950servers.pl">Z39.50 client targets</a></dt> >- <dd>Define which servers to query for MARC data in the integrated Z39.50 client.</dd> >+ <dd>Define which servers to query for MARC data in the integrated Z39.50 client.</dd> >+ > <dt><a href="/cgi-bin/koha/admin/didyoumean.pl">Did you mean?</a></dt> > <dd>Choose which plugins to use to suggest searches to patrons and staff.</dd> >+ >+ [% IF SMSSendDriver == 'Email' %] >+ <dt><a href="/cgi-bin/koha/admin/sms_providers.pl">SMS cellular providers</a></dt> >+ <dd>Define a list of cellular providers for sending SMS messages via email.</dd> >+ [% END %] > </dl> > </div> > >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/sms_providers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/sms_providers.tt >new file mode 100644 >index 0000000..2ef75a8 >--- /dev/null >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/sms_providers.tt >@@ -0,0 +1,102 @@ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>Koha › Administration › SMS cellular providers</title> >+[% INCLUDE 'doc-head-close.inc' %] >+</head> >+ >+<script type="text/javascript"> >+$(document).ready(function() { >+ $('#submit_update').hide(); >+ $("#name").focus(); >+}); >+ >+function edit_provider( id ) { >+ cancel_edit(); >+ >+ $("#id").val( id ); >+ $("#name").val( $("#name_" + id).text() ); >+ $("#domain").val( $("#domain_" + id).text() ); >+ >+ $("#name_" + id).parent().addClass("warn"); >+ >+ $("#submit_save").hide(); >+ $("#submit_update").show(); >+ >+ $("#name").focus(); >+} >+ >+function cancel_edit() { >+ $("#id").val(""); >+ $("#name").val(""); >+ $("#domain").val(""); >+ >+ $("tr").removeClass("warn"); >+ >+ $("#submit_update").hide(); >+ $("#submit_save").show(); >+ >+} >+ >+function delete_provider( id ) { >+ if ( confirm( _("Are you sure you want to delete ") + $("#name_" + id).html() + _("?") ) ) { >+ $("#op").val('delete'); >+ $("#id").val( id ); >+ $("#sms_form").submit(); >+ } >+} >+</script> >+<body id="admin_sms_providers" class="admin"> >+[% INCLUDE 'header.inc' %] >+ >+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> › <a href="/cgi-bin/koha/admin/admin-home.pl">Administration</a> › SMS cellular providers</div> >+ >+<div id="doc3" class="yui-t2"> >+ <div id="bd"> >+ <div id="yui-main"> >+ <div class="yui-b"> >+ <h2>SMS cellular providers</h2> >+ >+ <table> >+ <thead> >+ <tr> >+ <th>Name</th> >+ <th>Domain</th> >+ <th> </th> >+ <th> </th> >+ </tr> >+ </thead> >+ >+ <tbody> >+ [% FOREACH p IN providers %] >+ <tr> >+ <td id="name_[% p.id %]">[% p.name %]</td> >+ <td id="domain_[% p.id %]">[% p.domain %]</td> >+ <td><a href="#" id="edit_[% p.id %]" class="edit" onclick="edit_provider( [% p.id %] );">Edit</td> >+ <td><a href="#" id="delete_[% p.id %]" class="delete" onclick="delete_provider( [% p.id %] );">Delete</td> >+ </tr> >+ [% END %] >+ </tbody> >+ >+ <tfoot> >+ <form id="sms_form" action="sms_providers.pl" method="post"> >+ <input type="hidden" id="id" name="id" value="" /> >+ <input type="hidden" id="op" name="op" value="add_update" /> >+ <tr> >+ <td><input type="text" id="name" name="name" /></td> >+ <td><input type="text" id="domain" name="domain" size="40"/></td> >+ <td> >+ <input id="submit_save" type="submit" value="Add new"> >+ <input id="submit_update" type="submit" value="Update"> >+ </td> >+ <td><a id="cancel" href="#" onclick="cancel_edit()">Cancel</a></td> >+ </tr> >+ </form> >+ </tfoot> >+ </table> >+ </div> >+ </div> >+ <div class="yui-b"> >+ [% INCLUDE 'admin-menu.inc' %] >+ </div> >+ </div> >+</div> >+[% INCLUDE 'intranet-bottom.inc' %] >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt >index e327d03..4422e46 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt >@@ -1441,6 +1441,19 @@ > <input type="text" id="SMSnumber" name="SMSnumber" value="[% SMSnumber %]" /> > [% END %] > </p> >+ <p> >+ <label for="sms_provider_id">SMS provider:</label> >+ <select id="sms_provider_id" name="sms_provider_id"/> >+ <option value="">Unknown</option> >+ [% FOREACH s IN sms_providers %] >+ [% IF s.id == sms_provider_id %] >+ <option value="[% s.id %]" selected="selected">[% s.name %]</option> >+ [% ELSE %] >+ <option value="[% s.id %]">[% s.name %]</option> >+ [% END %] >+ [% END %] >+ </select> >+ </p> > [% END %] > </fieldset> > [% END %] [% END %] >diff --git a/members/memberentry.pl b/members/memberentry.pl >index 9a3dd18..533001d 100755 >--- a/members/memberentry.pl >+++ b/members/memberentry.pl >@@ -41,6 +41,7 @@ use C4::Log; > use C4::Letters; > use C4::Branch; # GetBranches > use C4::Form::MessagingPreferences; >+use Koha::SMS::Provider; > > use vars qw($debug); > >@@ -62,6 +63,12 @@ my ($template, $loggedinuser, $cookie) > flagsrequired => {borrowers => 1}, > debug => ($debug) ? 1 : 0, > }); >+ >+if ( C4::Context->preference('SMSSendDriver') eq 'Email' ) { >+ my @providers = Koha::SMS::Provider->all(); >+ $template->param( sms_providers => \@providers ); >+} >+ > my $guarantorid = $input->param('guarantorid'); > my $borrowernumber = $input->param('borrowernumber'); > my $actionType = $input->param('actionType') || ''; >-- >1.7.2.5
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 9021
:
13290
|
13291
|
13293
|
13294
|
14166
|
14167
|
14363
|
15685
|
15687
|
15689
|
15691
|
16628
|
17311
|
21729
|
22478
|
28488
|
29927
|
32453
|
34180
|
34181
|
35816
|
40720
|
44331
|
45152
|
46163
|
46164
|
46165
|
46168
|
46169
|
46170
|
46171
|
47128
|
47129
|
47130
|
47133
|
47134
|
47135
|
47338
|
47339
|
47814
|
47815
|
47816
|
47817
|
47818
|
47845
|
47846
|
47847
|
47848
|
47995
|
48024
|
48025
|
48026
|
48027
|
48028
|
48029
|
48030
|
48031
|
48032
|
48033
|
48034
|
48035
|
48036
|
48052
|
48053
|
48054
|
48055
|
48056
|
48057
|
48058
|
48059
|
48060
|
48061
|
48062
|
48063
|
48064
|
48065
|
48066