├── .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 | 6 | -------------------------------------------------------------------------------- /.idea/RestfulApiTool-Environment-Cache.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/aws.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 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 | 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 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/fastRequest/fastRequestCurrentProjectLocalConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/jpa.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 19 | 20 | 21 | 22 | 23 | 24 | 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 --------------------------------------------------------------------------------