Pregled svih komandi alata za prihvat i arhiviranje stampe
Pregled svih komandi. Alat stoji u E:\Work\AI\erste_tools, radi na čistom Pythonu 3.9+ bez ijedne dodatne biblioteke.
| Šta | Putanja |
|---|---|
Izvor (source_root) | \\192.168.1.250\ftpusers\erste\PROD\OUT |
Radni folder (work_root) | \\192.168.1.208\DevelopmentFiles\Work- TB\Dnevna |
Arhiva (archive_root) | \\192.168.1.250\ftpusers\erste\PROD\Arhiva |
| Netaknuta kopija | ...\Dnevna\_original\<datum prihvata>\ |
| Root priznat iz mail-a | /home/ftpusers/erste/PROD/OUT (i sve ispod njega) |
cd "E:\Work\AI\erste_tools"
python erste.py prihvat --proba :: pokaže šta bi uradio, ništa ne dira
python erste.py prihvat :: premešta foldere iz clipboard-a
python erste.py pregled :: šta čeka arhiviranje
python erste.py arhiva :: arhivira (na današnji dan)Ko ne voli kucanje — dupli klik na Erste.bat (meni sa brojevima).
| Komanda | Šta radi |
|---|---|
prihvat | premešta foldere iz OUT u radni folder (MOVE) |
pregled | spisak onoga što je prihvaćeno a nije arhivirano |
arhiva | kopira obrađeno u arhivu po danu štampe (COPY) |
ocisti | briše netaknute kopije već arhiviranih stavki |
provera | proverava podešavanja i dostupnost putanja |
nadji | gde je posao kod nas: radna kopija, netaknuta, arhiva |
mail | podešavanje i provera mail naloga (IMAP) |
meni | interaktivni meni |
init | pravi config.json |
Engleski nazivi rade isto: ingest, status, archive, cleanup, check, find, menu.
Uz svaku komandu radi i:
| Opcija | Šta radi |
|---|---|
--config <putanja> | drugi config.json |
--verbose | detaljniji ispis |
--version | verzija alata |
-h / --help | pomoć za tu komandu |
prihvat — premeštanje folderapython erste.py prihvat :: iz clipboard-a (podrazumevano)
python erste.py prihvat --fajl spisak.txt :: iz fajla
python erste.py prihvat --imap :: direktno sa mail naloga
python erste.py prihvat --ime JDCID274_20260809_232412 JDTID081_20260810_202529
python erste.py prihvat --proba :: proba, ništa se ne dira| Opcija | Šta radi |
|---|---|
--fajl <putanja> | čita spisak/mail iz fajla umesto iz clipboard-a |
--ime N1 N2 ... | imena foldera navedena direktno |
--imap | preuzima lokacije sa mail naloga |
| `--mode auto\ | mail\ |
--kriterijum "<IMAP SEARCH>" | npr. UNSEEN, ALL, FROM "x@y.rs" |
--limit <broj> | najviše toliko poruka |
--ne-diraj-poruke | obradi foldere, ali ostavi poruke NEPROČITANE |
--proba (--dry-run) | prikaže plan, ne dira ništa |
Šta se dešava: folder se premešta (move) iz OUT u ...\Dnevna\<današnji datum>\. Sve prihvaćeno istog dana ide u isti dnevni folder. Odmah se pravi i netaknuta kopija u ...\Dnevna\_original\<datum>\ — iz nje kasnije ide arhiva, pa operater sme da meša, preimenuje i briše svoju radnu kopiju bez posledica.
Zašto to nije suvišno: u stvarnoj obradi se svih 19 foldera prerasporedi po broju strana u dva foldera i spoji u dva PDF-a. Od originalne strukture u radnoj kopiji ne ostane ništa. Arhiva ipak ispadne uredna, jer se uzima iz netaknute kopije.
Kod IMAP-a se .eml snima u folder posla na koji se odnosi, pa je svaki posao celina — svi fajlovi + poruka iz koje je došao — i tako završi i u arhivi. ("mail_u_folder": false vraća staro: svi mailovi zajedno u _mail\.)
Ulaz može biti: ceo mail, više mailova odjednom (dele se po „Poštovani"), ili običan spisak imena foldera — po jedan u redu. Prihvataju se gola imena, unix putanje i Windows putanje.
Jedna poruka može da najavi više štampi — svaka u svom redu. Sve se obrađuju kao da su stigle zasebnim porukama, a kopija poruke ide u svaki folder na koji se odnosi. Ista lokacija navedena dvaput se obrađuje jednom.
Spisak je ono između najave i potpisa:
...koja se nalazi na lokaciji:, koji mora biti u prvih 5 nepraznih linija. Ako je dublje — to je nadovezana prepiska, stara najava ispod našeg odgovora — poruka se ne obrađuje;Pozdrav, Regards, --), citiranom tekstu (>) ili početku prosleđene poruke (-----Original Message-----, From:).Poruka koja ne počinje najavom se ne obeležava, pa ostaje vidljiva i prijavljuje se u svakom prolazu uz razlog. Isto i ako jedan od foldera fali — poruka se vraća sledeći put, da se ostatak ne izgubi. Ništa se ne gubi tiho.
Izmereno na 21 stvarnoj poruci: najava je uvek na 2. nepraznoj liniji.
Neke vrste poslova se skupljaju u zajednički folder u radnoj kopiji. Pravila su u config.json pod grupe:
| Poslovi | Ide u | Struktura |
|---|---|---|
JDICD083_*, JDTID076_* | Erste izvodi {datum} | ravno — svi fajlovi zajedno |
JDCID_215_*, JDCID_216_* | Erste uparivanje {datum} | podfolderi DCID215 / DCID216 |
{datum} je dan prihvata.
Dnevna\2026-08-13\
Erste izvodi 2026-08-13\ <- svi izvodi zajedno
izvod_a.pdf
izvod_b.pdf
Erste uparivanje 2026-08-13\
DCID215\ podaci.xlsx
DCID216\ podaci.xlsxArhiva se ne grupiše — ostaje po originalnim imenima poslova (Arhiva\2026\08\20\JDICD083_20260701_203829\), pa je pretraživa po nalogu.
Kod „ravno" strukture: isti fajl (ime + veličina + SHA-1) se ne duplira; različit fajl istog imena ide pored (izvod__2.pdf) i prijavi se kao sudar imena. Nikad preko.
nadji — gde je posao kod naspython erste.py nadji JDCID266 :: po imenu ili delu imena
python erste.py nadji JDCID266 --disk :: + pretraga celog diska (Everything)Za svaki pogodak kaže kada je prihvaćen, gde mu je radna kopija, netaknuta kopija i arhiva — i da li te putanje stvarno postoje ili su samo nedostupne. Ako ga nema u evidenciji, proverava da li još stoji u OUT.
--disk traži preko Everything CLI (es.exe). Ako es.exe nije instaliran, jasno to kaže; putanja se može zadati u config.json → everything_es.
pregled — stanjepython erste.py pregled :: samo ono što čeka arhivu
python erste.py pregled --sve :: i ono što je već arhiviranoOznaka [BEZ KOPIJE] znači da je netaknuta kopija nestala — arhiva će za tu stavku morati da traži fajlove po manifestu.
arhiva — kopiranje u arhivuPokreće se na dan štampe, koji se po pravilu razlikuje od dana prijema.
python erste.py arhiva :: pod današnjim datumom, sve što čeka
python erste.py arhiva --dan 2026-08-13 :: pod drugim datumom
python erste.py arhiva --proba :: proba
python erste.py arhiva --clipboard :: samo odštampana serija, spisak iz clipboard-a
python erste.py arhiva --fajl odstampano.txt :: isti spisak iz fajla
python erste.py arhiva --samo JDCID274_20260809_232412
python erste.py arhiva --paket 2026-08-11 :: samo iz tog dana prihvata
python erste.py arhiva --potvrdi :: bez pitanja za potvrdu| Opcija | Šta radi |
|---|---|
--dan <datum> | dan štampe; prima 2026-08-13, 13.08.2026 ili 20260813 |
--clipboard | spisak odštampanog uzima iz clipboard-a |
--fajl <putanja> | isti spisak iz fajla |
--samo <ime> ... | samo navedeni folderi |
--paket <dan> ... | samo stavke iz tih dnevnih foldera prihvata |
--potvrdi (--yes) | preskače pitanje za potvrdu |
--proba (--dry-run) | prikaže plan, ne dira ništa |
--danDan kada pokreneš komandu — ne dan prijema, ne dan iz imena foldera.
Sve što je prihvaćeno a nije arhivirano, iz svih dnevnih foldera. Zato se pri štampi u serijama koristi --clipboard: odštampaš seriju, kopiraš spisak tih poslova, arhiviraš tačno njih. Neodštampano ostaje u redu i ide kasnije, pod svojim danom štampe.
Ono što je traženo a nije ušlo prijavi se uz razlog — već arhivirano <datum> ili nije prihvaćen.
Rezultat: \\192.168.1.250\ftpusers\erste\PROD\Arhiva\2026\08\13\JDCID266_20260811_033134\ — kopija (ne move), sa nepromenjenom strukturom po folderima.
Fajlovi se uzimaju iz netaknute kopije. Ako nje nema, traže se po manifestu: prvo po imenu i veličini, pa po SHA-1 — tako se nađu i fajlovi koji su u međuvremenu premešteni ili preimenovani. Što se ne nađe, prijavi se poimenično.
ocisti — brisanje starih kopijapython erste.py ocisti --dana 30 --proba :: šta bi obrisao
python erste.py ocisti --dana 30 :: uz pitanje za potvrdu
python erste.py ocisti --dana 30 --potvrdi :: bez pitanjaBriše isključivo netaknute radne kopije (...\Dnevna\_original\) stavki koje su već arhivirane, i to starije od zadatog broja dana. Podrazumevano 30 dana; --dana 0 briše sve već arhivirano bez obzira na starost.
Kopija ostaje posle arhiviranja zato što je arhiviranje kopiranje, ne premeštanje. Za automatsko brisanje odmah po uspešnom arhiviranju: "keep_original_after_archive": false (kod delimične arhive kopija svejedno ostaje).
Arhiva je trajna i ova komanda je ne dira. Brisanje bilo čega unutararchive_rootilisource_rootje zabranjeno u kodu — odbija se i upisuje u log. Ako u arhivi već postoji folder istog imena, novi sadržaj ide pored (ime__2), nikad preko.
provera — da li je sve na mestupython erste.py proveraIspisuje sve putanje sa oznakom OK / !!, gde bi danas išla arhiva, i stanje IMAP podešavanja. Prvo što treba pustiti kad nešto ne radi.
mail — IMAPpython erste.py mail podesiVođeno podešavanje: pita server, način povezivanja, korisnika i lozinku, odmah proveri vezu, pa tek onda upiše. Ako prijava ne prođe, config.json ostaje netaknut.
Za server se može nalepiti i pun URL — imaps://korisnik@mail.primer.rs:993/ se sam razloži na host, port i SSL. Zatim se bira:
| Izbor | Port | Šifrovanje |
|---|---|---|
| 1 | 993 | SSL/TLS odmah (najčešće) |
| 2 | 143 | STARTTLS |
| 3 | ručno | ručno |
Na kraju bira gde ide lozinka: promenljiva okruženja (preporučeno — sam pozove setx), config.json (običan tekst), ili nigde (pita svaki put). Posle upisa u promenljivu okruženja otvoriti nov terminal da bi važila.
Ručno, u config.json pod imap: host, port, ssl (true za 993, false za 143 sa STARTTLS), user, processed_folder, timeout.
Redom; svaki korak dira manje nego sledeći.
python erste.py mail proba :: 1) server, prijava, folder za obrađene
python erste.py mail folderi :: 2) tačna imena foldera na serveru
python erste.py mail pregled :: 3) šta bi pročitao - poruke se NE diraju
python erste.py prihvat --imap :: 4) stvarna obradamail proba prvo kaže odakle uzima lozinku, pa razdvaja mrežnu grešku od pogrešnih kredencijala:
| Poruka | Šta znači |
|---|---|
Server '...' nije pronađen (DNS) | pogrešan imap.host |
...odbija vezu | pogrešan port |
Veza ... je istekla posle 20s | firewall, ili ssl ne odgovara portu |
TLS greška | server traži STARTTLS — stavi "ssl": false i "port": 143 |
Prijava odbijena | korisničko ime ili lozinka; kod 2FA treba lozinka za aplikaciju |
Uz pregled rade i --kriterijum i --limit.
Alat obrađenu poruku obeležava sopstvenom oznakom AutoObrada i traži NOT KEYWORD AutoObrada.
Zašto ne UNSEEN: ako se sanduče čita i preko POP3 (Outlook), server postavlja \Seen već pri POP3 preuzimanju. Poruka postane „pročitana" a da je alat nikad nije video, pa bi sa UNSEEN tiho ispala iz obrade. Custom oznaku POP3 ne dira.
| Polje | Uloga |
|---|---|
from_contains | grubo sito na serveru (IMAP ne ume regex), npr. mainstream |
from_pattern | precizan regex nad Ime <adresa> |
since_days | gleda samo poruke novije od N dana (podrazumevano 14) |
Regex vezuj za domen, ne za adresu — lokalni deo i TLD se menjaju:
(?i)@(?:[a-z0-9-]+\.)*imefirme\.[a-z]{2,6}(?=[>\s]|$)Završni (?=[>\s]|$) odbija lažni domen (a@imefirme.rs.tudje.com), a vezivanje za @ odbija podvalu preko imena (Ime Firme <podvala@gmail.com>). Neispravan regex zaustavlja rad — filter koji ne radi znači obradu tuđe pošte.
Oznaku dobija samo poruka iz koje je izvučen folder i čiji je prihvat uspeo. Poruka bez putanje ostaje neobeležena i vraća se sledeći put.
Više alata nad istim sandučetom: svakom dati svoj from_contains pa se ne sretnu.
python erste.py prihvat --imap --ne-diraj-porukeFolderi se obrade do kraja (premeštanje, netaknuta kopija, .eml, manifest), ali poruke ostaju nepročitane u INBOX-u — pa iste poruke mogu ponovo da se obrade. Korisno kad se prvi put pušta nad stvarnim nalogom.
Ponovno pokretanje je bezbedno: već prihvaćen folder se prepozna i preskoči, a .eml kopija se ne duplira (ime sadrži uid poruke).
Lozinka se traži ovim redom: promenljiva okruženja ERSTE_IMAP_PASSWORD → polje password u config.json → pitanje u terminalu. Preporuka:
setx ERSTE_IMAP_PASSWORD "lozinka"Šta se dešava sa porukom — tek pošto prihvat uspe: snimi se .eml kopija uz obrađene foldere i poruka se označi pročitanom. Poruka ostaje u INBOX-u.
To je dovoljno: pošto se gledaju samo nepročitane poruke, oznaka „pročitano" i sistemu i operateru govori da je poruka obrađena. Poseban folder za obrađene nije potreban — ako se ipak želi, upiše se ime u processed_folder (podrazumevano prazno) i pravi se sam.
Ako prihvat ne uspe, poruka ostaje nepročitana u INBOX-u i alat to prijavi — pa je nepročitana poruka ujedno i znak operateru da nešto treba pogledati.
| Fajl | Šta radi |
|---|---|
Erste.bat | meni |
1-Prihvat.bat | prihvat iz clipboard-a |
2-Pregled.bat | pregled stanja |
3-Arhiva.bat | arhiviranje |
install.bat | instalacija na novoj mašini |
python -m unittest discover -s tests -t . :: 92 testa
python tools\demo.py :: ceo tok na izmišljenim folderima
python erste.py init --prepisi :: nov, prazan config.jsontools\demo.py radi isključivo u %TEMP%\erste_demo — nijedna stvarna lokacija se ne dodiruje.
Tri kočnice sprečavaju da posao bude uhvaćen na pola:
1. Folder se objavljuje tek kad je ceo gotov. Prenosi se u <dnevni folder>\_uprihvatu\, tamo se napravi i netaknuta kopija, i tek onda se preimenuje na svoje ime. Poluprenet folder se nikad ne vidi pod pravim imenom, pa se ne može odštampati nepotpun posao. Ako prenos pukne, ostatak stoji u _uprihvatu i pregled javi NEDOVRŠEN PRENOS.
2. Brava. Prihvat i arhiviranje se ne mogu preklopiti — drugi posao odbija start uz poruku ko ga drži, sa kog računara i od kada (_erste.lock). Brava starija od sat vremena se smatra zaostalom i preuzima.
3. Manifest se upisuje posle svake stavke. Prekid ne ostavlja preneto ali nezabeleženo. Što nije u manifestu, arhiva ne može ni da pokupi.
Uz to, arhiva označava stavke prihvaćene u poslednjih sat vremena sa <-- prihvaćeno pre N min! i upozori da verovatno nisu odštampane.
Za ~10 poruka dnevno koje se štampaju u jednom sedenju, ručno pokretanje na početku rada je jednostavnije i predvidljivije od rasporeda:
python erste.py prihvat --imap :: pokupi sve novo
:: ... štampanje ...
python erste.py arhiva --clipboardAko ipak ide u raspored, neka interval bude redak i nikad ne puštaj arhiva iz rasporeda — samo operater zna šta je odštampano.
/home/ftpusers/erste/PROD/OUT, na bilo kojoj dubini. Šta je unutra nije bitno. Sve van toga se odbacuje uz jasan razlog.OUT se premešta (move), u arhivu se kopira (copy).logs\erste-GGGG-MM.log.