feat(db): add SQL script to fix incorrect bulk credit payouts in user wallet histories
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 19m38s
Build and Deploy to Kubernetes / build-and-deploy (push) Failing after 19m38s
Introduced a new SQL script to identify and correct erroneous bulk credit entries in user wallet histories. The script allows for a dry run to preview changes before applying fixes, ensuring accurate balance adjustments and removal of incorrect records.
This commit is contained in:
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
================================================================================
|
||||
FixBulkCreditPayoutsWrongBalance.sql
|
||||
================================================================================
|
||||
شناسایی لاگ اشتباه BulkCredit در UserWalletHistories:
|
||||
|
||||
RefrenceId IN (payoutهای BulkCredit شده)
|
||||
AND CreatedBy <> 'SP' -- لاگ SP = NetworkBalance درست، حذف نشود
|
||||
AND ChangeValue > 0 -- واریز اشتباه به Balance
|
||||
AND ChangeDiscountValue <= 0
|
||||
|
||||
اصلاح:
|
||||
- کسر ChangeValue از Balance همان WalletId
|
||||
- حذف رکوردهای UserWalletHistories اشتباه
|
||||
|
||||
@DryRun = 1 → فقط گزارش
|
||||
@DryRun = 0 → اعمال fix
|
||||
================================================================================
|
||||
*/
|
||||
|
||||
SET NOCOUNT ON;
|
||||
SET XACT_ABORT ON;
|
||||
|
||||
DECLARE @DryRun BIT = 1;
|
||||
DECLARE @WeeksBack INT = 4;
|
||||
DECLARE @SinceDate DATETIME = DATEADD(WEEK, -@WeeksBack, GETUTCDATE());
|
||||
|
||||
-- کاربرانی که fix برایشان اعمال میشود حتی اگر Balance منفی شود
|
||||
DECLARE @AllowNegativeUserIds TABLE (UserId BIGINT PRIMARY KEY);
|
||||
INSERT INTO @AllowNegativeUserIds (UserId) VALUES (106); -- مهرداد شجاعی
|
||||
|
||||
PRINT CONCAT('DryRun = ', @DryRun, ' | WeeksBack = ', @WeeksBack);
|
||||
PRINT '';
|
||||
|
||||
-- payoutهای BulkCredit شده (از CommissionPayoutHistories)
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0
|
||||
AND cph.Action = 1
|
||||
AND cph.Created >= @SinceDate
|
||||
AND (
|
||||
cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%'
|
||||
OR cph.Reason LIKE N'%واریز دسته%جمعی%'
|
||||
)
|
||||
),
|
||||
WrongWalletLogs AS (
|
||||
SELECT
|
||||
wh.Id AS WalletHistoryId,
|
||||
wh.WalletId,
|
||||
wh.RefrenceId AS PayoutId,
|
||||
p.UserId,
|
||||
wh.ChangeValue AS WrongBalanceCredit,
|
||||
wh.Created AS WrongCreditAt,
|
||||
wh.CreatedBy
|
||||
FROM CMS.UserWalletHistories wh
|
||||
INNER JOIN CMS.UserCommissionPayouts p
|
||||
ON p.Id = wh.RefrenceId AND p.IsDeleted = 0
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0
|
||||
)
|
||||
|
||||
-- 1) خلاصه
|
||||
SELECT
|
||||
(SELECT COUNT(*) FROM BulkCreditedPayoutIds) AS BulkCreditedPayoutCount,
|
||||
(SELECT COUNT(DISTINCT p.UserId)
|
||||
FROM CMS.UserCommissionPayouts p
|
||||
WHERE p.Id IN (SELECT PayoutId FROM BulkCreditedPayoutIds)) AS BulkCreditedUserCount,
|
||||
(SELECT COUNT(*) FROM WrongWalletLogs) AS WrongWalletHistoryCount,
|
||||
(SELECT COUNT(DISTINCT UserId) FROM WrongWalletLogs) AS AffectedUserCount,
|
||||
(SELECT ISNULL(SUM(WrongBalanceCredit), 0) FROM WrongWalletLogs) AS TotalWrongBalanceCredit;
|
||||
|
||||
PRINT '';
|
||||
PRINT '--- PayoutIdهای BulkCredit (برای مقایسه با لیست دستی) ---';
|
||||
SELECT PayoutId FROM (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
) x ORDER BY PayoutId;
|
||||
|
||||
PRINT '';
|
||||
PRINT '--- UserWalletHistories اشتباه ---';
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
)
|
||||
SELECT
|
||||
wh.Id AS WalletHistoryId,
|
||||
wh.RefrenceId AS PayoutId,
|
||||
p.UserId,
|
||||
u.Mobile,
|
||||
CONCAT(u.FirstName, N' ', u.LastName) AS FullName,
|
||||
p.WeekDefinitionId,
|
||||
p.TotalAmount AS PayoutAmount,
|
||||
wh.ChangeValue AS WrongBalanceCredit,
|
||||
uw.Balance AS CurrentBalance,
|
||||
uw.NetworkBalance,
|
||||
wh.Created AS WrongCreditAt,
|
||||
wh.CreatedBy
|
||||
FROM CMS.UserWalletHistories wh
|
||||
INNER JOIN CMS.UserCommissionPayouts p ON p.Id = wh.RefrenceId AND p.IsDeleted = 0
|
||||
INNER JOIN CMS.UserWallets uw ON uw.Id = wh.WalletId AND uw.IsDeleted = 0
|
||||
INNER JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0
|
||||
ORDER BY p.UserId, wh.RefrenceId;
|
||||
|
||||
PRINT '';
|
||||
PRINT '--- خلاصه به تفکیک کاربر ---';
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
),
|
||||
WrongWalletLogs AS (
|
||||
SELECT wh.Id AS WalletHistoryId, wh.WalletId, wh.RefrenceId AS PayoutId,
|
||||
p.UserId, wh.ChangeValue AS WrongBalanceCredit
|
||||
FROM CMS.UserWalletHistories wh
|
||||
INNER JOIN CMS.UserCommissionPayouts p ON p.Id = wh.RefrenceId AND p.IsDeleted = 0
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0
|
||||
)
|
||||
SELECT
|
||||
w.UserId,
|
||||
u.Mobile,
|
||||
CONCAT(u.FirstName, N' ', u.LastName) AS FullName,
|
||||
COUNT(w.WalletHistoryId) AS WrongHistoryCount,
|
||||
COUNT(DISTINCT w.PayoutId) AS AffectedPayoutCount,
|
||||
SUM(w.WrongBalanceCredit) AS TotalWrongCredit,
|
||||
uw.Balance AS CurrentBalance,
|
||||
uw.Balance - SUM(w.WrongBalanceCredit) AS BalanceAfterFix,
|
||||
CASE
|
||||
WHEN w.UserId IN (SELECT UserId FROM @AllowNegativeUserIds)
|
||||
AND uw.Balance < SUM(w.WrongBalanceCredit) THEN N'OK — منفی مجاز'
|
||||
WHEN uw.Balance < SUM(w.WrongBalanceCredit) THEN N'⚠ موجودی کافی نیست'
|
||||
ELSE N'OK'
|
||||
END AS FixStatus
|
||||
FROM WrongWalletLogs w
|
||||
INNER JOIN CMS.Users u ON u.Id = w.UserId AND u.IsDeleted = 0
|
||||
INNER JOIN CMS.UserWallets uw ON uw.Id = w.WalletId AND uw.IsDeleted = 0
|
||||
GROUP BY w.UserId, u.Mobile, u.FirstName, u.LastName, uw.Id, uw.Balance
|
||||
ORDER BY TotalWrongCredit DESC;
|
||||
|
||||
PRINT '';
|
||||
PRINT '--- blockers (بهجز کاربران با منفی مجاز) ---';
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
),
|
||||
WrongPerWallet AS (
|
||||
SELECT wh.WalletId, SUM(wh.ChangeValue) AS TotalWrongCredit
|
||||
FROM CMS.UserWalletHistories wh
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0
|
||||
GROUP BY wh.WalletId
|
||||
)
|
||||
SELECT uw.UserId, u.Mobile, uw.Balance AS CurrentBalance,
|
||||
w.TotalWrongCredit, uw.Balance - w.TotalWrongCredit AS BalanceAfterFix
|
||||
FROM WrongPerWallet w
|
||||
INNER JOIN CMS.UserWallets uw ON uw.Id = w.WalletId AND uw.IsDeleted = 0
|
||||
INNER JOIN CMS.Users u ON u.Id = uw.UserId AND u.IsDeleted = 0
|
||||
WHERE uw.Balance < w.TotalWrongCredit
|
||||
AND uw.UserId NOT IN (SELECT UserId FROM @AllowNegativeUserIds);
|
||||
|
||||
PRINT '';
|
||||
PRINT '--- منفی مجاز (fix اعمال میشود) ---';
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
),
|
||||
WrongPerWallet AS (
|
||||
SELECT wh.WalletId, SUM(wh.ChangeValue) AS TotalWrongCredit
|
||||
FROM CMS.UserWalletHistories wh
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0
|
||||
GROUP BY wh.WalletId
|
||||
)
|
||||
SELECT uw.UserId, u.Mobile, uw.Balance AS CurrentBalance,
|
||||
w.TotalWrongCredit, uw.Balance - w.TotalWrongCredit AS BalanceAfterFix
|
||||
FROM WrongPerWallet w
|
||||
INNER JOIN CMS.UserWallets uw ON uw.Id = w.WalletId AND uw.IsDeleted = 0
|
||||
INNER JOIN CMS.Users u ON u.Id = uw.UserId AND u.IsDeleted = 0
|
||||
WHERE uw.Balance < w.TotalWrongCredit
|
||||
AND uw.UserId IN (SELECT UserId FROM @AllowNegativeUserIds);
|
||||
|
||||
-- ── اعمال fix ──
|
||||
IF @DryRun = 1
|
||||
BEGIN
|
||||
PRINT '';
|
||||
PRINT 'DryRun — تغییری اعمال نشد. برای fix: @DryRun = 0';
|
||||
RETURN;
|
||||
END
|
||||
|
||||
DECLARE @BlockerCount INT;
|
||||
DECLARE @FixedWallets INT;
|
||||
DECLARE @DeletedHistories INT;
|
||||
DECLARE @TotalReverted BIGINT;
|
||||
DECLARE @ErrMsg NVARCHAR(4000);
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
),
|
||||
WrongPerWallet AS (
|
||||
SELECT wh.WalletId, SUM(wh.ChangeValue) AS TotalWrongCredit
|
||||
FROM CMS.UserWalletHistories wh
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0
|
||||
GROUP BY wh.WalletId
|
||||
)
|
||||
SELECT @BlockerCount = COUNT(*)
|
||||
FROM WrongPerWallet w
|
||||
INNER JOIN CMS.UserWallets uw ON uw.Id = w.WalletId AND uw.IsDeleted = 0
|
||||
WHERE uw.Balance < w.TotalWrongCredit
|
||||
AND uw.UserId NOT IN (SELECT UserId FROM @AllowNegativeUserIds);
|
||||
|
||||
IF @BlockerCount > 0
|
||||
BEGIN
|
||||
RAISERROR(N'%d کیف پول Balance منفی میشود — fix متوقف شد.', 16, 1, @BlockerCount);
|
||||
RETURN;
|
||||
END
|
||||
|
||||
BEGIN TRY
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
),
|
||||
WrongPerWallet AS (
|
||||
SELECT wh.WalletId, SUM(wh.ChangeValue) AS TotalWrongCredit
|
||||
FROM CMS.UserWalletHistories wh
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0
|
||||
GROUP BY wh.WalletId
|
||||
)
|
||||
UPDATE uw
|
||||
SET uw.Balance = uw.Balance - w.TotalWrongCredit,
|
||||
uw.LastModified = GETUTCDATE(),
|
||||
uw.LastModifiedBy = N'FixBulkCreditPayoutsWrongBalance'
|
||||
FROM CMS.UserWallets uw
|
||||
INNER JOIN WrongPerWallet w ON w.WalletId = uw.Id
|
||||
WHERE uw.IsDeleted = 0;
|
||||
|
||||
SET @FixedWallets = @@ROWCOUNT;
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
)
|
||||
SELECT @TotalReverted = ISNULL(SUM(wh.ChangeValue), 0)
|
||||
FROM CMS.UserWalletHistories wh
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0;
|
||||
|
||||
;WITH BulkCreditedPayoutIds AS (
|
||||
SELECT DISTINCT cph.UserCommissionPayoutId AS PayoutId
|
||||
FROM CMS.CommissionPayoutHistories cph
|
||||
WHERE cph.IsDeleted = 0 AND cph.Action = 1 AND cph.Created >= @SinceDate
|
||||
AND (cph.Reason LIKE N'%تایید پرداخت دسته%جمعی%' OR cph.Reason LIKE N'%واریز دسته%جمعی%')
|
||||
)
|
||||
DELETE wh
|
||||
FROM CMS.UserWalletHistories wh
|
||||
WHERE wh.IsDeleted = 0
|
||||
AND wh.RefrenceId IN (SELECT PayoutId FROM BulkCreditedPayoutIds)
|
||||
AND wh.CreatedBy <> N'SP'
|
||||
AND wh.ChangeValue > 0
|
||||
AND wh.ChangeDiscountValue <= 0;
|
||||
|
||||
SET @DeletedHistories = @@ROWCOUNT;
|
||||
|
||||
COMMIT TRANSACTION;
|
||||
|
||||
PRINT CONCAT('کیف پول اصلاحشده: ', @FixedWallets);
|
||||
PRINT CONCAT('لاگ حذفشده: ', @DeletedHistories);
|
||||
PRINT CONCAT('مجموع برگرداندهشده: ', @TotalReverted);
|
||||
END TRY
|
||||
BEGIN CATCH
|
||||
IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION;
|
||||
SET @ErrMsg = ERROR_MESSAGE();
|
||||
RAISERROR(@ErrMsg, 16, 1);
|
||||
END CATCH;
|
||||
|
||||
GO
|
||||
|
||||
/*
|
||||
-- کوئری ساده دستی (معادل همین منطق با لیست PayoutId ثابت):
|
||||
|
||||
SELECT *
|
||||
FROM CMS.UserWalletHistories
|
||||
WHERE RefrenceId IN (
|
||||
115,116,117,118,119,125,126,127,128,129,130,131,132,133,134,
|
||||
135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,
|
||||
150,151,152,153
|
||||
)
|
||||
AND CreatedBy <> N'SP'
|
||||
AND ChangeValue > 0
|
||||
AND ChangeDiscountValue <= 0;
|
||||
*/
|
||||
Reference in New Issue
Block a user