Skip to content

Latest commit

 

History

History
310 lines (253 loc) · 8.43 KB

README.md

File metadata and controls

310 lines (253 loc) · 8.43 KB

🎯 PHASE 2: SHOPPING CART & COUPONS

✅ Mục tiêu

Xây dựng hệ thống giỏ hàng và mã giảm giá, tích hợp với ProductAPI từ Phase 1.

🧱 Thành phần

Services

  • ProductAPI: Từ Phase 1
  • ShoppingCartAPI: Quản lý giỏ hàng
  • CouponAPI: Quản lý mã giảm giá
  • SQL Server: Database cho tất cả services

Database Schema

Cart Tables:

CREATE TABLE CartHeaders (
    CartHeaderId INT PRIMARY KEY IDENTITY,
    UserId NVARCHAR(450),
    CouponCode NVARCHAR(50),
    Discount DECIMAL(18,2) DEFAULT 0,
    CreatedDate DATETIME DEFAULT GETDATE()
);

CREATE TABLE CartDetails (
    CartDetailsId INT PRIMARY KEY IDENTITY,
    CartHeaderId INT FOREIGN KEY REFERENCES CartHeaders(CartHeaderId),
    ProductId INT,
    Count INT,
    FOREIGN KEY (CartHeaderId) REFERENCES CartHeaders(CartHeaderId) ON DELETE CASCADE
);

Coupon Table:

CREATE TABLE Coupons (
    CouponId INT PRIMARY KEY IDENTITY,
    CouponCode NVARCHAR(50) UNIQUE NOT NULL,
    DiscountAmount DECIMAL(18,2) NOT NULL,
    MinAmount DECIMAL(18,2) DEFAULT 0,
    CreatedDate DATETIME DEFAULT GETDATE()
);

🔌 API Endpoints

Shopping Cart API (http://localhost:5004)

Method Endpoint Description
GET /api/cart/{userId} Lấy giỏ hàng của user
POST /api/cart/add Thêm sản phẩm vào giỏ
PUT /api/cart/update Cập nhật số lượng
DELETE /api/cart/remove/{cartDetailsId} Xóa item khỏi giỏ
POST /api/cart/apply-coupon Áp dụng mã giảm giá
DELETE /api/cart/remove-coupon/{userId} Xóa mã giảm giá

Coupon API (http://localhost:5003)

Method Endpoint Description
GET /api/coupon Lấy danh sách coupons
GET /api/coupon/{code} Lấy coupon theo code
POST /api/coupon Tạo coupon mới (Admin)
PUT /api/coupon/{id} Cập nhật coupon
DELETE /api/coupon/{id} Xóa coupon

Sample Requests

Add item to cart:

curl -X POST http://localhost:5004/api/cart/add \
  -H "Content-Type: application/json" \
  -d '{
    "cartHeader": {
      "userId": "user123"
    },
    "cartDetails": {
      "productId": 1,
      "count": 2
    }
  }'

Apply coupon:

curl -X POST http://localhost:5004/api/cart/apply-coupon \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "user123",
    "couponCode": "SAVE10"
  }'

Get coupon:

curl -X GET http://localhost:5003/api/coupon/SAVE10

🧪 Kế hoạch kiểm thử

Unit Tests

ShoppingCartService Tests:

  • ✅ Test AddToCart: Thêm item mới vào giỏ trống
  • ✅ Test AddToCart: Tăng số lượng item đã tồn tại
  • ✅ Test UpdateCartItem: Cập nhật số lượng
  • ✅ Test RemoveFromCart: Xóa item khỏi giỏ
  • ✅ Test ApplyCoupon: Áp dụng mã giảm giá hợp lệ
  • ✅ Test ApplyCoupon: Từ chối mã không hợp lệ
  • ✅ Test CalculateTotal: Tính tổng tiền đúng
  • ✅ Test CalculateTotal: Tính tổng với discount

CouponService Tests:

  • ✅ Test GetCouponByCode: Lấy coupon hợp lệ
  • ✅ Test GetCouponByCode: Return null với code không tồn tại
  • ✅ Test ValidateCoupon: Kiểm tra minimum amount
  • ✅ Test CreateCoupon: Tạo coupon mới
  • ✅ Test CreateCoupon: Duplicate code validation

Example Unit Test:

[Fact]
public async Task AddToCart_NewItem_ShouldCreateCartAndAddItem()
{
    // Arrange
    var mockRepo = new Mock<ICartRepository>();
    var mockProductService = new Mock<IProductService>();
    var service = new CartService(mockRepo.Object, mockProductService.Object);

    var product = new Product { ProductId = 1, Name = "Burger", Price = 9.99m };
    mockProductService.Setup(p => p.GetProductByIdAsync(1))
                      .ReturnsAsync(product);

    var cartDto = new CartDto
    {
        CartHeader = new CartHeaderDto { UserId = "user123" },
        CartDetails = new List<CartDetailsDto>
        {
            new CartDetailsDto { ProductId = 1, Count = 2 }
        }
    };

    // Act
    var result = await service.AddToCartAsync(cartDto);

    // Assert
    result.Should().NotBeNull();
    result.CartHeader.UserId.Should().Be("user123");
    result.CartDetails.Should().HaveCount(1);
    mockRepo.Verify(r => r.CreateCartAsync(It.IsAny<CartHeader>()), Times.Once);
}

