Algoritmul de Distribuire a Suprasolicitarii
Aceasta pagina descrie in detaliu algoritmul executat de actiunea Acceptare diferente pentru un task ramas in starea EROARE (Q_DISPONIBIL < Q_NECESAR), implementat in WlpServiceImpl.distribuieActivitateOverload(). Acelasi algoritm are si o varianta punctuala, per resursa, descrisa la finalul paginii.
Context
Un task in eroare nu are nicio planificare generata — Pasul 8 al algoritmului de evaluare este sarit pentru taskurile cu eroare blocanta. La Acceptare diferente, sistemul trebuie sa genereze planificarea completa a taskului, tratand distinct:
orele care se incadreaza in capacitatea normal disponibila a fiecarei persoane;
orele care depasesc aceasta capacitate (suprasolicitare/overload), pe care organizatia le accepta explicit.
Faza 1 — alocarea orelor acoperite normal
Se aplica exact algoritmul standard de alocare (aplicaAlocarePlanificariPeTask, aceeasi logica ca la Pasul 8 al evaluarii, sarita initial din cauza erorii): pentru fiecare persoana din WLP_CA_DETALIU, in ordinea descrescatoare a capacitatii ei disponibile in perioada, se aloca ore pe zilele calendarului ei (WLP_CALENDAR) pana la limita capacitatii nete a zilei respective, fara a depasi niciodata necesarul cumulat al taskului. Rezultatul se scrie in WLP_CA_PLANIFICARI cu STARE = 0 (alocare normala), iar cantitatile agregate (Q_ALOCAT) se resincronizeaza pe WLP_CA_DETALIU si WLP_CA.
Daca la finalul Fazei 1 tot necesarul este acoperit, algoritmul se opreste aici (Faza 2 nu se mai executa).
Faza 2 — distribuirea suprasolicitarii
Se calculeaza diferenta ramasa neacoperita:
ore_neacoperite = Q_NECESAR (task) - Q_DISPONIBIL (task)
Se identifica toate zilele lucratoare din perioada taskului, pentru toate persoanele din detalierea lui (WLP_CA_DETALIU join WLP_CALENDAR unde IS_WORKING_DAY = 1), si se calculeaza numarul lor total: total_zile_lucratoare.
Se calculeaza indicele de suprasolicitare per zi:
indice_brut = ore_neacoperite / total_zile_lucratoare
Regulile de rotunjire si distributie sunt urmatoarele:
Conditie |
Comportament |
|---|---|
|
Se rotunjeste la cel mai apropiat numar intreg (partea fractionara |
|
Se aloca intreaga cantitate ( |
|
Se forteaza un minim de 2 ore/zi, aplicat pe un numar de zile determinat prin |
Fiecare ora de suprasolicitare astfel calculata se insereaza ca un rand nou si distinct in WLP_CA_PLANIFICARI, cu STARE = 3, separat de eventualele randuri normale (STARE = 0) generate in Faza 1 pentru aceeasi zi si aceeasi persoana.
Important
Suma tuturor randurilor cu STARE = 3 generate in Faza 2 este exact egala cu ore_neacoperite — corectia aplicata pe ultima zi garanteaza acest lucru, indiferent de rotunjirile intermediare.
Exemplu real, verificat
Urmatorul exemplu a fost rulat si verificat direct in sistem (task MAI_01G, ID_WLP_CA = 2400, persoana cu marca 66, meserie TRAGERE):
Marime |
Valoare |
|---|---|
|
80 ore |
|
0 ore (persoana nu avea deloc capacitate libera in perioada) |
|
15 zile |
|
80 - 0 = 80 ore |
|
80 / 15 = 5.333… |
|
5 ore/zi (0.333 < 0.5, rotunjire in jos) |
Rezultatul Fazei 1: niciun rand normal alocat (persoana nu avea nicio ora libera).
Rezultatul Fazei 2, verificat in WLP_CA_PLANIFICARI:
Zile |
Alocare |
|---|---|
14 zile |
5 ore/zi fiecare = 70 ore |
a 15-a zi (ultima) |
corectata la 10 ore (restul exact, nu 5), astfel incat totalul sa fie 80 ore |
Total verificat: 14 × 5 + 10 = 80 ore, exact cat ore_neacoperite, distribuit in 15 randuri distincte cu STARE = 3.
Dupa aplicarea celor doua faze, WLP_CA.STARE a taskului a trecut din EROARE in VALIDATA.
Varianta punctuala — distribuirea overload-ului pe o singura resursa
Actiunea Planificare resursa cu overload (WlpCaDetaliuServiceImpl.planificaResursa cu tipPlanificare = 2) executa acelasi algoritm in doua faze, dar restrans la un singur rand WLP_CA_DETALIU:
Faza 1 (
alocaDisponibilPeResursa) aloca disponibilul persoanei selectate, limitat la necesarul ramas al taskului (Q_NECESAR - Q_ALOCAT), pentru ca apelurile repetate pe persoane diferite sa nu supra-aloce;Faza 2 (
distribuieOverloadPeResursa) distribuie cantitatea de ore de overload introdusa de utilizator in dialog (nu neaparat intreaga diferenta — serverul o plafoneaza laQ_NECESAR - Q_DISPONIBILal persoanei), doar peste zilele lucratoare ale persoanei selectate, tot ca randuriWLP_CA_PLANIFICARIcuSTARE = 3. Intern, ambele fluxuri folosesc aceeasi metodadistribuieOverloadPeTask, cu un filtru optional peID_WLP_CA_DETALIU(null= toate resursele, fluxul de la Acceptare diferente).
Dupa distribuire, taskul este reevaluat soft (reevaluareTaskFaraStergereAlocari): se sterg doar mesajele din WLP_CA_LOG, se recalculeaza disponibilul pe toate resursele taskului peste alocarile existente (orele STARE = 3 conteaza ca acoperire), iar taskul se valideaza automat cand nu mai raman erori.
Regula de distributie partajata
Regula de calcul a orelor pe zi (indice brut, pragul de 2 ore/zi, rotunjirea si corectia pe ultima zi) este extrasa in metoda comuna WlpServiceImpl.calculeazaDistributieOrePeZile(totalOre, totalZile) si este refolosita de:
distribuirea suprasolicitarii pe task sau pe resursa (aceasta pagina);
actiunea Ore suplimentare, optiunea Total ore distribuite automat pe zilele lucratoare — cu diferenta ca acolo orele mareasc capacitatea zilelor (
WLP_CALENDAR.Q_OVERTIME+Q_CAPACITATE), nu genereaza randuri de planificareSTARE = 3.