feat(web-client-tpos): connect product catalog and create to catalog-service API

This commit is contained in:
Ho Ngoc Hai
2026-02-28 05:42:52 +07:00
parent 51cc8b249c
commit 5a81fee85a
280 changed files with 415 additions and 152864 deletions

View File

@@ -149,4 +149,85 @@ public class BffDataController : ControllerBase
new { ShopId = shopId });
return Ok(resources);
}
// ═══ ADMIN-LEVEL PRODUCT ENDPOINTS ═══
/// <summary>
/// EN: Get all products across all shops (admin level).
/// VI: Lấy tất cả sản phẩm trên tất cả cửa hàng (cấp admin).
/// </summary>
[HttpGet("products")]
public async Task<IActionResult> GetAllProducts([FromQuery] Guid? shopId = null)
{
await using var conn = new NpgsqlConnection(ConnStr("catalog_service"));
var sql = @"SELECT p.id, p.name, p.price, p.sku, p.description, p.image_url,
p.is_active, pt.name as type, p.shop_id, p.created_at,
'' as category_name
FROM products p
JOIN product_types pt ON p.type_id = pt.id";
if (shopId.HasValue)
sql += " WHERE p.shop_id = @ShopId";
sql += " ORDER BY p.name";
var products = await conn.QueryAsync<dynamic>(sql, new { ShopId = shopId });
return Ok(products);
}
/// <summary>
/// EN: Get all categories across all shops (admin level).
/// VI: Lấy tất cả danh mục trên tất cả cửa hàng (cấp admin).
/// </summary>
[HttpGet("categories")]
public async Task<IActionResult> GetAllCategories([FromQuery] Guid? shopId = null)
{
await using var conn = new NpgsqlConnection(ConnStr("catalog_service"));
var sql = @"SELECT id, name, description, display_order, shop_id, parent_id, is_active
FROM categories WHERE is_active = true";
if (shopId.HasValue)
sql += " AND shop_id = @ShopId";
sql += " ORDER BY display_order, name";
var categories = await conn.QueryAsync<dynamic>(sql, new { ShopId = shopId });
return Ok(categories);
}
/// <summary>
/// EN: Create a product via BFF (writes directly to catalog DB).
/// VI: Tạo sản phẩm qua BFF (ghi trực tiếp vào catalog DB).
/// </summary>
[HttpPost("products")]
public async Task<IActionResult> CreateProduct([FromBody] CreateProductRequest req)
{
var id = Guid.NewGuid();
// EN: Map type string to type_id / VI: Chuyển type string sang type_id
var typeId = (req.Type ?? "PreparedFood") switch
{
"Physical" => 1,
"Service" => 2,
"PreparedFood" => 3,
_ => 3
};
await using var conn = new NpgsqlConnection(ConnStr("catalog_service"));
await conn.ExecuteAsync(
@"INSERT INTO products (id, shop_id, name, description, price, type_id, sku, image_url, is_active, created_at)
VALUES (@Id, @ShopId, @Name, @Description, @Price, @TypeId, @Sku, @ImageUrl, true, NOW())",
new { Id = id, req.ShopId, req.Name, req.Description, req.Price, TypeId = typeId, req.Sku, req.ImageUrl });
return CreatedAtAction(nameof(GetAllProducts), new { }, new { id });
}
/// <summary>
/// EN: Delete (deactivate) a product.
/// VI: Xóa (vô hiệu hóa) sản phẩm.
/// </summary>
[HttpDelete("products/{productId:guid}")]
public async Task<IActionResult> DeleteProduct(Guid productId)
{
await using var conn = new NpgsqlConnection(ConnStr("catalog_service"));
await conn.ExecuteAsync(
"UPDATE products SET is_active = false WHERE id = @Id",
new { Id = productId });
return NoContent();
}
// EN: Request DTOs / VI: DTO yêu cầu
public record CreateProductRequest(Guid ShopId, string Name, string? Description, decimal Price, string? Type, string? Sku, string? ImageUrl);
}