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

(-)a/Koha/Patron/Message/Preference.pm (+51 lines)
Lines 281-286 sub store { Link Here
281
    return $self;
281
    return $self;
282
}
282
}
283
283
284
sub TO_JSON {
285
    my ($self, $params) = @_;
286
287
    my $json = {};
288
    my $pref;
289
    $params->{'options'} ||= Koha::Patron::Message::Preferences->get_options;
290
    my $transports = $self->message_transport_types;
291
292
    foreach my $option (@{$params->{'options'}}) {
293
        foreach my $param (keys %$option) {
294
            if ($param eq 'message_attribute_id' &&
295
                    $option->{$param} == $self->message_attribute_id) {
296
                $pref = $option;
297
                last;
298
            }
299
        }
300
    }
301
302
    foreach my $conf (keys %$pref) {
303
        if ($conf =~ /^transport_/) {
304
            my $mtt = $conf =~ s/^transport_//r;
305
            if ($mtt eq 'sms' && !C4::Context->preference('SMSSendDriver')) {
306
                next;
307
            }
308
            if ($mtt eq 'phone' &&
309
                !C4::Context->preference('TalkingTechItivaPhoneNotification')) {
310
                next;
311
            }
312
            $json->{'transport_types'}->{$mtt} = $transports->{$mtt} ?
313
                                Mojo::JSON->true : Mojo::JSON->false;
314
        }
315
    }
316
317
    $json->{'days_in_advance'} = {
318
        configurable => $pref->{'takes_days'} ?
319
                                Mojo::JSON->true : Mojo::JSON->false,
320
        value => defined $self->days_in_advance ?
321
                                0+$self->days_in_advance : undef
322
    };
323
    $json->{'digest'} = {
324
        configurable => $self->wants_digest
325
                            ? $pref->{'has_digest_off'} # can digest be unchecked?
326
                                    ? Mojo::JSON->true : Mojo::JSON->false
327
                            : $pref->{'has_digest'}     # can digest be checked?
328
                                    ? Mojo::JSON->true : Mojo::JSON->false,
329
        value => $self->wants_digest ? Mojo::JSON->true : Mojo::JSON->false
330
    };
331
332
    return $json;
333
}
334
284
=head3 validate
335
=head3 validate
285
336
286
Makes a basic validation for object.
337
Makes a basic validation for object.
(-)a/Koha/Patron/Message/Preferences.pm (+29 lines)
Lines 125-130 sub search_with_message_name { Link Here
125
    return $self->SUPER::search($params, $attributes);
125
    return $self->SUPER::search($params, $attributes);
126
}
126
}
127
127
128
sub TO_JSON {
129
    my ($self) = @_;
130
131
    my $preferences = {};
132
    my $options = $self->get_options;
133
    foreach my $preference ($self->as_list) {
134
        $preferences->{$preference->message_name} = $preference->TO_JSON({
135
            options => $options
136
        });
137
    }
138
139
    # If some preferences are not stored even though they are valid options,
140
    # then add those options to the returned HASHref as well
141
    foreach my $option (@$options) {
142
        unless ($preferences->{$option->{'message_name'}}) {
143
            my $message_attribute_id = Koha::Patron::Message::Attributes->find({
144
                message_name => $option->{'message_name'}
145
            })->message_attribute_id;
146
            $preferences->{$option->{'message_name'}} =
147
                Koha::Patron::Message::Preference->new({
148
                    borrowernumber => -1,
149
                    message_attribute_id => $message_attribute_id,
150
                })->TO_JSON({ options => $options });
151
        }
152
    }
153
154
    return $preferences;
155
}
156
128
=head3 type
157
=head3 type
129
158
130
=cut
159
=cut
(-)a/Koha/REST/V1/Patron/Message/Preference.pm (+164 lines)
Line 0 Link Here
1
package Koha::REST::V1::Patron::Message::Preference;
2
3
# This file is part of Koha.
4
#
5
# Koha is free software; you can redistribute it and/or modify it under the
6
# terms of the GNU General Public License as published by the Free Software
7
# Foundation; either version 3 of the License, or (at your option) any later
8
# version.
9
#
10
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License along
15
# with Koha; if not, write to the Free Software Foundation, Inc.,
16
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18
use Modern::Perl;
19
20
use Mojo::Base 'Mojolicious::Controller';
21
22
use Koha::Patron::Message::Attributes;
23
use Koha::Patron::Message::Preferences;
24
use Koha::Patron::Message::Transport::Types;
25
use Koha::Patron::Message::Transports;
26
27
use Try::Tiny;
28
29
sub list {
30
    my $c = shift->openapi->valid_input or return;
31
32
    my $enabled = _check_system_preferences($c);
33
    return $enabled if $enabled;
34
35
    my $borrowernumber = $c->validation->param('borrowernumber');
36
    my $categorycode   = $c->validation->param('categorycode');
37
38
    my $found = $borrowernumber
39
        ? Koha::Patrons->find($borrowernumber)
40
        : Koha::Patron::Categories->find($categorycode);
41
42
    return try {
43
        die unless $found;
44
        my $preferences = Koha::Patron::Message::Preferences->search({
45
            borrowernumber => $borrowernumber,
46
            categorycode   => $categorycode,
47
        });
48
49
        return $c->render(status => 200, openapi => $preferences);
50
    }
51
    catch {
52
        unless ($found) {
53
            return $c->render( status  => 400, openapi => {
54
                error => "Patron or category not found" } );
55
        }
56
        Koha::Exceptions::rethrow_exception($_);
57
    };
58
}
59
60
sub edit {
61
    my $c = shift->openapi->valid_input or return;
62
63
    my $enabled = _check_system_preferences($c);
64
    return $enabled if $enabled;
65
66
    my $borrowernumber = $c->validation->param('borrowernumber');
67
    my $categorycode   = $c->validation->param('categorycode');
68
    my $body           = $c->validation->param('body');
69
70
    my $found = $borrowernumber
71
        ? Koha::Patrons->find($borrowernumber)
72
        : Koha::Patron::Categories->find($categorycode);
73
74
    return try {
75
        die unless $found;
76
        foreach my $in (keys %{$body}) {
77
            my $preference =
78
                Koha::Patron::Message::Preferences->find_with_message_name({
79
                    borrowernumber => $borrowernumber,
80
                    categorycode => $categorycode,
81
                    message_name => $in
82
                });
83
84
            # Format wants_digest and days_in_advance values
85
            my $wants_digest = $body->{$in}->{'digest'} ?
86
                $body->{$in}->{'digest'}->{'value'} ? 1 : 0 : 0;
87
            my $days_in_advance = $body->{$in}->{'days_in_advance'} ?
88
                defined $body->{$in}->{'days_in_advance'}->{'value'} ?
89
                    $body->{$in}->{'days_in_advance'}->{'value'} : undef : undef;
90
91
            # HASHref for updated preference
92
            my @transport_types;
93
            foreach my $mtt (keys %{$body->{$in}->{'transport_types'}}) {
94
                if ($body->{$in}->{'transport_types'}->{$mtt}) {
95
                    push @transport_types, $mtt;
96
                }
97
            }
98
            my $edited_preference = {
99
                wants_digest => $wants_digest,
100
                days_in_advance => $days_in_advance,
101
                message_transport_types => \@transport_types
102
            };
103
104
            # Unless a preference for this message name exists, create it
105
            unless ($preference) {
106
                my $attr = Koha::Patron::Message::Attributes->find({
107
                    message_name => $in
108
                });
109
                unless ($attr) {
110
                    Koha::Exceptions::BadParameter->throw(
111
                        error => "Message type $in not found."
112
                    );
113
                }
114
                $edited_preference->{'message_attribute_id'} =
115
                        $attr->message_attribute_id;
116
                if ($borrowernumber) {
117
                    $edited_preference->{'borrowernumber'}=$found->borrowernumber;
118
                } else {
119
                    $edited_preference->{'categorycode'}=$found->categorycode;
120
                }
121
                Koha::Patron::Message::Preference->new($edited_preference)->store;
122
            }
123
            # Otherwise, modify the already-existing one
124
            else {
125
                $preference->set($edited_preference)->store;
126
            }
127
        }
128
129
        # Finally, return the preferences
130
        my $preferences = Koha::Patron::Message::Preferences->search({
131
            borrowernumber => $borrowernumber,
132
            categorycode   => $categorycode,
133
        });
134
135
        return $c->render( status => 200, openapi => $preferences);
136
    }
137
    catch {
138
        unless ($found) {
139
            return $c->render( status  => 400, openapi => {
140
                error => "Patron or category not found" } );
141
        }
142
        if ($_->isa('Koha::Exceptions::BadParameter')) {
143
            return $c->render( status => 400, openapi => { error => $_->error });
144
        }
145
        Koha::Exceptions::rethrow_exception($_);
146
    };
147
}
148
149
sub _check_system_preferences {
150
    my $c = shift;
151
    if ( ! C4::Context->preference('EnhancedMessagingPreferences') ) {
152
        return $c->render( status => 403, openapi => {
153
            error => "Enhanced messaging preferences are not enabled"});
154
    }
155
    if (($c->stash('is_owner_access') || $c->stash('is_guarantor_access'))
156
        && ! C4::Context->preference('EnhancedMessagingPreferencesOPAC')) {
157
        return $c->render( status => 403, openapi => {
158
            error => "Patrons does not have access to enhanced messaging"
159
                    ." preferences" });
160
    }
161
    return;
162
}
163
164
1;
(-)a/api/v1/swagger/definitions.json (+3 lines)
Lines 11-16 Link Here
11
  "holds": {
11
  "holds": {
12
    "$ref": "definitions/holds.json"
12
    "$ref": "definitions/holds.json"
13
  },
13
  },
