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

(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+30 lines)
Lines 683-685 OPAC: Link Here
683
                subtype: Subtypes
683
                subtype: Subtypes
684
                sorting: Sorting
684
                sorting: Sorting
685
                location: Location and availability
685
                location: Location and availability
686
    Payments:
687
        -
688
            - pref: EnablePayPalOpacPayments
689
              default: 1
690
              choices:
691
                  yes: Allow
692
                  no: "Don't allow"
693
            - "patrons to make payments from the OPAC via PayPal in"
694
            - pref: PayPalSandboxMode 
695
              default: 1
696
              choices:
697
                  yes: "Sandbox"
698
                  no: "Production"
699
            - "mode."
700
        -
701
            - "The email address to recieve PayPal payments is "
702
            - pref: PayPalUser
703
              class: long
704
        -
705
            - "The password for the PayPal account to recieve payments is "
706
            - pref: PayPalPwd
707
              class: long
708
        -
709
            - "The signature for the PayPal account to recieve payments is "
710
            - pref: PayPalSignature
711
              class: long
712
        -
713
            - "The patron should see the charge description as "
714
            - pref: PayPalChargeDescription 
715
              class: long
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account-pay-return.tt (+377 lines)
Line 0 Link Here
1
[% USE Koha %]
2
[% USE KohaDates %]
3
4
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges
5
[% INCLUDE 'doc-head-close.inc' %]
6
[% BLOCK cssinclude %][% END %]
7
8
9
</head>
10
<body id="opac-account" class="scrollto">
11
[% INCLUDE 'masthead.inc' %]
12
13
<div class="main">
14
    <ul class="breadcrumb">
15
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
16
        <li><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]</a> <span class="divider">&rsaquo;</span></li>
17
        <li><a href="#">Your fines and charges</a></li>
18
    </ul>
19
20
    <div class="container-fluid">
21
        <div class="row-fluid">
22
            <div class="span2">
23
                <div id="navigation">
24
                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
25
                </div>
26
            </div>
27
            <div class="span10">
28
                <div id="useraccount" class="maincontent">
29
                    [% IF error %]
30
                        <div id="error" class="dialog alert">
31
                            <p><strong>Error:</strong> there was an problem processing your payment</p>
32
33
                            [% IF error == "PAYPAL_UNABLE_TO_CONNECT" %]
34
                                <p>Unable to connect to PayPal.</p>
35
                                <p>Please try again later.</p>
36
                            [% ELSIF error == "PAYPAL_ERROR_PROCESSING" %]
37
                                <p>Unable to verify payment.</p>
38
                                <p>Please contact the library to verify your payment.</p>
39
                            [% END %]
40
                        </div>
41
                    [% ELSIF credit %]
42
                        <div class="dialog message">
43
                            <p><strong>Payment applied:</strong> your payment of [% credit.amount_paid %] has been applied to your account</p>
44
                        </div>
45
                    [% END %]
46
47
                    <a href="/cgi-bin/koha/opac-account.pl">Return to fine details</a>
48
                </div> <!-- / #useraccount -->
49
            </div> <!-- / .span10 -->
50
        </div> <!-- / .row-fluid -->
51
    </div> <!-- / .container-fluid -->
52
</div> <!-- / .main -->
53
54
[% INCLUDE 'opac-bottom.inc' %]
55
[% INCLUDE 'datatables.inc' %]
56
57
<script type="text/javascript">
58
//<![CDATA[
59
$(document).ready(function() {
60
    $('#account-credits').hide();
61
    $('#account-debits-switcher').click(function() {
62
         $('#account-debits').slideUp();
63
         $('#account-credits').slideDown();
64
    });
65
    $('#account-credits-switcher').click(function() {
66
         $('#account-credits').slideUp();
67
         $('#account-debits').slideDown();
68
    });
69
70
    var anOpen = [];
71
    var sImageUrl = "[% interface %]/[% theme %]/images/";
72
73
    var debitsTable = $('#debits-table').dataTable( {
74
        "bProcessing": true,
75
        "aoColumns": [
76
            {
77
                "mDataProp": null,
78
                "sClass": "control center",
79
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
80
            },
81
            { "mDataProp": "debit_id" },
82
            { "mDataProp": "description" },
83
            { "mDataProp": "type" },
84
            { "mDataProp": "amount_original" },
85
            { "mDataProp": "amount_outstanding" },
86
            { "mDataProp": "created_on" },
87
            { "mDataProp": "updated_on" },
88
            {
89
                /* Payment selection checkboxes */
90
                [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %]
91
                    "bVisible": false,
92
                [% END %]
93
                "mDataProp": null,
94
                "sDefaultContent": "",
95
                "fnRender": function ( o, val ) {
96
                    return val;
97
                },
98
                "mRender": function ( data, type, full ) {
99
                    if ( full.amount_outstanding_unformatted > 0 ) {
100
                        return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>"
101
                            + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>";
102
                    }
103
                }
104
            },
105
        ],
106
        "aaData": [
107
            [% FOREACH d IN debits %]
108
                {
109
                    [% PROCESS format_data data=d highlight='debit' %]
110
111
                    // Data for related item if there is one linked
112
                    "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]",
113
                    "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]",
114
                    "barcode": "[% d.item.barcode || d.deleted_item.barcode %]",
115
                    "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted
116
117
118
                    // Data for related issue if there is one linked
119
                    [% IF d.issue %]
120
                        [% SET table = 'issue' %]
121
                    [% ELSIF d.old_issue %]
122
                        [% SET table = 'old_issue' %]
123
                    [% END %]
124
125
                    [% IF table %]
126
                        "issue": {
127
                            [% PROCESS format_data data=d.$table %]
128
                        },
129
                    [% END %]
130
131
132
                    "account_offsets": [
133
                        [% FOREACH ao IN d.account_offsets %]
134
                            {
135
                                [% PROCESS format_data data=ao highlight='offset'%]
136
137
                                "credit": {
138
                                    [% PROCESS format_data data=ao.credit highlight='credit' %]
139
                                }
140
                            },
141
                        [% END %]
142
                    ]
143
144
                },
145
            [% END %]
146
        ]
147
    } );
148
149
    $('#debits-table td.control').live( 'click', function () {
150
        var nTr = this.parentNode;
151
        var i = $.inArray( nTr, anOpen );
152
153
        if ( i === -1 ) {
154
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
155
            var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' );
156
            $('div.innerDetails', nDetailsRow).slideDown();
157
            anOpen.push( nTr );
158
        }
159
        else {
160
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
161
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
162
                debitsTable.fnClose( nTr );
163
                anOpen.splice( i, 1 );
164
            } );
165
        }
166
    } );
