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

(-)a/Koha/Accounts/CreditTypes.pm (+10 lines)
Lines 58-63 sub IsValid { Link Here
58
          || $string eq Koha::Accounts::CreditTypes::Credit()
58
          || $string eq Koha::Accounts::CreditTypes::Credit()
59
          || $string eq Koha::Accounts::CreditTypes::Forgiven() );
59
          || $string eq Koha::Accounts::CreditTypes::Forgiven() );
60
60
61
    $is_valid ||= $string eq Koha::Accounts::CreditTypes::PayPal();
62
61
    unless ($is_valid) {
63
    unless ($is_valid) {
62
        $is_valid =
64
        $is_valid =
63
          Koha::Database->new()->schema->resultset('AuthorisedValue')
65
          Koha::Database->new()->schema->resultset('AuthorisedValue')
Lines 108-113 sub Forgiven { Link Here
108
    return 'FORGIVEN';
110
    return 'FORGIVEN';
109
}
111
}
110
112
113
=head2 PayPal
114
115
=cut
116
117
sub PayPal {
118
    return 'PAYPAL';
119
}
120
111
1;
121
1;
112
122
113
=head1 AUTHOR
123
=head1 AUTHOR
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref (+30 lines)
Lines 619-621 OPAC: Link Here
619
            - pref: PatronSelfRegistrationAdditionalInstructions
619
            - pref: PatronSelfRegistrationAdditionalInstructions
620
              type: textarea
620
              type: textarea
621
              class: html
621
              class: html
622
    Payments:
623
        -
624
            - pref: EnablePayPalOpacPayments
625
              default: 1
626
              choices:
627
                  yes: Allow
628
                  no: "Don't allow"
629
            - "patrons to make payments from the OPAC via PayPal in"
630
            - pref: PayPalSandboxMode 
631
              default: 1
632
              choices:
633
                  yes: "Sandbox"
634
                  no: "Production"
635
            - "mode."
636
        -
637
            - "The email address to recieve PayPal payments is "
638
            - pref: PayPalUser
639
              class: long
640
        -
641
            - "The password for the PayPal account to recieve payments is "
642
            - pref: PayPalPwd
643
              class: long
644
        -
645
            - "The signature for the PayPal account to recieve payments is "
646
            - pref: PayPalSignature
647
              class: long
648
        -
649
            - "The patron should see the charge description as "
650
            - pref: PayPalChargeDescription 
651
              class: long
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account-pay-return.tt (+392 lines)
Line 0 Link Here
1
[% USE Koha %]
2
[% USE KohaDates %]
3
[% USE Currency %]
4
5
[% INCLUDE 'doc-head-open.inc' %][% IF ( LibraryNameTitle ) %][% LibraryNameTitle %][% ELSE %]Koha online[% END %] catalog › Your fines and charges
6
[% INCLUDE 'doc-head-close.inc' %]
7
[% BLOCK cssinclude %][% END %]
8
9
10
</head>
11
<body id="opac-account" class="scrollto">
12
[% INCLUDE 'masthead.inc' %]
13
14
<div class="main">
15
    <ul class="breadcrumb">
16
        <li><a href="/cgi-bin/koha/opac-main.pl">Home</a> <span class="divider">&rsaquo;</span></li>
17
        <li><a href="/cgi-bin/koha/opac-user.pl">[% borrower.firstname %] [% borrower.surname %]</a> <span class="divider">&rsaquo;</span></li>
18
        <li><a href="#">Your fines and charges</a></li>
19
    </ul>
20
21
    <div class="container-fluid">
22
        <div class="row-fluid">
23
            <div class="span2">
24
                <div id="navigation">
25
                    [% INCLUDE 'navigation.inc' IsPatronPage=1 %]
26
                </div>
27
            </div>
28
            <div class="span10">
29
                <div id="useraccount" class="maincontent">
30
                    [% IF error %]
31
                        <div id="error" class="dialog alert">
32
                            <p><strong>Error:</strong> there was an problem processing your payment</p>
33
34
                            [% IF error == "PAYPAL_UNABLE_TO_CONNECT" %]
35
                                <p>Unable to connect to PayPal.</p>
36
                                <p>Please try again later.</p>
37
                            [% ELSIF error == "PAYPAL_ERROR_PROCESSING" %]
38
                                <p>Unable to verify payment.</p>
39
                                <p>Please contact the library to verify your payment.</p>
40
                            [% END %]
41
                        </div>
42
                    [% ELSIF credit %]
43
                        <div class="dialog message">
44
                            <p><strong>Payment applied:</strong> your payment of [% credit.amount_paid %] has been applied to your account</p>
45
                        </div>
46
                    [% END %]
47
48
                    <a href="/cgi-bin/koha/opac-account.pl">Return to fine details</a>
49
                </div> <!-- / #useraccount -->
50
            </div> <!-- / .span10 -->
51
        </div> <!-- / .row-fluid -->
52
    </div> <!-- / .container-fluid -->
53
</div> <!-- / .main -->
54
55
[% INCLUDE 'opac-bottom.inc' %]
56
[% INCLUDE 'datatables.inc' %]
57
58
<script type="text/javascript">
59
//<![CDATA[
60
$(document).ready(function() {
61
    $('#account-credits').hide();
62
    $('#account-debits-switcher').click(function() {
63
         $('#account-debits').slideUp();
64
         $('#account-credits').slideDown();
65
    });
66
    $('#account-credits-switcher').click(function() {
67
         $('#account-credits').slideUp();
68
         $('#account-debits').slideDown();
69
    });
70
71
    var anOpen = [];
72
    var sImageUrl = "[% interface %]/[% theme %]/images/";
73
74
    var debitsTable = $('#debits-table').dataTable( {
75
        "bProcessing": true,
76
        "aoColumns": [
77
            {
78
                "mDataProp": null,
79
                "sClass": "control center",
80
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
81
            },
82
            { "mDataProp": "debit_id" },
83
            { "mDataProp": "description" },
84
            { "mDataProp": "type" },
85
            { "mDataProp": "amount_original" },
86
            { "mDataProp": "amount_outstanding" },
87
            { "mDataProp": "created_on" },
88
            { "mDataProp": "updated_on" },
89
            {
90
                /* Payment selection checkboxes */
91
                [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %]
92
                    "bVisible": false,
93
                [% END %]
94
                "mDataProp": null,
95
                "sDefaultContent": "", 
96
                "fnRender": function ( o, val ) {
97
                    return val;
98
                },
99
                "mRender": function ( data, type, full ) {
100
                    if ( full.amount_outstanding_unformatted > 0 ) {
101
                        return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>"
102
                            + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>";
103
                    }
104
                }
105
            },
106
        ],
107
        "aaData": [
108
            [% FOREACH d IN debits %]
109
                {
110
                    [% PROCESS format_data data=d highlight='debit' %]
111
112
                    // Data for related item if there is one linked
113
                    "title": "[% d.item.biblio.title || d.deleted_item.biblio.title || d.deleted_item.deleted_biblio.title %]",
114
                    "biblionumber": "[% d.item.biblio.biblionumber || d.deleted_item.biblio.biblionumber %]",
115
                    "barcode": "[% d.item.barcode || d.deleted_item.barcode %]",
116
                    "itemnumber": "[% d.item.itemnumber %]", //This way itemnumber will be undef if deleted
117
118
119
                    // Data for related issue if there is one linked
120
                    [% IF d.issue %]
121
                        [% SET table = 'issue' %]
122
                    [% ELSIF d.old_issue %]
123
                        [% SET table = 'old_issue' %]
124
                    [% END %]
125
126
                    [% IF table %]
127
                        "issue": {
128
                            [% PROCESS format_data data=d.$table %]
129
                        },
130
                    [% END %]
131
132
133
                    "account_offsets": [
134
                        [% FOREACH ao IN d.account_offsets %]
135
                            {
136
                                [% PROCESS format_data data=ao highlight='offset'%]
137
138
                                "credit": {
139
                                    [% PROCESS format_data data=ao.credit highlight='credit' %]
140
                                }
141
                            },
142
                        [% END %]
143
                    ]
144
145
                },
146
            [% END %]
147
        ]
148
    } );
149
150
    $('#debits-table td.control').live( 'click', function () {
151
        var nTr = this.parentNode;
152
        var i = $.inArray( nTr, anOpen );
153
154
        if ( i === -1 ) {
155
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
156
            var nDetailsRow = debitsTable.fnOpen( nTr, fnFormatDebitDetails(debitsTable, nTr), 'details' );
157
            $('div.innerDetails', nDetailsRow).slideDown();
158
            anOpen.push( nTr );
159
        }
160
        else {
161
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
162
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
163
                debitsTable.fnClose( nTr );
164
                anOpen.splice( i, 1 );
165
            } );
166
        }
167
    } );
168
169
    var creditsTable = $('#credits-table').dataTable( {
170
        "bProcessing": true,
171
        "aoColumns": [
172
            {
173
                "mDataProp": null,
174
                "sClass": "control center",
175
                "sDefaultContent": '<img src="'+sImageUrl+'details_open.png'+'">'
176
            },
177
            { "mDataProp": "credit_id" },
178
            { "mDataProp": "notes" },
179
            { "mDataProp": "type" },
180
            { "mDataProp": "amount_paid" },
181
            { "mDataProp": "amount_remaining" },
182
            { "mDataProp": "created_on" },
183
            { "mDataProp": "updated_on" }
184
        ],
185
        "aaData": [
186
            [% FOREACH c IN credits %]
187
                {
188
                    [% PROCESS format_data data=c highlight='credit' %]
189
190
                    "account_offsets": [
191
                        [% FOREACH ao IN c.account_offsets %]
192
                            {
193
                                [% PROCESS format_data data=ao highlight='offset' %]
194
195
                                "debit": {
196
                                    [% PROCESS format_data data=ao.debit highlight='debit' %]
197
                                }
198
                            },
199
                        [% END %]
200
                    ]
201
202
                },
203
            [% END %]
204
        ]
205
    } );
206
207
    $('#credits-table td.control').live( 'click', function () {
208
        var nTr = this.parentNode;
209
        var i = $.inArray( nTr, anOpen );
210
211
        if ( i === -1 ) {
212
            $('img', this).attr( 'src', sImageUrl+"details_close.png" );
213
            var nDetailsRow = creditsTable.fnOpen( nTr, fnFormatCreditDetails(creditsTable, nTr), 'details' );
214
            $('div.innerDetails', nDetailsRow).slideDown();
215
            anOpen.push( nTr );
216
        }
217
        else {
218
            $('img', this).attr( 'src', sImageUrl+"details_open.png" );
219
            $('div.innerDetails', $(nTr).next()[0]).slideUp( function () {
220
                creditsTable.fnClose( nTr );
221
                anOpen.splice( i, 1 );
222
            } );
223
        }
224
    } );
225
226
    // Allow only numbers in ammount to pay
227
    $('#amount_to_pay').keypress(function(event) {
228
        end = $(this).val().split('.')[1];
229
        if (typeof end === 'undefined') {
230
            end = '';
231
        }
232
233
        if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) {
234
            event.preventDefault();
235
        }
236
    });