14
  "messagingpreference": {
15
    "$ref": "definitions/messagingpreference.json"
16
  },
14
  "patron": {
17
  "patron": {
15
    "$ref": "definitions/patron.json"
18
    "$ref": "definitions/patron.json"
16
  }
19
  }
(-)a/api/v1/swagger/definitions/messagingpreference.json (+20 lines)
Line 0 Link Here
1
{
2
  "type": "object",
3
  "properties": {
4
    "Item_Due": {
5
      "$ref": "messagingpreference/transport.json"
6
    },
7
    "Advance_Notice": {
8
      "$ref": "messagingpreference/transport.json"
9
    },
10
    "Hold_Filled": {
11
      "$ref": "messagingpreference/transport.json"
12
    },
13
    "Item_Check_in": {
14
      "$ref": "messagingpreference/transport.json"
15
    },
16
    "Item_Checkout": {
17
      "$ref": "messagingpreference/transport.json"
18
    }
19
  }
20
}
(-)a/api/v1/swagger/definitions/messagingpreference/transport.json (+52 lines)
Line 0 Link Here
1
{
2
  "type": "object",
3
  "properties": {
4
    "transport_types": {
5
      "type": "object",
6
      "properties": {
7
        "email": {
8
          "type": "boolean"
9
        },
10
        "phone": {
11
          "type": "boolean"
12
        },
13
        "print": {
14
          "type": "boolean"
15
        },
16
        "sms": {
17
          "type": "boolean"
18
        }
19
      }
20
    },
21
    "days_in_advance": {
22
      "type": "object",
23
      "properties": {
24
        "configurable": {
25
          "description": "Can this message have a value for days in advance",
26
          "type": "boolean",
27
          "readOnly": true
28
        },
29
        "value": {
30
          "type": ["integer", "null"],
31
          "minimum": 0,
32
          "maximum": 30
33
        }
34
      }
35
    },
36
    "digest": {
37
      "type": "object",
38
      "properties": {
39
        "configurable": {
40
          "description": "Can this message be requested as digest",
41
          "type": "boolean",
42
          "readOnly": true
43
        },
44
        "value": {
45
          "description": "Is digest enabled",
46
          "type": "boolean"
47
        }
48
      }
49
    }
50
  },
51
  "additionalProperties": false
52
}
(-)a/api/v1/swagger/paths.json (+3 lines)
Lines 11-16 Link Here
11
  "/holds/{reserve_id}": {
11
  "/holds/{reserve_id}": {
12
    "$ref": "paths/holds.json#/~1holds~1{reserve_id}"
12
    "$ref": "paths/holds.json#/~1holds~1{reserve_id}"
13
  },
13
  },
