Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

total project restructure #81

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
45060e1
total project restructure
gkhaavik Dec 30, 2024
a6844a7
entire products module rewrite, not finished
gkhaavik Jan 2, 2025
37ccccb
Order and products services taking shape
gkhaavik Jan 2, 2025
25281fa
Application runs, but many hibernate database issues
gkhaavik Jan 3, 2025
8609b39
adding OrderApplicationService
gkhaavik Jan 3, 2025
ac14220
preparing database setup
gkhaavik Jan 3, 2025
77ff1a6
Initial database migration
gkhaavik Jan 3, 2025
9550612
start user module implementation
gkhaavik Jan 3, 2025
2de2cc7
adding UsreDomainService and cleaning up OrderDomainService
gkhaavik Jan 4, 2025
7e39667
UserDomainService implementating UserStateflow and UserValidationServ…
gkhaavik Jan 4, 2025
6bb5b14
Adding database migration for user tables
gkhaavik Jan 4, 2025
3baa76d
adding user authentication
gkhaavik Jan 4, 2025
d70af60
removing unused imports
gkhaavik Jan 4, 2025
764cd9c
adding non null annotation to JwtAuthenticationFiltern
gkhaavik Jan 4, 2025
bf7f337
fixing user authentication couldn't start application
gkhaavik Jan 4, 2025
befae66
Merge pull request #83 from Zenfulcode/80-domain-driven-design
gkhaavik Jan 4, 2025
56a0471
adding admin user creation
gkhaavik Jan 12, 2025
e3ade2f
updating user status and improving database migrations
gkhaavik Jan 12, 2025
3cf25d9
Fixing authentication and cleanup
gkhaavik Jan 12, 2025
6d6a483
fixing order creation and database error
gkhaavik Jan 12, 2025
7988df5
fixes get order by id
gkhaavik Jan 13, 2025
a7ca095
Making sure that variant id is given to an order for a product that h…
gkhaavik Jan 13, 2025
75a23ce
commented debugging
gkhaavik Jan 13, 2025
d041431
adding payment domain
gkhaavik Jan 13, 2025
2c0888a
adding payments migration
gkhaavik Jan 21, 2025
0e7a851
cleanup for PaymentStateFlow
gkhaavik Jan 25, 2025
426638a
Adding mobilepay integration v0.1 and code clean
gkhaavik Jan 27, 2025
b883727
Fixing webhook registration and code cleanup
gkhaavik Jan 29, 2025
b4ca206
Fixed .env example typo
gkhaavik Jan 29, 2025
304eb33
Fixing webhook callbacks (not changing any state yet)
gkhaavik Jan 29, 2025
f9a804e
Merge pull request #89 from Zenfulcode/80-2-restructure-payment-process
gkhaavik Jan 30, 2025
8c2bda5
Add PaymentReservedEvent and enhance payment processing with transact…
gkhaavik Jan 30, 2025
2673e89
Fixing mobilepay webhooks
gkhaavik Feb 1, 2025
13afd5e
Merge pull request #99 from Zenfulcode/80-3-mobilepay-webhook-foundation
gkhaavik Feb 1, 2025
b313b43
Refactoring event handling and adding PaymentCancelledEventHandler
gkhaavik Feb 1, 2025
a631389
Merge pull request #100 from Zenfulcode/80-4-event-handling-refactor
gkhaavik Feb 1, 2025
15e36af
Adding even types
gkhaavik Feb 2, 2025
21ecd5c
Rethinking order and payment status's and their flow
gkhaavik Feb 2, 2025
40626ce
Refactors payment and order state flows
gkhaavik Feb 2, 2025
9f9c41e
Removes debugging println
gkhaavik Feb 2, 2025
2e4fcc4
Merge pull request #101 from Zenfulcode/80-6-order-and-payment-flows-…
gkhaavik Feb 2, 2025
b5483d8
Merge branch '80-complete-project-restructure' into 80-5-payment-even…
gkhaavik Feb 2, 2025
9e87024
Minor cleanup
gkhaavik Feb 2, 2025
b0e282f
Merge pull request #102 from Zenfulcode/80-5-payment-event-handling
gkhaavik Feb 2, 2025
f0c4cf1
Successfully sending order confirmation when order has been paid for
gkhaavik Feb 2, 2025
9aacf58
adding new order notification for admin
gkhaavik Feb 4, 2025
aea7626
Merge pull request #103 from Zenfulcode/80-7-emailing-order-confirmation
gkhaavik Feb 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ deploy/
*.log

