]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/perlmods/OpenILS/Application/Storage/Publisher/money.pm
moving fine generation into the storage server so that the biz logic can force it
[Evergreen.git] / Open-ILS / src / perlmods / OpenILS / Application / Storage / Publisher / money.pm
1 package OpenILS::Application::Storage::Publisher::money;
2 use base qw/OpenILS::Application::Storage/;
3 use OpenSRF::Utils qw/:datetime/;
4 use OpenSRF::Utils::Logger qw/:level/;
5 use OpenSRF::EX qw/:try/;
6 use OpenILS::Utils::Fieldmapper;
7 use DateTime;
8 use DateTime::Format::ISO8601;
9
10 my $log = 'OpenSRF::Utils::Logger';
11
12 sub xact_summary {
13         my $self = shift;
14         my $client = shift;
15         my $xact = shift || '';
16
17         my $sql = <<"   SQL";
18                 SELECT  balance_owed
19                   FROM  money.usr_billable_summary_xact
20                   WHERE transaction = ?
21         SQL
22
23         return money::billing->db_Main->selectrow_hashref($sql, {}, "$xact");
24 }
25 #__PACKAGE__->register_method(
26 #       api_name        => 'open-ils.storage.money.billing.billable_transaction_summary',
27 #       api_level       => 1,
28 #       method          => 'xact_summary',
29 #);
30
31 my $parser = DateTime::Format::ISO8601->new;
32 sub generate_fines {
33         my $self = shift;
34         my $client = shift;
35         my $grace = shift;
36         my $circ = shift;
37         
38         
39         my @circs;
40         if ($circ) {
41                 push @circs,
42                         $self->method_lookup(
43                                 'open-ils.storage.direct.action.circulation.search_where'
44                         )->run( { id => $circ, stop_fines => undef } );
45         } else {
46                 push @circs, $self->method_lookup('open-ils.storage.action.circulation.overdue')->run( $grace );
47         }
48
49         for my $c (@circs) {
50         
51                 try {
52                         my $due_dt = $parser->parse_datetime( clense_ISO8601( $c->due_date ) );
53         
54                         my $due = $due_dt->epoch;
55                         my $now = time;
56                         my $fine_interval = interval_to_seconds( $c->fine_interval );
57         
58                         if ( interval_to_seconds( $c->fine_interval ) >= interval_to_seconds('1d') ) {  
59                                 my $tz_offset_s = 0;;
60                                 if ($due_dt->strftime('%z') =~ /(-|\+)(\d{2}):?(\d{2})/) {
61                                         $tz_offset_s = $1 . interval_to_seconds( "${2}h ${3}m"); 
62                                 }
63         
64                                 $due -= ($due % $fine_interval) + $tz_offset_s;
65                                 $now -= ($now % $fine_interval) + $tz_offset_s;
66                         }
67         
68                         $client->respond(
69                                 "ARG! Overdue circulation ".$c->id.
70                                 " for item ".$c->target_copy.
71                                 " (user ".$c->usr.").\n".
72                                 "\tItem was due on or before: ".localtime($due)."\n");
73         
74                         my ($fine) = $self->method_lookup('open-ils.storage.direct.money.billing.search')->run(
75                                 { xact => $c->id, voided => 'f' },
76                                 { order_by => 'billing_ts DESC', limit => '1' }
77                         );
78         
79                         my $last_fine;
80                         if ($fine) {
81                                 $last_fine = $parser->parse_datetime( clense_ISO8601( $fine->billing_ts ) )->epoch;
82                         } else {
83                                 $last_fine = $due;
84                                 $last_fine += $fine_interval * $grace;
85                         }
86         
87                         my $pending_fine_count = int( ($now - $last_fine) / $fine_interval ); 
88                         unless($pending_fine_count) {
89                                 $client->respond( "\tNo fines to create.  " );
90                                 if ($grace && $now < $due + $fine_interval * $grace) {
91                                         $client->respond( "Still inside grace period of: ". seconds_to_interval( $fine_interval * $grace)."\n" );
92                                 } else {
93                                         $client->respond( "Last fine generated for: ".localtime($last_fine)."\n" );
94                                 }
95                                 next;
96                         }
97         
98                         $client->respond( "\t$pending_fine_count pending fine(s)\n" );
99         
100                         for my $bill (1 .. $pending_fine_count) {
101         
102                                 my ($total) = $self->method_lookup('open-ils.storage.direct.money.billable_transaction_summary.retrieve')->run( $c->id );
103         
104                                 if ($total && $total->balance_owed > $c->max_fine) {
105                                         $c->stop_fines('MAXFINES');
106                                         $self->method_lookup('open-ils.storage.direct.action.circulation.update')->run( $c );
107                                         $client->respond(
108                                                 "\tMaximum fine level of ".$c->max_fine.
109                                                 " reached for this circulation.\n".
110                                                 "\tNo more fines will be generated.\n" );
111                                         last;
112                                 }
113         
114                                 my $billing = new Fieldmapper::money::billing;
115                                 $billing->xact( $c->id );
116                                 $billing->note( "Overdue Fine" );
117                                 $billing->amount( $c->recuring_fine );
118         
119                                 $billing->billing_ts(
120                                         DateTime->from_epoch( epoch => $last_fine + $fine_interval * $bill )->strftime('%FT%T%z')
121                                 );
122         
123                                 $client->respond(
124                                         "\t\tCreating fine of ".$billing->amount." for period starting ".
125                                         localtime(
126                                                 $parser->parse_datetime(
127                                                         clense_ISO8601( $billing->billing_ts )
128                                                 )->epoch
129                                         )."\n" );
130         
131                                 $self->method_lookup('open-ils.storage.direct.money.billing.create')->run( $billing );
132                         }
133                 } catch Error with {
134                         my $e = shift;
135                         $client->respond( "Error processing overdue circulation [".$c->id."]:\n\n$e\n" );
136                 };
137         }
138 }
139 __PACKAGE__->register_method(
140         api_name        => 'open-ils.storage.action.circulation.overdue.generate_fines',
141         api_level       => 1,
142         stream          => 1,
143         method          => 'generate_fines',
144 );
145
146
147 1;