refactor: update user address models and methods to use CustomerAddressModel across multiple components
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 3m8s

This commit is contained in:
masoodafar-web
2026-02-08 00:25:12 +03:30
parent eab978188a
commit 081b9d3c10
14 changed files with 218 additions and 105 deletions
+2 -1
View File
@@ -11,7 +11,8 @@
<ItemGroup>
<PackageReference Include="DateTimeConverterCL" Version="1.0.0" />
<!-- Replace all FrontOffice.BFF protobuf packages with CMS protobuf -->
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.176" />
<!--<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.177" />-->
<ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />
<PackageReference Include="MudBlazor" Version="8.14.0" />
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="Mapster" Version="7.4.0" />
+5 -5
View File
@@ -21,8 +21,8 @@ public partial class Checkout
[Parameter] public long? PackageId { get; set; }
private Pack? _selectedPackage;
private List<GetAllUserAddressByFilterResponseModel> _addresses = new();
private GetAllUserAddressByFilterResponseModel? _selectedAddress;
private List<CustomerAddressModel> _addresses = new();
private CustomerAddressModel? _selectedAddress;
private bool _isLoadingAddresses;
private bool _isProcessingPayment;
@@ -77,7 +77,7 @@ public partial class Checkout
_isLoadingAddresses = true;
try
{
var response = await UserAddressContract.GetAllUserAddressByFilterAsync(request: new());
var response = await UserAddressContract.GetCustomerAddressesAsync(request: new());
if (response?.Models?.Any() == true)
{
_addresses = response.Models.ToList();
@@ -86,13 +86,13 @@ public partial class Checkout
}
else
{
_addresses = new List<GetAllUserAddressByFilterResponseModel>();
_addresses = new List<CustomerAddressModel>();
}
}
catch (Exception ex)
{
Snackbar.Add($"خطا در بارگذاری آدرس‌ها: {ex.Message}", Severity.Error);
_addresses = new List<GetAllUserAddressByFilterResponseModel>();
_addresses = new List<CustomerAddressModel>();
}
finally
{
@@ -56,19 +56,6 @@
<MudAlert Severity="Severity.Warning" Variant="Variant.Outlined">
<MudText>شما هنوز عضو باشگاه مشتریان نیستید. برای استفاده از مزایای ویژه، اکنون فعال کنید!</MudText>
</MudAlert>
@if (_clubConfig != null)
{
<MudPaper Elevation="0" Class="pa-3 mt-3 rounded-lg" Style="background-color: var(--mud-palette-info-lighten);">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<MudStack Spacing="1">
<MudText Typo="Typo.subtitle2" Color="Color.Info">هزینه عضویت در باشگاه مشتریان</MudText>
<MudText Typo="Typo.caption">شامل @((_clubConfig.MembershipGiftValue / 10000).ToString("N0")) تومان هدیه</MudText>
</MudStack>
<MudText Typo="Typo.h6" Color="Color.Info">@((_clubConfig.ActivationFee / 10000).ToString("N0")) تومان</MudText>
</MudStack>
</MudPaper>
}
}
</MudStack>
</MudPaper>
@@ -103,11 +90,6 @@
</MudStack>
</MudPaper>
<!-- فعال‌سازی یا تمدید عضویت -->
@if (!_membership.IsActive || (_membership.DaysRemaining.HasValue && _membership.DaysRemaining.Value <= 30))
{
<ActivationSection OnActivationSuccess="HandleActivationSuccess" />
}
<!-- دکمه مشاهده ویژگی‌های بیشتر -->
<MudButton Variant="Variant.Outlined"
@@ -10,7 +10,7 @@ public partial class Addresses : ComponentBase
{
[Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!;
private List<GetAllUserAddressByFilterResponseModel> _addresses = new();
private List<CustomerAddressModel> _addresses = new();
private bool _isLoadingAddresses;
protected override async Task OnInitializedAsync()
@@ -23,7 +23,7 @@ public partial class Addresses : ComponentBase
_isLoadingAddresses = true;
try
{
var response = await UserAddressContract.GetAllUserAddressByFilterAsync(new());
var response = await UserAddressContract.GetCustomerAddressesAsync(new());
_addresses = response?.Models?.ToList() ?? new();
}
catch (Exception ex)
@@ -45,7 +45,7 @@ public partial class Addresses : ComponentBase
await LoadAddresses();
}
private async Task OpenEditAddressDialog(GetAllUserAddressByFilterResponseModel address)
private async Task OpenEditAddressDialog(CustomerAddressModel address)
{
var dialog = await DialogService.ShowAsync<EditAddressDialog>("ویرایش آدرس", new DialogParameters<EditAddressDialog>
{
@@ -60,7 +60,7 @@ public partial class Addresses : ComponentBase
{
try
{
await UserAddressContract.SetAddressAsDefaultAsync(new() { Id = id });
await UserAddressContract.SetCustomerDefaultAddressAsync(new() { Id = id });
Snackbar.Add("آدرس پیش‌فرض تغییر کرد.", Severity.Success);
await LoadAddresses();
}
@@ -77,7 +77,7 @@ public partial class Addresses : ComponentBase
{
try
{
await UserAddressContract.DeleteUserAddressAsync(new() { Id = id });
await UserAddressContract.DeleteCustomerAddressAsync(new() { Id = id });
Snackbar.Add("آدرس حذف شد.", Severity.Success);
await LoadAddresses();
}
@@ -16,7 +16,7 @@ public partial class AddAddressDialog : ComponentBase
private MudForm? _form;
private bool _isSaving;
private CreateNewUserAddressRequest _request = new();
private CreateCustomerAddressRequest _request = new();
private object? _selectedCity;
private async Task<IEnumerable<object>> SearchCities(string value, CancellationToken ct)
@@ -56,7 +56,7 @@ public partial class AddAddressDialog : ComponentBase
_isSaving = true;
try
{
var response = await UserAddressContract.CreateNewUserAddressAsync(_request);
var response = await UserAddressContract.CreateCustomerAddressAsync(_request);
Snackbar.Add("آدرس با موفقیت اضافه شد.", Severity.Success);
MudDialog.Close(DialogResult.Ok(true));
}
@@ -13,11 +13,11 @@ public partial class EditAddressDialog : ComponentBase
[Inject] private UserAddressContract.UserAddressContractClient UserAddressContract { get; set; } = default!;
[Inject] private CityContract.CityContractClient CityContract { get; set; } = default!;
[Parameter] public GetAllUserAddressByFilterResponseModel? Model { get; set; }
[Parameter] public CustomerAddressModel? Model { get; set; }
private MudForm? _form;
private bool _isSaving;
private UpdateUserAddressRequest _request = new();
private UpdateCustomerAddressRequest _request = new();
private object? _selectedCity;
protected override async Task OnInitializedAsync()
@@ -25,7 +25,7 @@ public partial class EditAddressDialog : ComponentBase
await base.OnInitializedAsync();
if (Model != null)
{
_request = Model.Adapt<UpdateUserAddressRequest>();
_request = Model.Adapt<UpdateCustomerAddressRequest>();
// Load selected city if CityId exists
if (Model.CityId > 0)
@@ -90,7 +90,7 @@ public partial class EditAddressDialog : ComponentBase
_isSaving = true;
try
{
await UserAddressContract.UpdateUserAddressAsync(_request);
await UserAddressContract.UpdateCustomerAddressAsync(_request);
Snackbar.Add("آدرس با موفقیت ویرایش شد.", Severity.Success);
MudDialog.Close(DialogResult.Ok(true));
}
@@ -46,7 +46,7 @@ public partial class Index
private bool _isProcessingPayment;
// Address management
private List<GetAllUserAddressByFilterResponseModel> _addresses = new();
private List<CustomerAddressModel> _addresses = new();
private bool _isLoadingAddresses;
private CreateNewUserAddressRequest _newAddressRequest = new();
private UpdateUserAddressRequest _editAddressRequest = new();
@@ -251,20 +251,20 @@ public partial class Index
_isLoadingAddresses = true;
try
{
var response = await UserAddressContract.GetAllUserAddressByFilterAsync(request: new());
var response = await UserAddressContract.GetCustomerAddressesAsync(request: new());
if (response?.Models?.Any() == true)
{
_addresses = response.Models.ToList();
}
else
{
_addresses = new List<GetAllUserAddressByFilterResponseModel>();
_addresses = new List<CustomerAddressModel>();
}
}
catch (Exception ex)
{
Snackbar.Add($"خطا در بارگذاری آدرس‌ها: {ex.Message}", Severity.Error);
_addresses = new List<GetAllUserAddressByFilterResponseModel>();
_addresses = new List<CustomerAddressModel>();
}
finally
{
@@ -284,7 +284,7 @@ public partial class Index
}
}
private async Task OpenEditAddressDialog(GetAllUserAddressByFilterResponseModel address)
private async Task OpenEditAddressDialog(CustomerAddressModel address)
{
var dialog = await DialogService.ShowAsync<EditAddressDialog>("ویرایش آدرس", new DialogParameters<EditAddressDialog>
{
+81 -17
View File
@@ -12,20 +12,20 @@
<MudGrid Spacing="2">
<MudItem xs="12" sm="6" md="4">
<MudPaper Elevation="2" Class="pa-4 rounded-lg">
<MudText Typo="Typo.subtitle2" Class="mud-text-secondary">موجودی اعتباری</MudText>
<MudText Typo="Typo.subtitle2" Class="mud-text-secondary">موجودی عادی</MudText>
<MudText Typo="Typo.h4" Color="Color.Primary">@_balances.Credit</MudText>
</MudPaper>
</MudItem>
<MudItem xs="12" sm="6" md="4">
<MudPaper Elevation="2" Class="pa-4 rounded-lg">
<MudText Typo="Typo.subtitle2" Class="mud-text-secondary">موجودی فروشگاه تخفیفی</MudText>
<MudText Typo="Typo.h4" Color="Color.Warning">@_balances.Discount</MudText>
<MudText Typo="Typo.subtitle2" Class="mud-text-secondary">موجودی شبکه</MudText>
<MudText Typo="Typo.h4" Color="Color.Success">@_balances.Network</MudText>
</MudPaper>
</MudItem>
<MudItem xs="12" sm="6" md="4">
<MudPaper Elevation="2" Class="pa-4 rounded-lg">
<MudText Typo="Typo.subtitle2" Class="mud-text-secondary">موجودی پاداش تیمی</MudText>
<MudText Typo="Typo.h4" Color="Color.Success">@_balances.Network</MudText>
<MudText Typo="Typo.subtitle2" Class="mud-text-secondary">موجودی تخفیفی</MudText>
<MudText Typo="Typo.h4" Color="Color.Warning">@_balances.Discount</MudText>
</MudPaper>
</MudItem>
</MudGrid>
@@ -71,18 +71,45 @@
</MudGrid>
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert="true">
<MudTable Items="_txs" Dense="true">
<MudTable Items="_txs" Dense="true" Hover="true" Striped="true">
<HeaderContent>
<MudTh>تاریخ</MudTh>
<MudTh>مبلغ</MudTh>
<MudTh>مسیر</MudTh>
<MudTh>عادی (تغییرات / مانده)</MudTh>
<MudTh>شبکه (تغییرات / مانده)</MudTh>
<MudTh>تخفیفی (تغییرات / مانده)</MudTh>
<MudTh>شناسه ارجاع</MudTh>
<MudTh>توضیحات</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.Date</MudTd>
<MudTd Color="@(context.Amount > 0 ? Color.Success : Color.Error)">@FormatPrice(context.Amount)</MudTd>
<MudTd>@context.Channel</MudTd>
<MudTd>@context.Description</MudTd>
<MudTd DataLabel="تاریخ">
<MudText Typo="Typo.caption">@context.Date</MudText>
</MudTd>
<MudTd DataLabel="عادی">
<MudStack Spacing="0">
<MudText Color="@(context.CreditChange > 0 ? Color.Success : context.CreditChange < 0 ? Color.Error : Color.Default)" Typo="Typo.body2">
@(context.CreditChange != 0 ? (context.CreditChange > 0 ? "+" : "") + FormatPrice(context.CreditChange) : "-")
</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary">@FormatPrice(context.CreditBalance)</MudText>
</MudStack>
</MudTd>
<MudTd DataLabel="شبکه">
<MudStack Spacing="0">
<MudText Color="@(context.NetworkChange > 0 ? Color.Success : context.NetworkChange < 0 ? Color.Error : Color.Default)" Typo="Typo.body2">
@(context.NetworkChange != 0 ? (context.NetworkChange > 0 ? "+" : "") + FormatPrice(context.NetworkChange) : "-")
</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary">@FormatPrice(context.NetworkBalance)</MudText>
</MudStack>
</MudTd>
<MudTd DataLabel="تخفیفی">
<MudStack Spacing="0">
<MudText Color="@(context.DiscountChange > 0 ? Color.Success : context.DiscountChange < 0 ? Color.Error : Color.Default)" Typo="Typo.body2">
@(context.DiscountChange != 0 ? (context.DiscountChange > 0 ? "+" : "") + FormatPrice(context.DiscountChange) : "-")
</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary">@FormatPrice(context.DiscountBalance)</MudText>
</MudStack>
</MudTd>
<MudTd DataLabel="شناسه">@context.Channel</MudTd>
<MudTd DataLabel="توضیحات">@context.Description</MudTd>
</RowTemplate>
</MudTable>
</MudHidden>
@@ -91,13 +118,50 @@
<MudStack Spacing="2">
@foreach (var tx in _txs)
{
<MudPaper Class="pa-3 rounded-lg" Outlined="true">
<MudStack Spacing="1">
<MudPaper Class="pa-3 rounded-lg" Outlined="true" Elevation="1">
<MudStack Spacing="2">
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<MudText>@tx.Date</MudText>
<MudText Color="@(tx.Amount > 0 ? Color.Success : Color.Error)">@FormatPrice(tx.Amount)</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary">@tx.Date</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary">شناسه: @tx.Channel</MudText>
</MudStack>
<MudText Typo="Typo.caption" Class="mud-text-secondary">@tx.Channel</MudText>
<MudDivider />
<MudStack Row="true" Spacing="2" Justify="Justify.SpaceBetween">
<!-- کیف پول عادی -->
<MudPaper Class="pa-2 flex-grow-1" Outlined="true">
<MudStack Spacing="1" AlignItems="AlignItems.Center">
<MudText Typo="Typo.caption" Color="Color.Primary">عادی</MudText>
<MudText Color="@(tx.CreditChange > 0 ? Color.Success : tx.CreditChange < 0 ? Color.Error : Color.Default)" Style="font-weight: 600; font-size: 0.75rem;">
@(tx.CreditChange != 0 ? (tx.CreditChange > 0 ? "+" : "") + FormatPrice(tx.CreditChange) : "-")
</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary" Style="font-size: 0.7rem;">@FormatPrice(tx.CreditBalance)</MudText>
</MudStack>
</MudPaper>
<!-- کیف پول شبکه -->
<MudPaper Class="pa-2 flex-grow-1" Outlined="true">
<MudStack Spacing="1" AlignItems="AlignItems.Center">
<MudText Typo="Typo.caption" Color="Color.Success">شبکه</MudText>
<MudText Color="@(tx.NetworkChange > 0 ? Color.Success : tx.NetworkChange < 0 ? Color.Error : Color.Default)" Style="font-weight: 600; font-size: 0.75rem;">
@(tx.NetworkChange != 0 ? (tx.NetworkChange > 0 ? "+" : "") + FormatPrice(tx.NetworkChange) : "-")
</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary" Style="font-size: 0.7rem;">@FormatPrice(tx.NetworkBalance)</MudText>
</MudStack>
</MudPaper>
<!-- کیف پول تخفیفی -->
<MudPaper Class="pa-2 flex-grow-1" Outlined="true">
<MudStack Spacing="1" AlignItems="AlignItems.Center">
<MudText Typo="Typo.caption" Color="Color.Warning">تخفیفی</MudText>
<MudText Color="@(tx.DiscountChange > 0 ? Color.Success : tx.DiscountChange < 0 ? Color.Error : Color.Default)" Style="font-weight: 600; font-size: 0.75rem;">
@(tx.DiscountChange != 0 ? (tx.DiscountChange > 0 ? "+" : "") + FormatPrice(tx.DiscountChange) : "-")
</MudText>
<MudText Typo="Typo.caption" Class="mud-text-secondary" Style="font-size: 0.7rem;">@FormatPrice(tx.DiscountBalance)</MudText>
</MudStack>
</MudPaper>
</MudStack>
<MudText Typo="Typo.body2">@tx.Description</MudText>
</MudStack>
</MudPaper>
@@ -16,8 +16,8 @@ public partial class CheckoutSummary : ComponentBase
[Inject] private UserOrderContract.UserOrderContractClient UserOrderContract { get; set; } = default!;
// Snackbar and Navigation are injected via _Imports.razor
private List<GetAllUserAddressByFilterResponseModel> _addresses = new();
private GetAllUserAddressByFilterResponseModel? _selectedAddress;
private List<CustomerAddressModel> _addresses = new();
private CustomerAddressModel? _selectedAddress;
private bool _loadingAddresses;
private long walletBalance;
@@ -56,7 +56,7 @@ public partial class CheckoutSummary : ComponentBase
_loadingAddresses = true;
try
{
var response = await UserAddressContract.GetAllUserAddressByFilterAsync(new());
var response = await UserAddressContract.GetCustomerAddressesAsync(new());
if (response?.Models?.Any() == true)
{
_addresses = response.Models.ToList();
@@ -24,9 +24,15 @@ else
<MudPaper Elevation="2" Class="pa-4 rounded-lg">
<MudStack Spacing="2">
<MudText Typo="Typo.h5">سفارش #@_order.Id</MudText>
<MudText Typo="Typo.body2" Class="mud-text-secondary">تاریخ: @_order.PaymentDate.ToDateTime().MiladiToJalaliWithTime()</MudText>
@if (_order.PaymentDate != null)
{
<MudText Typo="Typo.body2" Class="mud-text-secondary">تاریخ پرداخت: @_order.PaymentDate.ToDateTime().MiladiToJalaliWithTime()</MudText>
}
else
{
<MudText Typo="Typo.body2" Class="mud-text-secondary">تاریخ ثبت: @DateTime.Now.MiladiToJalaliWithTime()</MudText>
}
<MudText Typo="Typo.body2">وضعیت: @GetStatusText(_order.PaymentStatus)</MudText>
<MudText Typo="Typo.body2">روش پرداخت: @GetPaymentMethodText(_order.PaymentMethod)</MudText>
<MudText Typo="Typo.body2">آدرس: @_order.UserAddressText</MudText>
<MudDivider Class="my-2" />
<MudHidden Breakpoint="Breakpoint.MdAndUp" Invert="true">
@@ -42,12 +48,12 @@ else
<MudStack Row="true" Spacing="2" AlignItems="AlignItems.Center">
<MudImage Src="@GetProductImageUrl(context.ProductThumbnailPath)" Alt="@context.ProductTitle"
Width="60" Height="60" Class="rounded-circle" />
<MudText>@context.ProductThumbnailPath</MudText>
<MudText>@context.ProductTitle</MudText>
</MudStack>
</MudTd>
<MudTd>@FormatPrice(context.UnitPrice.Value)</MudTd>
<MudTd>@FormatPrice(context.UnitPrice ?? 0)</MudTd>
<MudTd>@context.Count</MudTd>
<MudTd>@FormatPrice(context.UnitPrice.Value*context.Count.Value)</MudTd>
<MudTd>@FormatPrice((context.UnitPrice ?? 0) * (context.Count ?? 0))</MudTd>
</RowTemplate>
</MudTable>
</MudHidden>
@@ -64,10 +70,10 @@ else
<MudText>@it.ProductTitle</MudText>
</MudStack>
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText Class="mud-text-secondary">@FormatPrice(it.UnitPrice.Value) واحد</MudText>
<MudText Class="mud-text-secondary">@FormatPrice(it.UnitPrice ?? 0) واحد</MudText>
<MudText>تعداد: @it.Count</MudText>
</MudStack>
<MudText>جمع: @FormatPrice(it.UnitPrice.Value*it.Count.Value)</MudText>
<MudText>جمع: @FormatPrice((it.UnitPrice ?? 0) * (it.Count ?? 0))</MudText>
</MudStack>
</MudPaper>
}
@@ -77,7 +83,7 @@ else
@* نمایش جزئیات مالی *@
@{
var subtotal = _order.FactorDetails.Sum(s => s.UnitPrice.Value * s.Count.Value);
var subtotal = _order.FactorDetails.Sum(s => (s.UnitPrice ?? 0) * (s.Count ?? 0));
}
<MudStack Spacing="1" Class="pa-2" Style="background-color: var(--mud-palette-background-grey); border-radius: 8px;">
<MudStack Row="true" Justify="Justify.SpaceBetween">
+22 -4
View File
@@ -28,9 +28,18 @@
</HeaderContent>
<RowTemplate>
<MudTd>@context.Id</MudTd>
<MudTd>@context.PaymentDate.ToDateTime().MiladiToJalaliWithTime()</MudTd>
<MudTd>
@if (context.PaymentDate != null)
{
@context.PaymentDate.ToDateTime().MiladiToJalaliWithTime()
}
else
{
<text>در انتظار پرداخت</text>
}
</MudTd>
<MudTd>@GetStatusText(context.PaymentStatus)</MudTd>
<MudTd>@FormatPrice(context.FactorDetails.Sum(s=>s.UnitPrice.Value*s.Count.Value))</MudTd>
<MudTd>@FormatPrice(context.FactorDetails.Sum(s=>(s.UnitPrice ?? 0) * (s.Count ?? 0)))</MudTd>
<MudTd>
<MudButton Variant="Variant.Text" Href="@($"{RouteConstants.Store.OrderDetail}{context.Id}")" StartIcon="@Icons.Material.Filled.Receipt">جزئیات</MudButton>
</MudTd>
@@ -46,11 +55,20 @@
<MudStack Spacing="1">
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText>سفارش #@o.Id</MudText>
<MudText Class="mud-text-secondary">@o.PaymentDate.ToDateTime().MiladiToJalaliWithTime()</MudText>
<MudText Class="mud-text-secondary">
@if (o.PaymentDate != null)
{
@o.PaymentDate.ToDateTime().MiladiToJalaliWithTime()
}
else
{
<text>در انتظار پرداخت</text>
}
</MudText>
</MudStack>
<MudStack Row="true" Justify="Justify.SpaceBetween">
<MudText>وضعیت: @GetStatusText(o.PaymentStatus)</MudText>
<MudText Color="Color.Primary">@FormatPrice(o.FactorDetails.Sum(s=>s.UnitPrice.Value*s.Count.Value))</MudText>
<MudText Color="Color.Primary">@FormatPrice(o.FactorDetails.Sum(s=>(s.UnitPrice ?? 0) * (s.Count ?? 0)))</MudText>
</MudStack>
<MudStack Row="true" Justify="Justify.FlexEnd">
<MudButton Size="Size.Small" Variant="Variant.Outlined" Href="@($"{RouteConstants.Store.OrderDetail}{o.Id}")" StartIcon="@Icons.Material.Filled.Receipt">جزئیات</MudButton>
+11 -14
View File
@@ -71,7 +71,7 @@ public class CartService
{
if (existing is null)
{
await _client.AddNewUserCartAsync(new AddNewUserCartRequest
await _client.AddNewUserCartForCustomerAsync(new AddNewUserCartForCustomerRequest
{
ProductId = product.Id,
Count = newQuantity
@@ -80,10 +80,9 @@ public class CartService
}
else
{
await _client.UpdateUserCartAsync(new UpdateUserCartRequest
await _client.UpdateUserCartForCustomerAsync(new UpdateUserCartForCustomerRequest
{
UserCartId = existing.cartId,
CartItemId = existing.cartId,
Count = newQuantity
});
}
@@ -112,9 +111,9 @@ public class CartService
try
{
await _client.UpdateUserCartAsync(new UpdateUserCartRequest
await _client.UpdateUserCartForCustomerAsync(new UpdateUserCartForCustomerRequest
{
UserCartId = existing.cartId,
CartItemId = existing.cartId,
Count = quantity
});
}
@@ -134,11 +133,10 @@ public class CartService
try
{
// Interpret Count=0 as remove from cart
await _client.UpdateUserCartAsync(new UpdateUserCartRequest
// Use dedicated remove endpoint
await _client.RemoveUserCartForCustomerAsync(new RemoveUserCartForCustomerRequest
{
UserCartId = cartId,
Count = 0
CartItemId = cartId
});
}
catch
@@ -158,12 +156,11 @@ public class CartService
try
{
foreach (var id in productIds)
foreach (var item in productIds)
{
await _client.UpdateUserCartAsync(new UpdateUserCartRequest
await _client.RemoveUserCartForCustomerAsync(new RemoveUserCartForCustomerRequest
{
UserCartId = id,
Count = 0
CartItemId = item
});
}
}
@@ -5,15 +5,19 @@ namespace FrontOffice.Main.Utilities;
/// <summary>
/// Service for Club Membership operations
/// Connected to FrontOffice.BFF gRPC ClubMembershipCQ
/// Connected to CMS gRPC ClubMembershipCQ
/// </summary>
public class ClubMembershipService
{
private readonly ClubMembershipContract.ClubMembershipContractClient _client;
private readonly UserAuthInfo _authInfo;
public ClubMembershipService(ClubMembershipContract.ClubMembershipContractClient client)
public ClubMembershipService(
ClubMembershipContract.ClubMembershipContractClient client,
UserAuthInfo authInfo)
{
_client = client;
_authInfo = authInfo;
}
/// <summary>
@@ -24,8 +28,8 @@ public class ClubMembershipService
{
try
{
var userId = await GetCurrentUserIdAsync();
var response = await _client.GetClubMembershipAsync(new GetClubMembershipRequest { UserId = userId });
// UserId = 0 میفرستیم تا CMS از JWT بخونه
var response = await _client.GetClubMembershipAsync(new GetClubMembershipRequest { UserId = 0 });
return new ClubMembershipDto
{
UserId = response.UserId,
@@ -34,8 +38,11 @@ public class ClubMembershipService
DaysRemaining = response.DaysRemaining > 0 ? response.DaysRemaining : null
};
}
catch
catch (Exception ex)
{
// Log the error for debugging
Console.WriteLine($"GetMyMembershipAsync error: {ex.Message}");
// Return empty membership if backend is unavailable
return new ClubMembershipDto
{
@@ -59,6 +66,19 @@ public class ClubMembershipService
try
{
var userId = await GetCurrentUserIdAsync();
// Check if user is authenticated
if (userId <= 0)
{
return new ClubActivationResponseDto
{
Success = false,
Message = "کاربر احراز هویت نشده است. لطفاً ابتدا وارد شوید.",
ActivationDate = null,
AmountPaid = 0
};
}
var request = new ActivateClubMembershipRequest
{
UserId = userId,
@@ -93,10 +113,8 @@ public class ClubMembershipService
}
}
private async Task<long> GetCurrentUserIdAsync()
private Task<long> GetCurrentUserIdAsync()
{
// Get current user ID from auth service or JWT token
// This is a placeholder - should be implemented based on your auth system
return 1; // TODO: Implement proper user ID retrieval
return Task.FromResult(_authInfo.UserId);
}
}
+37 -10
View File
@@ -6,7 +6,17 @@ using Google.Protobuf.WellKnownTypes;
namespace FrontOffice.Main.Utilities;
public record WalletBalances(long CreditBalance, long DiscountBalance, long NetworkBalance);
public record WalletTransaction(string Date, long Amount, string Channel, string Description);
public record WalletTransaction(
string Date,
long CreditChange,
long CreditBalance,
long NetworkChange,
long NetworkBalance,
long DiscountChange,
long DiscountBalance,
string Channel,
string Description
);
public record WalletWithdrawal(long Id, long WeekDefinitionId, string WeekDisplayName, long Amount, int Status, int? Method, string? Iban, string Created);
public enum WithdrawalMethodClient
{
@@ -52,12 +62,19 @@ public class WalletService
request.IsIncrease = isIncrease.Value;
}
var response = await _client.GetCustomerWalletChangeLogAsync(request);
return response.Models
.Select(t => new WalletTransaction(
ResolveTransactionDate(t),
t.ChangeValue != 0 ? t.ChangeValue : t.CurrentBalance,
t.RefrenceId?.ToString() ?? "-",
ResolveDescription(t)))
.Select(log => new WalletTransaction(
ResolveTransactionDate(log),
log.ChangeValue,
log.CurrentBalance,
log.ChangeNerworkValue,
log.CurrentNetworkBalance,
log.ChangeDiscountValue,
log.CurrentDiscountBalance,
log.RefrenceId?.ToString() ?? "-",
ResolveDescription(log)
))
.OrderByDescending(t => t.Date)
.ToList();
}
@@ -74,7 +91,8 @@ public class WalletService
{
try
{
return model.CreatedAt.ToDateTime().MiladiToJalaliWithTime();
var utcDate = model.CreatedAt.ToDateTime();
return utcDate.ToLocalTime().MiladiToJalaliWithTime();
}
catch
{
@@ -87,9 +105,18 @@ public class WalletService
private static string ResolveDescription(CustomerWalletChangeLogModel model)
{
if (model.ChangeValue > 0) return "شارژ کیف پول";
if (model.ChangeValue < 0) return "برداشت/خرید";
return "تراکنش کیف پول";
var parts = new List<string>();
if (model.ChangeValue != 0)
parts.Add(model.ChangeValue > 0 ? "شارژ عادی" : "برداشت عادی");
if (model.ChangeNerworkValue != 0)
parts.Add(model.ChangeNerworkValue > 0 ? "دریافت شبکه" : "برداشت شبکه");
if (model.ChangeDiscountValue != 0)
parts.Add(model.ChangeDiscountValue > 0 ? "شارژ تخفیفی" : "خرید تخفیفی");
return parts.Count > 0 ? string.Join(" | ", parts) : "تراکنش کیف پول";
}
public async Task<bool> RequestWithdrawalAsync(long payoutId, WithdrawalMethodClient method, string? iban)