From 5e2f20967d9f7575bf75e531847a6544e0a168fc Mon Sep 17 00:00:00 2001 From: Ho Ngoc Hai Date: Sun, 12 Apr 2026 20:46:27 +0700 Subject: [PATCH] fix(merchant): wire up merchant registration in onboarding and settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OnboardingBusiness.razor was only navigating to the next step without calling the merchant registration API, so no merchant record was ever created in the database. This caused settings page updates to fail with "Merchant not found" and the SuperAdmin panel to show zero merchants. - Inject MerchantApiService and call RegisterMerchantAsync on "Tiếp tục" - Remove hardcoded demo data from onboarding form fields - Add fallback in AdminSettings SaveMerchant to auto-register if PUT fails - Add BFF POST /api/bff/account/register-merchant endpoint Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Pages/Admin/AdminSettings.razor | 29 +++++- .../Admin/Onboarding/OnboardingBusiness.razor | 92 +++++++++++++++++-- .../Controllers/AccountController.cs | 8 ++ 3 files changed, 118 insertions(+), 11 deletions(-) diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor index 3f17b941..5d4ff2f1 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/AdminSettings.razor @@ -764,10 +764,33 @@ _saving = true; _merchantMsg = null; try { + // EN: Try to update existing merchant first + // VI: Thử cập nhật merchant hiện tại trước var ok = await DataService.PutAsync("api/bff/account/merchant", new { businessName = _businessName, taxId = _taxId }); - _merchantMsg = ok ? "Cập nhật doanh nghiệp thành công!" : "Không thể cập nhật"; - _merchantMsgOk = ok; - if (ok) _editingMerchant = false; + if (ok) + { + _merchantMsg = "Cập nhật doanh nghiệp thành công!"; + _merchantMsgOk = true; + _editingMerchant = false; + } + else + { + // EN: Merchant might not exist yet — try to register first, then update + // VI: Merchant có thể chưa tồn tại — thử đăng ký trước, rồi cập nhật + var registerOk = await DataService.PostAsync("api/bff/account/register-merchant", + new { businessName = _businessName, type = "Individual", taxId = _taxId }); + if (registerOk) + { + _merchantMsg = "Đăng ký doanh nghiệp thành công!"; + _merchantMsgOk = true; + _editingMerchant = false; + } + else + { + _merchantMsg = "Không thể cập nhật hoặc đăng ký doanh nghiệp"; + _merchantMsgOk = false; + } + } } catch (Exception ex) { _merchantMsg = ex.Message; _merchantMsgOk = false; } finally { _saving = false; } diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Onboarding/OnboardingBusiness.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Onboarding/OnboardingBusiness.razor index d39b258f..c51550f4 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Onboarding/OnboardingBusiness.razor +++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Admin/Onboarding/OnboardingBusiness.razor @@ -1,6 +1,7 @@ @page "/admin/onboarding/business" @layout AdminLayout @inherits AdminBase +@inject WebClientTpos.Client.Services.MerchantApiService MerchantApi @* EN: Onboarding Step 1 — Business info (name, type, tax ID, address, logo upload) @@ -109,10 +110,25 @@ + @if (!string.IsNullOrEmpty(_errorMsg)) + { +
+ @_errorMsg +
+ } +
-
@@ -121,13 +137,15 @@ @code { private int currentStep = 1; - private string _businessName = "aPOS Bistro"; - private string _taxId = "0312345678"; - private string _address = "123 Nguyễn Huệ, Quận 1, TP.HCM"; - private string _phone = "028 7300 1234"; - private string _email = "contact@goodgo.vn"; + private string _businessName = ""; + private string _taxId = ""; + private string _address = ""; + private string _phone = ""; + private string _email = ""; private string _businessType = "fnb"; private string _logoPlaceholder = "Chưa chọn tệp"; + private bool _saving; + private string? _errorMsg; private record StepInfo(int Index, string Label); private readonly StepInfo[] _steps = @@ -150,4 +168,62 @@ private string GetBusinessTypeLabel() => Array.Find(_businessTypes, t => t.Key == _businessType)?.Label ?? "F&B"; + + /// + /// EN: Register merchant via API, then navigate to next step. + /// VI: Đăng ký merchant qua API, sau đó chuyển sang bước tiếp theo. + /// + private async Task SaveAndContinue() + { + _errorMsg = null; + + // EN: Validate required fields + // VI: Kiểm tra trường bắt buộc + if (string.IsNullOrWhiteSpace(_businessName)) + { + _errorMsg = "Vui lòng nhập tên doanh nghiệp"; + return; + } + + _saving = true; + StateHasChanged(); + + try + { + var dto = new WebClientTpos.Shared.DTOs.MerchantRegisterDto + { + BusinessName = _businessName.Trim(), + Type = "Individual", + TaxId = string.IsNullOrWhiteSpace(_taxId) ? null : _taxId.Trim() + }; + + var (result, error) = await MerchantApi.RegisterMerchantAsync(dto); + + if (result != null) + { + // EN: Registration successful, proceed to next step + // VI: Đăng ký thành công, chuyển sang bước tiếp theo + NavigateTo("onboarding/store"); + } + else if (error != null && error.Contains("already has", StringComparison.OrdinalIgnoreCase)) + { + // EN: User already has a merchant account, just continue to next step + // VI: User đã có tài khoản merchant, tiếp tục bước tiếp theo + NavigateTo("onboarding/store"); + } + else + { + _errorMsg = error ?? "Không thể đăng ký doanh nghiệp. Vui lòng thử lại."; + } + } + catch (Exception ex) + { + _errorMsg = $"Lỗi: {ex.Message}"; + } + finally + { + _saving = false; + StateHasChanged(); + } + } } diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/AccountController.cs b/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/AccountController.cs index 413056b8..6c4a861f 100644 --- a/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/AccountController.cs +++ b/apps/web-client-tpos-net/src/WebClientTpos.Server/Controllers/AccountController.cs @@ -89,6 +89,14 @@ public class AccountController : ControllerBase public Task UpdateMerchant([FromBody] JsonElement body) => _merchant.PutAsJsonAsync("/api/v1/merchants/me", body).ProxyAsync(); + /// + /// EN: Register current user as a new merchant. + /// VI: Đăng ký user hiện tại làm merchant mới. + /// + [HttpPost("register-merchant")] + public Task RegisterMerchant([FromBody] JsonElement body) => + _merchant.PostAsJsonAsync("/api/v1/merchants/register", body).ProxyAsync(); + // ═══ SECURITY ═══ ///