diff --git a/api/api-app/src/main/kotlin/co/nilin/opex/api/app/config/WebClientConfig.kt b/api/api-app/src/main/kotlin/co/nilin/opex/api/app/config/WebClientConfig.kt index 9a2f15994..a2fb64d13 100644 --- a/api/api-app/src/main/kotlin/co/nilin/opex/api/app/config/WebClientConfig.kt +++ b/api/api-app/src/main/kotlin/co/nilin/opex/api/app/config/WebClientConfig.kt @@ -1,18 +1,20 @@ package co.nilin.opex.api.app.config +import co.nilin.opex.common.data.UserLanguage import io.netty.channel.ChannelOption import io.netty.handler.logging.LogLevel -import org.springframework.beans.factory.annotation.Qualifier import org.springframework.cloud.client.ServiceInstance import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.context.annotation.Profile import org.springframework.http.client.reactive.ReactorClientHttpConnector +import org.springframework.web.reactive.function.client.ClientRequest +import org.springframework.web.reactive.function.client.ExchangeFilterFunction import org.springframework.web.reactive.function.client.WebClient import org.zalando.logbook.Logbook import org.zalando.logbook.netty.LogbookClientHandler +import reactor.core.publisher.Mono import reactor.netty.http.client.HttpClient import reactor.netty.resources.ConnectionProvider import reactor.netty.transport.logging.AdvancedByteBufFormat @@ -45,11 +47,12 @@ class WebClientConfig(private val logbook: Logbook) { return WebClient.builder() .filter(ReactorLoadBalancerExchangeFilterFunction(loadBalancerFactory, emptyList())) .clientConnector(ReactorClientHttpConnector(client)) + .filter(languageFilter()) .build() } @Bean("keycloakWebClient") - fun keycloakWebClient( logbook: Logbook): WebClient { + fun keycloakWebClient(logbook: Logbook): WebClient { val provider = ConnectionProvider.builder("apiKeycloakPool") .maxConnections(150) .maxIdleTime(Duration.ofSeconds(30)) @@ -71,5 +74,15 @@ class WebClientConfig(private val logbook: Logbook) { .build() } + private fun languageFilter() = ExchangeFilterFunction { request, next -> + Mono.deferContextual { ctx -> + val lang = ctx.getOrDefault("lang", UserLanguage.EN.toString()) + val mutatedRequest = ClientRequest.from(request) + .header("Accept-Language", lang) + .build() + next.exchange(mutatedRequest) + } + } + } \ No newline at end of file diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyCommand.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyCommand.kt index 5b0cadda5..db3195096 100644 --- a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyCommand.kt +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyCommand.kt @@ -7,7 +7,7 @@ import java.util.* data class CurrencyCommand( var symbol: String, var uuid: String? = UUID.randomUUID().toString(), - var name: String, + var name: String? = null, var precision: BigDecimal, var title: String? = null, var alias: String? = null, @@ -22,7 +22,7 @@ data class CurrencyCommand( var externalUrl: String? = null, var gateways: List? = null, var availableGatewayType: String? = null, - var order: Int? = null + var displayOrder: Int? = null ) { fun updateTo(newData: CurrencyCommand): CurrencyCommand { diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyData.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyData.kt index 42c85fdcb..89134d287 100644 --- a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyData.kt +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyData.kt @@ -7,7 +7,7 @@ import java.util.* data class CurrencyData( var symbol: String, var uuid: String? = UUID.randomUUID().toString(), - var name: String, + var name: String? = null, var precision: BigDecimal, var title: String? = null, var alias: String? = null, @@ -18,7 +18,7 @@ data class CurrencyData( var description: String? = null, var shortDescription: String? = null, var externalUrl: String? = null, - var order: Int? = null, - var maxOrder : BigDecimal? = null, + var displayOrder: Int? = null, + var maxOrder: BigDecimal? = null, ) diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationCommand.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationCommand.kt new file mode 100644 index 000000000..91fae9b94 --- /dev/null +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationCommand.kt @@ -0,0 +1,11 @@ +package co.nilin.opex.api.core.inout + +data class CurrencyLocalizationCommand( + var id: Long? = null, + var name: String? = null, + var title: String? = null, + var alias: String? = null, + var description: String? = null, + var shortDescription: String? = null, + var language: String, +) diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationRequest.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationRequest.kt new file mode 100644 index 000000000..ce10ffd9f --- /dev/null +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationRequest.kt @@ -0,0 +1,6 @@ +package co.nilin.opex.api.core.inout + + +data class CurrencyLocalizationRequest( + val currencyLocalizations: List +) \ No newline at end of file diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationResponse.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationResponse.kt new file mode 100644 index 000000000..4bb7bbaa6 --- /dev/null +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/CurrencyLocalizationResponse.kt @@ -0,0 +1,6 @@ +package co.nilin.opex.api.core.inout + +data class CurrencyLocalizationResponse( + val currency: String, + val currencyLocalizations: List +) \ No newline at end of file diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationCommand.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationCommand.kt new file mode 100644 index 000000000..091e1ddf2 --- /dev/null +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationCommand.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.api.core.inout + +data class TerminalLocalizationCommand( + var id : Long?, + var description: String, + var language: String, +) diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationRequest.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationRequest.kt new file mode 100644 index 000000000..a18474392 --- /dev/null +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationRequest.kt @@ -0,0 +1,6 @@ +package co.nilin.opex.api.core.inout + + +data class TerminalLocalizationRequest( + val terminalLocalizations: List +) \ No newline at end of file diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationResponse.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationResponse.kt new file mode 100644 index 000000000..8bcd6f71e --- /dev/null +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/inout/TerminalLocalizationResponse.kt @@ -0,0 +1,6 @@ +package co.nilin.opex.api.core.inout + +data class TerminalLocalizationResponse( + val terminalUuid: String, + val terminalLocalizations: List +) \ No newline at end of file diff --git a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/WalletProxy.kt b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/WalletProxy.kt index e07054d7f..f24a83d18 100644 --- a/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/WalletProxy.kt +++ b/api/api-core/src/main/kotlin/co/nilin/opex/api/core/spi/WalletProxy.kt @@ -2,7 +2,6 @@ package co.nilin.opex.api.core.spi import co.nilin.opex.api.core.inout.* import co.nilin.opex.api.core.inout.analytics.DailyAmount -import org.springframework.security.core.userdetails.UserDetails import java.math.BigDecimal interface WalletProxy { @@ -202,8 +201,40 @@ interface WalletProxy { suspend fun getDailyBalanceLast31Days(token: String, uuid: String): List - suspend fun reserveSwap(token: String, request: TransferReserveRequest) :ReservedTransferResponse - suspend fun finalizeSwap(token: String,reserveUuid: String,description: String?,transferRef: String?) : TransferResult - suspend fun getGatewayTerminal(gatewayUuid: String):List + suspend fun reserveSwap(token: String, request: TransferReserveRequest): ReservedTransferResponse + suspend fun finalizeSwap( + token: String, + reserveUuid: String, + description: String?, + transferRef: String? + ): TransferResult + + suspend fun getGatewayTerminal(gatewayUuid: String): List suspend fun getUsersDetailAssets(limit: Int, offset: Int): List + suspend fun getCurrencyLocalizations(token: String, currency: String): CurrencyLocalizationResponse + suspend fun saveCurrencyLocalizations( + token: String, + currency: String, + request: CurrencyLocalizationRequest + ): CurrencyLocalizationResponse + + suspend fun updateCurrencyLocalization( + token: String, + request: CurrencyLocalizationCommand + ): CurrencyLocalizationCommand + + suspend fun deleteCurrencyLocalization(token: String, id: Long) + suspend fun getTerminalLocalizations(token: String, terminalUuid: String): TerminalLocalizationResponse + suspend fun saveTerminalLocalizations( + token: String, + terminalUuid: String, + request: TerminalLocalizationRequest + ): TerminalLocalizationResponse + + suspend fun updateTerminalLocalization( + token: String, + request: TerminalLocalizationCommand + ): TerminalLocalizationCommand + + suspend fun deleteTerminalLocalization(token: String, id: Long) } \ No newline at end of file diff --git a/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/LocalizationAdminController.kt b/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/LocalizationAdminController.kt new file mode 100644 index 000000000..ba00e6e36 --- /dev/null +++ b/api/api-ports/api-opex-rest/src/main/kotlin/co/nilin/opex/api/ports/opex/controller/LocalizationAdminController.kt @@ -0,0 +1,89 @@ +package co.nilin.opex.api.ports.opex.controller + +import co.nilin.opex.api.core.inout.* +import co.nilin.opex.api.core.spi.WalletProxy +import co.nilin.opex.api.ports.opex.util.jwtAuthentication +import co.nilin.opex.api.ports.opex.util.tokenValue +import org.springframework.security.core.annotation.CurrentSecurityContext +import org.springframework.security.core.context.SecurityContext +import org.springframework.web.bind.annotation.* + +@RestController +@RequestMapping("/opex/v1/admin") +class LocalizationAdminController( + private val walletProxy: WalletProxy, +) { + @GetMapping("/currency/{currency}/localization") + suspend fun getCurrencyLocalizations( + @CurrentSecurityContext securityContext: SecurityContext, + @PathVariable("currency") currency: String + ): CurrencyLocalizationResponse { + return walletProxy.getCurrencyLocalizations(securityContext.jwtAuthentication().tokenValue(), currency) + } + + @PostMapping("/currency/{currency}/localization") + suspend fun saveCurrencyLocalizations( + @CurrentSecurityContext securityContext: SecurityContext, + @PathVariable("currency") currency: String, + @RequestBody request: CurrencyLocalizationRequest + ): CurrencyLocalizationResponse { + return walletProxy.saveCurrencyLocalizations( + securityContext.jwtAuthentication().tokenValue(), + currency, + request + ) + } + + @PutMapping("/currency/localization") + suspend fun updateCurrencyLocalization( + @CurrentSecurityContext securityContext: SecurityContext, + @RequestBody request: CurrencyLocalizationCommand + ): CurrencyLocalizationCommand { + return walletProxy.updateCurrencyLocalization(securityContext.jwtAuthentication().tokenValue(), request) + } + + @DeleteMapping("/currency/localization/{id}") + suspend fun deleteCurrencyLocalization( + @CurrentSecurityContext securityContext: SecurityContext, + @PathVariable("id") id: Long + ) { + walletProxy.deleteCurrencyLocalization(securityContext.jwtAuthentication().tokenValue(), id) + } + + @GetMapping("/terminal/{terminalUuid}/localization") + suspend fun getTerminalLocalizations( + @CurrentSecurityContext securityContext: SecurityContext, + @PathVariable("terminalUuid") terminalUuid: String + ): TerminalLocalizationResponse { + return walletProxy.getTerminalLocalizations(securityContext.jwtAuthentication().tokenValue(), terminalUuid) + } + + @PostMapping("/terminal/{terminalUuid}/localization") + suspend fun saveTerminalLocalizations( + @CurrentSecurityContext securityContext: SecurityContext, + @PathVariable("terminalUuid") terminalUuid: String, + @RequestBody request: TerminalLocalizationRequest + ): TerminalLocalizationResponse { + return walletProxy.saveTerminalLocalizations( + securityContext.jwtAuthentication().tokenValue(), + terminalUuid, + request + ) + } + + @PutMapping("/terminal/localization") + suspend fun updateTerminalLocalization( + @CurrentSecurityContext securityContext: SecurityContext, + @RequestBody request: TerminalLocalizationCommand + ): TerminalLocalizationCommand { + return walletProxy.updateTerminalLocalization(securityContext.jwtAuthentication().tokenValue(), request) + } + + @DeleteMapping("/terminal/localization/{id}") + suspend fun deleteTerminalLocalization( + @CurrentSecurityContext securityContext: SecurityContext, + @PathVariable("id") id: Long + ) { + walletProxy.deleteTerminalLocalization(securityContext.jwtAuthentication().tokenValue(), id) + } +} \ No newline at end of file diff --git a/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/WalletProxyImpl.kt b/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/WalletProxyImpl.kt index 1d06776ea..9d58ea104 100644 --- a/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/WalletProxyImpl.kt +++ b/api/api-ports/api-proxy-rest/src/main/kotlin/co/nilin/opex/api/ports/proxy/impl/WalletProxyImpl.kt @@ -17,10 +17,7 @@ import org.springframework.beans.factory.annotation.Value import org.springframework.http.HttpHeaders import org.springframework.http.MediaType import org.springframework.stereotype.Component -import org.springframework.web.reactive.function.client.WebClient -import org.springframework.web.reactive.function.client.body -import org.springframework.web.reactive.function.client.bodyToFlux -import org.springframework.web.reactive.function.client.bodyToMono +import org.springframework.web.reactive.function.client.* import reactor.core.publisher.Mono import java.math.BigDecimal @@ -804,5 +801,119 @@ class WalletProxyImpl(@Qualifier("generalWebClient") private val webClient: WebC .awaitFirstOrElse { emptyList() } } } + + override suspend fun getCurrencyLocalizations( + token: String, + currency: String + ): CurrencyLocalizationResponse { + return webClient.get() + .uri("$baseUrl/currency/${currency}/localization") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .retrieve() + .onStatus({ t -> t.isError }, { it.createException() }) + .bodyToMono() + .awaitFirstOrElse { throw OpexError.BadRequest.exception() } + } + + override suspend fun saveCurrencyLocalizations( + token: String, + currency: String, + request: CurrencyLocalizationRequest + ): CurrencyLocalizationResponse { + return webClient.post() + .uri("$baseUrl/currency/${currency}/localization") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .body(Mono.just(request)) + .retrieve() + .onStatus({ t -> t.isError }, { it.createException() }) + .bodyToMono() + .awaitFirstOrElse { throw OpexError.BadRequest.exception() } + } + + override suspend fun updateCurrencyLocalization( + token: String, + request: CurrencyLocalizationCommand + ): CurrencyLocalizationCommand { + return webClient.put() + .uri("$baseUrl/currency/localization") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .body(Mono.just(request)) + .retrieve() + .onStatus({ t -> t.isError }, { it.createException() }) + .bodyToMono() + .awaitFirstOrElse { throw OpexError.BadRequest.exception() } + } + + override suspend fun deleteCurrencyLocalization(token: String, id: Long) { + webClient.delete() + .uri("$baseUrl/currency/localization/${id}") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .retrieve() + .onStatus({ it.isError }) { response -> + response.createException() + } + .awaitBodilessEntity() + } + + override suspend fun getTerminalLocalizations( + token: String, + terminalUuid: String + ): TerminalLocalizationResponse { + return webClient.get() + .uri("$baseUrl/admin/deposit/terminal/${terminalUuid}/localization") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .retrieve() + .onStatus({ t -> t.isError }, { it.createException() }) + .bodyToMono() + .awaitFirstOrElse { throw OpexError.BadRequest.exception() } + } + + override suspend fun saveTerminalLocalizations( + token: String, + terminalUuid: String, + request: TerminalLocalizationRequest + ): TerminalLocalizationResponse { + return webClient.post() + .uri("$baseUrl/admin/deposit/terminal/${terminalUuid}/localization") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .body(Mono.just(request)) + .retrieve() + .onStatus({ t -> t.isError }, { it.createException() }) + .bodyToMono() + .awaitFirstOrElse { throw OpexError.BadRequest.exception() } + } + + override suspend fun updateTerminalLocalization( + token: String, + request: TerminalLocalizationCommand + ): TerminalLocalizationCommand { + return webClient.put() + .uri("$baseUrl/admin/deposit/terminal/localization") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .body(Mono.just(request)) + .retrieve() + .onStatus({ t -> t.isError }, { it.createException() }) + .bodyToMono() + .awaitFirstOrElse { throw OpexError.BadRequest.exception() } + } + + override suspend fun deleteTerminalLocalization(token: String, id: Long) { + webClient.delete() + .uri("$baseUrl/admin/deposit/terminal/localization/${id}") + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer $token") + .retrieve() + .onStatus({ it.isError }) { response -> + response.createException() + } + .awaitBodilessEntity() + } } diff --git a/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt b/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt index 57176f475..4142b1c5e 100644 --- a/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt +++ b/common/src/main/kotlin/co/nilin/opex/common/OpexError.kt @@ -116,6 +116,7 @@ enum class OpexError(val code: Int, val message: String?, val status: HttpStatus WithdrawRequestExpired(6051,"Withdraw request expired", HttpStatus.BAD_REQUEST), ForbiddenSwapPair(6052, null, HttpStatus.BAD_REQUEST), TerminalLocalizationNotFound(6053, "Terminal localization not found", HttpStatus.NOT_FOUND), + CurrencyLocalizationNotFound(6051, "Currency localization not found", HttpStatus.NOT_FOUND), // code 7000: api diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt index bcdeebcc1..4443bf142 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/config/SecurityConfig.kt @@ -22,6 +22,7 @@ class SecurityConfig(private val webClient: WebClient) { @Value("\${app.auth.cert-url}") private lateinit var certUrl: String + @Value("\${app.auth.iss-url}") private lateinit var issUrl: String @@ -33,6 +34,7 @@ class SecurityConfig(private val webClient: WebClient) { .pathMatchers("/balanceOf/**").authenticated() .pathMatchers("/owner/**").authenticated() .pathMatchers("/withdraw").authenticated() + .pathMatchers("/currency/localization/**").hasAuthority("ROLE_admin") .pathMatchers(HttpMethod.PUT, "/currency/**").hasAuthority("ROLE_admin") .pathMatchers(HttpMethod.POST, "/currency/**").hasAuthority("ROLE_admin") .pathMatchers(HttpMethod.DELETE, "/currency/**").hasAuthority("ROLE_admin") @@ -60,7 +62,7 @@ class SecurityConfig(private val webClient: WebClient) { //otc .pathMatchers("/admin/**").hasAuthority("ROLE_admin") .pathMatchers(HttpMethod.GET, "/otc/**").permitAll() - .pathMatchers(HttpMethod.PUT, "/otc/rate").hasAnyAuthority("ROLE_rate_bot","ROLE_admin") + .pathMatchers(HttpMethod.PUT, "/otc/rate").hasAnyAuthority("ROLE_rate_bot", "ROLE_admin") .pathMatchers(HttpMethod.PUT, "/otc/**").hasAuthority("ROLE_admin") .pathMatchers(HttpMethod.POST, "/otc/**").hasAuthority("ROLE_admin") .pathMatchers(HttpMethod.DELETE, "/otc/**").hasAuthority("ROLE_admin") diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/CurrencyController.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/CurrencyController.kt index e109a2849..667cdefaf 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/CurrencyController.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/controller/CurrencyController.kt @@ -1,12 +1,8 @@ package co.nilin.opex.wallet.app.controller -import co.nilin.opex.wallet.app.dto.CurrenciesDto -import co.nilin.opex.wallet.app.dto.CurrencyDto +import co.nilin.opex.wallet.app.dto.* import co.nilin.opex.wallet.app.service.CurrencyServiceV2 -import co.nilin.opex.wallet.core.inout.CurrencyData -import co.nilin.opex.wallet.core.inout.CurrencyGatewayCommand -import co.nilin.opex.wallet.core.inout.GatewayType -import co.nilin.opex.wallet.core.inout.TerminalCommand +import co.nilin.opex.wallet.core.inout.* import co.nilin.opex.wallet.core.model.QuoteCurrency import co.nilin.opex.wallet.core.spi.GatewayTerminalManager import co.nilin.opex.wallet.core.spi.QuoteCurrencyManager @@ -28,9 +24,9 @@ class CurrencyController( @PutMapping("/{currencySymbol}") suspend fun updateCurrency( @PathVariable("currencySymbol") currencySymbol: String, - @RequestBody request: CurrencyDto, + @RequestBody request: UpdateCurrencyRequest, ): CurrencyDto? { - return currencyService.updateCurrency(request.apply { symbol = currencySymbol }) + return currencyService.updateCurrency(request.apply { symbol = currencySymbol }.toCurrencyDto()) } @@ -158,4 +154,28 @@ class CurrencyController( quoteCurrencyManager.update(currency, isReference, displayOrder) } + @GetMapping("/{currency}/localization") + suspend fun getCurrencyLocalizations(@PathVariable("currency") currency: String): CurrencyLocalizationResponse { + val localizations = currencyService.fetchCurrencyLocalizations(currency) + return CurrencyLocalizationResponse(currency, localizations) + } + + @PostMapping("/{currency}/localization") + suspend fun saveCurrencyLocalizations( + @PathVariable("currency") currency: String, + @RequestBody request: CurrencyLocalizationRequest + ): CurrencyLocalizationResponse { + val localizations = currencyService.saveCurrencyLocalizations(currency, request.currencyLocalizations) + return CurrencyLocalizationResponse(currency, localizations) + } + + @PutMapping("/localization") + suspend fun updateCurrencyLocalization(@RequestBody request: CurrencyLocalizationCommand): CurrencyLocalizationCommand { + return currencyService.updateCurrencyLocalization(request) + } + + @DeleteMapping("/localization/{id}") + suspend fun deleteCurrencyLocalization(@PathVariable("id") id: Long) { + currencyService.deleteCurrencyLocalization(id) + } } \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyDto.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyDto.kt index 6c794f24d..b6714fbee 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyDto.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyDto.kt @@ -8,7 +8,7 @@ import java.util.* data class CurrencyDto( var symbol: String? = null, var uuid: String? = UUID.randomUUID().toString(), - var name: String, + var name: String? = null, var precision: BigDecimal, var title: String? = null, var alias: String? = null, @@ -23,11 +23,11 @@ data class CurrencyDto( var externalUrl: String? = null, var gateways: List? = null, var availableGatewayType: String? = null, - var order: Int? = null, + var displayOrder: Int? = null, var systemBalance: BigDecimal? = null, var maxOrder: BigDecimal? = null, -) { + ) { // Separated them just to support having "id" field in currency table. //Now it is unnecessary @@ -51,7 +51,7 @@ data class CurrencyDto( externalUrl, gateways, availableGatewayType, - order, + displayOrder, maxOrder ) } diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyLocalizationRequest.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyLocalizationRequest.kt new file mode 100644 index 000000000..cb6cc923c --- /dev/null +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyLocalizationRequest.kt @@ -0,0 +1,7 @@ +package co.nilin.opex.wallet.app.dto + +import co.nilin.opex.wallet.core.inout.CurrencyLocalizationCommand + +data class CurrencyLocalizationRequest( + val currencyLocalizations: List +) \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyLocalizationResponse.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyLocalizationResponse.kt new file mode 100644 index 000000000..1c99f41c6 --- /dev/null +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/CurrencyLocalizationResponse.kt @@ -0,0 +1,8 @@ +package co.nilin.opex.wallet.app.dto + +import co.nilin.opex.wallet.core.inout.CurrencyLocalizationCommand + +data class CurrencyLocalizationResponse( + val currency: String, + val currencyLocalizations: List +) \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/UpdateCurrencyRequest.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/UpdateCurrencyRequest.kt new file mode 100644 index 000000000..c260ca6fe --- /dev/null +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/dto/UpdateCurrencyRequest.kt @@ -0,0 +1,30 @@ +package co.nilin.opex.wallet.app.dto + +import java.math.BigDecimal + +data class UpdateCurrencyRequest( + var symbol: String? = null, + var precision: BigDecimal, + var icon: String? = null, + var isTransitive: Boolean? = false, + var isActive: Boolean? = true, + var sign: String? = null, + var externalUrl: String? = null, + var order: Int? = null, + var maxOrder: BigDecimal? = null, + + ) { + fun toCurrencyDto(): CurrencyDto { + return CurrencyDto( + symbol = symbol, + precision = precision, + icon = icon, + isTransitive = isTransitive, + isActive = isActive, + sign = sign, + externalUrl = externalUrl, + displayOrder = order, + maxOrder = maxOrder, + ) + } +} diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/CurrencyServiceV2.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/CurrencyServiceV2.kt index 3f792081a..5174f45f9 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/CurrencyServiceV2.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/service/CurrencyServiceV2.kt @@ -4,11 +4,7 @@ import co.nilin.opex.common.OpexError import co.nilin.opex.wallet.app.dto.CurrenciesDto import co.nilin.opex.wallet.app.dto.CurrencyDto import co.nilin.opex.wallet.app.utils.toDto -import co.nilin.opex.wallet.core.inout.CurrencyData -import co.nilin.opex.wallet.core.inout.CurrencyGatewayCommand -import co.nilin.opex.wallet.core.inout.GatewayType -import co.nilin.opex.wallet.core.inout.OffChainGatewayCommand -import co.nilin.opex.wallet.core.inout.OnChainGatewayCommand +import co.nilin.opex.wallet.core.inout.* import co.nilin.opex.wallet.core.model.FetchCurrency import co.nilin.opex.wallet.core.service.GatewayService import co.nilin.opex.wallet.core.spi.CurrencyServiceManager @@ -69,10 +65,12 @@ class CurrencyServiceV2( var gateways = gatewayService.fetchGateways(currencySymbol, includeGateways) return it.apply { it.depositAllowed = - gateways?.stream()?.filter { it.isDepositActive == true }?.map(CurrencyGatewayCommand::depositAllowed) + gateways?.stream()?.filter { it.isDepositActive == true } + ?.map(CurrencyGatewayCommand::depositAllowed) ?.reduce { t, u -> t ?: false || u ?: false }?.orElseGet { false } it.withdrawAllowed = - gateways?.stream()?.filter { it.isWithdrawActive == true }?.map(CurrencyGatewayCommand::withdrawAllowed) + gateways?.stream()?.filter { it.isWithdrawActive == true } + ?.map(CurrencyGatewayCommand::withdrawAllowed) ?.reduce { t, u -> t ?: false || u ?: false }?.orElseGet { false } it.gateways = gateways //It is a stupid field for resolving front-end developers need @@ -119,12 +117,14 @@ class CurrencyServiceV2( return CurrenciesDto(currencies?.stream()?.map { it.apply { it.gateways = groupedByGateways?.get(it.symbol) - it.depositAllowed = groupedByGateways?.get(it.symbol)?.stream()?.filter { g -> g.isDepositActive == true } - ?.map(CurrencyGatewayCommand::depositAllowed)?.reduce { t, u -> t ?: false || u ?: false } - ?.orElseGet { false } - it.withdrawAllowed = groupedByGateways?.get(it.symbol)?.stream()?.filter { g -> g.isWithdrawActive == true } - ?.map(CurrencyGatewayCommand::withdrawAllowed)?.reduce { t, u -> t ?: false || u ?: false } - ?.orElseGet { false } + it.depositAllowed = + groupedByGateways?.get(it.symbol)?.stream()?.filter { g -> g.isDepositActive == true } + ?.map(CurrencyGatewayCommand::depositAllowed)?.reduce { t, u -> t ?: false || u ?: false } + ?.orElseGet { false } + it.withdrawAllowed = + groupedByGateways?.get(it.symbol)?.stream()?.filter { g -> g.isWithdrawActive == true } + ?.map(CurrencyGatewayCommand::withdrawAllowed)?.reduce { t, u -> t ?: false || u ?: false } + ?.orElseGet { false } it.gateways?.forEach { gateway -> when (gateway) { is OnChainGatewayCommand -> { @@ -156,5 +156,23 @@ class CurrencyServiceV2( return currencyServiceManager.fetchAllCurrencies() } + suspend fun fetchCurrencyLocalizations(currency: String): List { + return currencyServiceManager.fetchCurrencyLocalizations(currency) + } + + suspend fun saveCurrencyLocalizations( + currency: String, + request: List + ): List { + return currencyServiceManager.saveCurrencyLocalizations(currency, request); + } + + suspend fun updateCurrencyLocalization(request: CurrencyLocalizationCommand): CurrencyLocalizationCommand { + return currencyServiceManager.updateCurrencyLocalization(request) + } + + suspend fun deleteCurrencyLocalization(id: Long) { + currencyServiceManager.deleteCurrencyLocalization(id) + } } \ No newline at end of file diff --git a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Convertor.kt b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Convertor.kt index ca7ada065..0020709d0 100644 --- a/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Convertor.kt +++ b/wallet/wallet-app/src/main/kotlin/co/nilin/opex/wallet/app/utils/Convertor.kt @@ -22,7 +22,7 @@ fun CurrencyCommand.toDto(): CurrencyDto { externalUrl, gateways, availableGatewayType, - order, + displayOrder, maxOrder = maxOrder ) } diff --git a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyCommand.kt b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyCommand.kt index 8531f173f..afb8d034d 100644 --- a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyCommand.kt +++ b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyCommand.kt @@ -7,7 +7,7 @@ import java.util.* data class CurrencyCommand( var symbol: String, var uuid: String? = UUID.randomUUID().toString(), - var name: String, + var name: String? = null, var precision: BigDecimal, var title: String? = null, var alias: String? = null, @@ -22,10 +22,10 @@ data class CurrencyCommand( var externalUrl: String? = null, var gateways: List? = null, var availableGatewayType: String? = null, - var order: Int? = null, + var displayOrder: Int? = null, var maxOrder: BigDecimal? = null, -) { + ) { fun updateTo(newData: CurrencyCommand): CurrencyCommand { return newData.apply { this.uuid = uuid diff --git a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyData.kt b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyData.kt index 366d4e8f4..eb1e3a297 100644 --- a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyData.kt +++ b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyData.kt @@ -7,7 +7,7 @@ import java.util.* data class CurrencyData( var symbol: String, var uuid: String? = UUID.randomUUID().toString(), - var name: String, + var name: String? = null , var precision: BigDecimal, var title: String? = null, var alias: String? = null, @@ -18,7 +18,7 @@ data class CurrencyData( var description: String? = null, var shortDescription: String? = null, var externalUrl: String? = null, - var order: Int? = null, + var displayOrder: Int? = null, var maxOrder: BigDecimal? = null, ) diff --git a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyLocalizationCommand.kt b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyLocalizationCommand.kt new file mode 100644 index 000000000..fd010ab99 --- /dev/null +++ b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/inout/CurrencyLocalizationCommand.kt @@ -0,0 +1,11 @@ +package co.nilin.opex.wallet.core.inout + +data class CurrencyLocalizationCommand( + var id: Long? = null, + var name: String? = null, + var title: String? = null, + var alias: String? = null, + var description: String? = null, + var shortDescription: String? = null, + var language: String, +) diff --git a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyServiceManager.kt b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyServiceManager.kt index a53143c9b..c5db39e9a 100644 --- a/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyServiceManager.kt +++ b/wallet/wallet-core/src/main/kotlin/co/nilin/opex/wallet/core/spi/CurrencyServiceManager.kt @@ -1,12 +1,7 @@ package co.nilin.opex.wallet.core.spi -//import co.nilin.opex.wallet.core.model.Currencies -//import co.nilin.opex.wallet.core.model.Currency -import co.nilin.opex.wallet.core.inout.CurrenciesCommand -import co.nilin.opex.wallet.core.inout.CurrencyCommand -import co.nilin.opex.wallet.core.inout.CurrencyData -import co.nilin.opex.wallet.core.inout.CurrencyPrecision +import co.nilin.opex.wallet.core.inout.* import co.nilin.opex.wallet.core.model.FetchCurrency import java.math.BigDecimal @@ -17,11 +12,16 @@ interface CurrencyServiceManager { suspend fun fetchAllCurrencies(): List suspend fun fetchCurrency(request: FetchCurrency): CurrencyCommand? suspend fun updateCurrency(request: CurrencyCommand): CurrencyCommand? - - // suspend fun prepareCurrencyToBeACryptoCurrency(request: String): CurrencyCommand? suspend fun deleteCurrency(request: FetchCurrency): Void? - suspend fun fetchAllCurrenciesPrecision(): List suspend fun fetchCurrencyMaxOrder(symbol: String): BigDecimal? + suspend fun fetchCurrencyLocalizations(symbol: String): List + suspend fun saveCurrencyLocalizations( + symbol: String, + localizations: List + ): List + + suspend fun updateCurrencyLocalization(request: CurrencyLocalizationCommand): CurrencyLocalizationCommand + suspend fun deleteCurrencyLocalization(id: Long) } \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyLocalizationsRepository.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyLocalizationsRepository.kt new file mode 100644 index 000000000..034b1ef5b --- /dev/null +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyLocalizationsRepository.kt @@ -0,0 +1,11 @@ +package co.nilin.opex.wallet.ports.postgres.dao + +import co.nilin.opex.wallet.ports.postgres.model.CurrencyLocalizationModel +import org.springframework.data.repository.reactive.ReactiveCrudRepository +import org.springframework.stereotype.Repository +import reactor.core.publisher.Flux + +@Repository +interface CurrencyLocalizationsRepository : ReactiveCrudRepository { + suspend fun findByCurrency(currency: String): Flux +} \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepositoryV2.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepositoryV2.kt index 4aad40b08..731d5a384 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepositoryV2.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/CurrencyRepositoryV2.kt @@ -1,6 +1,7 @@ package co.nilin.opex.wallet.ports.postgres.dao import co.nilin.opex.wallet.core.inout.CurrencyPrecision +import co.nilin.opex.wallet.ports.postgres.dto.CurrencyView import co.nilin.opex.wallet.ports.postgres.model.CurrencyModel import org.springframework.data.r2dbc.repository.Query import org.springframework.data.repository.reactive.ReactiveCrudRepository @@ -8,45 +9,117 @@ import org.springframework.stereotype.Repository import reactor.core.publisher.Flux import reactor.core.publisher.Mono import java.math.BigDecimal -import java.util.* @Repository interface CurrencyRepositoryV2 : ReactiveCrudRepository { - fun findByIsTransitive(isTransitive: Boolean): Flux? - @Query("select * from currency where (:symbol is null or symbol=:symbol ) and (:uuid is null or uuid=:uuid ) order by display_order ") - fun fetchCurrency(uuid: String? = null, symbol: String? = null): Mono? - + @Query( + """ + SELECT + c.symbol, + c.uuid, + cl.name, + c.precision, + cl.title, + cl.alias, + c.icon, + c.is_transitive, + c.is_active, + c.sign, + cl.description, + cl.short_description, + c.external_url , + c.display_order, + c.max_order + FROM currency c + LEFT JOIN currency_localization cl + ON cl.currency = c.symbol AND cl.language = :lang + WHERE (:symbol IS NULL OR c.symbol = :symbol) + AND (:uuid IS NULL OR c.uuid = :uuid) + ORDER BY c.display_order +""" + ) + fun fetchCurrency( + uuid: String? = null, + symbol: String? = null, + lang: String? = null + ): Mono? - fun findBySymbol(symbol: String? = null): Mono? - @Query("select * from currency where (:symbol is null or symbol=:symbol) and (:name is null or name =:name ) order by display_order") - fun fetchSemiCurrencies(symbol: String? = null, name: String? = null): Flux? + @Query( + """ + SELECT + c.symbol, + c.uuid, + cl.name, + c.precision, + cl.title, + cl.alias, + c.icon, + c.is_transitive, + c.is_active, + c.sign, + cl.description, + cl.short_description, + c.external_url, + c.display_order, + c.max_order + FROM currency c + LEFT JOIN currency_localization cl + ON cl.currency = c.symbol AND cl.language = :lang + WHERE (:symbol IS NULL OR c.symbol = :symbol) + AND (:name IS NULL OR cl.name = :name) + ORDER BY c.display_order +""" + ) + fun fetchSemiCurrencies( + symbol: String? = null, + name: String? = null, + lang: String? = null + ): Flux? - @Query("insert into currency(symbol,uuid,name,precision,title,alias,icon,is_transitive,is_active,sign,description,short_description,external_url,display_order) values(:symbol,:uuid,:name,:precision,:title,:alias,:icon,:isTransitive,:isActive,:sign,:description,:shortDescription,:externalUrl,:order) ") + @Query("insert into currency(symbol,uuid,precision,icon,is_transitive,is_active,sign,external_url,display_order) values(:symbol,:uuid,:precision,:icon,:isTransitive,:isActive,:sign,:externalUrl,:displayOrder) ") fun insert( symbol: String, uuid: String, - name: String, precision: BigDecimal, - title: String? = null, - alias: String? = null, icon: String? = null, isTransitive: Boolean? = false, isActive: Boolean? = true, sign: String? = null, - description: String? = null, - shortDescription: String? = null, externalUrl: String? = null, - order: Int? = null + displayOrder: Int? = null ): Mono - @Query("select * from currency order by display_order ") - fun fetchAll(): Flux + @Query( + """ + SELECT + c.symbol, + c.uuid, + cl.name, + c.precision, + cl.title, + cl.alias, + c.icon, + c.is_transitive, + c.is_active, + c.sign, + cl.description, + cl.short_description, + c.external_url, + c.display_order, + c.max_order + FROM currency c + LEFT JOIN currency_localization cl + ON cl.currency = c.symbol AND cl.language = :lang + ORDER BY c.display_order +""" + ) + fun fetchAll(lang: String): Flux @Query("select symbol,precision from currency") fun fetchAllCurrenciesPrecision(): Flux diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/GatewayTerminalRepository.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/GatewayTerminalRepository.kt index 39f7e11cb..6a30ef6d8 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/GatewayTerminalRepository.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dao/GatewayTerminalRepository.kt @@ -28,7 +28,7 @@ interface GatewayTerminalRepository : ReactiveCrudRepository? diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dto/CurrencyView.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dto/CurrencyView.kt new file mode 100644 index 000000000..c00c337d0 --- /dev/null +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/dto/CurrencyView.kt @@ -0,0 +1,22 @@ +package co.nilin.opex.wallet.ports.postgres.dto + + +import java.math.BigDecimal + +data class CurrencyView( + var symbol: String, + var uuid: String, + var name: String? = null, + var precision: BigDecimal, + var title: String? = null, + var alias: String? = null, + var icon: String? = null, + var isTransitive: Boolean? = false, + var isActive: Boolean? = true, + var sign: String? = null, + var description: String? = null, + var shortDescription: String? = null, + var externalUrl: String? = null, + var displayOrder: Int? = null, + var maxOrder: BigDecimal? = null, +) \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImplV2.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImplV2.kt index 95c8f2a97..f353de635 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImplV2.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceImplV2.kt @@ -1,16 +1,16 @@ package co.nilin.opex.wallet.ports.postgres.impl -//import co.nilin.opex.wallet.core.model.Currencies -//import co.nilin.opex.wallet.core.model.Currency -//import co.nilin.opex.wallet.core.model.CurrencyImp import co.nilin.opex.common.OpexError -import co.nilin.opex.wallet.core.inout.CurrenciesCommand -import co.nilin.opex.wallet.core.inout.CurrencyCommand -import co.nilin.opex.wallet.core.inout.CurrencyData -import co.nilin.opex.wallet.core.inout.CurrencyPrecision +import co.nilin.opex.common.data.UserLanguage +import co.nilin.opex.common.utils.LanguageUtils.getDefaultUserLanguage +import co.nilin.opex.common.utils.LanguageUtils.getUserLanguage +import co.nilin.opex.wallet.core.inout.* import co.nilin.opex.wallet.core.model.FetchCurrency import co.nilin.opex.wallet.core.spi.CurrencyServiceManager +import co.nilin.opex.wallet.ports.postgres.dao.CurrencyLocalizationsRepository import co.nilin.opex.wallet.ports.postgres.dao.CurrencyRepositoryV2 +import co.nilin.opex.wallet.ports.postgres.dto.CurrencyView +import co.nilin.opex.wallet.ports.postgres.model.CurrencyLocalizationModel import co.nilin.opex.wallet.ports.postgres.model.CurrencyModel import co.nilin.opex.wallet.ports.postgres.util.RedisCacheHelper import co.nilin.opex.wallet.ports.postgres.util.toCommand @@ -18,49 +18,46 @@ import co.nilin.opex.wallet.ports.postgres.util.toCurrencyData import co.nilin.opex.wallet.ports.postgres.util.toModel import kotlinx.coroutines.reactive.awaitFirstOrElse import kotlinx.coroutines.reactive.awaitFirstOrNull +import kotlinx.coroutines.reactor.awaitSingle +import kotlinx.coroutines.reactor.awaitSingleOrNull import org.slf4j.LoggerFactory import org.springframework.stereotype.Service +import org.springframework.transaction.reactive.TransactionalOperator +import org.springframework.transaction.reactive.executeAndAwait import reactor.core.publisher.Flux import reactor.core.publisher.Mono import java.math.BigDecimal import java.util.stream.Collectors @Service("newVersion") -class CurrencyServiceImplV2(val currencyRepository: CurrencyRepositoryV2, val redisCacheHelper: RedisCacheHelper) : - CurrencyServiceManager { +class CurrencyServiceImplV2( + val currencyRepository: CurrencyRepositoryV2, + val redisCacheHelper: RedisCacheHelper, + val currencyLocalizationsRepository: CurrencyLocalizationsRepository, + val transactionalOperator: TransactionalOperator +) : CurrencyServiceManager { private val logger = LoggerFactory.getLogger(CurrencyServiceImplV2::class.java) override suspend fun createNewCurrency(request: CurrencyCommand, ignoreIfExist: Boolean?): CurrencyCommand? { return loadCurrency(FetchCurrency(symbol = request.symbol))?.awaitFirstOrNull()?.let { - if (!ignoreIfExist!!) - throw OpexError.CurrencyIsExist.exception() - else - return null + if (!ignoreIfExist!!) throw OpexError.CurrencyIsExist.exception() + else return null } ?: run { - return doPersist(request.toModel())?.toCommand() + return doPersist(request)?.toCommand() .also { redisCacheHelper.put("${request.symbol}-precision", request.precision) } } } override suspend fun updateCurrency(request: CurrencyCommand): CurrencyCommand? { - return loadCurrency(FetchCurrency(symbol = request.symbol)) - ?.awaitFirstOrNull()?.let { - doSave(it.toCommand().updateTo(request).toModel())?.toCommand() - .also { redisCacheHelper.put("${request.symbol}-precision", request.precision) } - } ?: throw OpexError.CurrencyNotFound.exception() + return loadCurrency(FetchCurrency(symbol = request.symbol))?.awaitFirstOrNull()?.let { + doSave(it.toCommand().updateTo(request).toModel())?.toCommand() + .also { redisCacheHelper.put("${request.symbol}-precision", request.precision) } + } ?: throw OpexError.CurrencyNotFound.exception() } -// override suspend fun prepareCurrencyToBeACryptoCurrency(request: String): CurrencyCommand? { -// return loadCurrency(FetchCurrency(symbol = request))?.awaitFirstOrNull()?.let { -// if (it.isCryptoCurrency == false) -// return doSave(it.apply { isCryptoCurrency = true })?.toCommand() -// it.toCommand() -// } ?: throw OpexError.CurrencyNotFound.exception() -// } - override suspend fun deleteCurrency(request: FetchCurrency): Void? { return loadCurrency(request)?.awaitFirstOrNull()?.let { currencyRepository.deleteById(it.symbol!!)?.awaitFirstOrNull() @@ -69,17 +66,17 @@ class CurrencyServiceImplV2(val currencyRepository: CurrencyRepositoryV2, val re } override suspend fun fetchCurrencies(request: FetchCurrency?): CurrenciesCommand? { - return CurrenciesCommand(loadCurrencies(request)?.map { it.toCommand() } - ?.collect(Collectors.toList())?.awaitFirstOrNull()) + return CurrenciesCommand( + loadCurrencies(request)?.map { it.toCommand() }?.collect(Collectors.toList()) + ?.awaitFirstOrNull() + ) } override suspend fun fetchAllCurrencies(): List { - return currencyRepository.fetchAll() + return currencyRepository.fetchAll(UserLanguage.safeValueOf(getUserLanguage().awaitSingleOrNull()).toString()) .map { it.toCurrencyData() - } - .collectList() - .awaitFirstOrElse { emptyList() } + }.collectList().awaitFirstOrElse { emptyList() } } override suspend fun fetchCurrency(request: FetchCurrency): CurrencyCommand? { @@ -94,42 +91,124 @@ class CurrencyServiceImplV2(val currencyRepository: CurrencyRepositoryV2, val re return currencyRepository.fetchCurrencyMaxOrder(symbol)?.awaitFirstOrNull() } - private suspend fun loadCurrency(request: FetchCurrency): Mono? { - if (request.uuid == null && request.symbol == null) - throw OpexError.BadRequest.exception() - return currencyRepository.fetchCurrency(symbol = request.symbol, uuid = request.uuid) + override suspend fun fetchCurrencyLocalizations(symbol: String): List { + loadCurrency(FetchCurrency(symbol = symbol))?.awaitFirstOrNull()?.let { + return currencyLocalizationsRepository.findByCurrency(symbol).map { it.toCommand() }.collectList() + .awaitSingleOrNull() ?: emptyList() + } ?: throw OpexError.CurrencyNotFound.exception() + } + + override suspend fun saveCurrencyLocalizations( + symbol: String, localizations: List + ): List { + + return transactionalOperator.executeAndAwait { + + loadCurrency(FetchCurrency(symbol = symbol))?.awaitFirstOrNull() + ?: throw OpexError.CurrencyNotFound.exception() + + localizations.forEach { c -> + currencyLocalizationsRepository.save( + CurrencyLocalizationModel( + currency = symbol, + name = c.name, + title = c.title, + alias = c.alias, + description = c.description, + shortDescription = c.shortDescription, + language = UserLanguage.safeValueOf(c.language).toString() + ) + ).awaitSingle() + } + + currencyLocalizationsRepository.findByCurrency(symbol).map { it.toCommand() }.collectList() + .awaitSingleOrNull() ?: emptyList() + } ?: throw OpexError.BadRequest.exception("Failed to save currency localizations") + } + + override suspend fun updateCurrencyLocalization(request: CurrencyLocalizationCommand): CurrencyLocalizationCommand { + if (request.id != null) { + val localizationModel = + currencyLocalizationsRepository.findById(request.id!!).awaitSingleOrNull() + ?: throw OpexError.CurrencyLocalizationNotFound.exception() + localizationModel.apply { + name = request.name + title = request.title + alias = request.alias + description = request.description + shortDescription = request.shortDescription + } + return currencyLocalizationsRepository.save(localizationModel).awaitSingle().toCommand() + } + throw OpexError.CurrencyLocalizationNotFound.exception() } - private suspend fun loadCurrencies(request: FetchCurrency?): Flux? { - return currencyRepository.fetchSemiCurrencies(request?.symbol, request?.name) + override suspend fun deleteCurrencyLocalization(id: Long) { + currencyLocalizationsRepository.deleteById(id).awaitSingleOrNull() } - private suspend fun doSave(request: CurrencyModel): CurrencyModel? { - return currencyRepository.save(request).awaitFirstOrNull() + private suspend fun loadCurrency(request: FetchCurrency): Mono? { + if (request.uuid == null && request.symbol == null) throw OpexError.BadRequest.exception() + return currencyRepository.fetchCurrency( + symbol = request.symbol, + uuid = request.uuid, + lang = UserLanguage.safeValueOf(getUserLanguage().awaitSingleOrNull()).toString() + ) } - private suspend fun doPersist(request: CurrencyModel): CurrencyModel? { - with(request) { + private suspend fun loadCurrencies(request: FetchCurrency?): Flux? { + return currencyRepository.fetchSemiCurrencies( + request?.symbol, request?.name, UserLanguage.safeValueOf(getUserLanguage().awaitSingleOrNull()).toString() + ) + } + + private suspend fun doSave(request: CurrencyModel): CurrencyView? { + currencyRepository.save(request).awaitFirstOrNull() + return currencyRepository.fetchCurrency( + uuid = request.uuid, lang = getDefaultUserLanguage() + )?.awaitFirstOrNull() + } + + private suspend fun doPersist(request: CurrencyCommand): CurrencyView? { + return transactionalOperator.executeAndAwait { currencyRepository.insert( - this.symbol, - this.uuid!!, - this.name, - this.precision, - this.title, - this.alias, - this.icon, - this.isTransitive, - this.isActive, - this.sign, - this.description, - this.shortDescription, - this.externalUrl, - this.order + request.symbol, + request.uuid!!, + request.precision, + request.icon, + request.isTransitive, + request.isActive, + request.sign, + request.externalUrl, + request.displayOrder ).awaitFirstOrNull() + if (listOf( + request.name, + request.title, + request.alias, + request.description, + request.shortDescription + ).any { !it.isNullOrBlank() } + ) { + currencyLocalizationsRepository.save( + CurrencyLocalizationModel( + currency = request.symbol, + name = request.name, + title = request.title, + alias = request.alias, + description = request.description, + shortDescription = request.shortDescription, + language = getDefaultUserLanguage() + ) + ).awaitFirstOrNull() + } + + currencyRepository.fetchCurrency( + uuid = request.uuid, lang = getDefaultUserLanguage() + )?.awaitFirstOrNull() } - return currencyRepository.fetchCurrency(uuid = request.uuid)?.awaitFirstOrNull() } diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/RateServiceImpl.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/RateServiceImpl.kt index bec0d14f4..a2dcdbaf6 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/RateServiceImpl.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/RateServiceImpl.kt @@ -11,6 +11,7 @@ import co.nilin.opex.wallet.ports.postgres.model.CurrencyModel import co.nilin.opex.wallet.ports.postgres.model.ForbiddenPairModel import co.nilin.opex.wallet.ports.postgres.model.ForbiddenSwapPairModel import co.nilin.opex.wallet.ports.postgres.model.RateModel +import co.nilin.opex.wallet.ports.postgres.util.toModel import kotlinx.coroutines.reactive.awaitFirstOrNull import org.slf4j.LoggerFactory import org.springframework.stereotype.Component @@ -157,7 +158,7 @@ class RateServiceImpl( symbols.symbols?.forEach { currencyRepository.fetchCurrency(symbol = it)?.awaitFirstOrNull()?.let { if (it.isActive == true) - currencyRepository.save(it.apply { isTransitive = true }).awaitFirstOrNull() + currencyRepository.save(it.apply { isTransitive = true }.toModel()).awaitFirstOrNull() } } } @@ -165,7 +166,7 @@ class RateServiceImpl( override suspend fun deleteTransitiveSymbols(symbols: Symbols): Symbols { symbols.symbols?.forEach { currencyRepository.fetchCurrency(symbol = it)?.awaitFirstOrNull()?.let { - currencyRepository.save(it.apply { isTransitive = false }).awaitFirstOrNull() + currencyRepository.save(it.apply { isTransitive = false }.toModel()).awaitFirstOrNull() } } return Symbols( diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/TerminalManagerImpl.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/TerminalManagerImpl.kt index 9bc7b33d1..2869ae50a 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/TerminalManagerImpl.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/TerminalManagerImpl.kt @@ -27,31 +27,33 @@ class TerminalManagerImpl( ) : TerminalManager { override suspend fun save(terminalCommand: TerminalCommand): TerminalCommand? { + return transactionalOperator.executeAndAwait { - terminalRepository.findByIdentifier(terminalCommand.identifier) - ?.awaitSingleOrNull() - ?.let { throw OpexError.TerminalIsExist.exception() } - - val terminal = terminalRepository - .save(terminalCommand.toModel()) - .awaitSingleOrNull() - ?: return null - - val terminalId = terminal.id ?: return null - - terminalCommand.description - ?.takeIf { it.isNotBlank() } - ?.let { description -> - terminalLocalizationsRepository.save( - TerminalLocalizationModel( - terminalId = terminalId, - description = description, - language = getDefaultUserLanguage() - ) - ).awaitSingleOrNull() - } + terminalRepository.findByIdentifier(terminalCommand.identifier) + ?.awaitSingleOrNull() + ?.let { throw OpexError.TerminalIsExist.exception() } - return terminalCommand.apply { uuid = terminal.uuid } + val terminal = terminalRepository + .save(terminalCommand.toModel()) + .awaitSingleOrNull() + ?: return@executeAndAwait null + + val terminalId = terminal.id ?: return@executeAndAwait null + + terminalCommand.description + ?.takeIf { it.isNotBlank() } + ?.let { description -> + terminalLocalizationsRepository.save( + TerminalLocalizationModel( + terminalId = terminalId, + description = description, + language = getDefaultUserLanguage() + ) + ).awaitSingleOrNull() + } + + terminalCommand.apply { uuid = terminal.uuid } + } } override suspend fun update(terminalCommand: TerminalCommand): TerminalCommand? { @@ -112,7 +114,7 @@ class TerminalManagerImpl( .collectList() .awaitSingleOrNull() ?: emptyList() - } ?: emptyList() + } ?: throw OpexError.BadRequest.exception("Failed to save terminal localizations") } override suspend fun fetchTerminalLocalizations(terminalUuid: String): List { diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletDataManagerImpl.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletDataManagerImpl.kt index 6151ad6b0..52541bc67 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletDataManagerImpl.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletDataManagerImpl.kt @@ -6,7 +6,6 @@ import co.nilin.opex.wallet.core.model.WalletType import co.nilin.opex.wallet.core.spi.WalletDataManager import co.nilin.opex.wallet.ports.postgres.dao.CurrencyRepositoryV2 import co.nilin.opex.wallet.ports.postgres.dao.WalletRepository -import co.nilin.opex.wallet.ports.postgres.model.CurrencyModel import com.fasterxml.jackson.core.type.TypeReference import com.fasterxml.jackson.databind.ObjectMapper import kotlinx.coroutines.reactive.awaitFirstOrElse @@ -27,7 +26,7 @@ class WalletDataManagerImpl( private val objectMapper: ObjectMapper, private val cacheManager: CacheManager, @Value("\${app.zone-offset}") private val zoneOffsetString: String, - ) : WalletDataManager { +) : WalletDataManager { override suspend fun findWalletDataByCriteria( uuid: String?, @@ -89,7 +88,7 @@ class WalletDataManagerImpl( } override suspend fun findUserWalletsTotal(): List? { - val allCurrencies = currencyRepositoryV2.fetchSemiCurrencies()?.map(CurrencyModel::symbol) + val allCurrencies = currencyRepositoryV2.fetchSemiCurrencies()?.map { it.symbol } val allDepositedCurrency = walletRepository.findUserWalletsTotal().collectList().awaitFirstOrElse { emptyList() } return allCurrencies?.map { c -> diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerImplV2.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerImplV2.kt index 90623da02..80575a5c3 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerImplV2.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerImplV2.kt @@ -3,7 +3,6 @@ package co.nilin.opex.wallet.ports.postgres.impl import co.nilin.opex.common.OpexError import co.nilin.opex.wallet.core.exc.ConcurrentBalanceChangException import co.nilin.opex.wallet.core.inout.CurrencyCommand -import co.nilin.opex.wallet.core.inout.DailyAmount import co.nilin.opex.wallet.core.model.* import co.nilin.opex.wallet.core.spi.WalletManager import co.nilin.opex.wallet.ports.postgres.dao.* @@ -13,18 +12,13 @@ import co.nilin.opex.wallet.ports.postgres.util.toCommand import kotlinx.coroutines.reactive.awaitFirst import kotlinx.coroutines.reactive.awaitFirstOrElse import kotlinx.coroutines.reactive.awaitFirstOrNull -import kotlinx.coroutines.reactive.awaitSingle import kotlinx.coroutines.reactor.awaitSingle import kotlinx.coroutines.reactor.awaitSingleOrNull import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service import java.math.BigDecimal -import java.time.LocalDate import java.time.LocalDateTime -import java.time.ZoneOffset -import java.util.concurrent.TimeUnit -import java.util.stream.Collectors @Service class WalletManagerImplV2( @@ -300,6 +294,7 @@ class WalletManagerImplV2( ) } } + override suspend fun findWallet(ownerId: Long, currency: String, walletType: WalletType): BriefWallet? { val wallet = walletRepository.findByOwnerAndTypeAndCurrency(ownerId, walletType, currency) .awaitSingleOrNull() ?: return null diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyLocalizationModel.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyLocalizationModel.kt new file mode 100644 index 000000000..4d4f4b6c0 --- /dev/null +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyLocalizationModel.kt @@ -0,0 +1,19 @@ +package co.nilin.opex.wallet.ports.postgres.model + + +import org.springframework.data.annotation.Id +import org.springframework.data.relational.core.mapping.Table + +@Table("currency_localization") +data class CurrencyLocalizationModel( + @Id + var id: Long? = null, + var currency: String, + var name: String? = null, + var title: String? = null, + var alias: String? = null, + var description: String? = null, + var shortDescription: String? = null, + var language: String, + + ) \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt index 9c76fe2a8..480a20d22 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/model/CurrencyModel.kt @@ -12,22 +12,16 @@ data class CurrencyModel( @Id var symbol: String, var uuid: String? = UUID.randomUUID().toString(), - var name: String, var precision: BigDecimal, - var title: String? = null, - var alias: String? = null, var icon: String? = null, @Column("is_transitive") var isTransitive: Boolean? = false, @Column("is_active") var isActive: Boolean? = true, var sign: String? = null, - var description: String? = null, - @Column("short_description") - var shortDescription: String? = null, @Column("external_url") var externalUrl: String? = null, @Column("display_order") - var order: Int? = null, + var displayOrder: Int? = null, var maxOrder : BigDecimal? = null, ) \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/util/Convertor.kt b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/util/Convertor.kt index 5c77cbd6b..9151b2ec8 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/util/Convertor.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/kotlin/co/nilin/opex/wallet/ports/postgres/util/Convertor.kt @@ -2,16 +2,17 @@ package co.nilin.opex.wallet.ports.postgres.util import co.nilin.opex.wallet.core.inout.* import co.nilin.opex.wallet.core.model.TotalAssetsSnapshot +import co.nilin.opex.wallet.ports.postgres.dto.CurrencyView import co.nilin.opex.wallet.ports.postgres.dto.TerminalView import co.nilin.opex.wallet.ports.postgres.model.* import java.time.ZoneId import java.util.* -fun CurrencyCommand.toModel(): CurrencyModel { - return CurrencyModel( +fun CurrencyCommand.toView(): CurrencyView { + return CurrencyView( symbol, - uuid, + uuid!!, name, precision, title, @@ -23,12 +24,42 @@ fun CurrencyCommand.toModel(): CurrencyModel { description, shortDescription, externalUrl, - order, + displayOrder, maxOrder ) } -fun CurrencyModel.toCommand(): CurrencyCommand { +fun CurrencyView.toModel(): CurrencyModel { + return CurrencyModel( + symbol, + uuid, + precision, + icon, + isTransitive, + isActive, + sign, + externalUrl, + displayOrder, + maxOrder + ) +} + +fun CurrencyCommand.toModel(): CurrencyModel { + return CurrencyModel( + symbol, + uuid, + precision, + icon, + isTransitive, + isActive, + sign, + externalUrl, + displayOrder, + maxOrder + ) +} + +fun CurrencyView.toCommand(): CurrencyCommand { return CurrencyCommand( symbol, uuid, @@ -47,11 +78,23 @@ fun CurrencyModel.toCommand(): CurrencyCommand { externalUrl, null, null, - order, + displayOrder, maxOrder ) } +fun CurrencyLocalizationModel.toCommand(): CurrencyLocalizationCommand { + return CurrencyLocalizationCommand( + id, + name, + title, + alias, + description, + shortDescription, + language + ) +} + fun Deposit.toModel(): DepositModel { return DepositModel( @@ -181,7 +224,7 @@ fun TerminalLocalizationModel.toCommand(): TerminalLocalizationCommand { ) } -fun CurrencyModel.toCurrencyData(): CurrencyData { +fun CurrencyView.toCurrencyData(): CurrencyData { return CurrencyData( symbol, uuid, @@ -196,7 +239,7 @@ fun CurrencyModel.toCurrencyData(): CurrencyData { description, shortDescription, externalUrl, - order, + displayOrder, maxOrder, ) } diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/db/migration/V9__add_currency_localizations_table.sql b/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/db/migration/V9__add_currency_localizations_table.sql new file mode 100644 index 000000000..2f39a0c9e --- /dev/null +++ b/wallet/wallet-ports/wallet-persister-postgres/src/main/resources/db/migration/V9__add_currency_localizations_table.sql @@ -0,0 +1,29 @@ +CREATE TABLE IF NOT EXISTS currency_localization +( + id SERIAL PRIMARY KEY, + currency VARCHAR(25) NOT NULL REFERENCES currency (symbol) ON DELETE CASCADE, + name VARCHAR(25), + title VARCHAR(25), + alias VARCHAR(25), + description TEXT, + short_description TEXT, + language VARCHAR(10) NOT NULL, + UNIQUE (currency, language) +); + +INSERT INTO currency_localization (currency, + name, + title, + alias, + description, + short_description, + language) +SELECT symbol, name, title, alias, description, short_description, 'EN' +FROM currency; + +ALTER TABLE currency + DROP COLUMN name, + DROP COLUMN title, + DROP COLUMN alias, + DROP COLUMN description, + DROP COLUMN short_description; \ No newline at end of file diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceTest.kt b/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceTest.kt index d33d6581d..80dc6c7d8 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceTest.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/CurrencyServiceTest.kt @@ -1,26 +1,36 @@ package co.nilin.opex.wallet.ports.postgres.impl import co.nilin.opex.wallet.core.model.FetchCurrency +import co.nilin.opex.wallet.ports.postgres.dao.CurrencyLocalizationsRepository import co.nilin.opex.wallet.ports.postgres.dao.CurrencyRepositoryV2 import co.nilin.opex.wallet.ports.postgres.impl.sample.VALID import co.nilin.opex.wallet.ports.postgres.util.RedisCacheHelper -import co.nilin.opex.wallet.ports.postgres.util.toModel +import co.nilin.opex.wallet.ports.postgres.util.toView import io.mockk.every import io.mockk.mockk import kotlinx.coroutines.runBlocking import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test +import org.springframework.transaction.reactive.TransactionalOperator import reactor.core.publisher.Mono private class CurrencyServiceTest { private val currencyRepository: CurrencyRepositoryV2 = mockk() private val redisCacheHelper: RedisCacheHelper = mockk() - private val currencyService: CurrencyServiceImplV2 = CurrencyServiceImplV2(currencyRepository,redisCacheHelper) + private val currencyLocalizationsRepository: CurrencyLocalizationsRepository = mockk() + private val transactionalOperator: TransactionalOperator = mockk() + private val currencyService: CurrencyServiceImplV2 = CurrencyServiceImplV2( + currencyRepository, + redisCacheHelper, + currencyLocalizationsRepository, + transactionalOperator + ) @Test fun givenCurrency_whenGetCurrency_thenReturnCurrency(): Unit = runBlocking { - every { currencyRepository.fetchCurrency(symbol = VALID.CURRENCY.symbol) } returns Mono.just(VALID.CURRENCY.toModel()) - + every { + currencyRepository.fetchCurrency(null, VALID.CURRENCY.symbol, any()) + } returns Mono.just(VALID.CURRENCY.toView()) val c = currencyService.fetchCurrency(FetchCurrency(symbol = VALID.CURRENCY.symbol)) assertThat(c).isNotNull diff --git a/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerTest.kt b/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerTest.kt index 130f8df70..396512a22 100644 --- a/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerTest.kt +++ b/wallet/wallet-ports/wallet-persister-postgres/src/test/kotlin/co/nilin/opex/wallet/ports/postgres/impl/WalletManagerTest.kt @@ -5,7 +5,7 @@ import co.nilin.opex.wallet.core.model.WalletType import co.nilin.opex.wallet.ports.postgres.dao.* import co.nilin.opex.wallet.ports.postgres.dto.toModel import co.nilin.opex.wallet.ports.postgres.impl.sample.VALID -import co.nilin.opex.wallet.ports.postgres.util.toModel +import co.nilin.opex.wallet.ports.postgres.util.toView import io.mockk.MockKException import io.mockk.every import io.mockk.mockk @@ -319,7 +319,7 @@ private class WalletManagerTest { } returns Mono.just(VALID.WALLET.toModel()) every { currencyRepository.fetchCurrency(symbol = VALID.CURRENCY.symbol) - } returns Mono.just(VALID.CURRENCY.toModel()) + } returns Mono.just(VALID.CURRENCY.toView()) println( walletRepository.findByOwnerAndTypeAndCurrency( @@ -464,7 +464,7 @@ private class WalletManagerTest { } returns Mono.just(VALID.WALLET_OWNER.toModel()) every { currencyRepository.fetchCurrency(symbol = VALID.CURRENCY.symbol) - } returns Mono.just(VALID.CURRENCY.toModel()) + } returns Mono.just(VALID.CURRENCY.toView()) val wallet = walletManagerImpl.findWalletById(VALID.WALLET.id!!)