167
168
    var creditsTable = $('#credits-table').dataTable( {
169
        "bProcessing": true,
170
        "aoColumns": [
171
            {
172
                "mDataProp": null,
173
                "sClass": "control center",
174
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
175
            },
176
            { "mDataProp": "credit_id" },
177
            { "mDataProp": "notes" },
178
            { "mDataProp": "type" },
179
            { "mDataProp": "amount_paid" },
180
            { "mDataProp": "amount_remaining" },
181
            { "mDataProp": "created_on" },
182
            { "mDataProp": "updated_on" }
183
        ],
184
        "aaData": [
185
            [% FOREACH c IN credits %]
186
                {
187
                    [% PROCESS format_data data=c highlight='credit' %]
188
189
                    "account_offsets": [
190
                        [% FOREACH ao IN c.account_offsets %]
191
                            {
192
                                [% PROCESS format_data data=ao highlight='offset' %]
193
194
                                "debit": {
195
                                    [% PROCESS format_data data=ao.debit highlight='debit' %]
196
                                }
197
                            },
198
                        [% END %]
199
                    ]
200
201
                },
202
            [% END %]
203
        ]
204
    } );
205
206
    $('#credits-table td.control').live( 'click', function () {
207
        var nTr = this.parentNode;
208
        var i = $.inArray( nTr, anOpen );
209
210
        if ( i === -1 ) {
211
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
212
            var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' );
213
            $('div.innerDetails', nDetailsRow).slideDown();
214
            anOpen.push( nTr );
215
        }
216
        else {
217
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
218
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
219
                creditsTable.fnClose( nTr );
220
                anOpen.splice( i, 1 );
221
            } );
222
        }
223
    } );
224
225
    // Allow only numbers in ammount to pay
226
    $('#amount_to_pay').keypress(function(event) {
227
        end = $(this).val().split('.')[1];
228
        if (typeof end === 'undefined') {
229
            end = '';
230
        }
231
232
        if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) {
233
            event.preventDefault();
234
        }
235
    });
236
237
    // Update the "amount to pay" field whenever a fee checkbox is changed
238
    // Note, this is just a payment suggestion and can be changed to any amount
239
    $(".pay-checkbox" ).change(function() {
240
        var sum = 0;
241
        $("input[name='debit_id']:checked" ).each(function(i,n){
242
            sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() );
243
        });
244
        $('#amount_to_pay').val( sum.toFixed(2) );
245
    });