# Environment files
.env
*.env

# Documentation
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ build/

### VS Code ###
.vscode/
/deploy/.env
.env
deploy/.env
6 changes: 3 additions & 3 deletions deploy/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ DATASOURCE_USERNAME=commercifyapp
DATASOURCE_PASSWORD=password123!
STRIPE_SECRET_TEST_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_WEBHOOK_ENDPOINT=http://localhost:6091/api/v1/payments/stripe/webhooks
STRIPE_WEBHOOK_ENDPOINT=https://<insert_host>/api/v2/payments/webhooks/stripe/callback
JWT_SECRET_KEY=
[email protected]
ADMIN_PASSWORD=admin
Expand All @@ -14,8 +14,8 @@ MOBILEPAY_SUBSCRIPTION_KEY=
MOBILEPAY_MERCHANT_ID=
MOBILEPAY_API_URL=
MOBILEPAY_SYSTEM_NAME=Commercify
MOBILEPAY_WEBHOOK_CALLBACK=https://<insert_host>/api/v2/payments/webhooks/mobilepay/callback
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_HOST=smtp.ethereal.email
MAIL_PORT=587
FRONTEND_URL=http://localhost:3000
MAIL_PORT=587
7 changes: 4 additions & 3 deletions deploy/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
mysql:
image: mysql:8.0
image: mysql:9.1
container_name: commercify-mysql
environment:
- MYSQL_DATABASE=commercifydb
Expand Down Expand Up @@ -40,10 +40,11 @@ services:
- MOBILEPAY_SUBSCRIPTION_KEY=${MOBILEPAY_SUBSCRIPTION_KEY}
- MOBILEPAY_API_URL=${MOBILEPAY_API_URL}
- MOBILEPAY_SYSTEM_NAME=${MOBILEPAY_SYSTEM_NAME}
- MAIL_USERNAME=${MAIL_USERNAME}
- MAIL_PASSWORD=${MAIL_PASSWORD}
- MOBILEPAY_WEBHOOK_CALLBACK=${MOBILEPAY_WEBHOOK_CALLBACK}
- MAIL_HOST=${MAIL_HOST}
- MAIL_PORT=${MAIL_PORT}
- MAIL_USERNAME=${MAIL_USERNAME}
- MAIL_PASSWORD=${MAIL_PASSWORD}
depends_on:
mysql:
condition: service_healthy
Expand Down
20 changes: 20 additions & 0 deletions example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
DATASOURCE_URL=jdbc:mysql://localhost/commercifydb?createDatabaseIfNotExist=true
DATASOURCE_USERNAME=
DATASOURCE_PASSWORD=
STRIPE_SECRET_TEST_KEY=
STRIPE_WEBHOOK_SECRET=
JWT_SECRET_KEY=7581e8477a88733917bc3b48f683a827935a492a0bd976a59429a72f28c71fd3
ADMIN_EMAIL=<a valid email, order notification are sent here>
ADMIN_PASSWORD=commercifyadmin123!
ADMIN_ORDER_DASHBOARD=https://<admin dashboard>/admin/orders
MOBILEPAY_CLIENT_ID=
MOBILEPAY_CLIENT_SECRET=
MOBILEPAY_SUBSCRIPTION_KEY=
MOBILEPAY_MERCHANT_ID=
MOBILEPAY_API_URL=
MOBILEPAY_SYSTEM_NAME=
MOBILEPAY_WEBHOOK_CALLBACK=https://<publicdomain>/api/v2/payments/webhooks/mobilepay/callback
MAIL_HOST=smtp.gmail.com
MAIL_PORT=
MAIL_USERNAME=
MAIL_PASSWORD=
1 change: 0 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,4 @@
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
package com.zenfulcode.commercify.commercify;
package com.zenfulcode.commercify;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class CommercifyApplication {
public static void main(String[] args) {
SpringApplication.run(CommercifyApplication.class, args);
}

@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.zenfulcode.commercify.api.auth;

import com.zenfulcode.commercify.api.auth.dto.request.LoginRequest;
import com.zenfulcode.commercify.api.auth.dto.request.RefreshTokenRequest;
import com.zenfulcode.commercify.api.auth.dto.request.RegisterRequest;
import com.zenfulcode.commercify.api.auth.dto.response.AuthResponse;
import com.zenfulcode.commercify.auth.application.service.AuthenticationApplicationService;
import com.zenfulcode.commercify.auth.application.service.AuthenticationResult;
import com.zenfulcode.commercify.shared.interfaces.ApiResponse;
import com.zenfulcode.commercify.user.application.service.UserApplicationService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/v2/auth")
@RequiredArgsConstructor
public class AuthController {
private final AuthenticationApplicationService authService;
private final UserApplicationService userService;

@PostMapping("/signin")
public ResponseEntity<ApiResponse<AuthResponse>> login(
@RequestBody LoginRequest request) {
AuthenticationResult result = authService.authenticate(
request.email(),
request.password()
);

AuthResponse response = AuthResponse.from(result);
return ResponseEntity.ok(ApiResponse.success(response));
}

@PostMapping("/signup")
public ResponseEntity<ApiResponse<AuthResponse>> register(
@RequestBody RegisterRequest request) {

userService.registerUser(
request.firstName(),
request.lastName(),
request.email(),
request.password(),
request.phone()
);

// Authenticate the newly registered user
AuthenticationResult result = authService.authenticate(
request.email(),
request.password()
);

AuthResponse response = AuthResponse.from(result);
return ResponseEntity.ok(ApiResponse.success(response));
}

@PostMapping("/refresh")
public ResponseEntity<ApiResponse<AuthResponse>> refreshToken(
@RequestBody RefreshTokenRequest request) {

AuthenticationResult result = authService.refreshToken(request.refreshToken());
AuthResponse response = AuthResponse.from(result);
return ResponseEntity.ok(ApiResponse.success(response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.zenfulcode.commercify.api.auth.dto.request;

public record LoginRequest(
String email,
String password
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.zenfulcode.commercify.api.auth.dto.request;

public record RefreshTokenRequest(
String refreshToken
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.zenfulcode.commercify.api.auth.dto.request;

public record RegisterRequest(
String firstName,
String lastName,
String email,
String password,
String phone
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.zenfulcode.commercify.api.auth.dto.response;

import com.zenfulcode.commercify.auth.application.service.AuthenticationResult;
import com.zenfulcode.commercify.auth.domain.model.UserRole;

import java.util.Set;
import java.util.stream.Collectors;

public record AuthResponse(
String accessToken,
String refreshToken,
String tokenType,
String userId,
String username,
String email,
Set<String> roles
) {
public static AuthResponse from(AuthenticationResult result) {
Set<String> roles = result.user().getRoles().stream()
.map(UserRole::name)
.collect(Collectors.toSet());

return new AuthResponse(
result.accessToken(),
result.refreshToken(),
"Bearer",
result.user().getUserId(),
result.user().getUsername(),
result.user().getEmail(),
roles
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.zenfulcode.commercify.api.order;

import com.zenfulcode.commercify.api.order.dto.request.CreateOrderRequest;
import com.zenfulcode.commercify.api.order.dto.response.CreateOrderResponse;
import com.zenfulcode.commercify.api.order.dto.response.OrderDetailsResponse;
import com.zenfulcode.commercify.api.order.dto.response.PagedOrderResponse;
import com.zenfulcode.commercify.api.order.mapper.OrderDtoMapper;
import com.zenfulcode.commercify.order.application.command.CancelOrderCommand;
import com.zenfulcode.commercify.order.application.command.CreateOrderCommand;
import com.zenfulcode.commercify.order.application.dto.OrderDetailsDTO;
import com.zenfulcode.commercify.order.application.query.FindAllOrdersQuery;
import com.zenfulcode.commercify.order.application.query.FindOrdersByUserIdQuery;
import com.zenfulcode.commercify.order.application.service.OrderApplicationService;
import com.zenfulcode.commercify.order.domain.model.Order;
import com.zenfulcode.commercify.order.domain.valueobject.OrderId;
import com.zenfulcode.commercify.shared.interfaces.ApiResponse;
import com.zenfulcode.commercify.user.domain.valueobject.UserId;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/v2/orders")
@RequiredArgsConstructor
public class OrderController {
private final OrderApplicationService orderApplicationService;
private final OrderDtoMapper orderDtoMapper;

@PostMapping
public ResponseEntity<ApiResponse<CreateOrderResponse>> createOrder(
@RequestBody CreateOrderRequest request) {
CreateOrderCommand command = orderDtoMapper.toCommand(request);
OrderId orderId = orderApplicationService.createOrder(command);

CreateOrderResponse response = new CreateOrderResponse(
orderId.toString(),
"Order created successfully"
);

return ResponseEntity.ok(ApiResponse.success(response));
}

@GetMapping("/{orderId}")
public ResponseEntity<ApiResponse<OrderDetailsResponse>> getOrder(
@PathVariable String orderId) {
OrderDetailsDTO order = orderApplicationService.getOrderDetailsById(OrderId.of(orderId));
OrderDetailsResponse response = orderDtoMapper.toResponse(order);
return ResponseEntity.ok(ApiResponse.success(response));
}

@GetMapping("/user/{userId}")
@PreAuthorize("hasRole('USER') and #userId == authentication.principal.id or hasRole('ADMIN')")
public ResponseEntity<ApiResponse<PagedOrderResponse>> getOrdersByUserId(
@PathVariable String userId,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {

FindOrdersByUserIdQuery query = new FindOrdersByUserIdQuery(
UserId.of(userId),
PageRequest.of(page, size)
);

Page<Order> orders = orderApplicationService.findOrdersByUserId(query);
PagedOrderResponse response = orderDtoMapper.toPagedResponse(orders);
return ResponseEntity.ok(ApiResponse.success(response));
}

@GetMapping
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<ApiResponse<PagedOrderResponse>> getAllOrders(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {

FindAllOrdersQuery query = new FindAllOrdersQuery(PageRequest.of(page, size));
Page<Order> orders = orderApplicationService.findAllOrders(query);
PagedOrderResponse response = orderDtoMapper.toPagedResponse(orders);
return ResponseEntity.ok(ApiResponse.success(response));
}

@DeleteMapping("/{orderId}")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<ApiResponse<String>> cancelOrder(@PathVariable String orderId) {
CancelOrderCommand command = new CancelOrderCommand(OrderId.of(orderId));
orderApplicationService.cancelOrder(command);
return ResponseEntity.ok(ApiResponse.success("Order cancelled successfully"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.zenfulcode.commercify.api.order.dto.request;

public record AddressRequest(
String street,
String city,
String state,
String zipCode,
String country
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.zenfulcode.commercify.api.order.dto.request;


public record CreateOrderLineRequest(
String productId,
String variantId,
int quantity
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.zenfulcode.commercify.api.order.dto.request;

import java.util.List;

public record CreateOrderRequest(
String userId,
String currency,
CustomerDetailsRequest customerDetails,
AddressRequest shippingAddress,
AddressRequest billingAddress,
List<CreateOrderLineRequest> orderLines
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.zenfulcode.commercify.api.order.dto.request;

public record CustomerDetailsRequest(
String firstName,
String lastName,
String email,
String phone
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.zenfulcode.commercify.api.order.dto.request;

public record UpdateOrderStatusRequest(
String status
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.zenfulcode.commercify.api.order.dto.response;

public record AddressResponse(
String street,
String city,
String state,
String zipCode,
String country
) {
}
Loading