Bug 33105: Add vendor issues
This patch is the main patch of this patch set, it contains the controller acqui/vendor_issues.pl, its corresponding template, and some links to this script. It adds: * A new DB table aqbookseller_issues linked with the aqbooksellers table * A new subpermission acquisition.issue_manage * A new authorised value category VENDOR_ISSUE_TYPE and two examples MAINTENANCE and OUTAGE * A new controller couple acqui/vendor_issues.[pl,tt] Test plan: 0. Apply the patches, run updatedatabase and restart_all 1. Go to the acquisition module, create a new vendor or use an existing one 2. Create a couple of issues for this vendor 3. Edit/Delete and search for those issues This is the basics for tracking issues with vendors. Suggestions welcome, on follow-up bug reports. Signed-off-by: Jonathan Field <jonathan.fieeld@ptfs-europe.com> Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
This commit is contained in:
parent
56cdee5037
commit
0f7daf1b00
|
|
@ -0,0 +1,113 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
# Copyright 2023 Koha Development Team
|
||||
#
|
||||
# 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 CGI qw ( -utf8 );
|
||||
use Try::Tiny;
|
||||
use C4::Context;
|
||||
use C4::Auth qw( get_template_and_user );
|
||||
use C4::Output qw( output_html_with_http_headers );
|
||||
|
||||
use Koha::Acquisition::Booksellers;
|
||||
|
||||
my $input = CGI->new;
|
||||
my $booksellerid = $input->param('booksellerid');
|
||||
my $issue_id = $input->param('issue_id');
|
||||
my $op = $input->param('op') || 'list';
|
||||
my @messages;
|
||||
|
||||
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
|
||||
{
|
||||
template_name => "acqui/vendor_issues.tt",
|
||||
query => $input,
|
||||
type => "intranet",
|
||||
flagsrequired => { acquisition => 'issues_manage' },
|
||||
}
|
||||
);
|
||||
|
||||
my $issue;
|
||||
if ( $issue_id ) {
|
||||
$issue = Koha::Acquisition::Bookseller::Issues->find($issue_id);
|
||||
$booksellerid = $issue->vendor_id;
|
||||
}
|
||||
my $vendor = Koha::Acquisition::Booksellers->find($booksellerid);
|
||||
|
||||
if ( $op eq 'add_form' || $op eq 'show' ) {
|
||||
$template->param( issue => $issue );
|
||||
} elsif ( $op eq 'add_validate' ) {
|
||||
my $type = $input->param('type');
|
||||
my $started_on = $input->param('started_on');
|
||||
my $ended_on = $input->param('ended_on');
|
||||
my $notes = $input->param('notes');
|
||||
|
||||
if ($issue_id) {
|
||||
try {
|
||||
$issue->set(
|
||||
{
|
||||
type => $type,
|
||||
started_on => $started_on,
|
||||
ended_on => $ended_on,
|
||||
notes => $notes
|
||||
}
|
||||
)->store;
|
||||
push @messages, { type => 'message', code => 'success_on_update' };
|
||||
} catch {
|
||||
push @messages, { type => 'error', code => 'error_on_update' };
|
||||
};
|
||||
} else {
|
||||
try {
|
||||
Koha::Acquisition::Bookseller::Issue->new(
|
||||
{
|
||||
vendor_id => $booksellerid,
|
||||
type => $type,
|
||||
started_on => $started_on,
|
||||
ended_on => $ended_on,
|
||||
notes => $notes,
|
||||
}
|
||||
)->store;
|
||||
push @messages, { type => 'message', code => 'success_on_insert' };
|
||||
} catch {
|
||||
push @messages, { type => 'error', code => 'error_on_insert' };
|
||||
};
|
||||
}
|
||||
$op = 'list';
|
||||
} elsif ( $op eq 'delete_confirm' ) {
|
||||
$template->param( issue => $issue );
|
||||
} elsif ( $op eq 'delete_confirmed' ) {
|
||||
try {
|
||||
$issue->delete;
|
||||
push @messages, { type => 'message', code => 'success_on_delete' };
|
||||
} catch {
|
||||
push @messages, { type => 'error', code => 'error_on_delete' };
|
||||
};
|
||||
$op = 'list';
|
||||
}
|
||||
|
||||
if ( $op eq 'list' ) {
|
||||
$template->param( issues_count => $vendor->issues->search->count );
|
||||
}
|
||||
|
||||
$template->param(
|
||||
messages => \@messages,
|
||||
op => $op,
|
||||
vendor => $vendor,
|
||||
booksellerid => $vendor->id, # Used by vendor-menu.inc
|
||||
);
|
||||
|
||||
output_html_with_http_headers $input, $cookie, $template->output;
|
||||
|
|
@ -454,6 +454,11 @@
|
|||
Manage all baskets and order lines, regardless of restrictions on them
|
||||
</span>
|
||||
<span class="permissioncode">([% name | html %])</span>
|
||||
[%- CASE 'issue_manage' -%]
|
||||
<span class="sub_permission issues_manage_subpermission">
|
||||
Manage issues
|
||||
</span>
|
||||
<span class="permissioncode">([% name | html %])</span>
|
||||
[%- CASE 'order_receive' -%]
|
||||
<span class="sub_permission order_receive_subpermission">
|
||||
Receive orders and manage shipments
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
[% IF ( CAN_user_acquisition_order_manage ) %]<li><a href="/cgi-bin/koha/acqui/booksellers.pl?booksellerid=[% booksellerid | uri %]">Baskets</a></li>[% END %]
|
||||
[% IF ( CAN_user_acquisition_group_manage ) %]<li><a href="/cgi-bin/koha/acqui/basketgroup.pl?booksellerid=[% booksellerid | uri %]">Basket groups</a></li>[% END %]
|
||||
[% IF ( CAN_user_acquisition_contracts_manage ) %]<li><a href="/cgi-bin/koha/admin/aqcontract.pl?booksellerid=[% booksellerid | uri %]">Contracts</a></li>[% END %]
|
||||
[% IF ( CAN_user_acquisition_issue_manage ) %]<li><a href="/cgi-bin/koha/acqui/vendor_issues.pl?booksellerid=[% booksellerid | uri %]">Issues</a></li>[% END %]
|
||||
<li><a href="/cgi-bin/koha/acqui/invoices.pl?supplierid=[% booksellerid | uri %]&op=do_search">Invoices</a></li>
|
||||
[% IF ( CAN_user_acquisition_order_manage ) %][% IF ( basketno ) %]
|
||||
<li><a href="/cgi-bin/koha/acqui/uncertainprice.pl?booksellerid=[% booksellerid | uri %]&basketno=[% basketno | uri %]&owner=1">Uncertain prices</a></li>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,282 @@
|
|||
[% USE raw %]
|
||||
[% USE Asset %]
|
||||
[% USE AuthorisedValues %]
|
||||
[% USE KohaDates %]
|
||||
[% SET footerjs = 1 %]
|
||||
[% INCLUDE 'doc-head-open.inc' %]
|
||||
<title>
|
||||
[% IF op =='add_form' %]
|
||||
[% IF issue.issue_id %]
|
||||
Modify vendor issue
|
||||
[% ELSE %]
|
||||
New vendor issue
|
||||
[% END %] › [% ELSE %]
|
||||
[% IF op == 'delete_confirm' %]
|
||||
Confirm deletion of vendor issue › [% END %]
|
||||
[% END %]
|
||||
Vendor issue › Acquisition › Koha
|
||||
</title>
|
||||
[% INCLUDE 'doc-head-close.inc' %]
|
||||
</head>
|
||||
|
||||
<body id="acq_supplier_issues" class="acq">
|
||||
[% WRAPPER 'header.inc' %]
|
||||
[% INCLUDE 'acquisitions-search.inc' %]
|
||||
[% END %]
|
||||
|
||||
[% WRAPPER 'sub-header.inc' %]
|
||||
<nav id="breadcrumbs" aria-label="Breadcrumb" class="breadcrumb">
|
||||
<ol>
|
||||
<li>
|
||||
<a href="/cgi-bin/koha/mainpage.pl">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/cgi-bin/koha/acqui/acqui-home.pl">Acquisitions</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/cgi-bin/koha/acqui/supplier.pl?booksellerid=[% vendor.id | uri %]">[% vendor.name | html %]</a>
|
||||
</li>
|
||||
[% IF op == 'list' %]
|
||||
<li>
|
||||
<a href="#" aria-current="page">Issues</a>
|
||||
</li>
|
||||
[% ELSE %]
|
||||
<li>
|
||||
<a href="/cgi-bin/koha/acqui/vendor_issues.pl?booksellerid=[% vendor.id | uri %]">Issues</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" aria-current="page">
|
||||
[% IF issue %]
|
||||
Issue #[% issue.issue_id| html %]
|
||||
[% ELSE %]
|
||||
New issue
|
||||
[% END %]
|
||||
</a>
|
||||
</li>
|
||||
[% END %]
|
||||
</ol>
|
||||
</nav>
|
||||
[% END %]
|
||||
|
||||
<div class="main container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-sm-push-2">
|
||||
<main>
|
||||
|
||||
[% FOR m IN messages %]
|
||||
<div class="dialog [% m.type | html %]">
|
||||
[% SWITCH m.code %]
|
||||
[% CASE 'error_on_update' %]
|
||||
<span>An error occurred when updating this issue.</span>
|
||||
[% CASE 'error_on_insert' %]
|
||||
<span>An error occurred when adding this issue</span>
|
||||
[% CASE 'error_on_delete' %]
|
||||
<span>An error occurred when deleting this issue. Check the logs.</span>
|
||||
[% CASE 'success_on_update' %]
|
||||
<span>Issue updated successfully.</span>
|
||||
[% CASE 'success_on_insert' %]
|
||||
<span>Issue created successfully.</span>
|
||||
[% CASE 'success_on_delete' %]
|
||||
<span>Issue deleted successfully.</span>
|
||||
[% CASE %]
|
||||
<span>[% m.code | html %]</span>
|
||||
[% END %]
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
[% IF op == 'add_form' %]
|
||||
[% IF issue %]
|
||||
<h1>Modify a vendor issue</h1>
|
||||
[% ELSE %]
|
||||
<h1>New vendor issue</h1>
|
||||
[% END %]
|
||||
|
||||
<form action="/cgi-bin/koha/acqui/vendor_issues.pl" name="Aform" method="post" class="validated">
|
||||
<input type="hidden" name="op" value="add_validate" />
|
||||
<input type="hidden" name="booksellerid" value="[% vendor.id | html %]" />
|
||||
<input type="hidden" name="issue_id" value="[% issue.issue_id| html %]" />
|
||||
|
||||
<fieldset class="rows">
|
||||
<ol>
|
||||
[% IF issue %]
|
||||
<li><span class="label">Issue ID: </span>[% issue.issue_id | html %]</li>
|
||||
[% END %]
|
||||
<li>
|
||||
<label for="issue_type">Type: </label>
|
||||
[% PROCESS 'av-build-dropbox.inc' name="type", category="VENDOR_ISSUE_TYPE", default=issue.type, empty=1, size = 20 %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="started_on">Started on: </label>
|
||||
<input type="text" size="10" id="from" name="started_on" value="[% issue.started_on| html %]" class="flatpickr" data-date_to="to" />
|
||||
<div class="hint">[% INCLUDE 'date-format.inc' %]</div>
|
||||
</li>
|
||||
<li>
|
||||
<label for="ended_on">Ended on: </label>
|
||||
<input type="text" size="10" id="to" name="ended_on" value="[% issue.ended_on | html %]" class="flatpickr" />
|
||||
<div class="hint">[% INCLUDE 'date-format.inc' %]</div>
|
||||
</li>
|
||||
<li>
|
||||
<label for="notes">Notes: </label>
|
||||
<textarea name="notes" id="notes" rows="3" cols="50">[% issue.notes | html %]</textarea>
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="action">
|
||||
<input type="submit" class="btn btn-primary" value="Submit" />
|
||||
<a class="cancel" href="/cgi-bin/koha/acqui/vendor_issues.pl?booksellerid=[% vendor.id | uri %]">Cancel</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
[% END %]
|
||||
|
||||
[% IF op == 'delete_confirm' %]
|
||||
<div class="dialog alert">
|
||||
<h1>Delete issue #[% issue.issue_id | html %]?<h1>
|
||||
<form action="/cgi-bin/koha/acqui/vendor_issues.pl" method="post">
|
||||
<input type="hidden" name="op" value="delete_confirmed" />
|
||||
<input type="hidden" name="issue_id" value="[% issue.issue_id | html %]" />
|
||||
<button type="submit" class="approve"><i class="fa fa-fw fa-check"></i> Yes, delete</button>
|
||||
</form>
|
||||
<form action="/cgi-bin/koha/acqui/vendor_issues.pl?booksellerid=[% vendor.id | uri %]" method="get">
|
||||
<button type="submit" class="deny"><i class="fa fa-fw fa-remove"></i> No, do not delete</button>
|
||||
</form>
|
||||
</div>
|
||||
[% END %]
|
||||
|
||||
[% IF op == 'show' %]
|
||||
<h1>Vendor issue #[% issue.issue_id | html %]</h1>
|
||||
|
||||
<fieldset class="rows">
|
||||
<ol>
|
||||
[% IF issue %]
|
||||
<li><span class="label">Issue ID: </span>[% issue.issue_id | html %]</li>
|
||||
[% END %]
|
||||
<li>
|
||||
<label for="issue_type">Type: </label>
|
||||
[% AuthorisedValues.GetByCode( 'VENDOR_ISSUE_TYPE', issue.type, 0 ) | html %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="started_on">Started on: </label>
|
||||
[% issue.started_on | $KohaDates %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="ended_on">Ended on: </label>
|
||||
[% issue.ended_on | $KohaDates %]
|
||||
</li>
|
||||
<li>
|
||||
<label for="notes">Notes: </label>
|
||||
[% issue.notes | html %]
|
||||
</li>
|
||||
</ol>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="action">
|
||||
<a href="/cgi-bin/koha/acqui/vendor_issues.pl?booksellerid=[% vendor.id | uri %]">Back</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
[% END %]
|
||||
[% IF op == 'list' %]
|
||||
|
||||
<div id="toolbar" class="btn-toolbar">
|
||||
<a class="btn btn-default" id="new_issue" href="/cgi-bin/koha/acqui/vendor_issues.pl?booksellerid=[% vendor.id | uri %]&op=add_form"><i class="fa fa-plus"></i> New issue</a>
|
||||
</div>
|
||||
|
||||
<h1>Vendor issues</h1>
|
||||
|
||||
[% IF issues_count > 0 %]
|
||||
<div class="page-section">
|
||||
<div class="table_vendor_issues_table_controls"></div>
|
||||
<table id="vendor_issues">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Issue ID</th>
|
||||
<th>Type</th>
|
||||
<th>Started on</th>
|
||||
<th>Ended on</th>
|
||||
<th data-class-name="actions noExport">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div><!-- /.page-section -->
|
||||
[% ELSE %]
|
||||
<div class="dialog message">
|
||||
There are no issues defined. <a href="/cgi-bin/koha/acqui/vendor_issues.pl?booksellerid=[% vendor.id | uri %]&op=add_form">Create a new issue</a>.
|
||||
</div>
|
||||
[% END %]
|
||||
[% END %]
|
||||
|
||||
</main>
|
||||
</div> <!-- /.col-sm-10.col-sm-push-2 -->
|
||||
|
||||
<div class="col-sm-2 col-sm-pull-10">
|
||||
<aside>
|
||||
[% INCLUDE 'vendor-menu.inc' %]
|
||||
</aside>
|
||||
</div> <!-- /.col-sm-2.col-sm-pull-10 -->
|
||||
</div> <!-- /.row -->
|
||||
|
||||
[% MACRO jsinclude BLOCK %]
|
||||
[% Asset.js("js/acquisitions-menu.js") | $raw %]
|
||||
[% INCLUDE 'calendar.inc' %]
|
||||
[% INCLUDE 'datatables.inc' %]
|
||||
<script>
|
||||
|
||||
$(document).ready(function() {
|
||||
var issues_table_url = '/api/v1/acquisitions/vendors/[% vendor.id | uri %]/issues?';
|
||||
|
||||
var issues_table = $("#vendor_issues").kohaTable({
|
||||
ajax: {
|
||||
url: issues_table_url
|
||||
},
|
||||
embed: ["+strings"],
|
||||
order: [[ 0, "desc" ]],
|
||||
columns: [
|
||||
{
|
||||
data: "issue_id",
|
||||
searchable: true,
|
||||
orderable: true,
|
||||
render: function(data, type, row, meta) {
|
||||
return '<a href="/cgi-bin/koha/acqui/vendor_issues.pl?op=show&issue_id=' + encodeURIComponent(row.issue_id) +'">' + escape_str(row.issue_id) + '</a>';
|
||||
},
|
||||
},
|
||||
{
|
||||
data: "type",
|
||||
searchable: true,
|
||||
orderable: true,
|
||||
render: function(data, type, row, meta) {
|
||||
return row._strings.type ? escape_str(row._strings.type.str) : "";
|
||||
}
|
||||
},
|
||||
{
|
||||
data: "started_on",
|
||||
searchable: true,
|
||||
orderable: true,
|
||||
render: function(data, type, row, meta) {
|
||||
return $date(row.started_on);
|
||||
}
|
||||
},
|
||||
{
|
||||
data: "ended_on",
|
||||
searchable: true,
|
||||
orderable: true,
|
||||
render: function(data, type, row, meta) {
|
||||
return $date(row.ended_on);
|
||||
}
|
||||
},
|
||||
{
|
||||
data: function( row, type, val, meta ) {
|
||||
|
||||
var result = '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/acqui/vendor_issues.pl?op=add_form&issue_id='+ encodeURIComponent(row.issue_id) +'"><i class="fa fa-pencil" aria-hidden="true"></i> '+_("Edit")+'</a>'+"\n";
|
||||
result += '<a class="btn btn-default btn-xs" role="button" href="/cgi-bin/koha/acqui/vendor_issues.pl?op=delete_confirm&issue_id='+ encodeURIComponent(row.issue_id) +'"><i class="fa fa-trash" aria-hidden="true"></i> '+_("Delete")+'</a>';
|
||||
return result;
|
||||
},
|
||||
searchable: false,
|
||||
orderable: false
|
||||
}
|
||||
]
|
||||
}, null, 1);
|
||||
|
||||
});
|
||||
</script>
|
||||
[% END %]
|
||||
[% INCLUDE 'intranet-bottom.inc' %]
|
||||
|
|
@ -497,6 +497,8 @@
|
|||
<p>Values that can be entered to fill in the 'Vendor type' field in the acquisitions module, that can be used for statistical purposes</p>
|
||||
[% CASE 'VENDOR_INTERFACE_TYPE' %]
|
||||
<p>Values that can be entered to fill in the 'Vendor interface type' field in the acquisitions module</p>
|
||||
[% CASE 'VENDOR_ISSUE_TYPE' %]
|
||||
<p>Values that can be entered to fill in the 'Vendor issue type' field in the acquisitions module</p>
|
||||
[% CASE 'WITHDRAWN' %]
|
||||
<p>Description of a withdrawn item (appears when adding or editing an item)</p>
|
||||
[% CASE 'YES_NO' %]
|
||||
|
|
|
|||
Loading…
Reference in New Issue