246
247
} );
248
249
function fnFormatDebitDetails( debitsTable, nTr ) {
250
    var oData = debitsTable.fnGetData( nTr );
251
252
    var sOut = "<div class='innerDetails' style='display:none;'>";
253
254
    var account_offsets = oData.account_offsets;
255
256
    sOut += "<ul>";
257
    if ( oData.title ) {
258
        sOut += "<li>" + _("Title: ");
259
        if ( oData.biblionumber ) {
260
            sOut += "<a href='/cgi-bin/koha/opac-detail.pl?biblionumber=" + oData.biblionumber + "'>";
261
        }
262
263
        sOut += oData.title;
264
265
        if ( oData.biblionumber ) {
266
            sOut += "</a>";
267
        }
268
269
        sOut += "</li>";
270
    }
271
272
    if ( oData.barcode ) {
273
        sOut += "<li>" + _("Barcode: ") + oData.barcode + "</li>";
274
    }
275
276
    if ( oData.notes ) {
277
        sOut += "<li>" + _("Notes: ") + oData.notes + "</li>";
278
    }
279
280
    sOut += "</ul>";
281
282
    if ( account_offsets.length ) {
283
        sOut +=
284
            "<div class='innerDetails'>" +
285
                "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" +
286
                    "<thead>" +
287
                        "<tr><th colspan='99'>" + _("Payments applied") + "</th></tr>" +
288
                        "<tr>" +
289
                            "<th>" + _("ID") + "</th>" +
290
                            "<th>" + _("Created on") + "</th>" +
291
                            "<th>" + _("Payment amount") + "</th>" +
292
                            "<th>" + _("Applied amount") + "</th>" +
293
                            "<th>" + _("Type") + "</th>" +
294
                            "<th>" + _("Notes") + "</th>" +
295
                        "</tr>" +
296
                    "</thead>" +
297
                    "<tbody>";
298
299
        for ( var i = 0; i < account_offsets.length; i++ ) {
300
            ao = account_offsets[i];
301
            sOut +=
302
            "<tr>" +
303
                "<td>" + ao.credit_id + "</td>" +
304
                "<td>" + ao.created_on + "</td>" +
305
                "<td>" + ao.credit.amount_paid + "</td>" +
306
                "<td>" + ao.amount + "</td>" +
307
                "<td>" + ao.credit.type + "</td>" +
308
                "<td>" + ao.credit.notes + "</td>" +
309
            "</tr>";
310
        }
311
312
        sOut +=
313
            "</tbody>"+
314
            "</table>";
315
    }
316
317
    sOut +=
318
        "</div>";
319
320
    return sOut;
321
}
322
323
function fnFormatCreditDetails( creditsTable, nTr ) {
324
    var oData = creditsTable.fnGetData( nTr );
325
326
    var sOut = "<div class='innerDetails' style='display:none;'>";
327
328
    var account_offsets = oData.account_offsets;
329
330
    if ( account_offsets.length ) {
331
        sOut +=
332
                "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" +
333
                    "<thead>" +
334
                        "<tr><th colspan='99'>" + _("Fees paid") + "</th></tr>" +
335
                        "<tr>" +
336
                            "<th>" + _("ID") + "</th>" +
337
                            "<th>" + _("Description") + "</th>" +
338
                            "<th>" + _("Type") + "</th>" +
339
                            "<th>" + _("Amount") + "</th>" +
340
                            "<th>" + _("Remaining") + "</th>" +
341
                            "<th>" + _("Created on") + "</th>" +
342
                            "<th>" + _("Updated on") + "</th>" +
343
                            "<th>" + _("Notes") + "</th>" +
344
                        "</tr>" +
345
                    "</thead>" +
346
                    "<tbody>";
347
348
        for ( var i = 0; i < account_offsets.length; i++ ) {
349
            ao = account_offsets[i];
350
            sOut +=
351
            "<tr>" +
352
                "<td>" + ao.debit.debit_id + "</td>" +
353
                "<td>" + ao.debit.description + "</td>" +
354
                "<td>" + ao.debit.type + "</td>" +
355
                "<td>" + ao.debit.amount_original + "</td>" +
356
                "<td>" + ao.debit.amount_outstanding + "</td>" +
357
                "<td>" + ao.debit.created_on + "</td>" +
358
                "<td>" + ao.debit.updated_on + "</td>" +
359
                "<td>" + ao.debit.notes + "</td>" +
360
            "</tr>";
361
        }
362
363
        sOut +=
364
            "</tbody>"+
365
            "</table>";
366
    }
367
368
    sOut +=
369
        "</div>";
370
371
    return sOut;
372
}
373
374
//]]>
375
</script>
376
377
[% BLOCK jsinclude %][% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt (-2 / +67 lines)
Lines 1-5 Link Here
1
[% USE Koha %]
1
[% USE Koha %]
2
[% USE KohaDates %]
2
[% USE KohaDates %]
3
[% SET ENABLE_OPAC_PAYMENTS = Koha.Preference('EnablePayPalOpacPayments') %]
3
4
4
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your fines and charges
5
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your fines and charges
5
[% INCLUDE 'doc-head-close.inc' %]
6
[% INCLUDE 'doc-head-close.inc' %]
Lines 25-36 Link Here
25
            </div>
26
            </div>
26
            <div class="span10">
27
            <div class="span10">
27
                <div id="useraccount" class="maincontent">
28
                <div id="useraccount" class="maincontent">
29
30
                    [% IF message %]
31
                        <div class="alert alert-info">
32
                            [% IF message == 'valid_payment' %]
33
                                <p>Your payment of $[% message_value %] has been processed sucessfully!</p>
34
                            [% ELSIF message == 'duplicate_payment' %]
35
                                <p>A payment with the transaction id <i>[% message_value %]</i> has already been posted to an account.</p>
36
                                <p>Please contact a librarian for details.</p>
37
                            [% ELSIF message == 'invalid_payment' %]
38
                                <p>The transaction id <i>[% message_value %]</i> for this payment is invalid.</p>
39
                                <p>Please contact a librarian for details.</p>
40
                            [% END %]
41
                        </div>
42
                    [% END %]
43
28
                    <h3>Fines and charges</h3>
44
                    <h3>Fines and charges</h3>
29
45
30
                    [% IF ( ACCOUNT_LINES ) %]
46
                    [% IF ( ACCOUNT_LINES ) %]
47
                        <form method="post" action="opac-account-pay.pl" class="form-horizontal">
31
                        <table class="table table-bordered table-striped">
48
                        <table class="table table-bordered table-striped">
32
                            <thead>
49
                            <thead>
33
                                <tr>
50
                                <tr>
51
                                    [% IF ENABLE_OPAC_PAYMENTS %]<th>&nbsp;</th>[% END %]
34
                                    <th>Date</th>
52
                                    <th>Date</th>
35
                                    <th>Description</th>
53
                                    <th>Description</th>
36
                                    <th>Fine amount</th>
54
                                    <th>Fine amount</th>
Lines 40-46 Link Here
40
58
41
                            <tfoot>
59
                            <tfoot>
42
                            <tr>
60
                            <tr>
43
                                <th class="sum" colspan="3">Total due</th>
61
                                [%- IF ENABLE_OPAC_PAYMENTS -%]
62
                                    [%- SET COLSPAN = 4 -%]
63
                                [%- ELSE -%]
64
                                    [%- SET COLSPAN = 3 -%]
65
                                [%- END -%]
66
                                <th class="sum" colspan="[% COLSPAN %]">Total due</th>
44
                                <td class="sum">[% total %]</td>
67
                                <td class="sum">[% total %]</td>
45
                            </tr>
68
                            </tr>
46
                            </tfoot>
69
                            </tfoot>
Lines 48-53 Link Here
48
                            <tbody>
71
                            <tbody>
49
                                [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
72
                                [% FOREACH ACCOUNT_LINE IN ACCOUNT_LINES %]
50
                                    [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
73
                                    [% IF ( ACCOUNT_LINE.odd ) %]<tr class="highlight">[% ELSE %]<tr>[% END %]
74
                                        [% IF ENABLE_OPAC_PAYMENTS %]
75
                                            <td>
76
                                                [% IF ACCOUNT_LINE.amountoutstanding > 0 %]
77
                                                    <input name="accountline" type="checkbox" class="checkbox-pay" id="checkbox-pay-[% ACCOUNT_LINE.accountlines_id %]" value="[% ACCOUNT_LINE.accountlines_id %]">
78
                                                [% END %]
79
                                            </td>
80
                                        [% END %]
51
                                        <td>[% ACCOUNT_LINE.date | $KohaDates %]</td>
81
                                        <td>[% ACCOUNT_LINE.date | $KohaDates %]</td>
52
                                        <td>
82
                                        <td>
53
                                            [% SWITCH ACCOUNT_LINE.accounttype %]
83
                                            [% SWITCH ACCOUNT_LINE.accounttype %]
Lines 81-86 Link Here
81
                            </tbody>
111
                            </tbody>
82
112
83
                        </table>
113
                        </table>
114
115
                            [% IF ENABLE_OPAC_PAYMENTS %]
116
                                <fieldset>
117
                                    <legend>Pay selected fines and charges</legend>
118
                                        <span class="help-block"><h3>Payment method</h3></span>
119
                                        <div class="control-group">
120
                                            <label class="radio">
121
                                                <input type="radio" name="payment_method" id="payment_method-paypal" value="paypal" checked="checked">
122
                                                <!-- PayPal Logo --><a href="https://www.paypal.com/webapps/mpp/paypal-popup" title="How PayPal Works" onclick="javascript:window.open('https://www.paypal.com/webapps/mpp/paypal-popup','WIPaypal','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=1060, height=700'); return false;"><img src="https://www.paypalobjects.com/webstatic/mktg/logo/AM_SbyPP_mc_vs_dc_ae.jpg" border="0" alt="PayPal Acceptance Mark"></a><!-- PayPal Logo -->
123
                                            </label>
124
                                        </div>
125
                                        <!-- look to the future
126
                                        <div class="control-group">
127
                                            <label class="radio">
128
                                                <input type="radio" name="payment_method" id="payment_method-paypal" value="paypal" checked="checked">
129
                                                PayPal
130
                                            </label>
131
                                        </div>
132
                                        -->
133
134
                                        <div class="control-group">
135
                                            <input type="hidden" id="payment-amount" name="payment_amount" value="0" />
136
                                            <button id="submit-pay" type="submit" class="btn" disabled="disabled">Make payment</button>
137
                                        </div>
138
                                </fieldset>
139
                            [% END %]
140
                        </form>
84
                    [% ELSE %]
141
                    [% ELSE %]
85
                        <h4>You have no fines or charges</h4>
142
                        <h4>You have no fines or charges</h4>
86
                    [% END %]
143
                    [% END %]
Lines 91-94 Link Here
91
</div> <!-- / .main -->
148
</div> <!-- / .main -->
92
149
93
[% INCLUDE 'opac-bottom.inc' %]
150
[% INCLUDE 'opac-bottom.inc' %]
94
[% BLOCK jsinclude %][% END %]
151
[% BLOCK jsinclude %]
152
<script type="text/javascript">
153
$( document ).ready(function() {
154
    $('.checkbox-pay').change( function() {
155
        $("#submit-pay").prop('disabled', ! $('.checkbox-pay:checked').length );
156
    });
157
});
158
</script>
159
[% END %]
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-account-pay-return.tt (+396 lines)
Line 0 Link Here
1
[% SET accountview = 1 %]
2
3
[% USE Koha %]
4
[% USE KohaDates %]
5
[% USE Currency %]
6
7
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog &rsaquo; Your fines and charges
8
[% INCLUDE 'doc-head-close.inc' %]
9
</head>
10
<body id="opac-account">
11
<div id="doc3" class="yui-t1">
12
    <div id="bd">
13
        [% INCLUDE 'masthead.inc' %]
14
        <div id="yui-main">
15
            <div class="yui-b">
16
                <div class="yui-g">
17
                    <div id="useraccount" class="container">
18
                        <h3><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]'s account</a> &#8674; Fines and charges</h3>
19
20
                        [% IF error %]
21
                            <div id="error" class="dialog alert">
22
                                <p><strong>Error:</strong> there was an problem processing your payment</p>
23
24
                                [% IF error == "PAYPAL_UNABLE_TO_CONNECT" %]
25
                                    <p>Unable to connect to PayPal.</p>
26
                                    <p>Please try again later.</p>
27
                                [% ELSIF error == "PAYPAL_ERROR_PROCESSING" %]
28
                                    <p>Unable to verify payment.</p>
29
                                    <p>Please contact the library to verify your payment.</p>
30
                                [% END %]
31
                            </div>
32
                        [% ELSIF credit %]
33
                            <div class="dialog message">
34
                                <p><strong>Payment applied:</strong> your payment of [% credit.amount_paid %] has been applied to your account</p>
35
                            </div>
36
                        [% END %]
37
38
                        <a href="/cgi-bin/koha/opac-account.pl">Return to fine details</a>
39
                    </div>
40
                </div>
41
            </div>
42
        </div>
43
44
    <div class="yui-b">
45
        <div id="leftmenus" class="container">
46
            [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
47
        </div>
48
    </div>
49
</div>
50
[% INCLUDE 'opac-bottom.inc' %]
51
52
[% INCLUDE 'datatables.inc' %]
53
[% INCLUDE 'browser-strings.inc' %]
54
55
<script type="text/javascript">
56
//<![CDATA[
57
$(document).ready(function() {
58
    $('#account-credits').hide();
59
    $('#account-debits-switcher').click(function() {
60
         $('#account-debits').slideUp();
61
         $('#account-credits').slideDown();
62
    });
63
    $('#account-credits-switcher').click(function() {
64
         $('#account-credits').slideUp();
65
         $('#account-debits').slideDown();
66
    });
67
68
    var anOpen = [];
69
    var sImageUrl = "[% interface %]/[% theme %]/images/";
70
71
    var debitsTable = $('#debits-table').dataTable( {
72
        "bProcessing": true,
73
        "aoColumns": [
74
            {
75
                "mDataProp": null,
76
                "sClass": "control center",
77
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
78
            },
79
            { "mDataProp": "debit_id" },
80
            { "mDataProp": "description" },
81
            {
82
                "mDataProp": "type",
83
                "fnRender": function ( o, val ) {
84
                    return STRINGS['DebitTypes'][val];
85
                },
86
            },
87
            { "mDataProp": "amount_original" },
88
            { "mDataProp": "amount_outstanding" },
89
            { "mDataProp": "created_on" },
90
            { "mDataProp": "updated_on" },
91
            {
92
                "mDataProp": null,
93
                "sDefaultContent": "",
94
                "fnRender": function ( o, val ) {
95
                    return val;
96
                },
97
                "mRender": function ( data, type, full ) {
98
                    if ( full.amount_outstanding_unformatted > 0 ) {
99
                        return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>"
100
                            + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>";
101
                    }
102
                }
103
            },
104
        ],
105
        "aaData": [
106
            [% FOREACH d IN debits %]
107
                {
108
                    [% PROCESS format_data data=d highlight='debit' %]
109
110
                    // Data for related item if there is one linked
111
                    "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]",
112
                    "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]",
113
                    "barcode": "[% d.item.barcode || d.deleted_item.barcode %]",
114
                    "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted
115
116
117
                    // Data for related issue if there is one linked
118
                    [% IF d.issue %]
119
                        [% SET table = 'issue' %]
120
                    [% ELSIF d.old_issue %]
121
                        [% SET table = 'old_issue' %]
122
                    [% END %]
123
124
                    [% IF table %]
125
                        "issue": {
126
                            [% PROCESS format_data data=d.$table %]
127
                        },
128
                    [% END %]
129
130
131
                    "account_offsets": [
132
                        [% FOREACH ao IN d.account_offsets %]
133
                            {
134
                                [% PROCESS format_data data=ao highlight='offset'%]
135
136
                                "credit": {
137
                                    [% PROCESS format_data data=ao.credit highlight='credit' %]
138
                                }
139
                            },
140
                        [% END %]
141
                    ]
142
143
                },
144
            [% END %]
145
        ]
146
    } );
147
148
    $('#debits-table td.control').live( 'click', function () {
149
        var nTr = this.parentNode;
150
        var i = $.inArray( nTr, anOpen );
151
152
        if ( i === -1 ) {
153
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
154
            var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' );
155
            $('div.innerDetails', nDetailsRow).slideDown();
156
            anOpen.push( nTr );
157
        }
158
        else {
159
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
160
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
161
                debitsTable.fnClose( nTr );
162
                anOpen.splice( i, 1 );
163
            } );
164
        }
165
    } );
166
167
    var creditsTable = $('#credits-table').dataTable( {
168
        "bProcessing": true,
169
        "aoColumns": [
170
            {
171
                "mDataProp": null,
172
                "sClass": "control center",
173
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
174
            },
175
            { "mDataProp": "credit_id" },
176
            { "mDataProp": "notes" },
177
            {
178
                "mDataProp": "type",
179
                "fnRender": function ( o, val ) {
180
                    return STRINGS['CreditTypes'][val];
181
                },
182
            },
183
            { "mDataProp": "amount_paid" },
184
            { "mDataProp": "amount_remaining" },
185
            { "mDataProp": "created_on" },
186
            { "mDataProp": "updated_on" }
187
        ],
188
        "aaData": [
189
            [% FOREACH c IN credits %]
190
                {
191
                    [% PROCESS format_data data=c highlight='credit' %]
192
193
                    "account_offsets": [
194
                        [% FOREACH ao IN c.account_offsets %]
195
                            {
196
                                [% PROCESS format_data data=ao highlight='offset' %]
197
198
                                "debit": {
199
                                    [% PROCESS format_data data=ao.debit highlight='debit' %]
200
                                }
201
                            },
202
                        [% END %]
203
                    ]
204
205
                },
206
            [% END %]
207
        ]
208
    } );
209
210
    $('#credits-table td.control').live( 'click', function () {
211
        var nTr = this.parentNode;
212
        var i = $.inArray( nTr, anOpen );
213
214
        if ( i === -1 ) {
215
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
216
            var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' );
217
            $('div.innerDetails', nDetailsRow).slideDown();
218
            anOpen.push( nTr );
219
        }
220
        else {
221
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
222
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
223
                creditsTable.fnClose( nTr );
224
                anOpen.splice( i, 1 );
225
            } );
226
        }
227
    } );
228
229
    // Allow only numbers in ammount to pay
230
    $('#amount_to_pay').keypress(function(event) {
231
        end = $(this).val().split('.')[1];
232
        if (typeof end === 'undefined') {
233
            end = '';
234
        }
235
236
        if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) {
237
            event.preventDefault();
238
        }
239
    });