14
  "/messaging_preferences": {
15
    "$ref": "paths/messagingpreferences.json#/~1messaging_preferences"
16
  },
14
  "/patrons": {
17
  "/patrons": {
15
    "$ref": "paths/patrons.json#/~1patrons"
18
    "$ref": "paths/patrons.json#/~1patrons"
16
  },
19
  },
(-)a/api/v1/swagger/paths/messagingpreferences.json (+155 lines)
Line 0 Link Here
1
{
2
  "/messaging_preferences": {
3
    "get": {
4
      "x-mojo-to": "Patron::Message::Preference#list",
5
      "operationId": "listMessagingPreferences",
6
      "x-koha-authorization": {
7
        "permissions": {
8
          "borrowers": "*"
9
        },
10
        "allow-owner": true,
11
        "allow-guarantor": true
12
      },
13
      "tags": ["notices"],
14
      "parameters": [{
15
        "name": "borrowernumber",
16
        "in": "query",
17
        "description": "Patron's borrowernumber",
18
        "required": false,
19
        "type": "integer"
20
      }, {
21
        "name": "categorycode",
22
        "in": "query",
23
        "description": "Categorycode to find default messaging preferences for a category",
24
        "required": false,
25
        "type": "string"
26
      }],
27
      "produces": [
28
        "application/json"
29
      ],
30
      "responses": {
31
        "200": {
32
          "description": "A messaging preference object",
33
          "schema": {
34
              "$ref" : "../definitions.json#/messagingpreference"
35
          }
36
        },
37
        "400": {
38
          "description": "Bad parameter given",
39
          "schema": {
40
            "$ref": "../definitions.json#/error"
41
          }
42
        },
43
        "401": {
44
          "description": "Authentication required",
45
          "schema": {
46
            "$ref": "../definitions.json#/error"
47
          }
48
        },
49
        "403": {
50
          "description": "Access forbidden",
51
          "schema": {
52
            "$ref": "../definitions.json#/error"
53
          }
54
        },
55
        "404": {
56
          "description": "Preferences not found",
57
          "schema": {
58
            "$ref": "../definitions.json#/error"
59
          }
60
        },
61
        "500": {
62
          "description": "Internal error",
63
          "schema": {
64
            "$ref": "../definitions.json#/error"
65
          }
66
        },
67
        "503": {
68
          "description": "Under maintenance",
69
          "schema": {
70
            "$ref": "../definitions.json#/error"
71
          }
72
        }
73
      }
74
    },
75
    "put": {
76
      "x-mojo-to": "Patron::Message::Preference#edit",
77
      "operationId": "editMessagingPreferences",
78
      "description": "Modifies patron's messaging preferences. Please note that not all parameters defined in body object's documentation can actually be used for each message option due to dynamic configuration. Make a GET request first to see whether an option is configurable or if message transport type is available.",
79
      "x-koha-authorization": {
80
        "permissions": {
81
          "borrowers": "*"
82
        },
83
        "allow-owner": true,
84
        "allow-guarantor": true
85
      },
86
      "tags": ["notices"],
87
      "parameters": [
88
        {
89
          "name": "borrowernumber",
90
          "in": "query",
91
          "description": "Patron's borrowernumber",
92
          "required": false,
93
          "type": "integer"
94
        }, {
95
          "name": "categorycode",
96
          "in": "query",
97
          "description": "Categorycode to find default messaging preferences for a category",
98
          "required": false,
99
          "type": "string"
100
        }, {
101
          "name": "body",
102
          "in": "body",
103
          "description": "A JSON object containing information on messaging preferences",
104
          "required": true,
105
          "schema": { "$ref" : "../definitions.json#/messagingpreference" }
106
        }
107
      ],
108
      "produces": [
109
        "application/json"
110
      ],
111
      "responses": {
112
        "200": {
113
          "description": "A messaging preferences object",
114
          "schema": {
115
              "$ref" : "../definitions.json#/messagingpreference"
116
          }
117
        },
118
        "400": {
119
          "description": "Missing or wrong parameters",
120
          "schema": { "$ref": "../definitions.json#/error" }
121
        },
122
        "401": {
123
          "description": "Authentication required",
124
          "schema": {
125
            "$ref": "../definitions.json#/error"
126
          }
127
        },
128
        "403": {
129
          "description": "Access forbidden",
130
          "schema": {
131
            "$ref": "../definitions.json#/error"
132
          }
133
        },
134
        "404": {
135
          "description": "Patron or category not found",
136
          "schema": {
137
            "$ref": "../definitions.json#/error"
138
          }
139
        },
140
        "500": {
141
          "description": "Internal error",
142
          "schema": {
143
            "$ref": "../definitions.json#/error"
144
          }
145
        },
146
        "503": {
147
          "description": "Under maintenance",
148
          "schema": {
149
            "$ref": "../definitions.json#/error"
150
          }
151
        }
152
      }
153
    }
154
  }
155
}
(-)a/t/db_dependent/api/v1/messagingpreferences.t (-1 / +417 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/env perl
2
3
# Copyright Koha-Suomi Oy 2017
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use Modern::Perl;
21
22
23
use Test::More tests => 2;
24
use Test::Mojo;
25
use t::lib::Mocks;
26
use t::lib::TestBuilder;
27
28
use C4::Auth;
29
use C4::Context;
30
31
use Koha::Database;
32
use Koha::Notice::Templates;
33
use Koha::Patron::Message::Preferences;
34
35
my $schema  = Koha::Database->new->schema;
36
my $builder = t::lib::TestBuilder->new;
37
38
# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling
39
# this affects the other REST api tests
40
t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' );
41
42
my $remote_address = '127.0.0.1';
43
my $t              = Test::Mojo->new('Koha::REST::V1');
44
45
subtest 'list() tests' => sub {
46
    plan tests => 34;
47
48
    $schema->storage->txn_begin;
49
50
    my $path = '/api/v1/messaging_preferences';
51
52
    my ($patron, $session) = create_user_and_session();
53
    my $borrowernumber = $patron->borrowernumber;
54
    my $categorycode   = $patron->categorycode;
55
    my ($another_patron, undef) = create_user_and_session();
56
    my ($librarian, $librarian_session) = create_user_and_session({
57
        flags => 16
58
    });
59
    my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
60
        patron => $patron
61
    });