237
238
    // Update the "amount to pay" field whenever a fee checkbox is changed
239
    // Note, this is just a payment suggestion and can be changed to any amount
240
    $(".pay-checkbox" ).change(function() {
241
        var sum = 0;
242
        $("input[name='debit_id']:checked" ).each(function(i,n){
243
            sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() );
244
        });
245
        $('#amount_to_pay').val( sum.toFixed(2) );
246
    });
247
248
} );
249
250
function fnFormatDebitDetails( debitsTable, nTr ) {
251
    var oData = debitsTable.fnGetData( nTr );
252
253
    var sOut = "<div class='innerDetails' style='display:none;'>";
254
255
    var account_offsets = oData.account_offsets;
256
257
    sOut += "<ul>";
258
    if ( oData.title ) {
259
        sOut += "<li>" + _("Title: ");
260
        if ( oData.biblionumber ) {
261
            sOut += "<a href='/cgi-bin/koha/opac-detail.pl?biblionumber=" + oData.biblionumber + "'>";
262
        }
263
264
        sOut += oData.title;
265
266
        if ( oData.biblionumber ) {
267
            sOut += "</a>";
268
        }
269
270
        sOut += "</li>";
271
    }
272
273
    if ( oData.barcode ) {
274
        sOut += "<li>" + _("Barcode: ") + oData.barcode + "</li>";
275
    }
276
277
    if ( oData.notes ) {
278
        sOut += "<li>" + _("Notes: ") + oData.notes + "</li>";
279
    }
280
281
    sOut += "</ul>";
282
283
    if ( account_offsets.length ) {
284
        sOut +=
285
            "<div class='innerDetails'>" +
286
                "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" +
287
                    "<thead>" +
288
                        "<tr><th colspan='99'>" + _("Payments applied") + "</th></tr>" +
289
                        "<tr>" +
290
                            "<th>" + _("ID") + "</th>" +
291
                            "<th>" + _("Created on") + "</th>" +
292
                            "<th>" + _("Payment amount") + "</th>" +
293
                            "<th>" + _("Applied amount") + "</th>" +
294
                            "<th>" + _("Type") + "</th>" +
295
                            "<th>" + _("Notes") + "</th>" +
296
                        "</tr>" +
297
                    "</thead>" +
298
                    "<tbody>";
299
300
        for ( var i = 0; i < account_offsets.length; i++ ) {
301
            ao = account_offsets[i];
302
            sOut +=
303
            "<tr>" +
304
                "<td>" + ao.credit_id + "</td>" +
305
                "<td>" + ao.created_on + "</td>" +
306
                "<td>" + ao.credit.amount_paid + "</td>" +
307
                "<td>" + ao.amount + "</td>" +
308
                "<td>" + ao.credit.type + "</td>" +
309
                "<td>" + ao.credit.notes + "</td>" +
310
            "</tr>";
311
        }
312
313
        sOut +=
314
            "</tbody>"+
315
            "</table>";
316
    }
317
318
    sOut +=
319
        "</div>";
320
321
    return sOut;
322
}
323
324
function fnFormatCreditDetails( creditsTable, nTr ) {
325
    var oData = creditsTable.fnGetData( nTr );
326
327
    var sOut = "<div class='innerDetails' style='display:none;'>";
328
329
    var account_offsets = oData.account_offsets;
330
331
    if ( account_offsets.length ) {
332
        sOut +=
333
                "<table cellpadding='5' cellspacing='0' border='0' style='margin:10px;'>" +
334
                    "<thead>" +
335
                        "<tr><th colspan='99'>" + _("Fees paid") + "</th></tr>" +
336
                        "<tr>" +
337
                            "<th>" + _("ID") + "</th>" +
338
                            "<th>" + _("Description") + "</th>" +
339
                            "<th>" + _("Type") + "</th>" +
340
                            "<th>" + _("Amount") + "</th>" +
341
                            "<th>" + _("Remaining") + "</th>" +
342
                            "<th>" + _("Created on") + "</th>" +
343
                            "<th>" + _("Updated on") + "</th>" +
344
                            "<th>" + _("Notes") + "</th>" +
345
                        "</tr>" +
346
                    "</thead>" +
347
                    "<tbody>";
348
349
        for ( var i = 0; i < account_offsets.length; i++ ) {
350
            ao = account_offsets[i];
351
            sOut +=
352
            "<tr>" +
353
                "<td>" + ao.debit.debit_id + "</td>" +
354
                "<td>" + ao.debit.description + "</td>" +
355
                "<td>" + ao.debit.type + "</td>" +
356
                "<td>" + ao.debit.amount_original + "</td>" +
357
                "<td>" + ao.debit.amount_outstanding + "</td>" +
358
                "<td>" + ao.debit.created_on + "</td>" +
359
                "<td>" + ao.debit.updated_on + "</td>" +
360
                "<td>" + ao.debit.notes + "</td>" +
361
            "</tr>";
362
        }
363
364
        sOut +=
365
            "</tbody>"+
366
            "</table>";
367
    }
368
369
    sOut +=
370
        "</div>";
371
372
    return sOut;
373
}
374
375
//]]>
376
</script>
377
378
[% BLOCK jsinclude %][% END %]
379
380
[% BLOCK format_data %]
381
    [% FOREACH key IN data.result_source.columns %]