240
241
    // Update the "amount to pay" field whenever a fee checkbox is changed
242
    // Note, this is just a payment suggestion and can be changed to any amount
243
    $(".pay-checkbox" ).change(function() {
244
        var sum = 0;
245
        $("input[name='debit_id']:checked" ).each(function(i,n){
246
            sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() );
247
        });
248
        $('#amount_to_pay').val( sum.toFixed(2) );
249
    });
250
251
252
} );
253
254
function fnFormatDebitDetails( debitsTable, nTr ) {
255
    var oData = debitsTable.fnGetData( nTr );
256
257
    var sOut = "<div class='innerDetails' style='display:none;'>";
258
259
    var account_offsets = oData.account_offsets;
260
261
    sOut += "<ul>";
262
    if ( oData.title ) {
263
        sOut += "<li>" + _("Title: ");
264
        if ( oData.biblionumber ) {
265
            sOut += "<a href='/cgi-bin/koha/opac-detail.pl?biblionumber=" + oData.biblionumber + "'>";
266
        }
267
268
        sOut += oData.title;
269
270
        if ( oData.biblionumber ) {
271
            sOut += "</a>";
272
        }
273
274
        sOut += "</li>";
275
    }
276
277
    if ( oData.barcode ) {
278
        sOut += "<li>" + _("Barcode: ") + oData.barcode + "</li>";
279
    }
280
281
    if ( oData.notes ) {
282
        sOut += "<li>" + _("Notes: ") + oData.notes + "</li>";
283
    }
284
285
    sOut += "</ul>";
286
287
    if ( account_offsets.length ) {
288
        sOut +=
289
            "<div class='innerDetails'>" +
290
                "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" +
291
                    "<thead>" +
292
                        "<tr><th colspan='99'>" + _("Payments applied") + "</th></tr>" +
293
                        "<tr>" +
294
                            "<th>" + _("ID") + "</th>" +
295
                            "<th>" + _("Created on") + "</th>" +
296
                            "<th>" + _("Payment amount") + "</th>" +
297
                            "<th>" + _("Applied amount") + "</th>" +
298
                            "<th>" + _("Type") + "</th>" +
299
                            "<th>" + _("Notes") + "</th>" +
300
                        "</tr>" +
301
                    "</thead>" +
302
                    "<tbody>";
303
304
        for ( var i = 0; i < account_offsets.length; i++ ) {
305
            ao = account_offsets[i];
306
            sOut +=
307
            "<tr>" +
308
                "<td>" + ao.credit_id + "</td>" +
309
                "<td>" + ao.created_on + "</td>" +
310
                "<td>" + ao.credit.amount_paid + "</td>" +
311
                "<td>" + ao.amount + "</td>" +
312
                "<td>" + ao.credit.type + "</td>" +
313
                "<td>" + ao.credit.notes + "</td>" +
314
            "</tr>";
315
        }
316
317
        sOut +=
318
            "</tbody>"+
319
            "</table>";
320
    }
321
322
    sOut +=
323
        "</div>";
324
325
    return sOut;
326
}
327
328
function fnFormatCreditDetails( creditsTable, nTr ) {
329
    var oData = creditsTable.fnGetData( nTr );
330
331
    var sOut = '<div class="innerDetails" style="display:none;">';
332
333
    var account_offsets = oData.account_offsets;
334
335
    if ( account_offsets.length ) {
336
        sOut +=
337
                "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" +
338
                    "<thead>" +
339
                        "<tr><th colspan='99'>" + _("Fees paid") + "</th></tr>" +
340
                        "<tr>" +
341
                            "<th>" + _("ID") + "</th>" +
342
                            "<th>" + _("Description") + "</th>" +
343
                            "<th>" + _("Type") + "</th>" +
344
                            "<th>" + _("Amount") + "</th>" +
345
                            "<th>" + _("Remaining") + "</th>" +
346
                            "<th>" + _("Created on") + "</th>" +
347
                            "<th>" + _("Updated on") + "</th>" +
348
                            "<th>" + _("Notes") + "</th>" +
349
                        "</tr>" +
350
                    "</thead>" +
351
                    "<tbody>";
352
353
        for ( var i = 0; i < account_offsets.length; i++ ) {
354
            ao = account_offsets[i];
355
            sOut +=
356
            "<tr>" +
357
                "<td>" + ao.debit.debit_id + "</td>" +
358
                "<td>" + ao.debit.description + "</td>" +
359
                "<td>" + ao.debit.type + "</td>" +
360
                "<td>" + ao.debit.amount_original + "</td>" +
361
                "<td>" + ao.debit.amount_outstanding + "</td>" +
362
                "<td>" + ao.debit.created_on + "</td>" +
363
                "<td>" + ao.debit.updated_on + "</td>" +
364
                "<td>" + ao.debit.notes + "</td>" +
365
            "</tr>";
366
        }
367
368
        sOut +=
369
            "</tbody>"+
370
            "</table>";
371
    }
372
373
    sOut +=
374
        "</div>";
375
376
    return sOut;
377
}
378
379
//]]>
380
</script>
381
382
[% BLOCK jsinclude %][% END %]
383
384
[% BLOCK format_data %]
385
    [% FOREACH key IN data.result_source.columns %]
