wiki:UseCase0001PrototypeImplementationDB

Version 3 (modified by 231175, 11 hours ago) ( diff )

--

UseCase: Креирање на курс

Актер

Експерт

Цел

Експертот сака да креира нов курс во системот.

Предуслов: табела expert_course

Шемата нема врска помеѓу expert и course, па нема каде да се запише кој експерт го креирал курсот. Оваа табела мора да се додаде во DDL пред овој случај на употреба да работи.

CREATE TABLE expert_course (
    expert_id  bigint NOT NULL,
    course_id  bigint NOT NULL,
    CONSTRAINT pk_expert_course PRIMARY KEY (expert_id, course_id),
    CONSTRAINT fk_ec_expert FOREIGN KEY (expert_id)
        REFERENCES expert (expert_id) ON DELETE CASCADE,
    CONSTRAINT fk_ec_course FOREIGN KEY (course_id)
        REFERENCES course (course_id) ON DELETE CASCADE
);

Главен тек

  • На експертот му се прикажува долга форма со полиња кои треба да ги пополни.

  • Експертот ги пополнува сите полиња и кликнува на копчето Create Course

  • Експертот е навигиран кон почетната страна за експерти. Во база се креира новиот курс.
BEGIN;

DROP TABLE IF EXISTS temp_course_id;
DROP TABLE IF EXISTS temp_course_version_id;
DROP TABLE IF EXISTS temp_course_content_id;
DROP TABLE IF EXISTS temp_course_lecture_id;
DROP TABLE IF EXISTS temp_tag_id;

CREATE TEMP TABLE temp_course_id         (course_id BIGINT);
CREATE TEMP TABLE temp_course_version_id (course_version_id BIGINT);
CREATE TEMP TABLE temp_course_content_id (course_content_id BIGINT);
CREATE TEMP TABLE temp_course_lecture_id (course_lecture_id BIGINT);
CREATE TEMP TABLE temp_tag_id            (tag_id BIGINT, tag_type tag_type);

-- 1. Курс
WITH new_course AS (
    INSERT INTO course (image_url, difficulty, duration_minutes, price, color)
    VALUES ('https://example.com/image.png', 'intermediate', 120, 50.00, '#008CC2')
    RETURNING course_id
)
INSERT INTO temp_course_id (course_id)
SELECT course_id FROM new_course;

-- 2. Верзија на курс
WITH new_course_version AS (
    INSERT INTO course_version (version_number, created_at, is_active, course_id)
    SELECT 1, CURRENT_DATE, true, course_id FROM temp_course_id
    RETURNING course_version_id
)
INSERT INTO temp_course_version_id (course_version_id)
SELECT course_version_id FROM new_course_version;

-- 3. Преводи на курсот
--    what_will_be_learned е text[] колона, па се внесува заедно со преводот.
INSERT INTO course_translate (language_id, title_short, title,
                              description_short, description, description_long,
                              what_will_be_learned, course_id)
SELECT (SELECT id FROM language WHERE value = 'en'),
       'Advanced Sales',
       'Advanced Sales For Senior Salesman',
       'Short desc',
       'Normal desc',
       'Long desc',
       ARRAY['Advanced sales techniques',
             'How to successfully close deals'],
       course_id
FROM temp_course_id;

INSERT INTO course_translate (language_id, title_short, title,
                              description_short, description, description_long,
                              what_will_be_learned, course_id)
SELECT (SELECT id FROM language WHERE value = 'mk'),
       'Напредна Продажба',
       'Напредна Продажба за Сениор Продавачи',
       'Кратка дескрипција',
       'Нормална дескрипција',
       'Долга дескрипција',
       ARRAY['Напредни техники на продажба',
             'Како до успешно затворање на продажби'],
       course_id
FROM temp_course_id;

-- 4. Модул
WITH new_course_content AS (
    INSERT INTO course_content (position, course_version_id)
    SELECT 1, course_version_id FROM temp_course_version_id
    RETURNING course_content_id
)
INSERT INTO temp_course_content_id (course_content_id)
SELECT course_content_id FROM new_course_content;

INSERT INTO course_content_translate (title, language_id, course_content_id)
SELECT 'Module 1: Sales Strategies',
       (SELECT id FROM language WHERE value = 'en'),
       course_content_id
FROM temp_course_content_id;

