Merge kub-stage into production
Build and Deploy to Production / build-and-deploy (push) Successful in 11m49s
Build and Deploy to Production / build-and-deploy (push) Successful in 11m49s
- Resolved appsettings.Production.json conflict (new MerchantId, SeedWorkers) - Removed duplicate u21 migration (kept 155925 from production) - All features: Magic Wallet, Discount Wallet, StockMovement fix, FullInformation expansion, Wallet user_name, gateway activation
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.DiscountShopCQ.Commands.CompleteOrderPayment;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -186,4 +187,63 @@ public class PaymentCallbackController : ControllerBase
|
||||
return Redirect($"{frontOfficeBaseUrl}/magic-wallet?payment=failed");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback برای شارژ کیفپول تخفیفی — زرینپال بعد از پرداخت کاربر را اینجا برمیگرداند
|
||||
/// </summary>
|
||||
[HttpGet("/api/wallet/verify-discount-charge")]
|
||||
public async Task<IActionResult> DiscountChargeCallback(
|
||||
[FromQuery(Name = "Authority")] string? authority,
|
||||
[FromQuery(Name = "Status")] string? status,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var frontOfficeBaseUrl = _configuration["FrontOfficeBaseUrl"] ?? "https://localhost:5268";
|
||||
|
||||
_logger.LogInformation(
|
||||
"Discount charge callback received: Authority={Authority}, Status={Status}",
|
||||
authority, status);
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(authority))
|
||||
{
|
||||
_logger.LogError("Discount charge callback: Authority is missing");
|
||||
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=error&reason=no-authority");
|
||||
}
|
||||
|
||||
// پیدا کردن PaymentTransaction برای استخراج UserId و Amount
|
||||
var paymentTx = await _context.PaymentTransactions
|
||||
.FirstOrDefaultAsync(pt => pt.Authority == authority, cancellationToken);
|
||||
|
||||
if (paymentTx == null || !paymentTx.UserId.HasValue)
|
||||
{
|
||||
_logger.LogError("Discount charge callback: PaymentTransaction not found for Authority={Authority}", authority);
|
||||
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=error&reason=tx-not-found");
|
||||
}
|
||||
|
||||
if (!string.Equals(status, "OK", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_logger.LogWarning("Discount charge cancelled by user. Authority={Authority}", authority);
|
||||
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=cancelled");
|
||||
}
|
||||
|
||||
var result = await _sender.Send(new VerifyDiscountWalletChargeCommand
|
||||
{
|
||||
UserId = paymentTx.UserId.Value,
|
||||
Amount = paymentTx.Amount,
|
||||
Authority = authority
|
||||
}, cancellationToken);
|
||||
|
||||
_logger.LogInformation(
|
||||
"Discount charge completed successfully. Authority={Authority}, UserId={UserId}",
|
||||
authority, paymentTx.UserId.Value);
|
||||
|
||||
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=success");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Discount charge callback error. Authority={Authority}", authority);
|
||||
return Redirect($"{frontOfficeBaseUrl}/profile/charge-discount-wallet?payment=failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,9 @@ public class InventoryService : InventoryContract.InventoryContractBase
|
||||
Id = inventoryItem.Id,
|
||||
Quantity = Math.Abs(difference),
|
||||
FromReserved = false,
|
||||
ReferenceNumber = request.ReferenceNumber
|
||||
ReferenceNumber = request.ReferenceNumber,
|
||||
MovementType = Domain.Enums.StockMovementType.AdjustmentMinus,
|
||||
Note = "Stock adjustment (decrease)"
|
||||
},
|
||||
context.CancellationToken);
|
||||
|
||||
@@ -332,7 +334,9 @@ public class InventoryService : InventoryContract.InventoryContractBase
|
||||
Id = inventoryItem.Id,
|
||||
Quantity = request.Quantity,
|
||||
FromReserved = false,
|
||||
ReferenceNumber = request.ReferenceNumber ?? $"LOSS-{DateTime.UtcNow:yyyyMMddHHmmss}"
|
||||
ReferenceNumber = request.ReferenceNumber ?? $"LOSS-{DateTime.UtcNow:yyyyMMddHHmmss}",
|
||||
MovementType = (Domain.Enums.StockMovementType)request.LossType,
|
||||
Note = string.IsNullOrWhiteSpace(request.Reason) ? null : request.Reason
|
||||
},
|
||||
context.CancellationToken);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using CMSMicroservice.Application.UserWalletCQ.Commands.CreateNewUserWallet;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Commands.UpdateUserWallet;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Commands.DeleteUserWallet;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.ChargeMagicWallet;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.ChargeDiscountWallet;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetAllUserWalletByFilter;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletChangeLog;
|
||||
@@ -54,7 +55,28 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
|
||||
}
|
||||
public override async Task<GetAllUserWalletByFilterResponse> GetAllUserWalletByFilter(GetAllUserWalletByFilterRequest request, ServerCallContext context)
|
||||
{
|
||||
return await _dispatchRequestToCQRS.Handle<GetAllUserWalletByFilterRequest, GetAllUserWalletByFilterQuery, GetAllUserWalletByFilterResponse>(request, context);
|
||||
var response = await _dispatchRequestToCQRS.Handle<GetAllUserWalletByFilterRequest, GetAllUserWalletByFilterQuery, GetAllUserWalletByFilterResponse>(request, context);
|
||||
|
||||
// Enrich response with user names
|
||||
if (response?.Models != null && response.Models.Any())
|
||||
{
|
||||
var userIds = response.Models.Select(m => m.UserId).Distinct().ToList();
|
||||
var users = await _context.Users
|
||||
.AsNoTracking()
|
||||
.Where(u => userIds.Contains(u.Id))
|
||||
.Select(u => new { u.Id, u.FirstName, u.LastName })
|
||||
.ToDictionaryAsync(u => u.Id, context.CancellationToken);
|
||||
|
||||
foreach (var model in response.Models)
|
||||
{
|
||||
if (users.TryGetValue(model.UserId, out var user))
|
||||
{
|
||||
model.UserName = $"{user.FirstName} {user.LastName}".Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
// ============= Customer-specific Methods =============
|
||||
@@ -170,6 +192,27 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
|
||||
};
|
||||
}
|
||||
|
||||
// ============= Discount Wallet Methods =============
|
||||
|
||||
public override async Task<InitiateDiscountChargeResponse> InitiateDiscountCharge(
|
||||
InitiateDiscountChargeRequest request, ServerCallContext context)
|
||||
{
|
||||
var userId = GetCurrentUserId();
|
||||
|
||||
var result = await _sender.Send(new ChargeDiscountWalletCommand
|
||||
{
|
||||
UserId = userId,
|
||||
Amount = request.Amount
|
||||
}, context.CancellationToken);
|
||||
|
||||
return new InitiateDiscountChargeResponse
|
||||
{
|
||||
IsSuccess = result.IsSuccess,
|
||||
GatewayUrl = result.GatewayUrl ?? "",
|
||||
ErrorMessage = result.ErrorMessage ?? ""
|
||||
};
|
||||
}
|
||||
|
||||
public override async Task<GetMagicWalletStatusResponse> GetMagicWalletStatus(
|
||||
Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
|
||||
{
|
||||
@@ -181,6 +224,9 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
|
||||
if (wallet == null)
|
||||
throw new RpcException(new Status(StatusCode.NotFound, "کیف پول یافت نشد"));
|
||||
|
||||
var cycleCount = await _context.ClubMembershipCycles
|
||||
.CountAsync(c => c.UserId == userId, context.CancellationToken);
|
||||
|
||||
var response = new GetMagicWalletStatusResponse
|
||||
{
|
||||
WalletMode = (int)wallet.WalletMode,
|
||||
@@ -188,7 +234,8 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
|
||||
MagicTotalCredited = wallet.MagicTotalCredited,
|
||||
MagicMaxDeposit = SystemConstants.MagicWalletMaxDeposit,
|
||||
MagicRemainingDeposit = Math.Max(0, SystemConstants.MagicWalletMaxDeposit - wallet.MagicTotalDeposited),
|
||||
Balance = wallet.Balance
|
||||
Balance = wallet.Balance,
|
||||
PurchaseCycleCount = cycleCount
|
||||
};
|
||||
|
||||
if (wallet.MagicActivatedAt.HasValue)
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
{
|
||||
"PaymentProvider": "zarinpal",
|
||||
"ZarinPal": {
|
||||
"MerchantId": "6b098fc8-f490-47a1-aac3-1de1a1b84404",
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": false
|
||||
},
|
||||
"CmsBaseUrl": "https://cms.kbs1.ir",
|
||||
"FrontOfficeBaseUrl": "https://kbs1.ir",
|
||||
"UseRealPaymentGateway": false,
|
||||
"JwtSecurityKey": "TvlZVx5TJaHs8e9HgUdGzhGP2CIidoI444nAj+8+g7c=",
|
||||
"JwtIssuer": "https://localhost",
|
||||
"JwtAudience": "https://localhost",
|
||||
@@ -68,6 +67,11 @@
|
||||
"CronExpression": "5 0 * * 0"
|
||||
}
|
||||
},
|
||||
"SeedWorkers": {
|
||||
"MagicWalletCycleSeed": {
|
||||
"Enabled": true
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"PaymentProvider": "zarinpal",
|
||||
"ZarinPal": {
|
||||
"MerchantId": "6b098fc8-f490-47a1-aac3-1de1a1b84404",
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": true
|
||||
},
|
||||
"FMS": {
|
||||
@@ -68,6 +68,11 @@
|
||||
"CronExpression": "5 0 * * 0"
|
||||
}
|
||||
},
|
||||
"SeedWorkers": {
|
||||
"MagicWalletCycleSeed": {
|
||||
"Enabled": true
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Kestrel": {
|
||||
"EndpointDefaults": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"PaymentProvider": "zarinpal",
|
||||
"ZarinPal": {
|
||||
"MerchantId": "6b098fc8-f490-47a1-aac3-1de1a1b84404",
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": true
|
||||
},
|
||||
"CmsBaseUrl": "https://cms.kbs1.ir",
|
||||
@@ -75,6 +75,11 @@
|
||||
"CronExpression": "5 0 * * 0"
|
||||
}
|
||||
},
|
||||
"SeedWorkers": {
|
||||
"MagicWalletCycleSeed": {
|
||||
"Enabled": true
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"Authentication": {
|
||||
"Authority": "https://ids.domain.com/",
|
||||
|
||||
Reference in New Issue
Block a user