386
        [% IF key.match('^amount') %]
387
            "[% key %]": "[% data.$key FILTER $Currency %]",
388
            "[% key %]_unformatted": "[% data.$key %]",
389
        [% ELSIF key.match('_on$') %]
390
            "[% key %]": "[% data.$key | $KohaDates %]",
391
            "[% key %]_unformatted": "[% data.$key %]",
392
        [% ELSE %]
393
            "[% key %]": "[% data.$key %]",
394
        [% END %]
395
    [% END %]
396
[% END %]
(-)a/opac/opac-account-pay-paypal-return.pl (+110 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright Katipo Communications 2002
4
# Copyright Biblibre 2007,2010
5
#
6
# This file is part of Koha.
7
#
8
# Koha is free software; you can redistribute it and/or modify it under the
9
# terms of the GNU General Public License as published by the Free Software
10
# Foundation; either version 3 of the License, or (at your option) any later
11
# version.
12
#
13
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License along
18
# with Koha; if not, write to the Free Software Foundation, Inc.,
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21
use strict;
22
use warnings;
23
use utf8;
24
25
use CGI;
26
use HTTP::Request::Common;
27
use LWP::UserAgent;
28
use URL::Encode qw(url_params_mixed);
29
30
use C4::Auth;
31
use C4::Output;
32
use C4::Accounts;
33
use C4::Members;
34
use Koha::Database;
35
36
my $cgi = new CGI;
37
38
unless ( C4::Context->preference('EnablePayPalOpacPayments') ) {
39
    print $cgi->redirect("/cgi-bin/koha/errors/404.pl");
40
    exit;
41
}
42
43
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
44
    {
45
        template_name   => "opac-account-pay-return.tt",
46
        query           => $cgi,
47
        type            => "opac",
48
        authnotrequired => 0,
49
        flagsrequired   => { borrow => 1 },
50
        debug           => 1,
51
    }
52
);
53
54
my $token    = $cgi->param('token');
55
my $payer_id = $cgi->param('PayerID');
56
my $amount   = $cgi->param('amount');
57
my @accountlines = $cgi->param('accountlines');
58
59
my $ua = LWP::UserAgent->new;
60
61
my $url =
62
  C4::Context->preference('PayPalSandboxMode')
