diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 6ecc6dd3e..05645f66e 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -161,6 +161,7 @@ + diff --git a/company-command-service/company-command-data-access/src/main/java/com/intellibucket/onnetwork/company/dataAccess/command/model/entity/vacancy/VacancySalaryEntity.java b/company-command-service/company-command-data-access/src/main/java/com/intellibucket/onnetwork/company/dataAccess/command/model/entity/vacancy/VacancySalaryEntity.java index 56682ed6b..4f4e50459 100644 --- a/company-command-service/company-command-data-access/src/main/java/com/intellibucket/onnetwork/company/dataAccess/command/model/entity/vacancy/VacancySalaryEntity.java +++ b/company-command-service/company-command-data-access/src/main/java/com/intellibucket/onnetwork/company/dataAccess/command/model/entity/vacancy/VacancySalaryEntity.java @@ -1,7 +1,7 @@ package com.intellibucket.onnetwork.company.dataAccess.command.model.entity.vacancy; import az.rock.lib.domain.BaseEntity; -import az.rock.lib.valueObject.Currency; +import az.rock.lib.valueObject.CurrencyCode; import az.rock.lib.valueObject.vacancy.Payment; import jakarta.persistence.*; import lombok.AllArgsConstructor; @@ -25,7 +25,7 @@ public class VacancySalaryEntity extends BaseEntity { private Boolean hasSalary; @Column(name = "currency") - private Currency currency; + private CurrencyCode currencyCode; @Column(name = "start_amount") private BigDecimal startAmount; diff --git a/company-command-service/company-command-domain/company-command-domain-core/src/main/java/com/intellibucket/onnetwork/company/domain/core/command/root/vacancy/VacancySalaryRoot.java b/company-command-service/company-command-domain/company-command-domain-core/src/main/java/com/intellibucket/onnetwork/company/domain/core/command/root/vacancy/VacancySalaryRoot.java index 80f51a070..727ccb33f 100644 --- a/company-command-service/company-command-domain/company-command-domain-core/src/main/java/com/intellibucket/onnetwork/company/domain/core/command/root/vacancy/VacancySalaryRoot.java +++ b/company-command-service/company-command-domain/company-command-domain-core/src/main/java/com/intellibucket/onnetwork/company/domain/core/command/root/vacancy/VacancySalaryRoot.java @@ -3,11 +3,10 @@ import az.rock.lib.domain.AggregateRoot; import az.rock.lib.domain.id.vacancy.VacancyID; import az.rock.lib.domain.id.vacancy.VacancySalaryID; -import az.rock.lib.valueObject.Currency; +import az.rock.lib.valueObject.CurrencyCode; import az.rock.lib.valueObject.vacancy.Payment; import lombok.Builder; import lombok.Getter; -import lombok.experimental.SuperBuilder; import java.math.BigDecimal; @@ -18,7 +17,7 @@ public class VacancySalaryRoot extends AggregateRoot { private Boolean hasSalary; - private Currency currency; + private CurrencyCode currencyCode; private BigDecimal startAmount; diff --git a/company-command-service/company-command-domain/company-command-domain-presentation/src/main/java/com/intellibucket/onnetwork/company/domain/presentation/command/dto/request/vacancy/VacancySalaryCommand.java b/company-command-service/company-command-domain/company-command-domain-presentation/src/main/java/com/intellibucket/onnetwork/company/domain/presentation/command/dto/request/vacancy/VacancySalaryCommand.java index 4bc27fe62..b5fb85194 100644 --- a/company-command-service/company-command-domain/company-command-domain-presentation/src/main/java/com/intellibucket/onnetwork/company/domain/presentation/command/dto/request/vacancy/VacancySalaryCommand.java +++ b/company-command-service/company-command-domain/company-command-domain-presentation/src/main/java/com/intellibucket/onnetwork/company/domain/presentation/command/dto/request/vacancy/VacancySalaryCommand.java @@ -1,6 +1,6 @@ package com.intellibucket.onnetwork.company.domain.presentation.command.dto.request.vacancy; -import az.rock.lib.valueObject.Currency; +import az.rock.lib.valueObject.CurrencyCode; import az.rock.lib.valueObject.vacancy.Payment; import lombok.AllArgsConstructor; import lombok.Data; @@ -14,7 +14,7 @@ public class VacancySalaryCommand { private Boolean hasSalary; - private Currency currency; + private CurrencyCode currencyCode; private BigDecimal startAmount; diff --git a/exchange-service/pom.xml b/exchange-service/pom.xml index 15f57b943..f4eba315d 100644 --- a/exchange-service/pom.xml +++ b/exchange-service/pom.xml @@ -12,13 +12,19 @@ com.intellibucket.onnetwork.exchange exchange-service + 17 17 UTF-8 + + + org.springframework.boot + spring-boot-starter-aop + com.intellibucket.lib.fj ib-data-access @@ -81,8 +87,15 @@ grpc-client-spring-boot-starter 3.0.0.RELEASE + + com.intellibucket.lib + ib-auth-proto + 1.0-SNAPSHOT + compile + + @@ -92,6 +105,34 @@ + + org.liquibase + liquibase-maven-plugin + 4.4.3 + + src/main/resources/db/changelog-master.xml + + + + + diff + update + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + 2.3.2.RELEASE + + + org.postgresql + postgresql + 42.6.0 + + + org.springframework.boot spring-boot-maven-plugin diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/ExchangeServiceApplication.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/ExchangeServiceApplication.java index 6fe9957ec..5258df25e 100644 --- a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/ExchangeServiceApplication.java +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/ExchangeServiceApplication.java @@ -2,10 +2,14 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; +import org.springframework.cloud.openfeign.EnableFeignClients; @EnableDiscoveryClient @SpringBootApplication +@EnableFeignClients +@EntityScan(basePackages = "com/intellibucket/onnetwork/exchange/dataaccess/model/entity") public class ExchangeServiceApplication { public static void main(String[] args) { SpringApplication.run(ExchangeServiceApplication.class, args); diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/dataaccess/model/entity/CurrencyEntity.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/dataaccess/model/entity/CurrencyEntity.java new file mode 100644 index 000000000..90fd06b62 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/dataaccess/model/entity/CurrencyEntity.java @@ -0,0 +1,56 @@ +package com.intellibucket.onnetwork.exchange.dataaccess.model.entity; + +import az.rock.lib.domain.BaseEntity; +import az.rock.lib.valueObject.CurrencyCode; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.*; +import org.hibernate.Hibernate; + +import java.util.Objects; + +@Entity(name = "CurrencyEntity") +@Table(name = "currency", schema = "exchange", indexes = { + @Index(name = "currency_code_index", columnList = "code", unique = true) +}) +@Getter +@Setter +@ToString +@AllArgsConstructor +@NoArgsConstructor +public class CurrencyEntity extends BaseEntity { + + @Enumerated(EnumType.STRING) + @NotNull + private CurrencyCode code; + + @Column(name = "symbol", nullable = false, updatable = false) + private String symbol; + + @Column(name = "name", nullable = false, updatable = false) + private String name; + + @Column(name = "symbol_native") + private String symbolNative; + + @Column(name = "decimal_digits", nullable = false) + private String decimalDigits; + + @Column(name = "rounding", nullable = false) + private String rounding; + + @Column(name = "name_plural") + private String namePlural; + + @Column(name = "type") + private String type; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false; + CurrencyEntity that = (CurrencyEntity) o; + return getUuid() != null && Objects.equals(getUuid(), that.getUuid()); + } + +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/dataaccess/model/entity/ExchangeEntity.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/dataaccess/model/entity/ExchangeEntity.java new file mode 100644 index 000000000..cd81aeb39 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/dataaccess/model/entity/ExchangeEntity.java @@ -0,0 +1,27 @@ +package com.intellibucket.onnetwork.exchange.dataaccess.model.entity; + +import az.rock.lib.domain.BaseEntity; +import az.rock.lib.valueObject.CurrencyCode; +import jakarta.persistence.*; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Entity(name = "ExchangeEntity") +@Table(name = "exchanges", schema = "exchange") +@Getter +@Setter +@ToString +@AllArgsConstructor +@NoArgsConstructor +public class ExchangeEntity extends BaseEntity { + @Column(name = "fetch_date", nullable = false, columnDefinition = "TIMESTAMP") + private LocalDateTime fetchDate; + @Enumerated(EnumType.STRING) + private CurrencyCode baseCurrency; + @Enumerated(EnumType.STRING) + private CurrencyCode targetCurrency; + @Column(name = "rate", nullable = false) + private BigDecimal rate; +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/core/root/CurrencyRoot.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/core/root/CurrencyRoot.java new file mode 100644 index 000000000..4de80ffda --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/core/root/CurrencyRoot.java @@ -0,0 +1,17 @@ +package com.intellibucket.onnetwork.exchange.domain.core.root; + +import az.rock.lib.domain.AggregateRoot; +import az.rock.lib.domain.id.exchange.CurrencyID; +import az.rock.lib.valueObject.CurrencyCode; + + +public class CurrencyRoot extends AggregateRoot { + private CurrencyCode code; + private String symbol; + private String name; + private String symbolNative; + private String decimalDigits; + private String rounding; + private String namePlural; + private String type; +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/core/root/ExchangeRoot.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/core/root/ExchangeRoot.java new file mode 100644 index 000000000..093d20614 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/core/root/ExchangeRoot.java @@ -0,0 +1,15 @@ +package com.intellibucket.onnetwork.exchange.domain.core.root; + +import az.rock.lib.domain.AggregateRoot; +import az.rock.lib.domain.id.exchange.ExchangeID; +import az.rock.lib.valueObject.CurrencyCode; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +public class ExchangeRoot extends AggregateRoot { + private LocalDateTime fetchDate; + private CurrencyCode baseCurrency; + private CurrencyCode targetCurrency; + private BigDecimal rate; +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/config/AsyncConfig.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/config/AsyncConfig.java new file mode 100644 index 000000000..e9db4c23f --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/config/AsyncConfig.java @@ -0,0 +1,14 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +@Configuration +@EnableAsync +@Slf4j +public class AsyncConfig { + { + log.info("AsyncConfig initialized"); + } +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/config/SchedulerConfig.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/config/SchedulerConfig.java new file mode 100644 index 000000000..1b4ac9a7f --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/config/SchedulerConfig.java @@ -0,0 +1,14 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; + +@Configuration +@EnableScheduling +@Slf4j +public class SchedulerConfig { + { + log.info("SchedulerConfig initialized"); + } +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/api/request/package-info.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/api/request/package-info.java new file mode 100644 index 000000000..1b3f34686 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/api/request/package-info.java @@ -0,0 +1 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.dto.api.request; \ No newline at end of file diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/api/response/package-info.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/api/response/package-info.java new file mode 100644 index 000000000..1581cfe25 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/api/response/package-info.java @@ -0,0 +1 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.dto.api.response; \ No newline at end of file diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/feign/response/ExchangeRates.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/feign/response/ExchangeRates.java new file mode 100644 index 000000000..6a5c331ef --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/dto/feign/response/ExchangeRates.java @@ -0,0 +1,32 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.dto.feign.response; + +import az.rock.lib.valueObject.CurrencyCode; +import lombok.Data; +import lombok.ToString; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + + +@Data +@ToString +public class ExchangeRates { + private Map data; + + public ExchangeRates() { + this.data = new HashMap<>(); + } + + public static ExchangeRates of() { + return new ExchangeRates(); + } + + public void addCurrencyRate(CurrencyCode currencyCode, BigDecimal rate) { + this.data.put(currencyCode, rate); + } + + public void addCurrencyRate(String currencyCode, BigDecimal rate) { + this.addCurrencyRate(CurrencyCode.valueOf(currencyCode.toUpperCase()), rate); + } +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/annotations/JExecutionTime.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/annotations/JExecutionTime.java new file mode 100644 index 000000000..b9089d793 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/annotations/JExecutionTime.java @@ -0,0 +1,9 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.lib.aspect.annotations; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Target({java.lang.annotation.ElementType.METHOD}) +@Retention(java.lang.annotation.RetentionPolicy.RUNTIME) +public @interface JExecutionTime { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/impl/ExecutionTimeAspect.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/impl/ExecutionTimeAspect.java new file mode 100644 index 000000000..b217fe2c6 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/impl/ExecutionTimeAspect.java @@ -0,0 +1,30 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.lib.aspect.impl; + +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +@Aspect +@Component +@Slf4j +public class ExecutionTimeAspect { + + @Around("@annotation(com.intellibucket.onnetwork.exchange.domain.presentation.lib.aspect.annotations.JExecutionTime)") + public Object logExecutionTime(ProceedingJoinPoint proceedingJoinPoint) { + log.info("Execution time aspect is called for {}", proceedingJoinPoint.getSignature().getName()); + long start = System.currentTimeMillis(); + Object proceed = null; + try { + proceed = proceedingJoinPoint.proceed(); + } catch (Throwable throwable) { + log.error("Error in execution time aspect for {}, {}", throwable, proceedingJoinPoint.getSignature().getName()); + } + long executionTime = System.currentTimeMillis() - start; + log.info("{} executed in {} ms", proceedingJoinPoint.getSignature().getName(), executionTime); + log.info("Execution time aspect is completed for {}", proceedingJoinPoint.getSignature().getName()); + return proceed; + } + +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/package-info.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/package-info.java new file mode 100644 index 000000000..e4e3acca4 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/aspect/package-info.java @@ -0,0 +1 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.lib.aspect; \ No newline at end of file diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/package-info.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/package-info.java new file mode 100644 index 000000000..6798e0e84 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/lib/package-info.java @@ -0,0 +1 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.lib; \ No newline at end of file diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/abstracts/AbstractCurrencyDomainMapper.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/abstracts/AbstractCurrencyDomainMapper.java new file mode 100644 index 000000000..f0b561e4c --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/abstracts/AbstractCurrencyDomainMapper.java @@ -0,0 +1,4 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.mapper.abstracts; + +public abstract class AbstractCurrencyDomainMapper { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/abstracts/AbstractExchangeDomainMapper.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/abstracts/AbstractExchangeDomainMapper.java new file mode 100644 index 000000000..a4cbaa72a --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/abstracts/AbstractExchangeDomainMapper.java @@ -0,0 +1,4 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.mapper.abstracts; + +public abstract class AbstractExchangeDomainMapper { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/concretes/CurrencyDomainMapper.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/concretes/CurrencyDomainMapper.java new file mode 100644 index 000000000..10e671f62 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/concretes/CurrencyDomainMapper.java @@ -0,0 +1,8 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.mapper.concretes; + +import com.intellibucket.onnetwork.exchange.domain.presentation.mapper.abstracts.AbstractCurrencyDomainMapper; +import org.springframework.stereotype.Component; + +@Component +public class CurrencyDomainMapper extends AbstractCurrencyDomainMapper { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/concretes/ExchangeDomainMapper.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/concretes/ExchangeDomainMapper.java new file mode 100644 index 000000000..f0e444e3a --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/mapper/concretes/ExchangeDomainMapper.java @@ -0,0 +1,8 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.mapper.concretes; + +import com.intellibucket.onnetwork.exchange.domain.presentation.mapper.abstracts.AbstractExchangeDomainMapper; +import org.springframework.stereotype.Component; + +@Component +public class ExchangeDomainMapper extends AbstractExchangeDomainMapper { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/schedulers/abstracts/AbstractCurrencyScheduler.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/schedulers/abstracts/AbstractCurrencyScheduler.java new file mode 100644 index 000000000..dfc8c260b --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/schedulers/abstracts/AbstractCurrencyScheduler.java @@ -0,0 +1,8 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.schedulers.abstracts; + +public interface AbstractCurrencyScheduler { + void latestRateScheduler(); + + void exchangeInfoScheduler(); + +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/schedulers/concretes/FreeCurrencyAPIScheduler.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/schedulers/concretes/FreeCurrencyAPIScheduler.java new file mode 100644 index 000000000..7d69ed1b9 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/schedulers/concretes/FreeCurrencyAPIScheduler.java @@ -0,0 +1,46 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.schedulers.concretes; + +import com.intellibucket.onnetwork.exchange.domain.presentation.dto.feign.response.ExchangeRates; +import com.intellibucket.onnetwork.exchange.domain.presentation.lib.aspect.annotations.JExecutionTime; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.schedulers.abstracts.AbstractCurrencyScheduler; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.abstracts.AbstractCurrencyCommandDomainPresentationService; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.abstracts.AbstractExchangeCommandDomainPresentationService; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.output.currency.abstracts.FreeCurrencyAPIClient; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +@Slf4j +public class FreeCurrencyAPIScheduler implements AbstractCurrencyScheduler { + @Value("${external-api.free-currency.key}") + private String apiKey; + private final FreeCurrencyAPIClient freeCurrencyAPIClient; + private final AbstractCurrencyCommandDomainPresentationService currencyCommandDomainPresentationService; + private final AbstractExchangeCommandDomainPresentationService exchangeCommandDomainPresentationService; + + + @Override + @Scheduled(fixedRateString = "${ws.values.scheduler.latest-rate}") + @JExecutionTime + public void latestRateScheduler() { + log.info("Latest rate scheduler started"); + var currencyRates = ExchangeRates.of(); + this.freeCurrencyAPIClient.fetchAllLatestRates(this.apiKey) + .get("data").fields().forEachRemaining(entry -> { + currencyRates.addCurrencyRate(entry.getKey(), entry.getValue().decimalValue()); + }); + this.exchangeCommandDomainPresentationService.saveLatestRates(currencyRates); + } + + @Override + @Scheduled(cron = "${ws.values.scheduler.exchange-info-rate}") + //This scheduler must be executed every 1 month + public void exchangeInfoScheduler() { + log.info("Historical rate scheduler"); + } + +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/abstracts/AbstractCurrencyCommandDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/abstracts/AbstractCurrencyCommandDomainPresentationService.java new file mode 100644 index 000000000..665642fca --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/abstracts/AbstractCurrencyCommandDomainPresentationService.java @@ -0,0 +1,4 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.abstracts; + +public interface AbstractCurrencyCommandDomainPresentationService { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/abstracts/AbstractExchangeCommandDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/abstracts/AbstractExchangeCommandDomainPresentationService.java new file mode 100644 index 000000000..28da20339 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/abstracts/AbstractExchangeCommandDomainPresentationService.java @@ -0,0 +1,7 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.abstracts; + +import com.intellibucket.onnetwork.exchange.domain.presentation.dto.feign.response.ExchangeRates; + +public interface AbstractExchangeCommandDomainPresentationService { + void saveLatestRates(ExchangeRates currencyRates); +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/concretes/CurrencyCommandDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/concretes/CurrencyCommandDomainPresentationService.java new file mode 100644 index 000000000..d37aa16ac --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/concretes/CurrencyCommandDomainPresentationService.java @@ -0,0 +1,10 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.concretes; + +import az.rock.lib.annotation.InputPort; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.abstracts.AbstractCurrencyCommandDomainPresentationService; +import org.springframework.stereotype.Service; + +@Service +@InputPort +public class CurrencyCommandDomainPresentationService implements AbstractCurrencyCommandDomainPresentationService { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/concretes/ExchangeCommandDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/concretes/ExchangeCommandDomainPresentationService.java new file mode 100644 index 000000000..87f6e1b96 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/command/concretes/ExchangeCommandDomainPresentationService.java @@ -0,0 +1,15 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.concretes; + +import az.rock.lib.annotation.InputPort; +import com.intellibucket.onnetwork.exchange.domain.presentation.dto.feign.response.ExchangeRates; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.command.abstracts.AbstractExchangeCommandDomainPresentationService; +import org.springframework.stereotype.Service; + +@InputPort +@Service +public class ExchangeCommandDomainPresentationService implements AbstractExchangeCommandDomainPresentationService { + @Override + public void saveLatestRates(ExchangeRates currencyRates) { + + } +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/abstracts/AbstractCurrencyQueryDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/abstracts/AbstractCurrencyQueryDomainPresentationService.java new file mode 100644 index 000000000..e75fc963d --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/abstracts/AbstractCurrencyQueryDomainPresentationService.java @@ -0,0 +1,4 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.query.abstracts; + +public interface AbstractCurrencyQueryDomainPresentationService { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/abstracts/AbstractExchangeQueryDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/abstracts/AbstractExchangeQueryDomainPresentationService.java new file mode 100644 index 000000000..ad55966df --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/abstracts/AbstractExchangeQueryDomainPresentationService.java @@ -0,0 +1,4 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.query.abstracts; + +public interface AbstractExchangeQueryDomainPresentationService { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/concretes/CurrencyQueryDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/concretes/CurrencyQueryDomainPresentationService.java new file mode 100644 index 000000000..eff73b729 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/concretes/CurrencyQueryDomainPresentationService.java @@ -0,0 +1,10 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.query.concretes; + +import az.rock.lib.annotation.InputPort; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.query.abstracts.AbstractCurrencyQueryDomainPresentationService; +import org.springframework.stereotype.Service; + +@Service +@InputPort +public class CurrencyQueryDomainPresentationService implements AbstractCurrencyQueryDomainPresentationService { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/concretes/ExchangeQueryDomainPresentationService.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/concretes/ExchangeQueryDomainPresentationService.java new file mode 100644 index 000000000..d8abeb9cc --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/input/services/query/concretes/ExchangeQueryDomainPresentationService.java @@ -0,0 +1,10 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.query.concretes; + +import az.rock.lib.annotation.InputPort; +import com.intellibucket.onnetwork.exchange.domain.presentation.ports.input.services.query.abstracts.AbstractExchangeQueryDomainPresentationService; +import org.springframework.stereotype.Service; + +@InputPort +@Service +public class ExchangeQueryDomainPresentationService implements AbstractExchangeQueryDomainPresentationService { +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/currency/abstracts/FreeCurrencyAPIClient.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/currency/abstracts/FreeCurrencyAPIClient.java new file mode 100644 index 000000000..fbd57146d --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/currency/abstracts/FreeCurrencyAPIClient.java @@ -0,0 +1,15 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.output.currency.abstracts; + +import com.fasterxml.jackson.databind.JsonNode; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@Component +@FeignClient(name = "free-currency-api", url = "${external-api.free-currency.url}") +public interface FreeCurrencyAPIClient { + + @GetMapping("v1/latest?apikey={api-key}") + JsonNode fetchAllLatestRates(@PathVariable("api-key") String apiKey); +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/package-info.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/package-info.java new file mode 100644 index 000000000..3d441aaff --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/package-info.java @@ -0,0 +1 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.output; \ No newline at end of file diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/GRPCAuthorizationConfig.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/GRPCAuthorizationConfig.java new file mode 100644 index 000000000..135354e10 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/GRPCAuthorizationConfig.java @@ -0,0 +1,22 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.output.rpc.config; + +import com.intellibucket.lib.proto.UserRelationLevelServiceGrpc; +import net.devh.boot.grpc.client.inject.GrpcClient; +import net.devh.boot.grpc.client.inject.GrpcClientBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@GrpcClientBean( + clazz = UserRelationLevelServiceGrpc.UserRelationLevelServiceStub.class, + beanName = "userRelationLevelServiceStub", + client = @GrpcClient("authorization-rpc") +) +public class GRPCAuthorizationConfig { + + @Bean + public UserRelationLevelServiceGrpc.UserRelationLevelServiceStub userRelationLevelServiceStub() { + return null; + } + +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/GlobalRPCInterceptor.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/GlobalRPCInterceptor.java new file mode 100644 index 000000000..d2ae90e24 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/GlobalRPCInterceptor.java @@ -0,0 +1,13 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.output.rpc.config; + +import io.grpc.*; +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class GlobalRPCInterceptor implements ClientInterceptor { + @Override + public ClientCall interceptCall(MethodDescriptor method, CallOptions callOptions, Channel next) { + log.info("Intercepted call to method: {}", method.getFullMethodName()); + return next.newCall(method, callOptions); + } +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/RPCInterceptorConfig.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/RPCInterceptorConfig.java new file mode 100644 index 000000000..253348d1e --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/config/RPCInterceptorConfig.java @@ -0,0 +1,12 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.output.rpc.config; + +import net.devh.boot.grpc.client.interceptor.GrpcGlobalClientInterceptor; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RPCInterceptorConfig { + @GrpcGlobalClientInterceptor + public GlobalRPCInterceptor logClientInterceptor() { + return new GlobalRPCInterceptor(); + } +} diff --git a/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/package-info.java b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/package-info.java new file mode 100644 index 000000000..e6600a488 --- /dev/null +++ b/exchange-service/src/main/java/com/intellibucket/onnetwork/exchange/domain/presentation/ports/output/rpc/package-info.java @@ -0,0 +1 @@ +package com.intellibucket.onnetwork.exchange.domain.presentation.ports.output.rpc; \ No newline at end of file diff --git a/exchange-service/src/main/resources/db/changelog-master.xml b/exchange-service/src/main/resources/db/changelog-master.xml new file mode 100644 index 000000000..3cf749450 --- /dev/null +++ b/exchange-service/src/main/resources/db/changelog-master.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/exchange-service/src/main/resources/db/env/schema-init.xml b/exchange-service/src/main/resources/db/env/schema-init.xml new file mode 100644 index 000000000..d440d807c --- /dev/null +++ b/exchange-service/src/main/resources/db/env/schema-init.xml @@ -0,0 +1,11 @@ + + + + + CREATE SCHEMA IF NOT EXISTS exchange + + + diff --git a/exchange-service/src/main/resources/exchange-persistence.xml b/exchange-service/src/main/resources/exchange-persistence.xml new file mode 100644 index 000000000..15859845f --- /dev/null +++ b/exchange-service/src/main/resources/exchange-persistence.xml @@ -0,0 +1,9 @@ + + + + com.intellibucket.onnetwork.exchange.dataaccess.model.entity.CurrencyEntity + com.intellibucket.onnetwork.exchange.dataaccess.model.entity.ExchangeEntity + + \ No newline at end of file diff --git a/library/ib-rpc/ib-exchange-proto/pom.xml b/library/ib-rpc/ib-exchange-proto/pom.xml new file mode 100644 index 000000000..c40e297fa --- /dev/null +++ b/library/ib-rpc/ib-exchange-proto/pom.xml @@ -0,0 +1,86 @@ + + + + ib-rpc + com.intellibucket.lib + 1.0-SNAPSHOT + + 4.0.0 + + ib-exchange-proto + + + 17 + 17 + UTF-8 + 1.30.0 + + + + + + org.slf4j + slf4j-api + 1.7.32 + + + javax.annotation + javax.annotation-api + 1.3.2 + + + io.grpc + grpc-netty-shaded + 1.62.2 + + + io.grpc + grpc-protobuf + 1.62.2 + + + io.grpc + grpc-stub + 1.62.2 + + + org.projectlombok + lombok + compile + + + + + + + kr.motd.maven + os-maven-plugin + 1.7.0 + + + + + org.xolstice.maven.plugins + protobuf-maven-plugin + 0.6.1 + + com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier} + grpc-java + io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier} + + + + + + compile + compile-custom + + + + + + + + \ No newline at end of file diff --git a/library/ib-rpc/ib-exchange-proto/src/main/java/com/intellibucket/lib/package-info.java b/library/ib-rpc/ib-exchange-proto/src/main/java/com/intellibucket/lib/package-info.java new file mode 100644 index 000000000..924bbb464 --- /dev/null +++ b/library/ib-rpc/ib-exchange-proto/src/main/java/com/intellibucket/lib/package-info.java @@ -0,0 +1 @@ +package com.intellibucket.lib; \ No newline at end of file diff --git a/library/ib-rpc/ib-exchange-proto/src/main/proto/exchange.proto b/library/ib-rpc/ib-exchange-proto/src/main/proto/exchange.proto new file mode 100644 index 000000000..0fddc1310 --- /dev/null +++ b/library/ib-rpc/ib-exchange-proto/src/main/proto/exchange.proto @@ -0,0 +1,74 @@ +syntax = "proto3"; +option java_multiple_files = true; +package com.intellibucket.lib.proto; + + +enum CurrencyCode { + EUR = 0; + USD = 1; + AZN = 2; + TRY = 3; + JPY = 4; + BGN = 5; + CZK = 6; + DKK = 7; + GBP = 8; + HUF = 9; + PLN = 10; + RON = 11; + SEK = 12; + CHF = 13; + ISK = 14; + NOK = 15; + HRK = 16; + RUB = 17; + AUD = 18; + BRL = 19; + CAD = 20; + CNY = 21; + HKD = 22; + IDR = 23; + ILS = 24; + INR = 25; + KRW = 26; + MXN = 27; + MYR = 28; + NZD = 29; + PHP = 30; + SGD = 31; + THB = 32; + ZAR = 33; +} + + +message ExchangeRequest { + CurrencyCode code = 1; +} + + +message CurrentExchangeRateResponse { + string uuid = 1; + string baseCurrency = 2; + string targetCurrency = 3; + double exchangeRate = 4; + int64 timestamp = 5; +} + +service ExchangeRateService { + + rpc GetCurrentExchangeRate (ExchangeRequest) returns (CurrentExchangeRateResponse); + +} + + + + + + + + + + + + + diff --git a/library/ib-rpc/pom.xml b/library/ib-rpc/pom.xml index f83f58ddf..2d20ddc42 100644 --- a/library/ib-rpc/pom.xml +++ b/library/ib-rpc/pom.xml @@ -16,6 +16,7 @@ ib-auth-proto ib-dfs-proto + ib-exchange-proto 17 diff --git a/library/rock-domain/src/main/java/az/rock/lib/domain/id/exchange/CurrencyID.java b/library/rock-domain/src/main/java/az/rock/lib/domain/id/exchange/CurrencyID.java new file mode 100644 index 000000000..32d73b751 --- /dev/null +++ b/library/rock-domain/src/main/java/az/rock/lib/domain/id/exchange/CurrencyID.java @@ -0,0 +1,17 @@ +package az.rock.lib.domain.id.exchange; + +import az.rock.lib.domain.RootID; +import az.rock.lib.domain.id.IdReference; + +import java.util.UUID; + +public class CurrencyID extends RootID implements IdReference { + protected CurrencyID(UUID value) { + super(value); + } + + @Override + public UUID getAbsoluteID() { + return super.getRootID(); + } +} diff --git a/library/rock-domain/src/main/java/az/rock/lib/domain/id/exchange/ExchangeID.java b/library/rock-domain/src/main/java/az/rock/lib/domain/id/exchange/ExchangeID.java new file mode 100644 index 000000000..bb57abf97 --- /dev/null +++ b/library/rock-domain/src/main/java/az/rock/lib/domain/id/exchange/ExchangeID.java @@ -0,0 +1,17 @@ +package az.rock.lib.domain.id.exchange; + +import az.rock.lib.domain.RootID; +import az.rock.lib.domain.id.IdReference; + +import java.util.UUID; + +public class ExchangeID extends RootID implements IdReference { + protected ExchangeID(UUID value) { + super(value); + } + + @Override + public UUID getAbsoluteID() { + return super.getRootID(); + } +} diff --git a/library/rock-domain/src/main/java/az/rock/lib/valueObject/Currency.java b/library/rock-domain/src/main/java/az/rock/lib/valueObject/Currency.java deleted file mode 100644 index 29015fabd..000000000 --- a/library/rock-domain/src/main/java/az/rock/lib/valueObject/Currency.java +++ /dev/null @@ -1,18 +0,0 @@ -package az.rock.lib.valueObject; - -import az.rock.lib.annotation.ValueObject; - -@ValueObject -public enum Currency { - EUR("€"), USD("$"), AZN("₼"), YTL("₺"); - - private final String sign; - - Currency(String sign) { - this.sign = sign; - } - - public String getSign() { - return sign; - } -} diff --git a/library/rock-domain/src/main/java/az/rock/lib/valueObject/CurrencyCode.java b/library/rock-domain/src/main/java/az/rock/lib/valueObject/CurrencyCode.java new file mode 100644 index 000000000..118b18818 --- /dev/null +++ b/library/rock-domain/src/main/java/az/rock/lib/valueObject/CurrencyCode.java @@ -0,0 +1,52 @@ +package az.rock.lib.valueObject; + +import az.rock.lib.annotation.ValueObject; + +@ValueObject +public enum CurrencyCode { + EUR("€"), + USD("$"), + AZN("₼"), + TRY("₺"), + JPY("¥"), + BGN("лв"), + CZK("Kč"), + DKK("kr"), + GBP("£"), + HUF("Ft"), + PLN("zł"), + RON("lei"), + SEK("sek"), + CHF("chf"), + ISK("kr"), + NOK("kr"), + HRK("kn"), + RUB("₽"), + AUD("$"), + BRL("R$"), + CAD("$"), + CNY("¥"), + HKD("$"), + IDR("Rp"), + ILS("₪"), + INR("inr"), + KRW("krw"), + MXN("$"), + MYR("RM"), + NZD("$"), + PHP("₱"), + SGD("$"), + THB("฿"), + ZAR("R"), + NONE("NONE"); + + private final String sign; + + CurrencyCode(String sign) { + this.sign = sign; + } + + public String getSign() { + return sign; + } +}