Bugzilla – Attachment 24754 Details for
Bug 11622
Add ability to pay fees and fines from OPAC via PayPal
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 11622 - Add ability to pay fees and fines from OPAC via PayPal
Bug-11622---Add-ability-to-pay-fees-and-fines-from.patch (text/plain), 63.85 KB, created by
Kyle M Hall
on 2014-01-27 16:24:05 UTC
(
hide
)
Description:
Bug 11622 - Add ability to pay fees and fines from OPAC via PayPal
Filename:
MIME Type:
Creator:
Kyle M Hall
Created:
2014-01-27 16:24:05 UTC
Size:
63.85 KB
patch
obsolete
>From 39cc073d526d094eeb51407e84ff3e4a2ab6f44b Mon Sep 17 00:00:00 2001 >From: Kyle M Hall <kyle@bywatersolutions.com> >Date: Thu, 23 Jan 2014 15:18:29 -0500 >Subject: [PATCH] Bug 11622 - Add ability to pay fees and fines from OPAC via PayPal > >This patch adds the ability for a logged in user to pay fines and >fees from the OPAC via PayPal. > >Test Plan: >1) Apply the patches for bug 6427 >2) Apply this patch >3) Create a paypal developer account >4) Create two test accounts, a Personal account and a Business account >5) Enable PayPal in Sandbox mode via the system preferences. >6) Enter the business account API credentials into the new system > preferences. >7) Create a new patron, add some fines/fees >8) Log in as that patron in the OPAC >9) Choose to pay via PayPal, log in as the sandbox Personal account >10) Complete the transaction >11) Note the fee is now paid >--- > Koha/Accounts/CreditTypes.pm | 10 + > .../prog/en/modules/admin/preferences/opac.pref | 30 ++ > .../en/modules/opac-account-pay-return.tt | 392 +++++++++++++++++++ > .../opac-tmpl/bootstrap/en/modules/opac-account.tt | 161 ++++++--- > .../opac-tmpl/prog/en/includes/browser-strings.inc | 1 + > .../prog/en/modules/opac-account-pay-return.tt | 396 ++++++++++++++++++++ > .../opac-tmpl/prog/en/modules/opac-account.tt | 179 +++++++--- > opac/opac-account-pay-paypal-return.pl | 121 ++++++ > opac/opac-account-pay.pl | 127 +++++++ > opac/opac-account.pl | 1 - > 10 files changed, 1325 insertions(+), 93 deletions(-) > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account-pay-return.tt > create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-account-pay-return.tt > create mode 100755 opac/opac-account-pay-paypal-return.pl > create mode 100755 opac/opac-account-pay.pl > >diff --git a/Koha/Accounts/CreditTypes.pm b/Koha/Accounts/CreditTypes.pm >index 3916c72..0a888f9 100644 >--- a/Koha/Accounts/CreditTypes.pm >+++ b/Koha/Accounts/CreditTypes.pm >@@ -58,6 +58,8 @@ sub IsValid { > || $string eq Koha::Accounts::CreditTypes::Credit() > || $string eq Koha::Accounts::CreditTypes::Forgiven() ); > >+ $is_valid ||= $string eq Koha::Accounts::CreditTypes::PayPal(); >+ > unless ($is_valid) { > $is_valid = > Koha::Database->new()->schema->resultset('AuthorisedValue') >@@ -108,6 +110,14 @@ sub Forgiven { > return 'FORGIVEN'; > } > >+=head2 PayPal >+ >+=cut >+ >+sub PayPal { >+ return 'PAYPAL'; >+} >+ > 1; > > =head1 AUTHOR >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >index a75c7ef..027d8e6 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref >@@ -619,3 +619,33 @@ OPAC: > - pref: PatronSelfRegistrationAdditionalInstructions > type: textarea > class: html >+ Payments: >+ - >+ - pref: EnablePayPalOpacPayments >+ default: 1 >+ choices: >+ yes: Allow >+ no: "Don't allow" >+ - "patrons to make payments from the OPAC via PayPal in" >+ - pref: PayPalSandboxMode >+ default: 1 >+ choices: >+ yes: "Sandbox" >+ no: "Production" >+ - "mode." >+ - >+ - "The email address to recieve PayPal payments is " >+ - pref: PayPalUser >+ class: long >+ - >+ - "The password for the PayPal account to recieve payments is " >+ - pref: PayPalPwd >+ class: long >+ - >+ - "The signature for the PayPal account to recieve payments is " >+ - pref: PayPalSignature >+ class: long >+ - >+ - "The patron should see the charge description as " >+ - pref: PayPalChargeDescription >+ class: long >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account-pay-return.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account-pay-return.tt >new file mode 100644 >index 0000000..ca23d2c >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account-pay-return.tt >@@ -0,0 +1,392 @@ >+[% USE Koha %] >+[% USE KohaDates %] >+[% USE Currency %] >+ >+[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges >+[% INCLUDE 'doc-head-close.inc' %] >+[% BLOCK cssinclude %][% END %] >+ >+ >+</head> >+<body id="opac-account" class="scrollto"> >+[% INCLUDE 'masthead.inc' %] >+ >+<div class="main"> >+ <ul class="breadcrumb"> >+ <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">›</span></li> >+ <li><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]</a> <span class="divider">›</span></li> >+ <li><a href="#">Your fines and charges</a></li> >+ </ul> >+ >+ <div class="container-fluid"> >+ <div class="row-fluid"> >+ <div class="span2"> >+ <div id="navigation"> >+ [% INCLUDE 'navigation.inc' IsPatronPage=1 %] >+ </div> >+ </div> >+ <div class="span10"> >+ <div id="useraccount" class="maincontent"> >+ [% IF error %] >+ <div id="error" class="dialog alert"> >+ <p><strong>Error:</strong> there was an problem processing your payment</p> >+ >+ [% IF error == "PAYPAL_UNABLE_TO_CONNECT" %] >+ <p>Unable to connect to PayPal.</p> >+ <p>Please try again later.</p> >+ [% ELSIF error == "PAYPAL_ERROR_PROCESSING" %] >+ <p>Unable to verify payment.</p> >+ <p>Please contact the library to verify your payment.</p> >+ [% END %] >+ </div> >+ [% ELSIF credit %] >+ <div class="dialog message"> >+ <p><strong>Payment applied:</strong> your payment of [% credit.amount_paid %] has been applied to your account</p> >+ </div> >+ [% END %] >+ >+ <a href="/cgi-bin/koha/opac-account.pl">Return to fine details</a> >+ </div> <!-- / #useraccount --> >+ </div> <!-- / .span10 --> >+ </div> <!-- / .row-fluid --> >+ </div> <!-- / .container-fluid --> >+</div> <!-- / .main --> >+ >+[% INCLUDE 'opac-bottom.inc' %] >+[% INCLUDE 'datatables.inc' %] >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/images/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" }, >+ { >+ /* Payment selection checkboxes */ >+ [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %] >+ "bVisible": false, >+ [% END %] >+ "mDataProp": null, >+ "sDefaultContent": "", >+ "fnRender": function ( o, val ) { >+ return val; >+ }, >+ "mRender": function ( data, type, full ) { >+ if ( full.amount_outstanding_unformatted > 0 ) { >+ return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>" >+ + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>"; >+ } >+ } >+ }, >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { "mDataProp": "type" }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ // Allow only numbers in ammount to pay >+ $('#amount_to_pay').keypress(function(event) { >+ end = $(this).val().split('.')[1]; >+ if (typeof end === 'undefined') { >+ end = ''; >+ } >+ >+ if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) { >+ event.preventDefault(); >+ } >+ }); >+ >+ // Update the "amount to pay" field whenever a fee checkbox is changed >+ // Note, this is just a payment suggestion and can be changed to any amount >+ $(".pay-checkbox" ).change(function() { >+ var sum = 0; >+ $("input[name='debit_id']:checked" ).each(function(i,n){ >+ sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() ); >+ }); >+ $('#amount_to_pay').val( sum.toFixed(2) ); >+ }); >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = "<div class='innerDetails' style='display:none;'>"; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += "<ul>"; >+ if ( oData.title ) { >+ sOut += "<li>" + _("Title: "); >+ if ( oData.biblionumber ) { >+ sOut += "<a href='/cgi-bin/koha/opac-detail.pl?biblionumber=" + oData.biblionumber + "'>"; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += "</a>"; >+ } >+ >+ sOut += "</li>"; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += "<li>" + _("Barcode: ") + oData.barcode + "</li>"; >+ } >+ >+ if ( oData.notes ) { >+ sOut += "<li>" + _("Notes: ") + oData.notes + "</li>"; >+ } >+ >+ sOut += "</ul>"; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ "<div class='innerDetails'>" + >+ "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" + >+ "<thead>" + >+ "<tr><th colspan='99'>" + _("Payments applied") + "</th></tr>" + >+ "<tr>" + >+ "<th>" + _("ID") + "</th>" + >+ "<th>" + _("Created on") + "</th>" + >+ "<th>" + _("Payment amount") + "</th>" + >+ "<th>" + _("Applied amount") + "</th>" + >+ "<th>" + _("Type") + "</th>" + >+ "<th>" + _("Notes") + "</th>" + >+ "</tr>" + >+ "</thead>" + >+ "<tbody>"; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ "<tr>" + >+ "<td>" + ao.credit_id + "</td>" + >+ "<td>" + ao.created_on + "</td>" + >+ "<td>" + ao.credit.amount_paid + "</td>" + >+ "<td>" + ao.amount + "</td>" + >+ "<td>" + ao.credit.type + "</td>" + >+ "<td>" + ao.credit.notes + "</td>" + >+ "</tr>"; >+ } >+ >+ sOut += >+ "</tbody>"+ >+ "</table>"; >+ } >+ >+ sOut += >+ "</div>"; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = "<div class='innerDetails' style='display:none;'>"; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" + >+ "<thead>" + >+ "<tr><th colspan='99'>" + _("Fees paid") + "</th></tr>" + >+ "<tr>" + >+ "<th>" + _("ID") + "</th>" + >+ "<th>" + _("Description") + "</th>" + >+ "<th>" + _("Type") + "</th>" + >+ "<th>" + _("Amount") + "</th>" + >+ "<th>" + _("Remaining") + "</th>" + >+ "<th>" + _("Created on") + "</th>" + >+ "<th>" + _("Updated on") + "</th>" + >+ "<th>" + _("Notes") + "</th>" + >+ "</tr>" + >+ "</thead>" + >+ "<tbody>"; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ "<tr>" + >+ "<td>" + ao.debit.debit_id + "</td>" + >+ "<td>" + ao.debit.description + "</td>" + >+ "<td>" + ao.debit.type + "</td>" + >+ "<td>" + ao.debit.amount_original + "</td>" + >+ "<td>" + ao.debit.amount_outstanding + "</td>" + >+ "<td>" + ao.debit.created_on + "</td>" + >+ "<td>" + ao.debit.updated_on + "</td>" + >+ "<td>" + ao.debit.notes + "</td>" + >+ "</tr>"; >+ } >+ >+ sOut += >+ "</tbody>"+ >+ "</table>"; >+ } >+ >+ sOut += >+ "</div>"; >+ >+ return sOut; >+} >+ >+//]]> >+</script> >+ >+[% BLOCK jsinclude %][% END %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency %]", >+ "[% key %]_unformatted": "[% data.$key %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ "[% key %]_unformatted": "[% data.$key %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >index a1e2487..4c0bc7e 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt >@@ -34,51 +34,79 @@ > <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> > </p> > >- <div> >- <div id="account-debits"> >- <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >- <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >- <thead> >- <tr> >- <th colspan="99">Fees</th> >- </tr> >- <tr> >- <th></th> >- <th>ID</th> >- <th>Description</th> >- <th>Type</th> >- <th>Amount</th> >- <th>Outsanding</th> >- <th>Created on</th> >- <th>Updated on</th> >- </tr> >- </thead> >- <tbody></tbody> >- </table> >+ <form action="/cgi-bin/koha/opac-account-pay.pl" method="post"> >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ <th>Pay</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ [% IF Koha.Preference('EnablePayPalOpacPayments') %] >+ <fieldset> >+ <legend>Pay online</legend> >+ >+ <div> >+ Amount to pay: >+ [% Currency.symbol() %]<input type="text" id="amount_to_pay" name="amount_to_pay"/> >+ </div> >+ >+ <div> >+ <h6>Payment method:</h6> >+ <input type="radio" name="payment_method" value="paypal" checked="checked"/> >+ <label for="payment-method"> >+ <img src="https://www.paypal.com/en_US/i/logo/PayPal_mark_37x23.gif" align="left" style="margin-right:7px;"> >+ </label> >+ </div> >+ >+ <br/> >+ >+ <div> >+ <input type="submit" value="Make payment"> >+ </div> >+ </fieldset> >+ [% END %] > </div> >- >- <div id="account-credits"> >- <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >- <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >- <thead> >- <tr> >- <th colspan="99">Payments</th> >- </tr> >- <tr> >- <th></th> >- <th>ID</th> >- <th>Notes</th> >- <th>Type</th> >- <th>Amount</th> >- <th>Remaining</th> >- <th>Created on</th> >- <th>Updated on</th> >- </tr> >- </thead> >- <tbody></tbody> >- </table> >- </div> >- </div> >+ </form> > [% ELSE %] > <h4>You have no fines or charges</h4> > [% END %] >@@ -121,7 +149,24 @@ $(document).ready(function() { > { "mDataProp": "amount_original" }, > { "mDataProp": "amount_outstanding" }, > { "mDataProp": "created_on" }, >- { "mDataProp": "updated_on" } >+ { "mDataProp": "updated_on" }, >+ { >+ /* Payment selection checkboxes */ >+ [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %] >+ "bVisible": false, >+ [% END %] >+ "mDataProp": null, >+ "sDefaultContent": "", >+ "fnRender": function ( o, val ) { >+ return val; >+ }, >+ "mRender": function ( data, type, full ) { >+ if ( full.amount_outstanding_unformatted > 0 ) { >+ return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>" >+ + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>"; >+ } >+ } >+ }, > ], > "aaData": [ > [% FOREACH d IN debits %] >@@ -242,6 +287,28 @@ $(document).ready(function() { > } > } ); > >+ // Allow only numbers in ammount to pay >+ $('#amount_to_pay').keypress(function(event) { >+ end = $(this).val().split('.')[1]; >+ if (typeof end === 'undefined') { >+ end = ''; >+ } >+ >+ if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) { >+ event.preventDefault(); >+ } >+ }); >+ >+ // Update the "amount to pay" field whenever a fee checkbox is changed >+ // Note, this is just a payment suggestion and can be changed to any amount >+ $(".pay-checkbox" ).change(function() { >+ var sum = 0; >+ $("input[name='debit_id']:checked" ).each(function(i,n){ >+ sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() ); >+ }); >+ $('#amount_to_pay').val( sum.toFixed(2) ); >+ }); >+ > } ); > > function fnFormatDebitDetails( debitsTable, nTr ) { >@@ -321,7 +388,7 @@ function fnFormatDebitDetails( debitsTable, nTr ) { > function fnFormatCreditDetails( creditsTable, nTr ) { > var oData = creditsTable.fnGetData( nTr ); > >- var sOut = "<div class="innerDetails" style="display:none;">"; >+ var sOut = "<div class='innerDetails' style='display:none;'>"; > > var account_offsets = oData.account_offsets; > >@@ -378,8 +445,10 @@ function fnFormatCreditDetails( creditsTable, nTr ) { > [% FOREACH key IN data.result_source.columns %] > [% IF key.match('^amount') %] > "[% key %]": "[% data.$key FILTER $Currency %]", >+ "[% key %]_unformatted": "[% data.$key %]", > [% ELSIF key.match('_on$') %] > "[% key %]": "[% data.$key | $KohaDates %]", >+ "[% key %]_unformatted": "[% data.$key %]", > [% ELSE %] > "[% key %]": "[% data.$key %]", > [% END %] >diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc b/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc >index 0b61e01..62b46c6 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc >+++ b/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc >@@ -25,6 +25,7 @@ > "WRITEOFF" : _("Writeoff"), > "FOUND" : _("Lost item found"), > "FORGIVEN" : _("Forgiven"), >+ "PAYPAL" : _("PayPal"), > [% FOREACH a IN AuthorisedValues.Get('MANUAL_CREDIT') %] > "[% a.authorised_value %]" : "[% a.lib %]", > [% END %] >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account-pay-return.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-account-pay-return.tt >new file mode 100644 >index 0000000..8fc3edc >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-account-pay-return.tt >@@ -0,0 +1,396 @@ >+[% SET accountview = 1 %] >+ >+[% USE Koha %] >+[% USE KohaDates %] >+[% USE Currency %] >+ >+[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges >+[% INCLUDE 'doc-head-close.inc' %] >+</head> >+<body id="opac-account"> >+<div id="doc3" class="yui-t1"> >+ <div id="bd"> >+ [% INCLUDE 'masthead.inc' %] >+ <div id="yui-main"> >+ <div class="yui-b"> >+ <div class="yui-g"> >+ <div id="useraccount" class="container"> >+ <h3><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]'s account</a> ⇢ Fines and charges</h3> >+ >+ [% IF error %] >+ <div id="error" class="dialog alert"> >+ <p><strong>Error:</strong> there was an problem processing your payment</p> >+ >+ [% IF error == "PAYPAL_UNABLE_TO_CONNECT" %] >+ <p>Unable to connect to PayPal.</p> >+ <p>Please try again later.</p> >+ [% ELSIF error == "PAYPAL_ERROR_PROCESSING" %] >+ <p>Unable to verify payment.</p> >+ <p>Please contact the library to verify your payment.</p> >+ [% END %] >+ </div> >+ [% ELSIF credit %] >+ <div class="dialog message"> >+ <p><strong>Payment applied:</strong> your payment of [% credit.amount_paid %] has been applied to your account</p> >+ </div> >+ [% END %] >+ >+ <a href="/cgi-bin/koha/opac-account.pl">Return to fine details</a> >+ </div> >+ </div> >+ </div> >+ </div> >+ >+ <div class="yui-b"> >+ <div id="leftmenus" class="container"> >+ [% INCLUDE 'navigation.inc' IsPatronPage=1 %] >+ </div> >+ </div> >+</div> >+[% INCLUDE 'opac-bottom.inc' %] >+ >+[% INCLUDE 'datatables.inc' %] >+[% INCLUDE 'browser-strings.inc' %] >+ >+<script type="text/javascript"> >+//<![CDATA[ >+$(document).ready(function() { >+ $('#account-credits').hide(); >+ $('#account-debits-switcher').click(function() { >+ $('#account-debits').slideUp(); >+ $('#account-credits').slideDown(); >+ }); >+ $('#account-credits-switcher').click(function() { >+ $('#account-credits').slideUp(); >+ $('#account-debits').slideDown(); >+ }); >+ >+ var anOpen = []; >+ var sImageUrl = "[% interface %]/[% theme %]/images/"; >+ >+ var debitsTable = $('#debits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "debit_id" }, >+ { "mDataProp": "description" }, >+ { >+ "mDataProp": "type", >+ "fnRender": function ( o, val ) { >+ return STRINGS['DebitTypes'][val]; >+ }, >+ }, >+ { "mDataProp": "amount_original" }, >+ { "mDataProp": "amount_outstanding" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" }, >+ { >+ "mDataProp": null, >+ "sDefaultContent": "", >+ "fnRender": function ( o, val ) { >+ return val; >+ }, >+ "mRender": function ( data, type, full ) { >+ if ( full.amount_outstanding_unformatted > 0 ) { >+ return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>" >+ + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>"; >+ } >+ } >+ }, >+ ], >+ "aaData": [ >+ [% FOREACH d IN debits %] >+ { >+ [% PROCESS format_data data=d highlight='debit' %] >+ >+ // Data for related item if there is one linked >+ "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]", >+ "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]", >+ "barcode": "[% d.item.barcode || d.deleted_item.barcode %]", >+ "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted >+ >+ >+ // Data for related issue if there is one linked >+ [% IF d.issue %] >+ [% SET table = 'issue' %] >+ [% ELSIF d.old_issue %] >+ [% SET table = 'old_issue' %] >+ [% END %] >+ >+ [% IF table %] >+ "issue": { >+ [% PROCESS format_data data=d.$table %] >+ }, >+ [% END %] >+ >+ >+ "account_offsets": [ >+ [% FOREACH ao IN d.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset'%] >+ >+ "credit": { >+ [% PROCESS format_data data=ao.credit highlight='credit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#debits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ debitsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ var creditsTable = $('#credits-table').dataTable( { >+ "bProcessing": true, >+ "aoColumns": [ >+ { >+ "mDataProp": null, >+ "sClass": "control center", >+ "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">' >+ }, >+ { "mDataProp": "credit_id" }, >+ { "mDataProp": "notes" }, >+ { >+ "mDataProp": "type", >+ "fnRender": function ( o, val ) { >+ return STRINGS['CreditTypes'][val]; >+ }, >+ }, >+ { "mDataProp": "amount_paid" }, >+ { "mDataProp": "amount_remaining" }, >+ { "mDataProp": "created_on" }, >+ { "mDataProp": "updated_on" } >+ ], >+ "aaData": [ >+ [% FOREACH c IN credits %] >+ { >+ [% PROCESS format_data data=c highlight='credit' %] >+ >+ "account_offsets": [ >+ [% FOREACH ao IN c.account_offsets %] >+ { >+ [% PROCESS format_data data=ao highlight='offset' %] >+ >+ "debit": { >+ [% PROCESS format_data data=ao.debit highlight='debit' %] >+ } >+ }, >+ [% END %] >+ ] >+ >+ }, >+ [% END %] >+ ] >+ } ); >+ >+ $('#credits-table td.control').live( 'click', function () { >+ var nTr = this.parentNode; >+ var i = $.inArray( nTr, anOpen ); >+ >+ if ( i === -1 ) { >+ $('img', this).attr( 'src', sImageUrl+"details_close.png" ); >+ var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' ); >+ $('div.innerDetails', nDetailsRow).slideDown(); >+ anOpen.push( nTr ); >+ } >+ else { >+ $('img', this).attr( 'src', sImageUrl+"details_open.png" ); >+ $('div.innerDetails', $(nTr).next()[0]).slideUp( function () { >+ creditsTable.fnClose( nTr ); >+ anOpen.splice( i, 1 ); >+ } ); >+ } >+ } ); >+ >+ // Allow only numbers in ammount to pay >+ $('#amount_to_pay').keypress(function(event) { >+ end = $(this).val().split('.')[1]; >+ if (typeof end === 'undefined') { >+ end = ''; >+ } >+ >+ if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) { >+ event.preventDefault(); >+ } >+ }); >+ >+ // Update the "amount to pay" field whenever a fee checkbox is changed >+ // Note, this is just a payment suggestion and can be changed to any amount >+ $(".pay-checkbox" ).change(function() { >+ var sum = 0; >+ $("input[name='debit_id']:checked" ).each(function(i,n){ >+ sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() ); >+ }); >+ $('#amount_to_pay').val( sum.toFixed(2) ); >+ }); >+ >+ >+} ); >+ >+function fnFormatDebitDetails( debitsTable, nTr ) { >+ var oData = debitsTable.fnGetData( nTr ); >+ >+ var sOut = "<div class='innerDetails' style='display:none;'>"; >+ >+ var account_offsets = oData.account_offsets; >+ >+ sOut += "<ul>"; >+ if ( oData.title ) { >+ sOut += "<li>" + _("Title: "); >+ if ( oData.biblionumber ) { >+ sOut += "<a href='/cgi-bin/koha/opac-detail.pl?biblionumber=" + oData.biblionumber + "'>"; >+ } >+ >+ sOut += oData.title; >+ >+ if ( oData.biblionumber ) { >+ sOut += "</a>"; >+ } >+ >+ sOut += "</li>"; >+ } >+ >+ if ( oData.barcode ) { >+ sOut += "<li>" + _("Barcode: ") + oData.barcode + "</li>"; >+ } >+ >+ if ( oData.notes ) { >+ sOut += "<li>" + _("Notes: ") + oData.notes + "</li>"; >+ } >+ >+ sOut += "</ul>"; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ "<div class='innerDetails'>" + >+ "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" + >+ "<thead>" + >+ "<tr><th colspan='99'>" + _("Payments applied") + "</th></tr>" + >+ "<tr>" + >+ "<th>" + _("ID") + "</th>" + >+ "<th>" + _("Created on") + "</th>" + >+ "<th>" + _("Payment amount") + "</th>" + >+ "<th>" + _("Applied amount") + "</th>" + >+ "<th>" + _("Type") + "</th>" + >+ "<th>" + _("Notes") + "</th>" + >+ "</tr>" + >+ "</thead>" + >+ "<tbody>"; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ "<tr>" + >+ "<td>" + ao.credit_id + "</td>" + >+ "<td>" + ao.created_on + "</td>" + >+ "<td>" + ao.credit.amount_paid + "</td>" + >+ "<td>" + ao.amount + "</td>" + >+ "<td>" + ao.credit.type + "</td>" + >+ "<td>" + ao.credit.notes + "</td>" + >+ "</tr>"; >+ } >+ >+ sOut += >+ "</tbody>"+ >+ "</table>"; >+ } >+ >+ sOut += >+ "</div>"; >+ >+ return sOut; >+} >+ >+function fnFormatCreditDetails( creditsTable, nTr ) { >+ var oData = creditsTable.fnGetData( nTr ); >+ >+ var sOut = '<div class="innerDetails" style="display:none;">'; >+ >+ var account_offsets = oData.account_offsets; >+ >+ if ( account_offsets.length ) { >+ sOut += >+ "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" + >+ "<thead>" + >+ "<tr><th colspan='99'>" + _("Fees paid") + "</th></tr>" + >+ "<tr>" + >+ "<th>" + _("ID") + "</th>" + >+ "<th>" + _("Description") + "</th>" + >+ "<th>" + _("Type") + "</th>" + >+ "<th>" + _("Amount") + "</th>" + >+ "<th>" + _("Remaining") + "</th>" + >+ "<th>" + _("Created on") + "</th>" + >+ "<th>" + _("Updated on") + "</th>" + >+ "<th>" + _("Notes") + "</th>" + >+ "</tr>" + >+ "</thead>" + >+ "<tbody>"; >+ >+ for ( var i = 0; i < account_offsets.length; i++ ) { >+ ao = account_offsets[i]; >+ sOut += >+ "<tr>" + >+ "<td>" + ao.debit.debit_id + "</td>" + >+ "<td>" + ao.debit.description + "</td>" + >+ "<td>" + ao.debit.type + "</td>" + >+ "<td>" + ao.debit.amount_original + "</td>" + >+ "<td>" + ao.debit.amount_outstanding + "</td>" + >+ "<td>" + ao.debit.created_on + "</td>" + >+ "<td>" + ao.debit.updated_on + "</td>" + >+ "<td>" + ao.debit.notes + "</td>" + >+ "</tr>"; >+ } >+ >+ sOut += >+ "</tbody>"+ >+ "</table>"; >+ } >+ >+ sOut += >+ "</div>"; >+ >+ return sOut; >+} >+ >+//]]> >+</script> >+ >+[% BLOCK jsinclude %][% END %] >+ >+[% BLOCK format_data %] >+ [% FOREACH key IN data.result_source.columns %] >+ [% IF key.match('^amount') %] >+ "[% key %]": "[% data.$key FILTER $Currency %]", >+ "[% key %]_unformatted": "[% data.$key %]", >+ [% ELSIF key.match('_on$') %] >+ "[% key %]": "[% data.$key | $KohaDates %]", >+ "[% key %]_unformatted": "[% data.$key %]", >+ [% ELSE %] >+ "[% key %]": "[% data.$key %]", >+ [% END %] >+ [% END %] >+[% END %] >diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt >index 1d693dc..a32adb3 100644 >--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt >+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt >@@ -23,51 +23,79 @@ > <h3>Account balance: [% borrower.account_balance | $Currency %]</h3> > </p> > >- <div> >- <div id="account-debits"> >- <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >- <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >- <thead> >- <tr> >- <th colspan="99">Fees</th> >- </tr> >- <tr> >- <th></th> >- <th>ID</th> >- <th>Description</th> >- <th>Type</th> >- <th>Amount</th> >- <th>Outsanding</th> >- <th>Created on</th> >- <th>Updated on</th> >- </tr> >- </thead> >- <tbody></tbody> >- </table> >+ <form action="/cgi-bin/koha/opac-account-pay.pl" method="post"> >+ <div> >+ <div id="account-debits"> >+ <a id="account-debits-switcher" href="#" onclick="return false">View payments</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Fees</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Description</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Outsanding</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ <th>Pay</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ <div id="account-credits"> >+ <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >+ <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >+ <thead> >+ <tr> >+ <th colspan="99">Payments</th> >+ </tr> >+ <tr> >+ <th></th> >+ <th>ID</th> >+ <th>Notes</th> >+ <th>Type</th> >+ <th>Amount</th> >+ <th>Remaining</th> >+ <th>Created on</th> >+ <th>Updated on</th> >+ </tr> >+ </thead> >+ <tbody></tbody> >+ </table> >+ </div> >+ >+ [% IF Koha.Preference('EnablePayPalOpacPayments') %] >+ <fieldset> >+ <legend>Pay online</legend> >+ >+ <div> >+ Amount to pay: >+ [% Currency.symbol() %]<input type="text" id="amount_to_pay" name="amount_to_pay"/> >+ </div> >+ >+ <div> >+ <h6>Payment method:</h6> >+ <input type="radio" name="payment_method" value="paypal" checked="checked"/> >+ <label for="payment-method"> >+ <img src="https://www.paypal.com/en_US/i/logo/PayPal_mark_37x23.gif" align="left" style="margin-right:7px;"> >+ </label> >+ </div> >+ >+ <br/> >+ >+ <div> >+ <input type="submit" value="Make payment"> >+ </div> >+ </fieldset> >+ [% END %] > </div> >- >- <div id="account-credits"> >- <a id="account-credits-switcher" href="#" onclick="return false">View fees</a> >- <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table"> >- <thead> >- <tr> >- <th colspan="99">Payments</th> >- </tr> >- <tr> >- <th></th> >- <th>ID</th> >- <th>Notes</th> >- <th>Type</th> >- <th>Amount</th> >- <th>Remaining</th> >- <th>Created on</th> >- <th>Updated on</th> >- </tr> >- </thead> >- <tbody></tbody> >- </table> >- </div> >- </div> >+ </form> > [% ELSE %] > <h4>You have no fines or charges</h4> > [% END %] >@@ -122,7 +150,24 @@ $(document).ready(function() { > { "mDataProp": "amount_original" }, > { "mDataProp": "amount_outstanding" }, > { "mDataProp": "created_on" }, >- { "mDataProp": "updated_on" } >+ { "mDataProp": "updated_on" }, >+ { >+ /* Payment selection checkboxes */ >+ [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %] >+ "bVisible": false, >+ [% END %] >+ "mDataProp": null, >+ "sDefaultContent": "", >+ "fnRender": function ( o, val ) { >+ return val; >+ }, >+ "mRender": function ( data, type, full ) { >+ if ( full.amount_outstanding_unformatted > 0 ) { >+ return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>" >+ + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>"; >+ } >+ } >+ }, > ], > "aaData": [ > [% FOREACH d IN debits %] >@@ -205,7 +250,24 @@ $(document).ready(function() { > { "mDataProp": "amount_paid" }, > { "mDataProp": "amount_remaining" }, > { "mDataProp": "created_on" }, >- { "mDataProp": "updated_on" } >+ { "mDataProp": "updated_on" }, >+ { >+ /* Payment selection checkboxes */ >+ [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %] >+ "bVisible": false, >+ [% END %] >+ "mDataProp": null, >+ "sDefaultContent": "", >+ "fnRender": function ( o, val ) { >+ return val; >+ }, >+ "mRender": function ( data, type, full ) { >+ if ( full.amount_outstanding_unformatted > 0 ) { >+ return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>" >+ + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>"; >+ } >+ } >+ }, > ], > "aaData": [ > [% FOREACH c IN credits %] >@@ -248,6 +310,29 @@ $(document).ready(function() { > } > } ); > >+ // Allow only numbers in ammount to pay >+ $('#amount_to_pay').keypress(function(event) { >+ end = $(this).val().split('.')[1]; >+ if (typeof end === 'undefined') { >+ end = ''; >+ } >+ >+ if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) { >+ event.preventDefault(); >+ } >+ }); >+ >+ // Update the "amount to pay" field whenever a fee checkbox is changed >+ // Note, this is just a payment suggestion and can be changed to any amount >+ $(".pay-checkbox" ).change(function() { >+ var sum = 0; >+ $("input[name='debit_id']:checked" ).each(function(i,n){ >+ sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() ); >+ }); >+ $('#amount_to_pay').val( sum.toFixed(2) ); >+ }); >+ >+ > } ); > > function fnFormatDebitDetails( debitsTable, nTr ) { >@@ -384,8 +469,10 @@ function fnFormatCreditDetails( creditsTable, nTr ) { > [% FOREACH key IN data.result_source.columns %] > [% IF key.match('^amount') %] > "[% key %]": "[% data.$key FILTER $Currency %]", >+ "[% key %]_unformatted": "[% data.$key %]", > [% ELSIF key.match('_on$') %] > "[% key %]": "[% data.$key | $KohaDates %]", >+ "[% key %]_unformatted": "[% data.$key %]", > [% ELSE %] > "[% key %]": "[% data.$key %]", > [% END %] >diff --git a/opac/opac-account-pay-paypal-return.pl b/opac/opac-account-pay-paypal-return.pl >new file mode 100755 >index 0000000..bf91f4d >--- /dev/null >+++ b/opac/opac-account-pay-paypal-return.pl >@@ -0,0 +1,121 @@ >+#!/usr/bin/perl >+ >+# Copyright Katipo Communications 2002 >+# Copyright Biblibre 2007,2010 >+# >+# 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use strict; >+use warnings; >+use utf8; >+ >+use CGI; >+use HTTP::Request::Common; >+use LWP::UserAgent; >+use URL::Encode qw(url_params_mixed); >+ >+use C4::Auth; >+use C4::Output; >+use C4::Members; >+use Koha::Database; >+use Koha::Accounts qw(AddCredit); >+use Koha::Accounts::CreditTypes; >+ >+my $cgi = new CGI; >+ >+unless ( C4::Context->preference('EnablePayPalOpacPayments') ) { >+ print $cgi->redirect("/cgi-bin/koha/errors/404.pl"); >+ exit; >+} >+ >+my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >+ { >+ template_name => "opac-account-pay-return.tt", >+ query => $cgi, >+ type => "opac", >+ authnotrequired => 0, >+ flagsrequired => { borrow => 1 }, >+ debug => 1, >+ } >+); >+ >+my $token = $cgi->param('token'); >+my $payer_id = $cgi->param('PayerID'); >+my $amount = $cgi->param('amount'); >+my @debit_id = $cgi->param('debit_id'); >+ >+my $ua = LWP::UserAgent->new; >+ >+my $url = >+ C4::Context->preference('PayPalSandboxMode') >+ ? 'https://api-3t.sandbox.paypal.com/nvp' >+ : 'https://api-3t.paypal.com/nvp'; >+ >+my $nvp_params = { >+ 'USER' => C4::Context->preference('PayPalUser'), >+ 'PWD' => C4::Context->preference('PayPalPwd'), >+ 'SIGNATURE' => C4::Context->preference('PayPalSignature'), >+ >+ # API Version and Operation >+ 'METHOD' => 'DoExpressCheckoutPayment', >+ 'VERSION' => '82.0', >+ >+ # API specifics for DoExpressCheckout >+ 'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', >+ 'PAYERID' => $payer_id, >+ 'TOKEN' => $token, >+ 'PAYMENTREQUEST_0_AMT' => $amount, >+}; >+ >+my $response = $ua->request( POST $url, $nvp_params ); >+ >+if ( $response->is_success ) { >+ my $params = url_params_mixed( $response->decoded_content ); >+ >+ if ( $params->{ACK} eq "Success" ) { >+ $amount = $params->{PAYMENTINFO_0_AMT}; >+ >+ my $borrower = >+ Koha::Database->new()->schema->resultset('Borrower') >+ ->find($borrowernumber); >+ >+ my $credit = AddCredit( >+ { >+ borrower => $borrower, >+ amount => $amount, >+ type => Koha::Accounts::CreditTypes::PayPal, >+ debit_id => \@debit_id, >+ } >+ ); >+ >+ $template->param( credit => $credit ); >+ >+ } >+ else { >+ $template->param( error => "PAYPAL_ERROR_PROCESSING" ); >+ } >+ >+} >+else { >+ $template->param( error => "PAYPAL_UNABLE_TO_CONNECT" ); >+} >+ >+$template->param( >+ borrower => GetMemberDetails($borrowernumber), >+ accountview => 1 >+); >+ >+output_html_with_http_headers( $cgi, $cookie, $template->output ); >diff --git a/opac/opac-account-pay.pl b/opac/opac-account-pay.pl >new file mode 100755 >index 0000000..88a880c >--- /dev/null >+++ b/opac/opac-account-pay.pl >@@ -0,0 +1,127 @@ >+#!/usr/bin/perl >+ >+# Copyright Katipo Communications 2002 >+# Copyright Biblibre 2007,2010 >+# >+# 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use strict; >+use warnings; >+use utf8; >+ >+use CGI; >+use HTTP::Request::Common; >+use LWP::UserAgent; >+use URL::Encode qw(url_encode url_params_mixed); >+use URI; >+ >+use C4::Auth; >+ >+my $cgi = new CGI; >+ >+unless ( C4::Context->preference('EnablePayPalOpacPayments') ) { >+ print $cgi->redirect("/cgi-bin/koha/errors/404.pl"); >+ exit; >+} >+ >+my ( $template, $borrowernumber, $cookie ) = get_template_and_user( >+ { >+ template_name => "opac-account-pay-return.tt", >+ query => $cgi, >+ type => "opac", >+ authnotrequired => 0, >+ flagsrequired => { borrow => 1 }, >+ debug => 1, >+ } >+); >+ >+my $amount_to_pay = $cgi->param('amount_to_pay'); >+my $payment_method = $cgi->param('payment_method'); >+my @debit_id = $cgi->param('debit_id'); >+ >+my $error = 0; >+if ( $payment_method eq 'paypal' ) { >+ my $ua = LWP::UserAgent->new; >+ >+ my $amount = url_encode($amount_to_pay); >+ >+ my $url = >+ C4::Context->preference('PayPalSandboxMode') >+ ? 'https://api-3t.sandbox.paypal.com/nvp' >+ : 'https://api-3t.paypal.com/nvp'; >+ >+ my $opac_base_url = C4::Context->preference('OPACBaseURL'); >+ >+ my $return_url = >+ URI->new( "http://" >+ . $opac_base_url >+ . "/cgi-bin/koha/opac-account-pay-paypal-return.pl" ); >+ $return_url->query_form( { amount => $amount, debit_id => \@debit_id } ); >+ >+ my $cancel_url = >+ URI->new( "http://" . $opac_base_url . "/cgi-bin/koha/opac-account.pl" ); >+ >+ my $nvp_params = { >+ 'USER' => C4::Context->preference('PayPalUser'), >+ 'PWD' => C4::Context->preference('PayPalPwd'), >+ 'SIGNATURE' => C4::Context->preference('PayPalSignature'), >+ >+ # API Version and Operation >+ 'METHOD' => 'SetExpressCheckout', >+ 'VERSION' => '82.0', >+ >+ # API specifics for SetExpressCheckout >+ 'NOSHIPPING' => 1, >+ 'REQCONFIRMSHIPPING' => 0, >+ 'ALLOWNOTE' => 0, >+ 'BRANDNAME' => C4::Context->preference('LibraryName'), >+ 'CANCELURL' => $cancel_url->as_string(), >+ 'RETURNURL' => $return_url->as_string(), >+ 'PAYMENTREQUEST_0_AMT' => $amount_to_pay, >+ 'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale', >+ 'PAYMENTREQUEST_0_ALLOWEDPAYMENTMETHOD' => 'InstantPaymentOnly', >+ 'PAYMENTREQUEST_0_DESC' => >+ C4::Context->preference('PayPalChargeDescription'), >+ }; >+ >+ my $response = $ua->request( POST $url, $nvp_params ); >+ >+ if ( $response->is_success ) { >+ my $params = url_params_mixed( $response->decoded_content ); >+ >+ if ( $params->{ACK} eq "Success" ) { >+ my $token = $params->{TOKEN}; >+ >+ my $redirect_url = >+ C4::Context->preference('PayPalSandboxMode') >+ ? "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=" >+ : "https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token="; >+ print $cgi->redirect( $redirect_url . $token ); >+ >+ } >+ else { >+ $template->param( error => "PAYPAL_ERROR_PROCESSING" ); >+ $error = 1; >+ } >+ >+ } >+ else { >+ $template->param( error => "PAYPAL_UNABLE_TO_CONNECT" ); >+ $error = 1; >+ } >+} >+ >+output_html_with_http_headers( $cgi, $cookie, $template->output ) if $error; >diff --git a/opac/opac-account.pl b/opac/opac-account.pl >index 4ff1554..af9b464 100755 >--- a/opac/opac-account.pl >+++ b/opac/opac-account.pl >@@ -21,7 +21,6 @@ > use strict; > use CGI; > use C4::Members; >-use C4::Circulation; > use C4::Auth; > use C4::Output; > use warnings; >-- >1.7.2.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 11622
:
24753
|
24754
|
24756
|
40520
|
40521
|
40522
|
40523
|
42241
|
42351
|
42352
|
42594
|
42649
|
42702
|
42705
|
42715
|
42733
|
42774
|
42775
|
42777
|
42778
|
42842
|
42843
|
42857
|
42858
|
42859
|
42860
|
42861
|
42862
|
42863
|
42864
|
42865
|
44419
|
44420
|
44421
|
44422
|
44423
|
44424
|
44425
|
44426
|
44427
|
46143
|
46144
|
46145
|
46146
|
46147
|
46148
|
46149
|
46150
|
46151