382
        [% IF key.match('^amount') %]
383
            "[% key %]": "[% data.$key FILTER $Currency %]",
384
            "[% key %]_unformatted": "[% data.$key %]",
385
        [% ELSIF key.match('_on$') %]
386
            "[% key %]": "[% data.$key | $KohaDates %]",
387
            "[% key %]_unformatted": "[% data.$key %]",
388
        [% ELSE %]
389
            "[% key %]": "[% data.$key %]",
390
        [% END %]
391
    [% END %]
392
[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-account.tt (-46 / +115 lines)
Lines 34-84 Link Here
34
                            <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
34
                            <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
35
                        </p>
35
                        </p>
36
36
37
                        <div>
37
                        <form action="/cgi-bin/koha/opac-account-pay.pl" method="post">
38
                            <div id="account-debits">
38
                            <div>
39
                                <a id="account-debits-switcher" href="#" onclick="return false">View payments</a>
39
                                <div id="account-debits">
40
                                <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table">
40
                                    <a id="account-debits-switcher" href="#" onclick="return false">View payments</a>
41
                                    <thead>
41
                                    <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table">
42
                                        <tr>
42
                                        <thead>
43
                                            <th colspan="99">Fees</th>
43
                                            <tr>
44
                                        </tr>
44
                                                <th colspan="99">Fees</th>
45
                                        <tr>
45
                                            </tr>
46
                                            <th></th>
46
                                            <tr>
47
                                            <th>ID</th>
47
                                                <th></th>
48
                                            <th>Description</th>
48
                                                <th>ID</th>
49
                                            <th>Type</th>
49
                                                <th>Description</th>
50
                                            <th>Amount</th>
50
                                                <th>Type</th>
51
                                            <th>Outsanding</th>
51
                                                <th>Amount</th>
52
                                            <th>Created on</th>
52
                                                <th>Outsanding</th>
53
                                            <th>Updated on</th>
53
                                                <th>Created on</th>
54
                                        </tr>
54
                                                <th>Updated on</th>
55
                                    </thead>
55
                                                <th>Pay</th>
56
                                    <tbody></tbody>
56
                                            </tr>
57
                                </table>
57
                                        </thead>
58
                                        <tbody></tbody>
59
                                    </table>
60
                                </div>
61
62
                                <div id="account-credits">
63
                                    <a id="account-credits-switcher" href="#"  onclick="return false">View fees</a>
64
                                    <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table">
65
                                        <thead>
66
                                            <tr>
67
                                                <th colspan="99">Payments</th>
68
                                            </tr>
69
                                            <tr>
70
                                                <th></th>
71
                                                <th>ID</th>
72
                                                <th>Notes</th>
73
                                                <th>Type</th>
74
                                                <th>Amount</th>
75
                                                <th>Remaining</th>
76
                                                <th>Created on</th>
77
                                                <th>Updated on</th>
78
                                            </tr>
79
                                        </thead>
80
                                        <tbody></tbody>
81
                                    </table>
82
                                </div>
83
84
                                [% IF Koha.Preference('EnablePayPalOpacPayments') %]
85
                                    <fieldset>
86
                                        <legend>Pay online</legend>
87
88
                                        <div>
89
                                            Amount to pay:
90
                                            [% Currency.symbol() %]<input type="text" id="amount_to_pay" name="amount_to_pay"/>
91
                                        </div>
92
93
                                        <div>
94
                                            <h6>Payment method:</h6>
95
                                            <input type="radio" name="payment_method" value="paypal" checked="checked"/>
96
                                            <label for="payment-method">
97
                                                <img src="https://www.paypal.com/en_US/i/logo/PayPal_mark_37x23.gif" align="left" style="margin-right:7px;">
98
                                            </label>
99
                                        </div>
100
101
                                        <br/>
102
103
                                        <div>
104
                                            <input type="submit" value="Make payment">
105
                                        </div>
106
                                    </fieldset>
107
                                [% END %]
58
                            </div>
108
                            </div>
59
109
                        </form>
60
                            <div id="account-credits">
61
                                <a id="account-credits-switcher" href="#"  onclick="return false">View fees</a>
62
                                <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table">
63
                                    <thead>
64
                                        <tr>
65
                                            <th colspan="99">Payments</th>
66
                                        </tr>
67
                                        <tr>
68
                                            <th></th>
69
                                            <th>ID</th>
70
                                            <th>Notes</th>
71
                                            <th>Type</th>
72
                                            <th>Amount</th>
73
                                            <th>Remaining</th>
74
                                            <th>Created on</th>
75
                                            <th>Updated on</th>
76
                                        </tr>
77
                                    </thead>
78
                                    <tbody></tbody>
79
                                </table>
80
                            </div>
81
                        </div>
82
                    [% ELSE %]
110
                    [% ELSE %]
83
                        <h4>You have no fines or charges</h4>
111
                        <h4>You have no fines or charges</h4>
84
                    [% END %]
112
                    [% END %]
Lines 121-127 $(document).ready(function() { Link Here
121
            { "mDataProp": "amount_original" },
149
            { "mDataProp": "amount_original" },
122
            { "mDataProp": "amount_outstanding" },
150
            { "mDataProp": "amount_outstanding" },
123
            { "mDataProp": "created_on" },
151
            { "mDataProp": "created_on" },
124
            { "mDataProp": "updated_on" }
152
            { "mDataProp": "updated_on" },
153
            {
154
                /* Payment selection checkboxes */
155
                [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %]
156
                    "bVisible": false,
157
                [% END %]
158
                "mDataProp": null,
159
                "sDefaultContent": "", 
160
                "fnRender": function ( o, val ) {
161
                    return val;
162
                },
163
                "mRender": function ( data, type, full ) {
164
                    if ( full.amount_outstanding_unformatted > 0 ) {
165
                        return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>"
166
                            + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>";
167
                    }
168
                }
169
            },
125
        ],
170
        ],
126
        "aaData": [
171
        "aaData": [
127
            [% FOREACH d IN debits %]
172
            [% FOREACH d IN debits %]
Lines 242-247 $(document).ready(function() { Link Here
242
        }
287
        }
243
    } );
288
    } );
