wiki:BuyPackage

Version 1 (modified by 202033, 3 weeks ago) ( diff )

--

Купување пакет

Актери

  • Најавен корисник (клиент)

Чекор 1

Најавениот корисник ја отвора страницата за пакети, на пример:

  • страницата Book an Appointment (/book), каде се прикажува листа на пакети, или
  • страницата My Packages (/my-packages).

Системот му прикажува листа на достапни пакети со:

  • име на пакет,
  • максимален број користења (max_usage),
  • вкупна цена,
  • услугите што се вклучени во пакетот.

Податоците за пакетите се вчитуваат со следниот SQL:

SELECT
  p.package_id,
  p.name AS package_name,
  p.max_usage,
  CASE
    WHEN EXISTS (
      SELECT 1
      FROM information_schema.columns
      WHERE table_name = 'package'
        AND column_name = 'total_price'
    ) THEN p.total_price
    ELSE package_price.calc_total_price
  END::numeric AS total_price,
  s.service_id,
  s.name AS service_name,
  ps.discounted_price
FROM Package p
LEFT JOIN LATERAL (
  SELECT COALESCE(SUM(ps2.discounted_price), 0)::numeric AS calc_total_price
  FROM PackageService ps2
  WHERE ps2.package_id = p.package_id
) package_price ON true
LEFT JOIN PackageService ps
  ON ps.package_id = p.package_id
LEFT JOIN Service s
  ON s.service_id = ps.service_id
ORDER BY p.package_id, s.name;

Чекор 2

Корисникот избира конкретен пакет и кликнува на:

  • Buy only / Buy package – ако сака да го купи пакетот без веднаш да резервира термин, или
  • Buy & use now – ако сака да го купи пакетот и веднаш да го искористи при резервирање термин.

Во двата случаи, системот треба да го купи пакетот за корисникот.

Чекор 3

Системот го проверува избраниот пакет и ја пресметува вкупната цена што треба да се плати.

Се вчитува пакетот од базата според package_id:

SELECT
  p.package_id,
  p.name,
  p.max_usage,
  CASE
    WHEN EXISTS (
      SELECT 1
      FROM information_schema.columns
      WHERE table_name = 'package'
        AND column_name = 'total_price'
    ) THEN p.total_price
    ELSE package_price.calc_total_price
  END::numeric AS total_price
FROM package p
LEFT JOIN LATERAL (
  SELECT COALESCE(SUM(ps.discounted_price), 0)::numeric AS calc_total_price
  FROM packageservice ps
  WHERE ps.package_id = p.package_id
) package_price ON true
WHERE p.package_id = $1;

Параметар:

  • $1 – package_id на избраниот пакет.

Ако пакетот не постои, системот враќа грешка и купувањето се прекинува.

Чекор 4

Доколку пакетот е валиден, системот креира запис дека корисникот го купил пакетот, преку складираната функција sp_user_purchase_package:

SELECT sp_user_purchase_package($1::int, $2::int) AS purchase_id;

Параметри:

  • $1 – user_id на најавениот корисник,
  • $2 – package_id на избраниот пакет.

Функцијата sp_user_purchase_package вметнува ред во табелата UserPackagePurchase со:

  • user_id – корисникот кој купува пакет,
  • package_id – избраниот пакет,
  • total_uses – максимален број користења (max_usage од Package),
  • remaining_uses – почетно еднакво на total_uses,
  • status – 'ACTIVE'.

Чекор 5

Потоа системот креира запис за плаќањето на овој пакет во табелата payment. Ова плаќање е поврзано со купениот пакет (package_purchase_id), а не со конкретен термин (appointment_id е NULL):

INSERT INTO payment (amount, method, status, appointment_id, points_used, package_purchase_id)
VALUES ($1::numeric, $2::text, 'PENDING', NULL, 0, $3::int)
RETURNING payment_id;

Параметри:

  • $1 – вкупната цена на пакетот (total_price од Чекор 3),
  • $2 – метод на плаќање, на пример 'online' или 'CARD',
  • $3 – purchase_id добиен од sp_user_purchase_package.

Во овој тек:

  • appointment_id е NULL (се купува пакет, не термин),
  • points_used = 0 – не се дозволува користење лојалти поени за купување пакет.

Ограничувањата за ова плаќање се спроведуваат и преку trigger функцијата trg_payment_validate, која осигурува дека:

  • има или appointment_id или package_purchase_id,
  • за купување пакет (appointment_id IS NULL и package_purchase_id IS NOT NULL) сумата на плаќањето одговара на вкупната цена на пакетот,
  • не може да се користат лојалти поени (points_used мора да биде 0).

Чекор 6

По успешно креирање на плаќањето, системот го означува плаќањето како платено и доделува лојалти поени на корисникот со повик на функцијата sp_mark_payment_paid:

SELECT sp_mark_payment_paid($1::int) AS points_used;

Параметар:

  • $1 – payment_id на креираното плаќање.

Во случај на купување пакет (т.е. кога плаќањето има package_purchase_id и appointment_id IS NULL), функцијата:

  • проверува дека не постои друго 'PAID' плаќање за истото package_purchase_id,
  • ја ажурира табелата payment:
    • status = 'PAID' ,
    • amount = вкупната цена на пакетот,
    • points_used = 0,
  • се грижи да постои лојалти картичка за корисникот преку sp_ensure_loyalty_card,
  • пресметува колку поени да се доделат (на пример 5% од вкупната цена на пакетот) и ги зголемува points во табелата loyaltycard.

Пример логика за доделување поени (во функцијата):

  • v_points_earned := FLOOR(COALESCE(v_total_price, 0) * 0.05);
  • UPDATE loyaltycard SET points = points + v_points_earned WHERE user_id = v_user_id;

Чекор 7

По означувањето на плаќањето како платено, системот ги враќа деталите за купениот пакет за прикажување на корисникот:

SELECT
  upp.purchase_id,
  upp.package_id,
  p.name AS package_name,
  upp.total_uses,
  upp.remaining_uses,
  upp.status,
  upp.purchased_at,
  upp.expires_at
FROM userpackagepurchase upp
JOIN package p
  ON p.package_id = upp.package_id
WHERE upp.purchase_id = $1
LIMIT 1;

Параметар:

  • $1 – purchase_id на купениот пакет.

Дополнително, се вчитува и моменталниот број лојалти поени:

SELECT points
FROM loyaltycard
WHERE user_id = $1;

Резултат

  • Во табелата UserPackagePurchase постои нов запис за купениот пакет, со status = 'ACTIVE' и иницијално remaining_uses = total_uses.
  • Во табелата payment постои запис за плаќањето на пакетот со status = 'PAID' , правилен износ и points_used = 0.
  • Во табелата loyaltycard се ажурира бројот на поени на корисникот (се доделуваат поени за купениот пакет).
  • Корисникот на екранот добива потврда дека пакетот е успешно купен и може:
    • да го види во My Packages со број на преостанати користења, или
    • во случај на опцијата Buy & use now, веднаш да го искористи при создавање термин
Note: See TracWiki for help on using the wiki.