feat(payment): add manual credit charge functionality and update related components
Build and Deploy to Kubernetes / build-and-deploy (push) Has been cancelled
Build and Deploy to Kubernetes / build-and-deploy (push) Has been cancelled
- Introduced new manual credit charge endpoints in ADMIN-SERVICES.md. - Updated ReportLabels.cs and LedgerTransactions.razor to include manual credit wallet charge options. - Enhanced NavMenu.razor with a link to the manual credit charges page. - Bumped Foursat.CMSMicroservice.Protobuf version to 0.0.205 for compatibility with new features.
This commit is contained in:
@@ -167,6 +167,8 @@
|
|||||||
|---|-------------|---------------|-----------------|--------|
|
|---|-------------|---------------|-----------------|--------|
|
||||||
| 11.1 | `UserWalletContract.GetAllUserWalletByFilter` | `UserWalletContract` | `/wallets` | لیست کیف پول کاربران |
|
| 11.1 | `UserWalletContract.GetAllUserWalletByFilter` | `UserWalletContract` | `/wallets` | لیست کیف پول کاربران |
|
||||||
| 11.2 | `UserWalletHistoryContract.GetAllUserWalletHistoryByFilter` | `UserWalletHistoryContract` | `/wallets` (تب تاریخچه) | لاگ تغییرات کیف پول |
|
| 11.2 | `UserWalletHistoryContract.GetAllUserWalletHistoryByFilter` | `UserWalletHistoryContract` | `/wallets` (تب تاریخچه) | لاگ تغییرات کیف پول |
|
||||||
|
| 11.3 | `UserWalletContract.AdminManualCreditCharge` | `UserWalletContract` | `/payment/manual-credit-charges` | شارژ دستی کیف پول اصلی (Balance) |
|
||||||
|
| 11.4 | `UserWalletContract.GetManualCreditCharges` | `UserWalletContract` | `/payment/manual-credit-charges` | لیست شارژهای دستی (Type=17) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@
|
|||||||
<ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />
|
<ProjectReference Include="../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Condition="!Exists('../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj')">
|
<ItemGroup Condition="!Exists('../../../CMS/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj')">
|
||||||
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.203" />
|
<PackageReference Include="Foursat.CMSMicroservice.Protobuf" Version="0.0.205" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- ============================================================ -->
|
<!-- ============================================================ -->
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public static class ReportLabels
|
|||||||
TransactionType.MagicWalletDeposit => "واریز کیف جادویی",
|
TransactionType.MagicWalletDeposit => "واریز کیف جادویی",
|
||||||
TransactionType.MagicWalletBonus => "بونوس کیف جادویی",
|
TransactionType.MagicWalletBonus => "بونوس کیف جادویی",
|
||||||
TransactionType.CreditWalletCharge => "شارژ کیف اصلی",
|
TransactionType.CreditWalletCharge => "شارژ کیف اصلی",
|
||||||
|
TransactionType.ManualCreditWalletCharge => "شارژ دستی کیف اصلی",
|
||||||
_ => type?.ToString() ?? "—"
|
_ => type?.ToString() ?? "—"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
@using BackOffice.Pages.AutoComplete
|
||||||
|
@using CMSMicroservice.Protobuf.Protos.UserWallet
|
||||||
|
|
||||||
|
@inject UserWalletContract.UserWalletContractClient WalletClient
|
||||||
|
|
||||||
|
<MudDialog>
|
||||||
|
<DialogContent>
|
||||||
|
<MudStack Spacing="3">
|
||||||
|
<MudAlert Severity="Severity.Warning" Dense="true" Variant="Variant.Outlined">
|
||||||
|
مبلغ مستقیماً به کیف پول اصلی (Balance) کاربر اضافه میشود و در دفتر مالی با نوع «شارژ دستی کیف اصلی» ثبت میگردد.
|
||||||
|
</MudAlert>
|
||||||
|
|
||||||
|
<UserAutoComplete Label="کاربر" @bind-SelectedUserId="_userId" />
|
||||||
|
|
||||||
|
<MudNumericField T="long" @bind-Value="_amount"
|
||||||
|
Label="مبلغ (تومان)"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Min="10000"
|
||||||
|
HelperText="حداقل ۱۰,۰۰۰ تومان" />
|
||||||
|
|
||||||
|
<MudTextField T="string" @bind-Value="_note"
|
||||||
|
Label="توضیحات ادمین (اختیاری)"
|
||||||
|
Variant="Variant.Outlined"
|
||||||
|
Lines="2" />
|
||||||
|
</MudStack>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<MudButton OnClick="Cancel" Disabled="_isSubmitting">انصراف</MudButton>
|
||||||
|
<MudButton Color="Color.Primary" Variant="Variant.Filled"
|
||||||
|
OnClick="Submit" Disabled="_isSubmitting || !_userId.HasValue || _amount < 10000">
|
||||||
|
@if (_isSubmitting)
|
||||||
|
{
|
||||||
|
<MudProgressCircular Size="Size.Small" Indeterminate="true" Class="mr-2" />
|
||||||
|
}
|
||||||
|
ثبت شارژ
|
||||||
|
</MudButton>
|
||||||
|
</DialogActions>
|
||||||
|
</MudDialog>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[CascadingParameter] IMudDialogInstance MudDialog { get; set; } = default!;
|
||||||
|
|
||||||
|
private long? _userId;
|
||||||
|
private long _amount = 10000;
|
||||||
|
private string? _note;
|
||||||
|
private bool _isSubmitting;
|
||||||
|
|
||||||
|
private void Cancel() => MudDialog.Cancel();
|
||||||
|
|
||||||
|
private async Task Submit()
|
||||||
|
{
|
||||||
|
if (!_userId.HasValue || _userId.Value <= 0)
|
||||||
|
{
|
||||||
|
Snackbar.Add("لطفاً کاربر را انتخاب کنید", Severity.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_amount < 10000)
|
||||||
|
{
|
||||||
|
Snackbar.Add("حداقل مبلغ شارژ ۱۰,۰۰۰ تومان است", Severity.Warning);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool? confirm = await DialogService.ShowMessageBox(
|
||||||
|
"تأیید شارژ دستی",
|
||||||
|
$"آیا از شارژ {_amount:N0} تومان به کیف پول اصلی کاربر #{_userId.Value} مطمئن هستید؟",
|
||||||
|
yesText: "بله، شارژ شود", cancelText: "لغو");
|
||||||
|
|
||||||
|
if (confirm != true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_isSubmitting = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var request = new AdminManualCreditChargeRequest
|
||||||
|
{
|
||||||
|
UserId = _userId.Value,
|
||||||
|
Amount = _amount
|
||||||
|
};
|
||||||
|
if (!string.IsNullOrWhiteSpace(_note))
|
||||||
|
request.Note = _note.Trim();
|
||||||
|
|
||||||
|
var response = await WalletClient.AdminManualCreditChargeAsync(request);
|
||||||
|
|
||||||
|
if (response.Success)
|
||||||
|
{
|
||||||
|
Snackbar.Add(
|
||||||
|
$"شارژ موفق — تراکنش #{response.TransactionId}، موجودی جدید: {response.NewBalance:N0}",
|
||||||
|
Severity.Success);
|
||||||
|
MudDialog.Close(DialogResult.Ok(true));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Snackbar.Add(response.Message ?? "شارژ ناموفق بود", Severity.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Snackbar.Add($"خطا: {ex.Message}", Severity.Error);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_isSubmitting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,6 +44,7 @@
|
|||||||
<MudSelectItem T="TransactionType?" Value="TransactionType.MagicWalletDeposit">واریز کیف جادویی</MudSelectItem>
|
<MudSelectItem T="TransactionType?" Value="TransactionType.MagicWalletDeposit">واریز کیف جادویی</MudSelectItem>
|
||||||
<MudSelectItem T="TransactionType?" Value="TransactionType.MagicWalletBonus">بونوس کیف جادویی</MudSelectItem>
|
<MudSelectItem T="TransactionType?" Value="TransactionType.MagicWalletBonus">بونوس کیف جادویی</MudSelectItem>
|
||||||
<MudSelectItem T="TransactionType?" Value="TransactionType.CreditWalletCharge">شارژ کیف اصلی</MudSelectItem>
|
<MudSelectItem T="TransactionType?" Value="TransactionType.CreditWalletCharge">شارژ کیف اصلی</MudSelectItem>
|
||||||
|
<MudSelectItem T="TransactionType?" Value="TransactionType.ManualCreditWalletCharge">شارژ دستی کیف اصلی</MudSelectItem>
|
||||||
</MudSelect>
|
</MudSelect>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="12" sm="6" md="4">
|
<MudItem xs="12" sm="6" md="4">
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
@page "/payment/manual-credit-charges"
|
||||||
|
@attribute [Authorize(Roles = "Administrator")]
|
||||||
|
|
||||||
|
@using BackOffice.Common.BaseComponents
|
||||||
|
@using BackOffice.Pages.AutoComplete
|
||||||
|
@using BackOffice.Pages.Payment.Components
|
||||||
|
@using CMSMicroservice.Protobuf.Protos
|
||||||
|
@using CMSMicroservice.Protobuf.Protos.UserWallet
|
||||||
|
@using DateTimeConverterCL
|
||||||
|
@using Google.Protobuf.WellKnownTypes
|
||||||
|
|
||||||
|
@inject UserWalletContract.UserWalletContractClient WalletClient
|
||||||
|
|
||||||
|
<BasePageComponent @ref="_basePage" OnSubmitClick="OnFilterSubmit" OnClearFilterClick="OnFilterCleared">
|
||||||
|
<Filters>
|
||||||
|
<MudItem xs="12">
|
||||||
|
<MudAlert Severity="Severity.Info" Variant="Variant.Text" Dense="true">
|
||||||
|
شارژ دستی کیف پول اصلی (Balance) — بدون درگاه. جدا از «پرداختهای دستی» عضویت باشگاه.
|
||||||
|
</MudAlert>
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3">
|
||||||
|
<UserAutoComplete Label="جستجوی کاربر" @bind-SelectedUserId="_userIdFilter" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3">
|
||||||
|
<MudTextField T="long?" Label="شناسه تراکنش" Variant="Variant.Outlined"
|
||||||
|
Margin="Margin.Dense" @bind-Value="_transactionIdFilter" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="3">
|
||||||
|
<MudTextField T="string" Label="RefId" Variant="Variant.Outlined"
|
||||||
|
Margin="Margin.Dense" @bind-Value="_refIdFilter" />
|
||||||
|
</MudItem>
|
||||||
|
<MudItem xs="12" sm="6" md="4">
|
||||||
|
<DateRangePicker @bind-From="_createdFrom" @bind-To="_createdTo" Label="بازه ثبت" />
|
||||||
|
</MudItem>
|
||||||
|
</Filters>
|
||||||
|
<Content>
|
||||||
|
<MudDataGrid @ref="_dataGrid" T="ManualCreditChargeModel"
|
||||||
|
ServerData="LoadData"
|
||||||
|
Hover="true" Dense="true"
|
||||||
|
Height="calc(100vh - 240px)">
|
||||||
|
<ToolBarContent>
|
||||||
|
<MudText Typo="Typo.subtitle1">شارژ دستی کیف پول اصلی</MudText>
|
||||||
|
<MudSpacer />
|
||||||
|
<MudButton Variant="Variant.Filled" Color="Color.Primary" Size="Size.Small"
|
||||||
|
StartIcon="@Icons.Material.Filled.Add" OnClick="OpenCreateDialog">
|
||||||
|
شارژ دستی جدید
|
||||||
|
</MudButton>
|
||||||
|
</ToolBarContent>
|
||||||
|
<Columns>
|
||||||
|
<PropertyColumn Property="x => x.TransactionId" Title="شناسه تراکنش" />
|
||||||
|
<PropertyColumn Property="x => x.UserId" Title="شناسه کاربر" />
|
||||||
|
<PropertyColumn Property="x => x.UserName" Title="نام کاربر" />
|
||||||
|
<PropertyColumn Property="x => x.Amount" Title="مبلغ">
|
||||||
|
<CellTemplate>
|
||||||
|
@context.Item.Amount.ToString("N0")
|
||||||
|
</CellTemplate>
|
||||||
|
</PropertyColumn>
|
||||||
|
<PropertyColumn Property="x => x.NewBalance" Title="موجودی بعد از شارژ">
|
||||||
|
<CellTemplate>
|
||||||
|
@context.Item.NewBalance.ToString("N0")
|
||||||
|
</CellTemplate>
|
||||||
|
</PropertyColumn>
|
||||||
|
<PropertyColumn Property="x => x.RefId" Title="RefId" />
|
||||||
|
<PropertyColumn Property="x => x.Description" Title="توضیحات" />
|
||||||
|
<TemplateColumn Title="تاریخ">
|
||||||
|
<CellTemplate>
|
||||||
|
@(context.Item.Created?.ToDateTime().ToLocalTime().MiladiToJalaliWithTime() ?? "-")
|
||||||
|
</CellTemplate>
|
||||||
|
</TemplateColumn>
|
||||||
|
</Columns>
|
||||||
|
<NoRecordsContent>
|
||||||
|
<MudAlert Severity="Severity.Info" Dense="true" Variant="Variant.Text" Class="my-4">موردی یافت نشد.</MudAlert>
|
||||||
|
</NoRecordsContent>
|
||||||
|
<PagerContent>
|
||||||
|
<MudDataGridPager T="ManualCreditChargeModel" PageSizeOptions="@(new int[] { 20, 50, 100 })"
|
||||||
|
InfoFormat="سطر {first_item} تا {last_item} از {all_items}"
|
||||||
|
RowsPerPageString="تعداد در صفحه" />
|
||||||
|
</PagerContent>
|
||||||
|
</MudDataGrid>
|
||||||
|
</Content>
|
||||||
|
</BasePageComponent>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
private BasePageComponent? _basePage;
|
||||||
|
private MudDataGrid<ManualCreditChargeModel>? _dataGrid;
|
||||||
|
private long? _userIdFilter;
|
||||||
|
private long? _transactionIdFilter;
|
||||||
|
private string? _refIdFilter;
|
||||||
|
private DateTime? _createdFrom;
|
||||||
|
private DateTime? _createdTo;
|
||||||
|
|
||||||
|
private async Task<GridData<ManualCreditChargeModel>> LoadData(GridState<ManualCreditChargeModel> state)
|
||||||
|
{
|
||||||
|
var request = new GetManualCreditChargesRequest
|
||||||
|
{
|
||||||
|
PaginationState = new PaginationState
|
||||||
|
{
|
||||||
|
PageNumber = state.Page + 1,
|
||||||
|
PageSize = state.PageSize
|
||||||
|
},
|
||||||
|
Filter = new GetManualCreditChargesFilter()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_userIdFilter.HasValue)
|
||||||
|
request.Filter.UserId = _userIdFilter.Value;
|
||||||
|
if (_transactionIdFilter.HasValue)
|
||||||
|
request.Filter.TransactionId = _transactionIdFilter.Value;
|
||||||
|
if (!string.IsNullOrWhiteSpace(_refIdFilter))
|
||||||
|
request.Filter.RefId = _refIdFilter.Trim();
|
||||||
|
if (_createdFrom.HasValue)
|
||||||
|
request.Filter.CreatedFrom = Timestamp.FromDateTime(DateTime.SpecifyKind(_createdFrom.Value, DateTimeKind.Utc));
|
||||||
|
if (_createdTo.HasValue)
|
||||||
|
request.Filter.CreatedTo = Timestamp.FromDateTime(DateTime.SpecifyKind(_createdTo.Value, DateTimeKind.Utc));
|
||||||
|
|
||||||
|
var response = await WalletClient.GetManualCreditChargesAsync(request);
|
||||||
|
|
||||||
|
return new GridData<ManualCreditChargeModel>
|
||||||
|
{
|
||||||
|
Items = response.Models.ToList(),
|
||||||
|
TotalItems = (int)(response.MetaData?.TotalCount ?? 0)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnFilterSubmit()
|
||||||
|
{
|
||||||
|
if (_dataGrid != null)
|
||||||
|
await _dataGrid.ReloadServerData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnFilterCleared()
|
||||||
|
{
|
||||||
|
_userIdFilter = null;
|
||||||
|
_transactionIdFilter = null;
|
||||||
|
_refIdFilter = null;
|
||||||
|
_createdFrom = null;
|
||||||
|
_createdTo = null;
|
||||||
|
if (_dataGrid != null)
|
||||||
|
await _dataGrid.ReloadServerData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OpenCreateDialog()
|
||||||
|
{
|
||||||
|
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true };
|
||||||
|
var dialog = DialogService.Show<ManualCreditChargeDialog>("شارژ دستی کیف پول اصلی", options);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
if (result is { Canceled: false } && _dataGrid != null)
|
||||||
|
await _dataGrid.ReloadServerData();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -200,6 +200,12 @@
|
|||||||
</MudNavLink>
|
</MudNavLink>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
<MudNavLink Match="NavLinkMatch.Prefix"
|
||||||
|
Href="/payment/manual-credit-charges"
|
||||||
|
Icon="@Icons.Material.Filled.AddCard">
|
||||||
|
شارژ دستی کیف پول
|
||||||
|
</MudNavLink>
|
||||||
|
|
||||||
<MudNavLink Match="NavLinkMatch.Prefix"
|
<MudNavLink Match="NavLinkMatch.Prefix"
|
||||||
Href="/payment/transactions"
|
Href="/payment/transactions"
|
||||||
Icon="@Icons.Material.Filled.ReceiptLong">
|
Icon="@Icons.Material.Filled.ReceiptLong">
|
||||||
|
|||||||
Reference in New Issue
Block a user