- Track referral attribution at registration via ?ref code with same-IP and duplicate-pair guards - Add daily login rewards with streak tracking, claim flow and sendCurrency payout backed by RCON with DB fallback - Add admin pages for referral settings and the daily reward schedule - Add migration 0033 with tables, seed schedule, settings and ACL grants - Add admin.referrals.* and admin.dailyrewards.* permission slugs - Localize new copy in en, nl and it
154 lines
6.3 KiB
SQL
154 lines
6.3 KiB
SQL
-- 0033_referrals_daily_rewards.sql
|
|
-- Referral attribution tables (mirror the live-DB shape used by the existing
|
|
-- referral claim flow in src/actions/referral.ts) plus the CMS-owned daily
|
|
-- login reward schedule and claim ledger. All CREATE statements are idempotent
|
|
-- (IF NOT EXISTS) so fresh installs get the tables and existing hotels keep
|
|
-- whatever rows they already have.
|
|
|
|
CREATE TABLE IF NOT EXISTS `user_referrals` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT NOT NULL,
|
|
`referrals_total` BIGINT UNSIGNED NOT NULL DEFAULT 0,
|
|
`created_at` TIMESTAMP NULL,
|
|
`updated_at` TIMESTAMP NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `user_referrals_user_idx` (`user_id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `referrals` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT NOT NULL,
|
|
`referred_user_id` BIGINT UNSIGNED NOT NULL,
|
|
`referred_user_ip` VARCHAR(255) NOT NULL,
|
|
`created_at` TIMESTAMP NULL,
|
|
`updated_at` TIMESTAMP NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `referrals_user_idx` (`user_id`),
|
|
KEY `referrals_referred_user_idx` (`referred_user_id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
CREATE TABLE IF NOT EXISTS `claimed_referral_logs` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT NOT NULL,
|
|
`ip_address` VARCHAR(255) NOT NULL,
|
|
`created_at` TIMESTAMP NULL,
|
|
`updated_at` TIMESTAMP NULL,
|
|
PRIMARY KEY (`id`),
|
|
KEY `claimed_referral_logs_user_idx` (`user_id`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- Daily login reward schedule: one row per streak day. The cycle repeats after
|
|
-- the highest day (day 1 of the cycle is used for any missing day).
|
|
CREATE TABLE IF NOT EXISTS `website_daily_rewards` (
|
|
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`day` INT UNSIGNED NOT NULL DEFAULT 1,
|
|
`currency` VARCHAR(20) NOT NULL DEFAULT 'credits',
|
|
`amount` INT NOT NULL DEFAULT 0,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
`updated_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `website_daily_rewards_day_uk` (`day`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- Daily reward claims ledger; one row per user per claim date.
|
|
CREATE TABLE IF NOT EXISTS `website_daily_reward_claims` (
|
|
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
|
|
`user_id` INT NOT NULL,
|
|
`claim_date` DATE NOT NULL,
|
|
`streak` INT UNSIGNED NOT NULL DEFAULT 1,
|
|
`reward_day` INT UNSIGNED NOT NULL DEFAULT 1,
|
|
`currency` VARCHAR(20) NOT NULL DEFAULT 'credits',
|
|
`amount` INT NOT NULL DEFAULT 0,
|
|
`created_at` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `daily_claim_user_date_uk` (`user_id`, `claim_date`),
|
|
KEY `daily_claim_created_idx` (`created_at`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- Seed a sensible 7-day reward schedule only when the table is still empty.
|
|
INSERT INTO `website_daily_rewards` (`day`, `currency`, `amount`)
|
|
SELECT 1, 'duckets', 60
|
|
FROM DUAL
|
|
WHERE NOT EXISTS (SELECT 1 FROM `website_daily_rewards`);
|
|
INSERT INTO `website_daily_rewards` (`day`, `currency`, `amount`)
|
|
SELECT 3, 'credits', 50
|
|
FROM DUAL
|
|
WHERE (SELECT COUNT(*) FROM `website_daily_rewards`) = 1
|
|
AND NOT EXISTS (SELECT 1 FROM `website_daily_rewards` WHERE `day` = 3);
|
|
INSERT INTO `website_daily_rewards` (`day`, `currency`, `amount`)
|
|
SELECT 5, 'diamonds', 2
|
|
FROM DUAL
|
|
WHERE (SELECT COUNT(*) FROM `website_daily_rewards`) = 2
|
|
AND NOT EXISTS (SELECT 1 FROM `website_daily_rewards` WHERE `day` = 5);
|
|
|
|
-- Referral + daily reward configuration defaults (never overwrite an existing
|
|
-- value — operators tune these keys in the admin panel).
|
|
INSERT INTO `website_settings` (`key`, `value`, `comment`)
|
|
SELECT 'referrals_block_same_ip', '1', 'Block referral attribution when the new account shares the inviter IP'
|
|
FROM DUAL
|
|
WHERE NOT EXISTS (SELECT 1 FROM `website_settings` WHERE `key` = 'referrals_block_same_ip');
|
|
INSERT INTO `website_settings` (`key`, `value`, `comment`)
|
|
SELECT 'daily_reward_enabled', '1', 'Enable the daily login reward claims on /me'
|
|
FROM DUAL
|
|
WHERE NOT EXISTS (SELECT 1 FROM `website_settings` WHERE `key` = 'daily_reward_enabled');
|
|
|
|
-- New ACL slugs backing the /admin/referrals + /admin/daily-rewards modules.
|
|
INSERT INTO `acl_permissions` (`slug`, `title`) VALUES
|
|
('admin.referrals.view', 'View referrals'),
|
|
('admin.referrals.edit', 'Edit referrals'),
|
|
('admin.dailyrewards.view', 'View daily login rewards'),
|
|
('admin.dailyrewards.edit', 'Edit daily login rewards')
|
|
ON DUPLICATE KEY UPDATE `title` = VALUES(`title`);
|
|
|
|
-- Grant the new slugs to the same roles that already open the admin panel.
|
|
INSERT INTO `acl_model_permissions` (`model_type`, `model_id`, `permission_id`)
|
|
SELECT 'Role', ar.id, ap.id
|
|
FROM `acl_roles` ar
|
|
JOIN `acl_permissions` ap ON ap.slug IN (
|
|
'admin.referrals.view', 'admin.referrals.edit',
|
|
'admin.dailyrewards.view', 'admin.dailyrewards.edit'
|
|
)
|
|
WHERE EXISTS (
|
|
SELECT 1
|
|
FROM `acl_model_permissions` amp
|
|
JOIN `acl_permissions` apdash ON apdash.id = amp.permission_id
|
|
WHERE amp.model_type = 'Role'
|
|
AND amp.model_id = ar.id
|
|
AND apdash.slug = 'admin.dashboard'
|
|
)
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM `acl_model_permissions` amp2
|
|
WHERE amp2.model_type = 'Role'
|
|
AND amp2.model_id = ar.id
|
|
AND amp2.permission_id = ap.id
|
|
);
|
|
|
|
-- Safety net matching the 0018 seed: ranks >= 6 view, ranks >= 7 edit.
|
|
INSERT INTO `acl_model_permissions` (`model_type`, `model_id`, `permission_id`)
|
|
SELECT 'Role', ar.id, ap.id
|
|
FROM `permission_ranks` pr
|
|
JOIN `acl_roles` ar ON ar.slug = CONCAT('rank_', pr.id)
|
|
JOIN `acl_permissions` ap ON ap.slug IN ('admin.referrals.view', 'admin.dailyrewards.view')
|
|
WHERE pr.id >= 6
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM `acl_model_permissions` amp
|
|
WHERE amp.model_type = 'Role'
|
|
AND amp.model_id = ar.id
|
|
AND amp.permission_id = ap.id
|
|
);
|
|
|
|
INSERT INTO `acl_model_permissions` (`model_type`, `model_id`, `permission_id`)
|
|
SELECT 'Role', ar.id, ap.id
|
|
FROM `permission_ranks` pr
|
|
JOIN `acl_roles` ar ON ar.slug = CONCAT('rank_', pr.id)
|
|
JOIN `acl_permissions` ap ON ap.slug IN ('admin.referrals.edit', 'admin.dailyrewards.edit')
|
|
WHERE pr.id >= 7
|
|
AND NOT EXISTS (
|
|
SELECT 1
|
|
FROM `acl_model_permissions` amp
|
|
WHERE amp.model_type = 'Role'
|
|
AND amp.model_id = ar.id
|
|
AND amp.permission_id = ap.id
|
|
); |