├── .fastRequest
└── config
│ └── fastRequestCurrentProjectConfig.json
├── .idea
├── .gitignore
├── JPASupport-project.xml
├── RestfulApiTool-Environment-Cache.xml
├── aws.xml
├── compiler.xml
├── dbnavigator.xml
├── encodings.xml
├── fastRequest
│ ├── fastRequestCollection.xml
│ └── fastRequestCurrentProjectLocalConfig.xml
├── inspectionProfiles
│ └── Project_Default.xml
├── jarRepositories.xml
├── jpa.xml
├── jsLibraryMappings.xml
├── misc.xml
├── spring-boot-microservice.iml
├── uiDesigner.xml
└── vcs.xml
├── .vscode
└── settings.json
├── CONTRIBUTING.md
├── License
├── README.md
├── api-gateway
├── .gitattributes
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── api
│ │ │ └── gateway
│ │ │ ├── ApiGatewayApplication.java
│ │ │ ├── RedisConfig.java
│ │ │ └── filter
│ │ │ ├── JwtAuthenticationFilter.java
│ │ │ ├── JwtTokenUtil.java
│ │ │ └── RouteValidator.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── api
│ └── gateway
│ └── ApiGatewayApplicationTests.java
├── auth-service
├── .gitattributes
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── auth_service
│ │ │ ├── AuthServiceApplication.java
│ │ │ ├── config
│ │ │ ├── DataSourceConfig.java
│ │ │ ├── RedisConfig.java
│ │ │ ├── SecretManagerConfig.java
│ │ │ ├── SecurityConfig.java
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ ├── AdminController.java
│ │ │ ├── AuthController.java
│ │ │ └── TokenController.java
│ │ │ ├── dto
│ │ │ ├── request
│ │ │ │ ├── UserEmailVerificationRequestDto.java
│ │ │ │ ├── UserLoginRequestDTO.java
│ │ │ │ ├── UserRegistrationRequestDTO.java
│ │ │ │ └── UserUpdatePasswordRequestDTO.java
│ │ │ └── response
│ │ │ │ ├── UserEmailVerificationResponseDto.java
│ │ │ │ ├── UserLoginResponseDTO.java
│ │ │ │ ├── UserRegistrationResponseDTO.java
│ │ │ │ └── UserUpdatePasswordResponseDTO.java
│ │ │ ├── enums
│ │ │ └── Role.java
│ │ │ ├── exception
│ │ │ ├── AuthenticationException.java
│ │ │ ├── EmailAlreadyExistsException.java
│ │ │ ├── EmailSendException.java
│ │ │ ├── ErrorDetails.java
│ │ │ ├── InvalidRequestException.java
│ │ │ ├── InvalidVerificationCodeException.java
│ │ │ ├── UserNotFoundException.java
│ │ │ ├── VerificationCodeExpiredException.java
│ │ │ ├── VerificationCodeNotFoundException.java
│ │ │ ├── VerificationCodeStillValidException.java
│ │ │ └── handler
│ │ │ │ └── GlobalExceptionHandler.java
│ │ │ ├── filter
│ │ │ └── JwtAuthenticationFilter.java
│ │ │ ├── mapper
│ │ │ └── UserMapper.java
│ │ │ ├── model
│ │ │ ├── Token.java
│ │ │ └── User.java
│ │ │ ├── repository
│ │ │ ├── TokenRepository.java
│ │ │ └── UserRepository.java
│ │ │ ├── service
│ │ │ ├── AuthService.java
│ │ │ ├── CustomUserDetailsService.java
│ │ │ ├── EmailService.java
│ │ │ ├── JwtTokenCacheService.java
│ │ │ └── SecretManagerService.java
│ │ │ └── utils
│ │ │ ├── IdGenerator.java
│ │ │ ├── JwtTokenUtil.java
│ │ │ └── Prefix.java
│ └── resources
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── auth_service
│ └── AuthServiceApplicationTests.java
├── cargo-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── cargo_service
│ │ │ ├── CargoServiceApplication.java
│ │ │ ├── config
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ └── CargoController.java
│ │ │ ├── dto
│ │ │ ├── CargoRequestDto.java
│ │ │ ├── CargoResponseDto.java
│ │ │ └── CargoUpdateRequestDto.java
│ │ │ ├── enums
│ │ │ └── CargoStatus.java
│ │ │ ├── exception
│ │ │ ├── CargoNotFoundException.java
│ │ │ ├── EmailAlreadyVerifiedException.java
│ │ │ ├── ErrorDetails.java
│ │ │ └── GlobalExceptionHandler.java
│ │ │ ├── external
│ │ │ └── CustomerClientService.java
│ │ │ ├── mapper
│ │ │ └── CargoMapper.java
│ │ │ ├── model
│ │ │ ├── Cargo.java
│ │ │ └── Customer.java
│ │ │ ├── repository
│ │ │ └── CargoRepository.java
│ │ │ └── service
│ │ │ └── CargoService.java
│ └── resources
│ │ ├── application-dev.yml
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── cargo_service
│ ├── CargoServiceApplicationTests.java
│ ├── controller
│ └── CargoControllerTest.java
│ └── service
│ └── CargoServiceTest.java
├── config-server
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── config
│ │ │ └── server
│ │ │ └── ConfigServerApplication.java
│ └── resources
│ │ ├── application.properties
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── config
│ └── server
│ └── ConfigServerApplicationTests.java
├── customer-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── customer_service
│ │ │ ├── CustomerServiceApplication.java
│ │ │ ├── config
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ ├── AddressController.java
│ │ │ └── CustomerController.java
│ │ │ ├── dto
│ │ │ ├── addressDto
│ │ │ │ ├── AddressRequestDto.java
│ │ │ │ └── AddressResponseDto.java
│ │ │ └── customerDto
│ │ │ │ ├── CustomerRequestDto.java
│ │ │ │ ├── CustomerResponseDto.java
│ │ │ │ └── CustomerUpdateRequestDto.java
│ │ │ ├── enums
│ │ │ └── Country.java
│ │ │ ├── exception
│ │ │ ├── ErrorDetails.java
│ │ │ ├── GlobalExceptionHandler.java
│ │ │ ├── InsufficientStockException.java
│ │ │ ├── InventoryNotFoundException.java
│ │ │ ├── OrderNotFoundException.java
│ │ │ ├── ProductNotFoundException.java
│ │ │ └── ResourceCustomerNotFoundException.java
│ │ │ ├── external
│ │ │ └── CargoClientService.java
│ │ │ ├── mapper
│ │ │ ├── AddressMapper.java
│ │ │ └── CustomerMapper.java
│ │ │ ├── model
│ │ │ ├── Address.java
│ │ │ ├── Cargo.java
│ │ │ └── Customer.java
│ │ │ ├── repository
│ │ │ ├── AddressRepository.java
│ │ │ └── CustomerRepository.java
│ │ │ └── service
│ │ │ ├── AddressService.java
│ │ │ ├── CustomerService.java
│ │ │ └── MailService.java
│ └── resources
│ │ ├── application-dev.yml
│ │ ├── application.properties
│ │ ├── application.yml
│ │ └── templates
│ │ └── create-customer.html
│ └── test
│ └── java
│ └── com
│ └── example
│ └── customer_service
│ ├── CustomerServiceApplicationTests.java
│ ├── controller
│ ├── AddressControllerTest.java
│ └── CustomerControllerTest.java
│ └── service
│ ├── AddressServiceTest.java
│ ├── CustomerServiceTest.java
│ └── MailServiceTest.java
├── docker-compose.yml
├── inventory-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── inventory_service
│ │ │ ├── InventoryServiceApplication.java
│ │ │ ├── config
│ │ │ ├── KafkaConsumerConfig.java
│ │ │ └── SwaggerConfig.java
│ │ │ ├── consumer
│ │ │ └── KafkaConsumer.java
│ │ │ ├── controller
│ │ │ └── InventoryController.java
│ │ │ ├── dto
│ │ │ ├── InventoryRequestDto.java
│ │ │ ├── InventoryResponseDto.java
│ │ │ └── InventoryUpdateRequestDto.java
│ │ │ ├── exception
│ │ │ ├── ErrorDetails.java
│ │ │ ├── GlobalExceptionHandler.java
│ │ │ ├── InventoryNotFoundException.java
│ │ │ └── ProductNotFoundException.java
│ │ │ ├── mapper
│ │ │ └── InventoryMapper.java
│ │ │ ├── model
│ │ │ └── Inventory.java
│ │ │ ├── repository
│ │ │ └── InventoryRepository.java
│ │ │ └── service
│ │ │ └── InventoryService.java
│ └── resources
│ │ ├── application-dev.yml
│ │ ├── application.properties
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── inventory_service
│ ├── InventoryServiceApplicationTests.java
│ ├── controller
│ └── InventoryControllerTest.java
│ └── service
│ └── InventoryServiceTest.java
├── logs
└── auth-service.log
├── order-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── spring
│ │ │ └── boot
│ │ │ ├── OrderServiceApplication.java
│ │ │ ├── config
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ └── OrderController.java
│ │ │ ├── dto
│ │ │ ├── cargoDto
│ │ │ │ ├── CargoRequestDto.java
│ │ │ │ ├── CargoResponseDto.java
│ │ │ │ └── CargoUpdateRequestDto.java
│ │ │ ├── inventoryDto
│ │ │ │ └── InventoryUpdateRequestDto.java
│ │ │ ├── orderDto
│ │ │ │ ├── OrderRequestDto.java
│ │ │ │ ├── OrderResponseDto.java
│ │ │ │ └── OrderUpdateRequestDto.java
│ │ │ └── paymentDto
│ │ │ │ └── PaymentUpdateRequestDto.java
│ │ │ ├── enums
│ │ │ ├── CargoStatus.java
│ │ │ ├── Category.java
│ │ │ ├── OrderStatus.java
│ │ │ └── PaymentType.java
│ │ │ ├── exception
│ │ │ ├── ErrorDetails.java
│ │ │ ├── GlobalExceptionHandler.java
│ │ │ ├── InsufficientStockException.java
│ │ │ ├── InventoryNotFoundException.java
│ │ │ ├── OrderNotFoundException.java
│ │ │ └── ProductNotFoundException.java
│ │ │ ├── external
│ │ │ ├── CargoClientService.java
│ │ │ ├── CustomerClientService.java
│ │ │ ├── InventoryClientService.java
│ │ │ ├── PaymentClientService.java
│ │ │ └── ProductClientService.java
│ │ │ ├── mapper
│ │ │ └── OrderMapper.java
│ │ │ ├── model
│ │ │ ├── Address.java
│ │ │ ├── Cargo.java
│ │ │ ├── Customer.java
│ │ │ ├── Inventory.java
│ │ │ ├── Order.java
│ │ │ └── Product.java
│ │ │ ├── repository
│ │ │ └── OrderRepository.java
│ │ │ ├── schedulers
│ │ │ └── OrderScheduler.java
│ │ │ └── service
│ │ │ ├── MailService.java
│ │ │ └── OrderService.java
│ └── resources
│ │ ├── application-dev.yml
│ │ ├── application.properties
│ │ ├── application.yml
│ │ └── templates
│ │ └── create-order.html
│ └── test
│ └── java
│ └── com
│ └── example
│ └── spring
│ └── boot
│ ├── OrderServiceApplicationTests.java
│ ├── controller
│ └── OrderControllerTest.java
│ └── service
│ └── OrderServiceTest.java
├── payment-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── payment_service
│ │ │ ├── PaymentServiceApplication.java
│ │ │ ├── config
│ │ │ ├── KafkaConfig.java
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ └── PaymentController.java
│ │ │ ├── dto
│ │ │ ├── orderDto
│ │ │ │ └── OrderResponseDto.java
│ │ │ └── paymentDto
│ │ │ │ ├── PaymentRequestDto.java
│ │ │ │ ├── PaymentResponseDto.java
│ │ │ │ └── PaymentUpdateRequestDto.java
│ │ │ ├── enums
│ │ │ ├── CargoStatus.java
│ │ │ ├── PaymentStatus.java
│ │ │ └── PaymentType.java
│ │ │ ├── exception
│ │ │ ├── ErrorDetails.java
│ │ │ ├── GlobalExceptionHandler.java
│ │ │ ├── InsufficientStockException.java
│ │ │ ├── OrderNotFoundException.java
│ │ │ ├── PaymentCancellationException.java
│ │ │ ├── PaymentCustomerNotFoundException.java
│ │ │ └── PaymentNotFoundException.java
│ │ │ ├── external
│ │ │ ├── CargoClientService.java
│ │ │ ├── CustomerClientService.java
│ │ │ ├── InventoryServiceClient.java
│ │ │ └── OrderServiceClient.java
│ │ │ ├── mapper
│ │ │ └── PaymentMapper.java
│ │ │ ├── model
│ │ │ ├── Address.java
│ │ │ ├── Cargo.java
│ │ │ ├── Customer.java
│ │ │ ├── Inventory.java
│ │ │ └── Payment.java
│ │ │ ├── publisher
│ │ │ └── PaymentMessageSender.java
│ │ │ ├── repository
│ │ │ └── PaymentRepository.java
│ │ │ ├── service
│ │ │ └── PaymentService.java
│ │ │ └── util
│ │ │ └── PaymentMessage.java
│ └── resources
│ │ ├── application-dev.yml
│ │ ├── application.properties
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── payment_service
│ ├── PaymentServiceApplicationTests.java
│ ├── controller
│ └── PaymentControllerTest.java
│ └── service
│ └── PaymentServiceTest.java
├── product-service
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── product_service
│ │ │ ├── ProductServiceApplication.java
│ │ │ ├── config
│ │ │ └── SwaggerConfig.java
│ │ │ ├── controller
│ │ │ └── ProductController.java
│ │ │ ├── dto
│ │ │ ├── inventoryDto
│ │ │ │ ├── InventoryRequestDto.java
│ │ │ │ ├── InventoryResponseDto.java
│ │ │ │ └── InventoryUpdateRequestDto.java
│ │ │ └── productDto
│ │ │ │ ├── ProductRequestDto.java
│ │ │ │ ├── ProductResponseDto.java
│ │ │ │ └── ProductUpdateRequestDto.java
│ │ │ ├── enums
│ │ │ └── Category.java
│ │ │ ├── exception
│ │ │ ├── ErrorDetails.java
│ │ │ ├── GlobalExceptionHandler.java
│ │ │ ├── InventoryNotFoundException.java
│ │ │ └── ProductNotFoundException.java
│ │ │ ├── external
│ │ │ └── InventoryClientService.java
│ │ │ ├── mapper
│ │ │ └── ProductMapper.java
│ │ │ ├── model
│ │ │ ├── Inventory.java
│ │ │ └── Product.java
│ │ │ ├── repository
│ │ │ └── ProductRepository.java
│ │ │ ├── service
│ │ │ └── ProductService.java
│ │ │ └── util
│ │ │ └── ProductMessage.java
│ └── resources
│ │ ├── application-dev.yml
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── product_service
│ ├── ProductServiceApplicationTests.java
│ ├── controller
│ └── ProductControllerTest.java
│ └── service
│ └── ProductServiceTest.java
├── service-registry
├── .gitignore
├── .mvn
│ └── wrapper
│ │ └── maven-wrapper.properties
├── Dockerfile
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── example
│ │ │ └── service
│ │ │ └── registry
│ │ │ └── ServiceRegistryApplication.java
│ └── resources
│ │ ├── application.properties
│ │ └── application.yml
│ └── test
│ └── java
│ └── com
│ └── example
│ └── service
│ └── registry
│ └── ServiceRegistryApplicationTests.java
└── uploads
└── 69deca89-3ada-49a7-a61d-7ecd70a1ac78.jpg
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/JPASupport-project.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/RestfulApiTool-Environment-Cache.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/aws.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/.idea/fastRequest/fastRequestCollection.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.idea/fastRequest/fastRequestCurrentProjectLocalConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/jpa.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/.idea/spring-boot-microservice.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "java.compile.nullAnalysis.mode": "automatic"
3 | }
4 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | 🚀 KATKI REHBERİ 🚀
2 | Bu projeye katkı sağladığınız için teşekkürler! 🙏
3 | E-ticaret mikroservis uygulamamıza katkıda bulunmak isteyen herkese açık bir çağrı yapıyoruz! Aşağıdaki adımları takip ederek projeye katkı sağlayabilirsiniz. 💻✨
4 |
5 | Katkı Yapma Adımları:
6 | 1.Repo'yu Fork'layın
7 | GitHub reposunu kendi hesabınıza fork'layarak projeyi kopyalayın.
8 | 👉 [GitHub Repo Linki](https://github.com/orhanturkmenoglu/ecommerce-microservices-springboot)
9 |
10 | 2.Yeni Bir Branch Oluşturun
11 |
12 | 🔹git checkout -b ilk-gorev
13 |
14 | 3.Belirlenen Görevi Tamamlayın
15 |
16 | 🔹İlk görevle ilgili açılmış olan issue üzerinde çalışın veya yeni bir issue açarak katkıda bulunun.
17 |
18 | 4.Commit Yapın ve Pushlayın
19 |
20 | 🔹Yaptığınız değişiklikleri commit edin ve ardından fork’ladığınız repoya pushlayın.
21 |
22 | 🔹 git commit -m "Görev tamamlandı: [Görev Açıklaması]"
23 |
24 | 🔹 git push origin ilk-gorev
25 |
26 | 5.Pull Request (PR) Oluşturun
27 |
28 | 🔹GitHub üzerinde fork’ladığınız repo ile ana repoyu birleştirmek için bir Pull Request (PR) oluşturun.
29 |
30 | Katkı Kuralları:
31 |
32 | 🔹Kod Standartlarına Uyma
33 |
34 |
35 | 🔹Projeye katkıda bulunurken mevcut kod stilini takip edin. Temiz, okunabilir ve sürdürülebilir kod yazmaya özen gösterin.
36 |
37 | 🔹PR Açıklamaları
38 |
39 | 🔹PR açıklamalarını detaylı yazın. Yaptığınız değişikliklerin neden yapıldığını ve hangi sorunu çözdüğünü açıklayın.
40 |
41 | 🔹Testler
42 |
43 | 🔹Değişiklik yaptıysanız, ilgili testleri de eklemeyi unutmayın. Testler, tüm proje için kritik önem taşır.
44 |
45 | 🔹Dökümantasyon
46 |
47 | 🔹Yeni bir özellik eklediyseniz veya mevcut özellikte bir değişiklik yaptıysanız, ilgili dökümantasyonu güncellemeyi unutmayın.
48 |
--------------------------------------------------------------------------------
/License:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Orhan Türkmenoğlu
4 |
5 | İzin verilir, bu yazılım ve belgeleri kopyalamak, değiştirmek, birleştirmek, yayımlamak, dağıtmak, alt lisans vermek ve/veya satmak, yazılımın her kopyasına, yukarıdaki telif hakkı bildirimini ve bu izin bildirimini dahil etmek şartıyla yapılabilir.
6 |
7 | YAZILIM, HERHANGİ BİR GARANTİSİZ OLARAK "OLDUĞU GİBİ" SAĞLANMAKTADIR. İŞLETMEYİZ, AÇIKLAMAYI, ÜRETİMİ, YA DA SAĞLAMLIĞI SAĞLAMAK İÇİN HERHANGİ BİR GARANTİ VERMEYİZ. HİÇBİR DURUMDA YAZILIMIN KULLANIMI SONUCUNDA OLUŞAN HİÇBİR ZARAR İÇİN YAZARLAR SORUMLU TUTULAMAZ.
8 |
9 | Aşağıdaki koşullarla, bu yazılımın kullanımına izin verilmektedir:
10 | 1. **Kullanım**: Yazılımı herhangi bir amaçla özgürce kullanabilirsiniz.
11 | 2. **Değişiklik**: Yazılımı değiştirebilir ve geliştirebilirsiniz. Yaptığınız değişikliklerin telif hakkı sahibi tarafından açıklanmış olması gerekmektedir.
12 | 3. **Dağıtım**: Yazılımı dağıtabilir, satabilir veya birleştirebilirsiniz.
13 | 4. **Atıf**: Yazılımı kullanan veya dağıtan kişiler, yazılımdan faydalanan her versiyonda yukarıdaki telif hakkı ve izin bildirimini eklemelidir.
14 |
15 | Bu yazılımın kullanımıyla ilişkili olarak herhangi bir zarar meydana gelirse, yazılımın yazarları sorumlu tutulamaz.
16 |
17 |
--------------------------------------------------------------------------------
/api-gateway/.gitattributes:
--------------------------------------------------------------------------------
1 | /mvnw text eol=lf
2 | *.cmd text eol=crlf
3 |
--------------------------------------------------------------------------------
/api-gateway/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/api-gateway/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
20 |
--------------------------------------------------------------------------------
/api-gateway/src/main/java/com/example/api/gateway/ApiGatewayApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.api.gateway;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 |
7 | @SpringBootApplication
8 | @EnableDiscoveryClient
9 | public class ApiGatewayApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ApiGatewayApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/api-gateway/src/main/java/com/example/api/gateway/RedisConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.api.gateway;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.data.redis.connection.ReactiveRedisConnectionFactory;
6 | import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
7 |
8 | @Configuration
9 | public class RedisConfig {
10 |
11 | @Bean
12 | public ReactiveStringRedisTemplate reactiveStringRedisTemplate(ReactiveRedisConnectionFactory factory) {
13 | return new ReactiveStringRedisTemplate(factory);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/api-gateway/src/main/java/com/example/api/gateway/filter/JwtTokenUtil.java:
--------------------------------------------------------------------------------
1 | package com.example.api.gateway.filter;
2 |
3 |
4 | import io.jsonwebtoken.Claims;
5 | import io.jsonwebtoken.Jwts;
6 | import io.jsonwebtoken.io.Decoders;
7 | import io.jsonwebtoken.security.Keys;
8 | import lombok.RequiredArgsConstructor;
9 | import org.springframework.beans.factory.annotation.Value;
10 | import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
11 | import org.springframework.stereotype.Component;
12 | import reactor.core.publisher.Mono;
13 |
14 | import javax.crypto.SecretKey;
15 |
16 | @Component
17 | @RequiredArgsConstructor
18 | public class JwtTokenUtil {
19 |
20 | @Value("${spring.security.secret.key}")
21 | private String SECRET_KEY;
22 |
23 | private final ReactiveStringRedisTemplate redisTemplate;
24 |
25 |
26 | public SecretKey getSigningKey() {
27 | return Keys.hmacShaKeyFor(Decoders.BASE64.decode(SECRET_KEY));
28 | }
29 |
30 | public Mono validateToken(String token) {
31 | try {
32 | Claims claims = Jwts.parserBuilder()
33 | .setSigningKey(getSigningKey())
34 | .build()
35 | .parseClaimsJws(token)
36 | .getBody();
37 |
38 | String email = claims.getSubject();
39 |
40 | // Redis'te blacklist kontrolü:
41 | return redisTemplate.opsForSet()
42 | .isMember("BLACKLISTED", token)
43 | .flatMap(isBlacklisted -> {
44 | if (Boolean.TRUE.equals(isBlacklisted)) {
45 | System.out.println("Blacklisted token: " + token);
46 | return Mono.just(false); // blacklistteyse geçersiz
47 | }
48 |
49 | return redisTemplate.opsForValue()
50 | .get("access:" + email)
51 | .flatMap(redisToken -> Mono.just(token.equals(redisToken)))
52 | .defaultIfEmpty(false); // Redis'te access token yoksa da false dön
53 | });
54 | } catch (Exception e) {
55 | return Mono.just(false);
56 | }
57 | }
58 |
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/api-gateway/src/main/java/com/example/api/gateway/filter/RouteValidator.java:
--------------------------------------------------------------------------------
1 | package com.example.api.gateway.filter;
2 |
3 | import org.springframework.http.server.reactive.ServerHttpRequest;
4 | import org.springframework.stereotype.Component;
5 |
6 | import java.util.List;
7 | import java.util.function.Predicate;
8 |
9 | @Component
10 | public class RouteValidator {
11 |
12 | // Kimlik doğrulama gerektirmeyen uç noktalar
13 | public static final List openApiEndpoints = List.of(
14 | "/api/v1/auth/login",
15 | "/api/v1/auth/register",
16 | "/api/v1/auth/verify-email",
17 | "/api/v1/auth/resend-verification-code");
18 |
19 | // Güvenli uç noktalar için predikat
20 | public Predicate isSecured = serverHttpRequest ->
21 | openApiEndpoints
22 | .stream()
23 | .noneMatch(uri -> serverHttpRequest.getURI().getPath().contains(uri));
24 |
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/api-gateway/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8080
3 |
4 | spring:
5 | application:
6 | name: API-GATEWAY
7 |
8 | cloud:
9 | gateway:
10 | routes:
11 | - id: PRODUCT-SERVICE
12 | uri: lb://PRODUCT-SERVICE
13 | predicates:
14 | - Path=/api/v1/products/**
15 | filters:
16 | - JwtAuthenticationFilter
17 |
18 | - id: ORDER-SERVICE
19 | uri: lb://ORDER-SERVICE
20 | predicates:
21 | - Path=/api/v1/orders/**
22 | filters:
23 | - JwtAuthenticationFilter
24 |
25 | - id: INVENTORY-SERVICE
26 | uri: lb://INVENTORY-SERVICE
27 | predicates:
28 | - Path=/api/v1/inventories/**
29 | filters:
30 | - JwtAuthenticationFilter
31 |
32 | - id: PAYMENT-SERVICE
33 | uri: lb://PAYMENT-SERVICE
34 | predicates:
35 | - Path=/api/v1/payments/**
36 | filters:
37 | - JwtAuthenticationFilter
38 |
39 | - id: CARGO-SERVICE
40 | uri: lb://CARGO-SERVICE
41 | predicates:
42 | - Path=/api/v1/cargo/**
43 | filters:
44 | - JwtAuthenticationFilter
45 |
46 | - id: CUSTOMER-SERVICE
47 | uri: lb://CUSTOMER-SERVICE
48 | predicates:
49 | - Path=/api/v1/customers/**
50 | filters:
51 | - JwtAuthenticationFilter
52 |
53 | - id: AUTH-SERVICE
54 | uri: lb://AUTH-SERVICE
55 | predicates:
56 | - Path=/api/v1/auth/**
57 | filters:
58 | - JwtAuthenticationFilter
59 |
60 |
61 | data:
62 | redis:
63 | host: localhost
64 | port: 6379
65 |
66 | security:
67 | secret:
68 | key: ${SPRING.SECURITY.SECRET.KEY:default}
69 |
70 | config:
71 | import: optional:configserver:http://localhost:8084
72 |
73 | logging:
74 | level:
75 | org.springframework.cloud.gateway: DEBUG
76 |
77 |
--------------------------------------------------------------------------------
/api-gateway/src/test/java/com/example/api/gateway/ApiGatewayApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.api.gateway;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ApiGatewayApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/auth-service/.gitattributes:
--------------------------------------------------------------------------------
1 | /mvnw text eol=lf
2 | *.cmd text eol=crlf
3 |
--------------------------------------------------------------------------------
/auth-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/auth-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip
20 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/AuthServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 |
7 | @SpringBootApplication
8 | @EnableDiscoveryClient
9 | public class AuthServiceApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(AuthServiceApplication.class, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/config/DataSourceConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.config;
2 |
3 | import com.example.auth_service.service.SecretManagerService;
4 | import com.fasterxml.jackson.core.JsonProcessingException;
5 | import com.fasterxml.jackson.databind.ObjectMapper;
6 | import lombok.RequiredArgsConstructor;
7 | import org.springframework.beans.factory.annotation.Value;
8 | import org.springframework.boot.context.properties.ConfigurationProperties;
9 | import org.springframework.boot.jdbc.DataSourceBuilder;
10 | import org.springframework.context.annotation.Bean;
11 | import org.springframework.context.annotation.Configuration;
12 |
13 | import javax.sql.DataSource;
14 | import java.util.Map;
15 |
16 | @Configuration
17 | @RequiredArgsConstructor
18 | public class DataSourceConfig {
19 |
20 | private final SecretManagerService secretManagerService;
21 |
22 | @Value("${aws.db-config-secret-name}")
23 | private String dbConfigSecretName;
24 |
25 | @Bean
26 | @ConfigurationProperties("spring.datasource")
27 | public DataSource dataSource() throws JsonProcessingException {
28 | String secret = secretManagerService.getSecret(dbConfigSecretName);
29 |
30 |
31 | ObjectMapper objectMapper = new ObjectMapper();
32 | Map dbConfig = objectMapper.readValue(secret, Map.class);
33 |
34 | String host = dbConfig.get("host");
35 | String port = dbConfig.get("port");
36 | String dbname = dbConfig.get("dbname");
37 | String username = dbConfig.get("username");
38 | String password = dbConfig.get("password");
39 |
40 | if (username == null || password == null) {
41 | throw new IllegalArgumentException("Username or password not found in AWS Secret");
42 | }
43 |
44 | String url = String.format("jdbc:mysql://%s:%s/%s", host, port, dbname);
45 |
46 | return DataSourceBuilder.create()
47 | .url(url)
48 | .username(username)
49 | .password(password)
50 | .build();
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/config/RedisConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.config;
2 |
3 | import org.springframework.context.annotation.Bean;
4 | import org.springframework.context.annotation.Configuration;
5 | import org.springframework.data.redis.connection.RedisConnectionFactory;
6 | import org.springframework.data.redis.core.RedisTemplate;
7 | import org.springframework.data.redis.serializer.StringRedisSerializer;
8 |
9 | @Configuration
10 | public class RedisConfig {
11 |
12 | @Bean
13 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
14 | RedisTemplate template = new RedisTemplate<>();
15 | template.setConnectionFactory(redisConnectionFactory);
16 | template.setKeySerializer(new StringRedisSerializer());
17 | template.setValueSerializer(new StringRedisSerializer());
18 | return template;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/config/SecretManagerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.config;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
7 | import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
8 | import software.amazon.awssdk.regions.Region;
9 | import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
10 |
11 | @Configuration
12 | public class SecretManagerConfig {
13 |
14 | @Value("${aws.access-key-id}")
15 | private String aws_access_key_id;
16 |
17 | @Value("${aws.secret-access-key}")
18 | private String aws_access_value;
19 |
20 | @Value("${aws.region}")
21 | private String region;
22 |
23 | @Bean
24 | public SecretsManagerClient secretsManagerClient(){
25 | AwsBasicCredentials awsBasicCredentials = AwsBasicCredentials.create(aws_access_key_id, aws_access_value);
26 |
27 | return SecretsManagerClient.builder()
28 | .credentialsProvider(StaticCredentialsProvider.create(awsBasicCredentials))
29 | .region(Region.of(region))
30 | .build();
31 | }
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.config;
2 |
3 |
4 | import io.swagger.v3.oas.models.OpenAPI;
5 | import io.swagger.v3.oas.models.info.Contact;
6 | import io.swagger.v3.oas.models.info.Info;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class SwaggerConfig {
12 |
13 | @Bean
14 | public OpenAPI customOpenAPI() {
15 | return new OpenAPI()
16 | .info(info()
17 | .contact(contact()));
18 | }
19 |
20 | @Bean
21 | public Info info() {
22 | return new Info()
23 | .title("Microservice API Documentation")
24 | .version("1.0")
25 | .description("API documentation for the microservices.");
26 | }
27 |
28 | @Bean
29 | public Contact contact() {
30 | return new Contact()
31 | .name("Orhan")
32 | .email("orhantrkmn749@mail.com")
33 | .url("https://github.com/orhanturkmenoglu");
34 | }
35 | }
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/controller/AdminController.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.controller;
2 |
3 | import com.example.auth_service.service.SecretManagerService;
4 | import lombok.RequiredArgsConstructor;
5 | import org.springframework.http.ResponseEntity;
6 | import org.springframework.security.access.prepost.PreAuthorize;
7 | import org.springframework.web.bind.annotation.*;
8 |
9 | import java.util.List;
10 |
11 | @RestController
12 | @RequestMapping("/api/v1/admin")
13 | @RequiredArgsConstructor
14 | public class AdminController {
15 |
16 | private final SecretManagerService secretManagerService;
17 |
18 |
19 | @PreAuthorize("hasRole('ADMIN')")
20 | @GetMapping("/secret")
21 | public ResponseEntity getSecret(@RequestParam String secretName) {
22 | return ResponseEntity.ok(secretManagerService.getSecret(secretName));
23 | }
24 |
25 | @PreAuthorize("hasRole('ADMIN')")
26 | @GetMapping
27 | public ResponseEntity> getAllSecrets() {
28 | return ResponseEntity.ok(secretManagerService.getAllSecrets());
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/controller/TokenController.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.controller;
2 |
3 | import com.example.auth_service.model.Token;
4 | import com.example.auth_service.repository.TokenRepository;
5 | import lombok.RequiredArgsConstructor;
6 | import org.springframework.http.ResponseEntity;
7 | import org.springframework.web.bind.annotation.GetMapping;
8 | import org.springframework.web.bind.annotation.RequestMapping;
9 | import org.springframework.web.bind.annotation.RequestParam;
10 | import org.springframework.web.bind.annotation.RestController;
11 |
12 | @RestController
13 | @RequestMapping("/api/v1/tokens")
14 | @RequiredArgsConstructor
15 | public class TokenController {
16 |
17 | private final TokenRepository tokenRepository;
18 |
19 | @GetMapping("/validate")
20 | public ResponseEntity validateToken(@RequestParam String tokenId) {
21 | boolean isValid = tokenRepository.findByAccessToken(tokenId)
22 | .map(Token::isActive)
23 | .orElseThrow(() -> new RuntimeException("Token not found"));
24 | return ResponseEntity.ok(isValid);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/request/UserEmailVerificationRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.request;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.Email;
5 | import jakarta.validation.constraints.NotBlank;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Getter;
8 | import lombok.NoArgsConstructor;
9 | import lombok.Setter;
10 |
11 | @Getter
12 | @Setter
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Schema(description = "DTO for verifying a user's email with a verification code.")
16 | public class UserEmailVerificationRequestDto {
17 |
18 | @Email(message = "Invalid email format.")
19 | @NotBlank(message = "Email cannot be empty.")
20 | @Schema(description = "User's email address.", example = "orhanturkmenoglu@example.com")
21 | private String email;
22 |
23 | @NotBlank(message = "Verification code cannot be empty.")
24 | @Schema(description = "Email verification code sent to the user.", example = "123456")
25 | private String verificationCode;
26 | }
27 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/request/UserLoginRequestDTO.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.request;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.Email;
5 | import jakarta.validation.constraints.NotBlank;
6 | import jakarta.validation.constraints.Size;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Schema(description = "Represents user login information.")
15 | public class UserLoginRequestDTO {
16 |
17 | @Email(message = "Invalid email format.")
18 | @NotBlank(message = "Email cannot be empty.")
19 | @Schema(description = "User's email address.", example = "orhanturkmenoglu@example.com")
20 | private String email;
21 |
22 | @NotBlank(message = "Password cannot be empty.")
23 | @Size(min = 6, message = "Password must be at least 6 characters long.")
24 | @Schema(description = "User's password.", example = "securePassword123", minLength = 6)
25 | private String password;
26 | }
27 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/request/UserRegistrationRequestDTO.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.request;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.Email;
5 | import jakarta.validation.constraints.NotBlank;
6 | import jakarta.validation.constraints.Size;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Schema(description = "Represents user registration information.")
15 | public class UserRegistrationRequestDTO {
16 |
17 | @Email(message = "Invalid email format.")
18 | @NotBlank(message = "Email cannot be empty.")
19 | @Schema(description = "User's email address.", example = "orhanturkmenoglu@example.com")
20 | private String email;
21 |
22 | @NotBlank(message = "Password cannot be empty.")
23 | @Size(min = 6, message = "Password must be at least 6 characters long.")
24 | @Schema(description = "User's password.", example = "securePassword123", minLength = 6)
25 | private String password;
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/request/UserUpdatePasswordRequestDTO.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.request;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.NotBlank;
5 | import lombok.Data;
6 |
7 | @Data
8 | @Schema(description = "Request object for updating user password.")
9 | public class UserUpdatePasswordRequestDTO {
10 |
11 | @NotBlank(message = "Old password cannot be empty.")
12 | @Schema(description = "User's old password.", example = "oldPassword123")
13 | private String oldPassword;
14 |
15 | @NotBlank(message = "New password cannot be empty.")
16 | @Schema(description = "User's new password.", example = "newPassword123")
17 | private String newPassword;
18 |
19 | @NotBlank(message = "Confirm password cannot be empty.")
20 | @Schema(description = "User's confirmed password.", example = "newPassword123")
21 | private String confirmPassword;
22 | }
23 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/response/UserEmailVerificationResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.response;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Getter;
5 | import lombok.NoArgsConstructor;
6 | import lombok.Setter;
7 |
8 | @Getter
9 | @Setter
10 | @AllArgsConstructor
11 | @NoArgsConstructor
12 | public class UserEmailVerificationResponseDto {
13 |
14 | private String message;
15 | }
16 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/response/UserLoginResponseDTO.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.response;
2 |
3 | import com.fasterxml.jackson.annotation.JsonProperty;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | @Data
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | @Schema(description = "Represents the response data for user login including the access and refresh tokens.")
13 | public class UserLoginResponseDTO {
14 |
15 | @JsonProperty("access_token")
16 | @Schema(description = "JWT Access Token that allows the user to authenticate requests.", example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...")
17 | private String accessToken;
18 |
19 | @JsonProperty("refresh_token")
20 | @Schema(description = "JWT Refresh Token used to obtain new access tokens when the old one expires.", example = "dGhpc2lzYXJlZnJlc2h0b2tlbg==")
21 | private String refreshToken;
22 | }
23 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/response/UserRegistrationResponseDTO.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.response;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @NoArgsConstructor
10 | @AllArgsConstructor
11 | @Schema(description = "Represents the response data for user registration.")
12 | public class UserRegistrationResponseDTO {
13 |
14 | @Schema(description = "Message indicating the result of the user registration process.", example = "User registered successfully.")
15 | private String message;
16 | }
17 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/dto/response/UserUpdatePasswordResponseDTO.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.dto.response;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | @Data
9 | @AllArgsConstructor
10 | @NoArgsConstructor
11 | @Schema(description = "Response object for updating user password.")
12 | public class UserUpdatePasswordResponseDTO {
13 |
14 | @Schema(description = "Message indicating the result of the password update process.", example = "Password updated successfully.")
15 | String message;
16 | }
17 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/enums/Role.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.enums;
2 |
3 | public enum Role {
4 | ROLE_USER,
5 | ROLE_ADMIN
6 | }
7 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/AuthenticationException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class AuthenticationException extends RuntimeException{
4 | public AuthenticationException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/EmailAlreadyExistsException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class EmailAlreadyExistsException extends RuntimeException {
4 |
5 | public EmailAlreadyExistsException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/EmailSendException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class EmailSendException extends RuntimeException {
4 |
5 | public EmailSendException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/ErrorDetails.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.Map;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class ErrorDetails {
16 | private LocalDateTime dateTime;
17 | private String message;
18 | private String description;
19 | private int statusCode;
20 | private Map validationErrors;
21 | }
22 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/InvalidRequestException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class InvalidRequestException extends RuntimeException {
4 | public InvalidRequestException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/InvalidVerificationCodeException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class InvalidVerificationCodeException extends RuntimeException{
4 |
5 | public InvalidVerificationCodeException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/UserNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class UserNotFoundException extends RuntimeException {
4 | public UserNotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/VerificationCodeExpiredException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class VerificationCodeExpiredException extends RuntimeException {
4 | public VerificationCodeExpiredException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/VerificationCodeNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class VerificationCodeNotFoundException extends RuntimeException {
4 | public VerificationCodeNotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/exception/VerificationCodeStillValidException.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.exception;
2 |
3 | public class VerificationCodeStillValidException extends RuntimeException {
4 | public VerificationCodeStillValidException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.mapper;
2 |
3 | import com.example.auth_service.dto.request.UserRegistrationRequestDTO;
4 | import com.example.auth_service.enums.Role;
5 | import com.example.auth_service.model.User;
6 |
7 | public class UserMapper {
8 |
9 | public static User mapToUser(UserRegistrationRequestDTO userRegistrationRequestDTO) {
10 | User user = new User();
11 | user.setEmail(userRegistrationRequestDTO.getEmail());
12 | user.setEmailVerified(false);
13 | user.setLoggedOut(false);
14 | user.setPassword(userRegistrationRequestDTO.getPassword());
15 | user.setRole(Role.ROLE_USER);
16 | return user;
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/model/Token.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.model;
2 |
3 | import com.example.auth_service.utils.IdGenerator;
4 | import com.example.auth_service.utils.Prefix;
5 | import jakarta.persistence.*;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Getter;
8 | import lombok.NoArgsConstructor;
9 | import lombok.Setter;
10 |
11 | import java.time.LocalDateTime;
12 |
13 | @Prefix("token")
14 | @Entity
15 | @Table(name = "tokens")
16 | @Getter
17 | @Setter
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | public class Token {
21 |
22 | @Id
23 | private String id;
24 |
25 | @Column(unique = true, length = 1000)
26 | private String accessToken;
27 |
28 | @Column(unique = true, length = 1000)
29 | private String refreshToken;
30 |
31 | private boolean isActive;
32 |
33 | @ManyToOne
34 | @JoinColumn(name = "user_id")
35 | private User user;
36 |
37 | private LocalDateTime createdAt;
38 | private LocalDateTime updatedAt;
39 |
40 | @PrePersist
41 | public void init() {
42 |
43 | if (this.id == null) {
44 | this.id = IdGenerator.generateId(this);
45 | }
46 |
47 | this.createdAt = LocalDateTime.now();
48 | this.updatedAt = LocalDateTime.now();
49 | }
50 |
51 | @PreUpdate
52 | public void update() {
53 | this.updatedAt = LocalDateTime.now();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/model/User.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.model;
2 |
3 | import com.example.auth_service.enums.Role;
4 | import com.example.auth_service.utils.IdGenerator;
5 | import com.example.auth_service.utils.Prefix;
6 | import jakarta.persistence.*;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Getter;
9 | import lombok.NoArgsConstructor;
10 | import lombok.Setter;
11 |
12 | import java.time.LocalDateTime;
13 | import java.util.List;
14 |
15 | @Prefix("usr")
16 | @Entity
17 | @Table(name = "users")
18 | @Getter
19 | @Setter
20 | @NoArgsConstructor
21 | @AllArgsConstructor
22 | public class User {
23 |
24 | @Id
25 | private String id;
26 |
27 | private String email;
28 |
29 | private String password;
30 |
31 | @Enumerated(EnumType.STRING)
32 | private Role role;
33 |
34 | @Column(name = "email_verified")
35 | private boolean emailVerified;
36 |
37 | @Column(name = "is_logged_out")
38 | private boolean isLoggedOut;
39 |
40 | @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER)
41 | private List tokens;
42 |
43 | private LocalDateTime createdAt;
44 |
45 | private LocalDateTime updatedAt;
46 |
47 | @PrePersist
48 | public void init() {
49 |
50 | if (this.id == null) {
51 | this.id = IdGenerator.generateId(this);
52 | }
53 |
54 | this.createdAt = LocalDateTime.now();
55 | this.updatedAt = LocalDateTime.now();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/repository/TokenRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.repository;
2 |
3 | import com.example.auth_service.model.Token;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.data.jpa.repository.Query;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import java.util.List;
9 | import java.util.Optional;
10 |
11 | @Repository
12 | public interface TokenRepository extends JpaRepository {
13 |
14 | @Query(
15 | """
16 | select t from Token t inner join User u on t.user.id = u.id where u.id = :userId
17 | """
18 | )
19 | List findAllTokenByUser(String userId);
20 |
21 | Optional findByAccessToken(String accessToken);
22 |
23 | Optional findByRefreshToken(String refreshToken);
24 | }
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/repository/UserRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.repository;
2 |
3 | import com.example.auth_service.model.User;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.Optional;
8 |
9 | @Repository
10 | public interface UserRepository extends JpaRepository {
11 | Optional findByEmail(String email);
12 |
13 | boolean existsByEmail(String email);
14 | }
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/service/CustomUserDetailsService.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.service;
2 |
3 | import com.example.auth_service.model.User;
4 | import com.example.auth_service.repository.UserRepository;
5 | import lombok.RequiredArgsConstructor;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.security.core.GrantedAuthority;
8 | import org.springframework.security.core.authority.SimpleGrantedAuthority;
9 | import org.springframework.security.core.userdetails.UserDetails;
10 | import org.springframework.security.core.userdetails.UserDetailsService;
11 | import org.springframework.security.core.userdetails.UsernameNotFoundException;
12 | import org.springframework.stereotype.Service;
13 |
14 | import java.util.List;
15 |
16 | @Service
17 | @RequiredArgsConstructor
18 | @Slf4j
19 | public class CustomUserDetailsService implements UserDetailsService {
20 |
21 | private final UserRepository userRepository;
22 |
23 | @Override
24 | public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
25 |
26 | User user = userRepository.findByEmail(username)
27 | .orElseThrow(() -> new UsernameNotFoundException("User not found"));
28 |
29 | log.info("User found: {}", user);
30 |
31 | List authorities = List.of(
32 | new SimpleGrantedAuthority(user.getRole().name())
33 | );
34 |
35 | log.info("User authorities: {}", authorities);
36 |
37 | return new org.springframework.security.core.userdetails.User(
38 | user.getEmail(),
39 | user.getPassword(),
40 | authorities
41 | );
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/service/EmailService.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.service;
2 |
3 | import lombok.RequiredArgsConstructor;
4 | import lombok.extern.slf4j.Slf4j;
5 | import org.springframework.mail.SimpleMailMessage;
6 | import org.springframework.mail.javamail.JavaMailSender;
7 | import org.springframework.stereotype.Service;
8 |
9 | @Service
10 | @RequiredArgsConstructor
11 | @Slf4j
12 | public class EmailService {
13 |
14 | private final JavaMailSender javaMailSender;
15 |
16 | public void sendEmailVerification(String to, String code) {
17 |
18 | SimpleMailMessage message = new SimpleMailMessage();
19 | message.setTo(to);
20 | message.setSubject("Email Verification");
21 | message.setText("Your verification code is " + code);
22 | javaMailSender.send(message);
23 |
24 | log.info("Email sent to {}", to);
25 | log.info("Verification code: {}", code);
26 | log.info("Email sent successfully");
27 | log.info(String.format("Email SimpleMailMessage : %s", message));
28 |
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/utils/IdGenerator.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.utils;
2 |
3 |
4 | import java.util.UUID;
5 |
6 | public class IdGenerator {
7 |
8 | public static String generateId(Object entity) {
9 | Prefix prefixAnnotation = entity.getClass().getAnnotation(Prefix.class);
10 |
11 | if (prefixAnnotation == null) {
12 | throw new IllegalArgumentException("Prefix annotation is missing on the entity class.");
13 | }
14 |
15 | String prefix = prefixAnnotation.value();
16 | return prefix + "-" + UUID.randomUUID();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/auth-service/src/main/java/com/example/auth_service/utils/Prefix.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service.utils;
2 |
3 | import java.lang.annotation.Retention;
4 | import java.lang.annotation.RetentionPolicy;
5 |
6 | @Retention(RetentionPolicy.RUNTIME)
7 | public @interface Prefix {
8 | String value();
9 | }
10 |
--------------------------------------------------------------------------------
/auth-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 9090
3 |
4 | spring:
5 | application:
6 | name: AUTH-SERVICE
7 |
8 | jpa:
9 | hibernate:
10 | ddl-auto: update
11 | show-sql: true
12 | properties:
13 | hibernate:
14 | format_sql: true
15 |
16 | data:
17 | redis:
18 | host: ${SPRING_DATA_REDIS_HOST:default}
19 | port: ${SPRING_DATA_REDIS_PORT:default}
20 |
21 | config:
22 | import: >
23 | optional:configserver:http://localhost:8084,
24 | optional:aws-secretsmanager:spring-security-key,
25 | optional:aws-secretsmanager:microservice-db-config,
26 | optional:aws-secretsmanager:ecommerce-app/mail-config,
27 | optional:aws-secretsmanager:ecommerce-app/redis-config
28 |
29 |
30 | security:
31 | secret:
32 | key: ${SPRING.SECURITY.SECRET.KEY:default-local-secret}
33 | access:
34 | token:
35 | expiration: ${SPRING.SECURITY.ACCESS.TOKEN.EXPIRATION:3600000}
36 | refresh:
37 | token:
38 | expiration: ${SPRING.SECURITY.REFRESH.TOKEN.EXPIRATION:604800000}
39 | verification:
40 | code:
41 | ttl:
42 | minutes: ${SPRING.SECURITY.VERIFICATION.CODE.EXPIRATION:15}
43 |
44 |
45 | mail:
46 | host: ${SPRING.MAIL.HOST:}
47 | port: ${SPRING.MAIL.PORT:}
48 | username: ${SPRING.MAIL.USERNAME:}
49 | password: ${SPRING.MAIL.PASSWORD:}
50 | protocol: ${SPRING.MAIL.PROTOCOL:}
51 | properties:
52 | mail:
53 | smtp:
54 | auth: true
55 | starttls.enable: true
56 |
57 | aws:
58 | access-key-id: ${AWS_SECRET_KEY_ID}
59 | secret-access-key: ${AWS_SECRET_VALUE}
60 | region: ${AWS_REGION}
61 | db-config-secret-name: ${AWS_DB_CONFIG_SECRET_NAME}
62 |
63 | logging:
64 | level:
65 | org:
66 | springframework: DEBUG
67 | file:
68 | name: logs/auth-service.log
69 | charset:
70 | file: UTF-8
71 | pattern:
72 | dateformat: yyyy-MM-dd HH:mm:ss
73 |
74 |
75 |
--------------------------------------------------------------------------------
/auth-service/src/test/java/com/example/auth_service/AuthServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.auth_service;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class AuthServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/cargo-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/cargo-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/cargo-service/Dockerfile:
--------------------------------------------------------------------------------
1 | # 1. Kullanılacak temel imajı belirtir
2 | FROM openjdk:17-jdk
3 |
4 | # 2. Uygulama için bir çalışma dizini oluşturun
5 | WORKDIR /app
6 |
7 | # 3. Derleme zamanı değişken tanımlama
8 | ARG JAR_FILE=target/*.jar
9 |
10 | # 4. JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
11 | COPY ${JAR_FILE} cargo-service-0.0.1-SNAPSHOT.jar
12 |
13 | # 5. Uygulamanın çalıştırılması için gerekli komutu belirtir
14 | ENTRYPOINT ["java", "-jar", "cargo-service-0.0.1-SNAPSHOT.jar"]
15 |
16 | # 6. Bağlantı noktasını açığa çıkarma (Eğer varsayılan olarak 8080'de çalışıyorsa)
17 | EXPOSE 8082
18 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/CargoServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cache.annotation.EnableCaching;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.openfeign.EnableFeignClients;
8 |
9 | @SpringBootApplication
10 | @EnableDiscoveryClient
11 | @EnableFeignClients
12 | @EnableCaching
13 | public class CargoServiceApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(CargoServiceApplication.class, args);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.config;
2 |
3 |
4 | import io.swagger.v3.oas.models.OpenAPI;
5 | import io.swagger.v3.oas.models.info.Contact;
6 | import io.swagger.v3.oas.models.info.Info;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class SwaggerConfig {
12 |
13 | @Bean
14 | public OpenAPI customOpenAPI() {
15 | return new OpenAPI()
16 | .info(info()
17 | .contact(contact()));
18 | }
19 |
20 | @Bean
21 | public Info info() {
22 | return new Info()
23 | .title("Microservice API Documentation")
24 | .version("1.0")
25 | .description("API documentation for the microservices.");
26 | }
27 |
28 | @Bean
29 | public Contact contact() {
30 | return new Contact()
31 | .name("Orhan")
32 | .email("orhantrkmn749@mail.com")
33 | .url("https://github.com/orhanturkmenoglu");
34 | }
35 | }
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/dto/CargoRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.dto;
2 |
3 |
4 | import com.example.cargo_service.enums.CargoStatus;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import jakarta.validation.constraints.NotEmpty;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Builder;
9 | import lombok.Data;
10 | import lombok.NoArgsConstructor;
11 |
12 | import java.io.Serializable;
13 | import java.time.LocalDateTime;
14 |
15 | @Data
16 | @AllArgsConstructor
17 | @NoArgsConstructor
18 | @Builder
19 | @Schema(name = "CargoRequestDto", description = "DTO for creating a new cargo")
20 | public class CargoRequestDto implements Serializable {
21 |
22 | @Schema(description = "ID of the order associated with the cargo", example = "order123")
23 | @NotEmpty(message = "Order ID cannot be empty")
24 | private String orderId;
25 |
26 | @Schema(description = "ID of the customer associated with the cargo", example = "customer123")
27 | @NotEmpty(message = "Customer ID cannot be empty")
28 | private String customerId;
29 |
30 | @Schema(description = "Tracking number of the cargo", example = "TRK123456789")
31 | @NotEmpty(message = "Tracking number cannot be empty")
32 | private String trackingNumber;
33 |
34 | @Schema(description = "Status of the cargo", example = "Shipped")
35 | @NotEmpty(message = "Status cannot be empty")
36 | private CargoStatus status;
37 |
38 | @Schema(description = "Last updated timestamp of the cargo", example = "2024-08-30T10:15:30")
39 | private LocalDateTime lastUpdated;
40 |
41 | }
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/dto/CargoResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.dto;
2 |
3 |
4 | import com.example.cargo_service.enums.CargoStatus;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @AllArgsConstructor
16 | @NoArgsConstructor
17 | @Builder
18 | @Schema(name = "CargoResponseDto", description = "DTO for representing cargo details in the response")
19 | public class CargoResponseDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier for the cargo", example = "cargo123")
22 | private String id;
23 |
24 | @Schema(description = "ID of the order associated with the cargo", example = "order123")
25 | private String orderId;
26 |
27 | @Schema(description = "ID of the customer associated with the cargo", example = "customer123")
28 | private String customerId;
29 |
30 | @Schema(description = "Tracking number of the cargo", example = "TRK123456789")
31 | private String trackingNumber;
32 |
33 | @Schema(description = "Status of the cargo", example = "Delivered")
34 | private CargoStatus status;
35 |
36 | @Schema(description = "Last updated timestamp of the cargo", example = "2024-08-30T10:15:30")
37 | private LocalDateTime lastUpdated;
38 | }
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/dto/CargoUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.dto;
2 |
3 |
4 | import com.example.cargo_service.enums.CargoStatus;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import jakarta.validation.constraints.NotEmpty;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Builder;
9 | import lombok.Data;
10 | import lombok.NoArgsConstructor;
11 |
12 | import java.io.Serializable;
13 | import java.time.LocalDateTime;
14 |
15 | @Data
16 | @AllArgsConstructor
17 | @NoArgsConstructor
18 | @Builder
19 | @Schema(name = "CargoUpdateRequestDto", description = "DTO for updating cargo details")
20 | public class CargoUpdateRequestDto implements Serializable {
21 |
22 | @Schema(description = "Unique identifier for the cargo", example = "cargo123")
23 | private String id;
24 |
25 | @Schema(description = "ID of the order associated with the cargo", example = "order123")
26 | @NotEmpty(message = "Order ID cannot be empty")
27 | private String orderId;
28 |
29 | @Schema(description = "ID of the customer associated with the cargo", example = "customer123")
30 | @NotEmpty(message = "Customer ID cannot be empty")
31 | private String customerId;
32 |
33 | @Schema(description = "Tracking number of the cargo", example = "TRK123456789")
34 | @NotEmpty(message = "Tracking number cannot be empty")
35 | private String trackingNumber;
36 |
37 | @Schema(description = "Status of the cargo", example = "In Transit")
38 | @NotEmpty(message = "Status cannot be empty")
39 | private CargoStatus status;
40 |
41 | @Schema(description = "Last updated timestamp of the cargo", example = "2024-08-30T10:15:30")
42 | private LocalDateTime lastUpdated;
43 | }
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/enums/CargoStatus.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.enums;
2 |
3 | import com.fasterxml.jackson.annotation.JsonValue;
4 |
5 | public enum CargoStatus {
6 | PENDING("PENDING"), // Beklemede
7 | SHIPPED("SHIPPED"), // Gönderildi
8 | IN_TRANSIT("IN_TRANSIT"),// Yolda
9 | DELIVERED("DELIVERED"), // Teslim Edildi
10 | RETURNED("RETURNED"), // İade Edildi
11 | CANCELLED("CANCELLED"); // İptal Edildi
12 |
13 | private final String value;
14 |
15 | CargoStatus(String value) {
16 | this.value = value;
17 | }
18 |
19 | @JsonValue
20 | public String getValue() {
21 | return value;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/exception/CargoNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.exception;
2 |
3 | public class CargoNotFoundException extends RuntimeException {
4 | public CargoNotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/exception/EmailAlreadyVerifiedException.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.exception;
2 |
3 | public class EmailAlreadyVerifiedException extends RuntimeException {
4 |
5 | public EmailAlreadyVerifiedException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/exception/ErrorDetails.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.exception;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.Map;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class ErrorDetails {
16 | private LocalDateTime dateTime;
17 | private String message;
18 | private String description;
19 | private int statusCode;
20 | private Map validationErrors;
21 | }
22 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/external/CustomerClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.external;
2 |
3 | import com.example.cargo_service.model.Customer;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 |
8 | @FeignClient(name = "CUSTOMER-SERVICE")
9 | public interface CustomerClientService {
10 |
11 | @GetMapping("api/v1/customers/{customerId}")
12 | Customer getCustomerById(@PathVariable("customerId") String customerId);
13 | }
14 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/mapper/CargoMapper.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.mapper;
2 |
3 | import com.example.cargo_service.dto.CargoRequestDto;
4 | import com.example.cargo_service.dto.CargoResponseDto;
5 | import com.example.cargo_service.model.Cargo;
6 | import org.springframework.stereotype.Component;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.List;
10 |
11 | @Component
12 | public class CargoMapper {
13 | public Cargo mapToCargo(CargoRequestDto cargoRequestDto) {
14 | return Cargo.builder()
15 | .orderId(cargoRequestDto.getOrderId())
16 | .customerId(cargoRequestDto.getCustomerId())
17 | .status(cargoRequestDto.getStatus())
18 | .lastUpdated(LocalDateTime.now())
19 | .build();
20 | }
21 |
22 |
23 | public CargoResponseDto mapToCargoResponseDto(Cargo cargo) {
24 | return CargoResponseDto.builder()
25 | .id(cargo.getId())
26 | .orderId(cargo.getOrderId())
27 | .customerId(cargo.getCustomerId())
28 | .trackingNumber(cargo.getTrackingNumber())
29 | .status(cargo.getStatus())
30 | .lastUpdated(cargo.getLastUpdated())
31 | .build();
32 | }
33 |
34 | public List mapToCargoResponseDtoList(List cargoList) {
35 | return cargoList.stream()
36 | .map(this::mapToCargoResponseDto)
37 | .toList();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/model/Cargo.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.model;
2 |
3 | import com.example.cargo_service.enums.CargoStatus;
4 | import jakarta.persistence.*;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 | import org.hibernate.annotations.UuidGenerator;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Entity
15 | @Table(name = "cargo")
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | public class Cargo implements Serializable {
21 |
22 | @Id
23 | @GeneratedValue
24 | @UuidGenerator
25 | private String id;
26 |
27 | private String orderId;
28 |
29 | private String customerId;
30 |
31 | private String trackingNumber;
32 |
33 | @Enumerated(EnumType.STRING)
34 | private CargoStatus status;
35 |
36 | private LocalDateTime lastUpdated;
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/model/Customer.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class Customer {
15 | private String id;
16 | private String firstName;
17 | private String lastName;
18 | private String email;
19 | private String phoneNumber;
20 | private LocalDateTime createdDate;
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/cargo-service/src/main/java/com/example/cargo_service/repository/CargoRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service.repository;
2 |
3 | import com.example.cargo_service.model.Cargo;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.Optional;
8 |
9 | @Repository
10 | public interface CargoRepository extends JpaRepository {
11 |
12 | Optional findByOrderId(String orderId);
13 |
14 | Optional findCargoByTrackingNumber(String trackingNumber);
15 | }
--------------------------------------------------------------------------------
/cargo-service/src/test/java/com/example/cargo_service/CargoServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.cargo_service;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class CargoServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/config-server/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/config-server/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/config-server/Dockerfile:
--------------------------------------------------------------------------------
1 | # 1. Kullanılacak temel imajı belirtir
2 | FROM openjdk:17-jdk
3 |
4 | # 2. Uygulama için bir çalışma dizini oluşturun
5 | WORKDIR /app
6 |
7 | # 3. Derleme zamanı değişken tanımlama
8 | ARG JAR_FILE=target/*.jar
9 |
10 | # 4. JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
11 | COPY ${JAR_FILE} config-server-0.0.1-SNAPSHOT.jar
12 |
13 | # 5. Uygulamanın çalıştırılması için gerekli komutu belirtir
14 | ENTRYPOINT ["java", "-jar", "config-server-0.0.1-SNAPSHOT.jar"]
15 |
16 | # 6. Bağlantı noktasını açığa çıkarma (Eğer varsayılan olarak 8080'de çalışıyorsa)
17 | EXPOSE 8084
18 |
--------------------------------------------------------------------------------
/config-server/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 3.3.2
9 |
10 |
11 | com.example
12 | config-server
13 | 0.0.1-SNAPSHOT
14 | config-server
15 | Demo project for Spring Boot
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | 17
31 | 2023.0.3
32 |
33 |
34 |
35 | org.springframework.cloud
36 | spring-cloud-config-server
37 |
38 |
39 | org.springframework.cloud
40 | spring-cloud-starter
41 |
42 |
43 | org.springframework.cloud
44 | spring-cloud-starter-netflix-eureka-client
45 |
46 |
47 |
48 | org.springframework.boot
49 | spring-boot-starter-test
50 | test
51 |
52 |
53 |
54 |
55 |
56 | org.springframework.cloud
57 | spring-cloud-dependencies
58 | ${spring-cloud.version}
59 | pom
60 | import
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | org.springframework.boot
69 | spring-boot-maven-plugin
70 |
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/config-server/src/main/java/com/example/config/server/ConfigServerApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.config.server;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.config.server.EnableConfigServer;
6 |
7 | @SpringBootApplication
8 | @EnableConfigServer
9 | public class ConfigServerApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ConfigServerApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/config-server/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | spring.application.name=config-server
2 |
--------------------------------------------------------------------------------
/config-server/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8888
3 |
4 | spring:
5 | application:
6 | name: CONFIG-SERVER
7 |
8 | # config server configuration
9 | cloud:
10 | config:
11 | server:
12 | git:
13 | uri: https://github.com/orhanturkmenoglu/microservice-tutorial-config
14 | clone-on-start: true
15 |
--------------------------------------------------------------------------------
/config-server/src/test/java/com/example/config/server/ConfigServerApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.config.server;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ConfigServerApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/customer-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/customer-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/customer-service/Dockerfile:
--------------------------------------------------------------------------------
1 | # 1. Kullanılacak temel imajı belirtir
2 | FROM openjdk:17-jdk
3 |
4 | # 2. Uygulama için bir çalışma dizini oluşturun
5 | WORKDIR /app
6 |
7 | # 3. Derleme zamanı değişken tanımlama
8 | ARG JAR_FILE=target/*.jar
9 |
10 | # 4. JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
11 | COPY ${JAR_FILE} customerservice.jar
12 |
13 | # 5. Uygulamanın çalıştırılması için gerekli komutu belirtir
14 | ENTRYPOINT ["java", "-jar", "customerservice.jar"]
15 |
16 | # 6. Bağlantı noktasını açığa çıkarma (Eğer varsayılan olarak 8080'de çalışıyorsa)
17 | EXPOSE 8086
18 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/CustomerServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cache.annotation.EnableCaching;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.openfeign.EnableFeignClients;
8 |
9 | @SpringBootApplication
10 | @EnableDiscoveryClient
11 | @EnableFeignClients
12 | @EnableCaching
13 | public class CustomerServiceApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(CustomerServiceApplication.class, args);
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.config;
2 |
3 |
4 | import io.swagger.v3.oas.models.OpenAPI;
5 | import io.swagger.v3.oas.models.info.Contact;
6 | import io.swagger.v3.oas.models.info.Info;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class SwaggerConfig {
12 |
13 | @Bean
14 | public OpenAPI customOpenAPI() {
15 | return new OpenAPI()
16 | .info(info()
17 | .contact(contact()));
18 | }
19 |
20 | @Bean
21 | public Info info() {
22 | return new Info()
23 | .title("Microservice API Documentation")
24 | .version("1.0")
25 | .description("API documentation for the microservices.");
26 | }
27 |
28 | @Bean
29 | public Contact contact() {
30 | return new Contact()
31 | .name("Orhan")
32 | .email("orhantrkmn749@mail.com")
33 | .url("https://github.com/orhanturkmenoglu");
34 | }
35 | }
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/dto/addressDto/AddressRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.dto.addressDto;
2 |
3 | import com.example.customer_service.enums.Country;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import jakarta.persistence.EnumType;
6 | import jakarta.persistence.Enumerated;
7 | import jakarta.validation.constraints.NotEmpty;
8 | import lombok.AllArgsConstructor;
9 | import lombok.Builder;
10 | import lombok.Data;
11 | import lombok.NoArgsConstructor;
12 |
13 | import java.io.Serializable;
14 | import java.time.LocalDateTime;
15 |
16 |
17 | @Data
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | @Builder
21 | @Schema(description = "Data Transfer Object for creating an address")
22 | public class AddressRequestDto implements Serializable {
23 |
24 |
25 | @Schema(description = "The country of the address", example = "TURKEY")
26 | @Builder.Default
27 | private Country country = Country.TURKEY;
28 |
29 | @Schema(description = "The city of the address", example = "Istanbul")
30 | @NotEmpty(message = "Address city cannot be empty")
31 | private String city;
32 |
33 | @Schema(description = "The district of the address", example = "Kadikoy")
34 | @NotEmpty(message = "Address district cannot be empty")
35 | private String district;
36 |
37 | @Schema(description = "The street of the address", example = "Bagdat Caddesi")
38 | @NotEmpty(message = "Address street cannot be empty")
39 | private String street;
40 |
41 | @Schema(description = "The postal code of the address", example = "34700")
42 | @NotEmpty(message = "Address zipCode cannot be empty")
43 | private String zipCode;
44 |
45 | @Schema(description = "Additional description for the address", example = "Near the big park")
46 | private String description;
47 |
48 | @Schema(description = "The date and time when the address was created", example = "2024-08-30T10:00:00")
49 | private LocalDateTime createdDate;
50 | }
51 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/dto/addressDto/AddressResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.dto.addressDto;
2 |
3 | import com.example.customer_service.enums.Country;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | import java.time.LocalDateTime;
11 |
12 | @Data
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Builder
16 | @Schema(description = "Data Transfer Object for responding with address details")
17 | public class AddressResponseDto {
18 |
19 | @Schema(description = "Unique identifier for the address", example = "12345")
20 | private String id;
21 |
22 | @Schema(description = "The country of the address", example = "TURKEY")
23 | @Builder.Default
24 | private Country country = Country.TURKEY;
25 |
26 | @Schema(description = "The city of the address", example = "Istanbul")
27 | private String city;
28 |
29 | @Schema(description = "The district of the address", example = "Kadikoy")
30 | private String district;
31 |
32 | @Schema(description = "The street of the address", example = "Bagdat Caddesi")
33 | private String street;
34 |
35 | @Schema(description = "The postal code of the address", example = "34700")
36 | private String zipCode;
37 |
38 | @Schema(description = "Additional description for the address", example = "Near the big park")
39 | private String description;
40 |
41 | @Schema(description = "The date and time when the address was created", example = "2024-08-30T10:00:00")
42 | private LocalDateTime createdDate;
43 | }
44 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/dto/customerDto/CustomerRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.dto.customerDto;
2 |
3 | import com.example.customer_service.model.Address;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import jakarta.validation.constraints.NotEmpty;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 | import java.util.List;
14 |
15 | @Data
16 | @NoArgsConstructor
17 | @AllArgsConstructor
18 | @Builder
19 | @Schema(description = "Data Transfer Object for Customer request")
20 | public class CustomerRequestDto implements Serializable {
21 |
22 | @NotEmpty(message = "Customer firstName cannot be empty")
23 | @Schema(description = "The first name of the customer", example = "John")
24 | private String firstName;
25 |
26 | @NotEmpty(message = "Customer lastName cannot be empty")
27 | @Schema(description = "The last name of the customer", example = "Doe")
28 | private String lastName;
29 |
30 | @NotEmpty(message = "Customer email cannot be empty")
31 | @Schema(description = "The email address of the customer", example = "john.doe@example.com")
32 | private String email;
33 |
34 | @NotEmpty(message = "Customer phoneNumber cannot be empty")
35 | @Schema(description = "The phone number of the customer", example = "+1234567890")
36 | private String phoneNumber;
37 |
38 | @Schema(description = "The date and time when the customer was created", example = "2024-08-30T10:00:00")
39 | private LocalDateTime createdDate;
40 |
41 | @NotEmpty(message = "Customer addressList cannot be empty")
42 | @Schema(description = "List of addresses associated with the customer")
43 | private List addressList;
44 | }
45 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/dto/customerDto/CustomerResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.dto.customerDto;
2 |
3 | import com.example.customer_service.model.Address;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | import java.io.Serializable;
11 | import java.time.LocalDateTime;
12 | import java.util.List;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data Transfer Object for Customer response")
19 | public class CustomerResponseDto implements Serializable {
20 |
21 | @Schema(description = "The unique identifier of the customer", example = "12345")
22 | private String id;
23 |
24 | @Schema(description = "The first name of the customer", example = "John")
25 | private String firstName;
26 |
27 | @Schema(description = "The last name of the customer", example = "Doe")
28 | private String lastName;
29 |
30 | @Schema(description = "The email address of the customer", example = "john.doe@example.com")
31 | private String email;
32 |
33 | @Schema(description = "The phone number of the customer", example = "+1234567890")
34 | private String phoneNumber;
35 |
36 | @Schema(description = "The date and time when the customer was created", example = "2024-08-30T10:00:00")
37 | private LocalDateTime createdDate;
38 |
39 | @Schema(description = "List of addresses associated with the customer")
40 | private List addressList;
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/dto/customerDto/CustomerUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.dto.customerDto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.NotEmpty;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | import java.io.Serializable;
11 | import java.time.LocalDateTime;
12 |
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | @Builder
17 | @Schema(description = "Data Transfer Object for updating customer details")
18 | public class CustomerUpdateRequestDto implements Serializable {
19 |
20 | @Schema(description = "The first name of the customer", example = "Jane")
21 | @NotEmpty(message = "Customer firstName cannot be empty")
22 | private String firstName;
23 |
24 | @Schema(description = "The last name of the customer", example = "Smith")
25 | @NotEmpty(message = "Customer lastName cannot be empty")
26 | private String lastName;
27 |
28 | @Schema(description = "The email address of the customer", example = "jane.smith@example.com")
29 | @NotEmpty(message = "Customer email cannot be empty")
30 | private String email;
31 |
32 | @Schema(description = "The phone number of the customer", example = "+0987654321")
33 | @NotEmpty(message = "Customer phoneNumber cannot be empty")
34 | private String phoneNumber;
35 |
36 | @Schema(description = "The date and time when the customer was created", example = "2024-08-30T10:00:00")
37 | private LocalDateTime createdDate;
38 | }
39 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/enums/Country.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.enums;
2 |
3 | public enum Country {
4 | TURKEY,
5 | USA,
6 | CANADA,
7 | UK,
8 | GERMANY,
9 | FRANCE,
10 | ITALY,
11 | SPAIN,
12 | AUSTRALIA,
13 | JAPAN,
14 | CHINA
15 | }
16 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/exception/ErrorDetails.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.exception;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.Map;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class ErrorDetails {
16 | private LocalDateTime dateTime;
17 | private String message;
18 | private String description;
19 | private int statusCode;
20 | private Map validationErrors;
21 | }
22 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/exception/InsufficientStockException.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.exception;
2 |
3 | public class InsufficientStockException extends RuntimeException {
4 | public InsufficientStockException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/exception/InventoryNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.exception;
2 |
3 | public class InventoryNotFoundException extends RuntimeException {
4 |
5 | public InventoryNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/exception/OrderNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.exception;
2 |
3 | public class OrderNotFoundException extends RuntimeException {
4 |
5 | public OrderNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/exception/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.exception;
2 |
3 | public class ProductNotFoundException extends RuntimeException {
4 |
5 | public ProductNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/exception/ResourceCustomerNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.exception;
2 |
3 | public class ResourceCustomerNotFoundException extends RuntimeException {
4 | public ResourceCustomerNotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/external/CargoClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.external;
2 |
3 | import com.example.customer_service.model.Cargo;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 |
8 | @FeignClient("CARGO-SERVICE")
9 | public interface CargoClientService {
10 |
11 | @GetMapping("api/v1/cargo/trackingNumber/{trackingNumber}")
12 | Cargo getCargoByTrackingNumber(@PathVariable("trackingNumber") String trackingNumber);
13 | }
14 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/mapper/CustomerMapper.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.mapper;
2 |
3 | import com.example.customer_service.dto.customerDto.CustomerRequestDto;
4 | import com.example.customer_service.dto.customerDto.CustomerResponseDto;
5 | import com.example.customer_service.model.Customer;
6 | import org.springframework.stereotype.Component;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.List;
10 | import java.util.stream.Collectors;
11 |
12 | @Component
13 | public class CustomerMapper {
14 |
15 | public Customer mapToCustomer(CustomerRequestDto customerRequestDto){
16 | return Customer.builder()
17 | .firstName(customerRequestDto.getFirstName())
18 | .lastName(customerRequestDto.getLastName())
19 | .email(customerRequestDto.getEmail())
20 | .phoneNumber(customerRequestDto.getPhoneNumber())
21 | .createdDate(LocalDateTime.now())
22 | .addressList(customerRequestDto.getAddressList())
23 | .build();
24 | }
25 |
26 | public CustomerResponseDto mapToCustomerResponseDto(Customer customer){
27 | return CustomerResponseDto.builder()
28 | .id(customer.getId())
29 | .firstName(customer.getFirstName())
30 | .lastName(customer.getLastName())
31 | .email(customer.getEmail())
32 | .phoneNumber(customer.getPhoneNumber())
33 | .createdDate(customer.getCreatedDate())
34 | .addressList(customer.getAddressList())
35 | .build();
36 | }
37 |
38 | public List mapToCustomerResponseDtoList(List customerList){
39 | return customerList.stream()
40 | .map(this::mapToCustomerResponseDto)
41 | .collect(Collectors.toList());
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/model/Address.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.model;
2 |
3 | import com.example.customer_service.enums.Country;
4 | import jakarta.persistence.*;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 | import org.hibernate.annotations.UuidGenerator;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Entity
15 | @Table(name = "address")
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | public class Address implements Serializable {
21 |
22 | @Id
23 | @GeneratedValue
24 | @UuidGenerator
25 | private String id;
26 |
27 | @Enumerated(EnumType.STRING)
28 | @Builder.Default
29 | private Country country = Country.TURKEY;
30 | private String city;
31 | private String district;
32 | private String street;
33 | private String zipCode;
34 | private String description;
35 | private LocalDateTime createdDate;
36 | }
37 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/model/Cargo.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.model;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.GeneratedValue;
5 | import jakarta.persistence.Id;
6 | import jakarta.persistence.Table;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Builder;
9 | import lombok.Data;
10 | import lombok.NoArgsConstructor;
11 | import org.hibernate.annotations.UuidGenerator;
12 |
13 | import java.io.Serializable;
14 | import java.time.LocalDateTime;
15 |
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | public class Cargo implements Serializable {
21 | private String id;
22 |
23 | private String orderId;
24 |
25 | private String customerId;
26 |
27 | private String trackingNumber;
28 |
29 | private String status;
30 |
31 | private LocalDateTime lastUpdated;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/model/Customer.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.model;
2 |
3 | import jakarta.persistence.*;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 | import org.hibernate.annotations.UuidGenerator;
9 |
10 | import java.io.Serializable;
11 | import java.time.LocalDateTime;
12 | import java.util.List;
13 |
14 | @Entity
15 | @Table(name = "customers")
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | public class Customer implements Serializable {
21 |
22 | @Id
23 | @GeneratedValue
24 | @UuidGenerator
25 | private String id;
26 | private String firstName;
27 | private String lastName;
28 | private String email;
29 | private String phoneNumber;
30 | private LocalDateTime createdDate;
31 |
32 | @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
33 | @JoinColumn(name = "customer_id")
34 | private List addressList;
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/repository/AddressRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.repository;
2 |
3 | import com.example.customer_service.model.Address;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | @Repository
8 | public interface AddressRepository extends JpaRepository {
9 | }
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/repository/CustomerRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.repository;
2 |
3 | import com.example.customer_service.model.Customer;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 |
8 | @Repository
9 | public interface CustomerRepository extends JpaRepository {
10 | }
--------------------------------------------------------------------------------
/customer-service/src/main/java/com/example/customer_service/service/MailService.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.service;
2 |
3 | import jakarta.mail.MessagingException;
4 | import jakarta.mail.internet.MimeMessage;
5 | import lombok.RequiredArgsConstructor;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.mail.SimpleMailMessage;
8 | import org.springframework.mail.javamail.JavaMailSender;
9 | import org.springframework.mail.javamail.MimeMessageHelper;
10 | import org.springframework.stereotype.Service;
11 | import org.thymeleaf.TemplateEngine;
12 | import org.thymeleaf.context.Context;
13 |
14 | @Service
15 | @RequiredArgsConstructor
16 | @Slf4j
17 | public class MailService {
18 |
19 | private final JavaMailSender javaMailSender;
20 | private final TemplateEngine templateEngine; // Thymeleaf template engine
21 |
22 |
23 | // HTML içerikli e-posta gönderim metodu
24 | public void sendHtmlEmail(String to, String subject, String customerName, String customerId, String customerEmail) throws Exception {
25 | try {
26 | MimeMessage message = javaMailSender.createMimeMessage();
27 | MimeMessageHelper helper = new MimeMessageHelper(message, true); // true = multipart
28 |
29 | // Thymeleaf ile HTML şablonunu render et
30 | Context context = new Context();
31 | context.setVariable("customerName", customerName);
32 | context.setVariable("customerId", customerId);
33 | context.setVariable("customerEmail", customerEmail);
34 |
35 | String htmlContent = templateEngine.process("create-customer", context);
36 |
37 | helper.setTo(to);
38 | helper.setSubject(subject);
39 | helper.setText(htmlContent, true); // true = HTML içeriği olarak gönder
40 |
41 | javaMailSender.send(message);
42 | log.info("MailService::sendHtmlEmail message sent to: {}", to);
43 | } catch (MessagingException messagingException) {
44 | throw new Exception("MessagingException : " + messagingException.getMessage());
45 | } catch (Exception exception) {
46 | throw new Exception("Exception : " + exception.getMessage());
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/customer-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orhanturkmenoglu/ecommerce-microservices-springboot/6b9128ff359b6599573b79defdd2f869f796fc0e/customer-service/src/main/resources/application.properties
--------------------------------------------------------------------------------
/customer-service/src/test/java/com/example/customer_service/CustomerServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class CustomerServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/customer-service/src/test/java/com/example/customer_service/service/MailServiceTest.java:
--------------------------------------------------------------------------------
1 | package com.example.customer_service.service;
2 |
3 | import jakarta.mail.internet.MimeMessage;
4 | import org.junit.jupiter.api.BeforeEach;
5 | import org.junit.jupiter.api.Test;
6 | import org.junit.jupiter.api.extension.ExtendWith;
7 | import org.mockito.InjectMocks;
8 | import org.mockito.Mock;
9 | import org.mockito.junit.jupiter.MockitoExtension;
10 | import org.springframework.mail.javamail.JavaMailSender;
11 | import org.thymeleaf.TemplateEngine;
12 | import org.thymeleaf.context.Context;
13 |
14 | import static org.mockito.ArgumentMatchers.any;
15 | import static org.mockito.Mockito.*;
16 |
17 | @ExtendWith(MockitoExtension.class)
18 | class MailServiceTest {
19 |
20 | @Mock
21 | private JavaMailSender javaMailSender;
22 |
23 | @Mock
24 | private TemplateEngine templateEngine;
25 |
26 | @InjectMocks
27 | private MailService mailService;
28 |
29 | private MimeMessage mimeMessage;
30 |
31 | @BeforeEach
32 | void setUp() {
33 | mimeMessage = mock(MimeMessage.class);
34 | when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage);
35 | }
36 |
37 | @Test
38 | void sendHtmlEmail_ShouldSendEmail_WhenValidRequest() throws Exception {
39 | // Arrange
40 | String to = "test@example.com";
41 | String subject = "Test Subject";
42 | String customerName = "John Doe";
43 | String customerId = "12345";
44 | String customerEmail = "johndoe@example.com";
45 |
46 | // Thymeleaf şablonunun döndüreceği HTML içeriği
47 | String fakeHtmlContent = "Welcome, John Doe!
";
48 | when(templateEngine.process(eq("create-customer"), any(Context.class))).thenReturn(fakeHtmlContent);
49 |
50 | // Act
51 | mailService.sendHtmlEmail(to, subject, customerName, customerId, customerEmail);
52 |
53 | // Assert
54 | verify(javaMailSender, times(1)).send(any(MimeMessage.class));
55 | verify(templateEngine, times(1)).process(eq("create-customer"), any(Context.class));
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/inventory-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/inventory-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/inventory-service/Dockerfile:
--------------------------------------------------------------------------------
1 | # 1. Kullanılacak temel imajı belirtir
2 | FROM openjdk:17-jdk
3 |
4 | # 2. Uygulama için bir çalışma dizini oluşturun
5 | WORKDIR /app
6 |
7 | # 3. Derleme zamanı değişken tanımlama
8 | ARG JAR_FILE=target/*.jar
9 |
10 | # 4. JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
11 | COPY ${JAR_FILE} inventory-service-0.0.1-SNAPSHOT.jar
12 |
13 | # 5. Uygulamanın çalıştırılması için gerekli komutu belirtir
14 | ENTRYPOINT ["java", "-jar", "inventory-service-0.0.1-SNAPSHOT.jar"]
15 |
16 | # 6. Bağlantı noktasını açığa çıkarma (Eğer varsayılan olarak 8080'de çalışıyorsa)
17 | EXPOSE 8082
18 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/InventoryServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cache.annotation.EnableCaching;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 |
8 | @SpringBootApplication
9 | @EnableDiscoveryClient
10 | @EnableCaching
11 | public class InventoryServiceApplication {
12 |
13 | public static void main(String[] args) {
14 | SpringApplication.run(InventoryServiceApplication.class, args);
15 |
16 |
17 | // INVENTORY MİCROSERSERVİCE SORUMLULUKLARI :
18 |
19 | /*
20 | ENVANTER BİLGİLERİNİ YÖNETİR.
21 | ÜRÜNLERİN STOK DURUMUNU SAĞLAR.
22 | ÜRÜNLERİN STOKLARINI DOĞRULAR VE GÜNCELLER (PRODUCT MS VE ORDER MS İLE İLETİŞİM.)
23 | */
24 |
25 | /*
26 | API'ler:
27 | GET /inventory: Tüm stokları listeleme.
28 | GET /inventory/{productId}: Belirli bir ürünün stok durumunu getirme.
29 | POST /inventory: Yeni stok ekleme.
30 | PUT /inventory/{productId}: Stok güncelleme.
31 | DELETE /inventory/{productId}: Stok silme.
32 | */
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.config;
2 |
3 |
4 | import io.swagger.v3.oas.models.OpenAPI;
5 | import io.swagger.v3.oas.models.info.Contact;
6 | import io.swagger.v3.oas.models.info.Info;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class SwaggerConfig {
12 |
13 | @Bean
14 | public OpenAPI customOpenAPI() {
15 | return new OpenAPI()
16 | .info(info()
17 | .contact(contact()));
18 | }
19 |
20 | @Bean
21 | public Info info() {
22 | return new Info()
23 | .title("Microservice API Documentation")
24 | .version("1.0")
25 | .description("API documentation for the microservices.");
26 | }
27 |
28 | @Bean
29 | public Contact contact() {
30 | return new Contact()
31 | .name("Orhan")
32 | .email("orhantrkmn749@mail.com")
33 | .url("https://github.com/orhanturkmenoglu");
34 | }
35 | }
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/consumer/KafkaConsumer.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.consumer;
2 |
3 | import com.example.inventory_service.model.Inventory;
4 | import com.example.inventory_service.service.InventoryService;
5 | import com.example.inventory_service.dto.InventoryUpdateRequestDto;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.kafka.annotation.KafkaListener;
9 | import org.springframework.messaging.handler.annotation.Payload;
10 | import org.springframework.stereotype.Component;
11 |
12 | @Slf4j
13 | @RequiredArgsConstructor
14 | @Component
15 | public class KafkaConsumer {
16 |
17 | private final InventoryService inventoryService;
18 |
19 | @KafkaListener(topics = "inventory",
20 | groupId = "groupId")
21 | public void consumeProduct(@Payload Inventory inventory) {
22 | log.info("Consuming inventory update message: {}", inventory.toString());
23 |
24 | // Stok güncellemesi yap
25 | inventoryService.updateInventory(inventory.getId(),
26 | InventoryUpdateRequestDto.builder()
27 | .productId(inventory.getProductId())
28 | .newQuantity(inventory.getStockQuantity())
29 | .build());
30 |
31 | log.info("Inventory updated successfully for ID: {}", inventory.getId());
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/dto/InventoryRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.dto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.NotEmpty;
5 | import jakarta.validation.constraints.NotNull;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for creating or updating inventory information")
19 | public class InventoryRequestDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier for the inventory", example = "inv123")
22 | private String id;
23 |
24 | @Schema(description = "Unique identifier for the product associated with the inventory", example = "prod456")
25 | @NotEmpty(message = "Inventory productId cannot be empty")
26 | private String productId;
27 |
28 | @Schema(description = "Quantity of stock available in the inventory", example = "10")
29 | @NotNull(message = "Inventory stock quantity cannot be null")
30 | private int stockQuantity;
31 | }
32 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/dto/InventoryResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.dto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | import java.io.Serializable;
10 | import java.time.LocalDateTime;
11 |
12 | @Data
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Builder
16 | @Schema(description = "Data transfer object representing the details of an inventory item")
17 | public class InventoryResponseDto implements Serializable {
18 |
19 | @Schema(description = "Unique identifier for the inventory", example = "inv123")
20 | private String id;
21 |
22 | @Schema(description = "Unique identifier for the product associated with the inventory", example = "prod456")
23 | private String productId;
24 |
25 | @Schema(description = "Quantity of stock available in the inventory", example = "100")
26 | private int stockQuantity;
27 |
28 | @Schema(description = "Timestamp of the last update to the inventory record", example = "2024-08-30T12:00:00")
29 | private LocalDateTime lastUpdated;
30 | }
31 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/dto/InventoryUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.dto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.NotEmpty;
5 | import jakarta.validation.constraints.NotNull;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for updating inventory information")
19 | public class InventoryUpdateRequestDto implements Serializable {
20 | @Schema(description = "Unique identifier for the inventory item", example = "inv123")
21 | @NotEmpty(message = "Inventory id cannot be empty")
22 | private String inventoryId;
23 |
24 | @Schema(description = "Unique identifier for the product associated with the inventory", example = "prod456")
25 | @NotEmpty(message = "Inventory product Id cannot be empty")
26 | private String productId;
27 |
28 | @Schema(description = "New quantity of stock available in the inventory", example = "20")
29 | @NotNull(message = "Inventory new quantity cannot be null")
30 | private int newQuantity;
31 |
32 | @Schema(description = "Timestamp of the last update to the inventory record", example = "2024-08-30T12:00:00")
33 | private LocalDateTime lastUpdated;
34 | }
35 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/exception/ErrorDetails.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.exception;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.Map;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class ErrorDetails {
16 | private LocalDateTime dateTime;
17 | private String message;
18 | private String description;
19 | private int statusCode;
20 | private Map validationErrors;
21 | }
22 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/exception/InventoryNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.exception;
2 |
3 | public class InventoryNotFoundException extends RuntimeException {
4 |
5 | public InventoryNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/exception/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.exception;
2 |
3 | public class ProductNotFoundException extends RuntimeException {
4 |
5 | public ProductNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/model/Inventory.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.model;
2 |
3 | import jakarta.persistence.Entity;
4 | import jakarta.persistence.GeneratedValue;
5 | import jakarta.persistence.Id;
6 | import jakarta.persistence.Table;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Builder;
9 | import lombok.Data;
10 | import lombok.NoArgsConstructor;
11 | import org.hibernate.annotations.UuidGenerator;
12 |
13 | import java.io.Serializable;
14 | import java.time.LocalDateTime;
15 |
16 | @Entity
17 | @Table(name = "inventories")
18 | @Data
19 | @NoArgsConstructor
20 | @AllArgsConstructor
21 | @Builder
22 | public class Inventory implements Serializable {
23 |
24 | @Id
25 | @GeneratedValue
26 | @UuidGenerator
27 | private String id;
28 |
29 | private String productId;
30 | private int stockQuantity;
31 | private LocalDateTime lastUpdated;
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/inventory-service/src/main/java/com/example/inventory_service/repository/InventoryRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service.repository;
2 |
3 | import com.example.inventory_service.model.Inventory;
4 | import org.springframework.data.jpa.repository.JpaRepository;
5 | import org.springframework.stereotype.Repository;
6 |
7 | import java.util.Optional;
8 |
9 | @Repository
10 | public interface InventoryRepository extends JpaRepository {
11 | Optional findByProductId(String productId);
12 |
13 | Optional findById(String id);
14 | }
15 |
--------------------------------------------------------------------------------
/inventory-service/src/main/resources/application-dev.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8083
3 |
4 | spring:
5 | application:
6 | name: INVENTORY-SERVICE
7 |
8 | profiles:
9 | active: prod
10 |
11 | datasource:
12 | url: jdbc:mysql://localhost:3306/microservice
13 | username: root
14 | password: 12345
15 | jpa:
16 | hibernate:
17 | ddl-auto: create-drop
18 | show-sql: true
19 | properties:
20 | hibernate:
21 | format_sql: true
22 | #redis config
23 | data:
24 | redis:
25 | host: localhost
26 | port: 6379
27 | cache:
28 | type: redis
29 |
30 | config:
31 | import: optional:configserver:http://localhost:8084
32 |
33 |
34 | management:
35 | #Bu ayar, Actuator tarafından sunulan HTTP endpoint'lerini (veya yönlendiricilerini) hangi durumda açacağını belirtir. Özellikle web altındaki exposure bölümü, bu endpoint'lerin hangi koşullarda dış dünyaya (HTTP istemcilerine) açılacağını tanımlar.
36 | endpoints:
37 | web:
38 | exposure:
39 | include: health # Yani, /actuator/health endpoint'i HTTP isteklerine cevap verecektir.
40 | #Bu ayar, uygulamanızın sağlık (health) endpoint'inin sağladığı raporlarda detaylı bilgilerin gösterilip gösterilmeyeceğini belirtir. Özellikle health altındaki show-details parametresi, bu endpoint'in ne kadar ayrıntılı bilgi sunacağını kontrol eder.
41 | endpoint:
42 | health:
43 | show-details: always # : Sağlık endpoint'inin sağladığı raporlarda detaylı bilgilerin gösterilip gösterilmeyeceğini belirtir.
44 | tracing: #zipkin Tracing (İzleme) Yapılandırması
45 | sampling:
46 | probability: 1.0 #tüm isteklerin izleneceği anlamına gelir
47 |
48 | #eureka:
49 | # instance:
50 | # prefer-ip-address: true
51 | #
52 | # client:
53 | # register-with-eureka: true
54 | # fetch-registry: true
55 | # service-url:
56 | # defaultZone: http://localhost:8761/eureka
57 |
--------------------------------------------------------------------------------
/inventory-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/inventory-service/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8083
3 |
4 | spring:
5 | application:
6 | name: INVENTORY-SERVICE
7 |
8 | profiles:
9 | active: prod
10 |
11 | datasource:
12 | url: jdbc:mysql://localhost:3306/microservice
13 | username: root
14 | password: 12345
15 | jpa:
16 | hibernate:
17 | ddl-auto: create-drop
18 | show-sql: true
19 | properties:
20 | hibernate:
21 | format_sql: true
22 | #redis config
23 | data:
24 | redis:
25 | host: localhost
26 | port: 6379
27 | cache:
28 | type: redis
29 |
30 | kafka:
31 | bootstrap-servers: localhost:9092
32 |
33 |
34 | config:
35 | import: optional:configserver:http://localhost:8084
36 |
37 | management:
38 | #Bu ayar, Actuator tarafından sunulan HTTP endpoint'lerini (veya yönlendiricilerini) hangi durumda açacağını belirtir. Özellikle web altındaki exposure bölümü, bu endpoint'lerin hangi koşullarda dış dünyaya (HTTP istemcilerine) açılacağını tanımlar.
39 | endpoints:
40 | web:
41 | exposure:
42 | include: health # Yani, /actuator/health endpoint'i HTTP isteklerine cevap verecektir.
43 | #Bu ayar, uygulamanızın sağlık (health) endpoint'inin sağladığı raporlarda detaylı bilgilerin gösterilip gösterilmeyeceğini belirtir. Özellikle health altındaki show-details parametresi, bu endpoint'in ne kadar ayrıntılı bilgi sunacağını kontrol eder.
44 | endpoint:
45 | health:
46 | show-details: always # : Sağlık endpoint'inin sağladığı raporlarda detaylı bilgilerin gösterilip gösterilmeyeceğini belirtir.
47 | tracing: #zipkin Tracing (İzleme) Yapılandırması
48 | sampling:
49 | probability: 1.0 #tüm isteklerin izleneceği anlamına gelir
50 |
51 | #eureka:
52 | # instance:
53 | # prefer-ip-address: true
54 | #
55 | # client:
56 | # register-with-eureka: true
57 | # fetch-registry: true
58 | # service-url:
59 | # defaultZone: http://localhost:8761/eureka
60 |
--------------------------------------------------------------------------------
/inventory-service/src/test/java/com/example/inventory_service/InventoryServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.inventory_service;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class InventoryServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/order-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/order-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/order-service/Dockerfile:
--------------------------------------------------------------------------------
1 | # 1. Kullanılacak temel imajı belirtir
2 | FROM openjdk:17-jdk
3 |
4 | # 2. Uygulama için bir çalışma dizini oluşturun
5 | WORKDIR /app
6 |
7 | # 3. Derleme zamanı değişken tanımlama
8 | ARG JAR_FILE=target/*.jar
9 |
10 | # 4. JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
11 | COPY ${JAR_FILE} orderservice.jar
12 |
13 | # 5. Uygulamanın çalıştırılması için gerekli komutu belirtir
14 | ENTRYPOINT ["java", "-jar", "orderservice.jar"]
15 |
16 | # 6. Bağlantı noktasını açığa çıkarma (Eğer varsayılan olarak 8080'de çalışıyorsa)
17 | EXPOSE 8081
18 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/OrderServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cache.annotation.EnableCaching;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.openfeign.EnableFeignClients;
8 | import org.springframework.scheduling.annotation.EnableScheduling;
9 |
10 | @SpringBootApplication
11 | @EnableDiscoveryClient
12 | @EnableFeignClients
13 | @EnableCaching
14 | @EnableScheduling
15 | public class OrderServiceApplication {
16 |
17 | public static void main(String[] args) {
18 | SpringApplication.run(OrderServiceApplication.class, args);
19 |
20 |
21 | /*
22 | Sipariş Listeleme: Tüm siparişleri getirir.
23 | Sipariş Getirme: Belirli bir siparişi ID'ye göre getirir.
24 | Sipariş Oluşturma: Yeni bir sipariş oluşturur.
25 | Sipariş Güncelleme: Mevcut siparişi günceller.
26 | Sipariş Silme: Belirli bir siparişi siler.
27 | */
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.config;
2 |
3 |
4 | import io.swagger.v3.oas.models.OpenAPI;
5 | import io.swagger.v3.oas.models.info.Contact;
6 | import io.swagger.v3.oas.models.info.Info;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class SwaggerConfig {
12 |
13 | @Bean
14 | public OpenAPI customOpenAPI() {
15 | return new OpenAPI()
16 | .info(info()
17 | .contact(contact()));
18 | }
19 |
20 | @Bean
21 | public Info info() {
22 | return new Info()
23 | .title("Microservice API Documentation")
24 | .version("1.0")
25 | .description("API documentation for the microservices.");
26 | }
27 |
28 | @Bean
29 | public Contact contact() {
30 | return new Contact()
31 | .name("Orhan")
32 | .email("orhantrkmn749@mail.com")
33 | .url("https://github.com/orhanturkmenoglu");
34 | }
35 | }
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/cargoDto/CargoRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.cargoDto;
2 |
3 |
4 | import com.example.spring.boot.enums.CargoStatus;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @AllArgsConstructor
16 | @NoArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for cargo request")
19 | public class CargoRequestDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier for the order associated with the cargo", example = "order789")
22 | private String orderId;
23 |
24 | @Schema(description = "Unique identifier for the customer associated with the cargo", example = "cust123")
25 | private String customerId;
26 |
27 | @Schema(description = "Tracking number for the cargo", example = "TRACK123456789")
28 | private String trackingNumber;
29 |
30 | @Schema(description = "Current status of the cargo", example = "Shipped")
31 | private CargoStatus status;
32 |
33 | @Schema(description = "Last update timestamp for the cargo status", example = "2024-08-30T14:00:00")
34 | private LocalDateTime lastUpdated;
35 | }
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/cargoDto/CargoResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.cargoDto;
2 |
3 |
4 | import com.example.spring.boot.enums.CargoStatus;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @AllArgsConstructor
16 | @NoArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for cargo response")
19 | public class CargoResponseDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier for the cargo", example = "cargo123")
22 | private String id;
23 |
24 | @Schema(description = "Unique identifier for the order associated with the cargo", example = "order789")
25 | private String orderId;
26 |
27 | @Schema(description = "Unique identifier for the customer associated with the cargo", example = "cust123")
28 | private String customerId;
29 |
30 | @Schema(description = "Tracking number for the cargo", example = "123456789")
31 | private String trackingNumber;
32 |
33 | @Schema(description = "Current status of the cargo", example = "Shipped")
34 | private CargoStatus status;
35 |
36 | @Schema(description = "Last update timestamp for the cargo status", example = "2024-08-30T14:00:00")
37 | private LocalDateTime lastUpdated;
38 | }
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/cargoDto/CargoUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.cargoDto;
2 |
3 |
4 | import com.example.spring.boot.enums.CargoStatus;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @AllArgsConstructor
16 | @NoArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for cargo update request")
19 | public class CargoUpdateRequestDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier for the cargo", example = "cargo123")
22 | private String id;
23 |
24 | @Schema(description = "Unique identifier for the order associated with the cargo", example = "order789")
25 | private String orderId;
26 |
27 | @Schema(description = "Unique identifier for the customer associated with the cargo", example = "cust123")
28 | private String customerId;
29 |
30 | @Schema(description = "Tracking number for the cargo", example = "TRACK123456789")
31 | private String trackingNumber;
32 |
33 | @Schema(description = "Current status of the cargo", example = "In Transit")
34 | private CargoStatus status;
35 |
36 | @Schema(description = "Last update timestamp for the cargo status", example = "2024-08-30T14:00:00")
37 | private LocalDateTime lastUpdated;
38 | }
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/inventoryDto/InventoryUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.inventoryDto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.NotEmpty;
5 | import jakarta.validation.constraints.NotNull;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for inventory update request")
19 | public class InventoryUpdateRequestDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier for the inventory", example = "inventory123")
22 | @NotEmpty(message = "Inventory id cannot be empty")
23 | private String inventoryId;
24 |
25 | @Schema(description = "New quantity for the inventory", example = "100")
26 | @NotNull(message = "Inventory new quantity cannot be null")
27 | private int newQuantity;
28 |
29 | @Schema(description = "Last update timestamp for the inventory", example = "2024-08-30T14:00:00")
30 | private LocalDateTime lastUpdated;
31 | }
32 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/orderDto/OrderRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.orderDto;
2 |
3 | import com.example.spring.boot.model.Address;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import jakarta.validation.constraints.Min;
6 | import jakarta.validation.constraints.NotEmpty;
7 | import jakarta.validation.constraints.NotNull;
8 | import lombok.AllArgsConstructor;
9 | import lombok.Builder;
10 | import lombok.Data;
11 | import lombok.NoArgsConstructor;
12 |
13 | import java.io.Serializable;
14 | import java.time.LocalDateTime;
15 |
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | @Schema(description = "Data transfer object for creating a new order")
21 | public class OrderRequestDto implements Serializable {
22 |
23 | @Schema(description = "Unique identifier for the customer placing the order", example = "customer123")
24 | @NotEmpty(message = "Order customer Id cannot be empty")
25 | private String customerId;
26 |
27 | @Schema(description = "Unique identifier for the product being ordered", example = "product456")
28 | @NotEmpty(message = "Order productId cannot be empty")
29 | private String productId;
30 |
31 | @Schema(description = "Unique identifier for the inventory related to the order", example = "inventory789")
32 | @NotEmpty(message = "Order inventoryId cannot be empty")
33 | private String inventoryId;
34 |
35 | @Schema(description = "Quantity of the product being ordered", example = "10")
36 | @NotNull(message = "Order quantity cannot be null")
37 | @Min(value = 1, message = "Order quantity must be greater than zero")
38 | private int quantity;
39 |
40 | @Schema(description = "Shipping address for the order")
41 | private Address shippingAddress;
42 | }
43 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/orderDto/OrderResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.orderDto;
2 |
3 | import com.example.spring.boot.enums.OrderStatus;
4 | import com.example.spring.boot.model.Address;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for order response")
19 | public class OrderResponseDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier for the order", example = "order123")
22 | private String id;
23 |
24 | @Schema(description = "Unique identifier for the product associated with the order", example = "product456")
25 | private String customerId;
26 |
27 | @Schema(description = "Unique identifier for the product associated with the order", example = "product456")
28 | private String productId;
29 |
30 | @Schema(description = "Unique identifier for the inventory associated with the order", example = "inventory789")
31 | private String inventoryId;
32 |
33 | @Schema(description = "Date and time when the order was placed", example = "2024-08-30T14:00:00")
34 | private LocalDateTime orderDate;
35 |
36 | @Schema(description = "Current status of the order", example = "SHIPPED")
37 | private OrderStatus orderStatus;
38 |
39 | @Schema(description = "Quantity of the product ordered", example = "10")
40 | private int quantity;
41 |
42 | @Schema(description = "Total amount for the order", example = "199.99")
43 | private double totalAmount;
44 |
45 | @Schema(description = "Shipping address for the order")
46 | private Address shippingAddress;
47 | }
48 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/orderDto/OrderUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.orderDto;
2 |
3 | import com.example.spring.boot.model.Address;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import jakarta.validation.constraints.Min;
6 | import jakarta.validation.constraints.NotEmpty;
7 | import jakarta.validation.constraints.NotNull;
8 | import lombok.AllArgsConstructor;
9 | import lombok.Builder;
10 | import lombok.Data;
11 | import lombok.NoArgsConstructor;
12 |
13 | import java.io.Serializable;
14 | import java.time.LocalDateTime;
15 |
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | @Schema(description = "Data transfer object for updating an existing order")
21 | public class OrderUpdateRequestDto implements Serializable {
22 |
23 | @Schema(description = "Unique identifier for the customer associated with the order", example = "customer123")
24 | @NotEmpty(message = "Order customer Id cannot be empty")
25 | private String customerId;
26 |
27 | @Schema(description = "Unique identifier for the product being ordered", example = "product456")
28 | @NotEmpty(message = "Order productId cannot be empty")
29 | private String productId;
30 |
31 | @Schema(description = "Unique identifier for the inventory related to the order", example = "inventory789")
32 | @NotEmpty(message = "Order inventoryId cannot be empty")
33 | private String inventoryId;
34 |
35 | @Schema(description = "Unique identifier for the payment related to the order", example = "payment123")
36 | @NotEmpty(message = "Order paymentId cannot be empty")
37 | private String paymentId;
38 |
39 | @Schema(description = "Date and time when the order was placed or last updated", example = "2024-08-30T14:00:00")
40 | private LocalDateTime orderDate;
41 |
42 | @Schema(description = "Quantity of the product being ordered", example = "10")
43 | @NotNull(message = "Order quantity cannot be null")
44 | @Min(value = 1, message = "Order quantity must be greater than zero")
45 | private int quantity;
46 |
47 | @Schema(description = "Shipping address for the order")
48 | private Address shippingAddress;
49 | }
50 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/dto/paymentDto/PaymentUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.dto.paymentDto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.NotEmpty;
5 | import jakarta.validation.constraints.NotNull;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | @Schema(description = "Data transfer object for updating payment information")
16 | public class PaymentUpdateRequestDto {
17 |
18 | @Schema(description = "Unique identifier for the customer associated with the payment", example = "customer123")
19 | @NotEmpty(message = "Payment customerId cannot be empty")
20 | private String customerId;
21 |
22 | @Schema(description = "Unique identifier for the order related to the payment", example = "order456")
23 | @NotEmpty(message = "Payment orderId cannot be empty")
24 | private String orderId;
25 |
26 | @Schema(description = "Amount of the payment", example = "199.99")
27 | @NotNull(message = "Payment amount cannot be null")
28 | private Double amount;
29 | }
30 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/enums/CargoStatus.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.enums;
2 |
3 | public enum CargoStatus {
4 | PENDING, // Beklemede
5 | SHIPPED, // Gönderildi
6 | IN_TRANSIT,// Yolda
7 | DELIVERED, // Teslim Edildi
8 | RETURNED, // İade Edildi
9 | CANCELLED, // İptal Edildi
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/enums/Category.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.enums;
2 |
3 | public enum Category {
4 | ELEKTRONİK,
5 | MODA,
6 | EV_YAŞAM,
7 | SPOR_OUTDOOR,
8 | KOZMETİK,
9 | KIRTASİYE,
10 | SÜPERMARKET,
11 | DİĞER
12 | }
13 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/enums/OrderStatus.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.enums;
2 |
3 | public enum OrderStatus {
4 | NEW,
5 | PENDING,
6 | PROCESSING,
7 | SHIPPED,
8 | DELIVERED,
9 | CANCELLED,
10 | RETURNED,
11 | FAILED
12 | }
13 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/enums/PaymentType.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.enums;
2 |
3 | public enum PaymentType {
4 | CREDIT_CARD,
5 | BANK_TRANSFER,
6 | PAYPAL
7 | }
8 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/exception/ErrorDetails.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.exception;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.Map;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class ErrorDetails {
16 | private LocalDateTime dateTime;
17 | private String message;
18 | private String description;
19 | private int statusCode;
20 | private Map validationErrors;
21 | }
22 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/exception/InsufficientStockException.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.exception;
2 |
3 | public class InsufficientStockException extends RuntimeException {
4 | public InsufficientStockException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/exception/InventoryNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.exception;
2 |
3 | public class InventoryNotFoundException extends RuntimeException {
4 |
5 | public InventoryNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/exception/OrderNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.exception;
2 |
3 | public class OrderNotFoundException extends RuntimeException {
4 |
5 | public OrderNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/exception/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.exception;
2 |
3 | public class ProductNotFoundException extends RuntimeException {
4 |
5 | public ProductNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/external/CargoClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.external;
2 |
3 | import com.example.spring.boot.dto.cargoDto.CargoRequestDto;
4 | import com.example.spring.boot.dto.cargoDto.CargoResponseDto;
5 | import com.example.spring.boot.dto.cargoDto.CargoUpdateRequestDto;
6 | import org.springframework.cloud.openfeign.FeignClient;
7 | import org.springframework.web.bind.annotation.PostMapping;
8 | import org.springframework.web.bind.annotation.PutMapping;
9 |
10 | @FeignClient("CARGO-SERVICE")
11 | public interface CargoClientService {
12 |
13 | @PostMapping("api/v1/cargo")
14 | CargoResponseDto createCargo(CargoRequestDto cargoRequestDto);
15 |
16 | @PutMapping("api/v1/cargo")
17 | CargoResponseDto updateCargo(CargoUpdateRequestDto cargoUpdateRequestDto);
18 | }
19 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/external/CustomerClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.external;
2 |
3 | import com.example.spring.boot.model.Customer;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 |
8 | @FeignClient(name = "CUSTOMER-SERVICE")
9 | public interface CustomerClientService {
10 |
11 | @GetMapping("api/v1/customers/{customerId}")
12 | Customer getCustomerById(@PathVariable("customerId") String customerId);
13 | }
14 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/external/InventoryClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.external;
2 |
3 | import com.example.spring.boot.dto.inventoryDto.InventoryUpdateRequestDto;
4 | import com.example.spring.boot.model.Inventory;
5 | import org.springframework.cloud.openfeign.FeignClient;
6 | import org.springframework.web.bind.annotation.*;
7 |
8 | @FeignClient(name = "INVENTORY-SERVICE")
9 | public interface InventoryClientService {
10 |
11 | @PostMapping("/api/v1/inventories/create")
12 | Inventory addInventory(@RequestBody Inventory inventory);
13 |
14 | @GetMapping("/api/v1/inventories/{productId}")
15 | Inventory getInventoryByProductId(@PathVariable("productId") String productId);
16 |
17 | @PutMapping("/api/v1/inventories/{inventoryId}")
18 | Inventory updateInventory(@PathVariable("inventoryId") String inventoryId,@RequestBody InventoryUpdateRequestDto updateRequest);
19 |
20 | @DeleteMapping("/api/v1/inventories/{productId}")
21 | void deleteInventory(@PathVariable("productId") String productId);
22 |
23 | @GetMapping("/api/v1/inventories/getInventoryId/{id}")
24 | Inventory getInventoryById(@PathVariable("id") String id);
25 | }
26 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/external/PaymentClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.external;
2 |
3 | import com.example.spring.boot.dto.paymentDto.PaymentUpdateRequestDto;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.*;
6 |
7 | @FeignClient(name = "PAYMENT-SERVICE")
8 | public interface PaymentClientService {
9 |
10 | @PostMapping("/api/v1/payments/cancel/{paymentId}/")
11 | void cancelPayment(@PathVariable String paymentId);
12 |
13 | @GetMapping("/api/v1/payments/{paymentId}")
14 | void getPaymentById(@PathVariable("paymentId") String paymentId);
15 |
16 | @GetMapping("/api/v1/payments/paymentCustomer/{customerId}")
17 | void getPaymentCustomerById(@PathVariable("customerId") String customerId);
18 |
19 | @PutMapping("/api/v1/payments")
20 | void updatePayment(@RequestBody PaymentUpdateRequestDto paymentUpdateRequestDto);
21 |
22 | @DeleteMapping("/api/v1/payments/{paymentId}")
23 | void deletePaymentById(@PathVariable("paymentId") String paymentId);
24 | }
25 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/external/ProductClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.external;
2 |
3 | import com.example.spring.boot.model.Product;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.*;
6 |
7 | @FeignClient(name = "PRODUCT-SERVICE")
8 | public interface ProductClientService {
9 | @PostMapping("/api/v1/products")
10 | Product addProduct(@RequestBody Product product);
11 |
12 | @GetMapping("/api/v1/products/{id}")
13 | Product getProductById(@PathVariable("id") String id);
14 |
15 | @PutMapping("/api/v1/products/{id}")
16 | Product updateProduct(@PathVariable("id") String id, @RequestBody Product product);
17 |
18 | @DeleteMapping("/api/v1/products/{id}")
19 | void deleteProduct(@PathVariable("id") String id);
20 | }
21 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/model/Address.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.model;
2 |
3 | import jakarta.persistence.Embeddable;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | import java.io.Serializable;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | @Embeddable
16 | public class Address implements Serializable {
17 |
18 | private String country;
19 | private String city;
20 | private String district;
21 | private String street;
22 | private String zipCode;
23 | private String description;
24 | }
25 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/model/Cargo.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.model;
2 |
3 | import com.example.spring.boot.enums.CargoStatus;
4 |
5 | import java.io.Serializable;
6 | import java.time.LocalDateTime;
7 |
8 | public class Cargo implements Serializable {
9 |
10 | private String id;
11 |
12 | private String orderId;
13 |
14 | private String trackingNumber;
15 |
16 | private CargoStatus status;
17 |
18 | private LocalDateTime lastUpdated;
19 | }
20 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/model/Customer.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.util.List;
9 |
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class Customer {
16 | private String id;
17 |
18 | private String firstName;
19 | private String lastName;
20 | private String email;
21 | private String phoneNumber;
22 |
23 | private List addressList;
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/model/Inventory.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.io.Serializable;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class Inventory implements Serializable {
15 |
16 | private String id;
17 | private String productId;
18 | private int stockQuantity;
19 | }
20 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/model/Order.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.model;
2 |
3 | import com.example.spring.boot.enums.OrderStatus;
4 |
5 | import jakarta.persistence.*;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 | import org.hibernate.annotations.UuidGenerator;
11 |
12 | import java.io.Serializable;
13 | import java.time.LocalDateTime;
14 |
15 | @Entity
16 | @Table(name = "orders")
17 | @Data
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | @Builder
21 | public class Order implements Serializable {
22 |
23 | @Id
24 | @GeneratedValue
25 | @UuidGenerator
26 | private String id;
27 |
28 | private String customerId;
29 | private String productId;
30 | private String inventoryId;
31 | private LocalDateTime orderDate;
32 |
33 | @Enumerated(EnumType.STRING)
34 | private OrderStatus orderStatus;
35 |
36 | private int quantity;
37 | private double totalAmount;
38 |
39 | @Embedded
40 | private Address shippingAddress;
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/model/Product.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.model;
2 |
3 | import com.example.spring.boot.enums.Category;
4 | import jakarta.persistence.EnumType;
5 | import jakarta.persistence.Enumerated;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 |
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | @Builder
17 | public class Product implements Serializable {
18 |
19 | private String id;
20 | private String inventoryId;
21 | private String name;
22 | private String description;
23 | private Category category;
24 | private double price;
25 | }
26 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/repository/OrderRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.repository;
2 |
3 | import com.example.spring.boot.enums.OrderStatus;
4 | import com.example.spring.boot.model.Order;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 |
9 | import java.time.LocalDateTime;
10 | import java.util.List;
11 | import java.util.Optional;
12 |
13 | @Repository
14 | public interface OrderRepository extends JpaRepository {
15 |
16 | Optional findByProductId(String productId);
17 |
18 | Optional findByInventoryId(String inventoryId);
19 |
20 | List findByOrderDateBetween(LocalDateTime startDateTime, LocalDateTime endDateTime);
21 |
22 | List findByOrderStatusAndOrderDateBefore(OrderStatus orderStatus,LocalDateTime dateTime);
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/order-service/src/main/java/com/example/spring/boot/schedulers/OrderScheduler.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot.schedulers;
2 |
3 | import com.example.spring.boot.enums.OrderStatus;
4 | import com.example.spring.boot.model.Order;
5 | import com.example.spring.boot.repository.OrderRepository;
6 | import lombok.RequiredArgsConstructor;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.springframework.scheduling.annotation.Scheduled;
9 | import org.springframework.stereotype.Service;
10 |
11 | import java.time.LocalDateTime;
12 | import java.util.List;
13 |
14 | @Service
15 | @RequiredArgsConstructor
16 | @Slf4j
17 | public class OrderScheduler {
18 |
19 | private final OrderRepository orderRepository;
20 |
21 | @Scheduled(cron = "0 0 0 * * ?") // Her gece 00:00'da çalışır
22 | public void deleteUnfinishedOrders() {
23 | log.info("OrderScheduler::deleteUnfinishedOrders started.");
24 |
25 | LocalDateTime oneDayAgo = LocalDateTime.now().minusDays(1);
26 |
27 | List oldOrders = orderRepository.findByOrderStatusAndOrderDateBefore(OrderStatus.PROCESSING, oneDayAgo);
28 | log.info("OrderScheduler::deleteUnfinishedOrders - oldOrders: {}", oldOrders);
29 |
30 | if (!oldOrders.isEmpty()) {
31 | log.info("OrderScheduler::deleteUnfinishedOrders - oldOrders is not empty.");
32 | orderRepository.deleteAll(oldOrders);
33 | log.info("OrderScheduler::deleteUnfinishedOrders - oldOrders deleted.");
34 | } else {
35 | log.info("OrderScheduler::deleteUnfinishedOrders - oldOrders is empty.");
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/order-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orhanturkmenoglu/ecommerce-microservices-springboot/6b9128ff359b6599573b79defdd2f869f796fc0e/order-service/src/main/resources/application.properties
--------------------------------------------------------------------------------
/order-service/src/test/java/com/example/spring/boot/OrderServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.spring.boot;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class OrderServiceApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/payment-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/payment-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/payment-service/Dockerfile:
--------------------------------------------------------------------------------
1 | # 1. Kullanılacak temel imajı belirtir
2 | FROM openjdk:17-jdk
3 |
4 | # 2. Uygulama için bir çalışma dizini oluşturun
5 | WORKDIR /app
6 |
7 | VOLUME /temp
8 |
9 | # 4. JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
10 |
11 |
12 | # 5. Uygulamanın çalıştırılması için gerekli komutu belirtir
13 | ENTRYPOINT ["java", "-jar", "paymentservice.jar"]
14 |
15 | # 6. Bağlantı noktasını açığa çıkarma (Eğer varsayılan olarak 8080'de çalışıyorsa)
16 | EXPOSE 8085
17 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/PaymentServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cache.annotation.EnableCaching;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.openfeign.EnableFeignClients;
8 | import org.springframework.scheduling.annotation.EnableScheduling;
9 |
10 | @SpringBootApplication
11 | @EnableDiscoveryClient
12 | @EnableFeignClients
13 | @EnableCaching
14 | @EnableScheduling
15 | public class PaymentServiceApplication {
16 |
17 | public static void main(String[] args) {
18 | SpringApplication.run(PaymentServiceApplication.class, args);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/config/KafkaConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.config;
2 |
3 | import com.example.payment_service.model.Inventory;
4 | import org.apache.kafka.clients.producer.ProducerConfig;
5 | import org.apache.kafka.common.serialization.StringSerializer;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 | import org.springframework.kafka.core.DefaultKafkaProducerFactory;
10 | import org.springframework.kafka.core.KafkaTemplate;
11 | import org.springframework.kafka.core.ProducerFactory;
12 | import org.springframework.kafka.support.serializer.JsonSerializer;
13 |
14 | import java.util.HashMap;
15 | import java.util.Map;
16 |
17 | @Configuration
18 | public class KafkaConfig {
19 |
20 | @Value("${spring.kafka.bootstrap-servers}")
21 | private String bootstrapServers;
22 |
23 |
24 | public Map producerConfig() {
25 | Map props = new HashMap<>();
26 | props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
27 |
28 | props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
29 | props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class);
30 |
31 | return props;
32 | }
33 |
34 | @Bean
35 | public ProducerFactory producerFactory(){
36 | return new DefaultKafkaProducerFactory<>(producerConfig());
37 | }
38 |
39 |
40 | @Bean
41 | public KafkaTemplate kafkaTemplate(){
42 | return new KafkaTemplate<>(producerFactory());
43 | }
44 |
45 |
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.config;
2 |
3 |
4 | import io.swagger.v3.oas.models.OpenAPI;
5 | import io.swagger.v3.oas.models.info.Contact;
6 | import io.swagger.v3.oas.models.info.Info;
7 | import org.springframework.context.annotation.Bean;
8 | import org.springframework.context.annotation.Configuration;
9 |
10 | @Configuration
11 | public class SwaggerConfig {
12 | @Bean
13 | public OpenAPI customOpenAPI() {
14 | return new OpenAPI()
15 | .info(info()
16 | .contact(contact()));
17 | }
18 |
19 | @Bean
20 | public Info info() {
21 | return new Info()
22 | .title("Microservice API Documentation")
23 | .version("1.0")
24 | .description("API documentation for the microservices.");
25 | }
26 |
27 | @Bean
28 | public Contact contact() {
29 | return new Contact()
30 | .name("Orhan")
31 | .email("orhantrkmn749@mail.com")
32 | .url("https://github.com/orhanturkmenoglu");
33 | }
34 | }
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/dto/orderDto/OrderResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.dto.orderDto;
2 |
3 | import com.example.payment_service.model.Address;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 |
10 | import java.io.Serializable;
11 | import java.time.LocalDateTime;
12 |
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | @Builder
17 | @Schema(description = "Data transfer object for order response")
18 | public class OrderResponseDto implements Serializable {
19 |
20 | @Schema(description = "Unique identifier of the order", example = "order123")
21 | private String id;
22 |
23 | @Schema(description = "Unique identifier of the product associated with the order", example = "prod456")
24 | private String productId;
25 |
26 | @Schema(description = "Unique identifier of the inventory associated with the order", example = "inv789")
27 | private String inventoryId;
28 |
29 | @Schema(description = "Date and time when the order was placed", example = "2024-08-30T15:00:00")
30 | private LocalDateTime orderDate;
31 |
32 | @Schema(description = "Current status of the order", example = "SHIPPED")
33 | private String orderStatus;
34 |
35 | @Schema(description = "Quantity of the product ordered", example = "3")
36 | private int quantity;
37 |
38 | @Schema(description = "Total amount for the order", example = "299.99")
39 | private double totalAmount;
40 |
41 | @Schema(description = "Shipping address for the order")
42 | private Address shippingAddress;
43 | }
44 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/dto/paymentDto/PaymentRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.dto.paymentDto;
2 |
3 | import com.example.payment_service.enums.PaymentType;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import jakarta.validation.constraints.NotEmpty;
6 | import jakarta.validation.constraints.NotNull;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Builder;
9 | import lombok.Data;
10 | import lombok.NoArgsConstructor;
11 |
12 | import java.io.Serializable;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for payment request")
19 | public class PaymentRequestDto implements Serializable {
20 |
21 | @NotEmpty(message = "Payment customer id cannot be empty")
22 | @Schema(description = "Unique identifier of the customer making the payment", example = "cust123")
23 | private String customerId;
24 |
25 |
26 | @NotEmpty(message = "Order id cannot be empty")
27 | @Schema(description = "Unique identifier of the order being paid for", example = "order456")
28 | private String orderId;
29 |
30 | @NotEmpty(message = "Cargo id cannot be empty")
31 | @Schema(description = "Unique identifier of the cargo associated with the payment", example = "cargo789")
32 | private String cargoId;
33 |
34 |
35 | @NotNull(message = "Payment type cannot be empty")
36 | @Schema(description = "Type of payment being made", example = "CREDIT_CARD")
37 | private PaymentType paymentType;
38 | }
39 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/dto/paymentDto/PaymentUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.dto.paymentDto;
2 |
3 | import com.example.payment_service.enums.PaymentType;
4 | import io.swagger.v3.oas.annotations.media.Schema;
5 | import jakarta.validation.constraints.NotEmpty;
6 | import jakarta.validation.constraints.NotNull;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Builder;
9 | import lombok.Data;
10 | import lombok.NoArgsConstructor;
11 |
12 | import java.io.Serializable;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for updating payment information")
19 | public class PaymentUpdateRequestDto implements Serializable {
20 |
21 | @NotEmpty(message = "Payment customerId cannot be empty")
22 | @Schema(description = "Unique identifier of the customer making the payment", example = "cust123")
23 | private String customerId;
24 |
25 | @NotEmpty(message = "Payment orderId cannot be empty")
26 | @Schema(description = "Unique identifier of the order associated with the payment", example = "order456")
27 | private String orderId;
28 |
29 | @NotEmpty(message = "Payment amount cannot be empty")
30 | @Schema(description = "Amount of the payment", example = "150.75")
31 | private Double amount;
32 |
33 | @NotNull(message = "Payment type cannot be empty")
34 | @Schema(description = "Type of payment being made", example = "CREDIT_CARD" )
35 | private PaymentType paymentType;
36 | }
37 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/enums/CargoStatus.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.enums;
2 |
3 | public enum CargoStatus {
4 | PENDING, // Beklemede
5 | SHIPPED, // Gönderildi
6 | IN_TRANSIT,// Yolda
7 | DELIVERED, // Teslim Edildi
8 | RETURNED, // İade Edildi
9 | CANCELLED, // İptal Edildi
10 |
11 | }
12 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/enums/PaymentStatus.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.enums;
2 |
3 | public enum PaymentStatus {
4 | NEW,
5 | PENDING,
6 | PROCESSING,
7 | COMPLETED,
8 | SHIPPED,
9 | DELIVERED,
10 | CANCELLED,
11 | RETURNED,
12 | REFUNDED,
13 | PAID,
14 | NO_PAYMENT_REQUIRED, FAILED
15 | }
16 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/enums/PaymentType.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.enums;
2 |
3 | public enum PaymentType {
4 | CREDIT_CARD,
5 | BANK_TRANSFER,
6 | PAYPAL
7 | }
8 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/exception/ErrorDetails.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.exception;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.Map;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class ErrorDetails {
16 | private LocalDateTime dateTime;
17 | private String message;
18 | private String description;
19 | private int statusCode;
20 | private Map validationErrors;
21 | }
22 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/exception/InsufficientStockException.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.exception;
2 |
3 | public class InsufficientStockException extends RuntimeException {
4 | public InsufficientStockException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/exception/OrderNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.exception;
2 |
3 | public class OrderNotFoundException extends RuntimeException {
4 | public OrderNotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/exception/PaymentCancellationException.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.exception;
2 |
3 | public class PaymentCancellationException extends RuntimeException {
4 | public PaymentCancellationException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/exception/PaymentCustomerNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.exception;
2 |
3 | public class PaymentCustomerNotFoundException extends RuntimeException {
4 | public PaymentCustomerNotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/exception/PaymentNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.exception;
2 |
3 | public class PaymentNotFoundException extends RuntimeException {
4 | public PaymentNotFoundException(String message) {
5 | super(message);
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/external/CargoClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.external;
2 |
3 | import com.example.payment_service.model.Cargo;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.PutMapping;
6 |
7 | @FeignClient("CARGO-SERVICE")
8 | public interface CargoClientService {
9 |
10 | @PutMapping("api/v1/cargo")
11 | Cargo updateCargo(Cargo cargo);
12 | }
13 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/external/CustomerClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.external;
2 |
3 | import com.example.payment_service.model.Customer;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 |
8 | @FeignClient(name = "CUSTOMER-SERVICE")
9 | public interface CustomerClientService {
10 |
11 | @GetMapping("api/v1/customers/{customerId}")
12 | Customer getCustomerById(@PathVariable("customerId") String customerId);
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/external/InventoryServiceClient.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.external;
2 |
3 | import com.example.payment_service.model.Inventory;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 |
8 | @FeignClient(name = "INVENTORY-SERVICE")
9 | public interface InventoryServiceClient {
10 |
11 | @GetMapping("/api/v1/inventories/getInventoryId/{id}")
12 | Inventory getInventoryById(@PathVariable String id);
13 | }
14 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/external/OrderServiceClient.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.external;
2 |
3 | import com.example.payment_service.dto.orderDto.OrderResponseDto;
4 | import org.springframework.cloud.openfeign.FeignClient;
5 | import org.springframework.web.bind.annotation.GetMapping;
6 | import org.springframework.web.bind.annotation.PathVariable;
7 |
8 | @FeignClient(name = "ORDER-SERVICE")
9 | public interface OrderServiceClient {
10 |
11 | @GetMapping("api/v1/orders/{id}")
12 | OrderResponseDto getOrderById(@PathVariable String id);
13 | }
14 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/mapper/PaymentMapper.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.mapper;
2 |
3 | import com.example.payment_service.dto.paymentDto.PaymentRequestDto;
4 | import com.example.payment_service.dto.paymentDto.PaymentResponseDto;
5 | import com.example.payment_service.enums.PaymentStatus;
6 | import com.example.payment_service.model.Payment;
7 | import org.springframework.stereotype.Component;
8 |
9 | import java.time.LocalDateTime;
10 | import java.util.List;
11 |
12 | @Component
13 | public class PaymentMapper {
14 |
15 | public Payment mapToPayment(PaymentRequestDto paymentRequestDto) {
16 | return Payment.builder()
17 | .customerId(paymentRequestDto.getCustomerId())
18 | .orderId(paymentRequestDto.getOrderId())
19 | .cargoId(paymentRequestDto.getCargoId())
20 | .paymentStatus(PaymentStatus.PENDING) // Başlangıçta ödeme durumu PENDING
21 | .paymentType(paymentRequestDto.getPaymentType())
22 | .paymentDate(LocalDateTime.now())
23 | .amount(0.0) // Burada amount değerini atıyoruz
24 | .quantity(0) // Burada quantity değerini atıyoruz
25 | .build();
26 | }
27 |
28 | public PaymentResponseDto mapToPaymentResponseDto(Payment payment) {
29 | return PaymentResponseDto.builder()
30 | .id(payment.getId())
31 | .customerId(payment.getCustomerId())
32 | .orderId(payment.getOrderId())
33 | .cargoId(payment.getCargoId())
34 | .paymentStatus(payment.getPaymentStatus())
35 | .quantity(payment.getQuantity())
36 | .amount(payment.getAmount())
37 | .paymentType(payment.getPaymentType())
38 | .paymentDate(payment.getPaymentDate())
39 | .build();
40 | }
41 |
42 | public List maptoPaymentResponseDtoList(List payments) {
43 | return payments.stream()
44 | .map(this::mapToPaymentResponseDto)
45 | .toList();
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/model/Address.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.io.Serializable;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class Address implements Serializable {
15 |
16 | private String country;
17 | private String city;
18 | private String district;
19 | private String street;
20 | private String zipCode;
21 | private String description;
22 | }
23 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/model/Cargo.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.model;
2 |
3 | import com.example.payment_service.enums.CargoStatus;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | import java.io.Serializable;
10 | import java.time.LocalDateTime;
11 |
12 | @Data
13 | @NoArgsConstructor
14 | @AllArgsConstructor
15 | @Builder
16 | public class Cargo implements Serializable {
17 |
18 | private String id;
19 |
20 | private String orderId;
21 |
22 | private String customerId;
23 |
24 | private String trackingNumber; // izleme numarası
25 |
26 | private CargoStatus status;
27 |
28 | private LocalDateTime lastUpdated;
29 | }
30 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/model/Customer.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 |
9 | @Data
10 | @NoArgsConstructor
11 | @AllArgsConstructor
12 | @Builder
13 | public class Customer {
14 | private String id;
15 |
16 | private String firstName;
17 | private String lastName;
18 | private String email;
19 | private String phoneNumber;
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/model/Inventory.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.io.Serializable;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class Inventory implements Serializable {
15 | private String id;
16 | private String productId;
17 | private int stockQuantity;
18 | }
19 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/model/Payment.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.model;
2 |
3 | import com.example.payment_service.enums.PaymentStatus;
4 | import com.example.payment_service.enums.PaymentType;
5 | import jakarta.annotation.PostConstruct;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 | import org.springframework.data.annotation.Id;
11 | import org.springframework.data.mongodb.core.mapping.Document;
12 |
13 | import java.io.Serializable;
14 | import java.time.LocalDateTime;
15 | import java.util.UUID;
16 |
17 | @Data
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | @Builder
21 | @Document(collection = "payments")
22 | public class Payment implements Serializable {
23 |
24 | @Id
25 | private String id;
26 |
27 | private String customerId;
28 |
29 | private String orderId;
30 |
31 | private String cargoId;
32 |
33 | private int quantity;
34 |
35 | private Double amount;
36 |
37 | private PaymentStatus paymentStatus = PaymentStatus.PENDING; // ödeme durumu default değer.
38 |
39 |
40 | private PaymentType paymentType; // ödeme tipi
41 |
42 | private String stripePaymentStatus;
43 |
44 | private LocalDateTime paymentDate;
45 |
46 | private String checkOutUrl;
47 |
48 |
49 | @PostConstruct
50 | private void init() {
51 | if (this.id == null) {
52 | this.id = UUID.randomUUID().toString();
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/publisher/PaymentMessageSender.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.publisher;
2 |
3 |
4 | import com.example.payment_service.model.Inventory;
5 | import lombok.RequiredArgsConstructor;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.springframework.kafka.core.KafkaTemplate;
8 | import org.springframework.stereotype.Service;
9 |
10 | @Service
11 | @RequiredArgsConstructor
12 | @Slf4j
13 | public class PaymentMessageSender {
14 |
15 | private final KafkaTemplate kafkaTemplate;
16 |
17 | public void sendInventoryUpdateMessage(Inventory inventory) {
18 | log.info(String.format("SEND MESSAGE -> : %s", inventory));
19 | kafkaTemplate.send("inventory", inventory);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/repository/PaymentRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.repository;
2 |
3 | import com.example.payment_service.enums.PaymentStatus;
4 | import com.example.payment_service.enums.PaymentType;
5 | import com.example.payment_service.model.Payment;
6 | import org.springframework.data.mongodb.repository.MongoRepository;
7 | import org.springframework.stereotype.Repository;
8 |
9 | import java.time.LocalDateTime;
10 | import java.util.List;
11 | import java.util.Optional;
12 |
13 | @Repository
14 | public interface PaymentRepository extends MongoRepository {
15 |
16 | Optional findByOrderId(String orderId);
17 |
18 | Optional findByCustomerId(String customerId);
19 |
20 | List findByPaymentType(PaymentType paymentType);
21 |
22 | List findByPaymentDateBetween(LocalDateTime startDate,LocalDateTime endDate);
23 |
24 | List findByPaymentStatus(PaymentStatus paymentStatus);
25 | }
26 |
--------------------------------------------------------------------------------
/payment-service/src/main/java/com/example/payment_service/util/PaymentMessage.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service.util;
2 |
3 | public class PaymentMessage {
4 | public static final String PAYMENT_NOT_FOUND = "PAYMENT NOT FOUND WITH ID : ";
5 | public static final String INSUFFICIENT_STOCK = "NOT ENOUGH STOCK AVAILABLE : ";
6 | public static final String PAYMENT_CUSTOMER_NOT_FOUND = "PAYMENT CUSTOMER NOT FOUND WITH ID : ";
7 | }
8 |
--------------------------------------------------------------------------------
/payment-service/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/payment-service/src/test/java/com/example/payment_service/PaymentServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.payment_service;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 | import org.springframework.test.context.ActiveProfiles;
6 |
7 | @SpringBootTest
8 | @ActiveProfiles("dev")
9 | class PaymentServiceApplicationTests {
10 |
11 | @Test
12 | void contextLoads() {
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/product-service/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/product-service/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/product-service/Dockerfile:
--------------------------------------------------------------------------------
1 | #Kullanılacak temel imajı belirtir.
2 | FROM openjdk:17-jdk
3 |
4 | # Uygulama için bir çalışma dizini oluşturun
5 | # sonraki tüm komutlar bu dizin içerisinde çalışacaktır
6 | #düzen sağlar.
7 | WORKDIR /app
8 |
9 | VOLUME /temp
10 |
11 |
12 | # 4. JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
13 | COPY ./target/product-service-0.0.1-SNAPSHOT.jar ./product-service-0.0.1-SNAPSHOT.jar
14 |
15 | # 5. Uygulamanın çalıştırılması için gerekli komutu belirtir
16 | ENTRYPOINT ["java", "-jar", "product-service-0.0.1-SNAPSHOT.jar"]
17 |
18 |
19 | # 6. Bağlantı noktasını açığa çıkarma (Eğer varsayılan olarak 8080'de çalışıyorsa)
20 | EXPOSE 8080
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/ProductServiceApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cache.annotation.EnableCaching;
6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
7 | import org.springframework.cloud.openfeign.EnableFeignClients;
8 |
9 | @SpringBootApplication
10 | @EnableDiscoveryClient
11 | @EnableFeignClients
12 | @EnableCaching
13 | public class ProductServiceApplication {
14 |
15 | public static void main(String[] args) {
16 | SpringApplication.run(ProductServiceApplication.class, args);
17 |
18 |
19 | // PRODUCT MİCROSERVİCE SORUMLULUKLARI
20 | /*
21 | ÜRÜN BİLGİLERİNİ YÖNETİR (ÜRÜN EKLEME , SİLME GÜNCELLEME)
22 | ÜRÜN DETAYLARINI SAĞLAR (İSİM,AÇIKLAMA,FİYAT VB..)
23 | ÜRÜNLERİN MEVCUT STOK BİLGİLERİNİ SAĞLAR (INVENTORY MS İLE İLETİŞİM)
24 | */
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.config;
2 |
3 |
4 |
5 | import io.swagger.v3.oas.models.OpenAPI;
6 | import io.swagger.v3.oas.models.info.Contact;
7 | import io.swagger.v3.oas.models.info.Info;
8 | import org.springframework.context.annotation.Bean;
9 | import org.springframework.context.annotation.Configuration;
10 |
11 | @Configuration
12 | public class SwaggerConfig {
13 |
14 | @Bean
15 | public OpenAPI customOpenAPI() {
16 | return new OpenAPI()
17 | .info(info()
18 | .contact(contact()));
19 | }
20 |
21 | @Bean
22 | public Info info() {
23 | return new Info()
24 | .title("Microservice API Documentation")
25 | .version("1.0")
26 | .description("API documentation for the microservices.");
27 | }
28 |
29 | @Bean
30 | public Contact contact() {
31 | return new Contact()
32 | .name("Orhan")
33 | .email("orhantrkmn749@mail.com")
34 | .url("https://github.com/orhanturkmenoglu");
35 | }
36 | }
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/dto/inventoryDto/InventoryRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.dto.inventoryDto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.Min;
5 | import jakarta.validation.constraints.NotNull;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 |
13 | @Data
14 | @NoArgsConstructor
15 | @AllArgsConstructor
16 | @Builder
17 | @Schema(description = "Data transfer object for inventory requests")
18 | public class InventoryRequestDto implements Serializable {
19 |
20 | @Schema(description = "Unique identifier of the inventory")
21 | private String id;
22 |
23 | @Schema(description = "Unique identifier of the associated product")
24 | private String productId;
25 |
26 | @NotNull(message = "Inventory stock quantity cannot be null")
27 | @Min(value = 0,message = "Inventory stock quantity must be 0")
28 | @Schema(description = "Stock quantity of the inventory", example = "10")
29 | private int stockQuantity;
30 | }
31 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/dto/inventoryDto/InventoryResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.dto.inventoryDto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import lombok.AllArgsConstructor;
5 | import lombok.Builder;
6 | import lombok.Data;
7 | import lombok.NoArgsConstructor;
8 |
9 | import java.io.Serializable;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | @Schema(description = "Data transfer object for inventory response")
16 | public class InventoryResponseDto implements Serializable {
17 |
18 | @Schema(description = "Unique identifier of the inventory", example = "123")
19 | private String id;
20 |
21 | @Schema(description = "Unique identifier of the associated product", example = "456")
22 | private String productId;
23 |
24 | @Schema(description = "Current stock quantity of the inventory", example = "100")
25 | private int stockQuantity;
26 | }
27 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/dto/inventoryDto/InventoryUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.dto.inventoryDto;
2 |
3 | import io.swagger.v3.oas.annotations.media.Schema;
4 | import jakarta.validation.constraints.Min;
5 | import jakarta.validation.constraints.NotEmpty;
6 | import jakarta.validation.constraints.NotNull;
7 | import lombok.AllArgsConstructor;
8 | import lombok.Builder;
9 | import lombok.Data;
10 | import lombok.NoArgsConstructor;
11 |
12 | import java.io.Serializable;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for updating inventory")
19 | public class InventoryUpdateRequestDto implements Serializable {
20 |
21 | @NotEmpty(message = "Inventory Id cannot be empty")
22 | @Schema(description = "Unique identifier of the inventory", example = "inv123")
23 | private String inventoryId;
24 |
25 | @NotEmpty(message = "Inventory product Id cannot be empty")
26 | @Schema(description = "Unique identifier of the product associated with the inventory", example = "prod456")
27 | private String productId;
28 |
29 | @NotNull(message = "Inventory stock quantity cannot be null")
30 | @Min(value = 0,message = "Inventory stock quantity must be 0")
31 | @Schema(description = "New stock quantity for the inventory", example = "20")
32 | private int newQuantity;
33 | }
34 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/dto/productDto/ProductRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.dto.productDto;
2 |
3 | import com.example.product_service.dto.inventoryDto.InventoryRequestDto;
4 | import com.example.product_service.enums.Category;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import jakarta.persistence.Column;
7 | import jakarta.persistence.EnumType;
8 | import jakarta.persistence.Enumerated;
9 | import jakarta.validation.constraints.Min;
10 | import jakarta.validation.constraints.NotEmpty;
11 | import jakarta.validation.constraints.NotNull;
12 | import lombok.AllArgsConstructor;
13 | import lombok.Builder;
14 | import lombok.Data;
15 | import lombok.NoArgsConstructor;
16 |
17 | import java.io.Serializable;
18 |
19 | @Data
20 | @NoArgsConstructor
21 | @AllArgsConstructor
22 | @Builder
23 | @Schema(description = "Product entity representing the product details")
24 | public class ProductRequestDto implements Serializable {
25 |
26 | @Schema(description = "Unique identifier of the product")
27 | private String id;
28 |
29 | @Schema(description = "Name of the product", example = "Laptop")
30 | @NotEmpty(message = "Product name cannot be empty ")
31 | private String name;
32 |
33 | @Schema(description = "Image URL of the product", example = "https://example.com/laptop.jpg")
34 | private String imageUrl;
35 |
36 | @Schema(description = "Description of the product", example = "High-performance laptop for gaming and work")
37 | @NotEmpty(message = "Product description cannot be empty ")
38 | private String description;
39 |
40 | @NotEmpty(message = "Product category cannot be empty ")
41 | @Schema(description = "Category of the product", example = "ELEKTRONİK")
42 | @Enumerated(EnumType.STRING)
43 | private Category category;
44 |
45 | @NotNull(message = "Product price cannot be null")
46 | @Min(message = "Product price must be greater than zero", value = 0)
47 | @Schema(description = "Price of the product", example = "999.99")
48 | private double price;
49 |
50 |
51 | private InventoryRequestDto inventoryRequestDto;
52 | }
53 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/dto/productDto/ProductResponseDto.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.dto.productDto;
2 |
3 | import com.example.product_service.dto.inventoryDto.InventoryResponseDto;
4 | import com.example.product_service.enums.Category;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import lombok.AllArgsConstructor;
7 | import lombok.Builder;
8 | import lombok.Data;
9 | import lombok.NoArgsConstructor;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Data
15 | @NoArgsConstructor
16 | @AllArgsConstructor
17 | @Builder
18 | @Schema(description = "Data transfer object for product response")
19 | public class ProductResponseDto implements Serializable {
20 |
21 | @Schema(description = "Unique identifier of the product", example = "prod789")
22 | private String id;
23 |
24 | @Schema(description = "Unique identifier of the associated inventory", example = "inv123")
25 | private String inventoryId;
26 |
27 | @Schema(description = "Name of the product", example = "Laptop")
28 | private String name;
29 |
30 | @Schema(description = "Image URL of the product", example = "https://example.com/laptop.jpg")
31 | private String imageUrl;
32 |
33 | @Schema(description = "Description of the product", example = "A high-performance laptop with 16GB RAM and 512GB SSD.")
34 | private String description;
35 |
36 | @Schema(description = "Category of the product", example = "ELECTRONICS")
37 | private Category category;
38 |
39 | @Schema(description = "Price of the product", example = "999.99")
40 | private double price;
41 |
42 | @Schema(description = "Date and time when the product was created", example = "2024-08-29T10:15:30")
43 | private LocalDateTime createdDate;
44 |
45 |
46 | private InventoryResponseDto inventoryResponseDto;
47 | }
48 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/dto/productDto/ProductUpdateRequestDto.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.dto.productDto;
2 |
3 | import com.example.product_service.dto.inventoryDto.InventoryUpdateRequestDto;
4 | import com.example.product_service.enums.Category;
5 | import io.swagger.v3.oas.annotations.media.Schema;
6 | import jakarta.validation.constraints.Min;
7 | import jakarta.validation.constraints.NotEmpty;
8 | import jakarta.validation.constraints.NotNull;
9 | import lombok.AllArgsConstructor;
10 | import lombok.Builder;
11 | import lombok.Data;
12 | import lombok.NoArgsConstructor;
13 |
14 | import java.io.Serializable;
15 |
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | @Schema(description = "Data transfer object for updating product information")
21 | public class ProductUpdateRequestDto implements Serializable {
22 |
23 | @Schema(description = "Unique identifier of the product to be updated", example = "prod789")
24 | private String id;
25 |
26 | @NotEmpty(message = "Product name cannot be empty ")
27 | @Schema(description = "Name of the product", example = "Smartphone")
28 | private String name;
29 |
30 | @NotEmpty(message = "Product image URL cannot be empty ")
31 | @Schema(description = "Image URL of the product", example = "https://example.com/smartphone.jpg")
32 | private String imageUrl;
33 |
34 | @NotEmpty(message = "Product description cannot be empty ")
35 | @Schema(description = "Description of the product", example = "Latest model with advanced features.")
36 | private String description;
37 |
38 | @NotEmpty(message = "Product category cannot be empty ")
39 | @Schema(description = "Category of the product", example = "ELECTRONICS")
40 | private Category category;
41 |
42 | @NotNull(message = "Product price cannot be null")
43 | @Min(message = "Product price must be greater than zero", value = 0)
44 | @Schema(description = "Price of the product", example = "299.99")
45 | private double price;
46 |
47 |
48 | private InventoryUpdateRequestDto inventoryUpdateRequestDto;
49 | }
50 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/enums/Category.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.enums;
2 |
3 | public enum Category {
4 | ELEKTRONİK,
5 | MODA,
6 | EV_YAŞAM,
7 | SPOR_OUTDOOR,
8 | KOZMETİK,
9 | KIRTASİYE,
10 | SÜPERMARKET,
11 | DİĞER
12 | }
13 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/exception/ErrorDetails.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.exception;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.time.LocalDateTime;
9 | import java.util.Map;
10 |
11 | @Data
12 | @NoArgsConstructor
13 | @AllArgsConstructor
14 | @Builder
15 | public class ErrorDetails {
16 | private LocalDateTime dateTime;
17 | private String message;
18 | private String description;
19 | private int statusCode;
20 | private Map validationErrors;
21 | }
22 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/exception/InventoryNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.exception;
2 |
3 | public class InventoryNotFoundException extends RuntimeException {
4 |
5 | public InventoryNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/exception/ProductNotFoundException.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.exception;
2 |
3 | public class ProductNotFoundException extends RuntimeException {
4 |
5 | public ProductNotFoundException(String message) {
6 | super(message);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/external/InventoryClientService.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.external;
2 |
3 |
4 | import com.example.product_service.dto.inventoryDto.InventoryRequestDto;
5 | import com.example.product_service.dto.inventoryDto.InventoryResponseDto;
6 | import com.example.product_service.dto.inventoryDto.InventoryUpdateRequestDto;
7 | import com.example.product_service.model.Inventory;
8 | import org.springframework.cloud.openfeign.FeignClient;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | @FeignClient(name = "INVENTORY-SERVICE")
12 | public interface InventoryClientService {
13 |
14 |
15 | @PostMapping("/api/v1/inventories/create")
16 | InventoryResponseDto addInventory(@RequestBody InventoryRequestDto inventoryRequestDto);
17 |
18 | @GetMapping("/api/v1/inventories/{productId}")
19 | Inventory getInventoryByProductId(@PathVariable("productId") String productId);
20 |
21 | @PutMapping("/api/v1/inventories/{inventoryId}")
22 | InventoryResponseDto updateInventory(@PathVariable("inventoryId") String inventoryId, @RequestBody InventoryUpdateRequestDto inventoryUpdateRequestDto);
23 |
24 | @DeleteMapping("/api/v1/inventories/{productId}")
25 | void deleteInventory(@PathVariable("productId") String productId);
26 |
27 | @GetMapping("/api/v1/inventories/getInventoryId/{id}")
28 | Inventory getInventoryById(@PathVariable String id);
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/model/Inventory.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.model;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.io.Serializable;
9 |
10 | @Data
11 | @NoArgsConstructor
12 | @AllArgsConstructor
13 | @Builder
14 | public class Inventory implements Serializable {
15 |
16 | private String id;
17 | private String productId;
18 | private int stockQuantity;
19 | }
20 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/model/Product.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.model;
2 |
3 | import com.example.product_service.enums.Category;
4 | import jakarta.persistence.*;
5 | import lombok.AllArgsConstructor;
6 | import lombok.Builder;
7 | import lombok.Data;
8 | import lombok.NoArgsConstructor;
9 | import org.hibernate.annotations.UuidGenerator;
10 |
11 | import java.io.Serializable;
12 | import java.time.LocalDateTime;
13 |
14 | @Entity
15 | @Table(name = "products")
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | @Builder
20 | public class Product implements Serializable {
21 |
22 | @Id
23 | @GeneratedValue
24 | @UuidGenerator
25 | private String id;
26 |
27 | private String inventoryId;
28 |
29 | private String name;
30 |
31 | @Column(name = "image_url")
32 | private String imageUrl;
33 |
34 | private String description;
35 |
36 | @Enumerated(EnumType.STRING)
37 | private Category category = Category.DİĞER;
38 |
39 | private double price;
40 |
41 | private LocalDateTime createdDate;
42 |
43 | private Inventory inventory;
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/repository/ProductRepository.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.repository;
2 |
3 | import com.example.product_service.enums.Category;
4 | import com.example.product_service.model.Product;
5 | import org.springframework.data.jpa.repository.JpaRepository;
6 | import org.springframework.stereotype.Repository;
7 |
8 | import java.util.List;
9 | import java.util.Optional;
10 |
11 | @Repository
12 | public interface ProductRepository extends JpaRepository {
13 | Optional findByInventoryId(String inventoryId);
14 |
15 | List findByCategory(Category category);
16 | }
--------------------------------------------------------------------------------
/product-service/src/main/java/com/example/product_service/util/ProductMessage.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service.util;
2 |
3 | public class ProductMessage {
4 | public static final String PRODUCT_NOT_FOUND = "PRODUCT NOT FOUND WITH ID : ";
5 | public static final String INVENTORY_NOT_FOUND = "INVENTORY NOT FOUND WITH ID : ";
6 | public static final String SERVICE_UNAVAILABLE_EXCEPTION = "THE SYSTEM IS TEMPORARILY OUT OF SERVICE";
7 | }
8 |
--------------------------------------------------------------------------------
/product-service/src/test/java/com/example/product_service/ProductServiceApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.product_service;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 | import org.springframework.boot.test.mock.mockito.MockBean;
6 |
7 | @SpringBootTest
8 | class ProductServiceApplicationTests {
9 |
10 | @Test
11 | void contextLoads() {
12 | }
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/service-registry/.gitignore:
--------------------------------------------------------------------------------
1 | HELP.md
2 | target/
3 | !.mvn/wrapper/maven-wrapper.jar
4 | !**/src/main/**/target/
5 | !**/src/test/**/target/
6 |
7 | ### STS ###
8 | .apt_generated
9 | .classpath
10 | .factorypath
11 | .project
12 | .settings
13 | .springBeans
14 | .sts4-cache
15 |
16 | ### IntelliJ IDEA ###
17 | .idea
18 | *.iws
19 | *.iml
20 | *.ipr
21 |
22 | ### NetBeans ###
23 | /nbproject/private/
24 | /nbbuild/
25 | /dist/
26 | /nbdist/
27 | /.nb-gradle/
28 | build/
29 | !**/src/main/**/build/
30 | !**/src/test/**/build/
31 |
32 | ### VS Code ###
33 | .vscode/
34 |
--------------------------------------------------------------------------------
/service-registry/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # https://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing,
12 | # software distributed under the License is distributed on an
13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | # KIND, either express or implied. See the License for the
15 | # specific language governing permissions and limitations
16 | # under the License.
17 | wrapperVersion=3.3.2
18 | distributionType=only-script
19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.7/apache-maven-3.9.7-bin.zip
20 |
--------------------------------------------------------------------------------
/service-registry/Dockerfile:
--------------------------------------------------------------------------------
1 | #Kullanılacak temel imajı belirtir.
2 | FROM openjdk:17-jdk
3 |
4 | # Uygulama için bir çalışma dizini oluşturun
5 | # sonraki tüm komutlar bu dizin içerisinde çalışacaktır
6 | #düzen sağlar.
7 | WORKDIR /app
8 |
9 | #Derleme zamanı değişken tanımlama target altında .jar uzantılı dosyaları barındırır.
10 | ARG JAR_FILE=target/*.jar
11 |
12 | # JAR dosyasını Docker imajına kopyalıyoruz ve isimlendiriyoruz
13 |
14 | COPY ${JAR_FILE} service-registry-0.0.1-SNAPSHOT.jar
15 |
16 | #Uygulamanın çalıştırılması için gerekli komutu belirtir.
17 | ENTRYPOINT ["java","-jar","service-registry-0.0.1-SNAPSHOT.jar"]
18 |
19 | #BAĞLANTI NOKTASINI AÇIĞA ÇIKARMA
20 | EXPOSE 8761
21 |
22 | #docker build -t my-spring-boot-app .
23 | #docker run -p 8761:8761 my-spring-boot-app
--------------------------------------------------------------------------------
/service-registry/src/main/java/com/example/service/registry/ServiceRegistryApplication.java:
--------------------------------------------------------------------------------
1 | package com.example.service.registry;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
6 |
7 | @SpringBootApplication
8 | @EnableEurekaServer
9 | public class ServiceRegistryApplication {
10 |
11 | public static void main(String[] args) {
12 | SpringApplication.run(ServiceRegistryApplication.class, args);
13 | }
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/service-registry/src/main/resources/application.properties:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orhanturkmenoglu/ecommerce-microservices-springboot/6b9128ff359b6599573b79defdd2f869f796fc0e/service-registry/src/main/resources/application.properties
--------------------------------------------------------------------------------
/service-registry/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8761
3 |
4 | spring:
5 | application:
6 | name: SERVICE-REGISTRY
7 |
8 | eureka:
9 | instance:
10 | hostname: localhost
11 |
12 | client:
13 | register-with-eureka: false
14 | fetch-registry: false
15 |
16 |
--------------------------------------------------------------------------------
/service-registry/src/test/java/com/example/service/registry/ServiceRegistryApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.example.service.registry;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class ServiceRegistryApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/uploads/69deca89-3ada-49a7-a61d-7ecd70a1ac78.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/orhanturkmenoglu/ecommerce-microservices-springboot/6b9128ff359b6599573b79defdd2f869f796fc0e/uploads/69deca89-3ada-49a7-a61d-7ecd70a1ac78.jpg
--------------------------------------------------------------------------------