Домени
Парични вредности со деловни граници
Опис
Доменот positive_money дефинира валидни парични вредности со деловни граници — не дозволува негативни суми, ниту неразумно големи износи (над 1.000.000). Се користи за сите парични полиња во базата (цени, плаќања, вкупни износи).
Имплементација
CREATE DOMAIN project.positive_money AS NUMERIC(12,2) CHECK (VALUE >= 0 AND VALUE < 1000000);
ДДВ со законски дозволени стапки
Опис
Доменот vat_percentage дозволува само законски дозволени стапки на ДДВ во Македонија: 0%, 5%, 10% и 18%. Спречува внесување на невалидни стапки како 17% или 19%.
Имплементација
CREATE DOMAIN project.vat_percentage AS NUMERIC(5,2) CHECK (VALUE IN (0, 5, 10, 18));
Статус на маса
Опис
Доменот table_status дозволува само однапред дефинирани статуси на маса: СЛОБОДНА, ЗАФАТЕНА, РЕЗЕРВИРАНА, НЕДОСТАПНА. Овозможува конзистентност на статусите низ целата апликација.
Имплементација
CREATE DOMAIN project.table_status AS TEXT
CHECK (VALUE IN ('СЛОБОДНА', 'ЗАФАТЕНА', 'РЕЗЕРВИРАНА', 'НЕДОСТАПНА'));
Статус на нарачка
Опис
Доменот order_status дозволува само валидни статуси на нарачка во текот на нејзиниот животен циклус: НОВА, ПОРАЧАНО, ПОДГОТВЕНО, СЕРВИРАНО, ПЛАТЕНА, ОТКАЖАНА.
Имплементација
CREATE DOMAIN project.order_status AS TEXT
CHECK (VALUE IN ('НОВА', 'ПОРАЧАНО', 'ПОДГОТВЕНО', 'СЕРВИРАНО', 'ПЛАТЕНА', 'ОТКАЖАНА'));
Тип на инвентарна операција
Опис
Доменот inventory_operation дозволува само валидни типови на инвентарни операции: ПОЧЕТНА, ПРИЕМ, ПРОДАЖБА, ОТПИС, КОРЕКЦИЈА. Овозможува конзистентно евидентирање на движењата на залиха.
Имплементација
CREATE DOMAIN project.inventory_operation AS TEXT
CHECK (VALUE IN ('ПОЧЕТНА', 'ПРИЕМ', 'ПРОДАЖБА', 'ОТПИС', 'КОРЕКЦИЈА'));
Комплексна email валидација
Опис
Доменот valid_email валидира email адреси со комплексен regex и дополнителни услови:
- Основен regex за валиден формат
- Ограничување на должина (макс 255)
- Забрана за последователни точки (
..) - Забрана за започнување или завршување со точка
Имплементација
CREATE DOMAIN project.valid_email AS VARCHAR(255)
CHECK (
VALUE ~ '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$'
AND LENGTH(VALUE) <= 255
AND POSITION('..' IN VALUE) = 0
AND VALUE !~ '^\.'
AND VALUE !~ '\.$'
);
Македонски мобилен телефонски број
Опис
Доменот mkd_phone валидира македонски мобилни телефонски броеви во три дозволени формати:
+389 7X XXX XXX(меѓународен формат)0 7X XXX XXX(домашен формат со водечка нула)7X XXX XXX(краток формат)
Дозволува опционални празни места помеѓу групите цифри.
Имплементација
CREATE DOMAIN project.mkd_phone AS TEXT
CHECK (
VALUE ~ '^\+389\s?7[0-9]{2}\s?[0-9]{3}\s?[0-9]{3}$'
OR VALUE ~ '^0\s?7[0-9]{2}\s?[0-9]{3}\s?[0-9]{3}$'
OR VALUE ~ '^7[0-9]{2}\s?[0-9]{3}\s?[0-9]{3}$'
);
bcrypt password hash валидација
Опис
Доменот password_hash валидира bcrypt hash вредности во стандарден формат $2a$XX$.... Спречува внесување на plain-text лозинки или невалидни hash вредности. Форматот е: $2a$ или $2b$ или $2y$, потоа два броја за cost фактор, потоа $, потоа 53 карактери од base64 алфабетот (./A-Za-z0-9).
Имплементација
CREATE DOMAIN project.password_hash AS TEXT
CHECK (VALUE ~ '^\$2[aby]\$\d{2}\$[./A-Za-z0-9]{53}$');
Примена на домените на постоечки колони
Опис
Домените се применуваат на постоечките колони со ALTER TABLE ... ALTER COLUMN ... TYPE .... Ова автоматски ги валидира сите постоечки вредности против новите ограничувања.
Имплементација
ALTER TABLE project.payment
ALTER COLUMN amount TYPE project.positive_money;
ALTER TABLE project.product
ALTER COLUMN price TYPE project.positive_money;
ALTER TABLE project.order_item
ALTER COLUMN unit_price TYPE project.positive_money;
ALTER TABLE project.settings
ALTER COLUMN vat_percent TYPE project.vat_percentage;
ALTER TABLE project.app_settings
ALTER COLUMN vat_rate TYPE project.vat_percentage;
ALTER TABLE project.restaurant_table
ALTER COLUMN status TYPE project.table_status;
ALTER TABLE project.orders
ALTER COLUMN status TYPE project.order_status;
ALTER TABLE project.inventory
ALTER COLUMN operation_type TYPE project.inventory_operation;
ALTER TABLE project.ingredient_inventory
ALTER COLUMN operation_type TYPE project.inventory_operation;
ALTER TABLE project.app_user
ALTER COLUMN email TYPE project.valid_email,
ALTER COLUMN password_hash TYPE project.password_hash;
Тестирање
Успешно внесување
INSERT INTO project.payment (order_id, amount, method, payment_date) VALUES (1, 100.00, 'КЕШ', NOW());
Негативна сума (грешка)
INSERT INTO project.payment (order_id, amount, method, payment_date) VALUES (1, -50.00, 'КЕШ', NOW()); -- ERROR: value for domain positive_money violates check constraint
Преголема сума (грешка)
INSERT INTO project.payment (order_id, amount, method, payment_date) VALUES (1, 2000000.00, 'КЕШ', NOW()); -- ERROR: value for domain positive_money violates check constraint
Невалиден ДДВ (грешка)
UPDATE project.settings SET vat_percent = 17 WHERE id = 1; -- ERROR: value for domain vat_percentage violates check constraint
Невалиден статус на нарачка (грешка)
UPDATE project.orders SET status = 'НЕПОЗНАТО' WHERE order_id = 1; -- ERROR: value for domain order_status violates check constraint
Невалиден email (грешка)
INSERT INTO project.app_user (username, password_hash, role_id, first_name, last_name, email, active)
VALUES ('test', '$2a$06$abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTU', 1, 'Test', 'User', 'not-an-email', TRUE);
-- ERROR: value for domain valid_email violates check constraint
Заклучок
Со 8 кориснички дефинирани домени се постигнува:
- Централизирана валидација на деловни правила
- Конзистентност на податоците низ целата база
- Повторна употреба на исти ограничувања на повеќе колони
- Полесно одржување — промена на едно место
- Подобрена читливост на шемата
