Changes between Version 2 and Version 3 of AdvancedAppDevelopment


Ignore:
Timestamp:
09/03/25 20:38:33 (4 days ago)
Author:
185022
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • AdvancedAppDevelopment

    v2 v3  
    1 Развојот на овој дел од апликацијата може да се види на следниот линк:
    2 
    3 Back-end: https://github.com/borisdz/DistributorApp-Web/tree/dev-advanced
    4 
    5 Front-end: https://github.com/borisdz/DistributorApp-Frontend/tree/dev
     1===== Развојот на овој дел од апликацијата може да се види на следниот линк:
     2
     3'''Back-end''': https://github.com/borisdz/DistributorApp-Web/tree/dev-advanced
     4
     5'''Front-end''': https://github.com/borisdz/DistributorApp-Frontend/tree/dev
     6
     7[[PageOutline(2-4, Содржина, inline)]]
     8
     9== Индекси
     10
     11Заради забрзување на пристап и пребарување низ базата, креирани се индекси на секој надворешен клуч во секој ентитет.
     12
     13{{{#!sql
     14create index idx_article_manufacturerId on article(man_id);
     15create index idx_article_categoryId on article(art_id);
     16create index idx_articleUnit_warehouseId on article_unit(wh_id);
     17create index idx_articleUnit_orderId on article_unit(ord_id);
     18create index idx_city_regionId on city(region_id);
     19create index idx_warehouse_cityId on warehouse(city_id);
     20create index idx_vehicle_warehouseId on vehicle(wh_id);
     21create index idx_user_cityId on users(city_id);
     22create index idx_user_userEmail on users(user_email);
     23create index idx_manager_userId on manager(user_id);
     24create index idx_manager_warehouseId on manager(wh_id);
     25create index idx_delivery_dStatusId on delivery(d_status_id);
     26create index idx_delivery_vehicleId on delivery(veh_id);
     27create index idx_driver_userId on driver(user_id);
     28create index idx_driver_vehicleId on driver(veh_id);
     29create index idx_imageStore_entityType on image_store(img_ent_type);
     30create index idx_imageStore_entityId on image_store(img_ent_id);
     31create index idx_price_articleId on price(art_id);
     32create index idx_proForma_pfStatusId on pro_forma(pf_status_id);
     33create index idx_orders_oStatusId on orders(o_status_id);
     34create index idx_orders_deliveryId on orders(del_id);
     35create index idx_orders_pfId on orders(pf_id);
     36create index idx_unitPrice_unitId on unit_price(unit_id);
     37create index idx_unitPrice_priceId on unit_price(price_id);
     38create index idx_customerWeekday_customerId on customer_weekday(cust_id);
     39create index idx_customerWeekday_dayId on customer_weekday(day_id);
     40create index idx_token_userId on token_(t_user);
     41}}}
     42
     43== Процедури
     44
     45=== Промена на број на продажби на секој артикл при промена на цена
     46
     47{{{#!sql
     48create procedure ArticleSalesChangeOnPriceChange()
     49language plpgsql
     50as $$
     51begin
     52with PriceChanges as (
     53        select
     54                p.art_id,
     55                p.price,
     56                p.price_eff_date,
     57                lag(p.price) over (partition by p.art_id order by p.price_eff_date) as prevPrice
     58        from price p
     59),
     60FilteredPrice as (
     61        select
     62                art_id,
     63                price,
     64                price_eff_date
     65        from PriceChanges
     66        where prevPrice is null or abs(price - prevPrice) >= 1
     67),
     68SalesByPrice as (
     69        select
     70                p.art_id,
     71                fp.price,
     72                fp.price_eff_date,
     73                count(au.unit_id) as units_sold,
     74                count(au.unit_id) * fp.price as revenue
     75        from article_unit au
     76                join orders o on au.ord_id = o.ord_id
     77                join unit_price up on up.unit_id = au.unit_id
     78                join price p on up.price_id = p.price_id
     79                join FilteredPrice fp on p.art_id = fp.art_id and p.price_eff_date = fp.price_eff_date
     80        where o.ord_date >= fp.price_eff_date and o.ord_date < coalesce(
     81                                                                        (select min(fp2.price_eff_date)
     82                                                                        from FilteredPrice fp2
     83                                                                        where fp2.art_id = fp.art_id and fp2.price_eff_date > fp.price_eff_date),
     84                                                                        '9999-12-31'
     85        )
     86        group by p.art_id, fp.price, fp.price_eff_date
     87)
     88select
     89        a.art_name as articleName,
     90        sp.price as unitPrice,
     91        sp.price_eff_date as priceEffectiveDate,
     92        sp.units_sold,
     93        sp.revenue
     94from SalesByPrice sp
     95        join article a on sp.art_id = a.art_id
     96order by a.art_name, sp.price_eff_date;
     97end;
     98$$;
     99}}}
     100
     101=== Споредба на потрошувачка по категорија по региони изразено во количина и приход
     102
     103{{{#!sql
     104create procedure SalesComparisonByCategoryAndRegionInQuantityAndIncome()
     105language plpgsql
     106as $$
     107begin
     108with ArticleSales as (
     109    select a.art_id,
     110           a.ctg_id,
     111           w.wh_id,
     112           c.city_id,
     113           r.region_id,
     114           p.price as unitPrice,
     115           count(au.unit_id) as unitsSold,
     116           count(au.unit_id)*p.price as income
     117    from article_unit au
     118    join unit_price up on up.unit_id = au.unit_id
     119    join price p on up.price_id = p.price_id
     120    join article a on p.art_id  = a.art_id
     121    join warehouse w on au.wh_id = w.wh_id
     122    join city c on w.city_id = c.city_id
     123    join region r on c.region_id = r.region_id
     124    join orders o on au.ord_id = o.ord_id
     125    where o.ord_date>=p.price_eff_date
     126    group by a.art_id, a.ctg_id, w.wh_id, c.city_id, r.region_id, p.price, p.price
     127)
     128select r.region_name as region,
     129       cat.ctg_name as category,
     130       sum(asales.unitsSold) as totalUnitsSold,
     131       sum(asales.income) as totalIncome
     132from ArticleSales asales
     133join category cat on asales.ctg_id=cat.ctg_id
     134join region r on asales.region_id=r.region_id
     135group by r.region_name, cat.ctg_name
     136order by r.region_name, totalIncome desc;
     137end;
     138$$;
     139}}}
     140
     141=== Прогноза на потрошувачка на артикли од магацинот според продажба во претходните недели, за подобра претпоставка за набавка на нови артикли
     142
     143{{{#!sql
     144create procedure SalesPrognosingOnArticlesAccToSalesInPreviousWeeks()
     145language plpgsql
     146as $$
     147begin
     148with WeeklySales as (
     149        select a.art_id,
     150                date_trunc('week', o.ord_date) as week_start,
     151                count(*) as units_sold
     152        from orders o
     153        join article_unit au on o.ord_id = au.ord_id
     154        join unit_price up on au.unit_id = up.unit_id
     155        join price p on up.price_id = p.price_id
     156        join article a on p.art_id = a.art_id
     157        where au.wh_id = 1
     158                and o.ord_date between current_date - interval '10 weeks'
     159                        and current_date - interval '2 week'
     160        group by a.art_id, date_trunc('week',o.ord_date)
     161),
     162AvgSales as (
     163        select art_id,
     164        avg(units_sold) as avg_units_sold
     165        from WeeklySales
     166        group by art_id
     167),
     168Inventory as (
     169select a.art_id, count(distinct au.unit_id) as currentStock
     170from article_unit au
     171         join warehouse w on au.wh_id = w.wh_id
     172         join unit_price up on au.unit_id = up.unit_id
     173         join price p on up.price_id = p.price_id
     174         join article a on p.art_id = a.art_id
     175where w.wh_id = 1
     176group by a.art_id
     177order by currentStock
     178)
     179select i.art_id,
     180        a.art_name,
     181        i.currentStock,
     182        avs.avg_units_sold,
     183        (i.currentStock - avs.avg_units_sold) as remaining_after_forecast
     184from Inventory i
     185join article a on i.art_id = a.art_id
     186join AvgSales avs on i.art_id = avs.art_id;
     187end;
     188$$;
     189}}}
     190
     191=== Продажба на артикли во одреден магацин по квартали
     192
     193{{{#!sql
     194create procedure ArticleSalesInWarehouseByQuarters()
     195language plpgsql
     196as $$
     197begin
     198select w.wh_id as warehouseId,
     199       w.wh_adr as warehouseAddress,
     200       c.city_name as warehouseCity,
     201       r.region_name as warehouseRegion,
     202       extract(year from o.ord_date) as "year",
     203       extract(quarter from o.ord_date) as "quarter",
     204       count(au.unit_id) as totalArticlesSold,
     205       sum(o.ord_sum) as totalSales
     206from warehouse w
     207join city c on w.city_id = c.city_id
     208join region r on c.region_id = r.region_id
     209join article_unit au on w.wh_id = au.wh_id
     210join orders o on au.ord_id = o.ord_id
     211group by w.wh_id, w.wh_adr, c.city_name, r.region_name, extract(year from o.ord_date), extract(quarter from o.ord_date)
     212order by w.wh_id,"year","quarter";
     213end;
     214$$;
     215}}}
     216
     217=== Годишен приход, профит и трошок по магацини
     218
     219{{{#!sql
     220create procedure YearlyIncomeProfitAndExpensesByWarehouses()
     221language plpgsql
     222as $$
     223begin
     224select w.wh_id as warehouseId,
     225       c.city_name as warehouseCity,
     226       r.region_name as warehouseRegion,
     227       extract(year from o.ord_date) as "year",
     228       sum(o.ord_sum) as totalIncome,
     229       sum(ord_sum)-sum(au.unit_cost_price) as total_profit
     230from warehouse w
     231         join city c on w.city_id = c.city_id
     232         join region r on c.region_id = r.region_id
     233         join article_unit au on w.wh_id = au.wh_id
     234         join orders o on au.ord_id = o.ord_id
     235group by w.wh_id, c.city_name, r.region_name, o.ord_date
     236order by w.wh_id,"year";
     237end;
     238$$;
     239}}}
     240
     241=== Аналитика на продукти по приход, потрошувачка, профит на определен период
     242
     243{{{#!sql
     244create procedure AnalyticsOfProductsByIncomeExpensesAndProfit()
     245language plpgsql
     246as $$
     247begin
     248with ProductSales as (select a.art_id,
     249                             a.art_name,
     250                             cat.ctg_name                           as category,
     251                             sum(p.price)                           as totalIncome,
     252                             sum(au.unit_cost_price)                as totalCost,
     253                             sum(p.price) - sum(au.unit_cost_price) as totalProfit,
     254                             count(au.unit_id)                      as totalUnitsSold
     255                      from article_unit au
     256                                join unit_price up on up.unit_id = au.unit_id
     257                                join price p on up.price_id = p.price_id
     258                                join article a on p.art_id = a.art_id
     259                            join category cat on a.ctg_id = cat.ctg_id
     260                            join orders o on au.ord_id = o.ord_id
     261                      where o.ord_date between '2024-01-01' and '2024-12-31'
     262                        and o.ord_date >= p.price_eff_date
     263                      group by a.art_id, a.art_name, cat.ctg_name)
     264select art_id,
     265       art_name,
     266       category,
     267       totalUnitsSold,
     268       totalIncome,
     269       totalCost,
     270       totalProfit
     271from ProductSales
     272order by totalProfit desc;
     273end;
     274$$;
     275}}}
     276
     277== Погледи
     278
     279=== Чинење на единка артикл во моментот
     280
     281{{{#!sql
     282create view article_unit_current_cost as
     283select au.unit_id, uch.cost_price
     284from article_unit au
     285left join (
     286        select unit_id,
     287                cost_price,
     288                row_number() over (
     289                        partition by unit_id order by effective_date desc
     290                ) as rn
     291        from unit_cost_history
     292) uch on au.unit_id = uch.unit_id and uch.rn=1;
     293}}}
     294
     295=== Последен сервис на возило
     296
     297{{{#!sql
     298create view vehicle_latest_service as
     299select v.veh_id,
     300        vs.service_date as last_service_date,
     301        vs.service_km as last_service_km,
     302        vs.service_next_date,
     303        vs.service_next_km
     304from vehicle v
     305left join (
     306        select veh_id,
     307        service_date,
     308        service_km,
     309        servicie_next_date,
     310        service_next_km,
     311        row_number() over (partition by veh_id order by service_date desc) as rn
     312                from vehicle_service
     313) vs on v.veh_id = vs.veh_id and vs.rn=1;
     314}}}
     315
     316== Функции и Тригери
     317
     318=== `Update order sum` функција
     319
     320{{{#!sql
     321create or replace function update_order_sum()
     322returns trigger as $$
     323begin
     324        update orders
     325        set ord_sum = (
     326                select coalesce(sum(total_price),0)
     327                from order_item
     328                where ord_id = new.ord_id)
     329        where ord_id = new.ord_id;
     330return new;
     331end;
     332$$ language plpgsql;
     333}}}
     334
     335==== `Order item after change` тригер
     336
     337{{{#!sql
     338create trigger order_item_after_change
     339after insert or update or delete on order_item
     340for each row execute function update_order_sum();
     341}}}