153 lines
6.3 KiB
C#
153 lines
6.3 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Npgsql;
|
|
using Dapper;
|
|
|
|
namespace WebClientTpos.Server.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/bff")]
|
|
public class BffDataController : ControllerBase
|
|
{
|
|
// EN: DB host configurable via env var (Docker: "postgres", dev: "localhost")
|
|
// VI: DB host cấu hình qua env var (Docker: "postgres", dev: "localhost")
|
|
private static readonly string _dbHost = Environment.GetEnvironmentVariable("BFF_DB_HOST") ?? "localhost";
|
|
private static readonly string _dbPort = Environment.GetEnvironmentVariable("BFF_DB_PORT") ?? "5432";
|
|
private static readonly string _dbUser = Environment.GetEnvironmentVariable("BFF_DB_USER") ?? "goodgo";
|
|
private static readonly string _dbPass = Environment.GetEnvironmentVariable("BFF_DB_PASS") ?? "goodgo_dev_2024";
|
|
|
|
private static string ConnStr(string db) =>
|
|
$"Host={_dbHost};Port={_dbPort};Database={db};Username={_dbUser};Password={_dbPass}";
|
|
|
|
[HttpGet("shops")]
|
|
public async Task<IActionResult> GetShops()
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("merchant_service"));
|
|
var shops = await conn.QueryAsync<dynamic>(
|
|
@"SELECT s.id, s.name, s.slug, s.description, s.phone, s.email,
|
|
s.open_time, s.close_time, s.features_config,
|
|
bc.name as category, st.name as status
|
|
FROM shops s
|
|
JOIN business_categories bc ON s.category_id = bc.id
|
|
JOIN shop_statuses st ON s.status_id = st.id
|
|
WHERE s.is_deleted = false
|
|
ORDER BY s.name");
|
|
return Ok(shops);
|
|
}
|
|
|
|
[HttpGet("shops/{shopId:guid}")]
|
|
public async Task<IActionResult> GetShopById(Guid shopId)
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("merchant_service"));
|
|
var shop = await conn.QueryFirstOrDefaultAsync<dynamic>(
|
|
@"SELECT s.id, s.name, s.slug, s.description, s.phone, s.email,
|
|
s.open_time, s.close_time,
|
|
bc.name as category, st.name as status
|
|
FROM shops s
|
|
JOIN business_categories bc ON s.category_id = bc.id
|
|
JOIN shop_statuses st ON s.status_id = st.id
|
|
WHERE s.id = @ShopId AND s.is_deleted = false",
|
|
new { ShopId = shopId });
|
|
|
|
if (shop == null)
|
|
return NotFound(new { message = "Shop not found" });
|
|
|
|
return Ok(shop);
|
|
}
|
|
|
|
[HttpGet("staff")]
|
|
public async Task<IActionResult> GetStaff()
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("merchant_service"));
|
|
var staff = await conn.QueryAsync<dynamic>(
|
|
@"SELECT ms.id, ms.user_id, ms.employee_code, ms.phone, ms.email,
|
|
ms.joined_at, ms.terminated_at,
|
|
sr.name as role, ss.name as status,
|
|
s.name as shop_name
|
|
FROM merchant_staff ms
|
|
JOIN staff_roles sr ON ms.role_id = sr.id
|
|
JOIN staff_statuses ss ON ms.status_id = ss.id
|
|
LEFT JOIN shop_members sm ON sm.staff_id = ms.id
|
|
LEFT JOIN shops s ON sm.shop_id = s.id
|
|
ORDER BY ms.joined_at DESC");
|
|
return Ok(staff);
|
|
}
|
|
|
|
[HttpGet("shops/{shopId}/products")]
|
|
public async Task<IActionResult> GetProducts(Guid shopId)
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("catalog_service"));
|
|
var products = await conn.QueryAsync<dynamic>(
|
|
@"SELECT id, name, price, sku, description, image_url, is_active,
|
|
attributes->>'category' as category,
|
|
(attributes->>'duration')::int as duration_minutes
|
|
FROM products
|
|
WHERE shop_id = @ShopId AND is_active = true
|
|
ORDER BY name",
|
|
new { ShopId = shopId });
|
|
return Ok(products);
|
|
}
|
|
|
|
[HttpGet("shops/{shopId}/categories")]
|
|
public async Task<IActionResult> GetCategories(Guid shopId)
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("catalog_service"));
|
|
var categories = await conn.QueryAsync<dynamic>(
|
|
@"SELECT id, name, description, display_order
|
|
FROM categories
|
|
WHERE shop_id = @ShopId AND is_active = true
|
|
ORDER BY display_order",
|
|
new { ShopId = shopId });
|
|
return Ok(categories);
|
|
}
|
|
|
|
[HttpGet("shops/{shopId}/tables")]
|
|
public async Task<IActionResult> GetTables(Guid shopId)
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("fnb_engine"));
|
|
var tables = await conn.QueryAsync<dynamic>(
|
|
@"SELECT t.id, t.table_number, t.capacity, t.zone,
|
|
CASE t.status_id
|
|
WHEN 1 THEN 'available'
|
|
WHEN 2 THEN 'occupied'
|
|
WHEN 3 THEN 'reserved'
|
|
WHEN 4 THEN 'cleaning'
|
|
END as status,
|
|
s.id as session_id, s.guest_count, s.started_at
|
|
FROM tables t
|
|
LEFT JOIN sessions s ON s.table_id = t.id AND s.status = 'Active'
|
|
WHERE t.shop_id = @ShopId
|
|
ORDER BY t.table_number",
|
|
new { ShopId = shopId });
|
|
return Ok(tables);
|
|
}
|
|
|
|
[HttpGet("shops/{shopId}/appointments")]
|
|
public async Task<IActionResult> GetAppointments(Guid shopId)
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("booking_service"));
|
|
var appointments = await conn.QueryAsync<dynamic>(
|
|
@"SELECT a.id, a.customer_id, a.staff_id, a.resource_id,
|
|
a.service_id, a.start_time, a.end_time, a.status,
|
|
r.name as resource_name
|
|
FROM appointments a
|
|
LEFT JOIN resources r ON a.resource_id = r.id
|
|
WHERE a.shop_id = @ShopId
|
|
ORDER BY a.start_time",
|
|
new { ShopId = shopId });
|
|
return Ok(appointments);
|
|
}
|
|
|
|
[HttpGet("shops/{shopId}/resources")]
|
|
public async Task<IActionResult> GetResources(Guid shopId)
|
|
{
|
|
await using var conn = new NpgsqlConnection(ConnStr("booking_service"));
|
|
var resources = await conn.QueryAsync<dynamic>(
|
|
@"SELECT id, name, resource_type, capacity, is_active
|
|
FROM resources
|
|
WHERE shop_id = @ShopId AND is_active = true
|
|
ORDER BY name",
|
|
new { ShopId = shopId });
|
|
return Ok(resources);
|
|
}
|
|
}
|