INSERT INTO course_content_translate (title, language_id, course_content_id)
SELECT 'Модул 1: Продажни Стратегии',
       (SELECT id FROM language WHERE value = 'mk'),
       course_content_id
FROM temp_course_content_id;

-- 5. Лекција
WITH new_course_lecture AS (
    INSERT INTO course_lecture (duration_minutes, position, content_type, course_content_id)
    SELECT 30, 1, 'video', course_content_id FROM temp_course_content_id
    RETURNING course_lecture_id
)
INSERT INTO temp_course_lecture_id (course_lecture_id)
SELECT course_lecture_id FROM new_course_lecture;

INSERT INTO course_lecture_translate (title, language_id, content_file_name,
                                      description, content_text, course_lecture_id)
SELECT 'Lecture 1: Intro',
       (SELECT id FROM language WHERE value = 'en'),
       'lecture1.mp4',
       'Introduction to advanced sales',
       NULL,                       -- content_type = 'video' -> нема текстуална содржина
       course_lecture_id
FROM temp_course_lecture_id;

INSERT INTO course_lecture_translate (title, language_id, content_file_name,
                                      description, content_text, course_lecture_id)
SELECT 'Предавање 1: Вовед',
       (SELECT id FROM language WHERE value = 'mk'),
       'lecture1.mp4',
       'Вовед во напредна продажба',
       NULL,
       course_lecture_id
FROM temp_course_lecture_id;

-- 6. Тагови
--    ВНИМАНИЕ: ова креира НОВИ тагови при секое креирање на курс.
--    Во продукција формата треба да нуди постоечки тагови, па овој блок
--    се заменува со SELECT врз tag/tag_translate по избраните вредности.
WITH new_tags AS (
    INSERT INTO tag (tag_type)
    VALUES ('skill'), ('topic')
    RETURNING tag_id, tag_type
)
INSERT INTO temp_tag_id (tag_id, tag_type)
SELECT tag_id, tag_type FROM new_tags;

INSERT INTO tag_translate (language_id, value, tag_id)
SELECT (SELECT id FROM language WHERE value = 'en'),
       CASE tag_type WHEN 'skill' THEN 'Skill' WHEN 'topic' THEN 'Topic' END,
       tag_id
FROM temp_tag_id;

INSERT INTO tag_translate (language_id, value, tag_id)
SELECT (SELECT id FROM language WHERE value = 'mk'),
       CASE tag_type WHEN 'skill' THEN 'Вештина' WHEN 'topic' THEN 'Тема' END,
       tag_id
FROM temp_tag_id;

INSERT INTO course_tag (tag_id, course_id)
SELECT t.tag_id, c.course_id
FROM temp_tag_id t
CROSS JOIN temp_course_id c;

-- 7. Врска експерт <-> курс
INSERT INTO expert_course (course_id, expert_id)
SELECT course_id, :expert_id
FROM temp_course_id;

COMMIT;

Алтернативен тек

  • Доколку експертот не пополнил некои од полињата, се покажува порака за грешка.

Валидацијата се прави на ниво на апликација пред да се почне трансакцијата. Базата ги штити следниве полиња преку NOT NULL, но грешката тогаш доаѓа како 23502 откако курсот е делумно креиран:

Табела Задолжителни полиња
course image_url, color, difficulty, duration_minutes, price
course_translate title_short, title, description_short, description, description_long, what_will_be_learned, language_id
course_content position
course_content_translate title, language_id
course_lecture position, duration_minutes, content_type
course_lecture_translate title, description, language_id

Дополнителни ограничувања кои можат да фрлат грешка:

  • ck_course_duration_positive и ck_course_price_non_negative — времетраењето мора да е поголемо од нула, цената не смее да е негативна.
  • uq_course_content_position и uq_course_lecture_position — две модули или две лекции не смеат да имаат иста позиција.
  • uq_course_translate — не смее да има два превода на ист јазик за ист курс.

Забелешки

  • Сите вредности за difficulty, content_type и tag_type мора да се со мали букви — тоа се лабели на PostgreSQL enum типови и се осетливи на голема/мала буква.
  • tag_type има само две вредности: skill и topic. Вредноста interest не постои и предизвикува грешка, а не празен резултат.
  • Целиот блок мора да биде во една трансакција. Ако некој од чекорите падне, курсот не смее да остане делумно креиран.
  • uq_course_version_one_active дозволува само една активна верзија по курс. При креирање на нова верзија, старата мора прво да се постави на is_active = false.

Attachments (2)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.