Autor: Milan Oparnica (14.07.2009)
Revizija: Milan Oparnica (06.08.2017) Od sada zapisi koji ne trebaju imati uticaj na važeći period imaju NULL u vazod/vazdo
Algoritam iza zadatak da ukloni sledeća uska grla kod određivanja prodajne i cene koštanja:
Standardni algoritam je uvek polazio od početnog stanja i obrađivao sve promene do kraja. Postojale su dve verzije, svi artikli, ili artikli po nekom dokumentu, pri čemu ova poslednja verzija nije pokretana u slučaju da dokument obuhvata više od 300 promena. Dakle program bi uvek povukao sve promene od početka godine što u slučaju velikih baza podataka nije bilo izvodljivo.
Algoritam se oslanja na upotrebu LagerNaDanX metoda za dobijanje “početnog stanja” cena i količina prilikom obrade konkretnog dokumenta ili svih artikala i skladišta. Na taj način, nema potrebe da se obrađuju hiljade slogova već samo slogovi od datuma dokumenta do kraja perioda. U slučaju da se vrši obrada svih artikala i skladišta obrada se vrši od nekih “check-point” tačaka do kraja perioda.
Oslanja se na upit CS_OtpremniceUlazi koji pokušava da spoji otpremnice i ulaze sa validnim cenama za period u kom je otpremnica izdata.
Upitu je potrebno preko 20 min da vrati rezultat na srednjim (>300MB) i večnost na velikim bazama (>1GB).
Uočio sam da je glavni problem u nedostatku efikasne strukture kroz koju bi lako određivao periode u kojim određena srednja ili prodajna cena važe za određeni artikal i određeno skladište.
Tabela SasUlaz se pokazala najzgodnijom za uvođenje ove strukture, koju sam nazvao “Struktura važećeg perioda cena”, ili kraće struktura “važećeg perioda”.
Strukturu čine tri polja u tabeli SasUlaz
Polje | Tip | Svrha |
---|---|---|
vazod | INTEGER | Celobrojno polje koje predstavlja datum početka perioda za koji srednja i prodajna cena u slogu SasUlaz važi. |
vazdo | INTEGER | Celobrojno polje koje predstavlja datum kraja perioda (ne uključujući dan unet u VazDo) od kog srednja i prodajna cena u slogu SasUlaz više ne važi. |
vazdts | DOUBLE | Duplikat DTStamp polja iz Ulaz tabele kako bi se izbegao nepotreban JOIN u upitima koji će vraćati rezulate strukture. |
Primeri su dati nad sledećim vrednostima (#m/dd/yyyy#):
39875 - brojčana vrednost datuma #3/3/09#
39885 - brojčana vrednost datuma #3/13/09#
401769 - brojčana vrednost datuma #1/1/3000#
Sledeće kombinacije vrednosti ovih polja za isti ElID i SklID sloga SasUlaz su ispravne:
vazod | vazdo | Opis situacije |
---|---|---|
39875 | 401769 | Ovo je normalno kod prvog i jedinog ulaza artikla koji tada važi od datuma ulaza do kraja (1/1/3000) |
39875 | 39885 | vo je normalno za artikal koji je ponovo nabaljen za 10 dana, pri čemu bi drugi slog izgledao… |
39885 | 401769 | …ovako |
39875 | 39875 | Ovo je normalno za artikal koji je u toku jednog dana više puta ulazio. Mogući scenario sledećih polja je… |
39875 | 39875 | …ponovo je ušao, ali ima još jedan ulaz od istog dana |
39875 | 39885 | …sledeći ulaz od istog dana važi narednih 9 dana |
39885 | 401769 | …a 10-tog dana je artikal ponovo ušao, i od tada se više nije pojavljivao |
Iz ovih vrednosti mogu se izvući sledeći logički zaključci:
Izuzetno je važno da se popisi više ne tretiraju kao poslednji dokumenti u danu, ako već nisu tako i snimljeni. Periodi vazod i vazdo ne smeju postati netačni. Ovo tretiranje popisi imaju samo u procedurama za obradu srednjih cena i nivelacija, i to zato što svi ulazi pomeraju DTStamp svih otpremnica tako da ove uvek dolaze iza njih.
Popisima se na DTStamp dodaje 20000 tako da se oni veštački postave iza svih ulaznih dokumenata. Ovo je prvenstveno urađeno zbog uprošćavanja detekcije trenutnih količina u trenutku ulaza i formiranja srednje nabavne cene.
Pošto su svi izlazi agregirani pod jednim danom i smešteni na njegov kraj, jedini podatak koji nam informaciju može pružiti jeste TKol prethodnog ulaza. Stvar, nažalost, nije nimalo jednostavna. Ulazi pre popisa će u TKol da smeste sve ulaze do tog momenta minus količinu robe prodatu do kraja prethodnog dana. Popis će uzeti stanje u trenutku popisa i u svoj TKol upisati stanje posle popisa uključujući izlaze do momenta popisa.
Ulazi napravljeni posle popisa će uzeti:
zbir svih ulaza do pre popisa + izmene po popisu – zbir izlaza do kraja prošlog dana.
Tablica koja demonstrira problem:
Iz ovoga se vidi da će prethodni TKol biti isti kao i stanje lagera po obračunu SC ali će se razlikovati od stvarnog stanja koje je bilo u trenutku popisa.
Razlog za usaglašavanje dokumenta Popis može biti samo promena u stanju (ili ceni, ali ako to nema veze sa količinom radi se o drugoj priči) pre popisa. Do promene stanja može doći samo izmenom tabele Ulaz ili Otpremnice.
U prvom slučaju, izmena će se odraziti na TKol makar poslednjeg Ulaza pre popisa. U drugom slučaju desiće se isto sem ako je došlo do promene baš one otpremnice koja se nalazila između poslednjeg ulaza i popisa, odnosno popisa i prvog sledećeg ulaza, a to će se reflektovati tek na TKol-u prvog sledećeg Ulaza.
Problem je kako razlikovati da li je do razlike u izlazima došlo pre ili posle popisa ?
Jedino rešenje je ipak da popis u okviru zapisa u Popis unese i podatak o ukupnom ulazu i izlazu do trenutka izrade popisa. U tu svrhu su dodata polja inkol i outkol. Prilikom sakupljanja informacija o prometu artikala (CS_UlaziSumIzlazi i sl.), dodat je podupit koji za slogove popisa testira trenutno važeći izlaz do momenta popisa i posle popisa (potonje za sada ne trebaju, ali pošto ne utiču na performanse ostavio sam ih).
U strukturu uMag dodaću dva nova polja InKol i OutKol, ali i u matricu popisa isto to. Slog u SasUlaz će u polju ExtLink pamtiti PopID polje iz tabele Popis.
Matrica popisa se formira prilikom prebacivanja podataka iz recordseta sa prometom artikala. Tada se za sve slogove, za koje se otkrije da predstavljaju slog popisa, umetne zapis u matricu popisa koja ima sledeći format:
Naziv polja | Vrsta | Opis |
---|---|---|
iIndex | Long | Ovde se upisuje broj reda iz osnovne matrice gde se čuvaju svi podaci o slogu popisa. Pošto je taj broj unikatan poslužiće nam kao unikatan index. |
iElID | Long | ID artikla na koji se popis odnosi |
iSklID | Long | ID skladišta na kom je popis urađen |
dDatum | TDateTime | Datum i vreme izrade popisa |
nLoTKol | Double | Originalna TKol vrednost učitana iz baze |
nLoKol | Double | Količina uneta kroz popis |
nChTKol1 | Double | Vrednost TKol-a iz poslednjeg Ulaza pre popisa |
nChTKol2 | Double | Vrednost TKol-a iz Ulaza posle popisa |
< ima još polja u ovoj matrici…potrebno je updateovati ovaj dokument > |
Izmene se dešavaju u modulu za obračun srednjih cena i nivelacija BLSCNIV.
Koraci bitni za implementaciju:
U strukturu se ne unose slogovi iz SasUlaz koji imaju sklid = 0. U Balansu jedino interni nalozi za prijem ili prenos robe snimaju u Ulaz > SasUlaz pod sklid = 0.
Pošto ti podaci ionako ne učestvuju u formiranju cena i količina sasvim je ispravno da ne koriste strukturu važećeg perioda.
Od 06.08.2017 zapisi koji ne trebaju imati uticaj na važeći period (defDocTip.FNivelTot = false i defDocTip.FSCObrac = false
) imaju NULL u vazod/vazdo
Upit | Opis |
---|---|
CS_UlaziDDDoc | Novi upit za dobijanje obracunskog peroda sc i nivel po predatom dokumentu |
CS_UlaziSumIzlazi_Tst | CS_UlaziSumIzlazi samo bez UNIONA po Ulaz tabelama |
zCalc_INKOLByDoc_xx | Upiti za dobijanje stanja svih lagera artikala predatog dokumenta na trenutak pre izrade predatog dokumenta |
CS2_GetPer4Del | |
CS2_GetPer4New | |
CS2_GetPerErr_1 |