From 9fdc25b748754a98c8a74c7ca7a2cb2d5eb079cb Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Wed, 1 Mar 2023 15:53:22 +0100 Subject: [PATCH] Bug 33104: Add the ability to create vendor interfaces This patchset is adding the ability to create interfaces for vendors. An interface is a website, software, or portal that you use to manage orders or gather statistics from the vendor/organisation. It will help librarians to keep track of those different information within Koha. * new DB table aqbookseller_interfaces(id, vendor_id, type, name, uri, login, password, account_email, notes) * new AV category VENDOR_INTERFACE_TYPE with 3 example values ADMIN, ORDERS, REPORTS * new pair of Koha classes Koha::Acquisition::Bookseller::Interface[s] * new method to retrieve the interfaces from the vendor Koha::Acquisition::Bookseller->interfaces * Add/Delete interfaces when editing a vendor * Display the interfaces on the vendor show view Test plan: - Add a new vendor => Notice the new "Interfaces" block - Create some interfaces => They are display on the vendor show view => The password is hashed and can displayed on the demand QA Note: The "contacts" code is not very nice and I didn't want to replicate it, so I went another way and tried to make the code reusable, for further reutilisation. --- Koha/Acquisition/Bookseller.pm | 28 ++++++ acqui/updatesupplier.pl | 16 ++++ .../prog/css/src/staff-global.scss | 3 +- .../prog/en/modules/acqui/supplier.tt | 87 ++++++++++++++++++- 4 files changed, 132 insertions(+), 2 deletions(-) diff --git a/Koha/Acquisition/Bookseller.pm b/Koha/Acquisition/Bookseller.pm index 12b59b79cc8..13f829e2af6 100644 --- a/Koha/Acquisition/Bookseller.pm +++ b/Koha/Acquisition/Bookseller.pm @@ -19,6 +19,7 @@ use Modern::Perl; use Koha::Acquisition::Bookseller::Aliases; use Koha::Acquisition::Bookseller::Contacts; +use Koha::Acquisition::Bookseller::Interfaces; use Koha::Subscriptions; use base qw( Koha::Object ); @@ -104,6 +105,33 @@ sub aliases { return Koha::Acquisition::Bookseller::Aliases->_new_from_dbic( $rs ); } +=head3 interfaces + + my $interfaces = $vendor->interfaces + + $vendor->interfaces(\@interfaces); + +=cut + +sub interfaces { + my ($self, $interfaces) = @_; + + if ($interfaces) { + my $schema = $self->_result->result_source->schema; + $schema->txn_do( + sub { + $self->interfaces->delete; + for my $interface (@$interfaces) { + $self->_result->add_to_aqbookseller_interfaces($interface); + } + } + ); + } + + my $rs = $self->_result->aqbookseller_interfaces; + return Koha::Acquisition::Bookseller::Interfaces->_new_from_dbic( $rs ); +} + =head3 to_api_mapping diff --git a/acqui/updatesupplier.pl b/acqui/updatesupplier.pl index ac0d50ba649..642111ab4c2 100755 --- a/acqui/updatesupplier.pl +++ b/acqui/updatesupplier.pl @@ -47,6 +47,7 @@ contact_serialsprimary. =cut use Modern::Perl; +use List::MoreUtils qw( any ); use C4::Context; use C4::Auth qw( checkauth ); @@ -130,8 +131,23 @@ if($data{'name'}) { $contact->{booksellerid} = $data{id}; Koha::Acquisition::Bookseller::Contact->new( $contact )->store } + + # Insert aliases $bookseller->aliases([ map { { alias => $_ } } @aliases ]); + # Insert interfaces + my @interface_counters = $input->multi_param('interface_counter'); + my @interfaces; + for my $counter ( @interface_counters ) { + my $interface = {}; + for my $attr (qw(name type uri login password account_email notes)){ + my $v = $input->param("interface_${attr}_${counter}"); + $interface->{$attr} = $v; + } + push @interfaces, $interface if any { defined && length } values %$interface; + } + $bookseller->interfaces(\@interfaces); + #redirect to booksellers.pl print $input->redirect("booksellers.pl?booksellerid=".$data{id}); } else { diff --git a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss index 97af88deca9..5cd39d10311 100644 --- a/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss +++ b/koha-tmpl/intranet-tmpl/prog/css/src/staff-global.scss @@ -2569,7 +2569,8 @@ td.bundle { margin: 0 0 8px 8px; } -#contact-template { +#contact-template, +#interface-template { display: none; } diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt index 652666bb63c..c853cd39ef7 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/supplier.tt @@ -185,7 +185,6 @@
-
@@ -203,6 +202,11 @@
+
+ Interfaces +
+
+
Ordering information
  1. @@ -355,6 +359,29 @@

    Notes: [% notes | html %]

    [% END %] + + [% IF vendor.interfaces.count %] +
    +

    Interfaces

    + + [% FOR interface IN vendor.interfaces %] +
    + [% interface.name | html %] +
      +
    • +
    • Type: [% interface.type | html %]
    • +
    • URI: [% interface.uri | html %]
    • +
    • Login: [% interface.login | html %]
    • +
    • Password: [% interface.password | html %]
    • +
    • Account email: [% interface.account_email | html %]
    • +
    • Notes : [% interface.notes | html %]
    • + +
    +
    + [% END %] +
    + [% END %] +
    @@ -492,6 +519,63 @@ $("#aliases").html(nodes.html()); } + [% IF vendor %] + let interfaces = [% To.json(vendor.interfaces.unblessed) | $raw %]; + [% ELSE %] + let interfaces = []; + [% END %] + function serialize_interface_form(){ + interfaces = []; + $("#interfaces > fieldset.supplier-interface > ol.interface-form").each( (index, interface_form )=> { + let interface = {}; + $(interface_form).find('input,textarea').serializeArray().map(attr => { + let name = attr.name.replace(/interface_([\w_]+)_\d+/, "$1"); + interface[name] = attr.value + }) + interfaces.push(interface); + }); + return interfaces; + } + function remove_interface(i){ + interfaces = serialize_interface_form(); + interfaces.splice(i, 1); + refresh_interfaces(); + } + function add_interface(){ + interfaces = serialize_interface_form(); + interfaces.push({ + type: "", + name: "", + uri: "", + login: "", + password: "", + account_email: "", + notes: "", + }); + refresh_interfaces(); + } + function refresh_interfaces(){ + let nodes = $("
    "); + interfaces.forEach((interface, i) => { + let n = $("
    "); + n.append("" + _("Interface details") + ""); + n.append(``); + let ol = $('
      '); + ol.append(`
    1. `); + ol.append(`
    2. `); + ol.append(`
    3. `); + ol.append(`
    4. `); + ol.append(`
    5. `); + ol.append(`
    6. `); + ol.append(`
    7. `); + ol.append(`
    8. `); + n.append(ol); + nodes.append(n); + }); + nodes.append(`') + $("#interfaces").replaceWith(nodes); + } + var Sticky; $(document).ready(function() { @@ -532,6 +616,7 @@ }); refresh_aliases(); + refresh_interfaces(); Sticky = $("#toolbar"); Sticky.hcSticky({ -- 2.25.1