Files
tilbudgivern/bygma_prisbog_database.sql
T
alex fe8d73e8d1 Add integration tests for Bygma import services
- Implement test script for Bygma ESG data import (test_bygma_import.js)
- Create test script for Bygma Prisbog import functionality (test_bygma_prisbog_import.js)
- Develop full integration test for Bygma materials system (test_full_bygma_integration.js)
- Add materials synchronization test script (test_materials_sync.js)
- Ensure database connection and import statistics are logged
- Validate API visibility and price updates in integration tests
- Include sample data checks and cleanup procedures in tests
2025-09-18 13:24:50 +02:00

245 lines
8.4 KiB
SQL

-- Database struktur til månedlige Bygma prisbøger
-- Dette skema håndterer løbende prisimport fra Bygma's månedlige prislister
-- Hovedtabel for Bygma produkter (master data)
CREATE TABLE IF NOT EXISTS bygma_products (
id INT AUTO_INCREMENT PRIMARY KEY,
-- Produkt identifikation
product_code VARCHAR(255) NOT NULL UNIQUE, -- VareNr fra CSV
product_group VARCHAR(100) NOT NULL, -- Varegrp fra CSV
product_name TEXT NOT NULL, -- Tekst fra CSV
unit VARCHAR(50) NOT NULL, -- Enhed fra CSV
-- Tekniske felter
db_number VARCHAR(100), -- DB-nr fra CSV
ean_number VARCHAR(100), -- EAN-nr fra CSV
standard_field VARCHAR(100), -- Std fra CSV
-- Metadata
first_seen DATE NOT NULL,
last_seen DATE NOT NULL,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-- Indices for performance
INDEX idx_product_code (product_code),
INDEX idx_product_group (product_group),
INDEX idx_product_name (product_name(100)),
INDEX idx_active (is_active),
INDEX idx_last_seen (last_seen)
);
-- Varegrupper/kategorier fra Bygma
CREATE TABLE IF NOT EXISTS bygma_product_groups (
id INT AUTO_INCREMENT PRIMARY KEY,
group_code VARCHAR(100) NOT NULL UNIQUE, -- Varegrp fra CSV
group_name VARCHAR(255), -- Kan tilføjes manuelt eller mapping
parent_group VARCHAR(100), -- For hierarkisk struktur
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_group_code (group_code),
INDEX idx_group_name (group_name)
);
-- Prishistorik fra månedlige imports
CREATE TABLE IF NOT EXISTS bygma_price_history (
id INT AUTO_INCREMENT PRIMARY KEY,
product_id INT NOT NULL,
-- Priser fra CSV
gross_price DECIMAL(15,2) NOT NULL, -- BruttoPris fra CSV
net_price DECIMAL(15,2) NOT NULL, -- Nettopris fra CSV (vores indkøbspris)
update_flag TINYINT NOT NULL DEFAULT 1, -- Opdat fra CSV
-- Import metadata
import_date DATE NOT NULL, -- Dato for denne import
import_file VARCHAR(255) NOT NULL, -- Filnavn på importeret CSV
import_batch_id VARCHAR(100) NOT NULL, -- Unik ID for denne import batch
file_hash VARCHAR(64), -- SHA256 hash af CSV fil for duplikat check
-- Validering
is_current BOOLEAN DEFAULT TRUE, -- Er dette den aktuelle pris?
price_change_pct DECIMAL(8,4), -- Procentvis ændring fra forrige pris
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (product_id) REFERENCES bygma_products(id) ON DELETE CASCADE,
-- Indices for performance
INDEX idx_product_date (product_id, import_date),
INDEX idx_import_batch (import_batch_id),
INDEX idx_import_date (import_date),
INDEX idx_current (is_current),
INDEX idx_file_hash (file_hash),
-- Unik constraint: kun én pris per produkt per import
UNIQUE KEY unique_product_import (product_id, import_batch_id)
);
-- Log over imports for sporing
CREATE TABLE IF NOT EXISTS bygma_import_log (
id INT AUTO_INCREMENT PRIMARY KEY,
-- Import detaljer
import_batch_id VARCHAR(100) NOT NULL UNIQUE,
filename VARCHAR(255) NOT NULL,
filepath VARCHAR(500) NOT NULL,
file_size BIGINT NOT NULL,
file_hash VARCHAR(64) NOT NULL,
-- Import statistik
total_rows INT NOT NULL DEFAULT 0,
processed_rows INT NOT NULL DEFAULT 0,
successful_rows INT NOT NULL DEFAULT 0,
failed_rows INT NOT NULL DEFAULT 0,
new_products INT NOT NULL DEFAULT 0,
updated_prices INT NOT NULL DEFAULT 0,
-- Fejl og advarsler
error_summary JSON, -- Samling af fejl der opstod
warnings JSON, -- Advarsler (fx store prisændringer)
-- Import tider
started_at TIMESTAMP NOT NULL,
completed_at TIMESTAMP,
duration_seconds INT,
-- Status
status ENUM('running', 'completed', 'failed', 'cancelled') DEFAULT 'running',
imported_by VARCHAR(100), -- Hvem startede importen
INDEX idx_batch_id (import_batch_id),
INDEX idx_filename (filename),
INDEX idx_status (status),
INDEX idx_started_at (started_at),
INDEX idx_file_hash (file_hash)
);
-- Aktuelle priser view for nem adgang
CREATE OR REPLACE VIEW bygma_current_prices AS
SELECT
p.id as product_id,
p.product_code,
p.product_group,
p.product_name,
p.unit,
p.db_number,
p.ean_number,
ph.gross_price,
ph.net_price,
ph.import_date,
ph.import_file,
p.is_active as product_active
FROM bygma_products p
JOIN bygma_price_history ph ON p.id = ph.product_id
WHERE ph.is_current = TRUE
AND p.is_active = TRUE;
-- Integration med eksisterende materials system
-- Denne tabel mapper Bygma produkter til vores materials tabel
CREATE TABLE IF NOT EXISTS bygma_materials_mapping (
id INT AUTO_INCREMENT PRIMARY KEY,
-- Links
bygma_product_id INT NOT NULL,
material_id INT, -- Kan være NULL hvis ikke mapped endnu
-- Mapping detaljer
mapping_type ENUM('automatic', 'manual', 'verified') DEFAULT 'automatic',
mapping_confidence DECIMAL(3,2), -- 0.00-1.00 confidence score
mapping_notes TEXT,
-- Auto-sync indstillinger
auto_update_price BOOLEAN DEFAULT TRUE, -- Skal priser auto-opdateres i materials?
price_markup_pct DECIMAL(8,4) DEFAULT 0, -- Markup på Bygma priser
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
mapped_by VARCHAR(100),
FOREIGN KEY (bygma_product_id) REFERENCES bygma_products(id) ON DELETE CASCADE,
INDEX idx_bygma_product (bygma_product_id),
INDEX idx_material (material_id),
INDEX idx_mapping_type (mapping_type),
INDEX idx_auto_update (auto_update_price),
-- Sikr kun én mapping per Bygma produkt
UNIQUE KEY unique_bygma_mapping (bygma_product_id)
);
-- Triggers til at opdatere timestamps og vedligeholde data integritet
-- Trigger: Opdater last_seen når der kommer ny pris
DELIMITER //
CREATE TRIGGER tr_bygma_products_update_last_seen
AFTER INSERT ON bygma_price_history
FOR EACH ROW
BEGIN
UPDATE bygma_products
SET last_seen = NEW.import_date,
updated_at = CURRENT_TIMESTAMP
WHERE id = NEW.product_id;
END//
-- Trigger: Deaktiver gamle priser når nye kommer
CREATE TRIGGER tr_bygma_price_history_deactivate_old
AFTER INSERT ON bygma_price_history
FOR EACH ROW
BEGIN
-- Deaktiver alle andre priser for dette produkt
UPDATE bygma_price_history
SET is_current = FALSE
WHERE product_id = NEW.product_id
AND id != NEW.id;
END//
-- Trigger: Beregn prisændring procentvis
CREATE TRIGGER tr_bygma_price_history_calculate_change
BEFORE INSERT ON bygma_price_history
FOR EACH ROW
BEGIN
DECLARE prev_price DECIMAL(15,2);
-- Find forrige pris
SELECT net_price INTO prev_price
FROM bygma_price_history
WHERE product_id = NEW.product_id
AND is_current = TRUE
LIMIT 1;
-- Beregn ændring hvis der er en forrige pris
IF prev_price IS NOT NULL AND prev_price > 0 THEN
SET NEW.price_change_pct = ((NEW.net_price - prev_price) / prev_price) * 100;
END IF;
END//
DELIMITER ;
-- Indsæt Bygma som leverandør hvis ikke allerede eksisterer
INSERT IGNORE INTO bygma_product_groups (group_code, group_name) VALUES
('1000', 'Træ og byggeplader'),
('2000', 'Tagmaterialer'),
('3000', 'Isolering'),
('4000', 'Vinduer og døre'),
('5000', 'Beslag og skruer'),
('6000', 'Maling og behandling'),
('7000', 'VVS og el'),
('8000', 'Værktøj'),
('9000', 'Øvrige materialer');
-- Eksempel på indeks optimering for store datasets
-- Partition på import_date hvis vi får mange måneders data
-- ALTER TABLE bygma_price_history
-- PARTITION BY RANGE (YEAR(import_date) * 100 + MONTH(import_date))
-- (PARTITION p202501 VALUES LESS THAN (202502),
-- PARTITION p202502 VALUES LESS THAN (202503),
-- PARTITION p_future VALUES LESS THAN MAXVALUE);
-- Grants til applikation bruger (tilpas brugernavne efter behov)
-- GRANT SELECT, INSERT, UPDATE ON tilbudgivern.bygma_* TO 'tilbudgivern_user'@'localhost';
-- GRANT SELECT ON tilbudgivern.bygma_current_prices TO 'tilbudgivern_user'@'localhost';