<?php
/**
* Check if an invoice should be marked as paid based on the transaction amount
* Considers a threshold of 1% below invoice amount to account for payment fees
*
* @param float $txAmount The actual transaction/payment amount
* @param float $invAmount The invoice amount
* @return bool True if the payment meets the threshold criteria
*/
function checkInvoicePayed( $txAmount , $invAmount ) {
$threshold = $invAmount * 0.99 ; // 1% threshold
return $txAmount >= $threshold ;
}
/**
* Calculate the invoice amount for which a given transaction amount
* would be at exactly the 1% threshold boundary
*
* @param float $txAmount The transaction amount to test
* @return float The calculated invoice amount
*/
function challengeCheckInvoicePayed( $txAmount ) {
// If txAmount = invAmount * 0.99
// Then invAmount = txAmount / 0.99
return $txAmount / 0.99 ;
}
/**
* Test the payment checking functions with various edge cases
*/
function runTests( ) {
$testCases = [
[ 'tx' => 100 , 'expected_inv' => 101.01 ] ,
[ 'tx' => 99 , 'expected_inv' => 100 ] ,
[ 'tx' => 0.99 , 'expected_inv' => 1 ] ,
[ 'tx' => 1000 , 'expected_inv' => 1010.10 ] ,
] ;
foreach ( $testCases as $test ) {
$calculatedInv = challengeCheckInvoicePayed( $test [ 'tx' ] ) ;
$isPassed = checkInvoicePayed( $test [ 'tx' ] , $calculatedInv ) ;
"Test case: TX=%.2f , Calculated INV=%.2f , Expected INV=%.2f , Is at threshold: %s \n " ,
$test [ 'tx' ] ,
$calculatedInv ,
$test [ 'expected_inv' ] ,
$isPassed ? 'Yes' : 'No'
) ;
// Verify the boundary condition
$slightlyMore = checkInvoicePayed( $test [ 'tx' ] , $calculatedInv - 0.01 ) ;
$slightlyLess = checkInvoicePayed( $test [ 'tx' ] , $calculatedInv + 0.01 ) ;
if ( $slightlyMore !== true || $slightlyLess !== false ) {
echo "WARNING: Boundary condition failed for TX amount " . $test [ 'tx' ] . "\n " ;
}
}
}
// Run the tests
runTests( ) ;
PD9waHAKCi8qKgogKiBDaGVjayBpZiBhbiBpbnZvaWNlIHNob3VsZCBiZSBtYXJrZWQgYXMgcGFpZCBiYXNlZCBvbiB0aGUgdHJhbnNhY3Rpb24gYW1vdW50CiAqIENvbnNpZGVycyBhIHRocmVzaG9sZCBvZiAxJSBiZWxvdyBpbnZvaWNlIGFtb3VudCB0byBhY2NvdW50IGZvciBwYXltZW50IGZlZXMKICogCiAqIEBwYXJhbSBmbG9hdCAkdHhBbW91bnQgVGhlIGFjdHVhbCB0cmFuc2FjdGlvbi9wYXltZW50IGFtb3VudAogKiBAcGFyYW0gZmxvYXQgJGludkFtb3VudCBUaGUgaW52b2ljZSBhbW91bnQKICogQHJldHVybiBib29sIFRydWUgaWYgdGhlIHBheW1lbnQgbWVldHMgdGhlIHRocmVzaG9sZCBjcml0ZXJpYQogKi8KZnVuY3Rpb24gY2hlY2tJbnZvaWNlUGF5ZWQoJHR4QW1vdW50LCAkaW52QW1vdW50KSB7CiAgICAkdGhyZXNob2xkID0gJGludkFtb3VudCAqIDAuOTk7IC8vIDElIHRocmVzaG9sZAogICAgcmV0dXJuICR0eEFtb3VudCA+PSAkdGhyZXNob2xkOwp9CgovKioKICogQ2FsY3VsYXRlIHRoZSBpbnZvaWNlIGFtb3VudCBmb3Igd2hpY2ggYSBnaXZlbiB0cmFuc2FjdGlvbiBhbW91bnQKICogd291bGQgYmUgYXQgZXhhY3RseSB0aGUgMSUgdGhyZXNob2xkIGJvdW5kYXJ5CiAqIAogKiBAcGFyYW0gZmxvYXQgJHR4QW1vdW50IFRoZSB0cmFuc2FjdGlvbiBhbW91bnQgdG8gdGVzdAogKiBAcmV0dXJuIGZsb2F0IFRoZSBjYWxjdWxhdGVkIGludm9pY2UgYW1vdW50CiAqLwpmdW5jdGlvbiBjaGFsbGVuZ2VDaGVja0ludm9pY2VQYXllZCgkdHhBbW91bnQpIHsKICAgIC8vIElmIHR4QW1vdW50ID0gaW52QW1vdW50ICogMC45OQogICAgLy8gVGhlbiBpbnZBbW91bnQgPSB0eEFtb3VudCAvIDAuOTkKICAgIHJldHVybiAkdHhBbW91bnQgLyAwLjk5Owp9CgovKioKICogVGVzdCB0aGUgcGF5bWVudCBjaGVja2luZyBmdW5jdGlvbnMgd2l0aCB2YXJpb3VzIGVkZ2UgY2FzZXMKICovCmZ1bmN0aW9uIHJ1blRlc3RzKCkgewogICAgJHRlc3RDYXNlcyA9IFsKICAgICAgICBbJ3R4JyA9PiAxMDAsICdleHBlY3RlZF9pbnYnID0+IDEwMS4wMV0sCiAgICAgICAgWyd0eCcgPT4gOTksICdleHBlY3RlZF9pbnYnID0+IDEwMF0sCiAgICAgICAgWyd0eCcgPT4gMC45OSwgJ2V4cGVjdGVkX2ludicgPT4gMV0sCiAgICAgICAgWyd0eCcgPT4gMTAwMCwgJ2V4cGVjdGVkX2ludicgPT4gMTAxMC4xMF0sCiAgICBdOwogICAgCiAgICBmb3JlYWNoICgkdGVzdENhc2VzIGFzICR0ZXN0KSB7CiAgICAgICAgJGNhbGN1bGF0ZWRJbnYgPSBjaGFsbGVuZ2VDaGVja0ludm9pY2VQYXllZCgkdGVzdFsndHgnXSk7CiAgICAgICAgJGlzUGFzc2VkID0gY2hlY2tJbnZvaWNlUGF5ZWQoJHRlc3RbJ3R4J10sICRjYWxjdWxhdGVkSW52KTsKICAgICAgICAKICAgICAgICBlY2hvIHNwcmludGYoCiAgICAgICAgICAgICJUZXN0IGNhc2U6IFRYPSUuMmYsIENhbGN1bGF0ZWQgSU5WPSUuMmYsIEV4cGVjdGVkIElOVj0lLjJmLCBJcyBhdCB0aHJlc2hvbGQ6ICVzXG4iLAogICAgICAgICAgICAkdGVzdFsndHgnXSwKICAgICAgICAgICAgJGNhbGN1bGF0ZWRJbnYsCiAgICAgICAgICAgICR0ZXN0WydleHBlY3RlZF9pbnYnXSwKICAgICAgICAgICAgJGlzUGFzc2VkID8gJ1llcycgOiAnTm8nCiAgICAgICAgKTsKICAgICAgICAKICAgICAgICAvLyBWZXJpZnkgdGhlIGJvdW5kYXJ5IGNvbmRpdGlvbgogICAgICAgICRzbGlnaHRseU1vcmUgPSBjaGVja0ludm9pY2VQYXllZCgkdGVzdFsndHgnXSwgJGNhbGN1bGF0ZWRJbnYgLSAwLjAxKTsKICAgICAgICAkc2xpZ2h0bHlMZXNzID0gY2hlY2tJbnZvaWNlUGF5ZWQoJHRlc3RbJ3R4J10sICRjYWxjdWxhdGVkSW52ICsgMC4wMSk7CiAgICAgICAgCiAgICAgICAgaWYgKCRzbGlnaHRseU1vcmUgIT09IHRydWUgfHwgJHNsaWdodGx5TGVzcyAhPT0gZmFsc2UpIHsKICAgICAgICAgICAgZWNobyAiV0FSTklORzogQm91bmRhcnkgY29uZGl0aW9uIGZhaWxlZCBmb3IgVFggYW1vdW50ICIgLiAkdGVzdFsndHgnXSAuICJcbiI7CiAgICAgICAgfQogICAgfQp9CgovLyBSdW4gdGhlIHRlc3RzCnJ1blRlc3RzKCk7
stdout
Test case: TX=100.00, Calculated INV=101.01, Expected INV=101.01, Is at threshold: Yes
Test case: TX=99.00, Calculated INV=100.00, Expected INV=100.00, Is at threshold: Yes
Test case: TX=0.99, Calculated INV=1.00, Expected INV=1.00, Is at threshold: Yes
Test case: TX=1000.00, Calculated INV=1010.10, Expected INV=1010.10, Is at threshold: Yes