62
    my ($preference2, $mtt1_2, $mtt2_2) = build_a_test_category_preference({
63
        patron => $patron
64
    });
65
66
    t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1);
67
    my $tx = $t->ua->build_tx(GET => $path);
68
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
69
    $t->request_ok($tx)
70
      ->status_is(401);
71
72
    $tx = $t->ua->build_tx(GET => "$path?borrowernumber="
73
                           .$another_patron->borrowernumber);
74
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
75
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
76
    $t->request_ok($tx)
77
      ->status_is(403);
78
79
    $tx = $t->ua->build_tx(GET => "$path?categorycode=$categorycode");
80
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
81
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
82
    $t->request_ok($tx)
83
      ->status_is(403);
84
85
    $tx = $t->ua->build_tx(GET => $path);
86
    $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id});
87
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
88
    $t->request_ok($tx)
89
      ->status_is(400)
90
      ->json_is('/error', 'Patron or category not found');
91
92
    t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 0);
93
    $tx = $t->ua->build_tx(GET => "$path?borrowernumber=$borrowernumber");
94
    $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id});
95
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
96
    $t->request_ok($tx)
97
      ->status_is(403)
98
      ->json_is('/error' => 'Enhanced messaging preferences are not enabled');
99
    t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1);
100
101
    $tx = $t->ua->build_tx(GET => "$path?borrowernumber=$borrowernumber");
