@ -24,6 +24,7 @@ import java.math.BigDecimal;
import java.math.RoundingMode ;
import java.math.RoundingMode ;
import java.time.LocalDate ;
import java.time.LocalDate ;
import java.time.temporal.ChronoUnit ;
import java.time.temporal.ChronoUnit ;
import java.util.Currency ;
import java.util.* ;
import java.util.* ;
@Service
@Service
@ -183,12 +184,19 @@ public class TransactionService {
}
}
public EvaluatedCurrencyReponse getEvaluatedCurrency ( String porOrgacode , String baseCurrencyCode , String targetCurrencyCode , double sgtGntramtfc ) {
public EvaluatedCurrencyReponse getEvaluatedCurrency ( String porOrgacode , String baseCurrencyCode , String targetCurrencyCode , double sgtGntramtfc ) {
double pkrAmt = convertToPKR ( baseCurrencyCode , sgtGntramtfc , porOrgacode ) ;
List < ExchangeRateModel > exchangeRateModelList = fetchExchangeRate ( porOrgacode ) ;
double convertFromPkr = convertFromPKR ( targetCurrencyCode , pkrAmt , porOrgacode ) ;
if ( exchangeRateModelList = = null | | exchangeRateModelList . isEmpty ( ) ) {
List < ExchangeRateModel > exchangeRateModelList = fetchExchangeRate ( porOrgacode ) ;
throw new RuntimeException ( "No exchange rates configured for organization " + porOrgacode + ". Please configure exchange rates first." ) ;
}
String normalizedBase = normalizeCurrencyCode ( baseCurrencyCode , exchangeRateModelList ) ;
String normalizedTarget = normalizeCurrencyCode ( targetCurrencyCode , exchangeRateModelList ) ;
double pkrAmt = convertToPKR ( normalizedBase , sgtGntramtfc , porOrgacode , exchangeRateModelList ) ;
double convertFromPkr = convertFromPKR ( normalizedTarget , pkrAmt , porOrgacode , exchangeRateModelList ) ;
Optional < Double > rate = exchangeRateModelList . stream ( )
Optional < Double > rate = exchangeRateModelList . stream ( )
. filter ( x - > x . isPcrCurrbase ( ) & & x . getPcrCurrcode ( ) . equals ( targetCurrencyCode ) )
. filter ( x - > x . isPcrCurrbase ( ) & & currencyCodeMatches( x. getPcrCurrcode ( ) , normalizedTarget ) )
. map ( x - > {
. map ( x - > {
BigDecimal bd = BigDecimal . valueOf ( 1 / x . getPerEratrateact ( ) ) ;
BigDecimal bd = BigDecimal . valueOf ( 1 / x . getPerEratrateact ( ) ) ;
bd = bd . setScale ( 2 , RoundingMode . HALF_UP ) ;
bd = bd . setScale ( 2 , RoundingMode . HALF_UP ) ;
@ -198,7 +206,7 @@ public class TransactionService {
if ( ! rate . isPresent ( ) ) {
if ( ! rate . isPresent ( ) ) {
rate = exchangeRateModelList . stream ( )
rate = exchangeRateModelList . stream ( )
. filter ( x - > ! x . isPcrCurrbase ( ) & & x. getPcrCurrcode ( ) .equals ( targetCurrencyCode ) )
. filter ( x - > ! x . isPcrCurrbase ( ) & & currencyCodeMatches( x. getPcrCurrcode ( ) , normalizedTarget ) )
. map ( x - > {
. map ( x - > {
BigDecimal bd = BigDecimal . valueOf ( x . getPerEratrateact ( ) ) ;
BigDecimal bd = BigDecimal . valueOf ( x . getPerEratrateact ( ) ) ;
bd = bd . setScale ( 2 , RoundingMode . HALF_UP ) ;
bd = bd . setScale ( 2 , RoundingMode . HALF_UP ) ;
@ -220,22 +228,30 @@ public class TransactionService {
public double convertToPKR ( String fromcrCurrcode , double amount , String porOrgacode ) {
public double convertToPKR ( String fromcrCurrcode , double amount , String porOrgacode ) {
List < ExchangeRateModel > exchangeRateModelList = fetchExchangeRate ( porOrgacode ) ;
List < ExchangeRateModel > exchangeRateModelList = fetchExchangeRate ( porOrgacode ) ;
return convertToPKR ( fromcrCurrcode , amount , porOrgacode , exchangeRateModelList ) ;
}
private double convertToPKR ( String fromcrCurrcode , double amount , String porOrgacode , List < ExchangeRateModel > exchangeRateModelList ) {
if ( exchangeRateModelList = = null | | exchangeRateModelList . isEmpty ( ) ) {
throw new RuntimeException ( "No exchange rates configured for organization " + porOrgacode + ". Please configure exchange rates first." ) ;
}
String baseCurrencyCode = exchangeRateModelList . stream ( )
String baseCurrencyCode = exchangeRateModelList . stream ( )
. filter ( ExchangeRateModel : : isPcrCurrbase )
. filter ( ExchangeRateModel : : isPcrCurrbase )
. findFirst ( )
. findFirst ( )
. map ( ExchangeRateModel : : getPcrCurrcode )
. map ( ExchangeRateModel : : getPcrCurrcode )
. orElse ( null ) ;
. orElse ( null ) ;
if ( fromcrCurrcode . equals ( baseCurrencyCode ) ) {
if ( currencyCodeMatches( baseCurrencyCode , fromcrCurrc ode) ) {
return amount ;
return amount ;
}
}
return exchangeRateModelList . stream ( )
return exchangeRateModelList . stream ( )
. filter ( k - > k. getPcrCurrcode ( ) .equals ( fromcrCurrcode ) )
. filter ( k - > currencyCodeMatches( k. getPcrCurrcode ( ) , fromcrCurrcode ) )
. findFirst ( )
. findFirst ( )
. map ( k - > amount * k . getPerEratrateact ( ) )
. map ( k - > amount * k . getPerEratrateact ( ) )
. orElse ( 0.0 ) ;
. orElseThrow ( ( ) - > new RuntimeException (
"Exchange rate not found for currency " + fromcrCurrcode + " (organization: " + porOrgacode + "). Available: " + formatAvailableCurrencies ( exchangeRateModelList )
) ) ;
}
}
public List < ExchangeRateModel > fetchExchangeRate ( String porOrgacode ) {
public List < ExchangeRateModel > fetchExchangeRate ( String porOrgacode ) {
ObjectMapper objectMapper = new ObjectMapper ( ) ;
ObjectMapper objectMapper = new ObjectMapper ( ) ;
@ -243,23 +259,105 @@ public class TransactionService {
new TypeReference < List < ExchangeRateModel > > ( ) {
new TypeReference < List < ExchangeRateModel > > ( ) {
} ) ;
} ) ;
}
}
public double convertFromPKR ( String todrCurrcode , double amount , String porOrgacode ) {
public double convertFromPKR ( String todrCurrcode , double amount , String porOrgacode ) {
List < ExchangeRateModel > exchangeRateModelList = fetchExchangeRate ( porOrgacode ) ;
List < ExchangeRateModel > exchangeRateModelList = fetchExchangeRate ( porOrgacode ) ;
return convertFromPKR ( todrCurrcode , amount , porOrgacode , exchangeRateModelList ) ;
}
private double convertFromPKR ( String todrCurrcode , double amount , String porOrgacode , List < ExchangeRateModel > exchangeRateModelList ) {
if ( exchangeRateModelList = = null | | exchangeRateModelList . isEmpty ( ) ) {
throw new RuntimeException ( "No exchange rates configured for organization " + porOrgacode + ". Please configure exchange rates first." ) ;
}
String baseCurrencyCode = exchangeRateModelList . stream ( )
String baseCurrencyCode = exchangeRateModelList . stream ( )
. filter ( ExchangeRateModel : : isPcrCurrbase )
. filter ( ExchangeRateModel : : isPcrCurrbase )
. findFirst ( )
. findFirst ( )
. map ( ExchangeRateModel : : getPcrCurrcode )
. map ( ExchangeRateModel : : getPcrCurrcode )
. orElse ( null ) ;
. orElse ( null ) ;
if ( todrCurrcode. equals ( baseCurrencyC ode) ) {
if ( currencyCodeMatches( baseCurrencyCode , todrCurrc ode) ) {
return amount ;
return amount ;
}
}
return exchangeRateModelList . stream ( )
return exchangeRateModelList . stream ( )
. filter ( k - > k. getPcrCurrcode ( ) .equals ( todrCurrcode ) )
. filter ( k - > currencyCodeMatches( k. getPcrCurrcode ( ) , todrCurrcode ) )
. findFirst ( )
. findFirst ( )
. map ( k - > amount / k . getPerEratrateact ( ) )
. map ( k - > amount / k . getPerEratrateact ( ) )
. orElseThrow ( ( ) - > new RuntimeException ( "Product Not Found" ) ) ;
. orElseThrow ( ( ) - > new RuntimeException (
"Exchange rate not found for currency " + todrCurrcode + " (organization: " + porOrgacode + "). Available: " + formatAvailableCurrencies ( exchangeRateModelList )
) ) ;
}
private boolean currencyCodeMatches ( String storedCode , String requestedCode ) {
if ( requestedCode = = null ) return storedCode = = null ;
if ( storedCode = = null ) return false ;
return storedCode . trim ( ) . equals ( requestedCode . trim ( ) ) ;
}
private String normalizeCurrencyCode ( String currencyCode , List < ExchangeRateModel > exchangeRates ) {
if ( currencyCode = = null ) return null ;
String raw = currencyCode . trim ( ) ;
if ( raw . isEmpty ( ) ) return raw ;
String upper = raw . toUpperCase ( Locale . ROOT ) ;
if ( exchangeRates ! = null & & exchangeRates . stream ( ) . anyMatch ( r - > upper . equals ( safeTrimUpper ( r . getPcrCurrcode ( ) ) ) ) ) {
return upper ;
}
if ( exchangeRates ! = null ) {
Optional < String > byShort = exchangeRates . stream ( )
. filter ( r - > upper . equals ( safeTrimUpper ( r . getPcrCurrshort ( ) ) ) )
. map ( ExchangeRateModel : : getPcrCurrcode )
. filter ( Objects : : nonNull )
. findFirst ( ) ;
if ( byShort . isPresent ( ) ) {
return byShort . get ( ) ;
}
}
if ( upper . length ( ) = = 3 & & upper . chars ( ) . allMatch ( Character : : isLetter ) ) {
try {
int numeric = Currency . getInstance ( upper ) . getNumericCode ( ) ;
String numericStr = String . valueOf ( numeric ) ;
if ( exchangeRates ! = null & & exchangeRates . stream ( ) . anyMatch ( r - > numericStr . equals ( safeTrimUpper ( r . getPcrCurrcode ( ) ) ) ) ) {
return numericStr ;
}
} catch ( Exception ignored ) {
}
}
if ( upper . chars ( ) . allMatch ( Character : : isDigit ) ) {
try {
int numeric = Integer . parseInt ( upper ) ;
for ( Currency c : Currency . getAvailableCurrencies ( ) ) {
if ( c . getNumericCode ( ) = = numeric ) {
String alpha = c . getCurrencyCode ( ) ;
if ( exchangeRates ! = null & & exchangeRates . stream ( ) . anyMatch ( r - > alpha . equals ( safeTrimUpper ( r . getPcrCurrcode ( ) ) ) ) ) {
return alpha ;
}
break ;
}
}
} catch ( Exception ignored ) {
}
}
return upper ;
}
private String safeTrimUpper ( String s ) {
return s = = null ? null : s . trim ( ) . toUpperCase ( Locale . ROOT ) ;
}
private String formatAvailableCurrencies ( List < ExchangeRateModel > exchangeRates ) {
if ( exchangeRates = = null | | exchangeRates . isEmpty ( ) ) return "[]" ;
return exchangeRates . stream ( )
. map ( r - > {
String shortCode = ( r . getPcrCurrshort ( ) = = null | | r . getPcrCurrshort ( ) . isBlank ( ) ) ? "?" : r . getPcrCurrshort ( ) . trim ( ) ;
String code = ( r . getPcrCurrcode ( ) = = null | | r . getPcrCurrcode ( ) . isBlank ( ) ) ? "?" : r . getPcrCurrcode ( ) . trim ( ) ;
return shortCode + "(" + code + ")" ;
} )
. distinct ( )
. limit ( 20 )
. toList ( )
. toString ( ) ;
}
}
public Map < String , Object > glAccountTransaction ( GLAccontTranasctionRequestModel glAccontTranasctionRequestModel ) {
public Map < String , Object > glAccountTransaction ( GLAccontTranasctionRequestModel glAccontTranasctionRequestModel ) {