/* PHASE 1 — Create UserPackagePurchases (Manual=3) only. Scope: 17 users with verified manualy charge — both WalletHistory AND Transaction exist and WH.RefrenceId already points to the Tx. Hardcoded mapping (from UserWalletHistories.csv + Transactions.csv): UserId WH Tx ------ ---- ---- 75 102 23 93 103 24 96 104 25 99 105 26 47 106 28 43 107 29 45 108 30 52 122 31 116 138 42 115 139 43 119 140 44 113 141 45 103 142 46 170 292 107 171 293 108 172 294 109 175 295 110 Does NOT: - change Users / Club / Cycle PurchaseMethod - create or modify Transactions or WalletHistory - re-charge wallet PackagePurchaseMethod on UPP: Manual = 3 Defaults to ROLLBACK. Uncomment COMMIT after reviewing preview + counts. */ SET NOCOUNT ON; SET XACT_ABORT ON; BEGIN TRAN; DECLARE @Now DATETIME2 = SYSUTCDATETIME(); DECLARE @BasePackageId BIGINT; DECLARE @BasePackagePrice BIGINT; SELECT TOP (1) @BasePackageId = Id, @BasePackagePrice = Price FROM CMS.Packages WHERE IsDeleted = 0 AND IsBasePackage = 1 ORDER BY Id; IF @BasePackageId IS NULL THROW 50001, 'Base package not found.', 1; ------------------------------------------------------------ -- Expected mapping ------------------------------------------------------------ DECLARE @Phase1 TABLE ( UserId BIGINT NOT NULL, WalletHistoryId BIGINT NOT NULL, TransactionId BIGINT NOT NULL, PRIMARY KEY (UserId) ); INSERT INTO @Phase1 (UserId, WalletHistoryId, TransactionId) VALUES (75, 102, 23), (93, 103, 24), (96, 104, 25), (99, 105, 26), (47, 106, 28), (43, 107, 29), (45, 108, 30), (52, 122, 31), (116, 138, 42), (115, 139, 43), (119, 140, 44), (113, 141, 45), (103, 142, 46), (170, 292, 107), (171, 293, 108), (172, 294, 109), (175, 295, 110); DECLARE @Phase1Count INT = (SELECT COUNT(*) FROM @Phase1); PRINT CONCAT('Phase1 expected rows: ', @Phase1Count); ------------------------------------------------------------ -- Validate live DB matches expected mapping ------------------------------------------------------------ SELECT p.UserId, u.Mobile, u.FirstName, u.LastName, p.WalletHistoryId AS ExpectedWhId, p.TransactionId AS ExpectedTxId, h.Id AS ActualWhId, h.RefrenceId AS ActualWhRefrenceId, h.ChangeValue AS WhChangeValue, t.Id AS ActualTxId, t.RefId AS TxRefId, t.Amount AS TxAmount, t.PaymentStatus, w.UserId AS WhWalletUserId, CASE WHEN u.Id IS NULL THEN N'USER_MISSING' WHEN h.Id IS NULL THEN N'WH_MISSING' WHEN t.Id IS NULL THEN N'TX_MISSING' WHEN h.RefrenceId <> p.TransactionId THEN N'WH_REF_MISMATCH' WHEN w.UserId <> p.UserId THEN N'WH_WALLET_USER_MISMATCH' WHEN t.RefId NOT LIKE N'manualy%' THEN N'TX_NOT_MANUALY' WHEN t.PaymentStatus <> 0 THEN N'TX_NOT_SUCCESS' ELSE N'OK' END AS ValidationStatus FROM @Phase1 p LEFT JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0 LEFT JOIN CMS.UserWalletHistories h ON h.Id = p.WalletHistoryId AND h.IsDeleted = 0 LEFT JOIN CMS.UserWallets w ON w.Id = h.WalletId AND w.IsDeleted = 0 LEFT JOIN CMS.Transactions t ON t.Id = p.TransactionId AND t.IsDeleted = 0 ORDER BY p.UserId; DECLARE @BadValidation INT = ( SELECT COUNT(*) FROM @Phase1 p LEFT JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0 LEFT JOIN CMS.UserWalletHistories h ON h.Id = p.WalletHistoryId AND h.IsDeleted = 0 LEFT JOIN CMS.UserWallets w ON w.Id = h.WalletId AND w.IsDeleted = 0 LEFT JOIN CMS.Transactions t ON t.Id = p.TransactionId AND t.IsDeleted = 0 WHERE u.Id IS NULL OR h.Id IS NULL OR t.Id IS NULL OR h.RefrenceId <> p.TransactionId OR w.UserId <> p.UserId OR t.RefId NOT LIKE N'manualy%' OR t.PaymentStatus <> 0 ); IF @BadValidation > 0 BEGIN DECLARE @BadMsg NVARCHAR(200); SET @BadMsg = CONCAT( N'Validation failed for ', @BadValidation, N' row(s). Fix before creating UPP.' ); ROLLBACK; RAISERROR(@BadMsg, 16, 1); RETURN; END PRINT 'Validation OK for all 17 rows.'; ------------------------------------------------------------ -- Preview: who already has UPP / UPP on this Tx ------------------------------------------------------------ SELECT p.UserId, u.Mobile, p.TransactionId, CASE WHEN upp_any.Id IS NOT NULL THEN N'YES' ELSE N'NO' END AS HasAnyUpp, upp_any.Id AS ExistingUppId, upp_any.PurchaseMethod AS ExistingUppMethod, upp_any.TransactionId AS ExistingUppTxId, CASE WHEN upp_tx.Id IS NOT NULL THEN N'SKIP_UPP_EXISTS_FOR_TX' WHEN upp_any.Id IS NOT NULL THEN N'SKIP_USER_HAS_OTHER_UPP' ELSE N'CREATE_UPP' END AS PlanAction FROM @Phase1 p INNER JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0 OUTER APPLY ( SELECT TOP (1) upp.Id, upp.PurchaseMethod, upp.TransactionId FROM CMS.UserPackagePurchases upp WHERE upp.UserId = p.UserId AND upp.IsDeleted = 0 ORDER BY upp.Id DESC ) upp_any OUTER APPLY ( SELECT TOP (1) upp.Id FROM CMS.UserPackagePurchases upp WHERE upp.UserId = p.UserId AND upp.IsDeleted = 0 AND upp.TransactionId = p.TransactionId ORDER BY upp.Id DESC ) upp_tx ORDER BY p.UserId; ------------------------------------------------------------ -- Build UPP insert plan ------------------------------------------------------------ SELECT p.UserId, p.TransactionId, COALESCE( NULLIF(cm.LastPackageId, 0), NULLIF(cm.FirstPackageId, 0), @BasePackageId ) AS PackageId, COALESCE(t.Amount, @BasePackagePrice) AS Amount, COALESCE(t.PaymentDate, cm.ActivatedAt, @Now) AS PurchasedAt INTO #UppPlan FROM @Phase1 p INNER JOIN CMS.Transactions t ON t.Id = p.TransactionId AND t.IsDeleted = 0 LEFT JOIN CMS.ClubMemberships cm ON cm.UserId = p.UserId AND cm.IsDeleted = 0 WHERE NOT EXISTS ( SELECT 1 FROM CMS.UserPackagePurchases upp WHERE upp.UserId = p.UserId AND upp.IsDeleted = 0 AND upp.TransactionId = p.TransactionId ); DECLARE @ToCreate INT = (SELECT COUNT(*) FROM #UppPlan); DECLARE @Skipped INT = (SELECT COUNT(*) FROM @Phase1) - @ToCreate; PRINT CONCAT('UPP to create: ', @ToCreate, ' | Already linked (skip): ', @Skipped); SELECT pl.UserId, u.Mobile, u.FirstName, u.LastName, pl.TransactionId, pl.PackageId, pl.Amount, pl.PurchasedAt, N'INSERT_UPP_MANUAL_3' AS Action FROM #UppPlan pl INNER JOIN CMS.Users u ON u.Id = pl.UserId AND u.IsDeleted = 0 ORDER BY pl.UserId; ------------------------------------------------------------ -- Insert UPP ------------------------------------------------------------ INSERT INTO CMS.UserPackagePurchases ( UserId, PackageId, PurchaseMethod, PurchasedAt, Amount, OrderId, TransactionId, Created, CreatedBy, LastModified, LastModifiedBy, IsDeleted ) SELECT pl.UserId, pl.PackageId, 3, -- Manual pl.PurchasedAt, pl.Amount, NULL, pl.TransactionId, @Now, NULL, @Now, NULL, 0 FROM #UppPlan pl WHERE pl.PackageId IS NOT NULL AND pl.Amount > 0; PRINT CONCAT('UPP inserted: ', @@ROWCOUNT); DROP TABLE #UppPlan; ------------------------------------------------------------ -- Verify ------------------------------------------------------------ SELECT p.UserId, u.Mobile, p.TransactionId, CASE WHEN upp.Id IS NOT NULL THEN N'OK' ELSE N'MISSING_UPP' END AS UppStatus, upp.Id AS UppId, upp.PurchaseMethod, upp.TransactionId AS UppTxId FROM @Phase1 p INNER JOIN CMS.Users u ON u.Id = p.UserId AND u.IsDeleted = 0 LEFT JOIN CMS.UserPackagePurchases upp ON upp.UserId = p.UserId AND upp.IsDeleted = 0 AND upp.TransactionId = p.TransactionId ORDER BY p.UserId; SELECT N'Missing UPP after run' AS CheckName, COUNT(*) AS Cnt FROM @Phase1 p WHERE NOT EXISTS ( SELECT 1 FROM CMS.UserPackagePurchases upp WHERE upp.UserId = p.UserId AND upp.IsDeleted = 0 AND upp.TransactionId = p.TransactionId ); ROLLBACK; -- COMMIT; PRINT 'Done (rolled back by default). Uncomment COMMIT when preview looks correct.';