102
    $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id});
103
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
104
    $t->request_ok($tx)
105
      ->status_is(200)
106
      ->json_has('/'.$preference->message_name);
107
108
    $tx = $t->ua->build_tx(GET => "$path?borrowernumber=$borrowernumber");
109
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
110
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
111
    $t->request_ok($tx)
112
      ->status_is(200)
113
      ->json_has('/'.$preference->message_name)
114
      ->json_has('/'.$preference2->message_name)
115
      ->json_is('/'.$preference->message_name.'/transport_types/'
116
                .$mtt1->message_transport_type => Mojo::JSON->true)
117
      ->json_is('/'.$preference->message_name.'/transport_types/'
118
                .$mtt2->message_transport_type => Mojo::JSON->true)
119
      ->json_is('/'.$preference->message_name.'/days_in_advance/configurable'
120
                => Mojo::JSON->false)
121
      ->json_is('/'.$preference->message_name.'/days_in_advance/value'
122
                => undef)
123
      ->json_is('/'.$preference->message_name.'/digest/configurable'
124
                => Mojo::JSON->false)
125
      ->json_is('/'.$preference->message_name.'/digest/value'
126
                => Mojo::JSON->false);
127
128
    $tx = $t->ua->build_tx(GET => "$path?categorycode=$categorycode");
