diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeDesktop.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeDesktop.razor
index ce967c37..2fb4f001 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeDesktop.razor
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeDesktop.razor
@@ -209,8 +209,19 @@
-
@@ -246,8 +257,19 @@
}
-
- Xác nhận đã thanh toán
+ @if (!string.IsNullOrEmpty(_paymentError))
+ {
+ @_paymentError
+ }
+
+ @if (_paymentProcessing)
+ {
+ Đang xử lý...
+ }
+ else
+ {
+ Xác nhận đã thanh toán
+ }
@@ -932,11 +954,13 @@
}
private bool _paymentProcessing;
+ private string? _paymentError;
private async Task ConfirmPayment()
{
if (_paymentProcessing) return;
_paymentProcessing = true;
+ _paymentError = null;
StateHasChanged();
_lastOrderTotal = FinalTotal;
@@ -946,16 +970,26 @@
// EN: Call API to mark order as paid (order was already created in StartPayment)
// VI: Gọi API đánh dấu đơn đã thanh toán (đơn đã được tạo ở StartPayment)
+ bool paymentSuccess = false;
try
{
if (_createdOrderId.HasValue)
{
- await DataService.PayOrderAsync(_createdOrderId.Value, ShopId, _selectedMethod);
+ // EN: Pass amountTendered for cash (required by validator), use FinalTotal for non-cash
+ // VI: Truyền amountTendered cho tiền mặt (validator yêu cầu), dùng FinalTotal cho phương thức khác
+ var amount = _selectedMethod == "cash" ? _receivedAmount : FinalTotal;
+ var result = await DataService.PayOrderWithDetailsAsync(
+ _createdOrderId.Value, ShopId, _selectedMethod, amount);
+ paymentSuccess = result?.Success ?? false;
_lastTransactionId = _createdOrderId.Value.ToString()[..8].ToUpper();
}
- else
+
+ if (!paymentSuccess)
{
- _lastTransactionId = $"POS-{DateTime.Now:yyyyMMdd}-{DateTime.Now:HHmmss}";
+ _paymentError = "Thanh toán thất bại. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
}
// EN: Redeem voucher if applied / VI: Sử dụng voucher nếu đã áp dụng
@@ -964,11 +998,12 @@
try { await DataService.RedeemVoucherAsync(_appliedVoucher.VoucherId.Value, _discountAmount); } catch { }
}
}
- catch
+ catch (Exception ex)
{
- // EN: Fallback — generate local ID if API fails
- // VI: Fallback — tạo ID local nếu API lỗi
- _lastTransactionId = $"POS-{DateTime.Now:yyyyMMdd}-{DateTime.Now:HHmmss}";
+ _paymentError = $"Lỗi thanh toán: {ex.Message}. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
}
// EN: Save to session history (in-memory for this POS session)
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeMobile.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeMobile.razor
index 49beed38..57ea4fd8 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeMobile.razor
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeMobile.razor
@@ -518,27 +518,37 @@
}
private bool _paymentProcessing;
+ private string? _paymentError;
private async Task ConfirmPayment()
{
if (_paymentProcessing) return;
_paymentProcessing = true;
+ _paymentError = null;
StateHasChanged();
_lastOrderTotal = FinalTotal;
_lastPaymentMethod = _selectedMethod;
_lastReceiptItems = _cartItems.Select(i => (i.Name, i.Qty, i.Price)).ToList();
+ bool paymentSuccess = false;
try
{
if (_createdOrderId.HasValue)
{
- await DataService.PayOrderAsync(_createdOrderId.Value, ShopId);
+ var amount = _selectedMethod == "cash" ? _receivedAmount : FinalTotal;
+ var result = await DataService.PayOrderWithDetailsAsync(
+ _createdOrderId.Value, ShopId, _selectedMethod, amount);
+ paymentSuccess = result?.Success ?? false;
_lastTransactionId = _createdOrderId.Value.ToString()[..8].ToUpper();
}
- else
+
+ if (!paymentSuccess)
{
- _lastTransactionId = $"POS-{DateTime.Now:yyyyMMdd}-{DateTime.Now:HHmmss}";
+ _paymentError = "Thanh toán thất bại. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
}
if (_appliedVoucher?.VoucherId != null && _discountAmount > 0)
@@ -546,9 +556,12 @@
try { await DataService.RedeemVoucherAsync(_appliedVoucher.VoucherId.Value, _discountAmount); } catch { }
}
}
- catch
+ catch (Exception ex)
{
- _lastTransactionId = $"POS-{DateTime.Now:yyyyMMdd}-{DateTime.Now:HHmmss}";
+ _paymentError = $"Lỗi thanh toán: {ex.Message}. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
}
_paymentProcessing = false;
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeTablet.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeTablet.razor
index 23eb0331..4eb47a59 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeTablet.razor
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Cafe/CafeTablet.razor
@@ -495,27 +495,37 @@
}
private bool _paymentProcessing;
+ private string? _paymentError;
private async Task ConfirmPayment()
{
if (_paymentProcessing) return;
_paymentProcessing = true;
+ _paymentError = null;
StateHasChanged();
_lastOrderTotal = FinalTotal;
_lastPaymentMethod = _selectedMethod;
_lastReceiptItems = _cartItems.Select(i => (i.Name, i.Qty, i.Price)).ToList();
+ bool paymentSuccess = false;
try
{
if (_createdOrderId.HasValue)
{
- await DataService.PayOrderAsync(_createdOrderId.Value, ShopId);
+ var amount = _selectedMethod == "cash" ? _receivedAmount : FinalTotal;
+ var result = await DataService.PayOrderWithDetailsAsync(
+ _createdOrderId.Value, ShopId, _selectedMethod, amount);
+ paymentSuccess = result?.Success ?? false;
_lastTransactionId = _createdOrderId.Value.ToString()[..8].ToUpper();
}
- else
+
+ if (!paymentSuccess)
{
- _lastTransactionId = $"POS-{DateTime.Now:yyyyMMdd}-{DateTime.Now:HHmmss}";
+ _paymentError = "Thanh toán thất bại. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
}
if (_appliedVoucher?.VoucherId != null && _discountAmount > 0)
@@ -523,9 +533,12 @@
try { await DataService.RedeemVoucherAsync(_appliedVoucher.VoucherId.Value, _discountAmount); } catch { }
}
}
- catch
+ catch (Exception ex)
{
- _lastTransactionId = $"POS-{DateTime.Now:yyyyMMdd}-{DateTime.Now:HHmmss}";
+ _paymentError = $"Lỗi thanh toán: {ex.Message}. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
}
_paymentProcessing = false;
diff --git a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Restaurant/RestaurantDesktop.razor b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Restaurant/RestaurantDesktop.razor
index ee6cd0dc..cc879a36 100644
--- a/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Restaurant/RestaurantDesktop.razor
+++ b/apps/web-client-tpos-net/src/WebClientTpos.Client/Pages/Pos/Restaurant/RestaurantDesktop.razor
@@ -674,10 +674,13 @@
_receivedAmount = val;
}
+ private string? _paymentError;
+
private async Task ConfirmPayment()
{
if (_paymentProcessing || SelectedTable == null) return;
_paymentProcessing = true;
+ _paymentError = null;
StateHasChanged();
_lastOrderTotal = GrandTotal;
@@ -686,10 +689,34 @@
_lastTransactionId = $"POS-{DateTime.Now:yyyyMMdd}-{DateTime.Now:HHmmss}";
// Pay all orders for this table in the backend
- if (_tableOrderIds.TryGetValue(SelectedTable.Id, out var orderIds))
+ bool allPaid = true;
+ try
{
- foreach (var orderId in orderIds)
- await DataService.PayOrderAsync(orderId, ShopId);
+ if (_tableOrderIds.TryGetValue(SelectedTable.Id, out var orderIds))
+ {
+ var amount = _selectedMethod == "cash" ? _receivedAmount : GrandTotal;
+ foreach (var orderId in orderIds)
+ {
+ var result = await DataService.PayOrderWithDetailsAsync(
+ orderId, ShopId, _selectedMethod, amount);
+ if (result?.Success != true) allPaid = false;
+ }
+ }
+
+ if (!allPaid)
+ {
+ _paymentError = "Thanh toán thất bại. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
+ }
+ }
+ catch (Exception ex)
+ {
+ _paymentError = $"Lỗi thanh toán: {ex.Message}. Vui lòng thử lại.";
+ _paymentProcessing = false;
+ StateHasChanged();
+ return;
}
_paymentProcessing = false;