Files
CMS/src/dbbkup/4-Fix_Daya_ActiveExcel_ProcessMissing.sql
T
masoodafar-web 612d6fd141
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 10m15s
fix(network): update network statistics and tree documentation
- Updated README to reflect the new documentation location.
- Refactored GetNetworkStatisticsQueryHandler to improve method naming and logic for loading package holder counts.
- Enhanced GetNetworkStatisticsResponseDto and NetworkTreeDto to clarify the purpose of leg total properties.
- Updated Protobuf definitions to align with the new response structure for network statistics.
- Removed obsolete SQL scripts related to user package purchases and DayaLoan contracts cleanup.
2026-08-28 18:55:48 +03:30

541 lines
18 KiB
Transact-SQL

/*
Staging fix: complete post-Daya processing for Excel rows with status «فعال شده»
that are NOT_PROCESSED or PARTIAL.
Classification:
DONE — credit + processed + Daya UPP
PARTIAL — HasReceivedDayaCredit OR IsProcessed OR existing «اعتبار دایا» Tx in wallet
NOT_PROCESSED — none of the above (will create Tx + ledger WH)
If ExistingDayaTxId found (wallet RefrenceId → Tx Description LIKE '%اعتبار دایا%'
OR Tx.RefId = ContractNumber): REUSE that Tx — do NOT create Transaction.
NO wallet Balance/DiscountBalance charge — UserWalletHistory is ledger-only when needed.
Special UserId mapping (shared NationalCode):
C4_D8815963 / 2490371436 → UserId 50
C4_G8945289 / 2490371436 → UserId 51
@Commit = 0 → dry-run (ROLLBACK)
@Commit = 1 → apply
*/
SET NOCOUNT ON;
SET XACT_ABORT ON;
DECLARE @Commit BIT = 0; -- << set 1 to apply
DECLARE @Now DATETIME2 = SYSUTCDATETIME();
DECLARE @PackageId BIGINT;
DECLARE @PackagePrice BIGINT;
DECLARE @DiscountMultiplier DECIMAL(18,4);
DECLARE @DiscountAmount BIGINT;
SELECT TOP (1)
@PackageId = Id,
@PackagePrice = Price,
@DiscountMultiplier = DiscountMultiplier
FROM CMS.Packages
WHERE IsDeleted = 0 AND IsBasePackage = 1
ORDER BY Id;
IF @PackageId IS NULL
THROW 50001, 'Base package not found.', 1;
SET @DiscountAmount = CAST(@PackagePrice * @DiscountMultiplier AS BIGINT);
PRINT CONCAT('PackageId=', @PackageId, ' Price=', @PackagePrice, ' Discount=', @DiscountAmount);
------------------------------------------------------------
-- Targets: Excel «فعال شده»
------------------------------------------------------------
DECLARE @Targets TABLE (
ContractNumber NVARCHAR(50) NOT NULL,
NationalCode NVARCHAR(20) NOT NULL,
UserIdHint BIGINT NULL -- explicit override when NC is shared
);
INSERT INTO @Targets (ContractNumber, NationalCode, UserIdHint) VALUES
(N'C4_H10706299', N'4060667961', NULL),
(N'C4_P9320383', N'2572729636', NULL),
(N'C4_Q9465813', N'2480017796', NULL),
(N'C4_B9348378', N'0452314488', NULL),
(N'C4_X9630520', N'0680164286', NULL),
(N'C4_B9813553', N'0055680364', NULL), -- may match DayaLoanContracts.NationalCode if Users.NC differs
(N'C4_M9994735', N'0793851572', NULL),
(N'C4_S9301452', N'0082242925', NULL),
(N'C4_T9961063', N'0312342993', NULL),
(N'C4_L9524515', N'0024757489', NULL),
(N'C4_Q9947535', N'2480259668', NULL),
(N'C4_T9892089', N'2451477016', NULL),
(N'C4_W8785358', N'0322922720', NULL),
(N'C4_D8815963', N'2490371436', 50), -- earlier activation → user 50
(N'C4_G8945289', N'2490371436', 51), -- later activation → user 51
(N'C4_J8388494', N'2002637903', NULL);
DECLARE @Work TABLE (
ContractNumber NVARCHAR(50),
NationalCode NVARCHAR(20),
UserId BIGINT,
DayaContractId BIGINT NULL,
HasCredit BIT,
IsProcessed BIT,
HasDayaUpp BIT,
ExistingDayaTxId BIGINT NULL, -- Tx از قبل با شرح «اعتبار دایا» / RefId قرارداد (شارژ شده)
Verdict NVARCHAR(20)
);
INSERT INTO @Work (ContractNumber, NationalCode, UserId, DayaContractId, HasCredit, IsProcessed, HasDayaUpp, ExistingDayaTxId, Verdict)
SELECT
t.ContractNumber,
t.NationalCode,
u.Id,
d.Id,
CAST(ISNULL(u.HasReceivedDayaCredit, 0) AS BIT),
CAST(ISNULL(d.IsProcessed, 0) AS BIT),
CAST(CASE WHEN EXISTS (
SELECT 1
FROM CMS.UserPackagePurchases upp
LEFT JOIN CMS.Transactions tx ON tx.Id = upp.TransactionId AND tx.IsDeleted = 0
WHERE upp.UserId = u.Id
AND upp.IsDeleted = 0
AND upp.PurchaseMethod = 1
AND (upp.TransactionId IS NULL OR tx.PaymentStatus = 0)
) THEN 1 ELSE 0 END AS BIT),
etx.TxId,
CASE
WHEN u.Id IS NULL THEN N'NO_USER'
WHEN ISNULL(u.HasReceivedDayaCredit, 0) = 1
AND ISNULL(d.IsProcessed, 0) = 1
AND EXISTS (
SELECT 1
FROM CMS.UserPackagePurchases upp
LEFT JOIN CMS.Transactions tx ON tx.Id = upp.TransactionId AND tx.IsDeleted = 0
WHERE upp.UserId = u.Id
AND upp.IsDeleted = 0
AND upp.PurchaseMethod = 1
AND (upp.TransactionId IS NULL OR tx.PaymentStatus = 0)
) THEN N'DONE'
-- قبلاً شارژ دایا در کیف/تراکنش هست ولی فلگ/UPP/قرارداد کامل نیست
WHEN etx.TxId IS NOT NULL THEN N'PARTIAL'
WHEN ISNULL(u.HasReceivedDayaCredit, 0) = 1
OR ISNULL(d.IsProcessed, 0) = 1 THEN N'PARTIAL'
ELSE N'NOT_PROCESSED'
END
FROM @Targets t
OUTER APPLY (
SELECT TOP (1) u0.*
FROM CMS.Users u0
WHERE u0.IsDeleted = 0
AND (
(t.UserIdHint IS NOT NULL AND u0.Id = t.UserIdHint)
OR (t.UserIdHint IS NULL AND u0.NationalCode = t.NationalCode)
OR (t.UserIdHint IS NULL AND EXISTS (
SELECT 1 FROM CMS.DayaLoanContracts dx
WHERE dx.UserId = u0.Id
AND dx.NationalCode = t.NationalCode
AND dx.IsDeleted = 0
))
)
ORDER BY
CASE WHEN t.UserIdHint IS NOT NULL AND u0.Id = t.UserIdHint THEN 0 ELSE 1 END,
CASE WHEN u0.NationalCode = t.NationalCode THEN 0 ELSE 1 END,
u0.Id
) u
OUTER APPLY (
SELECT TOP (1) d0.*
FROM CMS.DayaLoanContracts d0
WHERE d0.UserId = u.Id
AND (
d0.ContractNumber = t.ContractNumber
OR d0.NationalCode = t.NationalCode
OR d0.IsDeleted IN (0, 1)
)
ORDER BY
CASE WHEN d0.ContractNumber = t.ContractNumber THEN 0 ELSE 1 END,
CASE WHEN d0.IsDeleted = 0 THEN 0 ELSE 1 END,
d0.Id DESC
) d
OUTER APPLY (
-- تراکنش دایا که از قبل شارژ شده (مرجع کیف پول یا RefId قرارداد)
SELECT TOP (1) t0.Id AS TxId
FROM CMS.Transactions t0
WHERE t0.IsDeleted = 0
AND t0.PaymentStatus = 0
AND (
t0.RefId = t.ContractNumber
OR (
t0.Description LIKE N'%اعتبار دایا%'
AND EXISTS (
SELECT 1
FROM CMS.UserWallets w
INNER JOIN CMS.UserWalletHistories h ON h.WalletId = w.Id
WHERE w.UserId = u.Id
AND h.RefrenceId = t0.Id
)
)
)
ORDER BY
CASE WHEN t0.RefId = t.ContractNumber THEN 0 ELSE 1 END,
t0.Id DESC
) etx;
PRINT '=== Before ===';
SELECT Verdict, COUNT(*) AS Cnt FROM @Work GROUP BY Verdict;
SELECT ContractNumber, NationalCode, UserId, DayaContractId, HasCredit, IsProcessed, HasDayaUpp,
ExistingDayaTxId, Verdict
FROM @Work
ORDER BY Verdict, ContractNumber;
------------------------------------------------------------
-- PREVIEW: ledger actions (no wallet charge)
------------------------------------------------------------
PRINT '=== LEDGER PREVIEW (Tx + WH history-only — NO wallet charge) ===';
SELECT
w.ContractNumber,
w.NationalCode,
w.UserId,
w.Verdict,
w.HasCredit,
w.ExistingDayaTxId,
CASE
WHEN w.UserId IS NULL THEN N'SKIP_NO_USER'
WHEN w.ExistingDayaTxId IS NOT NULL THEN N'REUSE_TX_ENSURE_WH_UPP'
WHEN w.HasCredit = 0 THEN N'CREATE_TX_WH_UPP'
ELSE N'SET_FLAGS_ONLY_UPP'
END AS LedgerAction
FROM @Work w
WHERE w.Verdict IN (N'NOT_PROCESSED', N'PARTIAL')
ORDER BY LedgerAction, w.ContractNumber;
SELECT
CASE
WHEN w.UserId IS NULL THEN N'SKIP_NO_USER'
WHEN w.ExistingDayaTxId IS NOT NULL THEN N'REUSE_TX_ENSURE_WH_UPP'
WHEN w.HasCredit = 0 THEN N'CREATE_TX_WH_UPP'
ELSE N'SET_FLAGS_ONLY_UPP'
END AS LedgerAction,
COUNT(*) AS Cnt
FROM @Work w
WHERE w.Verdict IN (N'NOT_PROCESSED', N'PARTIAL')
GROUP BY
CASE
WHEN w.UserId IS NULL THEN N'SKIP_NO_USER'
WHEN w.ExistingDayaTxId IS NOT NULL THEN N'REUSE_TX_ENSURE_WH_UPP'
WHEN w.HasCredit = 0 THEN N'CREATE_TX_WH_UPP'
ELSE N'SET_FLAGS_ONLY_UPP'
END
ORDER BY LedgerAction;
DECLARE @PreviewCreateTxCount INT = (
SELECT COUNT(*)
FROM @Work w
WHERE w.Verdict IN (N'NOT_PROCESSED', N'PARTIAL')
AND w.UserId IS NOT NULL
AND w.ExistingDayaTxId IS NULL
AND w.HasCredit = 0
);
PRINT CONCAT('>>> CREATE_TX (no wallet charge) count = ', @PreviewCreateTxCount);
BEGIN TRAN;
DECLARE @ContractNumber NVARCHAR(50), @NationalCode NVARCHAR(20), @UserId BIGINT;
DECLARE @DayaContractId BIGINT, @HasCredit BIT, @IsProcessed BIT, @HasDayaUpp BIT, @Verdict NVARCHAR(20);
DECLARE @ExistingDayaTxId BIGINT;
DECLARE @TxId BIGINT, @WalletId BIGINT, @NetworkBalance BIGINT, @Action NVARCHAR(200);
DECLARE @CreateTxCount INT = 0;
DECLARE @ReuseCount INT = 0;
DECLARE @SkipFlagsOnlyCount INT = 0;
DECLARE @WhCreatedCount INT = 0;
DECLARE @Log TABLE (
ContractNumber NVARCHAR(50),
UserId BIGINT,
VerdictBefore NVARCHAR(20),
ActionTaken NVARCHAR(200),
TxId BIGINT NULL
);
DECLARE cur CURSOR LOCAL FAST_FORWARD FOR
SELECT ContractNumber, NationalCode, UserId, DayaContractId, HasCredit, IsProcessed, HasDayaUpp, ExistingDayaTxId, Verdict
FROM @Work
WHERE Verdict IN (N'NOT_PROCESSED', N'PARTIAL');
OPEN cur;
FETCH NEXT FROM cur INTO @ContractNumber, @NationalCode, @UserId, @DayaContractId, @HasCredit, @IsProcessed, @HasDayaUpp, @ExistingDayaTxId, @Verdict;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @TxId = NULL;
SET @Action = N'';
IF @UserId IS NULL
BEGIN
INSERT INTO @Log VALUES (@ContractNumber, NULL, @Verdict, N'SKIP NO_USER', NULL);
GOTO NextRow;
END
------------------------------------------------------------
-- Ensure / revive DayaLoanContract
------------------------------------------------------------
IF @DayaContractId IS NULL
BEGIN
INSERT INTO CMS.DayaLoanContracts
(
UserId, NationalCode, ContractNumber, Status, IsProcessed,
LastCheckDate, ProcessedDate, TransactionId,
Created, CreatedBy, LastModified, LastModifiedBy, IsDeleted
)
VALUES
(
@UserId, @NationalCode, @ContractNumber, 2, 0,
@Now, NULL, NULL,
@Now, NULL, @Now, NULL, 0
);
SET @DayaContractId = SCOPE_IDENTITY();
SET @Action = @Action + N'INSERT_CONTRACT;';
END
ELSE
BEGIN
UPDATE CMS.DayaLoanContracts
SET
IsDeleted = 0,
NationalCode = @NationalCode,
ContractNumber = @ContractNumber,
Status = 2, -- Received («فعال شده»)
LastCheckDate = @Now,
LastModified = @Now
WHERE Id = @DayaContractId;
SET @Action = @Action + N'UPDATE_CONTRACT;';
END
------------------------------------------------------------
-- Resolve Tx (reuse existing or create ledger Tx — NO wallet charge)
------------------------------------------------------------
IF @ExistingDayaTxId IS NOT NULL
BEGIN
SET @TxId = @ExistingDayaTxId;
SET @Action = @Action + CONCAT(N'REUSE_EXISTING_DAYA_TX=', @TxId, N';');
SET @ReuseCount = @ReuseCount + 1;
UPDATE CMS.Users
SET
PackagePurchaseMethod = 1,
HasReceivedDayaCredit = 1,
DayaCreditReceivedAt = COALESCE(DayaCreditReceivedAt, @Now),
LastModified = @Now
WHERE Id = @UserId;
SET @HasCredit = 1;
SET @Action = @Action + N'SET_USER_FLAGS;';
END
ELSE IF @HasCredit = 0
BEGIN
INSERT INTO CMS.Transactions
(
Amount, Description, PaymentStatus, PaymentDate, RefId, Type,
Created, CreatedBy, LastModified, LastModifiedBy, IsDeleted
)
VALUES
(
@PackagePrice,
CONCAT(N'دریافت اعتبار دایا - قرارداد ', @ContractNumber),
0,
@Now,
@ContractNumber,
2,
@Now, NULL, @Now, NULL, 0
);
SET @TxId = SCOPE_IDENTITY();
SET @CreateTxCount = @CreateTxCount + 1;
UPDATE CMS.Users
SET
HasReceivedDayaCredit = 1,
DayaCreditReceivedAt = @Now,
PackagePurchaseMethod = 1,
LastModified = @Now
WHERE Id = @UserId;
SET @HasCredit = 1;
SET @Action = @Action + N'CREATE_TX+USER_FLAGS;';
END
ELSE
BEGIN
UPDATE CMS.Users
SET
PackagePurchaseMethod = 1,
HasReceivedDayaCredit = 1,
DayaCreditReceivedAt = COALESCE(DayaCreditReceivedAt, @Now),
LastModified = @Now
WHERE Id = @UserId;
SET @SkipFlagsOnlyCount = @SkipFlagsOnlyCount + 1;
SET @Action = @Action + N'SET_FLAGS_ONLY;';
END
------------------------------------------------------------
-- UserWalletHistory for Tx (ledger-only — NO Balance/Discount charge)
------------------------------------------------------------
IF @TxId IS NOT NULL
BEGIN
SELECT @WalletId = Id, @NetworkBalance = COALESCE(NetworkBalance, 0)
FROM CMS.UserWallets
WHERE UserId = @UserId AND IsDeleted = 0;
IF @WalletId IS NULL
BEGIN
INSERT INTO CMS.UserWallets
(UserId, Balance, NetworkBalance, DiscountBalance, WalletMode, Created, LastModified, IsDeleted)
VALUES (@UserId, 0, 0, 0, 0, @Now, @Now, 0);
SET @WalletId = SCOPE_IDENTITY();
SET @NetworkBalance = 0;
END
IF NOT EXISTS (
SELECT 1
FROM CMS.UserWalletHistories h
WHERE h.WalletId = @WalletId
AND h.IsDeleted = 0
AND h.RefrenceId = @TxId
)
BEGIN
INSERT INTO CMS.UserWalletHistories
(
WalletId, CurrentBalance, ChangeValue, CurrentNetworkBalance, ChangeNerworkValue,
CurrentDiscountBalance, ChangeDiscountValue, IsIncrease, RefrenceId, PackageId,
Created, CreatedBy, LastModified, LastModifiedBy, IsDeleted
)
VALUES
(
@WalletId, 0, @PackagePrice, @NetworkBalance, 0,
0, @DiscountAmount, 1, @TxId, @PackageId,
@Now, NULL, @Now, NULL, 0
);
SET @WhCreatedCount = @WhCreatedCount + 1;
SET @Action = @Action + N'INSERT_WH_HISTORY;';
END
END
------------------------------------------------------------
-- Ensure successful Daya UPP (no duplicate if already exists)
------------------------------------------------------------
IF @HasDayaUpp = 0
BEGIN
IF @TxId IS NULL
BEGIN
-- فقط لجر؛ بدون شارژ کیف (نباید برای کسی که Tx دایا دارد به اینجا برسد)
INSERT INTO CMS.Transactions
(
Amount, Description, PaymentStatus, PaymentDate, RefId, Type,
Created, CreatedBy, LastModified, LastModifiedBy, IsDeleted
)
VALUES
(
@PackagePrice,
CONCAT(N'لجر UPP دایا (بدون شارژ مجدد) - قرارداد ', @ContractNumber),
0,
@Now,
CONCAT(N'UPP-DAYA-FIX-', @ContractNumber),
2,
@Now, NULL, @Now, NULL, 0
);
SET @TxId = SCOPE_IDENTITY();
SET @Action = @Action + N'LEDGER_TX;';
END
INSERT INTO CMS.UserPackagePurchases
(
UserId, PackageId, PurchaseMethod, PurchasedAt, Amount,
OrderId, TransactionId, Created, CreatedBy, LastModified, LastModifiedBy, IsDeleted
)
VALUES
(
@UserId, @PackageId, 1, @Now, @PackagePrice,
NULL, @TxId, @Now, NULL, @Now, NULL, 0
);
SET @Action = @Action + N'INSERT_UPP;';
END
------------------------------------------------------------
-- Mark contract processed
------------------------------------------------------------
UPDATE CMS.DayaLoanContracts
SET
IsProcessed = 1,
ProcessedDate = COALESCE(ProcessedDate, @Now),
TransactionId = COALESCE(TransactionId, @TxId),
Status = 2,
ContractNumber = @ContractNumber,
IsDeleted = 0,
LastModified = @Now
WHERE Id = @DayaContractId;
SET @Action = @Action + N'MARK_PROCESSED;';
INSERT INTO @Log VALUES (@ContractNumber, @UserId, @Verdict, @Action, @TxId);
NextRow:
FETCH NEXT FROM cur INTO @ContractNumber, @NationalCode, @UserId, @DayaContractId, @HasCredit, @IsProcessed, @HasDayaUpp, @ExistingDayaTxId, @Verdict;
END
CLOSE cur;
DEALLOCATE cur;
PRINT '=== LEDGER SUMMARY (no wallet charge) ===';
PRINT CONCAT('CREATE_TX count = ', @CreateTxCount);
PRINT CONCAT('REUSE_TX count = ', @ReuseCount);
PRINT CONCAT('SET_FLAGS_ONLY count = ', @SkipFlagsOnlyCount);
PRINT CONCAT('WH history created = ', @WhCreatedCount);
PRINT '=== Actions ===';
SELECT * FROM @Log ORDER BY VerdictBefore, ContractNumber;
-- Re-score after changes
PRINT '=== After (same targets) ===';
SELECT
t.ContractNumber,
t.NationalCode,
u.Id AS UserId,
u.HasReceivedDayaCredit,
d.IsProcessed,
d.ContractNumber AS DbContractNumber,
d.Status,
CASE WHEN EXISTS (
SELECT 1 FROM CMS.UserPackagePurchases upp
LEFT JOIN CMS.Transactions tx ON tx.Id = upp.TransactionId AND tx.IsDeleted = 0
WHERE upp.UserId = u.Id AND upp.IsDeleted = 0 AND upp.PurchaseMethod = 1
AND (upp.TransactionId IS NULL OR tx.PaymentStatus = 0)
) THEN 1 ELSE 0 END AS HasDayaUpp,
CASE
WHEN u.Id IS NULL THEN N'NO_USER'
WHEN u.HasReceivedDayaCredit = 1 AND d.IsProcessed = 1
AND EXISTS (
SELECT 1 FROM CMS.UserPackagePurchases upp
LEFT JOIN CMS.Transactions tx ON tx.Id = upp.TransactionId AND tx.IsDeleted = 0
WHERE upp.UserId = u.Id AND upp.IsDeleted = 0 AND upp.PurchaseMethod = 1
AND (upp.TransactionId IS NULL OR tx.PaymentStatus = 0)
) THEN N'DONE'
WHEN u.HasReceivedDayaCredit = 1 OR d.IsProcessed = 1 THEN N'PARTIAL'
ELSE N'NOT_PROCESSED'
END AS Verdict
FROM @Targets t
LEFT JOIN CMS.Users u ON u.IsDeleted = 0 AND (
(t.UserIdHint IS NOT NULL AND u.Id = t.UserIdHint) OR (t.UserIdHint IS NULL AND u.NationalCode = t.NationalCode)
)
LEFT JOIN CMS.DayaLoanContracts d ON d.IsDeleted = 0 AND d.UserId = u.Id
AND (d.ContractNumber = t.ContractNumber OR d.NationalCode = t.NationalCode)
ORDER BY Verdict, t.ContractNumber;
IF @Commit = 1
BEGIN
COMMIT;
PRINT 'COMMITTED.';
END
ELSE
BEGIN
ROLLBACK;
PRINT 'Dry-run ROLLBACK. Set @Commit = 1 to apply.';
END