129
    $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id});
130
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
131
    $t->request_ok($tx)
132
      ->status_is(200)
133
      ->json_has('/'.$preference->message_name)
134
      ->json_has('/'.$preference2->message_name)
135
      ->json_is('/'.$preference2->message_name.'/transport_types/'
136
                .$mtt1_2->message_transport_type => Mojo::JSON->true)
137
      ->json_is('/'.$preference2->message_name.'/transport_types/'
138
                .$mtt2_2->message_transport_type => Mojo::JSON->true)
139
      ->json_is('/'.$preference2->message_name.'/days_in_advance/configurable'
140
                => Mojo::JSON->false)
141
      ->json_is('/'.$preference2->message_name.'/days_in_advance/value'
142
                => undef)
143
      ->json_is('/'.$preference2->message_name.'/digest/value'
144
                => Mojo::JSON->false);
145
146
    $schema->storage->txn_rollback;
147
};
148
149
subtest 'edit() tests' => sub {
150
    plan tests => 28;
151
152
    $schema->storage->txn_begin;
153
154
    my $path = '/api/v1/messaging_preferences';
155
156
    my ($patron, $session) = create_user_and_session();
157
    my ($librarian, $librarian_session) = create_user_and_session({
158
        flags => 16
159
    });
160
    my ($another_patron, undef) = create_user_and_session();
161
    my $borrowernumber = $patron->borrowernumber;
162
    my $categorycode   = $patron->categorycode;
163
    my ($preference, $mtt1, $mtt2) = build_a_test_complete_preference({
164
        patron => $patron
165
    });
166
    my ($preference2, $mtt1_2, $mtt2_2) = build_a_test_category_preference({
167
        patron => $patron
168
    });
169
170
    my $edited_preference = {
171
        $preference->message_name => {
172
            digest => {
173
                value => Mojo::JSON->true
174
            },
175
            days_in_advance => {
176
                value => 15
177
            },
178
            transport_types => {
179
                $mtt1->message_transport_type => Mojo::JSON->true,
180
                $mtt2->message_transport_type => Mojo::JSON->false
181
            }
182
        }
183
    };
184
185
    t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1);
186
    my $tx = $t->ua->build_tx(PUT => $path => json => $edited_preference);
187
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
188
    $t->request_ok($tx)
189
      ->status_is(401);
190
191
    $tx = $t->ua->build_tx(PUT => "$path?borrowernumber="
192
                           .$another_patron->borrowernumber
193
                           => json => $edited_preference);
194
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
195
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
196
    $t->request_ok($tx)
197
      ->status_is(403);
198
199
    $tx = $t->ua->build_tx(PUT => "$path?categorycode=$categorycode"
200
                           => json => $edited_preference);
