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

(-)a/Koha/Patron/Modification.pm (-3 / +33 lines)
Lines 27-40 use base qw(Koha::Object); Link Here
27
27
28
=head1 NAME
28
=head1 NAME
29
29
30
Koha::Item - Koha Item object class
30
Koha::Patron::Modification - Class represents a requrest to modify or create a patron
31
32
=head1 API
33
31
34
=head2 Class Methods
32
=head2 Class Methods
35
33
36
=cut
34
=cut
37
35
36
=head2 approve
37
38
$m->approve();
39
40
Commits the pending modifications to the borrower record and removes
41
them from the modifications table.
42
43
=cut
44
45
sub approve {
46
    my ($self) = @_;
47
48
    my $data = $self->unblessed();
49
50
    delete $data->{timestamp};
51
    delete $data->{verification_token};
52
53
    foreach my $key ( keys %$data ) {
54
        delete $data->{$key} unless ( defined( $data->{$key} ) );
55
    }
56
57
    my $patron = Koha::Patrons->find( $self->borrowernumber );
58
59
    return unless $patron;
60
61
    $patron->set($data);
62
63
    if ( $patron->store() ) {
64
        return $self->delete();
65
    }
66
}
67
38
=head3 type
68
=head3 type
39
69
40
=cut
70
=cut
(-)a/Koha/Patron/Modifications.pm (-208 / +10 lines)
Lines 25-104 Koha::Patron::Modifications Link Here
25
use Modern::Perl;
25
use Modern::Perl;
26
26
27
use C4::Context;
27
use C4::Context;
28
use C4::Debug;
29
28
30
use base qw(Koha::Objects);
29
use Koha::Patron::Modification;
31
32
=head2 AddModifications
33
34
Koha::Patron::Modifications->AddModifications( $data );
35
36
Adds or updates modifications for a patron
37
38
Requires either the key borrowernumber, or verification_token
39
to be part of the passed in hash.
40
41
=cut
42
43
sub AddModifications {
44
    my ( $self, $data ) = @_;
45
46
    delete $data->{borrowernumber};
47
    if( $self->{borrowernumber} ) {
48
        return if( not keys %$data );
49
        $data->{borrowernumber} = $self->{borrowernumber};
50
        $data->{verification_token} = '';
51
    }
52
    elsif( $self->{verification_token} ) {
53
        $data->{verification_token} = $self->{verification_token};
54
        $data->{borrowernumber} = 0;
55
    }
56
    else {
57
        return;
58
    }
59
30
60
    my $rs = Koha::Database->new()->schema->resultset('BorrowerModification');
31
use base qw(Koha::Objects);
61
    return $rs->update_or_create($data, { key => 'primary' } );
62
}
63
64
=head2 Verify
65
66
$verified = Koha::Patron::Modifications->Verify( $verification_token );
67
68
Returns true if the passed in token is valid.
69
70
=cut
71
72
sub Verify {
73
    my ( $self, $verification_token ) = @_;
74
75
    $verification_token =
76
      ($verification_token)
77
      ? $verification_token
78
      : $self->{'verification_token'};
79
80
    my $dbh   = C4::Context->dbh;
81
    my $query = "
82
        SELECT COUNT(*) AS count
83
        FROM borrower_modifications
84
        WHERE verification_token = ?
85
    ";
86
    my $sth = $dbh->prepare($query);
87
    $sth->execute($verification_token);
88
    my $result = $sth->fetchrow_hashref();
89
90
    return $result->{'count'};
91
}
92
32
93
=head2 GetPendingModificationsCount
33
=head2 pending_count
94
34
95
$count = Koha::Patron::Modifications->GetPendingModificationsCount();
35
$count = Koha::Patron::Modifications->pending_count();
96
36
97
Returns the number of pending modifications for existing patron.
37
Returns the number of pending modifications for existing patrons.
98
38
99
=cut
39
=cut
100
40
101
sub GetPendingModificationsCount {
41
sub pending_count {
102
    my ( $self, $branchcode ) = @_;
42
    my ( $self, $branchcode ) = @_;
103
43
104
    my $dbh   = C4::Context->dbh;
44
    my $dbh   = C4::Context->dbh;
Lines 119-136 sub GetPendingModificationsCount { Link Here
119
    $sth->execute(@params);
59
    $sth->execute(@params);
120
    my $result = $sth->fetchrow_hashref();
60
    my $result = $sth->fetchrow_hashref();
121
61
122
    return $result->{'count'};
62
    return $result->{count};
123
}
63
}
124
64
125
=head2 GetPendingModifications
65
=head2 pending
126
66
127
$arrayref = Koha::Patron::Modifications->GetPendingModifications();
67
$arrayref = Koha::Patron::Modifications->pending();
128
68
129
Returns an arrayref of hashrefs for all pending modifications for existing patrons.
69
Returns an arrayref of hashrefs for all pending modifications for existing patrons.
130
70
131
=cut
71
=cut
132
72
133
sub GetPendingModifications {
73
sub pending {
134
    my ( $self, $branchcode ) = @_;
74
    my ( $self, $branchcode ) = @_;
135
75
136
    my $dbh   = C4::Context->dbh;
76
    my $dbh   = C4::Context->dbh;
Lines 162-305 sub GetPendingModifications { Link Here
162
    return \@m;
102
    return \@m;
163
}
103
}
164
104
165
=head2 ApproveModifications
166
167
Koha::Patron::Modifications->ApproveModifications( $borrowernumber );
168
169
Commits the pending modifications to the borrower record and removes
170
them from the modifications table.
171
172
=cut
173
174
sub ApproveModifications {
175
    my ( $self, $borrowernumber ) = @_;
176
177
    $borrowernumber =
178
      ($borrowernumber) ? $borrowernumber : $self->{'borrowernumber'};
179
180
    return unless $borrowernumber;
181
182
    my $data = $self->GetModifications( { borrowernumber => $borrowernumber } );
183
    delete $data->{timestamp};
184
    delete $data->{verification_token};
185
186
    my $rs = Koha::Database->new()->schema->resultset('Borrower')->search({
187
        borrowernumber => $data->{borrowernumber},
188
    });
189
    if( $rs->update($data) ) {
190
        $self->DelModifications( { borrowernumber => $borrowernumber } );
191
    }
192
}
193
194
=head2 DenyModifications
195
196
Koha::Patron::Modifications->DenyModifications( $borrowernumber );
197
198
Removes the modifications from the table for the given patron,
199
without committing the changes to the patron record.
200
201
=cut
202
203
sub DenyModifications {
204
    my ( $self, $borrowernumber ) = @_;
205
206
    $borrowernumber =
207
      ($borrowernumber) ? $borrowernumber : $self->{'borrowernumber'};
208
209
    return unless $borrowernumber;
210
211
    return $self->DelModifications( { borrowernumber => $borrowernumber } );
212
}
213
214
=head2 DelModifications
215
216
Koha::Patron::Modifications->DelModifications({
217
  [ borrowernumber => $borrowernumber ],
218
  [ verification_token => $verification_token ]
219
});
220
221
Deletes the modifications for the given borrowernumber or verification token.
222
223
=cut
224
225
sub DelModifications {
226
    my ( $self, $params ) = @_;
227
228
    my ( $field, $value );
229
230
    if ( $params->{'borrowernumber'} ) {
231
        $field = 'borrowernumber';
232
        $value = $params->{'borrowernumber'};
233
    }
234
    elsif ( $params->{'verification_token'} ) {
235
        $field = 'verification_token';
236
        $value = $params->{'verification_token'};
237
    }
238
239
    return unless $value;
240
241
    my $dbh = C4::Context->dbh;
242
243
    $field = $dbh->quote_identifier($field);
244
245
    my $query = "
246
        DELETE
247
        FROM borrower_modifications
248
        WHERE $field = ?
249
    ";
250
251
    my $sth = $dbh->prepare($query);
252
    return $sth->execute($value);
253
}
254
255
=head2 GetModifications
256
257
$hashref = Koha::Patron::Modifications->GetModifications({
258
  [ borrowernumber => $borrowernumber ],
259
  [ verification_token => $verification_token ]
260
});
261
262
Gets the modifications for the given borrowernumber or verification token.
263
264
=cut
265
266
sub GetModifications {
267
    my ( $self, $params ) = @_;
268
269
    my ( $field, $value );
270
271
    if ( defined( $params->{'borrowernumber'} ) ) {
272
        $field = 'borrowernumber';
273
        $value = $params->{'borrowernumber'};
274
    }
275
    elsif ( defined( $params->{'verification_token'} ) ) {
276
        $field = 'verification_token';
277
        $value = $params->{'verification_token'};
278
    }
279
280
    return unless $value;
281
282
    my $dbh = C4::Context->dbh;
283
284
    $field = $dbh->quote_identifier($field);
285
286
    my $query = "
287
        SELECT *
288
        FROM borrower_modifications
289
        WHERE $field = ?
290
    ";
291
292
    my $sth = $dbh->prepare($query);
293
    $sth->execute($value);
294
    my $data = $sth->fetchrow_hashref();
295
296
    foreach my $key ( keys %$data ) {
297
        delete $data->{$key} unless ( defined( $data->{$key} ) );
298
    }
299
300
    return $data;
301
}
302
303
sub _type {
105
sub _type {
304
    return 'BorrowerModification';
106
    return 'BorrowerModification';
305
}
107
}
(-)a/mainpage.pl (-2 / +1 lines)
Lines 65-72 my $branch = Link Here
65
my $pendingcomments    = numberofreviews(0);
65
my $pendingcomments    = numberofreviews(0);
66
my $pendingtags        = get_count_by_tag_status(0);
66
my $pendingtags        = get_count_by_tag_status(0);
67
my $pendingsuggestions = CountSuggestion("ASKED");
67
my $pendingsuggestions = CountSuggestion("ASKED");
68
my $pending_borrower_modifications =
68
my $pending_borrower_modifications = Koha::Patron::Modifications->pending_count( $branch );
69
  Koha::Patron::Modifications->GetPendingModificationsCount( $branch );
70
my $pending_discharge_requests = Koha::Patron::Discharge::count({ pending => 1 });
69
my $pending_discharge_requests = Koha::Patron::Discharge::count({ pending => 1 });
71
70
72
$template->param(
71
$template->param(
(-)a/members/members-home.pl (-1 / +1 lines)
Lines 89-95 else { Link Here
89
89
90
90
91
my $pending_borrower_modifications =
91
my $pending_borrower_modifications =
92
  Koha::Patron::Modifications->GetPendingModificationsCount( $branch );
92
  Koha::Patron::Modifications->pending_count( $branch );
93
93
94
$template->param( 
94
$template->param( 
95
        no_add => $no_add,
95
        no_add => $no_add,
(-)a/members/members-update-do.pl (-5 / +5 lines)
Lines 50-63 foreach my $param (@params) { Link Here
50
        my $action = $query->param($param);
50
        my $action = $query->param($param);
51
51
52
        if ( $action eq 'approve' ) {
52
        if ( $action eq 'approve' ) {
53
            Koha::Patron::Modifications->ApproveModifications( $borrowernumber );
53
            my $m = Koha::Patron::Modifications->find( { borrowernumber => $borrowernumber } );
54
            $m->approve() if $m;
54
        }
55
        }
55
        elsif ( $action eq 'deny' ) {
56
        elsif ( $action eq 'deny' ) {
56
            Koha::Patron::Modifications->DenyModifications( $borrowernumber );
57
            my $m = Koha::Patron::Modifications->find( { borrowernumber => $borrowernumber } );
57
        }
58
            $m->delete() if $m;
58
        elsif ( $action eq 'ignore' ) {
59
60
        }
59
        }
60
        # elsif ( $action eq 'ignore' ) { }
61
    }
61
    }
62
}
62
}
63
63
(-)a/members/members-update.pl (-1 / +1 lines)
Lines 49-55 my $branch = Link Here
49
  : undef;
49
  : undef;
50
50
51
my $pending_modifications =
51
my $pending_modifications =
52
  Koha::Patron::Modifications->GetPendingModifications($branch);
52
  Koha::Patron::Modifications->pending($branch);
53
53
54
my $borrowers;
54
my $borrowers;
55
foreach my $pm (@$pending_modifications) {
55
foreach my $pm (@$pending_modifications) {
(-)a/opac/opac-memberentry.pl (-9 / +8 lines)
Lines 27-32 use C4::Output; Link Here
27
use C4::Members;
27
use C4::Members;
28
use C4::Form::MessagingPreferences;
28
use C4::Form::MessagingPreferences;
29
use Koha::Patrons;
29
use Koha::Patrons;
30
use Koha::Patron::Modification;
30
use Koha::Patron::Modifications;
31
use Koha::Patron::Modifications;
31
use C4::Branch qw(GetBranchesLoop);
32
use C4::Branch qw(GetBranchesLoop);
32
use C4::Scrubber;
33
use C4::Scrubber;
Lines 127-137 if ( $action eq 'create' ) { Link Here
127
            $template->param( 'email' => $borrower{'email'} );
128
            $template->param( 'email' => $borrower{'email'} );
128
129
129
            my $verification_token = md5_hex( \%borrower );
130
            my $verification_token = md5_hex( \%borrower );
130
            $borrower{'password'} = random_string("..........");
131
131
132
            Koha::Patron::Modifications->new(
132
            $borrower{password}           = random_string("..........");
133
                verification_token => $verification_token )
133
            $borrower{verification_token} = $verification_token;
134
              ->AddModifications(\%borrower);
134
135
            Koha::Patron::Modification->new( \%borrower )->store();
135
136
136
            #Send verification email
137
            #Send verification email
137
            my $letter = C4::Letters::GetPreparedLetter(
138
            my $letter = C4::Letters::GetPreparedLetter(
Lines 224-235 elsif ( $action eq 'update' ) { Link Here
224
                }
225
                }
225
            );
226
            );
226
227
227
            my $m =
228
            $borrower_changes{borrowernumber} = $borrowernumber;
228
              Koha::Patron::Modifications->new(
229
229
                borrowernumber => $borrowernumber );
230
            my $m = Koha::Patron::Modification->new( \%borrower_changes )->store();
230
231
231
            $m->DelModifications;
232
            $m->AddModifications(\%borrower_changes);
233
            $template->param(
232
            $template->param(
234
                borrower => GetMember( borrowernumber => $borrowernumber ),
233
                borrower => GetMember( borrowernumber => $borrowernumber ),
235
            );
234
            );
(-)a/opac/opac-registration-verify.pl (-4 / +4 lines)
Lines 34-43 unless ( C4::Context->preference('PatronSelfRegistration') ) { Link Here
34
}
34
}
35
35
36
my $token = $cgi->param('token');
36
my $token = $cgi->param('token');
37
my $m = Koha::Patron::Modifications->new( verification_token => $token );
37
my $m = Koha::Patron::Modifications->find( { verification_token => $token } );
38
38
39
my ( $template, $borrowernumber, $cookie );
39
my ( $template, $borrowernumber, $cookie );
40
if ( $m->Verify() ) {
40
if ( $m ) {
41
    ( $template, $borrowernumber, $cookie ) = get_template_and_user(
41
    ( $template, $borrowernumber, $cookie ) = get_template_and_user(
42
        {
42
        {
43
            template_name   => "opac-registration-confirmation.tt",
43
            template_name   => "opac-registration-confirmation.tt",
Lines 50-62 if ( $m->Verify() ) { Link Here
50
    $template->param(
50
    $template->param(
51
        OpacPasswordChange => C4::Context->preference('OpacPasswordChange') );
51
        OpacPasswordChange => C4::Context->preference('OpacPasswordChange') );
52
52
53
    my $borrower = Koha::Patron::Modifications->GetModifications({ verification_token => $token });
53
    my $borrower = $m->unblessed();
54
54
55
    my $password;
55
    my $password;
56
    ( $borrowernumber, $password ) = AddMember_Opac(%$borrower);
56
    ( $borrowernumber, $password ) = AddMember_Opac(%$borrower);
57
57
58
    if ($borrowernumber) {
58
    if ($borrowernumber) {
59
        Koha::Patron::Modifications->DelModifications({ verification_token => $token });
59
        $m->delete();
60
        C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if C4::Context->preference('EnhancedMessagingPreferences');
60
        C4::Form::MessagingPreferences::handle_form_action($cgi, { borrowernumber => $borrowernumber }, $template, 1, C4::Context->preference('PatronSelfRegistrationDefaultCategory') ) if C4::Context->preference('EnhancedMessagingPreferences');
61
61
62
        $template->param( password_cleartext => $password );
62
        $template->param( password_cleartext => $password );
(-)a/t/db_dependent/Koha_borrower_modifications.t (-90 / +48 lines)
Lines 1-133 Link Here
1
#!/usr/bin/perl
1
#!/usr/bin/perl
2
2
3
use Modern::Perl;
3
use Modern::Perl;
4
use Test::More tests => 14;
4
use Test::More tests => 8;
5
5
6
use C4::Context;
6
use C4::Context;
7
use t::lib::TestBuilder;
7
use t::lib::TestBuilder;
8
use C4::Members;
8
use C4::Members;
9
9
10
use Koha::Patron::Modifications;
10
BEGIN {
11
    use_ok('Koha::Patron::Modification');
12
    use_ok('Koha::Patron::Modifications');
13
}
11
14
12
my $dbh = C4::Context->dbh;
15
my $schema = Koha::Database->new->schema;
13
$dbh->{RaiseError} = 1;
16
$schema->storage->txn_begin;
14
$dbh->{AutoCommit} = 0;
15
17
18
my $dbh = C4::Context->dbh;
16
$dbh->do("DELETE FROM borrower_modifications");
19
$dbh->do("DELETE FROM borrower_modifications");
17
20
18
## Create new pending modification
21
## Create new pending modification
19
Koha::Patron::Modifications->new( verification_token => '1234567890' )
22
Koha::Patron::Modification->new(
20
  ->AddModifications( { surname => 'Hall', firstname => 'Kyle' } );
23
    {
24
        verification_token => '1234567890',
25
        surname            => 'Hall',
26
        firstname          => 'Kyle'
27
    }
28
)->store();
21
29
22
## Get the new pending modification
30
## Get the new pending modification
23
my $borrower = Koha::Patron::Modifications->GetModifications(
31
my $borrower =
24
    { verification_token => '1234567890' } );
32
  Koha::Patron::Modifications->find( { verification_token => '1234567890' } );
25
33
26
## Verify we get the same data
34
## Verify we get the same data
27
ok( $borrower->{'surname'} = 'Hall',
35
is( $borrower->surname, 'Hall', 'Found modification has matching surname' );
28
    'Test AddModifications() and GetModifications()' );
29
30
## Check the Verify method
31
ok(
32
    Koha::Patron::Modifications->Verify('1234567890'),
33
    'Test that Verify() succeeds with a valid token'
34
);
35
36
## Delete the pending modification
37
$borrower = Koha::Patron::Modifications->DelModifications(
38
    { verification_token => '1234567890' } );
39
40
## Verify it's no longer in the database
41
$borrower = Koha::Patron::Modifications->GetModifications(
42
    { verification_token => '1234567890' } );
43
ok( !defined( $borrower->{'surname'} ), 'Test DelModifications()' );
44
45
## Check the Verify method
46
ok(
47
    !Koha::Patron::Modifications->Verify('1234567890'),
48
    'Test that Verify() method fails for a bad token'
49
);
50
36
51
## Create new pending modification for a patron
37
## Create new pending modification for a patron
52
my $builder = t::lib::TestBuilder->new;
38
my $builder = t::lib::TestBuilder->new;
53
my $borr1 = $builder->build({ source => 'Borrower' })->{borrowernumber};
39
my $borr1 = $builder->build( { source => 'Borrower' } )->{borrowernumber};
54
Koha::Patron::Modifications->new( borrowernumber => $borr1 )
40
55
  ->AddModifications( { surname => 'Hall', firstname => 'Kyle' } );
41
my $m1 = Koha::Patron::Modification->new(
42
    {
43
        borrowernumber => $borr1,
44
        surname        => 'Hall',
45
        firstname      => 'Kyle'
46
    }
47
)->store();
56
48
57
## Test the counter
49
## Test the counter
58
ok( Koha::Patron::Modifications->GetPendingModificationsCount() == 1,
50
is( Koha::Patron::Modifications->pending_count,
59
    'Test GetPendingModificationsCount()' );
51
    1, 'Test pending_count()' );
60
52
61
## Create new pending modification for another patron
53
## Create new pending modification for another patron
62
my $borr2 = $builder->build({ source => 'Borrower' })->{borrowernumber};
54
my $borr2 = $builder->build( { source => 'Borrower' } )->{borrowernumber};
63
Koha::Patron::Modifications->new( borrowernumber => $borr2 )
55
my $m2 = Koha::Patron::Modification->new(
64
  ->AddModifications( { surname => 'Smith', firstname => 'Sandy' } );
56
    {
57
        borrowernumber => $borr2,
58
        surname        => 'Smith',
59
        firstname      => 'Sandy'
60
    }
61
)->store();
65
62
66
## Test the counter
63
## Test the counter
67
ok(
64
is(
68
    Koha::Patron::Modifications->GetPendingModificationsCount() == 2,
65
    Koha::Patron::Modifications->pending_count(), 2,
69
'Add a new pending modification and test GetPendingModificationsCount() again'
66
'Add a new pending modification and test pending_count() again'
70
);
67
);
71
68
72
## Check GetPendingModifications
69
## Check GetPendingModifications
73
my $pendings = Koha::Patron::Modifications->GetPendingModifications();
70
my $pendings = Koha::Patron::Modifications->pending;
74
my @firstnames_mod = sort ( $pendings->[0]->{firstname}, $pendings->[1]->{firstname} );
71
my @firstnames_mod =
75
ok( $firstnames_mod[0] eq 'Kyle', 'Test GetPendingModifications()' );
72
  sort ( $pendings->[0]->{firstname}, $pendings->[1]->{firstname} );
76
ok( $firstnames_mod[1] eq 'Sandy', 'Test GetPendingModifications() again' );
73
ok( $firstnames_mod[0] eq 'Kyle',  'Test pending()' );
74
ok( $firstnames_mod[1] eq 'Sandy', 'Test pending() again' );
77
75
78
## This should delete the row from the table
76
## This should delete the row from the table
79
Koha::Patron::Modifications->DenyModifications( $borr2 );
77
$m2->delete();
80
81
## Test the counter
82
ok( Koha::Patron::Modifications->GetPendingModificationsCount() == 1,
83
    'Test DenyModifications()' );
84
78
85
## Save a copy of the borrowers original data
79
## Save a copy of the borrowers original data
86
my $old_borrower = GetMember( borrowernumber => $borr1 );
80
my $old_borrower = GetMember( borrowernumber => $borr1 );
87
81
88
## Apply the modifications
82
## Apply the modifications
89
Koha::Patron::Modifications->ApproveModifications( $borr1 );
83
$m1->approve();
90
91
## Test the counter
92
ok(
93
    Koha::Patron::Modifications->GetPendingModificationsCount() == 0,
94
    'Test ApproveModifications() removes pending modification from db'
95
);
96
84
97
## Get a copy of the borrowers current data
85
## Get a copy of the borrowers current data
98
my $new_borrower = GetMember( borrowernumber => $borr1 );
86
my $new_borrower = GetMember( borrowernumber => $borr1 );
99
87
100
## Check to see that the approved modifications were saved
88
## Check to see that the approved modifications were saved
101
ok( $new_borrower->{'surname'} eq 'Hall',
89
ok( $new_borrower->{'surname'} eq 'Hall',
102
    'Test ApproveModifications() applys modification to borrower' );
90
    'Test approve() applys modification to borrower' );
103
104
## Now let's put it back the way it was
105
Koha::Patron::Modifications->new( borrowernumber => $borr1 )->AddModifications(
106
    {
107
        surname   => $old_borrower->{'surname'},
108
        firstname => $old_borrower->{'firstname'}
109
    }
110
);
111
112
## Test the counter
113
ok( Koha::Patron::Modifications->GetPendingModificationsCount() == 1,
114
    'Test GetPendingModificationsCount()' );
115
116
## Apply the modifications
117
Koha::Patron::Modifications->ApproveModifications( $borr1 );
118
119
## Test the counter
120
ok(
121
    Koha::Patron::Modifications->GetPendingModificationsCount() == 0,
122
    'Test ApproveModifications() removes pending modification from db, again'
123
);
124
125
$new_borrower = GetMember( borrowernumber => $borr1 );
126
127
## Test to verify the borrower has been updated with the original values
128
ok(
129
    $new_borrower->{'surname'} eq $old_borrower->{'surname'},
130
    'Test ApproveModifications() applys modification to borrower, again'
131
);
132
91
133
$dbh->rollback();
92
$dbh->rollback();
134
- 

Return to bug 16960