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