201
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
202
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
203
    $t->request_ok($tx)
204
      ->status_is(403);
205
206
    $tx = $t->ua->build_tx(PUT => $path => json => $edited_preference);
207
    $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id});
208
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
209
    $t->request_ok($tx)
210
      ->status_is(400)
211
      ->json_is('/error', 'Patron or category not found');
212
213
    t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 0);
214
    $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" =>
215
                           json => $edited_preference);
216
    $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id});
217
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
218
    $t->request_ok($tx)
219
      ->status_is(403)
220
      ->json_is('/error' => 'Enhanced messaging preferences are not enabled');
221
    t::lib::Mocks::mock_preference('EnhancedMessagingPreferences', 1);
222
223
    $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" =>
224
                           json => $edited_preference);
225
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
226
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
227
    $t->request_ok($tx)
228
      ->status_is(400)
229
      ->json_like('/error' => qr/^days_in_advance cannot/);
230
231
    $edited_preference->{$preference->message_name}->
232
                                        {days_in_advance}->{value} = undef;
233
    $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" =>
234
                           json => $edited_preference);
235
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
236
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
237
    $t->request_ok($tx)
238
      ->status_is(400)
239
      ->json_like('/error' => qr/igest not available/);
240
241
    $edited_preference->{$preference->message_name}->{digest}->{value}
242
                        = Mojo::JSON->false;
243
    $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" =>
244
                           json => $edited_preference);
245
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
246
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
247
    $t->request_ok($tx)
248
      ->status_is(200)
249
      ->json_is('/'.$preference->message_name.'/transport_types/'.
250
                $mtt2->message_transport_type => Mojo::JSON->false)
251
      ->json_is('/'.$preference->message_name.'/transport_types/'.
252
                $mtt1->message_transport_type => Mojo::JSON->true);
253
254
    Koha::Patron::Message::Transports->search({
255
        message_attribute_id => $preference->message_attribute_id,
256
    })->update({ is_digest => 1 });
257
    $edited_preference->{$preference->message_name}->{digest}->{value}
258
                        = Mojo::JSON->true;
259
    $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" =>
260
                           json => $edited_preference);
261
    $tx->req->cookies({name => 'CGISESSID', value => $session->id});
262
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
263
    $t->request_ok($tx)
264
      ->status_is(200)
265
      ->json_is('/'.$preference->message_name.'/digest/value' => Mojo::JSON->true);
266
267
    # Test librarian access
268
    $tx = $t->ua->build_tx(PUT => "$path?borrowernumber=$borrowernumber" =>
269
                           json => $edited_preference);
270
    $tx->req->cookies({name => 'CGISESSID', value => $librarian_session->id});
271
    $tx->req->env({REMOTE_ADDR => '127.0.0.1'});
272
    $t->request_ok($tx)
273
      ->status_is(200)
274
      ->json_is('/'.$preference->message_name.'/digest/value' => Mojo::JSON->true);
275
276
    $schema->storage->txn_rollback;
