wiki:BuyPackage

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

Актери

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

Чекор 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 & 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, веднаш да го искористи при создавање термин
Last modified 3 weeks ago Last modified on 03/03/26 09:40:05
Note: See TracWiki for help on using the wiki.