feat: manual payment package-based + StockMovement constraint fix
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 7m23s

- ManualPayment: add package_id to proto, handler selects package by ID
- ManualPayment: remove manual amount input, use package price
- ManualPayment: validator now checks PackageId instead of Amount
- StockMovement: fix CHECK constraint (store negative qty for decreases)
- StockMovement: Reserved/Released don't change physical Quantity
- Proto NuGet bumped to 0.0.192
This commit is contained in:
masoodafar-web
2026-03-11 23:44:28 +03:30
parent 1a0bb83c99
commit 0e9d0cad2f
7 changed files with 113 additions and 18 deletions
@@ -14,10 +14,15 @@ public class CreateManualPaymentCommand : IRequest<long>
public long UserId { get; set; }
/// <summary>
/// مبلغ تراکنش (تومان)
/// مبلغ تراکنش (تومان) — [DEPRECATED] مبلغ از پکیج خوانده می‌شود
/// </summary>
public long Amount { get; set; }
/// <summary>
/// شناسه پکیج — اگر 0 باشد، پکیج پایه استفاده می‌شود
/// </summary>
public long PackageId { get; set; }
/// <summary>
/// نوع تراکنش دستی
/// </summary>
@@ -70,10 +70,20 @@ public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPay
throw new NotFoundException($"کیف پول کاربر {request.UserId} یافت نشد");
}
// 4. بارگذاری پکیج پایه و محاسبه مبالغ
var package = await _context.Packages
.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
?? throw new NotFoundException("پکیج پایه یافت نشد");
// 4. بارگذاری پکیج انتخاب‌شده (یا پکیج پایه اگر PackageId=0)
Domain.Entities.Package package;
if (request.PackageId > 0)
{
package = await _context.Packages
.FirstOrDefaultAsync(p => p.Id == request.PackageId && !p.IsDeleted, cancellationToken)
?? throw new NotFoundException($"پکیج با شناسه {request.PackageId} یافت نشد");
}
else
{
package = await _context.Packages
.FirstOrDefaultAsync(p => p.IsBasePackage && !p.IsDeleted, cancellationToken)
?? throw new NotFoundException("پکیج پایه یافت نشد");
}
var balanceAmount = package.Price;
var discountBalanceAmount = (long)(package.Price * package.DiscountMultiplier);
@@ -11,12 +11,10 @@ public class CreateManualPaymentCommandValidator : AbstractValidator<CreateManua
.GreaterThan(0)
.WithMessage("شناسه کاربر باید بزرگتر از صفر باشد");
// حصار ایمنی — مبلغ واقعی از پکیج کاربر خوانده می‌شود
RuleFor(x => x.Amount)
.GreaterThan(0)
.WithMessage("مبلغ باید بزرگتر از صفر باشد")
.LessThanOrEqualTo(SystemConstants.WalletMaxSafeAmount)
.WithMessage("مبلغ وارد شده بیش از حد مجاز است");
// مبلغ از پکیج خوانده می‌شود — فیلد Amount دیگر اعتبارسنجی نمی‌شود
RuleFor(x => x.PackageId)
.GreaterThanOrEqualTo(0)
.WithMessage("شناسه پکیج نامعتبر است");
RuleFor(x => x.Type)
.IsInEnum()