Files
CMS/src/CMSMicroservice.Infrastructure/Persistence/StoredProcedures/sp_CalculateWeeklyCommissionPool.sql
T
masoodafar-web 8518c7b3ec
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 8m9s
feat: Enhance club membership activation and commission pool validation
- Updated AcceptClubMembershipContractCommandHandler to set PackagePurchasedAt to the contract-signing time, ensuring accurate pool charging.
- Modified ActivateClubMembershipCommand to allow specifying a PackageId for forced activation, defaulting to the base package if not provided.
- Improved ActivateClubMembershipCommandHandler to handle new and existing memberships differently regarding pool charging.
- Added validation logic in GetWeeklyCommissionPoolQueryHandler to compare TotalPoolAmount against actual activations.
- Introduced validation fields in WeeklyCommissionPoolDto for tracking discrepancies and expected amounts.
- Updated stored procedures to ensure accurate calculations based on package purchases and to handle empty pools.
- Enhanced protobuf definitions to include validation fields for commission pools and network tree nodes.
- Added mapping for new fields in CommissionProfile and NetworkMembershipProfile.
- Created DiscountProductProfile for mapping discount product requests and responses.
2026-05-01 00:07:05 +03:30

282 lines
10 KiB
Transact-SQL

-- =============================================
-- Stored Procedure: sp_CalculateWeeklyCommissionPool
-- Description: محاسبه استخر کمیسیون هفتگی و توزیع بین کاربران
-- Author: System
-- Created: 2025-12-19
-- Updated: Q29 — اضافه کردن @PackageId، fix فیلتر pool، مدیریت pool خالی
-- =============================================
CREATE OR ALTER PROCEDURE [CMS].[sp_CalculateWeeklyCommissionPool]
@WeekDefinitionId BIGINT,
@PackageId BIGINT, -- هر بار به ازای یک پکیج اجرا می‌شود
@ForceRecalculate BIT = 0,
@PoolId BIGINT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @TotalPoolAmount BIGINT = 0;
DECLARE @TotalBalances INT;
DECLARE @ValuePerBalance BIGINT;
DECLARE @CalculatedAt DATETIME = GETDATE();
BEGIN TRY
BEGIN TRANSACTION;
-- =============================================
-- 1. پیدا کردن Pool هفته (فیلتر بر اساس PackageId)
-- =============================================
SELECT @PoolId = Id, @TotalPoolAmount = TotalPoolAmount
FROM CMS.WeeklyCommissionPools
WHERE WeekDefinitionId = @WeekDefinitionId AND PackageId = @PackageId;
-- اگر Pool وجود ندارد (هیچ فعال‌سازی در این هفته نبوده)، یک رکورد خالی ایجاد می‌کنیم
IF @PoolId IS NULL
BEGIN
INSERT INTO CMS.WeeklyCommissionPools (
WeekDefinitionId, PackageId, TotalPoolAmount, TotalBalances,
ValuePerBalance, IsCalculated, CalculatedAt,
IsDeleted, Created, CreatedBy, LastModified, LastModifiedBy
) VALUES (
@WeekDefinitionId, @PackageId, 0, 0, 0, 0, NULL,
0, @CalculatedAt, 'SP', @CalculatedAt, 'SP'
);
SET @PoolId = SCOPE_IDENTITY();
SET @TotalPoolAmount = 0;
END
-- =============================================
-- 2. بررسی محاسبات قبلی (بر اساس همین Pool نه کل هفته)
-- =============================================
IF EXISTS (SELECT 1 FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId)
BEGIN
IF @ForceRecalculate = 0
BEGIN
SET @ErrorMessage = N'کمیسیون هفته ' + CAST(@WeekDefinitionId AS NVARCHAR(20))
+ N' (پکیج ' + CAST(@PackageId AS NVARCHAR(20)) + N') قبلاً محاسبه شده است. برای محاسبه مجدد از ForceRecalculate استفاده کنید';
RAISERROR(@ErrorMessage, 16, 1);
RETURN;
END
-- =============================================
-- 3. Revert کیف پول‌ها (در صورت ForceRecalculate، فقط پرداخت‌های این Pool)
-- =============================================
-- کم کردن مقادیر قبلی از NetworkBalance
UPDATE uw
SET uw.NetworkBalance = uw.NetworkBalance - ISNULL(
(SELECT SUM(wl.ChangeNerworkValue)
FROM CMS.UserWalletChangeLogs wl
WHERE wl.WalletId = uw.Id
AND wl.RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId)
), 0)
FROM CMS.UserWallets uw
WHERE uw.Id IN (
SELECT DISTINCT wl.WalletId
FROM CMS.UserWalletChangeLogs wl
WHERE wl.RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId)
);
-- حذف لاگ‌های تغییرات قبلی
DELETE FROM CMS.UserWalletChangeLogs
WHERE RefrenceId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId);
-- حذف تاریخچه پرداخت
DELETE FROM CMS.CommissionPayoutHistories
WHERE UserCommissionPayoutId IN (SELECT Id FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId);
-- حذف پرداخت‌های قبلی این Pool
DELETE FROM CMS.UserCommissionPayouts WHERE WeeklyPoolId = @PoolId;
-- Reset وضعیت Pool
UPDATE CMS.WeeklyCommissionPools
SET IsCalculated = 0
WHERE Id = @PoolId;
END
-- =============================================
-- 4. بررسی وجود تعادل‌های هفتگی
-- =============================================
IF NOT EXISTS (SELECT 1 FROM CMS.NetworkWeeklyBalances WHERE WeekDefinitionId = @WeekDefinitionId)
BEGIN
-- بالانسی محاسبه نشده — pool را به عنوان "محاسبه شده بدون پرداخت" علامت می‌زنیم
UPDATE CMS.WeeklyCommissionPools
SET IsCalculated = 1, CalculatedAt = @CalculatedAt
WHERE Id = @PoolId;
COMMIT TRANSACTION;
RETURN;
END
-- =============================================
-- 5. محاسبه مجموع تعادل‌ها
-- =============================================
SELECT @TotalBalances = SUM(TotalBalances)
FROM CMS.NetworkWeeklyBalances
WHERE WeekDefinitionId = @WeekDefinitionId AND TotalBalances > 0;
IF @TotalBalances IS NULL OR @TotalBalances = 0
BEGIN
-- هیچ تعادلی برای توزیع وجود ندارد — pool محاسبه شده اما پرداختی ندارد
UPDATE CMS.WeeklyCommissionPools
SET IsCalculated = 1, CalculatedAt = @CalculatedAt
WHERE Id = @PoolId;
COMMIT TRANSACTION;
RETURN;
END
-- =============================================
-- 6. محاسبه ارزش هر تعادل
-- =============================================
SET @ValuePerBalance = @TotalPoolAmount / @TotalBalances;
-- =============================================
-- 7. ایجاد پرداخت برای هر کاربر
-- =============================================
INSERT INTO CMS.UserCommissionPayouts (
UserId,
WeekDefinitionId,
WeeklyPoolId,
BalancesEarned,
ValuePerBalance,
TotalAmount,
Status,
PaidAt,
IsDeleted,
Created,
CreatedBy,
LastModified,
LastModifiedBy
)
SELECT
nb.UserId,
@WeekDefinitionId,
@PoolId,
nb.TotalBalances,
@ValuePerBalance,
nb.TotalBalances * @ValuePerBalance,
0, -- Status: Pending
NULL, -- PaidAt
0, -- IsDeleted
@CalculatedAt,
'SP',
@CalculatedAt,
'SP'
FROM CMS.NetworkWeeklyBalances nb
WHERE nb.WeekDefinitionId = @WeekDefinitionId AND nb.TotalBalances > 0;
-- =============================================
-- 8. ثبت تاریخچه پرداخت
-- =============================================
INSERT INTO CMS.CommissionPayoutHistories (
UserCommissionPayoutId,
UserId,
WeekDefinitionId,
AmountBefore,
AmountAfter,
OldStatus,
NewStatus,
Action,
PerformedBy,
Reason,
IsDeleted,
Created,
CreatedBy,
LastModified,
LastModifiedBy
)
SELECT
cp.Id,
cp.UserId,
@WeekDefinitionId,
0,
cp.TotalAmount,
0, -- OldStatus: Pending
0, -- NewStatus: Pending
0, -- Action: Created
'SP',
N'محاسبه اولیه توسط SP',
0,
@CalculatedAt,
'SP',
@CalculatedAt,
'SP'
FROM CMS.UserCommissionPayouts cp
WHERE cp.WeeklyPoolId = @PoolId;
-- =============================================
-- 9. شارژ کیف پول کاربران
-- =============================================
-- بروزرسانی NetworkBalance
UPDATE uw
SET uw.NetworkBalance = uw.NetworkBalance + cp.TotalAmount
FROM CMS.UserWallets uw
INNER JOIN CMS.UserCommissionPayouts cp ON cp.UserId = uw.UserId
WHERE cp.WeeklyPoolId = @PoolId;
-- ثبت لاگ تغییرات کیف پول
INSERT INTO CMS.UserWalletChangeLogs (
WalletId,
CurrentBalance,
ChangeValue,
CurrentNetworkBalance,
ChangeNerworkValue,
CurrentDiscountBalance,
ChangeDiscountValue,
IsIncrease,
RefrenceId,
IsDeleted,
Created,
CreatedBy,
LastModified,
LastModifiedBy
)
SELECT
uw.Id,
uw.Balance,
0, -- ChangeValue (no change to main balance)
uw.NetworkBalance, -- CurrentNetworkBalance (after update)
cp.TotalAmount, -- ChangeNerworkValue
uw.DiscountBalance,
0, -- ChangeDiscountValue
1, -- IsIncrease: true
cp.Id, -- RefrenceId: PayoutId
0,
@CalculatedAt,
'SP',
@CalculatedAt,
'SP'
FROM CMS.UserCommissionPayouts cp
INNER JOIN CMS.UserWallets uw ON uw.UserId = cp.UserId
WHERE cp.WeeklyPoolId = @PoolId;
-- =============================================
-- 10. بروزرسانی Pool
-- =============================================
UPDATE CMS.WeeklyCommissionPools
SET
IsCalculated = 1,
CalculatedAt = @CalculatedAt,
TotalBalances = @TotalBalances,
ValuePerBalance = @ValuePerBalance,
LastModified = @CalculatedAt,
LastModifiedBy = 'SP'
WHERE Id = @PoolId;
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
SET @ErrorMessage = ERROR_MESSAGE();
RAISERROR(@ErrorMessage, 16, 1);
END CATCH
END
GO