244
289
290
    // Allow only numbers in ammount to pay
291
    $('#amount_to_pay').keypress(function(event) {
292
        end = $(this).val().split('.')[1];
293
        if (typeof end === 'undefined') {
294
            end = '';
295
        }
296
297
        if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) {
298
            event.preventDefault();
299
        }
300
    });
301
302
    // Update the "amount to pay" field whenever a fee checkbox is changed
303
    // Note, this is just a payment suggestion and can be changed to any amount
304
    $(".pay-checkbox" ).change(function() {
305
        var sum = 0;
306
        $("input[name='debit_id']:checked" ).each(function(i,n){
307
            sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() );
308
        });
309
        $('#amount_to_pay').val( sum.toFixed(2) );
310
    });
311
245
} );
312
} );
246
313
247
function fnFormatDebitDetails( debitsTable, nTr ) {
314
function fnFormatDebitDetails( debitsTable, nTr ) {
Lines 321-327 function fnFormatDebitDetails( debitsTable, nTr ) { Link Here
321
function fnFormatCreditDetails( creditsTable, nTr ) {
388
function fnFormatCreditDetails( creditsTable, nTr ) {
322
    var oData = creditsTable.fnGetData( nTr );
389
    var oData = creditsTable.fnGetData( nTr );
323
390
324
    var sOut = "<div class="innerDetails" style="display:none;">";
391
    var sOut = "<div class='innerDetails' style='display:none;'>";
325
392
326
    var account_offsets = oData.account_offsets;
393
    var account_offsets = oData.account_offsets;
327
394
Lines 378-385 function fnFormatCreditDetails( creditsTable, nTr ) { Link Here
378
    [% FOREACH key IN data.result_source.columns %]
445
    [% FOREACH key IN data.result_source.columns %]
379
        [% IF key.match('^amount') %]
446
        [% IF key.match('^amount') %]
380
            "[% key %]": "[% data.$key FILTER $Currency %]",
447
            "[% key %]": "[% data.$key FILTER $Currency %]",
448
            "[% key %]_unformatted": "[% data.$key %]",
381
        [% ELSIF key.match('_on$') %]
449
        [% ELSIF key.match('_on$') %]
382
            "[% key %]": "[% data.$key | $KohaDates %]",
450
            "[% key %]": "[% data.$key | $KohaDates %]",
451
            "[% key %]_unformatted": "[% data.$key %]",
383
        [% ELSE %]
452
        [% ELSE %]
384
            "[% key %]": "[% data.$key %]",
453
            "[% key %]": "[% data.$key %]",
385
        [% END %]
454
        [% END %]
(-)a/koha-tmpl/opac-tmpl/prog/en/includes/browser-strings.inc (+1 lines)
Lines 25-30 Link Here
25
            "WRITEOFF"                  : _("Writeoff"),
25
            "WRITEOFF"                  : _("Writeoff"),
26
            "FOUND"                     : _("Lost item found"),
26
            "FOUND"                     : _("Lost item found"),
27
            "FORGIVEN"                  : _("Forgiven"),
27
            "FORGIVEN"                  : _("Forgiven"),
28
            "PAYPAL"                    : _("PayPal"),
28
            [% FOREACH a IN AuthorisedValues.Get('MANUAL_CREDIT') %]
29
            [% FOREACH a IN AuthorisedValues.Get('MANUAL_CREDIT') %]
29
                "[% a.authorised_value %]" : "[% a.lib %]",
30
                "[% a.authorised_value %]" : "[% a.lib %]",
30
            [% END %]
31
            [% 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/koha-tmpl/opac-tmpl/prog/en/modules/opac-account.tt (-46 / +133 lines)
Lines 23-73 Link Here
23
                                <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
23
                                <h3>Account balance: [% borrower.account_balance | $Currency %]</h3>
24
                            </p>
24
                            </p>
25
25
26
                            <div>
26
                            <form action="/cgi-bin/koha/opac-account-pay.pl" method="post">
27
                                <div id="account-debits">
27
                                <div>
28
                                    <a id="account-debits-switcher" href="#" onclick="return false">View payments</a>
28
                                    <div id="account-debits">
29
                                    <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table">
29
                                        <a id="account-debits-switcher" href="#" onclick="return false">View payments</a>
30
                                        <thead>
30
                                        <table cellpadding="0" cellspacing="0" border="0" class="display" id="debits-table">
31
                                            <tr>
31
                                            <thead>
32
                                                <th colspan="99">Fees</th>
32
                                                <tr>
33
                                            </tr>
33
                                                    <th colspan="99">Fees</th>
34
                                            <tr>
34
                                                </tr>
35
                                                <th></th>
35
                                                <tr>
36
                                                <th>ID</th>
36
                                                    <th></th>
37
                                                <th>Description</th>
37
                                                    <th>ID</th>
38
                                                <th>Type</th>
38
                                                    <th>Description</th>
39
                                                <th>Amount</th>
39
                                                    <th>Type</th>
40
                                                <th>Outsanding</th>
40
                                                    <th>Amount</th>
41
                                                <th>Created on</th>
41
                                                    <th>Outsanding</th>
42
                                                <th>Updated on</th>
42
                                                    <th>Created on</th>
43
                                            </tr>
43
                                                    <th>Updated on</th>
44
                                        </thead>
44
                                                    <th>Pay</th>
45
                                        <tbody></tbody>
45
                                                </tr>
46
                                    </table>
46
                                            </thead>
47
                                            <tbody></tbody>
48
                                        </table>
49
                                    </div>
50
51
                                    <div id="account-credits">
52
                                        <a id="account-credits-switcher" href="#"  onclick="return false">View fees</a>
53
                                        <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table">
54
                                            <thead>
55
                                                <tr>
56
                                                    <th colspan="99">Payments</th>
57
                                                </tr>
58
                                                <tr>
59
                                                    <th></th>
60
                                                    <th>ID</th>
61
                                                    <th>Notes</th>
62
                                                    <th>Type</th>
63
                                                    <th>Amount</th>
64
                                                    <th>Remaining</th>
65
                                                    <th>Created on</th>
66
                                                    <th>Updated on</th>
67
                                                </tr>
68
                                            </thead>
69
                                            <tbody></tbody>
70
                                        </table>
71
                                    </div>
72
73
                                    [% IF Koha.Preference('EnablePayPalOpacPayments') %]
74
                                        <fieldset>
75
                                            <legend>Pay online</legend>
76
77
                                            <div>
78
                                                Amount to pay:
79
                                                [% Currency.symbol() %]<input type="text" id="amount_to_pay" name="amount_to_pay"/>
80
                                            </div>
81
82
                                            <div>
83
                                                <h6>Payment method:</h6>
84
                                                <input type="radio" name="payment_method" value="paypal" checked="checked"/>
85
                                                <label for="payment-method">
86
                                                    <img src="https://www.paypal.com/en_US/i/logo/PayPal_mark_37x23.gif" align="left" style="margin-right:7px;">
87
                                                </label>
88
                                            </div>
89
90
                                            <br/>
91
92
                                            <div>
93
                                                <input type="submit" value="Make payment">
94
                                            </div>
95
                                        </fieldset>
96
                                    [% END %]
47
                                </div>
97
                                </div>
48
98
                            </form>
49
                                <div id="account-credits">
50
                                    <a id="account-credits-switcher" href="#"  onclick="return false">View fees</a>
51
                                    <table cellpadding="0" cellspacing="0" border="0" class="display" id="credits-table">
52
                                        <thead>
53
                                            <tr>
54
                                                <th colspan="99">Payments</th>
55
                                            </tr>
56
                                            <tr>
57
                                                <th></th>
58
                                                <th>ID</th>
59
                                                <th>Notes</th>
60
                                                <th>Type</th>
61
                                                <th>Amount</th>
62
                                                <th>Remaining</th>
63
                                                <th>Created on</th>
64
                                                <th>Updated on</th>
65
                                            </tr>
66
                                        </thead>
67
                                        <tbody></tbody>
68
                                    </table>
69
                                </div>
70
                            </div>
71
                        [% ELSE %]
99
                        [% ELSE %]
72
                            <h4>You have no fines or charges</h4>
100
                            <h4>You have no fines or charges</h4>
73
                        [% END %]
101
                        [% END %]
Lines 122-128 $(document).ready(function() { Link Here
122
            { "mDataProp": "amount_original" },
150
            { "mDataProp": "amount_original" },
123
            { "mDataProp": "amount_outstanding" },
151
            { "mDataProp": "amount_outstanding" },
124
            { "mDataProp": "created_on" },
152
            { "mDataProp": "created_on" },
125
            { "mDataProp": "updated_on" }
153
            { "mDataProp": "updated_on" },
154
            {
155
                /* Payment selection checkboxes */
156
                [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %]
157
                    "bVisible": false,
158
                [% END %]
159
                "mDataProp": null,
160
                "sDefaultContent": "", 
161
                "fnRender": function ( o, val ) {
162
                    return val;
163
                },
164
                "mRender": function ( data, type, full ) {
165
                    if ( full.amount_outstanding_unformatted > 0 ) {
166
                        return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>"
167
                            + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>";
168
                    }
169
                }
170
            },
126
        ],
171
        ],
127
        "aaData": [
172
        "aaData": [
128
            [% FOREACH d IN debits %]
173
            [% FOREACH d IN debits %]
Lines 205-211 $(document).ready(function() { Link Here
205
            { "mDataProp": "amount_paid" },
250
            { "mDataProp": "amount_paid" },
206
            { "mDataProp": "amount_remaining" },
251
            { "mDataProp": "amount_remaining" },
207
            { "mDataProp": "created_on" },
252
            { "mDataProp": "created_on" },
208
            { "mDataProp": "updated_on" }
253
            { "mDataProp": "updated_on" },
254
            {
255
                /* Payment selection checkboxes */
256
                [% UNLESS Koha.Preference('EnablePayPalOpacPayments') %]
257
                    "bVisible": false,
258
                [% END %]
259
                "mDataProp": null,
260
                "sDefaultContent": "", 
261
                "fnRender": function ( o, val ) {
262
                    return val;
263
                },
264
                "mRender": function ( data, type, full ) {
265
                    if ( full.amount_outstanding_unformatted > 0 ) {
266
                        return "<input class='pay-checkbox' name='debit_id' value='" + full.debit_id + "' type='checkbox'/>"
267
                            + "<input type='hidden' id='amount_outstanding_" + full.debit_id + "' value='" + full.amount_outstanding_unformatted + "'/>";
268
                    }
269
                }
270
            },
209
        ],
271
        ],
210
        "aaData": [
272
        "aaData": [
211
            [% FOREACH c IN credits %]
273
            [% FOREACH c IN credits %]
Lines 248-253 $(document).ready(function() { Link Here
248
        }
310
        }
249
    } );
311
    } );
250
312
313
    // Allow only numbers in ammount to pay
314
    $('#amount_to_pay').keypress(function(event) {
315
        end = $(this).val().split('.')[1];
316
        if (typeof end === 'undefined') {
317
            end = '';
318
        }
319
320
        if ( ( ( event.which != 46 || $(this).val().indexOf('.') != -1 ) && ( event.which < 48 || event.which > 57 ) ) || ( end.length > 1 ) ) {
321
            event.preventDefault();
322
        }
323
    });
324
325
    // Update the "amount to pay" field whenever a fee checkbox is changed
326
    // Note, this is just a payment suggestion and can be changed to any amount
327
    $(".pay-checkbox" ).change(function() {
328
        var sum = 0;
329
        $("input[name='debit_id']:checked" ).each(function(i,n){
330
            sum += parseFloat( $( "#amount_outstanding_" + $(this).val() ).val() );
331
        });
332
        $('#amount_to_pay').val( sum.toFixed(2) );
333
    });
334
335
251
} );
336
} );
252
337
253
function fnFormatDebitDetails( debitsTable, nTr ) {
338
function fnFormatDebitDetails( debitsTable, nTr ) {
Lines 384-391 function fnFormatCreditDetails( creditsTable, nTr ) { Link Here
384
    [% FOREACH key IN data.result_source.columns %]
469
    [% FOREACH key IN data.result_source.columns %]
385
        [% IF key.match('^amount') %]
470
        [% IF key.match('^amount') %]
386
            "[% key %]": "[% data.$key FILTER $Currency %]",
471
            "[% key %]": "[% data.$key FILTER $Currency %]",
472
            "[% key %]_unformatted": "[% data.$key %]",
387
        [% ELSIF key.match('_on$') %]
473
        [% ELSIF key.match('_on$') %]
388
            "[% key %]": "[% data.$key | $KohaDates %]",
474
            "[% key %]": "[% data.$key | $KohaDates %]",
475
            "[% key %]_unformatted": "[% data.$key %]",
389
        [% ELSE %]
476
        [% ELSE %]
390
            "[% key %]": "[% data.$key %]",
477
            "[% key %]": "[% data.$key %]",
391
        [% END %]
478
        [% END %]
(-)a/opac/opac-account-pay-paypal-return.pl (+121 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 2 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::Members;
33
use Koha::Database;
34
use Koha::Accounts qw(AddCredit);
35
use Koha::Accounts::CreditTypes;
36
37
my $cgi = new CGI;
38
39
unless ( C4::Context->preference('EnablePayPalOpacPayments') ) {
40
    print $cgi->redirect("/cgi-bin/koha/errors/404.pl");
41
    exit;
42
}
43
44
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
45
    {
46
        template_name   => "opac-account-pay-return.tt",
47
        query           => $cgi,
48
        type            => "opac",
49
        authnotrequired => 0,
50
        flagsrequired   => { borrow => 1 },
51
        debug           => 1,
52
    }
53
);
54
55
my $token    = $cgi->param('token');
56
my $payer_id = $cgi->param('PayerID');
57
my $amount   = $cgi->param('amount');
58
my @debit_id = $cgi->param('debit_id');
59
60
my $ua = LWP::UserAgent->new;
61
62
my $url =
63
  C4::Context->preference('PayPalSandboxMode')
64
  ? 'https://api-3t.sandbox.paypal.com/nvp'
65
  : 'https://api-3t.paypal.com/nvp';
66
67
my $nvp_params = {
68
    'USER'      => C4::Context->preference('PayPalUser'),
69
    'PWD'       => C4::Context->preference('PayPalPwd'),
70
    'SIGNATURE' => C4::Context->preference('PayPalSignature'),
71
72
    # API Version and Operation
73
    'METHOD'  => 'DoExpressCheckoutPayment',
74
    'VERSION' => '82.0',
75
76
    # API specifics for DoExpressCheckout
77
    'PAYMENTREQUEST_0_PAYMENTACTION' => 'Sale',
78
    'PAYERID'                        => $payer_id,
79
    'TOKEN'                          => $token,
80
    'PAYMENTREQUEST_0_AMT'           => $amount,
81
};
82
83
my $response = $ua->request( POST $url, $nvp_params );
84
85
if ( $response->is_success ) {
86
    my $params = url_params_mixed( $response->decoded_content );
87
88
    if ( $params->{ACK} eq "Success" ) {
89
        $amount = $params->{PAYMENTINFO_0_AMT};
90
91
        my $borrower =
92
          Koha::Database->new()->schema->resultset('Borrower')
93
          ->find($borrowernumber);
94
95
        my $credit = AddCredit(
96
            {
97
                borrower => $borrower,
98
                amount   => $amount,
99
                type     => Koha::Accounts::CreditTypes::PayPal,
100
                debit_id => \@debit_id,
101
            }
102
        );
103
104
        $template->param( credit => $credit );
105
106
    }
107
    else {
108
        $template->param( error => "PAYPAL_ERROR_PROCESSING" );
109
    }
110
111
}
112
else {
113
    $template->param( error => "PAYPAL_UNABLE_TO_CONNECT" );
114
}
115
116
$template->param(
117
    borrower    => GetMemberDetails($borrowernumber),
118
    accountview => 1
119
);
120
121
output_html_with_http_headers( $cgi, $cookie, $template->output );
(-)a/opac/opac-account-pay.pl (+127 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 2 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_encode url_params_mixed);
29
use URI;
30
31
use C4::Auth;
32
33
my $cgi = new CGI;
34
35
unless ( C4::Context->preference('EnablePayPalOpacPayments') ) {
36
    print $cgi->redirect("/cgi-bin/koha/errors/404.pl");
37
    exit;
38
}
39
40
my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
41
    {
42
        template_name   => "opac-account-pay-return.tt",
43
        query           => $cgi,
44
        type            => "opac",
45
        authnotrequired => 0,
46
        flagsrequired   => { borrow => 1 },
47
        debug           => 1,
48
    }
49
);
50
51
my $amount_to_pay  = $cgi->param('amount_to_pay');
52
my $payment_method = $cgi->param('payment_method');
53
my @debit_id       = $cgi->param('debit_id');
54
55
my $error = 0;
56
if ( $payment_method eq 'paypal' ) {
57
    my $ua = LWP::UserAgent->new;
58
59
    my $amount = url_encode($amount_to_pay);
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 $opac_base_url = C4::Context->preference('OPACBaseURL');
67
68
    my $return_url =
69
      URI->new( "http://"
70
          . $opac_base_url
71
          . "/cgi-bin/koha/opac-account-pay-paypal-return.pl" );
72
    $return_url->query_form( { amount => $amount, debit_id => \@debit_id } );
73
74
    my $cancel_url =
75
      URI->new( "http://" . $opac_base_url . "/cgi-bin/koha/opac-account.pl" );
76
77
    my $nvp_params = {
78
        'USER'      => C4::Context->preference('PayPalUser'),
79
        'PWD'       => C4::Context->preference('PayPalPwd'),
80
        'SIGNATURE' => C4::Context->preference('PayPalSignature'),
81
82
        # API Version and Operation
83
        'METHOD'  => 'SetExpressCheckout',
84
        'VERSION' => '82.0',
85
86
        # API specifics for SetExpressCheckout
87
        'NOSHIPPING'           => 1,
88
        'REQCONFIRMSHIPPING'   => 0,
89
        'ALLOWNOTE'            => 0,
90
        'BRANDNAME'            => C4::Context->preference('LibraryName'),
91
        'CANCELURL'            => $cancel_url->as_string(),
92
        'RETURNURL'            => $return_url->as_string(),
93
        'PAYMENTREQUEST_0_AMT' => $amount_to_pay,
94
        'PAYMENTREQUEST_0_PAYMENTACTION'        => 'Sale',
95
        'PAYMENTREQUEST_0_ALLOWEDPAYMENTMETHOD' => 'InstantPaymentOnly',
96
        'PAYMENTREQUEST_0_DESC' =>
97
          C4::Context->preference('PayPalChargeDescription'),
98
    };
99
100
    my $response = $ua->request( POST $url, $nvp_params );
101
102
    if ( $response->is_success ) {
103
        my $params = url_params_mixed( $response->decoded_content );
104
105
        if ( $params->{ACK} eq "Success" ) {
106
            my $token = $params->{TOKEN};
107
108
            my $redirect_url =
109
              C4::Context->preference('PayPalSandboxMode')
110
              ? "https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token="
111
              : "https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=";
112
            print $cgi->redirect( $redirect_url . $token );
113
114
        }
115
        else {
116
            $template->param( error => "PAYPAL_ERROR_PROCESSING" );
117
            $error = 1;
118
        }
119
120
    }
121
    else {
122
        $template->param( error => "PAYPAL_UNABLE_TO_CONNECT" );
123
        $error = 1;
124
    }
125
}
126
127
output_html_with_http_headers( $cgi, $cookie, $template->output ) if $error;
(-)a/opac/opac-account.pl (-2 lines)
Lines 21-27 Link Here
21
use strict;
21
use strict;
22
use CGI;
22
use CGI;
23
use C4::Members;
23
use C4::Members;
24
use C4::Circulation;
25
use C4::Auth;
24
use C4::Auth;
26
use C4::Output;
25
use C4::Output;
27
use warnings;
26
use warnings;
28
- 

Return to bug 11622