Bug 32030: ERM - Users
Signed-off-by: Jonathan Field <jonathan.field@ptfs-europe.com> Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
parent
b5465a2b88
commit
b8e7788167
9 changed files with 385 additions and 13 deletions
|
@ -22,6 +22,7 @@ use Koha::Database;
|
|||
use base qw(Koha::Object);
|
||||
|
||||
use Koha::ERM::Agreement::Periods;
|
||||
use Koha::ERM::Agreement::UserRoles;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
|
@ -46,6 +47,19 @@ sub periods {
|
|||
return Koha::ERM::Agreement::Periods->_new_from_dbic($periods_rs);
|
||||
}
|
||||
|
||||
=head3 user_roles
|
||||
|
||||
Returns the user roles for this agreement
|
||||
|
||||
=cut
|
||||
|
||||
sub user_roles {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my $user_roles_rs = $self->_result->erm_agreement_user_roles;
|
||||
return Koha::ERM::Agreement::UserRoles->_new_from_dbic($user_roles_rs);
|
||||
}
|
||||
|
||||
=head2 Internal methods
|
||||
|
||||
=head3 _type
|
||||
|
|
58
Koha/ERM/Agreement/UserRole.pm
Normal file
58
Koha/ERM/Agreement/UserRole.pm
Normal file
|
@ -0,0 +1,58 @@
|
|||
package Koha::ERM::Agreement::UserRole;
|
||||
|
||||
# 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 3 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, see <http://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use Koha::Database;
|
||||
|
||||
use Koha::Patrons;
|
||||
|
||||
use base qw(Koha::Object);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::ERM::Agreement::UserRole - Koha Agreement UserRole Object class
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class Methods
|
||||
|
||||
=cut
|
||||
|
||||
=head3 patron
|
||||
|
||||
Return the patron linked to this user role
|
||||
|
||||
=cut
|
||||
|
||||
sub patron {
|
||||
my ( $self ) = @_;
|
||||
my $patron_rs = $self->_result->user;
|
||||
return Koha::Patron->_new_from_dbic($patron_rs);
|
||||
}
|
||||
|
||||
=head2 Internal methods
|
||||
|
||||
=head3 _type
|
||||
|
||||
=cut
|
||||
|
||||
sub _type {
|
||||
return 'ErmAgreementUserRole';
|
||||
}
|
||||
|
||||
1;
|
53
Koha/ERM/Agreement/UserRoles.pm
Normal file
53
Koha/ERM/Agreement/UserRoles.pm
Normal file
|
@ -0,0 +1,53 @@
|
|||
package Koha::ERM::Agreement::UserRoles;
|
||||
|
||||
# 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 3 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, see <http://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
|
||||
use Koha::Database;
|
||||
|
||||
use Koha::ERM::Agreement::UserRole;
|
||||
|
||||
use base qw(Koha::Objects);
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::ERM::Agreement::UserRoles- Koha Agreement UserRole Object set class
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class Methods
|
||||
|
||||
=cut
|
||||
|
||||
=head3 type
|
||||
|
||||
=cut
|
||||
|
||||
sub _type {
|
||||
return 'ErmAgreementUserRole';
|
||||
}
|
||||
|
||||
=head3 object_class
|
||||
|
||||
=cut
|
||||
|
||||
sub object_class {
|
||||
return 'Koha::ERM::Agreement::UserRole';
|
||||
}
|
||||
|
||||
1;
|
58
Koha/REST/V1/ERM.pm
Normal file
58
Koha/REST/V1/ERM.pm
Normal file
|
@ -0,0 +1,58 @@
|
|||
package Koha::REST::V1::ERM;
|
||||
|
||||
# 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 3 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, see <http://www.gnu.org/licenses>.
|
||||
|
||||
use Modern::Perl;
|
||||
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
|
||||
use Koha::Patrons;
|
||||
|
||||
use Try::Tiny qw( catch try );
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Koha::REST::V1::Acquisitions::Funds
|
||||
|
||||
=head1 API
|
||||
|
||||
=head2 Class methods
|
||||
|
||||
=head3 list_users
|
||||
|
||||
Return the list of possible ERM' users
|
||||
|
||||
=cut
|
||||
|
||||
sub list_users {
|
||||
my $c = shift->openapi->valid_input or return;
|
||||
|
||||
return try {
|
||||
|
||||
my $patrons_rs = Koha::Patrons->search->filter_by_have_permission('erm');
|
||||
my $patrons = $c->objects->search( $patrons_rs );
|
||||
|
||||
return $c->render(
|
||||
status => 200,
|
||||
openapi => $patrons
|
||||
);
|
||||
}
|
||||
catch {
|
||||
$c->unhandled_exception($_);
|
||||
};
|
||||
}
|
||||
|
||||
1;
|
47
api/v1/swagger/paths/erm_users.yaml
Normal file
47
api/v1/swagger/paths/erm_users.yaml
Normal file
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
/erm/users:
|
||||
get:
|
||||
x-mojo-to: ERM#list_users
|
||||
operationId: listERMUsers
|
||||
description: This resource returns a list of patron allowed to be users of the ERM module
|
||||
summary: List possibe users for ERM
|
||||
tags:
|
||||
- ERM
|
||||
parameters:
|
||||
- $ref: ../parameters.yaml#/match
|
||||
- $ref: ../parameters.yaml#/order_by
|
||||
- $ref: ../parameters.yaml#/page
|
||||
- $ref: ../parameters.yaml#/per_page
|
||||
- $ref: ../parameters.yaml#/q_param
|
||||
- $ref: ../parameters.yaml#/q_body
|
||||
- $ref: ../parameters.yaml#/q_header
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: A list of ERM' users
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: ../definitions.yaml#/patron
|
||||
"403":
|
||||
description: Access forbidden
|
||||
schema:
|
||||
$ref: ../definitions.yaml#/error
|
||||
"500":
|
||||
description: |
|
||||
Internal server error. Possible `error_code` attribute values:
|
||||
|
||||
* `internal_server_error`
|
||||
schema:
|
||||
$ref: ../definitions.yaml#/error
|
||||
"503":
|
||||
description: Under maintenance
|
||||
schema:
|
||||
$ref: ../definitions.yaml#/error
|
||||
x-koha-authorization:
|
||||
permissions:
|
||||
erm: 1
|
||||
x-koha-embed:
|
||||
- extended_attributes
|
||||
|
|
@ -157,6 +157,10 @@ paths:
|
|||
$ref: ./paths/config_smtp_servers.yaml#/~1config~1smtp_servers
|
||||
"/config/smtp_servers/{smtp_server_id}":
|
||||
$ref: "./paths/config_smtp_servers.yaml#/~1config~1smtp_servers~1{smtp_server_id}"
|
||||
/erm/agreements:
|
||||
$ref: ./paths/erm_agreements.yaml#/~1erm~1agreements
|
||||
/erm/users:
|
||||
$ref: ./paths/erm_users.yaml#/~1erm~1users
|
||||
/holds:
|
||||
$ref: ./paths/holds.yaml#/~1holds
|
||||
"/holds/{hold_id}":
|
||||
|
|
|
@ -107,6 +107,7 @@ elsif ( $op eq 'add_validate' ) {
|
|||
if ( $stored ) {
|
||||
if ( $agreement_id ) {
|
||||
$agreement->periods->delete;
|
||||
$agreement->user_roles->delete;
|
||||
}
|
||||
for my $unique_id ( $input->multi_param('period_unique_id') ) {
|
||||
my $started_on = $input->param( 'started_on_' . $unique_id );
|
||||
|
@ -129,6 +130,20 @@ elsif ( $op eq 'add_validate' ) {
|
|||
}
|
||||
)->store;
|
||||
}
|
||||
|
||||
for my $unique_id ( $input->multi_param('user_unique_id') ) {
|
||||
my $user_id = $input->param('user_id_' . $unique_id);
|
||||
next unless $user_id;
|
||||
my $role = $input->param('user_role_' . $unique_id);
|
||||
Koha::ERM::Agreement::UserRole->new(
|
||||
{
|
||||
agreement_id => $agreement->agreement_id,
|
||||
user_id => $user_id,
|
||||
role => $role,
|
||||
}
|
||||
)->store;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
$op = 'list';
|
||||
|
|
|
@ -103,7 +103,7 @@
|
|||
[%# - Browse by last name %]
|
||||
[%# - The table %]
|
||||
[%# Get the following parameters: %]
|
||||
[%# - filter: can be 'suggestions_managers', 'orders_managers', 'funds_owners' or 'funds_users' to filter patrons on their permissions %]
|
||||
[%# - filter: can be 'suggestions_managers', 'orders_managers', 'funds_owners', 'funds_users' or 'erm_users' to filter patrons on their permissions %]
|
||||
[%# - table_id: the ID of the table %]
|
||||
[%# open_on_row_click: See patron_search_js %]
|
||||
[%# columns: See patron_search_js %]
|
||||
|
@ -115,6 +115,8 @@
|
|||
<div class="hint">Only staff with superlibrarian or acquisitions permissions (or order_manage permission if granular permissions are enabled) are returned in the search results</div>
|
||||
[% ELSIF filter == 'funds_owners' OR filter == 'funds_users' %]
|
||||
<div class="hint">Only staff with superlibrarian or acquisitions permissions (or budget_modify permission if granular permissions are enabled) are returned in the search results</div>
|
||||
[% ELSIF filter == 'erm_users' %]
|
||||
<div class="hint">Only staff with superlibrarian or ERM permissions are returned in the search results</div>
|
||||
[% END %]
|
||||
|
||||
<div class="browse">
|
||||
|
@ -269,6 +271,8 @@
|
|||
let patron_search_url = '/api/v1/acquisitions/funds/owners';
|
||||
[% CASE 'funds_users' %]
|
||||
let patron_search_url = '/api/v1/acquisitions/funds/users';
|
||||
[% CASE 'erm_users' %]
|
||||
let patron_search_url = '/api/v1/erm/users';
|
||||
[% CASE %]
|
||||
let patron_search_url = '/api/v1/patrons';
|
||||
[% END %]
|
||||
|
|
|
@ -218,7 +218,53 @@
|
|||
[% ELSE %]
|
||||
[% PROCESS agreement_period id => 1 %]
|
||||
[% END %]
|
||||
<button class="add_new_period" type="button" class="btn btn-primary"><i class="fa fa-plus" aria-hidden="true"></i>Add new period</button>
|
||||
<button class="add_new_period" type="button" class="btn btn-primary"><i class="fa fa-plus" aria-hidden="true"></i> Add new period</button>
|
||||
</fieldset>
|
||||
|
||||
[% BLOCK agreement_user %]
|
||||
<fieldset class="agreement_user">
|
||||
<legend>
|
||||
User <span class="user_count">[% id | html %]</span>
|
||||
<a href="#" class="remove_user"><i class="fa fa-trash"></i> Remove this user</a>
|
||||
</legend>
|
||||
<input type="hidden" name="user_unique_id" value="[% id | html %]" />
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
<label for="user" class="required">User: </label>
|
||||
<span class="user">
|
||||
[% IF u %]
|
||||
<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% u.user_id| uri %]">
|
||||
[% INCLUDE 'patron-title.inc' patron = u.patron %]
|
||||
</a>
|
||||
<input type="hidden" class="user_id" name="user_id_[% id | html %]" value="[% u.user_id %]" />
|
||||
[% END %]
|
||||
</span>
|
||||
(<a href="#" class="pick_user" class="btn btn-default">Select user</a>)
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<label>Role: </label>
|
||||
<select class="user_role" name="user_role_[% id | html %]">
|
||||
<option value=""></option>
|
||||
[% PROCESS options_for_authorised_values authorised_values => AuthorisedValues.GetAuthValueDropbox( 'ERM_AGREEMENT_USER_ROLES' ), selected_av => u.role %]
|
||||
</select>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
[% END %]
|
||||
|
||||
<fieldset class="rows">
|
||||
<legend>Users</legend>
|
||||
[% IF agreement.user_roles.count %]
|
||||
[% FOR u IN agreement.user_roles %]
|
||||
[% PROCESS agreement_user user => u, id => loop.count %]
|
||||
[% END %]
|
||||
[% ELSE %]
|
||||
[% PROCESS agreement_user, id => 1 %]
|
||||
[% END %]
|
||||
|
||||
<button class="add_new_user_block" type="button" class="btn btn-primary"><i class="fa fa-plus" aria-hidden="true"></i> Add new user</button>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="action">
|
||||
|
@ -321,6 +367,7 @@
|
|||
[% INCLUDE 'calendar.inc' %]
|
||||
[% INCLUDE 'datatables.inc' %]
|
||||
[% INCLUDE 'columns_settings.inc' %]
|
||||
[% INCLUDE 'js-patron-format.inc' %]
|
||||
<script>
|
||||
|
||||
const agreement_statuses = [% To.json(AuthorisedValues.Get('ERM_AGREEMENT_STATUS')) | $raw %];
|
||||
|
@ -340,7 +387,7 @@
|
|||
}, {});
|
||||
|
||||
|
||||
|
||||
let current_user_node;
|
||||
var columns_settings = [% TablesSettings.GetColumns( 'erm', 'agreements', 'table_agreements', 'json' ) | $raw %];
|
||||
$(document).ready(function() {
|
||||
var agreements_table_url = '/api/v1/erm/agreements?';
|
||||
|
@ -428,28 +475,77 @@
|
|||
|
||||
$(".add_new_period").on("click", function(e){
|
||||
e.preventDefault();
|
||||
let new_period_block = $("fieldset.agreement_period:first").clone(1);
|
||||
new_period_block.find("input").val("");
|
||||
$(new_period_block).insertBefore(this);
|
||||
let first_period_block = $("fieldset.agreement_period:first");
|
||||
if ( first_period_block.is(":visible") ) {
|
||||
let new_period_block = first_period_block.clone(1);
|
||||
new_period_block.find("input").val("");
|
||||
$(new_period_block).insertBefore(this);
|
||||
} else {
|
||||
first_period_block.show();
|
||||
}
|
||||
update_period_count();
|
||||
});
|
||||
$(".remove_period").on("click", function(e){
|
||||
e.preventDefault();
|
||||
$(this).parent().parent().remove();
|
||||
let fieldset = $(this).parent().parent();
|
||||
if ( $("fieldset.agreement_period").length == 1 ) {
|
||||
clear_block(fieldset);
|
||||
fieldset.hide();
|
||||
} else {
|
||||
fieldset.remove();
|
||||
}
|
||||
update_period_count();
|
||||
});
|
||||
|
||||
$(".add_new_user_block").on("click",function(e){
|
||||
e.preventDefault();
|
||||
let first_user_block = $("fieldset.agreement_user:first");
|
||||
if ( first_user_block.is(":visible") ) {
|
||||
let new_user_block = $("fieldset.agreement_user:first").clone(1);
|
||||
new_user_block.find("span.user").empty();
|
||||
clear_block(new_user_block);
|
||||
$(new_user_block).insertBefore(this);
|
||||
} else {
|
||||
first_user_block.show();
|
||||
}
|
||||
|
||||
update_user_count();
|
||||
});
|
||||
$(".remove_user").on("click", function(e){
|
||||
e.preventDefault();
|
||||
let fieldset = $(this).parent().parent();
|
||||
if ( $("fieldset.agreement_user").length == 1 ) {
|
||||
fieldset.find("span.user").empty();
|
||||
clear_block(fieldset);
|
||||
fieldset.hide();
|
||||
} else {
|
||||
fieldset.remove();
|
||||
}
|
||||
|
||||
update_user_count();
|
||||
});
|
||||
|
||||
$(".pick_user").on("click", function(e){
|
||||
e.preventDefault();
|
||||
current_user_node = $(this).closest("fieldset");
|
||||
window.open("/cgi-bin/koha/members/search.pl?columns=cardnumber,name,category,branch,action&selection_type=select&filter=erm_users",
|
||||
'PatronPopup',
|
||||
'width=740,height=450,location=yes,toolbar=no,'
|
||||
+ 'scrollbars=yes,resize=yes'
|
||||
);
|
||||
});
|
||||
|
||||
update_period_count();
|
||||
update_user_count();
|
||||
});
|
||||
|
||||
function clear_block(block){
|
||||
$(block).find('input').val("");
|
||||
$(block).find("select option:first-child").attr("selected", "selected");
|
||||
}
|
||||
function update_period_count(){
|
||||
$("fieldset.agreement_period").each(function(i, period){
|
||||
let id = i + 1;
|
||||
let remove_period_link = $(this).find(".remove_period");
|
||||
if ( id == 1 ) {
|
||||
$(remove_period_link).hide();
|
||||
} else {
|
||||
$(remove_period_link).show();
|
||||
}
|
||||
$(period).find(".period_count").text(id);
|
||||
$(period).find("input[name='period_unique_id']").val(id);
|
||||
|
||||
|
@ -468,9 +564,32 @@
|
|||
$(cancellation_deadline_input).flatpickr();
|
||||
|
||||
$(period).find(".notes").attr("name", "notes_" + id);
|
||||
$(period).attr('id', 'agreement_period_' + id);
|
||||
});
|
||||
}
|
||||
|
||||
function update_user_count(){
|
||||
$("fieldset.agreement_user").each(function(i, user){
|
||||
let id = i + 1;
|
||||
let remove_user_link = $(this).find(".remove_user");
|
||||
$(user).find(".user_count").text(id);
|
||||
$(user).find("input[name='user_unique_id']").val(id);
|
||||
|
||||
$(user).find(".user_id").attr("name", "user_id_" + id);
|
||||
$(user).find(".user_role").attr("name", "user_role_" + id);
|
||||
});
|
||||
}
|
||||
|
||||
function select_user(borrowernumber, patron) {
|
||||
patron['patron_id'] = borrowernumber;
|
||||
let unique_id = $(current_user_node).find("input[name='user_unique_id']").val();
|
||||
let a = '<a href="/cgi-bin/koha/members/moremember.pl?borrowernumber='
|
||||
+ borrowernumber + '">' + $patron_to_html(patron) + '</a> '
|
||||
+ '<input type="hidden" class="user_id" name="user_id_' + unique_id + '" value="' + borrowernumber + '" />';
|
||||
$(current_user_node).find("span.user").html(a);
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
[% END %]
|
||||
[% INCLUDE 'intranet-bottom.inc' %]
|
||||
|
|
Loading…
Reference in a new issue