- Refactor ActivateClubMembershipCommandHandler to use UserPackagePurchases instead of UserOrders for package activation.
- Modify PlaceOrderCommandHandler to redirect payment callbacks to the front office.
- Update ChargeDiscountWalletCommandHandler and ChargeMagicWalletCommandHandler to direct payment callbacks to the front office.
- Remove PaymentCallbackController and integrate payment verification directly into DiscountOrderService and UserWalletService.
- Add CustomerVerifyDiscountOrderPayment RPC to DiscountOrderService for verifying discount order payments.
- Implement VerifyMagicCharge and VerifyDiscountCharge methods in UserWalletService for wallet charge verifications.
- Update appsettings.json to use local URLs for development.
- Remove appsettings.Development.json as it is no longer needed.
- Comment out history tracking methods in ClubMembershipCycle and Package classes.
- Update PackageService to automatically activate club membership after successful payment verification.
- Adjust UserService to generate JWT tokens with user details.
- PackageService: build callback URL from FrontOfficeBaseUrl config instead of request.CallbackUrl
- TransactionsService: same fix — callback URL from config
- Prevents potential open redirect vulnerability (user could send arbitrary URL)
All callback URLs now come from appsettings FrontOfficeBaseUrl or CmsBaseUrl.
- PaymentCallbackController: fix redirect paths /magic-wallet → /profile/magic-wallet
- Add appsettings.Development.json with local CmsBaseUrl (localhost:32846) and FrontOfficeBaseUrl (localhost:5268)
- Proto: fix comments ریال → تومان in wallet charge messages
Root cause: CmsBaseUrl in appsettings.json points to stage (cms.se.kbs1.ir),
so when testing locally, ZarinPal callback went to stage CMS instead of local.
Also redirect after verify used wrong FO path (/magic-wallet instead of /profile/magic-wallet).
- PackageService.CustomerVerifyPackagePurchase: look up PaymentTransaction.Amount and pass to 3-arg overload
- TransactionsService.CustomerPaymentVerification: same fix
- VerifyDiscountWalletChargeCommandHandler: look up amount from PaymentTransaction
- VerifyPackagePurchaseCommandHandler: fix copy-paste bug (Authority as verificationToken) + add amount
- IPaymentGatewayService: throw NotImplementedException in default 3-arg impl to prevent silent amount=0
- MockPaymentGatewayService & DayaPaymentService: add 3-arg overload for compatibility
Root cause: ZarinPal requires the exact amount in verify request.
The 2-arg overload was sending amount=0 which caused Code=-1 (تأیید تراکنش ناموفق).
F2: اضافه شدن packageName به SmsTemplates، IUserNotificationService، UserNotificationService
- DayaLoan، ClubActivated، CommissionDeposited حالا نام پکیج را نشان میدهند
F4: اضافه شدن ستون پکیج به CSV خروجیها
- commission.proto: package_name در WithdrawalRequestModel
- manualpayment.proto: package_name در ManualPaymentModel
- کوئریهندلرها UserPackagePurchases لوکاپ اضافه شد
F6: مقادیر داینامیک کیفپول جادویی از پکیج
- userwallet.proto: magic_multiplier + magic_max_credit
- UserWalletService: پاپیولیت فیلدهای جدید + فالبک به SystemConstants
F7: ولیدیتورها از SystemConstants استفاده میکنند
- WalletMaxSafeAmount (10B ریال) به عنوان حصار ایمنی
- MagicWalletMinCharge، DiscountWalletMinCharge ثابتهای مرکزی
- سقف واقعی per-package در هندلرها اعمال میشود
Proto: v0.0.189
- Proto: add package_id filter to 4 request messages, package_id/package_title to 4 response models
- Queries: add PackageId filter to GetUserWeeklyBalances, GetUserCommissionPayouts, GetMyCommissionPayouts, GetMyWeeklyBalances
- Handlers: include Package navigation, filter by PackageId, map PackageId/PackageTitle
- DTOs: add PackageId + PackageTitle to all response models
- Mappings: update CommissionProfile with PackageId/PackageTitle for all admin+customer mappings
- NuGet: bump proto version to 0.0.187
- CustomerPurchasePackage: append orderId to callback URL before sending to gateway
- Ensures PaymentCallback page receives orderId via query string for verification
- Mark PurchaseGoldenPackage/VerifyGoldenPackagePurchase RPCs as deprecated
- Mark InitiateBasePackagePayment/VerifyBasePackagePayment RPCs as deprecated
- Remove deprecated SystemConstants from GetAllAsDict/GetAllWithDescriptions helpers
- Add MagicWallet per-package values to ConfigurationService (Multiplier, MaxDeposit, MaxCredit)
- All deprecated constants have zero active code usages — safe dead code
- ActivateClubMembership: Load Package, set First/Last fields, PackageId on Cycle+Pool
- AcceptClubMembershipContract: Load Package, set First/Last fields, PackageId on Pool
- CalculateWeeklyBalances: Load base package, use package.MaxBalancesPerLeg/MaxNetworkLevel, set PackageId on NetworkWeeklyBalance
- ProcessUserPayouts: Load base package, use package.MaxNetworkLevel, set PackageId on UserCommissionPayout
- CheckAndProcessDayaLoans: Load base package (IsBasePackage), replace DayaLoanAmount→package.Price, fix hardcoded p.Id==4
- CreateManualPayment: Load base package, replace BasePackageAmount→package.Price, use DiscountMultiplier
- InitiateBasePackagePayment: Remove hardcoded BasePackageId=4, load from IsBasePackage, use package.Price/Id
- VerifyBasePackagePayment: Load Package from order.PackageId, use package.Price+DiscountMultiplier
- ChargeMagicWallet: Load user's package from current cycle, use package.MagicWalletMaxDeposit
- VerifyMagicWalletCharge: Load user's package, use package.MagicWalletMultiplier/MagicWalletMaxDeposit
- OrmCommissionCalculationStrategy: Load base package in both methods, set PackageId on Balance+Payout
- ConfigurationService: Inject IApplicationDbContext, read package values from DB instead of SystemConstants
- UserOrderService: Load user's package for EXIT trigger MagicWalletMaxDeposit check
- UserWalletService: Load user's package for GetMagicWalletStatus display
All 9 deprecated SystemConstants now have ZERO usages outside SystemConstants.cs
Build: 0 errors, 521 warnings (all pre-existing)
B6: PackagePurchaseMethod was NOT reset when exiting Magic Mode.
This caused Guards G1-G3 to permanently block re-purchase.
Changes:
- user.PackagePurchaseMethod = None (allows re-purchase via G1-G3)
- currentCycle.IsCurrentCycle = false (ready for new cycle)
Note: membership.IsActive is intentionally preserved (Q19 — contract is one-time).
Features are preserved — DIFF will be applied on next purchase (Q20).
B1: VerifyGoldenPackagePurchase — DiscountBalance was NOT charged (Amount × 2)
Now charges DiscountBalance same as all other handlers.
B2: VerifyGoldenPackagePurchase — UserPackagePurchase record was NOT created
Now creates UPP with OrderId and TransactionId.
B3: VerifyPackagePurchase — UserPackagePurchase record was NOT created
Now creates UPP after wallet charge.
B4: VerifyBasePackagePayment — UserPackagePurchase record was NOT created
Now creates UPP after wallet change log.
Also: VerifyGolden WalletChangeLog split into 2 logs (Balance + Discount)
to match the pattern used by VerifyPackagePurchase.
Transaction description changed from 'پکیج طلایی' to 'پکیج' (generic).
Impact: Only Daya Loan handler was creating UserPackagePurchase before.
Now all 4 payment paths create it consistently.
Bug: when buying from discount shop, DiscountBalance was deducted from DB
but no UserWalletChangeLog was created — making it invisible in wallet history.
Same issue existed for discount wallet top-up (charge).
Fixed in 3 handlers:
- PlaceOrderCommandHandler (fully paid by discount balance path)
- CompleteOrderPaymentCommandHandler (gateway + discount balance path)
- VerifyDiscountWalletChargeCommandHandler (discount wallet charge)
- userwallet.proto: added string user_name = 5 to GetAllUserWalletByFilterResponseModel
- UserWalletService: enriches response with user names from Users table
- Proto version bumped to 0.0.183
- ActivateClubMembershipCommandHandler: block activation in Magic mode
- CheckAndProcessDayaLoansCommandHandler: reject Daya after first cycle
- userwallet.proto: add purchase_cycle_count to GetMagicWalletStatusResponse
- UserWalletService: query ClubMembershipCycles count for cycle info
- EF Migration u21: ClubMembershipCycle table + UserWallet Magic fields
- Added ClubMembershipCycle entity and DbSet to IApplicationDbContext.
- Updated VAT rate from 9% to 10% in VatCalculator and related areas.
- Introduced Magic Wallet settings in SystemConstants.
- Enhanced UserWallet entity to support Magic Wallet features.
- Updated TransactionType enum to include Magic Wallet transactions.
- Configured UserWallet to handle Magic Wallet properties in ApplicationDbContext.
- Implemented OrmCommissionCalculationStrategy to exclude Magic Wallet users from commission calculations.
- Added Protobuf definitions for Magic Wallet methods and responses.
- Created PaymentCallbackController endpoint for handling Magic Wallet charge callbacks.
- Updated UserOrderService to manage Magic Wallet state transitions.
- Developed UserWalletService to support Magic Wallet operations.
- Created ChargeMagicWalletCommand and its handler for initiating Magic Wallet charges.
- Implemented VerifyMagicWalletChargeCommand and handler for payment verification.
- Added validation for ChargeMagicWalletCommand.
- Established ClubMembershipCycle configuration for EF Core.
- Introduced WalletMode enum to differentiate between Normal and Magic modes.