63
  ? 'https://api-3t.sandbox.paypal.com/nvp'
64
  : 'https://api-3t.paypal.com/nvp';
65
66
my $nvp_params = {
67
    'USER'      => C4::Context->preference('PayPalUser'),
68
    'PWD'       => C4::Context->preference('PayPalPwd'),
69
    'SIGNATURE' => C4::Context->preference('PayPalSignature'),
70
71
    # API Version and Operation
72
    'METHOD'  => 'DoExpressCheckoutPayment',
73
    'VERSION' => '82.0',
74
75
    # API specifics for DoExpressCheckout
76
    'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
77
    'PAYERID'                        => $payer_id,
78
    'TOKEN'                          => $token,
79
    'PAYMENTREQUEST_0_AMT'           => $amount,
80
};
81
82
my $response = $ua->request( POST $url, $nvp_params );
83
84
if ( $response->is_success ) {
85
    my $params = url_params_mixed( $response->decoded_content );
86
87
    if ( $params->{ACK} eq "Success" ) {
88
        $amount = $params->{PAYMENTINFO_0_AMT};
89
90
        my $accountlines_rs = Koha::Database->new()->schema()->resultset('Accountline');
91
        foreach my $accountlines_id ( @accountlines ) {
92
            my $accountline = $accountlines_rs->find( $accountlines_id );
93
            makepayment( $accountlines_id, $borrowernumber, undef, $accountline->amountoutstanding, undef, undef, 'PayPal' );
94
        }
95
    }
96
    else {
97
        $template->param( error => "PAYPAL_ERROR_PROCESSING" );
98
    }
99
100
}
101
else {
102
    $template->param( error => "PAYPAL_UNABLE_TO_CONNECT" );
103
}
104
105
$template->param(
106
    borrower    => GetMemberDetails($borrowernumber),
107
    accountview => 1
108
);
109
110
output_html_with_http_headers( $cgi, $cookie, $template->output );
(-)a/opac/opac-account-pay.pl (+129 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
# Copyright Katipo Communications 2002
4
# Copyright Biblibre 2007,2010
5
#
6
# This file is part of Koha.
7
#
8
# Koha is free software; you can redistribute it and/or modify it under the
9
# terms of the GNU General Public License as published by the Free Software
10
# Foundation; either version 3 of the License, or (at your option) any later
11
# version.
12
#
13
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
14
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
16
#
17
# You should have received a copy of the GNU General Public License along
18
# with Koha; if not, write to the Free Software Foundation, Inc.,
19
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20
21
use utf8;
22
23
use Modern::Perl;
24
25
use CGI;
26
use HTTP::Request::Common;
27
use LWP::UserAgent;
28
use URL::Encode qw(url_encode url_params_mixed);
29
use URI;
30
31
use C4::Auth;
32
use C4::Output;
33
use C4::Context;
34
use Koha::Database;
35
36
my $cgi = new CGI;
37
38
unless ( C4::Context->preference('EnablePayPalOpacPayments') ) {
39
    print $cgi->redirect("/cgi-bin/koha/errors/404.pl");
40
    exit;
41
}
42
43
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
44
    {
45
        template_name   => "opac-account-pay-return.tt",
46
        query           => $cgi,
47
        type            => "opac",
48
        authnotrequired => 0,
49
        flagsrequired   => { borrow => 1 },
50
        debug           => 1,
51
    }
52
);
53
54
my $payment_method = $cgi->param('payment_method');
55
my @accountlines = $cgi->param('accountline');
56
57
my $amount_to_pay =
58
  Koha::Database->new()->schema()->resultset('Accountline')->search( { accountlines_id => { -in => \@accountlines } } )