Integration Tests

Cart Workflow Tests:

  • ✅ Test: Add product → Get cart → Verify item exists
  • ✅ Test: Add same product twice → Verify count increased
  • ✅ Test: Apply valid coupon → Verify discount applied
  • ✅ Test: Apply invalid coupon → Verify error response
  • ✅ Test: Remove item → Verify cart updated
  • ✅ Test: Empty cart → Verify all items removed

Service Integration Tests:

  • ✅ Test CartAPI calls ProductAPI to get product info
  • ✅ Test CartAPI calls CouponAPI to validate coupon
  • ✅ Test concurrent cart operations (race conditions)

Example Integration Test:

[Fact]
public async Task CartWorkflow_AddProductAndApplyCoupon_ShouldCalculateCorrectTotal()
{
    // Arrange - Add product to cart
    var addCartResponse = await _client.PostAsJsonAsync("/api/cart/add", new
    {
        CartHeader = new { UserId = "test-user" },
        CartDetails = new { ProductId = 1, Count = 2 }
    });
    addCartResponse.EnsureSuccessStatusCode();

    // Act - Apply coupon
    var applyCouponResponse = await _client.PostAsJsonAsync("/api/cart/apply-coupon", new
    {
        UserId = "test-user",
        CouponCode = "SAVE10"
    });
    applyCouponResponse.EnsureSuccessStatusCode();

    // Get cart
    var getCartResponse = await _client.GetAsync("/api/cart/test-user");
    var cart = await getCartResponse.Content.ReadFromJsonAsync<CartDto>();

    // Assert
    cart.Should().NotBeNull();
    cart.CartHeader.Discount.Should().Be(10);
    cart.CartHeader.CouponCode.Should().Be("SAVE10");
}

Performance Tests

  • ✅ Test concurrent add to cart (100 users)
  • ✅ Test cart calculation with 50 items
  • ✅ Response time < 500ms for cart operations

Test Coverage Target

  • Minimum: 75%
  • Target: 85%

🐳 Docker Setup

Build & Run

./scripts/build-phase.sh 2 v2.0
./scripts/run-phase.sh 2

Verify Services

# ProductAPI
curl http://localhost:5002/swagger

# CouponAPI
curl http://localhost:5003/swagger

# ShoppingCartAPI
curl http://localhost:5004/swagger

🌿 Git Workflow

# 1. Create branch from main
git checkout main
git pull origin main
git checkout -b phase2-cart-coupons

# 2. Development
git add .
git commit -m "feat: add CartHeader and CartDetails models"
git commit -m "feat: implement ShoppingCartAPI endpoints"
git commit -m "feat: add CouponAPI with CRUD operations"
git commit -m "feat: integrate ProductAPI with CartAPI"
git commit -m "test: add unit tests for Cart and Coupon services"
git commit -m "test: add integration tests for cart workflow"
git commit -m "docker: create Phase 2 docker-compose"

# 3. Push and create PR
git push origin phase2-cart-coupons

# 4. After merge, tag release
git checkout main
git pull origin main
git tag -a v2.0-phase2 -m "Phase 2: Shopping Cart & Coupons"
git push origin v2.0-phase2

📊 Demo Checklist

  • ProductAPI running (from Phase 1)
  • CouponAPI running với Swagger
  • ShoppingCartAPI running với Swagger
  • Tạo được coupon mới
  • Thêm được sản phẩm vào giỏ hàng
  • Áp dụng được mã giảm giá
  • Tính toán tổng tiền chính xác
  • Xóa được item khỏi giỏ hàng
  • Unit tests pass (≥ 75% coverage)
  • Integration tests pass
  • Database có 3 services hoạt động

🎓 Deliverables

  1. ✅ ShoppingCartAPI service
  2. ✅ CouponAPI service
  3. ✅ Integration with ProductAPI
  4. ✅ Database với Cart và Coupon tables
  5. ✅ Unit tests cho Cart & Coupon
  6. ✅ Integration tests cho cart workflow
  7. ✅ Docker compose Phase 2
  8. ✅ Documentation

📝 Báo cáo Phase 2

  1. Tính năng mới

    • Shopping Cart management
    • Coupon system
    • Product-Cart integration
  2. Testing results

    • Unit test coverage
    • Integration test scenarios
    • Performance test results
  3. Technical challenges

    • Service-to-service communication
    • Data consistency
    • Error handling

🚀 Next Phase

Phase 3: Authentication & Order Processing


Phase 2 Estimated Time: 2-3 tuần Difficulty: ⭐⭐⭐ (Medium)