124 lines
6.1 KiB
SQL
124 lines
6.1 KiB
SQL
-- ============================================================================
|
|
-- Adverteren op MijnBesluit: adverteerders, campagnes en tellers.
|
|
--
|
|
-- Lees docs/Adverteren.md voordat je hier iets aan verandert. Daar staat waarom de balk laag
|
|
-- is, hoe er wordt gekozen wie er getoond wordt, en waarom goedkeuring vooraf gaat.
|
|
--
|
|
-- Draaien met:
|
|
-- mysql -u root -p mijnbesluit < db\13_adverteren.sql
|
|
--
|
|
-- Opnieuw draaien mag: er gebeurt dan niets.
|
|
-- ============================================================================
|
|
|
|
USE `mijnbesluit`;
|
|
|
|
-- ------------------------------------------------------------ adverteerders ---
|
|
-- Een bedrijf dat adverteert. Bewust een eigen tabel en géén regel in `users`:
|
|
--
|
|
-- * Een adverteerder is een bedrijf, geen persoon met een kluis, familie of nalatenschap.
|
|
-- Hem in `users` zetten zou betekenen dat elke query over gebruikers hem moet uitzonderen,
|
|
-- en één vergeten uitzondering is er één te veel in een applicatie die over nalatenschappen
|
|
-- gaat.
|
|
-- * Het scheidt de twee werelden ook fysiek: wie in het adverteerdersdeel inbreekt, staat nog
|
|
-- steeds nergens bij de kluizen in de buurt.
|
|
--
|
|
-- Inloggen gaat net als bij gebruikers met een code per e-mail; die codes staan in dezelfde
|
|
-- tabel `login_codes`, met een eigen doel-nummer.
|
|
CREATE TABLE IF NOT EXISTS `adverteerders` (
|
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
|
`company_name` VARCHAR(160) NOT NULL,
|
|
`contact_name` VARCHAR(160) NOT NULL DEFAULT '',
|
|
`email` VARCHAR(255) NOT NULL,
|
|
`phone` VARCHAR(50) NULL,
|
|
`address` VARCHAR(160) NULL,
|
|
`postal_code` VARCHAR(20) NULL,
|
|
`city` VARCHAR(120) NULL,
|
|
`country` VARCHAR(80) NULL,
|
|
`coc_number` VARCHAR(40) NULL, -- KvK
|
|
`vat_number` VARCHAR(40) NULL, -- btw
|
|
`created_at` DATETIME(6) NOT NULL,
|
|
`last_seen_at` DATETIME(6) NULL,
|
|
`blocked_at` DATETIME(6) NULL, -- geen nieuwe campagnes meer; bestaande blijven staan
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `ux_adverteerders_email` (`email`)
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- ---------------------------------------------------------------- campagnes ---
|
|
-- Eén geboekte advertentie: wat er staat, wanneer hij mag draaien, hoe vaak per uur, wat hij
|
|
-- kost en hoe ver hij is.
|
|
--
|
|
-- De afbeelding staat hier als blob en niet in `vault_files`. Die tabel is voor spullen van
|
|
-- gebruikers en is versleuteld met sleutels per gebruiker; een advertentielogo is juist
|
|
-- openbaar en hoort daar niet tussen te staan. Hij wordt bij het opslaan verkleind, dus groot
|
|
-- kan hij niet worden.
|
|
--
|
|
-- `amount_cents` wordt bij het boeken berekend en dan vastgelegd. Verandert het tarief later,
|
|
-- dan verandert een al geboekte campagne niet mee - je hebt afgesproken wat je afsprak.
|
|
CREATE TABLE IF NOT EXISTS `campagnes` (
|
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
|
`advertiser_id` BIGINT NOT NULL,
|
|
|
|
`text` VARCHAR(300) NOT NULL,
|
|
`link` VARCHAR(500) NOT NULL,
|
|
`image` LONGBLOB NULL,
|
|
`image_type` VARCHAR(100) NULL,
|
|
|
|
`starts_on` DATE NOT NULL,
|
|
`ends_on` DATE NOT NULL,
|
|
`per_hour` INT NOT NULL,
|
|
|
|
`amount_cents` INT NOT NULL,
|
|
`rate_cents` INT NOT NULL, -- het tarief waarmee gerekend is, voor de verantwoording
|
|
`payment_reference` VARCHAR(40) NULL, -- wat de adverteerder bij zijn bunq-betaling zet
|
|
`paid_at` DATETIME(6) NULL,
|
|
`paid_by_user_id` BIGINT NULL, -- welke beheerder het afvinkte
|
|
|
|
`state` TINYINT NOT NULL DEFAULT 0,
|
|
`approved_at` DATETIME(6) NULL,
|
|
`approved_by_user_id` BIGINT NULL,
|
|
`rejection_reason` VARCHAR(500) NULL,
|
|
|
|
`created_at` DATETIME(6) NOT NULL,
|
|
`updated_at` DATETIME(6) NULL,
|
|
|
|
PRIMARY KEY (`id`),
|
|
KEY `ix_campagnes_adverteerder` (`advertiser_id`),
|
|
|
|
-- De vraag "welke campagnes mogen nu draaien" komt bij élke keer dat iemand het overzicht
|
|
-- opent. Die moet op een index kunnen landen en niet op de hele tabel.
|
|
KEY `ix_campagnes_lopend` (`state`, `starts_on`, `ends_on`),
|
|
|
|
CONSTRAINT `fk_campagnes_adverteerder` FOREIGN KEY (`advertiser_id`)
|
|
REFERENCES `adverteerders` (`id`) ON DELETE RESTRICT
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- --------------------------------------------------------------- vertoningen ---
|
|
-- Eén regel per campagne per klokuur, met tellers erin. Níét één regel per vertoning: bij een
|
|
-- paar honderd bezoekers per uur loopt zo'n tabel eindeloos vol, en voor het kiezen én voor de
|
|
-- verantwoording is een teller per uur genoeg.
|
|
--
|
|
-- Het uur staat in UTC, op het hele uur afgerond. De unieke sleutel is wat het optellen veilig
|
|
-- maakt: twee bezoekers tegelijk leveren een INSERT ... ON DUPLICATE KEY UPDATE op en geen
|
|
-- tweede regel.
|
|
CREATE TABLE IF NOT EXISTS `campagne_uren` (
|
|
`id` BIGINT NOT NULL AUTO_INCREMENT,
|
|
`campaign_id` BIGINT NOT NULL,
|
|
`hour_utc` DATETIME(6) NOT NULL,
|
|
`shown` INT NOT NULL DEFAULT 0,
|
|
`clicks` INT NOT NULL DEFAULT 0,
|
|
PRIMARY KEY (`id`),
|
|
UNIQUE KEY `ux_campagne_uren` (`campaign_id`, `hour_utc`),
|
|
CONSTRAINT `fk_campagne_uren_campagne` FOREIGN KEY (`campaign_id`)
|
|
REFERENCES `campagnes` (`id`) ON DELETE CASCADE
|
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
|
|
-- De rechten voor de applicatiegebruiker staan NIET hier maar in 02_applicatiegebruiker.sql.
|
|
--
|
|
-- Waarom: de scripts vanaf 03 worden ook door de uitrolagent gedraaid, met een beperkt
|
|
-- databaseaccount dat geen rechten mág uitdelen. Een GRANT hier laat die hele uitrol struikelen,
|
|
-- en dat account meer macht geven is de verkeerde kant op. Rechten uitdelen is inrichten; dat
|
|
-- doet een mens één keer als root. Een zelfcontrole legt elke CREATE TABLE in deze map naast de
|
|
-- lijst in 02, dus vergeten kan niet ongemerkt.
|
|
|
|
SELECT 'Klaar. Adverteerders, campagnes en tellers staan klaar.' AS melding;
|