tslittle / tiffanymaster

0 stars 0 forks source link

LP1175400: Possible to overallocate from a funding source #83

Open tslittle opened 3 years ago

tslittle commented 3 years ago

https://bugs.launchpad.net/evergreen/+bug/1175400

tslittle commented 3 years ago

Seems like this would be something to do from the Perl rather than the JS. Check and see how fund transfers or whatever work when there's a stop warning at play.

tslittle commented 2 years ago

Look here in Financials.pm

sub create_fund_alloc { 474 my($self, $conn, $auth, $fundalloc) = @; 475 my $e = new_editor(xact=>1, authtoken=>$auth); 476 return $e->die_event unless $e->checkauth; 477 478 # this action is equivalent to both debiting a funding source and crediting a fund 479 480 my $source = $e->retrieve_acq_funding_source($fund_alloc->funding_source) 481 or return $e->die_event; 482 return $e->die_event unless $e->allowed('MANAGE_FUNDING_SOURCE', $source->owner); 483 484 my $fund = $e->retrieve_acq_fund($fund_alloc->fund) or return $e->die_event; 485 return $e->die_event unless $e->allowed('MANAGE_FUND', $fund->org, $fund); 486 487 $fund_alloc->allocator($e->requestor->id); 488 $e->create_acq_fund_allocation($fund_alloc) or return $e->die_event; 489 $e->commit; 490 return $fund_alloc->id;

tslittle commented 2 years ago

I think that I would add something around line 486 to check the balance of the funding source against how much is being allocated? How does it know how much is being allocated? Oh, it looks like that's in the $fund_alloc variable, which probably is an array/hash that comes from the JS.

This is how stop/warning limits are being done in Order.pm:

sub fund_exceeds_balance_percent { 1024 my ($fund, $debitamount, $e, $which) = @; 1025 1026 my ($method_name, $event_name) = @{{ 1027 "warning" => [ 1028 "balance_warning_percent", "ACQ_FUND_EXCEEDS_WARN_PERCENT" 1029 ], 1030 "stop" => [ 1031 "balance_stop_percent", "ACQ_FUND_EXCEEDS_STOP_PERCENT" 1032 ] 1033 }->{$which}}; 1034 1035 if ($fund->$method_name) { 1036 my $balance = 1037 $e->search_acq_fund_combined_balance({"fund" => $fund->id})->[0]; 1038 my $allocations = 1039 $e->search_acq_fund_allocation_total({"fund" => $fund->id})->[0]; 1040 1041 $balance = ($balance) ? $balance->amount : 0; 1042 $allocations = ($allocations) ? $allocations->amount : 0; 1043 1044 if ( 1045 $allocations == 0 || # if no allocations were ever made, assume we have hit the stop percent 1046 ((($allocations - $balance + $debit_amount) / $allocations) * 100) > $fund->$method_name 1047 ) { 1048 $logger->info("fund would hit a limit: " . $fund->id . ", $balance, $debit_amount, $allocations, $method_name"); 1049 $e->event( 1050 new OpenILS::Event( 1051 $event_name, 1052 "payload" => { 1053 "fund" => $fund, "debit_amount" => $debit_amount 1054 } 1055 ) 1056 ); 1057 return 1; 1058 } 1059 } 1060 return 0;