277
};
278
279
sub create_user_and_session {
280
    my ($params) = @_;
281
282
    my $categorycode = $builder->build({ source => 'Category' })->{categorycode};
283
    my $branchcode = $builder->build({ source => 'Branch' })->{ branchcode };
284
285
    my $borrower = $builder->build({
286
        source => 'Borrower',
287
        value => {
288
            branchcode   => $branchcode,
289
            categorycode => $categorycode,
290
            flags        => $params->{'flags'} || 0,
291
        }
292
    });
293
294
    my $session = C4::Auth::get_session('');
295
    $session->param('number', $borrower->{ borrowernumber });
296
    $session->param('id', $borrower->{ userid });
297
    $session->param('ip', '127.0.0.1');
298
    $session->param('lasttime', time());
299
    $session->flush;
300
    my $patron = Koha::Patrons->find($borrower->{borrowernumber});
301
302
    return ($patron, $session);
303
}
304
305
306
sub build_a_test_attribute {
307
    my ($params) = @_;
308
309
    $params->{takes_days} = $params->{takes_days} && $params->{takes_days} > 0
310
                            ? 1 : 0;
311
312
    my $attribute = $builder->build({
313
        source => 'MessageAttribute',
314
        value => $params,
315
    });
316
317
    return Koha::Patron::Message::Attributes->find(
318
        $attribute->{message_attribute_id}
319
    );
320
}
321
322
sub build_a_test_category {
323
    my $categorycode   = $builder->build({
324
        source => 'Category' })->{categorycode};
325
326
    return Koha::Patron::Categories->find($categorycode);
327
}
328
329
sub build_a_test_letter {
330
    my ($params) = @_;
331
332
    my $mtt = $params->{mtt} ? $params->{mtt} : 'email';
333
    my $branchcode     = $builder->build({
334
        source => 'Branch' })->{branchcode};
335
    my $letter = $builder->build({
336
        source => 'Letter',
337
        value => {
338
            branchcode => '',
339
            is_html => 0,
340
            message_transport_type => $mtt
341
        }
342
    });
343
344
    return Koha::Notice::Templates->find({
345
        module     => $letter->{module},
346
        code       => $letter->{code},
347
        branchcode => $letter->{branchcode},
348
    });
349
}
350
351
sub build_a_test_transport_type {
352
    my $mtt = $builder->build({
353
        source => 'MessageTransportType' });
354
355
    return Koha::Patron::Message::Transport::Types->find(
356
        $mtt->{message_transport_type}
357
    );
358
}
359
360
sub build_a_test_category_preference {
361
    my ($params) = @_;
362
363
    my $patron = $params->{patron};
364
    my $attr = $params->{attr}
365
                    ? $params->{attr}
366
                    : build_a_test_attribute($params->{days_in_advance});
367
368
    my $letter = $params->{letter} ? $params->{letter} : build_a_test_letter();
369
    my $mtt1 = $params->{mtt1} ? $params->{mtt1} : build_a_test_transport_type();
370
    my $mtt2 = $params->{mtt2} ? $params->{mtt2} : build_a_test_transport_type();
371
372
    Koha::Patron::Message::Transport->new({
373
        message_attribute_id   => $attr->message_attribute_id,
374
        message_transport_type => $mtt1->message_transport_type,
375
        is_digest              => $params->{digest} ? 1 : 0,
376
        letter_module          => $letter->module,
377
        letter_code            => $letter->code,
378
    })->store;
379
380
    Koha::Patron::Message::Transport->new({
381
        message_attribute_id   => $attr->message_attribute_id,
382
        message_transport_type => $mtt2->message_transport_type,
383
        is_digest              => $params->{digest} ? 1 : 0,
384
        letter_module          => $letter->module,
385
        letter_code            => $letter->code,
386
    })->store;
387
388
    my $default = Koha::Patron::Message::Preference->new({
389
        categorycode         => $patron->categorycode,
390
        message_attribute_id => $attr->message_attribute_id,
391
        wants_digest         => $params->{digest} ? 1 : 0,
392
        days_in_advance      => $params->{days_in_advance}
393
                                 ? $params->{days_in_advance} : undef,
394
    })->store;
395
396
    Koha::Patron::Message::Transport::Preference->new({
397
        borrower_message_preference_id => $default->borrower_message_preference_id,
398
        message_transport_type         => $mtt1->message_transport_type,
399
    })->store;
400
    Koha::Patron::Message::Transport::Preference->new({
401
        borrower_message_preference_id => $default->borrower_message_preference_id,
402
        message_transport_type         => $mtt2->message_transport_type,
403
    })->store;
404
405
    return ($default, $mtt1, $mtt2);
406
}
407
408
sub build_a_test_complete_preference {
409
    my ($params) = @_;
410
411
    my ($default, $mtt1, $mtt2) = build_a_test_category_preference($params);
412
    my $patron = $params->{patron};
413
    $patron->set_default_messaging_preferences;
414
    return (Koha::Patron::Message::Preferences->search({
415
        borrowernumber => $patron->borrowernumber
416
    })->next, $mtt1, $mtt2);
417
}

Return to bug 17505