59
  ->get_column('amountoutstanding')->sum();
60
$amount_to_pay = sprintf( "%.2f", $amount_to_pay );
61
62
my $error = 0;
63
if ( $payment_method eq 'paypal' ) {
64
    my $ua = LWP::UserAgent->new;
65
66
    my $amount = url_encode($amount_to_pay);
67
68
    my $url =
69
      C4::Context->preference('PayPalSandboxMode')
70
      ? 'https://api-3t.sandbox.paypal.com/nvp'
71
      : 'https://api-3t.paypal.com/nvp';
72
73
    my $opac_base_url = C4::Context->preference('OPACBaseURL');
74
75
    my $return_url = URI->new( $opac_base_url . "/cgi-bin/koha/opac-account-pay-paypal-return.pl" );
76
    $return_url->query_form( { amount => $amount, accountlines => \@accountlines } );
77
78
    my $cancel_url = URI->new( $opac_base_url . "/cgi-bin/koha/opac-account.pl" );
79
80
    my $nvp_params = {
81
        'USER'      => C4::Context->preference('PayPalUser'),
82
        'PWD'       => C4::Context->preference('PayPalPwd'),
83
        'SIGNATURE' => C4::Context->preference('PayPalSignature'),
84
85
        # API Version and Operation
86
        'METHOD'  => 'SetExpressCheckout',
87
        'VERSION' => '82.0',
88
89
        # API specifics for SetExpressCheckout
90
        'NOSHIPPING'                            => 1,
91
        'REQCONFIRMSHIPPING'                    => 0,
92
        'ALLOWNOTE'                             => 0,
93
        'BRANDNAME'                             => C4::Context->preference('LibraryName'),
94
        'CANCELURL'                             => $cancel_url->as_string(),
95
        'RETURNURL'                             => $return_url->as_string(),
96
        'PAYMENTREQUEST_0_AMT'                  => $amount_to_pay,
97
        'PAYMENTREQUEST_0_PAYMENTACTION'        => 'Sale',
98
        'PAYMENTREQUEST_0_ALLOWEDPAYMENTMETHOD' => 'InstantPaymentOnly',
99
        'PAYMENTREQUEST_0_DESC'                 => C4::Context->preference('PayPalChargeDescription'),
100
    };
101
102
    my $response = $ua->request( POST $url, $nvp_params );
103
104
    if ( $response->is_success ) {
105
        my $params = url_params_mixed( $response->decoded_content );
106
107
        if ( $params->{ACK} eq "Success" ) {
108
            my $token = $params->{TOKEN};
109
110
            my $redirect_url =
111
              C4::Context->preference('PayPalSandboxMode')
112
              ? "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token="
113
              : "https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=";
114
            print $cgi->redirect( $redirect_url . $token );
115
116
        }
117
        else {
118
            $template->param( error => "PAYPAL_ERROR_PROCESSING" );
119
            $error = 1;
120
        }
121
122
    }
123
    else {
124
        $template->param( error => "PAYPAL_UNABLE_TO_CONNECT" );
125
        $error = 1;
126
    }
127
}
128
129
output_html_with_http_headers( $cgi, $cookie, $template->output ) if $error;
(-)a/opac/opac-account.pl (-5 / +5 lines)
Lines 22-28 Link Here
22
use strict;
22
use strict;
23
use CGI qw ( -utf8 );
23
use CGI qw ( -utf8 );
24
use C4::Members;
24
use C4::Members;
25
use C4::Circulation;
26
use C4::Auth;
25
use C4::Auth;
27
use C4::Output;
26
use C4::Output;
28
use warnings;
27
use warnings;
Lines 68-77 foreach my $row (@$accts) { Link Here
68
    $num++;
67
    $num++;
69
}
68
}
70
69
71
$template->param (
70
$template->param(
72
    ACCOUNT_LINES => $accts,
71
    ACCOUNT_LINES => $accts,
73
    total => sprintf( "%.2f", $total ),
72
    total         => sprintf( "%.2f", $total ),
74
	accountview => 1
73
    accountview   => 1,
74
    message       => $query->param('message') || q{},
75
    message_value => $query->param('message_value') || q{},
75
);
76
);
76
77
77
output_html_with_http_headers $query, $cookie, $template->output;
78
output_html_with_http_headers $query, $cookie, $template->output;
78
- 

Return to bug 11622