102 Commits

Author SHA1 Message Date
pepa 6ac6d783fb - Opravena kontrola práv při ružení schválení vyúčtování SC.
- Opraven refresh gridů při mazání záznamů.
- Zrušeno výchozí třídění v agendě Cestovní příkazy.
- Opraven pom.xml.
2015-10-19 10:24:53 +02:00
pepa 67ff54d3f1 Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-10-18 16:28:30 +02:00
pepa 275e120021 Opraveno ukládání záznamu v agendě Fakturace požadavků. Příznak Fakturováno se již ukládá správně. 2015-10-16 10:03:34 +02:00
franta d20a72b336 Kvůli přechodu na IntelliJ IDEA upravena konfigurace Maven.
Fakturace rozděleny na fakturace materiálu a služeb.

closes #249
2015-10-14 10:06:41 +02:00
pepa e24684bbd0 Přesunut podpis příkazce operace na vyúčtování služební cesty.
closes #258
2015-10-12 15:26:25 +02:00
pepa 21bf006c19 Aktualizace podepisovací komponenty. 2015-10-11 22:08:30 +02:00
pepa 970928bb4e Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-10-11 21:53:33 +02:00
pepa 369184940b Do agendy Cestovní příkazy byly přidány záložky "Má střediska", "Mé komise" a "Vše", kde se zobrazují vyúčtování služebních ke schválení. V záložkách lze vyúčtování označit jako proplacené. Do e-mailu se generuje odkaz do těchto záložek.
closes #253
closes #250
2015-10-11 21:52:50 +02:00
franta cc374a3bf1 Podepsané dokumenty se nyní zobrazují ve dvou záložkách - Aktuální
dokumenty a Archiv.
V Archivu se zobrazují dokumenty starší než rok.

closes #225
2015-10-05 13:09:20 +02:00
franta 66e0c427ac Popisek změněn na "Zajistím sám", případně ve sloupci na "Zaj. sám"
closes #247
2015-10-05 08:57:26 +02:00
franta 095089d020 U požadavků na nákup je nyní pole Popis povinné.
closes #248
2015-10-05 08:32:42 +02:00
pepa 84154ccbff Neaktivní uživatelé se nenabízí v seznamech pro výběr uživatele (spolucestující...). V agendě Uživatelé a Střediska/komise jsou barevně odlišeni.
closes #239
2015-10-02 14:58:51 +02:00
pepa 1230959854 Opraveno duplikování vyúčtování SC, když se na požadavku provede úprava a znovu se schválí.
closes #255
2015-10-02 13:27:24 +02:00
pepa 96154a6b98 Opraveno mazání záznamů z požadavků
closes #257
2015-10-02 09:41:16 +02:00
pepa 14242fa41a Vyúčtování služebních cest u spolucestujících lze nyní zrušit u každého zvlášť. Lze tak provést dodatečnou opravu vyúčtování.
closes #251
2015-10-02 09:32:09 +02:00
pepa 67a99d8d78 Na sestavách se pro viditelný dig. podpis vytváří klasické read only formulářové pole, které se podpisem nahradí za obrázek podpisu.
Změna podepisovací komponenty- na windows se spouští stejná jak na linuxu, macos...
closes #244
2015-10-01 16:00:49 +02:00
pepa 768d3ee874 Opraveno duplicitní vkládání záznamů do agendy Fakturace požadavků, v případě, že se požadavek upraví a znovu schválí.
closes #252
2015-09-08 22:22:23 +02:00
pepa cd6a6cf5a6 Přidaná sestava "Protokol o kontrole" - digitální podpis při schvalování nákupů. 2015-09-07 22:08:21 +02:00
pepa d1ccaf530d Při napojování uživatele z AD se login převede na malá písmena. Opravena chyba při mazání uživatele.
closes #237
2015-08-18 22:21:05 +02:00
pepa 10439b5001 Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-08-08 22:53:15 +02:00
pepa b33f9f2e8a Pokud se upraví požadavek, u kterého je podepsaný dokument, tak se dokument smaže a požadavek se nastaví jako nový.
closes #227
2015-08-08 22:52:10 +02:00
franta 07d0949bea Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-07-14 20:21:10 +02:00
franta 2819cc125c Implementován validátor pro Globální nastavení.
closes #236
2015-07-14 20:17:32 +02:00
pepa c0922921c5 V agendě Procesy schválení lze u jednotlivých schvalovacích rolí nastavit, jestli bude vyžadován při schválení elektronický podpis.
closes #242
2015-07-11 01:05:41 +02:00
pepa b70041bfff Změněn způsob ukládání PDF dokumentu. Data se předávájí ve ViewModelu, tak nemůže dojít k tomu, že by se schválením jiného záznamu v druhém okně prohlížeče uložilo jiné PDF.
refs #243
2015-07-10 15:29:44 +02:00
pepa b5ffa07644 Aktualizace podepisovací aplikace- opraveno náhodné zatuhnutí po startu.
refs #224
2015-07-09 08:22:32 +02:00
pepa cccd8177fa Implementace uložiště podepsaných dokumentů. Při prvním podpisu se uloží podepsané PDF a vytvoří se záznam v agendě podepsaných dokumentů.
closes #243
2015-07-08 12:55:41 +02:00
pepa 6db416dd04 Vyřešeno generování PDF pro podpis na základě entity, která se schvaluje.
closes #240
2015-07-03 13:36:23 +02:00
pepa 05faa87071 Digitální podpis se zobrazí v PDF viditelně. Server předá podepisovací aplikaci ID fieldu, kde se podpis zobrazí. ID je zadáno v reportu jaku parametr pole signature.
refs #224
2015-07-02 14:12:26 +02:00
pepa 11e3a48b28 Ve windows se spustí podepisovací aplikace, která si bere certifikáty ze systémového uložiště.
refs #224
2015-06-25 13:08:06 +02:00
pepa d7999e78ca Merge remote-tracking branch 'origin/master' 2015-06-24 12:54:57 +02:00
pepa d6cff454fd Základní implementace podepisování PDF dokumentů. Podpis implementován pouze pro sestavu schválení služební cesty (natvrdo v kódu). Spouští se univerzální podepisovací aplikace, která čte certifikát ze souboru.
closes #224
2015-06-24 12:54:31 +02:00
franta 1d30f0d0c7 Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-06-24 10:16:36 +02:00
franta 9fb1ef7601 Přidána základní funkčnost zobrazování dat agendy.
refs #225
2015-06-24 10:14:21 +02:00
pepa 312b62af7b Merge branch 'Verze_2.0' 2015-06-21 00:36:08 +02:00
pepa b0fedfa3f3 Opraveny datumy na vyúčtování služební cesty.
closes #232
2015-06-21 00:31:33 +02:00
pepa dc0607c072 Vytvořením požadavku na služební cestu se odešle e-mail spolucestujícím.
closes #235
2015-06-20 23:49:49 +02:00
pepa 162cea6001 Merge branch 'Verze_2.0' 2015-06-15 21:18:14 +02:00
pepa 4d74b0a3fe Opraven binding formuláře vyúčtování služební cesty.
closes #231
2015-06-15 21:17:17 +02:00
pepa 3b3e4b38e6 Vyúčtování služební cesty nelze odeslat ke schválení, pokud nejsou vyplněné časy odjezdu a příjezdu.
closes #230
2015-06-14 20:45:36 +02:00
pepa 1164e11107 Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-06-13 00:07:05 +02:00
pepa c2ca2e45ec Opraveno generovani vyuctovani sluzebni cesty spolucestujicich, pokud je pozadovana zaloha- zaloha se nyni neprenese.
closes #229
Po schvaleni pozadavku na sluzebni cestu se spolucestujicimi se posle mail o schvaleni i spolucestujicim.
closes #228
2015-06-13 00:00:00 +02:00
franta c9a56887dc Připraveny podklady pro novou agendu "Podepsané dokumenty"
Vzhled agendy (grid/strom/...) zatím není znám.

closes #222
2015-06-04 14:19:54 +02:00
franta aaa89a2653 Workaround pro zápis číselné řady.
Vznikaly duplicity nad unikátním indexem.
Nyní se číslo nezapisuje a načítá se z vazby na požadavku na cesťák.

closes #221
2015-05-22 12:10:00 +02:00
franta fbc7a02161 Zpráva z pracovní cesty prodloužena na 8kB
closes #220
2015-05-20 07:51:47 +02:00
pepa e5a8e0f0d9 Po otevření dialogu pro zobrazení vyúčtování SC se přepne na první záložku, kterou může schválit aktuálně přihlášený uživatel.
closes #217
2015-05-17 21:52:46 +02:00
pepa 0f169f8be9 Na formuláři vyúčtování služební cesty se automaticky předvyplní datum v poli "Zpráva z pracovní cesty podána dne", pokud je pole prázdné.
closes #216
2015-05-17 21:06:26 +02:00
pepa b6d0546b48 Na formulář vyúčtování služební cesty bylo přidáno tlačítko "Uložit a odeslat ke schválení"
closes #218
2015-05-17 20:52:38 +02:00
pepa a6799064f7 Opraveno generování e-mailu po odeslání vyúčtování služební cesty ke schválení. Text a URL se nyní vygeneruje správně.
closes #219
2015-05-13 13:36:51 +02:00
pepa 933f5e784b V dialogu pro zobrazení vyúčtování služební cesty se po otevření přepne záložka na první neschválené vyúčtování.
refs #212
2015-05-06 15:22:07 +02:00
franta 04dc8a5587 Metodou pokus-omyl je správně width="100%" a vflex="1"
refs #215
2015-04-28 09:01:40 +02:00
franta b63a2c3944 Upraveno zobrazování seznamu souborů...
closes #214
2015-04-28 08:17:19 +02:00
franta 67629cf312 IFrame v náhledu na sestavy upraven z width a height na vflex a hflex.
closes #215
2015-04-28 08:15:16 +02:00
pepa cdd2f81cad Oprava sestavy.
refs #213
2015-04-27 14:46:39 +02:00
pepa c292c3bcde Na sestavě "žádost o služební cestu" byl opraven seznam spolucestujících- nyní se generuje vedle sebe a bylo přidáno pole pro cizí osobu.
closes #213
2015-04-27 12:02:03 +02:00
pepa 9d202192ee Změněn způsob přenosu vyúčtování ke spolucestujícím: výúčtování se přenese pouze v případě, když ho ještě spolucestující needitoval. Do zeditovaného vyúčtování se vyúčtování žadatele už nepřenáší.
Vyúčtování spolucestujících se schvalují každé zvlášť.
refs #212
2015-04-24 14:00:36 +02:00
pepa 93a463db69 Upraveno třídění výsledku fulltextového vyhledávání- niní se třídí podle relevancve výsledku.
refs #211
2015-04-13 09:56:04 +02:00
pepa 3a5da06c48 Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-04-12 18:54:09 +02:00
pepa 76969a2baf - Přidán fulltext index na číslo požadavku.
- Opravena velikost písmen v SQL dotazu pro úklid tabulek s přiloženými soubory.
- Informativní číslo verze zvýšeno na 2.0
2015-04-12 18:53:43 +02:00
franta 4e6af2ceed Upraveny data a razítka na sestavách služební cesty.
closes #205
2015-04-09 12:14:37 +02:00
franta ef431867e1 V globálním nastavení umožněn upload loga školy.
Upraveny tiskových sestav vloženo logo a název organizace.

closes #199
2015-04-08 11:35:41 +02:00
franta 25c8405f03 Ag. Služební cesty / Cestovní příkazy
• přidáno povinné pole Zpráva z pracovní cesty
• u existujících záznamů přidán text "Zpráva z pracovní cesty"
• upraveno rozdělení formuláře

closes #203
2015-03-23 07:41:23 +01:00
franta ac90b0a2e3 Formulář ag. Služební cesty / Aktuální požadavky
• přidáno textové pole "Cizí osoby"
• upraven popisek formuláře
• upraven vzhled a zarovnání prvků
• přidána kontrola ukazatele při promazávání souborů na disku i v
databázi
• sjednocena maska pro formátování data v <datebox>
closes #197
2015-03-19 10:12:18 +01:00
pepa 9c5679af2c Implementováno schvalování vyúčtování služebních cest.
closes #202
2015-03-17 10:20:59 +01:00
franta ceac59c8d3 Agenda Fakturace požadavků
• grid rozdělen na 2 záložky [Nevyřízené] a [Archive]
• na formuláři přidán checkbox [Vyřízeno]

closes #207
2015-03-09 09:37:58 +01:00
pepa 5d9e6226d3 Merge branch 'Verze_1.0' 2015-03-08 20:16:34 +01:00
pepa 9b8bfe2228 Na formulář požadavku na služební byl přidán checkbox pro vygenerování vyúčtování služební cesty i pro spolucestující. Spolucestující nemůžou vyúčtování měnit.
closes #212
2015-03-08 19:33:15 +01:00
pepa 42deec695a Oprava merge. 2015-03-08 10:39:17 +01:00
pepa e01e32f10c Merge branch 'Verze_1.0'
Conflicts:
	src/main/java/info/bukova/isspst/services/requirement/TripRequirementService.java
	src/main/java/info/bukova/isspst/services/requirement/TripRequirementServiceImpl.java
	src/main/java/info/bukova/isspst/ui/requirement/TripRequirementForm.java
	src/main/webapp/WEB-INF/locales/zk-label.properties
2015-03-07 19:00:00 +01:00
pepa 021d73bf48 Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-03-06 14:51:01 +01:00
pepa 340abb5269 Vypnuto debug-js v zk.xml. 2015-03-06 14:48:42 +01:00
franta 724f6b3559 Implementováno třístavové vyhledávání boolean hodnot.
Agendu Schválené položky požadavků lze nyní filtrovat podle materiálu a
služeb.

#closes 206
2015-03-06 10:27:37 +01:00
pepa ecd3cf426b Umožněn upload souborů k požadavkům na služební cesty a k vyúčtování služební cesty.
closes #131
2015-03-03 14:46:21 +01:00
pepa c6ebf8959b Umožněna změna data schválení požadavku.
closes #209
2015-03-01 19:28:49 +01:00
pepa 48d2c75d7b Merge remote-tracking branch 'origin/master'
Conflicts:
	src/main/webapp/app/mainMenu.zul
2015-02-23 22:28:14 +01:00
pepa 1d2810f78d Obsah přiložených dokumentů ve formátech ODF - OpenOffice, openxml - MS Office a PDF se extrahuje do čistého textu a indexuje pro fulltextové vyhledávání.
closes #211
2015-02-23 22:21:25 +01:00
franta c4f5671327 Přepracováno vykreslování dialogu Faturace požadavků.
Vyhledávací edit dostane focus po otevření okna.
Opraveno Main menu.


closes #210
2015-02-23 21:06:41 +01:00
pepa 860c7227cd Opraven merge mainMenu.zul 2015-02-17 21:19:33 +01:00
pepa f94afbc3ed Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-02-15 19:15:32 +01:00
pepa 1df90a41c4 Do agendy požadavků na služební cesty byla přidána možnost prohlížení vyúčtování služební cesty.
closes #200
2015-02-15 19:14:03 +01:00
franta 93e1ef1fd3 Merge branch 'master' of https://git.bukova.info/repos/git/isspst
Conflicts:
	src/main/webapp/app/mainMenu.zul
2015-02-09 13:35:35 +01:00
franta 277ea0f993 Merge branch 'Verze_1.0'
Conflicts:
	src/main/webapp/WEB-INF/locales/zk-label.properties
	src/main/webapp/app/mainMenu.zul
2015-02-09 13:31:48 +01:00
pepa 678c140a94 Třídy pro práci se soubory a přílohami záznamů.
refs #131
2015-02-02 22:18:38 +01:00
pepa 566b408ddd Reindaxece fulltextu se spouští asynchronně- rychlejší start aplikace 2015-01-29 13:56:55 +01:00
pepa 9ec15943ed Merge branch 'Verze_1.0' 2015-01-21 10:59:48 +01:00
pepa 024f1321ad Merge branch 'Verze_1.0'
Conflicts:
	src/main/webapp/WEB-INF/locales/zk-label.properties
2015-01-20 15:21:55 +01:00
pepa ea64e5a888 Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-01-20 10:35:59 +01:00
pepa 08532dcd02 Merge branch 'Verze_1.0'
Conflicts:
	src/main/webapp/WEB-INF/locales/zk-label.properties
	src/main/webapp/app/mainMenu.zul
2015-01-20 10:35:38 +01:00
franta c04f74c5a2 Merge branch 'Verze_1.0' 2015-01-20 10:13:19 +01:00
franta eed31fe6da Merge branch 'Verze_1.0' 2015-01-20 09:02:47 +01:00
franta 61a4b3ba82 Merge branch 'Verze_1.0'
Conflicts:
	src/main/java/info/bukova/isspst/AppInitListener.java
	src/main/java/info/bukova/isspst/Constants.java
	src/main/java/info/bukova/isspst/data/Order.java
	src/main/java/info/bukova/isspst/data/OrderItem.java
	src/main/java/info/bukova/isspst/data/RequirementBase.java
	src/main/java/info/bukova/isspst/data/RequirementItem.java
	src/main/java/info/bukova/isspst/ui/settings/NumberSeriesVM.java
2015-01-19 13:29:41 +01:00
pepa ee2539000c Merge branch 'Verze_1.0' 2015-01-18 21:04:30 +01:00
pepa 0f02efbec3 Merge branch 'Verze_1.0' 2015-01-15 15:45:39 +01:00
pepa b357d0a7ef Merge branch 'Verze_1.0' of https://git.bukova.info/repos/git/isspst 2015-01-15 10:48:24 +01:00
pepa 100889d44a Merge branch 'master' of https://git.bukova.info/repos/git/isspst 2015-01-15 10:47:32 +01:00
pepa 765c56f250 Merge branch 'Verze_1.0'
Conflicts:
	src/main/java/info/bukova/isspst/Constants.java
2015-01-15 10:46:02 +01:00
franta f5e69ce80d Merge branch 'Verze_1.0' 2015-01-13 14:12:44 +01:00
pepa e9cd08c249 Implementováno fulltextové vyhledávání přes všechny záznamy. Nutno
dořešit konfiguraci adresáře pro ukládání fulltextového indexu.
2015-01-09 14:00:27 +01:00
pepa 34f1bb86de Merge branch 'master' into fulltext 2015-01-07 17:07:53 +01:00
pepa ad2a861a7b Vyhledávání - index.zul 2015-01-07 17:07:46 +01:00
pepa cf6c523698 Umožněna deaktivace modulu prostřednictvím nastavení objektu modulu ve
třídě Constants. Položku neaktivního modulu v menu lze skrýt funkcí
isActive definovanou v module.tld (viz mainMenu.zul).
2015-01-07 17:03:58 +01:00
pepa 02311ae5dd Rozdělané fulltextové vyhledávání 2015-01-06 09:08:36 +01:00
263 changed files with 11914 additions and 1685 deletions
+79
View File
@@ -0,0 +1,79 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 16464111046498525641 (0xe47c45c4252121c9)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=CZ, ST=Vysocina, O=bukova.info, CN=Josef Rokos/emailAddress=rokos@bukova.info
Validity
Not Before: Jun 24 09:59:50 2015 GMT
Not After : Jun 21 09:59:50 2025 GMT
Subject: C=CZ, ST=Vysocina, O=bukova.info, CN=Josef Rokos/emailAddress=rokos@bukova.info
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:bc:fb:64:50:5b:58:03:8c:20:1c:77:d3:50:31:
94:55:78:d6:05:bb:bc:88:9d:cb:20:b1:8c:ff:ac:
fc:97:1a:b1:9c:29:c4:ac:af:ed:3b:de:93:d5:cf:
75:3e:d0:05:41:32:bf:12:25:53:60:28:af:ff:3e:
3c:3a:4c:52:78:3f:b2:78:b9:c6:2f:fc:0e:44:eb:
65:c3:7f:38:2b:ab:88:37:8c:68:55:69:e3:3d:5e:
9b:99:25:11:55:06:ab:e8:c1:fa:54:da:5b:e7:9b:
3e:3f:39:4f:cf:b3:cb:48:cf:96:02:89:0b:7e:24:
c7:00:e9:ce:8d:ea:07:cf:21:f2:89:51:c8:cc:7a:
04:e4:68:6f:1c:a8:e0:76:18:40:62:ee:2f:bd:13:
64:b7:1e:2e:18:bb:b1:d4:17:d5:fb:1f:07:59:65:
46:f0:c4:51:dc:ac:62:ff:31:a8:72:26:a6:1a:88:
37:23:82:49:9a:02:d2:39:74:98:71:7f:a4:77:52:
3a:ed:22:2e:99:9c:81:2c:48:16:3c:82:7b:af:2c:
0d:4b:28:4d:e0:46:7d:b5:b8:ea:3f:e7:5a:5b:4f:
d8:06:b2:a3:86:2f:8b:5b:9c:bc:04:2e:64:b6:e1:
09:c9:14:6d:54:7e:86:40:7b:66:33:27:33:4a:3d:
7c:97
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
EF:9B:88:5C:07:27:79:EA:60:90:5C:7A:28:45:FB:7F:35:E6:CB:3F
X509v3 Authority Key Identifier:
keyid:EF:9B:88:5C:07:27:79:EA:60:90:5C:7A:28:45:FB:7F:35:E6:CB:3F
X509v3 Basic Constraints:
CA:TRUE
Signature Algorithm: sha1WithRSAEncryption
08:e9:a4:32:cc:35:7c:66:5a:ea:f2:bd:e6:75:78:81:52:11:
22:27:32:c9:ec:91:6e:51:8a:f1:1e:0f:25:8a:e1:64:ba:e4:
85:1c:e4:fd:75:f0:26:3d:65:62:16:29:20:4f:5f:d2:66:36:
de:2b:bd:7b:96:71:f6:2c:d1:c5:54:69:89:dd:52:20:49:49:
b1:ac:09:b4:1e:33:59:0d:89:fd:a4:28:7a:70:96:e5:cb:58:
7e:b9:1d:02:7a:33:ee:ad:6a:ad:2c:3c:5e:7d:cc:f5:72:69:
51:fd:77:b4:0f:10:fd:9e:c2:1a:04:c5:a9:56:6e:fd:66:9f:
b6:1c:f9:d3:68:f4:4f:8c:6c:67:af:f5:e0:a5:30:67:a6:a7:
9b:6e:16:89:8a:e5:b4:20:f4:f7:74:f4:9c:ca:5d:c7:2f:e6:
30:9d:6b:2e:95:29:c1:e7:aa:d7:d6:59:dc:a9:f0:10:40:02:
66:3f:58:a2:38:8c:89:1a:0b:94:1a:e5:80:49:14:44:f4:06:
b1:11:1a:cd:ef:76:6a:bf:f8:6f:58:9d:af:a3:6b:9a:8e:bb:
6c:10:d6:d8:4e:73:58:20:0b:99:38:41:d4:22:d4:80:0b:09:
0d:25:40:3e:66:15:a0:44:4e:d6:59:5a:58:07:e5:4b:62:f1:
e9:ae:b6:7c
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIJAOR8RcQlISHJMA0GCSqGSIb3DQEBBQUAMG4xCzAJBgNV
BAYTAkNaMREwDwYDVQQIDAhWeXNvY2luYTEUMBIGA1UECgwLYnVrb3ZhLmluZm8x
FDASBgNVBAMMC0pvc2VmIFJva29zMSAwHgYJKoZIhvcNAQkBFhFyb2tvc0BidWtv
dmEuaW5mbzAeFw0xNTA2MjQwOTU5NTBaFw0yNTA2MjEwOTU5NTBaMG4xCzAJBgNV
BAYTAkNaMREwDwYDVQQIDAhWeXNvY2luYTEUMBIGA1UECgwLYnVrb3ZhLmluZm8x
FDASBgNVBAMMC0pvc2VmIFJva29zMSAwHgYJKoZIhvcNAQkBFhFyb2tvc0BidWtv
dmEuaW5mbzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALz7ZFBbWAOM
IBx301AxlFV41gW7vIidyyCxjP+s/JcasZwpxKyv7Tvek9XPdT7QBUEyvxIlU2Ao
r/8+PDpMUng/sni5xi/8DkTrZcN/OCuriDeMaFVp4z1em5klEVUGq+jB+lTaW+eb
Pj85T8+zy0jPlgKJC34kxwDpzo3qB88h8olRyMx6BORobxyo4HYYQGLuL70TZLce
Lhi7sdQX1fsfB1llRvDEUdysYv8xqHImphqINyOCSZoC0jl0mHF/pHdSOu0iLpmc
gSxIFjyCe68sDUsoTeBGfbW46j/nWltP2Aayo4Yvi1ucvAQuZLbhCckUbVR+hkB7
ZjMnM0o9fJcCAwEAAaNQME4wHQYDVR0OBBYEFO+biFwHJ3nqYJBceihF+3815ss/
MB8GA1UdIwQYMBaAFO+biFwHJ3nqYJBceihF+3815ss/MAwGA1UdEwQFMAMBAf8w
DQYJKoZIhvcNAQEFBQADggEBAAjppDLMNXxmWuryveZ1eIFSESInMsnskW5RivEe
DyWK4WS65IUc5P118CY9ZWIWKSBPX9JmNt4rvXuWcfYs0cVUaYndUiBJSbGsCbQe
M1kNif2kKHpwluXLWH65HQJ6M+6taq0sPF59zPVyaVH9d7QPEP2ewhoExalWbv1m
n7Yc+dNo9E+MbGev9eClMGemp5tuFomK5bQg9Pd09JzKXccv5jCday6VKcHnqtfW
Wdyp8BBAAmY/WKI4jIkaC5Qa5YBJFET0BrERGs3vdmq/+G9Yna+ja5qOu2wQ1thO
c1ggC5k4QdQi1IALCQ0lQD5mFaBETtZZWlgH5Uti8emutnw=
-----END CERTIFICATE-----
+44 -10
View File
@@ -24,7 +24,7 @@
<repository>
<id>fdvsolution.public</id>
<name>Dynamic Jasper</name>
<url>http://archiva.fdvs.com.ar/repository/public1/</url>
<url>http://nexus.fdvs.com.ar/content/groups/public/</url>
</repository>
</repositories>
@@ -215,16 +215,20 @@
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.8.Final</version>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.2.8.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search</artifactId>
<version>4.4.6.Final</version>
</dependency>
<!-- ZK -->
<dependency>
@@ -344,7 +348,20 @@
<artifactId>joda-time</artifactId>
<version>2.4</version>
</dependency>
<!-- Text extractors -->
<dependency>
<groupId>org.apache.odftoolkit</groupId>
<artifactId>simple-odf</artifactId>
<version>0.7-incubating</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.11</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
@@ -390,6 +407,23 @@
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.js</include>
<include>**/*.wpd</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.xml</include>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>
<dependencyManagement>
<dependencies>
@@ -12,6 +12,7 @@ import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.reporting.ReportMapping;
import info.bukova.isspst.reporting.ReportType;
import info.bukova.isspst.services.dbinfo.DbInfoService;
import info.bukova.isspst.services.fulltext.FullTextService;
import info.bukova.isspst.services.munits.MUnitService;
import info.bukova.isspst.services.numberseries.NumberSeriesService;
import info.bukova.isspst.services.requirement.RequirementTypeService;
@@ -19,19 +20,17 @@ import info.bukova.isspst.services.settings.GlobalSettingsService;
import info.bukova.isspst.services.users.PermissionService;
import info.bukova.isspst.services.users.RoleService;
import info.bukova.isspst.services.users.UserService;
import java.math.BigDecimal;
import java.util.List;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import java.math.BigDecimal;
import java.util.List;
public class AppInitListener implements ServletContextListener {
@@ -43,6 +42,7 @@ public class AppInitListener implements ServletContextListener {
private NumberSeriesService nsService;
private RequirementTypeService reqTypeService;
private GlobalSettingsService gSettingsService;
private FullTextService ftService;
@Override
public void contextDestroyed(ServletContextEvent arg0) {
@@ -63,6 +63,7 @@ public class AppInitListener implements ServletContextListener {
nsService =ctx.getBean(NumberSeriesService.class);
gSettingsService = ctx.getBean(GlobalSettingsService.class);
reqTypeService = ctx.getBean(RequirementTypeService.class);
ftService = ctx.getBean(FullTextService.class);
userService.grantAdmin();
this.checkDbInfo();
@@ -74,11 +75,15 @@ public class AppInitListener implements ServletContextListener {
this.checkNumberSeries();
checkReqTypes();
this.checkGlobalSettings();
buildFulltext();
userService.removeAccess();
loadModuleReports();
}
private void buildFulltext() {
ftService.reindex();
}
private void checkDbInfo()
{
List<User> userList = userService.getAll();
@@ -223,6 +228,9 @@ public class AppInitListener implements ServletContextListener {
private void checkPermissions() {
for (Module m : Constants.MODULES) {
if (!m.isDefaultPermissions()) {
continue;
}
for (Permission p : Constants.DEF_PERMISSIONS) {
if (permService.getPermissionByModule(m.getId(), p.getAuthority()) == null) {
p.setModule(m.getId());
@@ -1,13 +1,48 @@
package info.bukova.isspst;
import org.jfree.util.Log;
public class BooleanUtils
{
public static boolean isEqualByBoolean(Boolean b1, Boolean b2)
private static final String TAG = BooleanUtils.class.getSimpleName();
public static boolean isEqualByBooleanValue(Boolean b1, Boolean b2)
{
boolean bool1 = ((b1 == null) ? false : b1.booleanValue());
boolean bool2 = ((b2 == null) ? false : b2.booleanValue());
boolean equals = (bool1 == bool2);
return equals;
}
public static boolean isEqualByBoolean(Boolean b1, Boolean b2)
{
if ((b1 == null) && (b2 == null))
{
return true;
}
else if ((b1 != null) && (b2 != null))
{
return (b1.booleanValue() == b2.booleanValue());
}
return false;
}
public static boolean isEqualFilterByBoolean(Boolean value, Boolean filterValue)
{
if (filterValue == null)
{
// Show all records
return true;
}
if (value == null)
{
// Fuck!!! Tri-state data (null, false, true)... We need new solution for selecting ALL data
Log.warn(TAG + "\nVelky Boolean v databazi... Pozor na filtrovani.");
return true;
}
return (value.booleanValue() == filterValue.booleanValue());
}
}
@@ -1,15 +1,19 @@
package info.bukova.isspst;
import info.bukova.isspst.data.Order;
import info.bukova.isspst.data.Permission;
import info.bukova.isspst.data.PermissionType;
import info.bukova.isspst.data.Requirement;
import info.bukova.isspst.data.RequirementType;
import info.bukova.isspst.data.Role;
import info.bukova.isspst.data.TripBill;
import info.bukova.isspst.data.TripBillApproval;
import info.bukova.isspst.data.TripRequirement;
import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.reporting.ReportMapping;
import info.bukova.isspst.services.addressbook.AdbService;
import info.bukova.isspst.services.buildings.BuildingService;
import info.bukova.isspst.services.fulltext.FullTextService;
import info.bukova.isspst.services.invoicing.InvoicingService;
import info.bukova.isspst.services.munits.MUnitService;
import info.bukova.isspst.services.orders.ApprovedService;
@@ -19,6 +23,7 @@ import info.bukova.isspst.services.reqsubjects.ServiceItemService;
import info.bukova.isspst.services.requirement.RequirementService;
import info.bukova.isspst.services.requirement.RequirementTypeService;
import info.bukova.isspst.services.requirement.TripRequirementService;
import info.bukova.isspst.services.signeddocs.SignedDocumentService;
import info.bukova.isspst.services.tripbill.TripBillService;
import info.bukova.isspst.services.users.RoleService;
import info.bukova.isspst.services.users.UserService;
@@ -30,7 +35,7 @@ import java.util.Map;
public class Constants {
public final static long DB_VERSION = 2;
public final static long DB_VERSION = 5;
public final static String DEF_ADMIN = "admin";
public final static String DEF_ADMIN_PASSWD = "admin";
@@ -81,6 +86,8 @@ public class Constants {
public final static String MOD_APPROVED = "APPROVED";
public final static String MOD_ORDER = "ORDER";
public final static String MOD_INVOICING = "INVOICING";
public final static String MOD_SEARCH = "SEARCH";
public final static String MOD_SIGNEDDOCS = "SIGNEDDOCS";
public final static Module MODULES[] = {
new Module(MOD_USERS, "Uživatelé", UserService.class),
new Module(MOD_PERMISSIONS, "Práva", RoleService.class),
@@ -96,7 +103,10 @@ public class Constants {
new Module(MOD_TRIPBILL, "Cestovní příkazy", TripBillService.class),
new Module(MOD_APPROVED, "Schválené položky požadavků", ApprovedService.class),
new Module(MOD_ORDER, "Objednávky", OrderService.class),
new Module(MOD_INVOICING, "Fakturace požadavků", InvoicingService.class) };
new Module(MOD_INVOICING, "Fakturace požadavků", InvoicingService.class),
new Module(MOD_SEARCH, "Fulltextové vyhledávání", FullTextService.class, true, false),
new Module(MOD_SIGNEDDOCS, "Podepsané dokumenty", SignedDocumentService.class, true, false),
};
public final static String PERM_APPROVE = "PERM_APPROVE";
public final static String PERM_SHOW_WORKGROUP_REQ = "PERM_SHOW_WORKGROUP_REQ";
@@ -105,6 +115,8 @@ public class Constants {
public final static String PERM_EDIT_NEW = "PERM_EDIT_NEW";
public final static String PERM_EDIT_OWN = "PERM_EDIT_OWN";
public final static String PERM_DELETE_NEW = "PERM_DELETE_NEW";
public final static String PERM_SEARCH = "PERM_SEARCH";
public final static String PERM_PAY_BILL = "PERM_PAY_BILL";
public final static Permission SPECIAL_PERMISSIONS[] = {
new Permission(PERM_EDIT_NEW, "Upravit neschválené", MOD_REQUIREMENTS, PermissionType.GLOBAL),
@@ -120,16 +132,23 @@ public class Constants {
new Permission(PERM_SHOW_CENTRE_REQ, "Zobrazení požadavků střediska", MOD_TRIPREQUIREMENTS, PermissionType.CENTRE),
new Permission(PERM_SHOW_ALL_REQ, "Zobrazení všech požadavků", MOD_TRIPREQUIREMENTS, PermissionType.GLOBAL),
new Permission(PERM_APPROVE, "Schválení", MOD_TRIPREQUIREMENTS, PermissionType.WORKGROUP),
new Permission(PERM_SEARCH, "Vyhledávat", MOD_SEARCH, PermissionType.GLOBAL),
new Permission(PERM_READ, "Číst", MOD_SIGNEDDOCS, PermissionType.GLOBAL),
new Permission(PERM_PAY_BILL, "Vyplacení SC", MOD_TRIPBILL, PermissionType.GLOBAL)
};
public final static String DYNAMIC_REPORT_NAME = "Tabulková sestava";
public final static ReportMapping REPORTS[] = {
new ReportMapping(MOD_ADDRESSBOOK, new Report("Adresní karty", "address")),
new ReportMapping(MOD_ADDRESSBOOK, new Report("Adresa", "address", false, true)),
new ReportMapping(MOD_TRIPBILL, new Report("Žádost", "tripRequirement", false, true)),
new ReportMapping(MOD_TRIPBILL, new Report("Vyúčtování", "tripBill", false, true)),
new ReportMapping(MOD_ORDER, new Report("Objednávka", "order", true, true)),
new ReportMapping(MOD_REQUIREMENTS, new Report("Požadavky", "requirements"))
new ReportMapping(MOD_ADDRESSBOOK, new Report(1, false, "Adresní karty", "address")),
new ReportMapping(MOD_ADDRESSBOOK, new Report(2, false, "Adresa", "address", false, true)),
new ReportMapping(MOD_TRIPBILL, new Report(3, false, "Žádost", "tripRequirement", false, true)),
new ReportMapping(MOD_TRIPBILL, new Report(4, true, "Vyúčtování", "tripBill", false, true, true)),
new ReportMapping(MOD_ORDER, new Report(5, false, "Objednávka", "order", true, true)),
new ReportMapping(MOD_REQUIREMENTS, new Report(6, false, "Požadavky", "requirements")),
new ReportMapping(MOD_TRIPREQUIREMENTS, new Report(7, true, "Žádost o SC", "tripRequirementApp", false, true)),
new ReportMapping(MOD_REQUIREMENTS, new Report(8, true, "Protokol o kontrole", "orderRequirement", false, true))
};
public final static String REQTYPE_ORDER = "ORDER";
@@ -146,8 +165,17 @@ public class Constants {
public final static Map<Class<?>, String> URL_MAP = Collections.unmodifiableMap(new HashMap<Class<?>, String>() {{
put(Requirement.class, "/main/orders/");
put(TripRequirement.class, "/main/trips/requirements/");
put(TripBillApproval.class, "/main/trips/bill/");
put(Order.class, "/main/orders/created/");
put(TripBill.class, "/main/trips/bill/");
}} );
public final static int LEN_TEXT = 255;
public final static int LEN_DESCRIPTION = 8192;
public final static int LEN_RESULT_MESSAGE = 8192;
public final static String MAIL_URL_KEYWORD = "-url-";
public final static String KEY_SIGN_DATA = "SIGN_DATA";
public final static String KEY_SIGN_GUID = "SIGN_GUID";
}
@@ -2,6 +2,7 @@ package info.bukova.isspst;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import org.apache.commons.lang.time.DateUtils;
@@ -54,4 +55,31 @@ public class DateTimeUtils
{
return DateTimeUtils.getDate(DateTimeUtils.getCurrDateTime());
}
public static Calendar getCalendarDelta(Date value, int calendarType, int delta) {
if (value == null) {
value = DateTimeUtils.getCurrDate();
}
Calendar calendar = new GregorianCalendar();
calendar.setTime(value);
int deltaValue = calendar.get(calendarType);
calendar.set(calendarType, deltaValue + delta);
return calendar;
}
public static Calendar getCalendar(Date value) {
if (value == null) {
value = DateTimeUtils.getCurrDate();
}
Calendar calendar = new GregorianCalendar();
calendar.setTime(value);
return calendar;
}
public static Date getDateDelta(Date value, int calendarType, int delta) {
Calendar calendar = DateTimeUtils.getCalendarDelta(value, calendarType, delta);
return calendar.getTime();
}
}
@@ -1,16 +1,26 @@
package info.bukova.isspst;
import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.services.AbstractService;
import info.bukova.isspst.services.ModuleNotActiveException;
import java.util.ArrayList;
import java.util.List;
/**
* @author Pepa Rokos
*
* Třída reprezentuje informace o modulu (agendě).
*
*/
public class Module {
private String id;
private String name;
private Class<?> serviceClass;
private List<Report> reports;
private boolean defaultPermissions;
private boolean active;
public Class<?> getServiceClass() {
return serviceClass;
@@ -20,11 +30,42 @@ public class Module {
this.serviceClass = serviceClass;
}
/**
*
* @param id identifikátor modulu
* @param name jméno zobrazované v aplikaci
* @param serviceClass servisní třída
*/
public Module(String id, String name, Class<?> serviceClass) {
this.id = id;
this.name = name;
this.serviceClass = serviceClass;
reports = new ArrayList<Report>();
defaultPermissions = true;
active = true;
}
/**
* @param id identifikátor modulu
* @param name jméno zobrazované v aplikaci
* @param serviceClass servisní třída
* @param active příznak, jestli je modul aktivní
*/
public Module(String id, String name, Class<?> serviceClass, boolean active) {
this(id, name, serviceClass);
this.active = active;
}
/**
* @param id identifikátor modulu
* @param name jméno zobrazované v aplikaci
* @param serviceClass servisní třída
* @param active příznak, jestli je modul aktivní.
* @param defaultPermissions příznak určující jestli modul kontroluje výchozí práva (čtení, zápis, modifikace, mazání)
*/
public Module(String id, String name, Class<?> serviceClass, boolean active, boolean defaultPermissions) {
this(id, name, serviceClass, active);
this.defaultPermissions = defaultPermissions;
}
public String getId() {
@@ -51,4 +92,33 @@ public class Module {
this.reports.add(report);
}
/**
* Pokud je true, modul kontroluje výchozí práva (čtení, zápis, modifikace, mazání). Má vliv
* na generování formulářů v nastavení práv.
*
* @return výchozí práva. Default true
*/
public boolean isDefaultPermissions() {
return defaultPermissions;
}
public void setDefaultPermissions(boolean defaultPermissions) {
this.defaultPermissions = defaultPermissions;
}
/**
* Určuje, zda je modul aktivní. Neaktivní moduly nejsou viditelné v UI. Při pokusu o přístup přímo přes URL
* se generuje výjimka {@link ModuleNotActiveException}. Pokud servisní třída modulu nedědí z {@link AbstractService},
* musí se implementovat kontrola aktivity do příslušné třídy.
*
* @return aktivita. Default true
*/
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
}
@@ -0,0 +1,94 @@
package info.bukova.isspst;
import info.bukova.isspst.data.DataModel;
import info.bukova.isspst.services.Service;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContext;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ModuleUtils {
public static List<Module> getActiveModules() {
List<Module> modules = new ArrayList<Module>();
for (Module m : Arrays.asList(Constants.MODULES)) {
if (m.isActive()) {
modules.add(m);
}
}
return modules;
}
public static Module getModule(Class<?> serviceClass) {
for (Module m : Constants.MODULES) {
if (Arrays.asList(serviceClass.getInterfaces()).contains(m.getServiceClass())) {
return m;
}
}
return null;
}
public static Module getModule(String id) {
for (Module m : Constants.MODULES) {
if (m.getId().equals(id)) {
return m;
}
}
return null;
}
public static Module getModule(DataModel entity, ServletContext sc) {
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
for (Module m : Constants.MODULES) {
Service<?> service;
try {
service = (Service<?>) ctx.getBean(m.getServiceClass());
} catch (NoSuchBeanDefinitionException e) {
String[] beans = ctx.getBeanNamesForType(m.getServiceClass());
for (String s : beans) {
service = (Service<?>) ctx.getBean(s);
if (service.getEntityClasses().contains(entity.getClass())) {
return m;
}
}
continue;
} catch (ClassCastException e) { //nestandardní moduly neřeší...
continue;
}
if (service.getEntityClasses().contains(entity.getClass())) {
return m;
}
}
return null;
}
public static Service<?> getServiceInstance(Module m, ServletContext sc) {
WebApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
try {
return (Service<?>) ctx.getBean(m.getServiceClass());
} catch (NoSuchBeanDefinitionException e) {
String[] beans = ctx.getBeanNamesForType(m.getServiceClass());
return (Service<?>) ctx.getBean(beans[0]);
}
}
public static boolean isActive(String id) {
return getModule(id).isActive();
}
}
@@ -0,0 +1,31 @@
package info.bukova.isspst;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegExUtils {
public static List<String> getMatches(String input, String regEx, int group) {
List<String> list = new ArrayList<String>();
if (!StringUtils.isNullOrEmpty(input) && !StringUtils.isNullOrEmpty(regEx)) {
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(input);
int groupCount = matcher.groupCount() + 1;
if ((groupCount >= 0) && (group < groupCount)) {
while (matcher.find()) {
String item = matcher.group(group);
list.add(item);
}
}
}
return list;
}
public static List<String> getMatches(String input, String regEx) {
return RegExUtils.getMatches(input, regEx, 0);
}
}
@@ -29,7 +29,7 @@ public class RequirementUrlResolver implements EntityUrlResolver {
Requirement req = (Requirement)entity;
if (req.getKind() == Constants.REQ_TYPE_MATERIAL) {
if (req.getKind() != null && req.getKind() == Constants.REQ_TYPE_MATERIAL) {
return defaultUrl + Constants.URL_MAP.get(req.getClass()) + "material/?select=" + String.valueOf(req.getId());
} else {
return defaultUrl + Constants.URL_MAP.get(req.getClass()) + "services/?select=" + String.valueOf(req.getId());
@@ -5,6 +5,7 @@ import info.bukova.isspst.data.User;
import info.bukova.isspst.data.Workgroup;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -13,16 +14,18 @@ public class SessionData implements Serializable {
/**
*
*/
private static final long serialVersionUID = -764426911263559758L;
private static final long serialVersionUID = -764426911263559759L;
private List<Workgroup> userCentres;
private List<Workgroup> userWorkgroups;
private User currentUser;
private Map<Integer, List<Role>> workgroupRoles;
private boolean loginFailed;
private Map<String, Object> properties;
public SessionData() {
loginFailed = false;
properties = new HashMap<String, Object>();
}
public List<Workgroup> getUserCentres() {
@@ -65,4 +68,11 @@ public class SessionData implements Serializable {
this.loginFailed = loginFailed;
}
public void setProperty(String key, Object value) {
properties.put(key, value);
}
public Object getProperty(String key) {
return properties.get(key);
}
}
@@ -0,0 +1,25 @@
package info.bukova.isspst;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContext;
/**
* @author Pepa Rokos
*/
public class SpringUtils {
private static WebApplicationContext webCtx(ServletContext sc) {
return WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
}
public static Object getBean(String name, ServletContext sc) {
return webCtx(sc).getBean(name);
}
public static <T> T getBean(Class<T> clazz, ServletContext sc) {
return webCtx(sc).getBean(clazz);
}
}
@@ -7,6 +7,15 @@ import org.zkoss.util.resource.Labels;
public class StringUtils
{
public static boolean isNullOrEmpty(String str)
{
return ((str == null) || (str.isEmpty()));
}
public static boolean isNullOrTrimmedEmpty(String str)
{
return ((str == null) || (str.trim().isEmpty()));
}
public static String nullToEmptyString(String str)
{
@@ -0,0 +1,29 @@
package info.bukova.isspst;
import info.bukova.isspst.data.TripBillApproval;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
/**
* @author Pepa Rokos
*/
public class TripBillAprovalUrlResolver implements EntityUrlResolver {
@Autowired
private HttpServletRequest request;
@Override
public String entityUrl(Object entity) {
String defUrl = request.getRequestURL().toString();
defUrl = defUrl.substring(0, defUrl.indexOf(request.getServletPath()));
if (entity instanceof TripBillApproval) {
String url = Constants.URL_MAP.get(entity.getClass());
return defUrl + url + "?select=" + String.valueOf(((TripBillApproval)entity).getId());
}
return defUrl + "/app";
}
}
@@ -0,0 +1,7 @@
package info.bukova.isspst.dao;
import info.bukova.isspst.data.SignedDocument;
public interface SignedDocumentDao extends BaseDao<SignedDocument> {
}
@@ -0,0 +1,9 @@
package info.bukova.isspst.dao;
import info.bukova.isspst.data.TripBillApproval;
/**
* @author Pepa Rokos
*/
public interface TripBillApprovalDao extends BaseDao<TripBillApproval> {
}
@@ -0,0 +1,9 @@
package info.bukova.isspst.dao.jpa;
import info.bukova.isspst.dao.SignedDocumentDao;
import info.bukova.isspst.data.SignedDocument;
public class SignedDocumentDaoJPA extends BaseDaoJPA<SignedDocument> implements SignedDocumentDao {
}
@@ -0,0 +1,11 @@
package info.bukova.isspst.dao.jpa;
import info.bukova.isspst.dao.TripBillApprovalDao;
import info.bukova.isspst.data.TripBillApproval;
/**
* @author Pepa Rokos
*/
public class TripBillApprovalDaoJPA extends BaseDaoJPA<TripBillApproval> implements TripBillApprovalDao {
}
@@ -7,11 +7,18 @@ import java.util.List;
import javax.persistence.Embeddable;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
@Embeddable
@Indexed
public class AddressEmb
{
private int id;
@Field(index = Index.YES, analyze = Analyze.YES)
private String company;
private String department;
private String contactName;
@@ -11,7 +11,11 @@ import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
@MappedSuperclass
@Indexed
public abstract class BaseData implements OwnedDataModel {
@Id
@@ -24,9 +28,11 @@ public abstract class BaseData implements OwnedDataModel {
private Date modified;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="OWNED_BY_ID")
@IndexedEmbedded
private User ownedBy;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="MODIFIED_BY_ID")
@IndexedEmbedded
private User modifiedBy;
@Transient
private boolean valid;
@@ -0,0 +1,97 @@
package info.bukova.isspst.data;
import org.hibernate.annotations.Type;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author Pepa Rokos
*/
@Entity
@Table(name = "FILE_CONTENTS")
@Indexed
public class FileContent {
@Id
@Column(name = "ID")
@GeneratedValue
private int id;
@Column(name = "CONTENT")
@Type(type = "text")
@Field(index = Index.YES, analyze = Analyze.YES)
private String plainText;
@Column(name = "CONTENT_TYPE")
private String contentType;
@Column(name = "PATH_IN_FILESYSTEM")
private String pathInFilesystem;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getPlainText() {
return plainText;
}
public void setPlainText(String content) {
this.plainText = content;
}
public String getContentType() {
return contentType;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getPathInFilesystem() {
return pathInFilesystem;
}
public void setPathInFilesystem(String pathInFilesystem) {
this.pathInFilesystem = pathInFilesystem;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FileContent)) return false;
FileContent that = (FileContent) o;
if (id != that.id) return false;
if (plainText != null ? !plainText.equals(that.plainText) : that.plainText != null) return false;
if (contentType != null ? !contentType.equals(that.contentType) : that.contentType != null) return false;
if (pathInFilesystem != null ? !pathInFilesystem.equals(that.pathInFilesystem) : that.pathInFilesystem != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (plainText != null ? plainText.hashCode() : 0);
result = 31 * result + (contentType != null ? contentType.hashCode() : 0);
result = 31 * result + (pathInFilesystem != null ? pathInFilesystem.hashCode() : 0);
return result;
}
}
@@ -0,0 +1,152 @@
package info.bukova.isspst.data;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "FILE_METAINFO")
@Indexed
public class FileMetainfo extends BaseData {
@Column(name = "FILE_NAME")
@Field(index = Index.YES, analyze = Analyze.YES)
private String fileName;
@Column(name = "MODULE_ID")
private String moduleId;
@Column(name = "RECORD_ID")
private int recordId;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "CONTENT_ID")
@Cascade(CascadeType.SAVE_UPDATE)
@IndexedEmbedded
private FileContent content;
@Column(name = "MD5")
private String md5;
@Column(name = "DESCRIPTION")
@Field(index = Index.YES, analyze = Analyze.YES)
private String description;
private void ensureContentExists() {
if (content == null) {
content = new FileContent();
}
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getPathInFilesystem() {
if (content != null) {
return content.getPathInFilesystem();
}
return null;
}
public void setPathInFilesystem(String pathInFilesystem) {
ensureContentExists();
content.setPathInFilesystem(pathInFilesystem);
}
public String getModuleId() {
return moduleId;
}
public void setModuleId(String moduleId) {
this.moduleId = moduleId;
}
public int getRecordId() {
return recordId;
}
public void setRecordId(int recordId) {
this.recordId = recordId;
}
public FileContent getContent() {
return content;
}
public void setContent(FileContent content) {
this.content = content;
}
public String getMd5() {
return md5;
}
public void setMd5(String md5) {
this.md5 = md5;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getContentType() {
if (content != null) {
return content.getContentType();
}
return null;
}
public void setContentType(String contentType) {
ensureContentExists();
content.setContentType(contentType);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof FileMetainfo)) return false;
FileMetainfo that = (FileMetainfo) o;
if (recordId != that.recordId) return false;
if (content != null ? !content.equals(that.content) : that.content != null) return false;
if (description != null ? !description.equals(that.description) : that.description != null) return false;
if (fileName != null ? !fileName.equals(that.fileName) : that.fileName != null) return false;
if (md5 != null ? !md5.equals(that.md5) : that.md5 != null) return false;
if (moduleId != null ? !moduleId.equals(that.moduleId) : that.moduleId != null) return false;
return true;
}
@Override
public int hashCode() {
int result = fileName != null ? fileName.hashCode() : 0;
result = 31 * result + (moduleId != null ? moduleId.hashCode() : 0);
result = 31 * result + recordId;
result = 31 * result + (content != null ? content.hashCode() : 0);
result = 31 * result + (md5 != null ? md5.hashCode() : 0);
result = 31 * result + (description != null ? description.hashCode() : 0);
return result;
}
}
@@ -1,7 +1,8 @@
package info.bukova.isspst.data;
import java.math.BigDecimal;
import java.util.List;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -11,16 +12,17 @@ import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import java.math.BigDecimal;
import java.util.List;
@Entity
@Table(name = "INVOICING")
public class Invoicing extends BaseData {
public class Invoicing extends BaseData implements Cloneable
{
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "REQUIREMENT_ID")
@Cascade(org.hibernate.annotations.CascadeType.SAVE_UPDATE)
private Requirement requirement;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@@ -31,6 +33,9 @@ public class Invoicing extends BaseData {
@Column(name = "TOTAL_INVOICED", precision = 15, scale = 4)
private BigDecimal totalInvoiced;
@Column(name = "COMPLETED")
private boolean completed;
public Requirement getRequirement() {
return requirement;
}
@@ -55,4 +60,20 @@ public class Invoicing extends BaseData {
this.totalInvoiced = totalInvoiced;
}
public boolean isCompleted()
{
return completed;
}
public void setCompleted(boolean completed)
{
this.completed = completed;
}
@Override
public Object clone() throws CloneNotSupportedException
{
Invoicing cloned = (Invoicing) super.clone();
return cloned;
}
}
@@ -1,5 +1,7 @@
package info.bukova.isspst.data;
import info.bukova.isspst.Constants;
import java.math.BigDecimal;
import java.util.Date;
@@ -220,6 +222,23 @@ public class JoinedItem implements DataModel, FilterableRequirement
this.ownedBy = owner;
}
protected Boolean itemMaterial;
public boolean isItemMaterialReal()
{
return ((this.requirement != null) && (this.requirement.getKind() == Constants.REQ_TYPE_MATERIAL));
}
public Boolean getItemMaterial()
{
return this.itemMaterial;
}
public void setItemMaterial(Boolean value)
{
this.itemMaterial = value;
}
@Override
public boolean equals(Object obj)
{
@@ -18,9 +18,15 @@ import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
@Entity
@Table(name = "ORDERS")
@Indexed
public class Order extends BaseData implements Cloneable
{
@@ -47,6 +53,7 @@ public class Order extends BaseData implements Cloneable
@AttributeOverride(name = "street", column = @Column(name = "SUPPLIER_STREET")),
@AttributeOverride(name = "web", column = @Column(name = "SUPPLIER_WEB")),
@AttributeOverride(name = "zipCode", column = @Column(name = "SUPPLIER_ZIP_CODE")) })
@IndexedEmbedded
private AddressEmb suplier;
@Embedded
@@ -97,10 +104,12 @@ public class Order extends BaseData implements Cloneable
private String deliveryType;
@Column(name = "DESCRIPTION", length = Constants.LEN_DESCRIPTION)
@Field(index = Index.YES, analyze = Analyze.YES)
private String description;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "order", orphanRemoval = true)
@LazyCollection(LazyCollectionOption.TRUE)
@IndexedEmbedded
private List<OrderItem> items;
@Column(name = "TOTAL", precision = 15, scale = 4)
@@ -14,8 +14,14 @@ import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
@Entity
@Table(name = "ORDER_ITEM")
@Indexed
public class OrderItem
{
@@ -28,9 +34,11 @@ public class OrderItem
private String code;
@Column(name = "NAME")
@Field(index = Index.YES, analyze = Analyze.YES)
private String name;
@Column(name = "TEXTITEM")
@Field(index = Index.YES, analyze = Analyze.YES)
private String textItem;
@Column(name = "QUANTITY", precision = 15, scale = 4)
@@ -46,6 +54,7 @@ public class OrderItem
private BigDecimal total;
@Column(name = "DESCRIPTION", length = Constants.LEN_DESCRIPTION)
@Field(index = Index.YES, analyze = Analyze.YES)
private String description;
@ManyToOne(fetch = FetchType.EAGER)
@@ -12,11 +12,16 @@ import javax.persistence.FetchType;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
@Entity
@Table(name = "REQUIREMENT")
@Indexed
public class Requirement extends RequirementBase
{
@OneToMany(fetch = FetchType.LAZY, mappedBy = "requirement", cascade = CascadeType.ALL, orphanRemoval = true)
@IndexedEmbedded
private List<RequirementItem> items;
@Column(name = "DELIVERYDATE")
@@ -19,8 +19,13 @@ import javax.persistence.OrderBy;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
@MappedSuperclass
@Indexed
public class RequirementBase extends BaseData implements FilterableRequirement {
@ManyToOne(fetch = FetchType.LAZY)
@@ -31,10 +36,12 @@ public class RequirementBase extends BaseData implements FilterableRequirement {
@OrderBy("CENTRE, WORDER")
private List<Workflow> workflow;
@Column(name = "NUMSER", unique = true)
@Field(index = Index.YES, analyze = Analyze.YES)
private String numser;
@Column(name = "REQ_DATE")
private Date reqDate;
@Column(name = "DESCRIPTION", length = Constants.LEN_DESCRIPTION)
@Field(index = Index.YES, analyze = Analyze.YES)
private String description;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "CENTRE_ID")
@@ -14,8 +14,15 @@ import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
@Entity
@Table(name = "REQUIREMENT_ITEMS")
@Indexed
public class RequirementItem
{
@Id
@@ -35,9 +42,11 @@ public class RequirementItem
private String code;
@Column(name = "NAME")
@Field(index = Index.YES, analyze = Analyze.YES)
private String name;
@Column(name = "TEXTITEM")
@Field(index = Index.YES, analyze = Analyze.YES)
private String textItem;
@Column(name = "QUANTITY", precision=15, scale=4)
@@ -53,6 +62,7 @@ public class RequirementItem
private BigDecimal total;
@Column(name = "DESCRIPTION", length = Constants.LEN_DESCRIPTION)
@Field(index = Index.YES, analyze = Analyze.YES)
private String description;
@Column(name = "DELIVERED")
@@ -14,6 +14,8 @@ public class SettingsData {
private MailMessage newReqTemplate;
private MailMessage authReqTemplate;
private MailMessage confReqTemplate;
private MailMessage confReqTripPassenger;
private MailMessage reqPassenger;
private Address mainAddress;
private List<Address> shippingAddrs;
private String bankName;
@@ -22,11 +24,14 @@ public class SettingsData {
private List<Vehicle> vehicles;
private Map<Integer, BigDecimal[]> refunds;
private String stampFile;
private String logoFile;
public SettingsData() {
newReqTemplate = new MailMessage();
authReqTemplate = new MailMessage();
confReqTemplate = new MailMessage();
confReqTripPassenger = new MailMessage();
reqPassenger = new MailMessage();
mainAddress = new Address();
shippingAddrs = new ArrayList<Address>();
vehicles = new ArrayList<Vehicle>();
@@ -140,4 +145,29 @@ public class SettingsData {
this.stampFile = stampFile;
}
public String getLogoFile()
{
return logoFile;
}
public void setLogoFile(String logoFile)
{
this.logoFile = logoFile;
}
public MailMessage getConfReqTripPassenger() {
return confReqTripPassenger;
}
public void setConfReqTripPassenger(MailMessage confReqTripPassenger) {
this.confReqTripPassenger = confReqTripPassenger;
}
public MailMessage getReqPassenger() {
return reqPassenger;
}
public void setReqPassenger(MailMessage reqPassenger) {
this.reqPassenger = reqPassenger;
}
}
@@ -0,0 +1,114 @@
package info.bukova.isspst.data;
import info.bukova.isspst.Constants;
import info.bukova.isspst.Module;
import info.bukova.isspst.StringUtils;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.IndexedEmbedded;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "SIGNED_DOCUMENTS")
public class SignedDocument extends BaseData {
@Column(name = "MODULE_NAME", length = Constants.LEN_TEXT)
private String moduleName;
@Column(name = "RECORD_ID")
private int recordId;
@Column(name = "NUMSER", length = Constants.LEN_TEXT)
private String numser;
@Column(name = "DESCRIPTION", length = Constants.LEN_DESCRIPTION)
private String description;
@Column(name = "SIGN_DATE")
private Date signDate;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "signedDocument", orphanRemoval = true)
@LazyCollection(LazyCollectionOption.TRUE)
@IndexedEmbedded
private List<SignedDocumentItem> items;
public String getModuleName() {
return moduleName;
}
public void setModuleName(String moduleName) {
this.moduleName = moduleName;
}
public int getRecordId() {
return recordId;
}
public void setRecordId(int recordId) {
this.recordId = recordId;
}
public String getNumser() {
return numser;
}
public void setNumser(String numser) {
this.numser = numser;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getSignDate() {
return signDate;
}
public void setSignDate(Date signDate) {
this.signDate = signDate;
}
public String getAgendaName() {
if (StringUtils.isNullOrEmpty(this.moduleName)) {
return "";
}
for (Module m : Constants.MODULES) {
if (this.moduleName.equals(m.getId())) {
return m.getName();
}
}
return "";
}
public List<SignedDocumentItem> getItems() {
return items;
}
public void setItems(List<SignedDocumentItem> items) {
this.items = items;
}
public void addItem(SignedDocumentItem item) {
if (items == null) {
items = new ArrayList<SignedDocumentItem>();
}
item.setSignedDocument(this);
this.items.add(item);
}
}
@@ -0,0 +1,88 @@
package info.bukova.isspst.data;
import info.bukova.isspst.Constants;
import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.reporting.ReportMapping;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "SIGNED_DOCUMENTS_ITEMS")
public class SignedDocumentItem {
@Id
@Column(name = "ID")
@GeneratedValue
private int id;
@Column(name = "REPORT_ID")
private long reportId;
@Column(name = "REPORT_NAME", length = Constants.LEN_TEXT)
private String reportName;
@Column(name = "FILENAME", length = Constants.LEN_TEXT)
private String fileName;
@ManyToOne
@JoinColumn(name = "SIGNED_DOCUMENT_ID")
private SignedDocument signedDocument;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public long getReportId() {
return reportId;
}
public void setReportId(long reportId) {
this.reportId = reportId;
}
public String getReportName() {
return reportName;
}
public void setReportName(String reportName) {
this.reportName = reportName;
}
public String getActualReportName() {
for (ReportMapping rm : Constants.REPORTS) {
Report rep = rm.getReport();
if (this.reportId == rep.getReportId()) {
return rep.getName();
}
}
return reportName;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public SignedDocument getSignedDocument() {
return signedDocument;
}
public void setSignedDocument(SignedDocument signedDocument) {
this.signedDocument = signedDocument;
}
}
@@ -1,9 +1,14 @@
package info.bukova.isspst.data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.bukova.isspst.Constants;
import info.bukova.isspst.storage.EntityWithAttachment;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -13,13 +18,15 @@ import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Entity
@Table(name = "TRIP_BILL")
public class TripBill extends BaseData {
@Indexed
public class TripBill extends BaseData implements EntityWithAttachment {
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "REQUIREMENT_ID")
@@ -28,6 +35,11 @@ public class TripBill extends BaseData {
private Date resultMessageDate;
@Column(name = "SIGN_DATE")
private Date signDate;
@Column(name = "RESULT_MESSAGE", length = Constants.LEN_RESULT_MESSAGE)
@Field(index = Index.YES, analyze = Analyze.YES)
private String resultMessage;
@Column(name = "FREE_MEALS")
private boolean freeMeals;
@Column(name = "FREE_HOUSING")
@@ -44,9 +56,23 @@ public class TripBill extends BaseData {
private BigDecimal downPayment;
@Column(name = "TOTAL", precision = 15, scale = 4)
private BigDecimal total;
@OneToMany(cascade = CascadeType.ALL)
@LazyCollection(LazyCollectionOption.TRUE)
@IndexedEmbedded
private List<FileMetainfo> attachedFiles;
@OneToOne(fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "APPROVAL_ID")
private TripBillApproval approval;
@Column(name = "SAVED")
private Boolean saved; // Nastaveno na true, pokud uživatel udělá změnu- nepřenáší se pak částky od žadatele
@Column(name = "PAID")
private Boolean paid;
@Column(name = "PAID_DATE")
private Date paidDate;
public TripBill() {
billItems = new ArrayList<TripBillItem>();
attachedFiles = new ArrayList<FileMetainfo>();
}
public TripRequirement getRequirement() {
@@ -73,6 +99,16 @@ public class TripBill extends BaseData {
this.signDate = signDate;
}
public String getResultMessage()
{
return resultMessage;
}
public void setResultMessage(String resultMessage)
{
this.resultMessage = resultMessage;
}
public boolean isFreeMeals() {
return freeMeals;
}
@@ -121,4 +157,53 @@ public class TripBill extends BaseData {
this.total = total;
}
public List<FileMetainfo> getAttachedFiles() {
return attachedFiles;
}
@Override
public void addAttachment(FileMetainfo metaInfo) {
attachedFiles.add(metaInfo);
}
@Override
public void removeAttachment(FileMetainfo metainfo) {
attachedFiles.remove(metainfo);
}
public void setAttachedFiles(List<FileMetainfo> attachedFiles) {
this.attachedFiles = attachedFiles;
}
public TripBillApproval getApproval() {
return approval;
}
public void setApproval(TripBillApproval approval) {
this.approval = approval;
}
public Boolean getSaved() {
return saved;
}
public void setSaved(Boolean saved) {
this.saved = saved;
}
public Boolean getPaid() {
return paid;
}
public void setPaid(Boolean paid) {
this.paid = paid;
}
public Date getPaidDate() {
return paidDate;
}
public void setPaidDate(Date paidDate) {
this.paidDate = paidDate;
}
}
@@ -0,0 +1,44 @@
package info.bukova.isspst.data;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
/**
* @author Pepa Rokos
*/
@Entity
@Table(name = "TRIP_BILL_APPROVAL")
public class TripBillApproval extends RequirementBase {
@OneToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "TRIPBILL_ID")
private TripBill bill;
@Override
public String getNumser() {
if (bill == null) {
return "";
}
TripRequirement tr = bill.getRequirement();
if (tr == null) {
return "";
}
return tr.getNumser();
}
public TripBill getBill() {
return bill;
}
public void setBill(TripBill bill) {
this.bill = bill;
}
}
@@ -2,15 +2,14 @@ package info.bukova.isspst.data;
import info.bukova.isspst.Constants;
import java.math.BigDecimal;
import java.util.Date;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.math.BigDecimal;
import java.util.Date;
@Entity
@Table(name = "TRIP_BILL_ITEMS")
@@ -65,6 +64,35 @@ public class TripBillItem extends BaseData {
@Column(name = "ADJUSTED_TOTAL", precision = 15, scale = 4)
private BigDecimal adjustedTotal;
public TripBillItem() {
}
public TripBillItem(TripBillItem src) {
date = src.getDate();
to = src.getTo();
back = src.getBack();
toDeparture = src.getToDeparture();
toArrival = src.getToArrival();
backDeparture = src.getBackDeparture();
backArrival = src.getBackArrival();
toVehicle = src.getToVehicle();
backVehicle = src.getBackVehicle();
beginWork = src.getBeginWork();
endWork = src.getEndWork();
freeMealsCount = src.getFreeMealsCount();
distance = src.getDistance();
fuelConsumption = src.getFuelConsumption();
distanceAmount = src.getDistanceAmount();
fuelAmount = src.getFuelAmount();
carefare = src.getCarefare();
housing = src.getHousing();
meals = src.getMeals();
otherExpenses = src.getOtherExpenses();
total = src.getTotal();
adjustedTotal = src.getAdjustedTotal();
}
public Date getDate() {
return date;
}
@@ -1,28 +1,40 @@
package info.bukova.isspst.data;
import info.bukova.isspst.storage.EntityWithAttachment;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.IndexedEmbedded;
@Entity
@Table(name = "TRIPREQUIREMENT")
public class TripRequirement extends RequirementBase {
@Indexed
public class TripRequirement extends RequirementBase implements EntityWithAttachment {
@Column(name = "TRIP_FROM")
@Field(index = Index.YES, analyze = Analyze.YES)
private String from;
@Column(name = "TRIP_TO")
@Field(index = Index.YES, analyze = Analyze.YES)
private String to;
@Column(name = "TRIP_DATE")
private Date tripDate;
@@ -34,16 +46,28 @@ public class TripRequirement extends RequirementBase {
@LazyCollection(LazyCollectionOption.TRUE)
@JoinTable(name="TRIPREQUIREMENT_PASSANGER", joinColumns={@JoinColumn(name="TRIPREQUIREMENT_ID")}, inverseJoinColumns={@JoinColumn(name="USER_ID")})
private List<User> passengers;
@Column(name = "FOREIGN_PERSONS")
@Field(index = Index.YES, analyze = Analyze.YES)
private String foreignPersons;
@Embedded
private Vehicle vehicle;
@Column(name = "REQUIRE_DOWN_PAYMENT")
private Boolean requireDownPayment;
@Column(name = "DOWN_PAYMENT", precision = 15, scale = 4)
private BigDecimal downPayment;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@LazyCollection(LazyCollectionOption.TRUE)
@IndexedEmbedded
private List<FileMetainfo> attachedFiles;
@Column(name = "BILL_FOR_PASSENGERS")
private Boolean billForPassengers;
public TripRequirement() {
this.setOwnedBy(new User());
passengers = new ArrayList<User>();
attachedFiles = new ArrayList<FileMetainfo>();
}
public String getFrom() {
@@ -94,6 +118,16 @@ public class TripRequirement extends RequirementBase {
this.passengers = passengers;
}
public String getForeignPersons()
{
return foreignPersons;
}
public void setForeignPersons(String foreignPersons)
{
this.foreignPersons = foreignPersons;
}
public Vehicle getVehicle() {
return vehicle;
}
@@ -118,4 +152,30 @@ public class TripRequirement extends RequirementBase {
this.downPayment = downPayment;
}
@Override
public List<FileMetainfo> getAttachedFiles() {
return attachedFiles;
}
public void setAttachedFiles(List<FileMetainfo> attachedFiles) {
this.attachedFiles = attachedFiles;
}
@Override
public void addAttachment(FileMetainfo metaInfo) {
attachedFiles.add(metaInfo);
}
@Override
public void removeAttachment(FileMetainfo metainfo) {
attachedFiles.remove(metainfo);
}
public Boolean getBillForPassengers() {
return billForPassengers;
}
public void setBillForPassengers(Boolean billForPassengers) {
this.billForPassengers = billForPassengers;
}
}
@@ -14,10 +14,15 @@ import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import org.hibernate.search.annotations.Analyze;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.springframework.security.core.userdetails.UserDetails;
@Entity
@Table(name="USER")
@Indexed
public class User extends Member implements UserDetails, DataModel {
/**
@@ -32,8 +37,10 @@ public class User extends Member implements UserDetails, DataModel {
@Column(name="ENABLED")
private boolean enabled;
@Column(name="FIRST_NAME")
@Field(index = Index.YES, analyze = Analyze.YES)
private String firstName;
@Column(name="LAST_NAME")
@Field(index = Index.YES, analyze = Analyze.YES)
private String lastName;
@Column(name="PERSONAL_NUMBER")
private String personalNumber;
@@ -1,5 +1,10 @@
package info.bukova.isspst.data;
import info.bukova.isspst.StringUtils;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Embeddable;
@@ -47,4 +52,22 @@ public class UsersAddress {
this.city = city;
}
public String toString() {
List<String> list = new ArrayList<String>();
list.add(this.street);
list.add(this.houseNumber);
final String s1 = StringUtils.joinNotEmpty(list, " ");
list.clear();
list.add(this.zipCode);
list.add(this.city);
final String s2 = StringUtils.joinNotEmpty(list, " ");
list.clear();
list.add(s1);
list.add(s2);
final String s = StringUtils.joinNotEmpty(list, ", ");
return s;
}
}
@@ -1,15 +1,14 @@
package info.bukova.isspst.data;
import java.math.BigDecimal;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;
import java.math.BigDecimal;
@Entity
@Table(name = "WORKFLOW")
@@ -24,7 +23,9 @@ public class Workflow extends BaseData {
@Column(name = "WORDER")
private Integer wOrder;
@Column(name = "WLIMIT", precision=15, scale=4)
private BigDecimal limit;
private BigDecimal limit;
@Column(name = "SIGNATURE")
private Boolean signature;
public Boolean getCentre() {
return centre;
@@ -68,4 +69,11 @@ public class Workflow extends BaseData {
this.limit = limit;
}
public Boolean getSignature() {
return signature;
}
public void setSignature(Boolean signature) {
this.signature = signature;
}
}
@@ -0,0 +1,57 @@
package info.bukova.isspst.filters;
import info.bukova.isspst.StringUtils;
import java.util.ArrayList;
import java.util.List;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listitem;
@SuppressWarnings("serial")
public class BooleanFilterListbox extends Listbox
{
class TristateBooleanListItem extends TristateBoolean
{
public TristateBooleanListItem(String text, int value)
{
this.setText(text);
this.setValue(value);
}
private String text;
public String getText()
{
return text;
}
public void setText(String text)
{
this.text = text;
}
}
public BooleanFilterListbox()
{
super();
List<TristateBooleanListItem> list = new ArrayList<TristateBooleanListItem>();
list.add(new TristateBooleanListItem(StringUtils.localize("LabelAll"), TristateBoolean.NULL));
list.add(new TristateBooleanListItem(StringUtils.localize("LabelNo"), TristateBoolean.FALSE));
list.add(new TristateBooleanListItem(StringUtils.localize("LabelYes"), TristateBoolean.TRUE));
for (int i = 0; i < list.size(); i++)
{
TristateBooleanListItem triStateItem = (TristateBooleanListItem) list.get(i);
this.appendItem(triStateItem.getText(), "");
Listitem item = this.getItemAtIndex(i);
item.setValue((TristateBoolean) triStateItem);
}
this.setSelectedIndex(0);
// this.setHflex("1");
this.setMold("select");
}
}
@@ -1,5 +1,6 @@
package info.bukova.isspst.filters;
import info.bukova.isspst.BooleanUtils;
import info.bukova.isspst.StringUtils;
import info.bukova.isspst.data.JoinedItem;
import info.bukova.isspst.data.MUnitEmb;
@@ -42,6 +43,7 @@ public class JoinedItemFilter implements Filter<JoinedItem>
@Override
public boolean matchesSafely(JoinedItem item)
{
boolean foundItemMaterial = BooleanUtils.isEqualFilterByBoolean(item.isItemMaterialReal(), condition.getItemMaterial());
boolean foundCode = StringUtils.isEqualForFilter(item.getCode(), condition.getCode());
boolean foundName = StringUtils.isEqualForFilter(item.getName(), condition.getName());
boolean foundTextItem = StringUtils.isEqualForFilter(item.getTextItem(), condition.getTextItem());
@@ -56,7 +58,18 @@ public class JoinedItemFilter implements Filter<JoinedItem>
boolean foundCenter = Workgroup.isEqualByWorkgroupForFilter(item.getCentre(), condition.getCentre());
boolean foundOwner = User.isEqualByUserForFilter(item.getOwnedBy(), condition.getOwnedBy());
boolean foundDescription = StringUtils.isEqualForFilter(item.getDescription(), condition.getDescription());
return (foundCode && foundName && foundTextItem && foundDescription && foundQuantity && foundUnitPrice && foundMUnit && foundTotal && foundWorkgroup && foundCenter && foundOwner && foundDescription);
return (foundItemMaterial
&& foundCode
&& foundName
&& foundTextItem
&& foundDescription
&& foundQuantity
&& foundUnitPrice
&& foundMUnit
&& foundTotal
&& foundWorkgroup
&& foundCenter
&& foundOwner && foundDescription);
}
@Factory
@@ -47,7 +47,7 @@ public class RequirementFilter implements Filter<Requirement>
boolean foundDescription = StringUtils.isEqualForFilter(item.getDescription(), condition.getDescription());
boolean foundDeliveryDate = DateTimeUtils.isEqualByDateForFilter(item.getDeliveryDate(), condition.getDeliveryDate());
boolean foundUser = User.isEqualByUserForFilter(item.getOwnedBy(), condition.getOwnedBy());
boolean foundProject = BooleanUtils.isEqualByBoolean(item.getProject(), condition.getProject());
boolean foundProject = BooleanUtils.isEqualByBooleanValue(item.getProject(), condition.getProject());
return (foundNumser && foundReqDate && foundCenter && foundDescription && foundDeliveryDate && foundUser && foundProject);
}
@@ -0,0 +1,64 @@
package info.bukova.isspst.filters;
import info.bukova.isspst.DateTimeUtils;
import info.bukova.isspst.StringUtils;
import info.bukova.isspst.data.SignedDocument;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
public class SignedDocumentFilter implements Filter<SignedDocument>
{
private SignedDocument condition;
public SignedDocumentFilter(SignedDocument cond)
{
this.condition = cond;
}
private static class SignedDocumentMatcher extends TypeSafeMatcher<SignedDocument>
{
private SignedDocument condition;
public SignedDocumentMatcher(SignedDocument cond)
{
this.condition = cond;
}
@Override
public void describeTo(Description desc)
{
desc.appendText("SignedDocument matches");
}
@Override
public boolean matchesSafely(SignedDocument item)
{
boolean foundAgendaName = StringUtils.isEqualForFilter(item.getAgendaName(), condition.getAgendaName());
boolean foundNumSer = StringUtils.isEqualForFilter(item.getNumser(), condition.getNumser());
boolean foundDescription = StringUtils.isEqualForFilter(item.getDescription(), condition.getDescription());
boolean foundSignDate = DateTimeUtils.isEqualByDateForFilter(item.getSignDate(), condition.getSignDate());
return (foundAgendaName && foundNumSer && foundDescription && foundSignDate);
}
@Factory
public static Matcher<SignedDocument> matchBuilding(SignedDocument item)
{
return new SignedDocumentMatcher(item);
}
}
@Override
public SignedDocumentMatcher matcher()
{
return new SignedDocumentMatcher(condition);
}
@Override
public String queryString()
{
return "";
}
}
@@ -0,0 +1,78 @@
package info.bukova.isspst.filters;
import info.bukova.isspst.BooleanUtils;
import info.bukova.isspst.DateTimeUtils;
import info.bukova.isspst.StringUtils;
import info.bukova.isspst.data.TripBillApproval;
import info.bukova.isspst.data.User;
import org.hamcrest.Description;
import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
public class TripBillApprovalFilter implements Filter<TripBillApproval>
{
private TripBillApproval condition;
public TripBillApprovalFilter(TripBillApproval cond)
{
this.condition = cond;
}
private static class TripBillApprovalMatcher extends TypeSafeMatcher<TripBillApproval>
{
private TripBillApproval condition;
public TripBillApprovalMatcher(TripBillApproval cond)
{
this.condition = cond;
}
@Override
public void describeTo(Description desc)
{
desc.appendText("requirement matches");
}
@Override
public boolean matchesSafely(TripBillApproval item)
{
if (item.getBill() == null) {
return false;
}
boolean foundNumser = StringUtils.isEqualForFilter(item.getNumser(), condition.getNumser());
boolean foundReqDate = DateTimeUtils.isEqualByDateForFilter(item.getBill().getRequirement().getReqDate(), condition.getBill().getRequirement().getReqDate());
boolean foundDescription = StringUtils.isEqualForFilter(item.getDescription(), condition.getDescription());
boolean foundFrom = StringUtils.isEqualForFilter(item.getBill().getRequirement().getFrom(), condition.getBill().getRequirement().getFrom());
boolean foundTo = StringUtils.isEqualForFilter(item.getBill().getRequirement().getTo(), condition.getBill().getRequirement().getTo());
boolean foundWorkgroup = (condition.getWorkgroup() == null ||(item.getWorkgroup() != null && item.getWorkgroup().equals(condition.getWorkgroup())));
boolean foundCentre = (condition.getCentre() == null || (item.getCentre() != null && item.getCentre().equals(condition.getCentre())));
boolean foundOwner = User.isEqualByUserForFilter(item.getBill().getOwnedBy(), condition.getBill().getOwnedBy());
boolean foundPaid = BooleanUtils.isEqualByBooleanValue(item.getBill().getPaid(), condition.getBill().getPaid());
boolean foundPaidDate = DateTimeUtils.isEqualByDateForFilter(item.getBill().getPaidDate(), condition.getBill().getPaidDate());
return foundNumser && foundReqDate && foundDescription && foundFrom && foundTo && foundWorkgroup && foundCentre && foundOwner && foundPaid && foundPaidDate;
}
@Factory
public static Matcher<TripBillApproval> matchTripRequirement(TripBillApproval building)
{
return new TripBillApprovalMatcher(building);
}
}
@Override
public TripBillApprovalMatcher matcher()
{
return new TripBillApprovalMatcher(condition);
}
@Override
public String queryString()
{
return "";
}
}
@@ -0,0 +1,87 @@
package info.bukova.isspst.filters;
import org.jfree.util.Log;
public class TristateBoolean
{
private static final String TAG = TristateBoolean.class.getSimpleName();
public static final int NULL = -1;
public static final int FALSE = 0;
public static final int TRUE = 1;
public static final int getValidValue(final int value)
{
if ((value != TristateBoolean.NULL) && (value != TristateBoolean.FALSE) && (value != TristateBoolean.TRUE))
{
Log.warn(TAG + "\nBad tristate boolean value.");
return TristateBoolean.NULL;
}
return value;
}
public TristateBoolean()
{
this.setValue(TristateBoolean.NULL);
}
public TristateBoolean(boolean value)
{
this.setValue(value ? TristateBoolean.TRUE : TristateBoolean.FALSE);
}
public TristateBoolean(int value)
{
this.setValue(value);
}
protected int value;
public int getValue()
{
return value;
}
public void setValue(int value)
{
this.value = TristateBoolean.getValidValue(value);
}
public Boolean getBoolean()
{
switch (this.value)
{
case TristateBoolean.FALSE:
return new Boolean(false);
case TristateBoolean.TRUE:
return new Boolean(true);
default:
return null;
}
}
@Override
public boolean equals(Object obj)
{
if (obj != null)
{
if (obj instanceof TristateBoolean)
{
TristateBoolean item = (TristateBoolean) obj;
int thisValue = this.getValue();
int itemValue = item.getValue();
return (thisValue == itemValue);
}
}
return false;
}
public boolean equals(int value)
{
return (this.getValue() == value);
}
}
@@ -1,5 +1,6 @@
package info.bukova.isspst.mail;
import info.bukova.isspst.Constants;
import info.bukova.isspst.EntityUrlResolver;
import info.bukova.isspst.UrlResolverHolder;
@@ -57,7 +58,7 @@ public class EntityMessageBuilder implements MessageBuilder {
for (String p : properties) {
try {
if (p.equals("-url-")) {
if (p.equals(Constants.MAIL_URL_KEYWORD)) {
ret = ret.replaceAll("\\[" + p + "\\]", getUrl(data));
} else {
ret = ret.replaceAll("\\[" + p + "\\]", BeanUtils.getProperty(data, p));
@@ -1,8 +1,7 @@
package info.bukova.isspst.reporting;
import java.util.HashMap;
import java.util.Map;
import com.mysql.jdbc.StringUtils;
import info.bukova.isspst.data.Address;
import info.bukova.isspst.data.AuthItem;
import info.bukova.isspst.data.Order;
import info.bukova.isspst.data.TripBill;
@@ -10,11 +9,14 @@ import info.bukova.isspst.data.User;
import info.bukova.isspst.data.UserSettingsData;
import info.bukova.isspst.services.requirement.TripRequirementService;
import info.bukova.isspst.services.settings.GlobalSettingsService;
import info.bukova.isspst.services.tripbill.TripBillApprovalService;
import info.bukova.isspst.services.users.UserService;
import info.bukova.isspst.storage.FileStorage;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.HashMap;
import java.util.Map;
public class ParamFiller {
@Autowired
@@ -27,6 +29,8 @@ public class ParamFiller {
private TripRequirementService tripReqService;
@Autowired
private GlobalSettingsService settingService;
@Autowired
private TripBillApprovalService tripBillApprovalService;
public void fill() {
if (definition.getDataSet() == null || definition.getDataSet().isEmpty()) {
@@ -45,6 +49,7 @@ public class ParamFiller {
if ((definition.getDataSet().get(0) instanceof TripBill)
&& definition.getReport().isSingleRecord()) {
if (userService.getUserSettings().getSignatureFile() != null
&& !userService.getUserSettings().getSignatureFile().isEmpty()) {
definition.setParam("P_USER_SIGNATURE", storage.serverPath(userService.getUserSettings().getSignatureFile()));
@@ -52,18 +57,32 @@ public class ParamFiller {
TripBill tb = (TripBill)definition.getDataSet().get(0);
tripReqService.loadAuthItems(tb.getRequirement());
AuthItem lastAuth = tb.getRequirement().getAuthorization().get(tb.getRequirement().getAuthorization().size() - 1);
definition.setParam("P_APPROVE_DATE", lastAuth.getAuthDate());
User u = lastAuth.getApprover();
UserSettingsData approverSettings = userService.getUserSettings(u);
if (approverSettings != null
&& approverSettings.getSignatureFile() != null
&& !approverSettings.getSignatureFile().isEmpty()) {
definition.setParam("P_APPROVER_SIGNATURE", storage.serverPath(approverSettings.getSignatureFile()));
if (tb.getApproval() != null) {
tripBillApprovalService.loadAuthItems(tb.getApproval());
}
if (tb.getApproval() != null && tb.getApproval().getAuthorization() != null && !tb.getApproval().getAuthorization().isEmpty()) {
AuthItem lastButOneAuth = tb.getApproval().getAuthorization().get(0);
definition.setParam("P_PREV_APPROVE_DATE", lastButOneAuth.getAuthDate());
User lastButOneUser = lastButOneAuth.getApprover();
UserSettingsData prevApproverSettings = userService.getUserSettings(lastButOneUser);
if (prevApproverSettings != null && !StringUtils.isNullOrEmpty(prevApproverSettings.getSignatureFile())) {
definition.setParam("P_PREV_APPROVER_SIGNATURE", storage.serverPath(prevApproverSettings.getSignatureFile()));
}
AuthItem lastAuth = tb.getApproval().getAuthorization().get(tb.getApproval().getAuthorization().size() - 1);
definition.setParam("P_APPROVE_DATE", lastAuth.getAuthDate());
User u = lastAuth.getApprover();
UserSettingsData approverSettings = userService.getUserSettings(u);
if (approverSettings != null && !StringUtils.isNullOrEmpty(approverSettings.getSignatureFile())) {
definition.setParam("P_APPROVER_SIGNATURE", storage.serverPath(approverSettings.getSignatureFile()));
}
}
}
@@ -74,6 +93,15 @@ public class ParamFiller {
definition.setParam("P_STAMP", storage.serverPath(settingService.getSettings().getStampFile()));
}
}
definition.setParam("P_LOGO", storage.serverPath(settingService.getSettings().getLogoFile()));
Address mainAddress = settingService.getSettings().getMainAddress();
if (mainAddress != null) {
String addr = (StringUtils.isNullOrEmpty(mainAddress.getCompany()) ? "" : mainAddress.getCompany());
definition.setParam("P_MAIN_ADDRESS", addr);
}
}
}
@@ -1,18 +1,21 @@
package info.bukova.isspst.reporting;
import java.io.File;
import javax.servlet.ServletContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import info.bukova.isspst.SpringUtils;
import info.bukova.isspst.data.DataModel;
import info.bukova.isspst.data.SignedDocumentItem;
import info.bukova.isspst.services.signeddocs.SignedDocumentService;
import info.bukova.isspst.storage.ReportFileStorage;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JasperRunManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.util.JRProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletContext;
import java.io.File;
@SuppressWarnings("deprecation")
public class PredefinedGenerator implements Generator {
@@ -20,7 +23,7 @@ public class PredefinedGenerator implements Generator {
private ReportDefinition definition;
private ServletContext ctx;
private final static Logger logger = LoggerFactory.getLogger(PredefinedGenerator.class);
public PredefinedGenerator(ReportDefinition definition, ServletContext ctx) {
this.definition = definition;
this.ctx = ctx;
@@ -29,7 +32,12 @@ public class PredefinedGenerator implements Generator {
@Override
public byte[] generate() {
byte[] bytes = null;
SignedDocumentItem signedItem = getSignedDocument();
if (signedItem != null) {
return fromStorage(signedItem);
}
try {
JasperReport report = (JasperReport) JRLoader.loadObject(getReportFile());
JRProperties.setProperty("net.sf.jasperreports.default.pdf.encoding", "Cp1250");
@@ -43,6 +51,18 @@ public class PredefinedGenerator implements Generator {
return bytes;
}
private byte[] fromStorage(SignedDocumentItem sdItem) {
ReportFileStorage reportStorage = SpringUtils.getBean(ReportFileStorage.class, ctx);
return reportStorage.fileData(sdItem);
}
private SignedDocumentItem getSignedDocument() {
SignedDocumentService sdService = SpringUtils.getBean(SignedDocumentService.class, ctx);
SignedDocumentItem sdItem = sdService.getItem((DataModel) definition.getDataSet().get(0), definition.getReport().getReportId());
return sdItem;
}
protected File getReportFile() {
return new File(ctx.getRealPath("WEB-INF/reports") + "/" + definition.getReport().getJasperFile() + ".jasper");
@@ -4,48 +4,77 @@ package info.bukova.isspst.reporting;
public class Report {
private ReportType type;
private long reportId;
private boolean signable;
private String name;
private String jasperFile;
private boolean hasSettings;
private boolean singleRecord;
private boolean hasCondition;
public Report() {
this.reportId = 0;
this.signable = false;
hasSettings = false;
singleRecord = false;
hasCondition = false;
}
/**
* @param reportId
* @param signable
* @param name
* @param jasperFile
*/
public Report(String name, String jasperFile) {
public Report(long reportId, boolean signable, String name, String jasperFile) {
this();
this.type = ReportType.DEFINED;
this.reportId = reportId;
this.signable = signable;
this.name = name;
this.jasperFile = jasperFile;
}
/**
* @param reportId
* @param signable
* @param name
* @param jasperFile
* @param hasSettings
*/
public Report(String name, String jasperFile, boolean hasSettings) {
this(name, jasperFile);
public Report(long reportId, boolean signable, String name, String jasperFile, boolean hasSettings) {
this(reportId, signable, name, jasperFile);
this.hasSettings = hasSettings;
}
/**
* @param reportId
* @param signable
* @param name
* @param jasperFile
* @param hasSettings
* @param singleRecord
*/
public Report(String name, String jasperFile, boolean hasSettings, boolean singleRecord) {
this(name, jasperFile, hasSettings);
public Report(long reportId, boolean signable, String name, String jasperFile, boolean hasSettings, boolean singleRecord) {
this(reportId, signable, name, jasperFile, hasSettings);
this.singleRecord = singleRecord;
}
/**
*
* @param reportId
* @param signable
* @param name
* @param jasperFile
* @param hasSettings
* @param singleRecord
* @param hasCondition
*/
public Report(long reportId, boolean signable, String name, String jasperFile, boolean hasSettings, boolean singleRecord, boolean hasCondition) {
this(reportId, signable, name, jasperFile, hasSettings, singleRecord);
this.hasCondition = hasCondition;
}
public ReportType getType() {
return type;
}
@@ -86,4 +115,27 @@ public class Report {
this.singleRecord = singleRecord;
}
public boolean isHasCondition() {
return hasCondition;
}
public void setHasCondition(boolean hasCondition) {
this.hasCondition = hasCondition;
}
public long getReportId() {
return reportId;
}
public void setReportId(long reportId) {
this.reportId = reportId;
}
public boolean isSignable() {
return signable;
}
public void setSignable(boolean signable) {
this.signable = signable;
}
}
@@ -1,17 +1,17 @@
package info.bukova.isspst.reporting;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import info.bukova.isspst.storage.ReportFileStorage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
@Controller
public class ReportController {
@@ -21,6 +21,8 @@ public class ReportController {
private GeneratorFactory factory;
@Autowired
private ParamFiller paramFiller;
@Autowired
private ReportFileStorage reportFileStorage;
private static final String ERROR_MESSAGE = "<html><body><b>Generator returned no data!</b><br/>%s</body></html>";
private final static Logger logger = LoggerFactory.getLogger(ReportController.class);
@@ -46,13 +48,20 @@ public class ReportController {
try {
os = response.getOutputStream();
if (reportDefinition.getReport() == null || reportDefinition.getDataSet() == null) {
if ((reportDefinition.getReport() == null || reportDefinition.getDataSet() == null) && reportDefinition.getSignedDocItem() == null) {
throw new ReportException("Definition is null");
}
paramFiller.fill();
Generator gen = factory.createGenerator(reportDefinition);
byte[] data = gen.generate();
byte[] data;
if (reportDefinition.getSignedDocItem() == null) {
paramFiller.fill();
Generator gen = factory.createGenerator(reportDefinition);
data = gen.generate();
} else {
data = reportFileStorage.fileData(reportDefinition.getSignedDocItem());
}
response.setContentType(contentType);
response.setContentLength(data.length);
@@ -1,5 +1,6 @@
package info.bukova.isspst.reporting;
import info.bukova.isspst.data.SignedDocumentItem;
import info.bukova.isspst.services.Service;
import java.io.Serializable;
@@ -20,6 +21,7 @@ public class ReportDefinition implements Serializable {
private List<String> fieldsToPrint;
private String reportTitle;
private Service<Object> service;
private SignedDocumentItem signedDocItem;
public ReportDefinition() {
params = new HashMap<String, Object>();
@@ -92,6 +94,7 @@ public class ReportDefinition implements Serializable {
reportTitle = "";
service = null;
params.clear();
signedDocItem = null;
}
public String getReportTitle() {
@@ -110,4 +113,11 @@ public class ReportDefinition implements Serializable {
this.service = service;
}
public SignedDocumentItem getSignedDocItem() {
return signedDocItem;
}
public void setSignedDocItem(SignedDocumentItem signedDocItem) {
this.signedDocItem = signedDocItem;
}
}
@@ -0,0 +1,68 @@
package info.bukova.isspst.reporting;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfFormField;
import com.lowagie.text.pdf.PdfName;
import net.sf.jasperreports.engine.JRGenericPrintElement;
import net.sf.jasperreports.engine.JRPropertiesMap;
import net.sf.jasperreports.engine.export.GenericElementHandler;
import net.sf.jasperreports.engine.export.GenericElementHandlerBundle;
import net.sf.jasperreports.engine.export.GenericElementPdfHandler;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterContext;
import net.sf.jasperreports.extensions.ExtensionsRegistry;
import net.sf.jasperreports.extensions.ExtensionsRegistryFactory;
import net.sf.jasperreports.extensions.SingletonExtensionRegistry;
/**
* @author Pepa Rokos
*/
public class SignaturePdfHandler implements GenericElementPdfHandler, GenericElementHandlerBundle, ExtensionsRegistryFactory {
@Override
public ExtensionsRegistry createRegistry(String registryId, JRPropertiesMap properties) {
return new SingletonExtensionRegistry<GenericElementHandlerBundle>(GenericElementHandlerBundle.class, this);
}
@Override
public void exportElement(JRPdfExporterContext exporterContext, JRGenericPrintElement element) {
//PdfFormField field = PdfFormField.createSignature(exporterContext.getPdfWriter());
PdfFormField field = PdfFormField.createTextField(exporterContext.getPdfWriter(), true, false, 255);
Object param = element.getParameterValue("index");
String index = param != null ? String.valueOf(param) : null;
if (index != null) {
field.setFieldName("signature-" + index);
} else {
field.setFieldName("signature");
}
field.put(PdfName.V, exporterContext.getPdfWriter().getPdfIndirectReference());
field.setFieldFlags(PdfFormField.FF_READ_ONLY);
field.setWidget(new Rectangle(element.getX(),
exporterContext.getExportedReport().getPageHeight() - element.getY(),
element.getX() + element.getWidth(),
exporterContext.getExportedReport().getPageHeight() - element.getY() - element.getHeight()), PdfName.HIGHLIGHT);
exporterContext.getPdfWriter().addAnnotation(field);
}
@Override
public boolean toExport(JRGenericPrintElement element) {
return true;
}
@Override
public String getNamespace() {
return "urn:sig:sig";
}
@Override
public GenericElementHandler getHandler(String elementName, String exporterKey) {
if (elementName.equals("signature") && exporterKey.equals(JRPdfExporter.PDF_EXPORTER_KEY)) {
return this;
}
return null;
}
}
@@ -24,14 +24,16 @@ public abstract class AbstractRequirementEvaluator extends AbstractModuleEvaluat
return false;
}
RequirementBase req = (RequirementBase) targetDomainObject;
if (permission.equals(Constants.PERM_EDIT_NEW)) {
return req.getState() == RequirementState.NEW;
}
if (permission.equals(Constants.PERM_DELETE_NEW)) {
return req.getState() == RequirementState.NEW;
if (targetDomainObject instanceof RequirementBase) {
RequirementBase req = (RequirementBase) targetDomainObject;
if (permission.equals(Constants.PERM_EDIT_NEW)) {
return req.getState() == RequirementState.NEW;
}
if (permission.equals(Constants.PERM_DELETE_NEW)) {
return req.getState() == RequirementState.NEW;
}
}
return true;
@@ -5,9 +5,6 @@ import info.bukova.isspst.data.User;
import info.bukova.isspst.services.users.LdapUserImporter;
import info.bukova.isspst.services.users.RoleService;
import info.bukova.isspst.services.users.UserService;
import java.util.Collection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.DirContextOperations;
@@ -15,6 +12,8 @@ import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator;
import java.util.Collection;
public class AuthPopulator implements LdapAuthoritiesPopulator {
private UserService userService;
@@ -30,7 +29,8 @@ public class AuthPopulator implements LdapAuthoritiesPopulator {
public Collection<? extends GrantedAuthority> getGrantedAuthorities(
DirContextOperations userData, String login) {
User user = null;
User user;
try {
user = (User) userService.loadUserByUsername(login);
} catch (UsernameNotFoundException e) {
@@ -1,7 +1,7 @@
package info.bukova.isspst.services;
import java.util.Date;
import info.bukova.isspst.data.OwnedDataModel;
import info.bukova.isspst.data.User;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Query;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -9,8 +9,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.transaction.annotation.Transactional;
import info.bukova.isspst.data.OwnedDataModel;
import info.bukova.isspst.data.User;
import java.util.Date;
public class AbstractOwnedService<T extends OwnedDataModel> extends AbstractService<T> {
@@ -32,6 +31,7 @@ public class AbstractOwnedService<T extends OwnedDataModel> extends AbstractServ
entity.setModifiedBy(getLoggedInUser());
entity.setModified(new Date());
dao.modify(entity);
maintainStorrage();
}
@Transactional
@@ -1,8 +1,7 @@
package info.bukova.isspst.services;
import static ch.lambdaj.Lambda.filter;
import info.bukova.isspst.Constants;
import info.bukova.isspst.Module;
import info.bukova.isspst.ModuleUtils;
import info.bukova.isspst.SessionData;
import info.bukova.isspst.dao.BaseDao;
import info.bukova.isspst.dao.QueryDao;
@@ -11,23 +10,26 @@ import info.bukova.isspst.data.NumberSeries;
import info.bukova.isspst.filters.Filter;
import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.services.numberseries.NumberSeriesService;
import info.bukova.isspst.storage.DocumentFileStorage;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.GenericTypeResolver;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import org.hibernate.NonUniqueResultException;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import static ch.lambdaj.Lambda.filter;
public abstract class AbstractService<T extends DataModel> implements Service<T> {
@@ -37,9 +39,26 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
protected SessionData sessionData;
@Autowired
protected QueryDao queryDao;
private DocumentFileStorage documentFileStorage;
private NumberSeriesService numberSeriesService;
private Class<T> entityClass;
public AbstractService() {
entityClass = (Class<T>) GenericTypeResolver.resolveTypeArgument(getClass(), AbstractService.class);
}
@Override
public List<Class<?>> getEntityClasses() {
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(entityClass);
return classes;
}
public void setDocumentFileStorage(DocumentFileStorage storage) {
this.documentFileStorage = storage;
}
public NumberSeriesService getNumberSeriesService()
{
@@ -62,6 +81,12 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
public String getDeleteEntityPermission() {
return "";
}
protected void maintainStorrage() {
if (documentFileStorage != null) {
documentFileStorage.purge();
}
}
@Override
@PreAuthorize("hasPermission(this, 'PERM_ADD')")
@@ -77,6 +102,10 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
throw new IsspstException("DAO is null");
}
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
validate(entity);
entity.setCreated(new Date());
dao.add(entity);
@@ -90,9 +119,14 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
throw new IsspstException("DAO is null");
}
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
validate(entity);
entity.setModified(new Date());
dao.modify(entity);
maintainStorrage();
}
@Override
@@ -103,7 +137,13 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
throw new IsspstException("DAO is null");
}
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
dao.delete(entity);
maintainStorrage(); // poklidit přiložené soubory
}
@Override
@@ -141,6 +181,10 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
throw new IsspstException("DAO is null");
}
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
return dao.getById(id);
}
@@ -152,6 +196,10 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
throw new IsspstException("DAO is null");
}
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
return dao.getAll();
}
@@ -163,6 +211,10 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
throw new IsspstException("DAO is null");
}
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
return dao.execQuery(query);
}
@@ -175,6 +227,10 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
throw new IsspstException("DAO is null");
}
if (getModule() != null && !getModule().isActive()) {
throw new ModuleNotActiveException();
}
try {
Query q = dao.getQuery(query);
return (T) q.uniqueResult();
@@ -193,13 +249,7 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
@Override
public Module getModule() {
for (Module m : Constants.MODULES) {
if (Arrays.asList(this.getClass().getInterfaces()).contains(m.getServiceClass())) {
return m;
}
}
return null;
return ModuleUtils.getModule(this.getClass());
}
public List<Report> getReports() {
@@ -238,6 +288,10 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
@Override
@Transactional
public void loadLazyData(String group, T entity) {
if (entity == null) {
return;
}
Method[] methods = this.getClass().getMethods();
for (Method m : methods) {
@@ -260,4 +314,9 @@ public abstract class AbstractService<T extends DataModel> implements Service<T>
}
}
}
@Override
public boolean canPrintRecord(T entity) {
return true;
}
}
@@ -0,0 +1,14 @@
package info.bukova.isspst.services;
public class ModuleNotActiveException extends IsspstException {
/**
*
*/
private static final long serialVersionUID = -1219763294556500698L;
public ModuleNotActiveException() {
super("Module deactivated");
}
}
@@ -22,5 +22,7 @@ public interface Service<T> {
public List<T> filterList(List<T> sourceList, Filter<T> filter);
public Module getModule();
public List<Report> getReports();
public boolean canPrintRecord(T entity);
public List<Class<?>> getEntityClasses();
}
@@ -60,6 +60,9 @@ public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfo
}
}
// String source = UserCountUtils.encryptUserCount(1000);
// long users = UserCountUtils.decryptUserCount(source);
long dbVersion = this.getDbInfo().getVersion();
if (Constants.DB_VERSION > dbVersion)
@@ -71,29 +74,29 @@ public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfo
{
List<Str2Str> tables = new ArrayList<Str2Str>();
tables.add(new Str2Str("address", "DESCRIPTION"));
tables.add(new Str2Str("building", "DESCRIPTION"));
tables.add(new Str2Str("material", "DESCRIPTION"));
tables.add(new Str2Str("munit", "DESCRIPTION"));
tables.add(new Str2Str("orders", "DESCRIPTION"));
tables.add(new Str2Str("order_item", "DESCRIPTION"));
tables.add(new Str2Str("permission", "DESCRIPTION"));
tables.add(new Str2Str("requirement", "DESCRIPTION"));
tables.add(new Str2Str("requirementtype", "DESCRIPTION"));
tables.add(new Str2Str("requirement_items", "DESCRIPTION"));
tables.add(new Str2Str("role", "DESCRIPTION"));
tables.add(new Str2Str("service", "DESCRIPTION"));
tables.add(new Str2Str("triprequirement", "DESCRIPTION"));
tables.add(new Str2Str("ADDRESS", "DESCRIPTION"));
tables.add(new Str2Str("BUILDING", "DESCRIPTION"));
tables.add(new Str2Str("MATERIAL", "DESCRIPTION"));
tables.add(new Str2Str("MUNIT", "DESCRIPTION"));
tables.add(new Str2Str("ORDERS", "DESCRIPTION"));
tables.add(new Str2Str("ORDER_ITEM", "DESCRIPTION"));
tables.add(new Str2Str("PERMISSION", "DESCRIPTION"));
tables.add(new Str2Str("REQUIREMENT", "DESCRIPTION"));
tables.add(new Str2Str("REQUIREMENTTYPE", "DESCRIPTION"));
tables.add(new Str2Str("REQUIREMENT_ITEMS", "DESCRIPTION"));
tables.add(new Str2Str("ROLE", "DESCRIPTION"));
tables.add(new Str2Str("SERVICE", "DESCRIPTION"));
tables.add(new Str2Str("TRIPREQUIREMENT", "DESCRIPTION"));
tables.add(new Str2Str("material", "MUNIT_DESCRIPTION"));
tables.add(new Str2Str("orders", "INVOICE_DESCRIPTION"));
tables.add(new Str2Str("orders", "DELIVERY_DESCRIPTION"));
tables.add(new Str2Str("orders", "SUPPLIER_DESCRIPTION"));
tables.add(new Str2Str("order_item", "MUNIT_DESCRIPTION"));
tables.add(new Str2Str("requirement_items", "MUNIT_DESCRIPTION"));
tables.add(new Str2Str("triprequirement", "VEHICLE_DESCRIPTION"));
tables.add(new Str2Str("trip_bill_items", "BACK_VEHICLE_DESCRIPTION"));
tables.add(new Str2Str("trip_bill_items", "VEHICLE_DESCRIPTION"));
tables.add(new Str2Str("MATERIAL", "MUNIT_DESCRIPTION"));
tables.add(new Str2Str("ORDERS", "INVOICE_DESCRIPTION"));
tables.add(new Str2Str("ORDERS", "DELIVERY_DESCRIPTION"));
tables.add(new Str2Str("ORDERS", "SUPPLIER_DESCRIPTION"));
tables.add(new Str2Str("ORDER_ITEM", "MUNIT_DESCRIPTION"));
tables.add(new Str2Str("REQUIREMENT_ITEMS", "MUNIT_DESCRIPTION"));
tables.add(new Str2Str("TRIPREQUIREMENT", "VEHICLE_DESCRIPTION"));
tables.add(new Str2Str("TRIP_BILL_ITEMS", "BACK_VEHICLE_DESCRIPTION"));
tables.add(new Str2Str("TRIP_BILL_ITEMS", "VEHICLE_DESCRIPTION"));
for (Str2Str item : tables)
{
@@ -107,9 +110,9 @@ public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfo
{
List<String> tables = new ArrayList<String>();
tables.add("material");
tables.add("order_item");
tables.add("requirement_items");
tables.add("MATERIAL");
tables.add("ORDER_ITEM");
tables.add("REQUIREMENT_ITEMS");
for (String item : tables)
{
@@ -119,6 +122,26 @@ public class DbInfoServiceImpl extends AbstractService<DbInfo> implements DbInfo
}
}
if (dbVersion < 3)
{
sql = "UPDATE INVOICING SET COMPLETED = false WHERE (COMPLETED Is NULL) ";
sq = this.dao.getSession().createSQLQuery(sql);
sq.executeUpdate();
}
if (dbVersion < 4)
{
sql = "UPDATE TRIP_BILL SET RESULT_MESSAGE = 'Zpráva z pracovní cesty' WHERE (RESULT_MESSAGE Is NULL) ";
sq = this.dao.getSession().createSQLQuery(sql);
sq.executeUpdate();
}
if (dbVersion < 5) {
sql = "ALTER TABLE TRIP_BILL MODIFY RESULT_MESSAGE VARCHAR(" + String.valueOf(Constants.LEN_RESULT_MESSAGE) + ")";
sq = this.dao.getSession().createSQLQuery(sql);
sq.executeUpdate();
}
this.updateDatabaseVersion();
}
}
@@ -0,0 +1,14 @@
package info.bukova.isspst.services.fulltext;
import java.io.ByteArrayInputStream;
/**
* @author Pepa Rokos
*/
public abstract class AbstractExtractor implements Extractor {
public String extract(byte[] data) {
return extract(new ByteArrayInputStream(data));
}
}
@@ -0,0 +1,25 @@
package info.bukova.isspst.services.fulltext;
import org.apache.poi.POIXMLTextExtractor;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Pepa Rokos
*/
public abstract class AbstractOfficeExtractor extends AbstractExtractor {
@Override
public String extract(InputStream is) throws ExtractorException {
try {
POIXMLTextExtractor extractor = createExtractor(is);
return extractor.getText();
} catch (IOException e) {
throw new ExtractorException(e);
}
}
protected abstract POIXMLTextExtractor createExtractor(InputStream is) throws IOException;
}
@@ -0,0 +1,19 @@
package info.bukova.isspst.services.fulltext;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.xssf.extractor.XSSFExcelExtractor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Pepa Rokos
*/
public class ExcelExtractor extends AbstractOfficeExtractor implements Extractor {
@Override
protected POIXMLTextExtractor createExtractor(InputStream is) throws IOException {
return new XSSFExcelExtractor(new XSSFWorkbook(is));
}
}
@@ -0,0 +1,30 @@
package info.bukova.isspst.services.fulltext;
import java.io.InputStream;
/**
* @author Pepa Rokos
*
* Rozhraní extractoru čistého textu z formátů Office a PDF
*/
public interface Extractor {
/**
* Extrahuje text z předaného pole bytů
*
* @param data zdrajová data
* @return čistý text
* @throws ExtractorException
*/
public String extract(byte[] data) throws ExtractorException;
/**
* Extrahuje text z předaného InputStream objektu
*
* @param is zdrojový InputStream
* @return čistý text
* @throws ExtractorException
*/
public String extract(InputStream is) throws ExtractorException;
}
@@ -0,0 +1,16 @@
package info.bukova.isspst.services.fulltext;
import info.bukova.isspst.services.IsspstException;
/**
* @author Pepa Rokos
*
* Výjimka extrakce textu
*/
public class ExtractorException extends IsspstException {
public ExtractorException(Throwable cause) {
super("Extractor exception: ", cause);
}
}
@@ -0,0 +1,42 @@
package info.bukova.isspst.services.fulltext;
/**
* @author Pepa Rokos
*
* Factory pro konkrétní extractor
*/
public class ExtractorFactory {
/**
* Vytvoří extractor podle předaného content typu
*
* @param contentType
* @return Extractor
*/
public static Extractor createExtractor(String contentType) {
if (contentType.equals("application/vnd.oasis.opendocument.text")
|| contentType.equals("application/vnd.oasis.opendocument.spreadsheet")
|| contentType.equals("application/vnd.oasis.opendocument.presentation")) {
return new OdfExtractor();
}
if (contentType.equals("application/vnd.openxmlformats-officedocument.wordprocessingml.document")) {
return new WordExtractor();
}
if (contentType.equals("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
return new ExcelExtractor();
}
if (contentType.equals("application/vnd.openxmlformats-officedocument.presentationml.slideshow")) {
return new PowerPointExtractor();
}
if (contentType.equals("application/pdf")) {
return new PdfExtractor();
}
return null;
}
}
@@ -0,0 +1,42 @@
package info.bukova.isspst.services.fulltext;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import java.util.List;
/**
* @author Pepa Rokos
*
* Rozhraní služby fulltextového vyhledávání
*
*/
public interface FullTextService {
/**
* Přegeneruje fulltextový index.
*/
public void reindex();
/**
* Vyhledává entity zadané třídy. Třída entity musí být anotovaná {@link Indexed}
*
* @param entityClass třída entity k vyhledání
* @param fields property entity kde se bude vyhledávat. Musí být anotované {@link Field}
* @param word vyhledávaný výraz
* @return list odpovídajících entit
*/
public List<?> search(Class<?> entityClass, String[] fields, String word);
/**
* Globální vyhledávání ve všech entitách, jejichš třídy jsou anotované {@link Indexed} a
* property {@link Field}
*
* @param word vyhledávaný výraz
* @return list odpovídajících entit
*/
public List<?> globalSearch(String word);
}
@@ -0,0 +1,154 @@
package info.bukova.isspst.services.fulltext;
import info.bukova.isspst.ModuleUtils;
import info.bukova.isspst.dao.QueryDao;
import info.bukova.isspst.data.BaseData;
import info.bukova.isspst.data.User;
import info.bukova.isspst.services.ModuleNotActiveException;
import info.bukova.isspst.sort.ReflectionTools;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.hibernate.Hibernate;
import org.hibernate.search.FullTextQuery;
import org.hibernate.search.FullTextSession;
import org.hibernate.search.Search;
import org.hibernate.search.annotations.IndexedEmbedded;
import org.hibernate.search.query.dsl.QueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FullTextServiceImpl implements FullTextService {
@Autowired
private QueryDao queryDao;
private List<Class<?>> classesForSearch;
private Map<Class<?>, String[]> fields;
private List<Class<?>> nestedClasses;
public FullTextServiceImpl() {
nestedClasses = new ArrayList<Class<?>>();
nestedClasses.add(User.class);
nestedClasses.add(BaseData.class);
}
@Override
@Transactional
public void reindex() {
Logger logger = LoggerFactory.getLogger(FullTextServiceImpl.class);
logger.info("Indexing database for fulltext search");
FullTextSession ftSession = Search.getFullTextSession(queryDao.getSession());
ftSession.createIndexer().start();
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_SEARCH')")
public List<?> search(Class<?> entityClass, String[] fields, String word) {
checkActivity();
FullTextSession session = Search.getFullTextSession(queryDao.getSession());
QueryBuilder qb = session.getSearchFactory().buildQueryBuilder().forEntity(entityClass).get();
Query luceneQuery = qb.keyword().onFields(fields).matching(word).createQuery();
FullTextQuery hiberQuery = session.createFullTextQuery(luceneQuery, entityClass);
hiberQuery.setSort(Sort.RELEVANCE);
return hiberQuery.list();
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_SEARCH')")
public List<?> globalSearch(String word) {
checkActivity();
List<Object> result = new ArrayList<Object>();
for (Class<?> clazz : classesForSearch()) {
result.addAll(search(clazz, fields.get(clazz), word));
}
for (Object o : result) {
BaseData data = (BaseData) o;
Hibernate.initialize(data.getModifiedBy());
Hibernate.initialize(data.getOwnedBy());
}
return result;
}
private void checkActivity() {
if (!ModuleUtils.getModule(this.getClass()).isActive()) {
throw new ModuleNotActiveException();
}
}
private List<Class<?>> classesForSearch() {
if (classesForSearch != null) {
return classesForSearch;
}
classesForSearch = new ArrayList<Class<?>>();
fields = new HashMap<Class<?>, String[]>();
FullTextSession session = Search.getFullTextSession(queryDao.getSession());
for (Class<?> clazz : session.getSearchFactory().getIndexedTypes()) {
if (nestedClasses.contains(clazz)) {
continue;
}
classesForSearch.add(clazz);
fields.put(clazz, fields(clazz, ""));
}
return classesForSearch;
}
private String[] fields(Class<?> clazz, String prefix) {
List<String> res = new ArrayList<String>();
for (Field field : ReflectionTools.getFields(clazz)) {
for (Annotation a : field.getDeclaredAnnotations()) {
if (a instanceof org.hibernate.search.annotations.Field) {
res.add(prefix + field.getName());
}
if (a instanceof IndexedEmbedded) {
Class<?> fieldClass;
fieldClass = field.getType();
if (fieldClass.isAssignableFrom(List.class)) {
ParameterizedType type = (ParameterizedType) field.getGenericType();
Type[] types = type.getActualTypeArguments();
if (types.length == 1) {
fieldClass = (Class<?>)types[0];
}
}
classesForSearch.remove(fieldClass);
fields.remove(fieldClass);
nestedClasses.add(fieldClass);
String nestedPrefix = prefix + field.getName() + ".";
res.addAll(Arrays.asList(fields(fieldClass, nestedPrefix)));
}
}
}
String resArray[] = new String[res.size()];
resArray = res.toArray(resArray);
return resArray;
}
}
@@ -0,0 +1,24 @@
package info.bukova.isspst.services.fulltext;
import org.odftoolkit.simple.Document;
import org.odftoolkit.simple.common.TextExtractor;
import java.io.InputStream;
/**
* @author Pepa Rokos
*/
public class OdfExtractor extends AbstractExtractor implements Extractor {
@Override
public String extract(InputStream is) throws ExtractorException {
try {
Document odfDocument = Document.loadDocument(is);
TextExtractor extractor = TextExtractor.newOdfTextExtractor(odfDocument.getContentRoot());
return extractor.getText();
} catch (Exception e) {
throw new ExtractorException(e);
}
}
}
@@ -0,0 +1,32 @@
package info.bukova.isspst.services.fulltext;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.parser.PdfTextExtractor;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Pepa Rokos
*/
public class PdfExtractor extends AbstractExtractor implements Extractor {
@Override
public String extract(InputStream is) throws ExtractorException {
try {
PdfReader reader = new PdfReader(is);
PdfTextExtractor extractor = new PdfTextExtractor(reader);
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
sb.append(extractor.getTextFromPage(i));
}
return sb.toString();
} catch (IOException e) {
throw new ExtractorException(e);
}
}
}
@@ -0,0 +1,20 @@
package info.bukova.isspst.services.fulltext;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.xslf.extractor.XSLFPowerPointExtractor;
import org.apache.poi.xslf.usermodel.XMLSlideShow;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Pepa Rokos
*/
public class PowerPointExtractor extends AbstractOfficeExtractor implements Extractor {
@Override
protected POIXMLTextExtractor createExtractor(InputStream is) throws IOException {
return new XSLFPowerPointExtractor(new XMLSlideShow(is));
}
}
@@ -0,0 +1,19 @@
package info.bukova.isspst.services.fulltext;
import org.apache.poi.POIXMLTextExtractor;
import org.apache.poi.xwpf.extractor.XWPFWordExtractor;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import java.io.IOException;
import java.io.InputStream;
/**
* @author Pepa Rokos
*/
public class WordExtractor extends AbstractOfficeExtractor implements Extractor {
@Override
protected POIXMLTextExtractor createExtractor(InputStream is) throws IOException {
return new XWPFWordExtractor(new XWPFDocument(is));
}
}
@@ -1,11 +1,13 @@
package info.bukova.isspst.services.invoicing;
import java.math.BigDecimal;
import info.bukova.isspst.data.Invoicing;
import info.bukova.isspst.data.Requirement;
import info.bukova.isspst.data.Workgroup;
import info.bukova.isspst.services.Service;
import java.math.BigDecimal;
import java.util.List;
public interface InvoicingService extends Service<Invoicing> {
public BigDecimal totalInvoicedForWorkgroup(Workgroup workgroup);
@@ -16,4 +18,17 @@ public interface InvoicingService extends Service<Invoicing> {
public void calculate(Invoicing invoicing);
public List<Invoicing> getPendingList();
public List<Invoicing> getArchiveList();
public Invoicing getForRequirement(Requirement req);
public List<Invoicing> getMaterialPendingList();
public List<Invoicing> getMaterialArchiveList();
public List<Invoicing> getServicesPendingList();
public List<Invoicing> getServicesArchiveList();
}
@@ -1,19 +1,20 @@
package info.bukova.isspst.services.invoicing;
import info.bukova.isspst.Constants;
import info.bukova.isspst.data.Invoicing;
import info.bukova.isspst.data.InvoicingItem;
import info.bukova.isspst.data.Requirement;
import info.bukova.isspst.data.Workgroup;
import info.bukova.isspst.services.AbstractOwnedService;
import info.bukova.isspst.services.LazyLoader;
import java.math.BigDecimal;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
public class InvoicingServiceImpl extends AbstractOwnedService<Invoicing> implements
InvoicingService {
@@ -73,4 +74,72 @@ public class InvoicingServiceImpl extends AbstractOwnedService<Invoicing> implem
invoice.getRequirement().setOwnedBy(inv.getRequirement().getOwnedBy());
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<Invoicing> getPendingList()
{
Query q = dao.getQuery("select inv from Invoicing as inv join fetch inv.requirement rq join fetch rq.ownedBy where (inv.completed Is Null or inv.completed = false) order by rq.numser");
return q.list();
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<Invoicing> getArchiveList()
{
Query q = dao.getQuery("select inv from Invoicing as inv join fetch inv.requirement rq join fetch rq.ownedBy where inv.completed = true order by rq.numser");
return q.list();
}
@Override
@Transactional
public Invoicing getForRequirement(Requirement req) {
Query query = dao.getQuery("select invoice from Invoicing invoice join invoice.requirement rq where rq.id = :reqId");
query.setParameter("reqId", req.getId());
return (Invoicing) query.uniqueResult();
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<Invoicing> getMaterialPendingList() {
Query q = dao.getQuery("select inv from Invoicing as inv join fetch inv.requirement rq join fetch rq.ownedBy where (inv.completed Is Null or inv.completed = false) and (rq.kind = :kind) order by rq.numser");
q.setParameter("kind", Constants.REQ_TYPE_MATERIAL);
return q.list();
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<Invoicing> getMaterialArchiveList() {
Query q = dao.getQuery("select inv from Invoicing as inv join fetch inv.requirement rq join fetch rq.ownedBy where (inv.completed = true) and (rq.kind = :kind) order by rq.numser");
q.setParameter("kind", Constants.REQ_TYPE_MATERIAL);
return q.list();
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<Invoicing> getServicesPendingList() {
Query q = dao.getQuery("select inv from Invoicing as inv join fetch inv.requirement rq join fetch rq.ownedBy where (inv.completed Is Null or inv.completed = false) and (rq.kind = :kind) order by rq.numser");
q.setParameter("kind", Constants.REQ_TYPE_SERVICES);
return q.list();
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<Invoicing> getServicesArchiveList() {
Query q = dao.getQuery("select inv from Invoicing as inv join fetch inv.requirement rq join fetch rq.ownedBy where (inv.completed = true) and (rq.kind = :kind) order by rq.numser");
q.setParameter("kind", Constants.REQ_TYPE_SERVICES);
return q.list();
}
}
@@ -0,0 +1,24 @@
package info.bukova.isspst.services.requirement;
import info.bukova.isspst.services.IsspstException;
/**
* @author Pepa Rokos
*/
public class ApproveException extends IsspstException {
/**
*
*/
private static final long serialVersionUID = -3794779381621324848L;
public ApproveException() {
super();
}
public ApproveException(String message) {
super(message);
this.setReason(message);
}
}
@@ -2,8 +2,10 @@ package info.bukova.isspst.services.requirement;
import info.bukova.isspst.data.RequirementBase;
import info.bukova.isspst.data.User;
import info.bukova.isspst.data.Workflow;
import info.bukova.isspst.services.Service;
import java.util.Date;
import java.util.List;
/**
@@ -21,8 +23,11 @@ public interface RequirementBaseService<T extends RequirementBase> extends Servi
public void loadType(T data);
public void loadWorkflow(T data);
public void approve(T entity);
public void approve(T entity, Date approveDate, byte[] signedPdf);
public boolean canApprove(T entity);
public List<User> getNextApprover(T entity);
public boolean prepareSignData(T entity, Date approveDate);
public Workflow getNextWorkflow(T entity);
public List<T> getMy();
@@ -1,28 +1,38 @@
package info.bukova.isspst.services.requirement;
import info.bukova.isspst.Constants;
import info.bukova.isspst.Module;
import info.bukova.isspst.ModuleUtils;
import info.bukova.isspst.data.AuthItem;
import info.bukova.isspst.data.DataModel;
import info.bukova.isspst.data.JobMapping;
import info.bukova.isspst.data.RequirementBase;
import info.bukova.isspst.data.RequirementState;
import info.bukova.isspst.data.Role;
import info.bukova.isspst.data.SettingsData;
import info.bukova.isspst.data.SignedDocument;
import info.bukova.isspst.data.SignedDocumentItem;
import info.bukova.isspst.data.User;
import info.bukova.isspst.data.Workflow;
import info.bukova.isspst.data.Workgroup;
import info.bukova.isspst.mail.MailMessage;
import info.bukova.isspst.mail.Mailer;
import info.bukova.isspst.mail.MessageBuilder;
import info.bukova.isspst.reporting.Generator;
import info.bukova.isspst.reporting.GeneratorFactory;
import info.bukova.isspst.reporting.ParamFiller;
import info.bukova.isspst.reporting.Report;
import info.bukova.isspst.reporting.ReportDefinition;
import info.bukova.isspst.services.AbstractOwnedService;
import info.bukova.isspst.services.LazyLoader;
import info.bukova.isspst.services.Service;
import info.bukova.isspst.services.settings.GlobalSettingsService;
import info.bukova.isspst.services.signeddocs.SignedDocumentService;
import info.bukova.isspst.services.users.UserService;
import info.bukova.isspst.services.workgroups.WorkgroupService;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import info.bukova.isspst.signapi.SignData;
import info.bukova.isspst.storage.FileStorage;
import info.bukova.isspst.storage.ReportFileStorage;
import org.hibernate.LazyInitializationException;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
@@ -30,6 +40,12 @@ import org.springframework.security.access.prepost.PostFilter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.ServletContext;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @author Pepa Rokos
* @author Franta Přibyl
@@ -51,6 +67,20 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
private UserService userService;
@Autowired
protected WorkgroupService workgroupService;
@Autowired
private ReportDefinition reportDefinition;
@Autowired
private ParamFiller paramFiller;
@Autowired
private GeneratorFactory genFactory;
@Autowired
private ServletContext servletContext;
@Autowired
private FileStorage storage;
@Autowired
private SignedDocumentService signedDocumentService;
@Autowired
private ReportFileStorage signedDocStorage;
@Override
@Transactional
@@ -76,11 +106,7 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
super.add(entity);
if (canApprove(entity)) {
approve(entity);
} else {
this.sendToApprovers(entity);
}
this.postAdd(entity);
}
private void checkEnable() {
@@ -104,6 +130,15 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
}
}
protected void postAdd(T entity) {
Workflow wf = getNextWorkflow(entity);
if (canApprove(entity) && (wf.getSignature() == null || !wf.getSignature())) {
approve(entity);
} else {
this.sendToApprovers(entity);
}
}
protected void addWorkflow(T entity) {
if (entity.getType() == null) {
return;
@@ -116,6 +151,7 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
workflow.setLimit(w.getLimit());
workflow.setOrder(w.getOrder());
workflow.setRole(w.getRole());
workflow.setSignature(w.getSignature());
entity.getWorkflow().add(workflow);
}
}
@@ -211,37 +247,51 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
}
}
protected void approve(T entity, User user) {
protected void approve(T entity, User user, Date approveDate, byte[] signedPdf) {
T e = (T) dao.getById(entity.getId());
if (e.getReqDate().getTime() > approveDate.getTime()) {
throw new ApproveException("ErrApproveBeforeRequirement");
}
if (e.getLastApproveDate() != null && e.getLastApproveDate().getTime() > approveDate.getTime()) {
throw new ApproveException("ErrAppreveBeforeLastApprove");
}
Workflow wf = getNextWorkflow(e);
if (wf == null) {
return;
}
Role role = wf.getRole();
AuthItem auth = new AuthItem();
auth.setApprover(user);
auth.setRole(role);
auth.setAuthDate(new Date());
auth.setAuthDate(approveDate);
e.getAuthorization().add(auth);
if (getNextWorkflow(e) == null) {
e.setState(RequirementState.APPROVED);
} else {
e.setState(RequirementState.PARTIALLY);
}
super.update(e);
if (!autoApprove(e)) {
if (signedPdf != null) {
saveSignedDoc(e, signedPdf);
} else if (wf.getSignature() != null && wf.getSignature() && !signatureNotRequired(wf)) {
throw new ApproveException("ErrApproveMustBeSigned");
}
if (!autoApprove(e, approveDate)) {
this.sendToApprovers(e);
SettingsData settings = settingsService.getSettings();
MailMessage message = null;
if (e.getOwnedBy().getEmail() != null
if (e.getOwnedBy().getEmail() != null
&& !e.getOwnedBy().getEmail().isEmpty()
&& e.getOwnedBy().isNotify()) {
if (e.getState() == RequirementState.APPROVED && settings.getConfReqTemplate() != null) {
@@ -249,17 +299,30 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
} else if (settings.getAuthReqTemplate() != null) {
message = messageBuilder.buildMessage(settings.getAuthReqTemplate(), e);
}
if (message != null) {
message.setFrom(getLoggedInUser().getEmail());
message.setTo(e.getOwnedBy().getEmail());
mailer.send(message);
mailer.send(message);
}
}
}
postApprove(e);
}
/**
* Check pro automatické schválení, kdy není třeba podepisovat- nadlimitní nákupy se neautorizují...
* @param wf Další krok schválení
* @return true pokud není potřeba podepisovat. Zde vrací vždy false, v případě potřeby nutno překrýt.
*/
protected boolean signatureNotRequired(Workflow wf) {
return false;
}
protected void approve(T entity, User user) {
approve(entity, user, new Date(), null);
}
@Override
@Transactional
@@ -268,13 +331,21 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
approve(entity, getLoggedInUser());
}
@Override
@Transactional
@PreAuthorize("this.canApprove(#entity)")
public void approve(T entity, Date approveDate, byte[] signedPdf) {
approve(entity, getLoggedInUser(), approveDate, signedPdf);
}
/**
* Volá se z metody approve pro automatické schválení dalším schvalovatelem v pořadí. Metoda z báze nedělá nic.
*
* @param entity Požadavek
* @param approveDate
* @return true pokud se provedlo automatické schválení.
*/
protected boolean autoApprove(T entity) {
protected boolean autoApprove(T entity, Date approveDate) {
return false;
}
@@ -287,6 +358,30 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
}
protected void saveSignedDoc(T entity, byte[] signedPdf) {
DataModel reportEntity = entityForSignReport(entity);
SignedDocumentItem signedItem = signedDocumentService.getItem(entityForSignReport(entity), getSignReport(entity).getReportId());
if (signedItem == null) {
SignedDocument signDoc = new SignedDocument();
signDoc.setDescription(entity.getDescription());
signDoc.setNumser(entity.getNumser());
signDoc.setRecordId(reportEntity.getId());
signDoc.setModuleName(ModuleUtils.getModule(reportEntity, servletContext).getId());
signDoc.setSignDate(entity.getLastApproveDate());
SignedDocumentItem item = new SignedDocumentItem();
item.setReportId(reportDefinition.getReport().getReportId());
item.setReportName(reportDefinition.getReport().getName());
signDoc.addItem(item);
signedDocStorage.saveFile(signedPdf, item);
signedDocumentService.addFromApprove(signDoc);
} else {
signedDocStorage.saveFile(signedPdf, signedItem);
}
}
@Override
@Transactional
public boolean canApprove(T entity) {
@@ -297,8 +392,12 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
return false;
}
protected Workflow getNextWorkflow(T e) {
@Override
@Transactional
public Workflow getNextWorkflow(T entity) {
T e = dao.getById(entity.getId());
AuthItem authItem = null;
if (e.getWorkflow() == null) {
return null;
@@ -385,4 +484,92 @@ public abstract class RequirementBaseServiceImpl<T extends RequirementBase> exte
return Constants.PERM_DELETE_NEW;
}
@Override
@Transactional
public boolean prepareSignData(T entity, Date approveDate) {
SignData data = new SignData();
sessionData.setProperty(Constants.KEY_SIGN_DATA, data);
data.setSignGuid(UUID.randomUUID().toString());
sessionData.setProperty(Constants.KEY_SIGN_GUID, data.getSignGuid());
reportDefinition.clear();
reportDefinition.setSingleObject(entityForSignReport(entity));
Report report = getSignReport(entity);
if (report == null) {
return false;
}
reportDefinition.setReport(report);
Module module = ModuleUtils.getModule(entityForSignReport(entity), servletContext);
reportDefinition.setService((Service<Object>) ModuleUtils.getServiceInstance(module, servletContext));
paramFiller.fill();
Generator gen = genFactory.createGenerator(reportDefinition);
data.setPdfData(gen.generate());
data.setDescription(entity.getDescription());
data.setNumser(entity.getNumser());
data.setSignDate(approveDate);
data.setSigned(signedDocumentService.getItem(entityForSignReport(entity), report.getReportId()) != null);
if (getNextWorkflow(entity).getCentre()) { // viditelné podpisy lze pouze na urovni strediska
if (entity.getState() == RequirementState.NEW) {
data.setAreaId(1);
} else {
loadAuthItems(entity);
int wgCount = 0;
for (Workflow wf : entity.getWorkflow()) {
if (!wf.getCentre()) {
++wgCount;
}
}
data.setAreaId(entity.getAuthorization().size() - wgCount + 1);
}
if (userService.getUserSettings().getSignatureFile() != null) {
data.setSignImg(storage.fileData(userService.getUserSettings().getSignatureFile()));
}
}
return true;
}
protected DataModel entityForSignReport(T entity) {
return entity;
}
private Report getSignReport(T entity) {
Module module = ModuleUtils.getModule(entityForSignReport(entity), servletContext);
Report report = null;
for (Report r : module.getReports()) {
if (r.isSignable()) {
report = r;
break;
}
}
return report;
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_EDIT') or hasPermission(#entity, this.getUpdateEntityPermission())")
public void update(T entity) {
entity.getAuthorization().clear();
entity.setState(RequirementState.NEW);
signedDocumentService.deleteForEntity(entity);
super.update(entity);
sendToApprovers(entity);
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_DELETE') or hasPermission(#entity, this.getDeleteEntityPermission())")
public void delete(T entity) {
signedDocumentService.delFromApprove(signedDocumentService.getForEntity(entity));
super.delete(entity);
}
}
@@ -10,16 +10,15 @@ import info.bukova.isspst.data.User;
import info.bukova.isspst.data.Workflow;
import info.bukova.isspst.services.LazyLoader;
import info.bukova.isspst.services.invoicing.InvoicingService;
import org.hibernate.Hibernate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
/**
* @author Pepa Rokos
* @author Franta Přibyl
@@ -48,7 +47,7 @@ public class RequirementServiceImpl extends RequirementBaseServiceImpl<Requireme
}
@Override
protected boolean autoApprove(Requirement entity)
protected boolean autoApprove(Requirement entity, Date approveDate)
{
List<User> approvers = this.getNextApprover(entity);
Workflow nextWf = this.getNextWorkflow(entity);
@@ -61,13 +60,23 @@ public class RequirementServiceImpl extends RequirementBaseServiceImpl<Requireme
if ((entity.getSumTotal() != null)
&& (entity.getSumTotal().compareTo(nextWf.getLimit()) == -1))
{
approve(entity, approvers.get(0));
approve(entity, approvers.get(0), approveDate, null);
return true;
}
return false;
}
/**
* Nadlimitní autorizovat bez podpisu
* @param wf Další krok schválení
* @return true, pokud role nastavený limit- automatické schválení podlimitního požadavku
*/
@Override
protected boolean signatureNotRequired(Workflow wf) {
return wf.getLimit() != null;
}
@Override
protected boolean canAdd(Requirement entity)
{
@@ -245,11 +254,19 @@ public class RequirementServiceImpl extends RequirementBaseServiceImpl<Requireme
@Override
@Transactional
public BigDecimal getInvoicedAmount(Requirement req) {
Query query = dao.getQuery("select invoice from Invoicing invoice join invoice.requirement rq where rq.id = :reqId");
query.setParameter("reqId", req.getId());
Invoicing inv = (Invoicing) query.uniqueResult();
Invoicing inv = invoicingService.getForRequirement(req);
return inv != null ? inv.getTotalInvoiced() : null;
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_EDIT') or hasPermission(#entity, this.getUpdateEntityPermission())")
public void update(Requirement entity) {
super.update(entity);
Invoicing inv = invoicingService.getForRequirement(entity);
if (inv != null) {
invoicingService.delete(inv);
}
}
}
@@ -10,6 +10,8 @@ public interface TripRequirementService extends RequirementBaseService<TripRequi
public void loadPassangers(TripRequirement entity);
public TripBill getTripBill(TripRequirement requirement);
/**
* Vrátí seznam vyúčtování, která josu vázána k požadavku
*
@@ -4,11 +4,18 @@ import info.bukova.isspst.Constants;
import info.bukova.isspst.data.NumberSeries;
import info.bukova.isspst.data.RequirementState;
import info.bukova.isspst.data.TripBill;
import info.bukova.isspst.data.TripBillApproval;
import info.bukova.isspst.data.TripRequirement;
import info.bukova.isspst.data.User;
import info.bukova.isspst.mail.MailMessage;
import info.bukova.isspst.mail.Mailer;
import info.bukova.isspst.mail.MessageBuilder;
import info.bukova.isspst.services.LazyLoader;
import info.bukova.isspst.services.settings.GlobalSettingsService;
import info.bukova.isspst.services.tripbill.TripBillApprovalService;
import info.bukova.isspst.services.tripbill.TripBillService;
import info.bukova.isspst.services.workgroups.WorkgroupService;
import info.bukova.isspst.services.users.UserService;
import org.hibernate.Hibernate;
import org.hibernate.LazyInitializationException;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
@@ -24,9 +31,17 @@ public class TripRequirementServiceImpl extends RequirementBaseServiceImpl<TripR
@Autowired
private RequirementTypeService reqTypeService;
@Autowired
private WorkgroupService workgroupService;
@Autowired
private TripBillService tripBillService;
@Autowired
private TripBillApprovalService tripBillApprovalService;
@Autowired
private Mailer mailer;
@Autowired
private MessageBuilder messageBuilder;
@Autowired
private GlobalSettingsService settingsService;
@Autowired
private UserService userService;
@Override
protected TripRequirement createEntity() {
@@ -42,17 +57,39 @@ public class TripRequirementServiceImpl extends RequirementBaseServiceImpl<TripR
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_EDIT') or hasPermission(#entity, this.getUpdateEntityPermission())")
public void update(TripRequirement entity) {
super.update(entity);
if (entity.getState() == RequirementState.APPROVED) {
for (TripBill bill : getBills(entity)) {
TripBill newBill = tripBillService.createTripBill(entity);
bill.getBillItems().clear();
bill.getBillItems().addAll(newBill.getBillItems());
TripBillApproval approval = bill.getApproval();
if (approval != null) {
tripBillApprovalService.delete(approval);
}
bill.setApproval(null);
tripBillService.calculate(bill);
tripBillService.update(bill);
}
}
super.update(entity);
}
@Override
protected void postAdd(TripRequirement entity) {
super.postAdd(entity);
sendMailToPassengers(entity, settingsService.getSettings().getReqPassenger());
}
private void sendMailToPassengers(TripRequirement entity, MailMessage messageTemplate) {
if (entity.getBillForPassengers() != null && !entity.getPassengers().isEmpty() && messageTemplate != null) {
MailMessage message = messageBuilder.buildMessage(messageTemplate, entity);
message.setFrom(userService.getCurrent().getEmail());
message.setTo(userService.getEmailsForSend(entity.getPassengers()));
mailer.send(message);
}
}
@Override
@@ -72,6 +109,20 @@ public class TripRequirementServiceImpl extends RequirementBaseServiceImpl<TripR
}
}
@Override
@Transactional
public TripBill getTripBill(TripRequirement requirement) {
Query q = dao.getQuery("from TripBill tb where tb.requirement = :req");
q.setParameter("req", requirement);
List<TripBill> result = q.list();
if (result.size() > 0) {
return result.get(0);
}
return null;
}
@Override
@Transactional
public List<TripBill> getBills(TripRequirement entity) {
@@ -80,25 +131,65 @@ public class TripRequirementServiceImpl extends RequirementBaseServiceImpl<TripR
return q.list();
}
@Transactional
@LazyLoader("form")
public void loadAttachments(TripRequirement entity) {
TripRequirement e = dao.getById(entity.getId());
Hibernate.initialize(e.getAttachedFiles());
entity.setAttachedFiles(e.getAttachedFiles());
}
@Override
protected void postApprove(TripRequirement entity) {
if (entity.getState() == RequirementState.APPROVED) {
if (entity.getState() != RequirementState.APPROVED) {
return;
}
List<TripBill> billList = getBills(entity);
boolean hasOwned = false;
for (TripBill tb : billList) {
if (tb.getOwnedBy().equals(entity.getOwnedBy())) {
hasOwned = true;
break;
}
}
if (!hasOwned) {
TripBill bill = tripBillService.createTripBill(entity);
tripBillService.add(bill);
bill.setOwnedBy(entity.getOwnedBy());
tripBillService.update(bill);
}
if (entity.getBillForPassengers() != null && entity.getBillForPassengers()) {
for (User u : entity.getPassengers()) {
if (!u.equals(entity.getOwnedBy())) {
TripBill passBill = tripBillService.createTripBill(entity);
if (canCreateBill(entity, u, billList)) {
TripBill passBill = tripBillService.createPassengersBill(entity);
tripBillService.add(passBill);
passBill.setOwnedBy(u);
tripBillService.update(passBill);
}
}
sendMailToPassengers(entity, settingsService.getSettings().getConfReqTripPassenger());
}
}
private boolean canCreateBill(TripRequirement req, User owner, List<TripBill> bills) {
if (owner.equals(req.getOwnedBy())) {
return false;
}
for (TripBill tb : bills) {
if (tb.getOwnedBy().equals(owner)) {
return false;
}
}
return true;
}
@Override
protected String getNumberSerie() {
String currentNumber = "";
@@ -0,0 +1,20 @@
package info.bukova.isspst.services.signeddocs;
import info.bukova.isspst.data.DataModel;
import info.bukova.isspst.data.SignedDocument;
import info.bukova.isspst.data.SignedDocumentItem;
import info.bukova.isspst.services.Service;
import java.util.List;
public interface SignedDocumentService extends Service<SignedDocument> {
SignedDocument getForEntity(DataModel entity);
SignedDocumentItem getItem(DataModel entity, long reportId);
void addFromApprove(SignedDocument document);
void delFromApprove(SignedDocument document);
void deleteForEntity(DataModel entity);
public List<SignedDocument> getActualList();
public List<SignedDocument> getArchiveList();
}
@@ -0,0 +1,129 @@
package info.bukova.isspst.services.signeddocs;
import info.bukova.isspst.DateTimeUtils;
import info.bukova.isspst.Module;
import info.bukova.isspst.ModuleUtils;
import info.bukova.isspst.data.DataModel;
import info.bukova.isspst.data.SignedDocument;
import info.bukova.isspst.data.SignedDocumentItem;
import info.bukova.isspst.services.AbstractOwnedService;
import info.bukova.isspst.services.LazyLoader;
import info.bukova.isspst.storage.ReportFileStorage;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletContext;
import org.hibernate.Hibernate;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
public class SignedDocumentServiceImpl extends AbstractOwnedService<SignedDocument> implements SignedDocumentService {
@Autowired
private ServletContext servletContext;
@Autowired
private ReportFileStorage signedDocStorage;
@LazyLoader("grid")
@Transactional
public void lazyLoadItems(SignedDocument signedDocument) {
if (signedDocument == null) {
return;
}
SignedDocument sd = dao.getById(signedDocument.getId());
Hibernate.initialize(sd.getItems());
signedDocument.setItems(sd.getItems());
}
@Override
@Transactional
public SignedDocument getForEntity(DataModel entity) {
Module module = ModuleUtils.getModule(entity, servletContext);
if (module == null) {
return null;
}
Query q = dao.getQuery("from SignedDocument where moduleName = :module and recordId = :record");
q.setParameter("module", module.getId());
q.setParameter("record", entity.getId());
return (SignedDocument) q.uniqueResult();
}
@Override
@Transactional
public SignedDocumentItem getItem(DataModel entity, long reportId) {
SignedDocument doc = getForEntity(entity);
if (doc == null) {
return null;
}
for (SignedDocumentItem item : doc.getItems()) {
if (item.getReportId() == reportId) {
return item;
}
}
return null;
}
@Override
public void addFromApprove(SignedDocument document) {
super.add(document);
}
@Override
public void delFromApprove(SignedDocument document) {
if (document == null) {
return;
}
super.delete(document);
for (SignedDocumentItem item : document.getItems()) {
signedDocStorage.removeFile(item);
}
}
@Override
@Transactional
public void deleteForEntity(DataModel entity) {
SignedDocument doc = getForEntity(entity);
if (doc != null) {
delFromApprove(doc);
}
}
private Date getTresholdDate() {
Date date = DateTimeUtils.getDateDelta(DateTimeUtils.getCurrDate(), Calendar.YEAR, -1);
return date;
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<SignedDocument> getActualList() {
Query q = dao.getQuery("from SignedDocument where signDate >= :refDate");
q.setParameter("refDate", this.getTresholdDate());
return q.list();
}
@SuppressWarnings("unchecked")
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_READ')")
public List<SignedDocument> getArchiveList() {
Query q = dao.getQuery("from SignedDocument where signDate < :refDate");
q.setParameter("refDate", this.getTresholdDate());
return q.list();
}
}
@@ -0,0 +1,18 @@
package info.bukova.isspst.services.tripbill;
import info.bukova.isspst.services.IsspstException;
/**
* @author Pepa Rokos
*/
public class PayException extends IsspstException {
public PayException() {
super();
}
public PayException(String message) {
super(message);
setReason(message);
}
}
@@ -0,0 +1,15 @@
package info.bukova.isspst.services.tripbill;
import info.bukova.isspst.data.TripBill;
import info.bukova.isspst.data.TripBillApproval;
import info.bukova.isspst.services.requirement.RequirementBaseService;
/**
* @author Pepa Rokos
*/
public interface TripBillApprovalService extends RequirementBaseService<TripBillApproval> {
public TripBillApproval createApproval(TripBill bill);
public void cancelApproval(TripBill bill);
}
@@ -0,0 +1,103 @@
package info.bukova.isspst.services.tripbill;
import info.bukova.isspst.Constants;
import info.bukova.isspst.Module;
import info.bukova.isspst.ModuleUtils;
import info.bukova.isspst.StringUtils;
import info.bukova.isspst.data.DataModel;
import info.bukova.isspst.data.RequirementState;
import info.bukova.isspst.data.TripBill;
import info.bukova.isspst.data.TripBillApproval;
import info.bukova.isspst.services.IsspstException;
import info.bukova.isspst.services.requirement.RequirementBaseServiceImpl;
import info.bukova.isspst.services.requirement.RequirementTypeService;
import info.bukova.isspst.services.signeddocs.SignedDocumentService;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
/**
* @author Pepa Rokos
*/
public class TripBillApprovalServiceImpl extends RequirementBaseServiceImpl<TripBillApproval> implements TripBillApprovalService {
@Autowired
private RequirementTypeService reqTypeService;
@Autowired
private TripBillService tripBillService;
@Autowired
private SignedDocumentService signedDocumentService;
@Override
public TripBillApproval createApproval(TripBill bill) {
if (bill.getApproval() != null) {
throw new IsspstException("Approval already exists");
}
TripBillApproval approval = new TripBillApproval();
approval.setCentre(bill.getRequirement().getCentre());
approval.setWorkgroup(bill.getRequirement().getWorkgroup());
approval.setReqDate(new Date());
approval.setType(reqTypeService.getTypeById(Constants.REQTYPE_BUSINESSTRIP));
approval.setState(RequirementState.NEW);
// approval.setNumser(bill.getRequirement().getNumser());
approval.setDescription(StringUtils.localize("TravelOrdersFormTitle") + " \"" + bill.getOwnedBy() + "\" - " + bill.getRequirement().getDescription());
approval.setBill(bill);
bill.setApproval(approval);
return approval;
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_ADD')")
public void add(TripBillApproval entity) {
entity.setCreated(new Date());
entity.setOwnedBy(getLoggedInUser());
addWorkflow(entity);
dao.add(entity);
postAdd(entity);
}
@Override
protected DataModel entityForSignReport(TripBillApproval entity) {
return entity.getBill();
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_DELETE') or this.canApprove(#bill.approval)")
public void cancelApproval(TripBill bill) {
bill.setApproval(null);
signedDocumentService.deleteForEntity(bill);
tripBillService.update(bill);
}
@Override
public Module getModule() {
return ModuleUtils.getModule(Constants.MOD_TRIPREQUIREMENTS);
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_DELETE') or hasPermission(#entity, this.getDeleteEntityPermission())")
public void delete(TripBillApproval entity) {
TripBill bill = entity.getBill();
if (bill == null) {
Query q = queryDao.getQuery("FROM TripBill WHERE APPROVAL_ID = :appId");
q.setInteger("appId", entity.getId());
bill = (TripBill) q.uniqueResult();
}
if (bill != null) {
dao.delete(entity);
cancelApproval(bill);
} else {
super.delete(entity);
}
}
}
@@ -1,18 +1,28 @@
package info.bukova.isspst.services.tripbill;
import java.util.List;
import info.bukova.isspst.data.TripBill;
import info.bukova.isspst.data.TripRequirement;
import info.bukova.isspst.services.Service;
import java.util.Date;
import java.util.List;
public interface TripBillService extends Service<TripBill> {
public TripBill createTripBill(TripRequirement requirement);
public TripBill createPassengersBill(TripRequirement requirement);
public void loadItems(TripBill bill);
public void calculate(TripBill bill);
public List<TripBill> getMy();
public void loadOwner(TripBill bill);
public void loadPassengers(TripBill bill);
public void setPaid(TripBill bill, Date date);
/**
* Uloží vyúčtování a nastaví příznak přenosu vyúčtování od žadatele
*
* @param bill
*/
public void updateOwned(TripBill bill);
}
@@ -1,5 +1,6 @@
package info.bukova.isspst.services.tripbill;
import info.bukova.isspst.data.RequirementState;
import info.bukova.isspst.data.SettingsData;
import info.bukova.isspst.data.TripBill;
import info.bukova.isspst.data.TripBillItem;
@@ -7,13 +8,7 @@ import info.bukova.isspst.data.TripRequirement;
import info.bukova.isspst.services.AbstractOwnedService;
import info.bukova.isspst.services.LazyLoader;
import info.bukova.isspst.services.settings.GlobalSettingsService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import org.hibernate.Hibernate;
import org.hibernate.LazyInitializationException;
import org.hibernate.Query;
import org.joda.time.DateTime;
@@ -24,6 +19,13 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implements
TripBillService {
@@ -32,13 +34,26 @@ public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implemen
@Override
public TripBill createTripBill(TripRequirement requirement) {
return createBill(requirement, false);
}
@Override
public TripBill createPassengersBill(TripRequirement requirement) {
return createBill(requirement, true);
}
private TripBill createBill(TripRequirement requirement, boolean passengers) {
TripBill bill = new TripBill();
bill.setRequirement(requirement);
int daysCount = Days.daysBetween((new DateTime(requirement.getTripDate())).withTimeAtStartOfDay(),
if (!passengers) {
bill.setDownPayment(requirement.getDownPayment());
}
int daysCount = Days.daysBetween((new DateTime(requirement.getTripDate())).withTimeAtStartOfDay(),
(new DateTime(requirement.getEndDate())).withTimeAtStartOfDay()).getDays() + 1;
for (int i = 0 ; i < daysCount ; i++) {
TripBillItem item = new TripBillItem();
if (i == 0) {
@@ -49,17 +64,17 @@ public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implemen
item.setBack(requirement.getTo() + " - " + requirement.getFrom());
item.setBackVehicle(requirement.getVehicle());
}
Calendar calTripDate = Calendar.getInstance();
calTripDate.setTime(requirement.getTripDate());
calTripDate.add(Calendar.DATE, i);
item.setDate(calTripDate.getTime());
bill.getBillItems().add(item);
}
this.calculate(bill);
return bill;
}
@@ -80,6 +95,14 @@ public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implemen
}
}
@Transactional
@LazyLoader("form")
public void loadAttachments(TripBill entity) {
TripBill e = dao.getById(entity.getId());
Hibernate.initialize(e.getAttachedFiles());
entity.setAttachedFiles(e.getAttachedFiles());
}
@Override
public void calculate(TripBill bill) {
bill.setTotal(BigDecimal.ZERO);
@@ -93,8 +116,8 @@ public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implemen
bill.setTotal(bill.getTotal().add(item.getTotal()));
}
if (bill.getRequirement().getDownPayment() != null) {
bill.setTotal(bill.getTotal().subtract(bill.getRequirement().getDownPayment()));
if (bill.getDownPayment() != null) {
bill.setTotal(bill.getTotal().subtract(bill.getDownPayment()));
}
}
@@ -170,11 +193,13 @@ public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implemen
@Override
@Transactional
@LazyLoader("print")
@LazyLoader({"print", "form"})
public void loadOwner(TripBill bill) {
TripBill tb = dao.getById(bill.getId());
tb.getOwnedBy().getFirstName();
tb.getRequirement().getOwnedBy().getFirstName();
bill.setOwnedBy(tb.getOwnedBy());
bill.getRequirement().setOwnedBy(tb.getRequirement().getOwnedBy());
}
@Override
@@ -188,4 +213,65 @@ public class TripBillServiceImpl extends AbstractOwnedService<TripBill> implemen
bill.getRequirement().setPassengers(tr.getPassengers());
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_PAY_BILL')")
public void setPaid(TripBill bill, Date date) {
if (bill.getApproval() == null || bill.getApproval().getState() != RequirementState.APPROVED) {
throw new PayException("BillNotApproved");
}
bill.setPaid(true);
bill.setPaidDate(date);
super.update(bill);
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_EDIT') or hasPermission(#entity, this.getUpdateEntityPermission())")
public void updateOwned(TripBill bill) {
bill.setSaved(true);
update(bill);
}
@Override
@Transactional
@PreAuthorize("hasPermission(this, 'PERM_EDIT') or hasPermission(#entity, this.getUpdateEntityPermission())")
public void update(TripBill entity) {
super.update(entity);
TripRequirement req = entity.getRequirement();
if (req.getOwnedBy().equals(entity.getOwnedBy())) {
Query q = dao.getQuery("from TripBill where requirement = :req and id != :id and (saved = false or saved is null)");
q.setParameter("req", req);
q.setParameter("id", entity.getId());
List<TripBill> bills = q.list();
for (TripBill tb : bills) {
tb.getBillItems().clear();
for (TripBillItem item : entity.getBillItems()) {
tb.getBillItems().add(new TripBillItem(item));
}
tb.setFreeCarfare(entity.isFreeCarfare());
tb.setFreeHousing(entity.isFreeHousing());
tb.setFreeMeals(entity.isFreeMeals());
calculate(tb);
super.update(tb);
}
}
}
@Override
public boolean canPrintRecord(TripBill entity) {
if (entity.getApproval() != null
&& entity.getApproval().getState() == RequirementState.APPROVED
&& (entity.getPaid() == null || !entity.getPaid())) {
return true;
}
return false;
}
}
@@ -3,9 +3,6 @@ package info.bukova.isspst.services.users;
import info.bukova.isspst.Constants;
import info.bukova.isspst.data.User;
import info.bukova.isspst.security.AuthMethod;
import java.util.Collection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.DirContextAdapter;
@@ -16,6 +13,8 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.ldap.authentication.ad.ActiveDirectoryLdapAuthenticationProvider;
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper;
import java.util.Collection;
/**
* Mapovač doménových uživatelů Active Directory na uživatele aplikace. Pokud uživatel není v aplikační databází,
* importu je se tam pomoci {@link LdapUserImporter}. Tento objekt se předává do {@link ActiveDirectoryLdapAuthenticationProvider}.
@@ -40,7 +39,8 @@ public class AdUserCtxMapper implements UserDetailsContextMapper {
@Override
public UserDetails mapUserFromContext(DirContextOperations userData,
String username, Collection<? extends GrantedAuthority> authorities) {
username = username.toLowerCase();
try {
User user = (User) userService.loadUserByUsername(username);
return user;
@@ -7,15 +7,7 @@ import info.bukova.isspst.data.UserSettingsData;
import info.bukova.isspst.security.AuthMethod;
import info.bukova.isspst.services.AbstractService;
import info.bukova.isspst.services.StringXmlMarshaller;
//import info.bukova.isspst.services.LazyLoader;
import info.bukova.isspst.services.workgroups.WorkgroupService;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.exolab.castor.xml.Marshaller;
import org.exolab.castor.xml.Unmarshaller;
import org.hibernate.LazyInitializationException;
@@ -31,6 +23,13 @@ import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
//import info.bukova.isspst.services.LazyLoader;
public class UserServiceImpl extends AbstractService<User> implements UserService {
private PasswordEncoder encoder;
@@ -220,6 +219,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
}
@Override
@Transactional
public void delete(User entity) {
workgroupService.loadParents(entity);
@@ -234,7 +234,7 @@ public class UserServiceImpl extends AbstractService<User> implements UserServic
@Override
@Transactional
public List<User> getUsersForCombo() {
Query q = dao.getQuery("from User u order by u.lastName");
Query q = dao.getQuery("from User u where u.enabled = true order by u.lastName");
return q.list();
}
@@ -0,0 +1,10 @@
package info.bukova.isspst.signapi;
/**
* @author Pepa Rokos
*/
public interface JnlpGenerator {
public byte[] generate();
}
@@ -0,0 +1,121 @@
package info.bukova.isspst.signapi;
import org.springframework.beans.factory.annotation.Autowired;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.ByteArrayOutputStream;
/**
* @author Pepa Rokos
*/
public class JnlpGeneratorImpl implements JnlpGenerator {
@Autowired
private HttpServletRequest request;
@Override
public byte[] generate() {
String sessionId;
if (request.getParameter("id") != null && !request.getParameter("id").isEmpty()) {
sessionId = request.getParameter("id");
} else {
sessionId = request.getSession().getId();
}
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document document = docBuilder.newDocument();
Element root = document.createElement("jnlp");
root.setAttribute("spec", "1.0+");
String signerUrl = request.getRequestURL().toString();
signerUrl = signerUrl.substring(0, signerUrl.indexOf(request.getServletPath())) + "/api/sign";
root.setAttribute("codebase", signerUrl);
root.setAttribute("href", "signer.jnlp" + "?id=" + sessionId);
document.appendChild(root);
Element info = document.createElement("information");
Element title = document.createElement("title");
title.appendChild(document.createTextNode("Signer component"));
info.appendChild(title);
Element vendor = document.createElement("vendor");
vendor.appendChild(document.createTextNode("bukova.info"));
info.appendChild(vendor);
root.appendChild(info);
Element security = document.createElement("security");
security.appendChild(document.createElement("all-permissions"));
root.appendChild(security);
Element resources = document.createElement("resources");
resources.setAttribute("os", "Linux");
Element j2se = document.createElement("j2se");
j2se.setAttribute("version", "1.8+");
Element jar = document.createElement("jar");
jar.setAttribute("href", "pdfsigner.jar");
resources.appendChild(j2se);
resources.appendChild(jar);
root.appendChild(resources);
Element resourcesWin = document.createElement("resources");
resourcesWin.setAttribute("os", "Windows");
Element j2seWin = document.createElement("j2se");
j2seWin.setAttribute("version", "1.8+");
Element jarWin = document.createElement("jar");
jarWin.setAttribute("href", "pdfsignerWin.jar");
resourcesWin.appendChild(j2seWin);
resourcesWin.appendChild(jarWin);
root.appendChild(resourcesWin);
Element appDesc = document.createElement("application-desc");
appDesc.setAttribute("main-class", "info.bukova.pdfsigner.Main");
Element argUrl = document.createElement("argument");
argUrl.appendChild(document.createTextNode(signerUrl + "/data"));
appDesc.appendChild(argUrl);
Element argSession = document.createElement("argument");
argSession.appendChild(document.createTextNode(sessionId));
appDesc.appendChild(argSession);
root.appendChild(appDesc);
System.out.println(signerUrl);
System.out.println(request.getSession().getId());
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
StreamResult result = new StreamResult(bos);
transformer.transform(source, result);
return bos.toByteArray();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
} catch (TransformerException e) {
e.printStackTrace();
}
return null;
}
}
@@ -0,0 +1,92 @@
package info.bukova.isspst.signapi;
import java.io.Serializable;
import java.util.Date;
/**
* @author Pepa Rokos
*/
public class SignData implements Serializable {
private byte[] pdfData;
private byte[] signImg;
private int areaId;
private Date signDate;
private String description;
private String numser;
private boolean signed;
private String signGuid;
private boolean signSuccess;
public byte[] getPdfData() {
return pdfData;
}
public void setPdfData(byte[] pdfData) {
this.pdfData = pdfData;
}
public Date getSignDate() {
return signDate;
}
public void setSignDate(Date signDate) {
this.signDate = signDate;
}
public String getNumser() {
return numser;
}
public void setNumser(String numser) {
this.numser = numser;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isSigned() {
return signed;
}
public void setSigned(boolean signed) {
this.signed = signed;
}
public String getSignGuid() {
return signGuid;
}
public void setSignGuid(String signGuid) {
this.signGuid = signGuid;
}
public boolean isSignSuccess() {
return signSuccess;
}
public void setSignSuccess(boolean signSuccess) {
this.signSuccess = signSuccess;
}
public byte[] getSignImg() {
return signImg;
}
public void setSignImg(byte[] signImg) {
this.signImg = signImg;
}
public int getAreaId() {
return areaId;
}
public void setAreaId(int areaId) {
this.areaId = areaId;
}
}
@@ -0,0 +1,28 @@
package info.bukova.isspst.signapi;
import java.io.Serializable;
/**
* @author Pepa Rokos
*/
public class SignUploadResponse implements Serializable {
private boolean ok;
private String errorMessage;
public boolean isOk() {
return ok;
}
public void setOk(boolean ok) {
this.ok = ok;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
@@ -0,0 +1,148 @@
package info.bukova.isspst.signapi;
import info.bukova.isspst.Constants;
import info.bukova.isspst.SessionData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* @author Pepa Rokos
*/
@Controller
public class SigningController {
@Autowired
private SessionData sessionData;
@Autowired
private JnlpGenerator jnlpGenerator;
@Autowired
private ServletContext context;
@RequestMapping(value="/sign/data", method= RequestMethod.GET)
public void dataForSign(HttpServletResponse response, HttpServletRequest request) {
SignData data = (SignData) sessionData.getProperty(Constants.KEY_SIGN_DATA);
ObjectOutputStream os = null;
try {
os = new ObjectOutputStream(response.getOutputStream());
response.setContentType("application/x-java-serialized-object");
os.writeObject(data);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@RequestMapping(value="/sign/data", method= RequestMethod.POST)
public void signedData(HttpServletRequest request, HttpServletResponse response) {
ObjectInputStream ois = null;
ObjectOutputStream os = null;
String error = null;
try {
ois = new ObjectInputStream(request.getInputStream());
SignData data = (SignData) ois.readObject();
sessionData.setProperty(Constants.KEY_SIGN_DATA, data);
} catch (IOException e) {
e.printStackTrace();
error = "IO error";
} catch (ClassNotFoundException e) {
e.printStackTrace();
error = "Loading error";
}
try {
SignUploadResponse resp = new SignUploadResponse();
if (error == null) {
resp.setOk(true);
} else {
resp.setOk(false);
resp.setErrorMessage(error);
}
os = new ObjectOutputStream(response.getOutputStream());
response.setContentType("application/x-java-serialized-object");
os.writeObject(resp);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@RequestMapping(value="/sign/signer.jnlp", method= RequestMethod.GET)
public void jnlp(HttpServletResponse response) {
byte[] data = jnlpGenerator.generate();
sendByte(response, data, "application/x-java-jnlp-file");
}
@RequestMapping(value="/sign/pdfsigner.jar", method= RequestMethod.GET)
public void pdfsigner(HttpServletResponse response) {
sendJar(response, "Linux");
}
@RequestMapping(value="/sign/pdfsignerWin.jar", method= RequestMethod.GET)
public void pdfsignerWin(HttpServletResponse response) {
sendJar(response, "Windows");
}
private void sendJar(HttpServletResponse response, String os) {
File inputJar;
if (os.startsWith("Windows")) {
inputJar = new File(context.getRealPath("/WEB-INF/signer/PDFSignerWin.jar"));
} else {
inputJar = new File(context.getRealPath("/WEB-INF/signer/PDFSigner.jar"));
}
try {
byte[] data = new byte[(int) inputJar.length()];
FileInputStream is = new FileInputStream(inputJar);
is.read(data);
sendByte(response, data, "application/java-archive");
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void sendByte(HttpServletResponse response, byte[] data, String contentType) {
ServletOutputStream os = null;
try {
os = response.getOutputStream();
response.setContentType(contentType);
response.setContentLength(data.length);
os.write(data);
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@@ -4,8 +4,10 @@ import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ReflectionTools {
@@ -78,4 +80,23 @@ public class ReflectionTools {
return getEntityFields(entity.getClass());
}
public static List<Field> getFields(Object entity) {
if (entity == null) {
return null;
}
return getFields(entity.getClass());
}
public static List<Field> getFields(Class<?> clazz) {
List<Field> ret = new ArrayList<Field>();
ret.addAll(Arrays.asList(clazz.getDeclaredFields()));
if (!clazz.getSuperclass().equals(Object.class)) {
ret.addAll(getFields(clazz.getSuperclass()));
}
return ret;
}
}
@@ -0,0 +1,103 @@
package info.bukova.isspst.storage;
import java.io.*;
/**
* Abstraktni třída pro práci se soubory.
*
* @author Pepa Rokos
*/
public abstract class AbstractFileStorage<T> implements FileStorage<T> {
protected void saveFileDataToPath(byte[] data, String path) {
File file = new File(path);
FileOutputStream os = null;
try {
os = new FileOutputStream(file);
os.write(data);
os.flush();
os.close();
} catch (FileNotFoundException e) {
throw new StorageException("File cannot be found: " + file.getName(), e.getCause());
} catch (IOException e) {
throw new StorageException("Cannot write file: " + file.getName(), e.getCause());
} finally {
try {
if (os != null) {
os.flush();
os.close();
}
} catch (IOException e) {
throw new StorageException("Cannot close stream", e.getCause());
}
}
}
protected void saveFileToPtah(File file, String path) {
File dest = new File(path + File.pathSeparator + file.getName());
FileOutputStream fos = null;
try {
fos = new FileOutputStream(dest);
fos.write(readFile(file));
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
throw new StorageException("Cannot move file: " + file.getName(), e.getCause());
} catch (IOException e) {
throw new StorageException("Cannot move file: " + file.getName(), e.getCause());
} finally {
if (fos != null) {
try {
fos.flush();
fos.close();
} catch (IOException e) {
throw new StorageException("Cannot close stream", e.getCause());
}
}
}
}
protected void removeFileByPath(String path) {
File f = new File(path);
if (!f.delete()) {
throw new StorageException("Cannot delete file: " + path);
}
}
protected byte[] fileDataFromPath(String path) {
File f = new File(path);
return readFile(f);
}
protected byte[] readFile(File file) {
byte[] out = new byte[(int) file.length()];
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
fis.read(out);
fis.close();
} catch (FileNotFoundException e) {
throw new StorageException("File cannot be found: " + file.getName(), e.getCause());
} catch (IOException e) {
throw new StorageException("Cannot read file: " + file.getName(), e.getCause());
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
throw new StorageException("Cannot close stream", e.getCause());
}
}
}
return out;
}
protected File fileFromPath(String path) {
return new File(path);
}
}
@@ -0,0 +1,72 @@
package info.bukova.isspst.storage;
import info.bukova.isspst.data.FileMetainfo;
import java.io.File;
/**
* Rozhraní servisního objektu pro práci s přílohami u záznamů. Přílohy jsou reprezentovány objektem FileMetainfo,
* kde je zobrazované jméno souboru, vygenerovaný GUID, pod kterým je soubor fyzicky uložen a MD5 součet používaný
* pro deduplikaci.
*
* @see info.bukova.isspst.data.FileMetainfo
*
* @author Pepa Rokos
*/
public interface DocumentFileStorage extends FileStorage<FileMetainfo> {
/**
* Uloží data předaná jako byte[] do uložiště příloh a vrátí metainformace.
* Metoda řeší deduplikaci souborů, takže v uložišti je fyzicky vždy jen jedna kopie.
*
* @see info.bukova.isspst.data.FileMetainfo
*
* @param data Data souboru
* @param name Zobrazovaný název souboru
* @return Metainformace o souboru
*/
public FileMetainfo saveAndCreateInfo(byte[] data, String name);
/**
* Uloží data předaná jako File do uložiště příloh a vrátí metainformace.
* Metoda řeší deduplikaci souborů, takže v uložišti je fyzicky vždy jen jedna kopie.
*
* @see info.bukova.isspst.data.FileMetainfo
*
* @param file Objekt reprezentující soubor
* @param name Zobrazovaný název souboru
* @return Metainformace o souboru
*/
public FileMetainfo saveAndCreateInfo(File file, String name);
/**
* Vrátí metainformace podle fyzické cesty v uložišti.
*
* @param path Cesta k souboru v uložišti
* @return Metainformace o souboru
*/
public FileMetainfo getMetainfoForPath(String path);
/**
* Bezpečně odstraní přílohu ze záznamu. Záznam o příloze odstraní z kolekce příloh a následně zavolá metodu
* removeFile(FileMetainfo info), která soubor fyzicky smaže, pokud není nikam linkovaný.
*
* @param entity Entita s přílohami
* @param metaInfo Příloha k odstranění
*/
public void removeAttachment(EntityWithAttachment entity, FileMetainfo metaInfo);
/**
* Bezpečně odstraní všechny přílohy ze záznamu.
*
* @param entity Entita s přílohami
*/
public void removeAllAttachments(EntityWithAttachment entity);
/**
* Uklidí soubory, na které neexistuje reference v databázi a z tabulky FILE_CONTENTS vymaže záznamy, na které
* neexistuje refernece z FILE_METAINFO
*/
public void purge();
}
@@ -0,0 +1,272 @@
package info.bukova.isspst.storage;
import info.bukova.isspst.dao.QueryDao;
import info.bukova.isspst.data.FileContent;
import info.bukova.isspst.data.FileMetainfo;
import info.bukova.isspst.services.fulltext.Extractor;
import info.bukova.isspst.services.fulltext.ExtractorFactory;
import org.apache.commons.codec.binary.Hex;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.UUID;
/**
* @author Pepa Rokos
*
* Třída pro práci s uložištěm příloh u záznamů. Na soubory příloh se odkazuje pomocí objektů FileMetainfo.
*
* @see info.bukova.isspst.data.FileMetainfo
*/
public class DocumentFileStorageImpl extends AbstractFileStorage<FileMetainfo> implements DocumentFileStorage {
private String rootPath;
@Autowired
private QueryDao queryDao;
/**
* Nastavuje kořenová adresář pro ukládání příloh. Nastavuje se absolutní cesta na filesystému serveru.
*
* @param rootPath kořenový adresář pro přílohy
*/
public void setRootPath(String rootPath) {
this.rootPath = rootPath;
}
@Override
public void saveFile(byte[] data, FileMetainfo fileID) {
String fileName = generateFileName(fileID.getFileName());
saveFileDataToPath(data, rootPath + File.separator + fileName);
fileID.setPathInFilesystem(fileName);
fileID.setContentType(MimeTypes.getContentType(data, fileName));
}
@Override
public void saveFile(File file, FileMetainfo fileID) {
String fileName = generateFileName(fileID.getFileName());
saveFileToPtah(file, rootPath + File.separator + fileName);
fileID.setPathInFilesystem(fileName);
fileID.setContentType(MimeTypes.getContentType(readFile(file), fileName));
}
private String generateFileName(String originalName) {
String extension = null;
String fileName = UUID.randomUUID().toString();
if (originalName != null && !originalName.isEmpty()) {
extension = MimeTypes.fileExtension(originalName);
}
if (extension != null) {
fileName = fileName + "." + extension;
}
return fileName;
}
private void extractContent(InputStream is, FileMetainfo fileID) {
Extractor extractor = ExtractorFactory.createExtractor(fileID.getContentType());
if (extractor != null) {
fileID.getContent().setPlainText(extractor.extract(is));
}
}
@Override
@Transactional
public void removeFile(FileMetainfo fileID) {
if (fileID.getPathInFilesystem() == null || fileID.getPathInFilesystem().isEmpty()) {
return;
}
if (infosForPath(fileID.getPathInFilesystem()).size() <= 1) {
removeFileByPath(rootPath + File.separator + fileID.getPathInFilesystem());
}
}
@Override
public void moveFile(String source, String destination) {
throw new UnsupportedOperationException();
}
@Override
public void createDirectory(String dir) {
throw new UnsupportedOperationException();
}
@Override
public byte[] fileData(FileMetainfo fileID) {
if (fileID.getPathInFilesystem() != null && !fileID.getPathInFilesystem().isEmpty()) {
return fileDataFromPath(rootPath + File.separator + fileID.getPathInFilesystem());
}
return null;
}
@Override
public File file(FileMetainfo fileID) {
if (fileID.getPathInFilesystem() != null && !fileID.getPathInFilesystem().isEmpty()) {
return fileFromPath(rootPath + File.separator + fileID.getPathInFilesystem());
}
return null;
}
@Override
public boolean dirExists(String path) {
throw new UnsupportedOperationException();
}
@Override
public String serverPath(FileMetainfo fileID) {
return "/api/dl/" + fileID.getPathInFilesystem() + "/" + fileID.getFileName();
}
@Override
@Transactional
public FileMetainfo saveAndCreateInfo(byte[] data, String name) {
FileMetainfo metaInfo = new FileMetainfo();
metaInfo.setFileName(name);
if (!checkForDuplicate(new ByteArrayInputStream(data), metaInfo)) {
saveFile(data, metaInfo);
extractContent(new ByteArrayInputStream(data), metaInfo);
}
return metaInfo;
}
@Override
@Transactional
public FileMetainfo saveAndCreateInfo(File file, String name) {
FileMetainfo metaInfo = new FileMetainfo();
metaInfo.setFileName(name);
try {
if (!checkForDuplicate(new FileInputStream(file), metaInfo)) {
saveFile(file, metaInfo);
extractContent(new FileInputStream(file), metaInfo);
}
} catch (FileNotFoundException e) {
//TODO: ošetřit
e.printStackTrace();
}
return metaInfo;
}
@Override
@Transactional
public FileMetainfo getMetainfoForPath(String path) {
if (infosForPath(path).isEmpty()) {
return null;
}
return infosForPath(path).get(0);
}
private List<FileMetainfo> infosForPath(String path) {
Query q = queryDao.getQuery("from FileMetainfo info where info.content.pathInFilesystem = :path");
q.setString("path", path);
return q.list();
}
private boolean checkForDuplicate(InputStream is, FileMetainfo info) {
String md5 = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] dataBytes = new byte[1024];
int nread = 0;
while ((nread = is.read(dataBytes)) != -1) {
md.update(dataBytes, 0, nread);
}
md5 = new String(Hex.encodeHex(md.digest()));
} catch (NoSuchAlgorithmException e) {
//TODO: ošetřit
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
}
Query q = queryDao.getQuery("select info from FileMetainfo info where info.md5 = :md5");
q.setString("md5", md5);
List<FileMetainfo> found = (List<FileMetainfo>) q.list();
if (!found.isEmpty()) {
FileMetainfo foundInfo = found.get(0);
info.setMd5(foundInfo.getMd5());
info.setContent(foundInfo.getContent());
return true;
} else {
info.setMd5(md5);
return false;
}
}
@Override
@Transactional
public void removeAttachment(EntityWithAttachment entity, FileMetainfo metaInfo) {
entity.removeAttachment(metaInfo);
removeFile(metaInfo);
}
@Override
@Transactional
public void removeAllAttachments(EntityWithAttachment entity) {
for (FileMetainfo metaInfo : entity.getAttachedFiles()) {
removeFile(metaInfo);
}
entity.getAttachedFiles().clear();
}
@Override
@Transactional
public void purge() {
File folder = new File(rootPath);
File[] allFiles = folder.listFiles();
Query q = queryDao.getQuery("from FileMetainfo");
List<FileMetainfo> infos = q.list();
for (File f : allFiles) {
boolean fileExists = false;
for (FileMetainfo info : infos) {
FileContent fileContent = info.getContent();
if ((fileContent != null) && f.isFile() && fileContent.getPathInFilesystem().equals(f.getName()))
{
fileExists = true;
break;
}
}
if (!fileExists && f.isFile())
{
f.delete();
}
}
SQLQuery sql = queryDao.getSession().createSQLQuery("delete from FILE_CONTENTS where ID not in(select CONTENT_ID from FILE_METAINFO)");
sql.executeUpdate();
}
}
@@ -0,0 +1,18 @@
package info.bukova.isspst.storage;
import info.bukova.isspst.data.FileMetainfo;
import java.util.List;
/**
* Rozhraní datových entit s přílohami.
*
* @author Pepa Rokos
*/
public interface EntityWithAttachment {
public List<FileMetainfo> getAttachedFiles();
public void addAttachment(FileMetainfo metaInfo);
public void removeAttachment(FileMetainfo metainfo);
}
@@ -2,17 +2,22 @@ package info.bukova.isspst.storage;
import java.io.File;
public interface FileStorage {
/**
* Rozhraní pro uložiště souborů
*
* @param <T> typ objektu, kterým se odkazuje na soubory
*/
public interface FileStorage<T> {
// public String getRootPath();
public void saveFile(byte[] data, String fileName);
public void saveFile(File file, String path);
public void removeFile(String fileName);
public void saveFile(byte[] data, T fileID);
public void saveFile(File file, T fileId);
public void removeFile(T fileID);
public void moveFile(String source, String destination);
public void createDirectory(String dir);
public byte[] fileData(String fileName);
public File file(String fileName);
public byte[] fileData(T fileID);
public File file(T fileID);
public boolean dirExists(String path);
public String serverPath(String fileName);
public String serverPath(T fileID);
}
@@ -1,14 +1,9 @@
package info.bukova.isspst.storage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import javax.servlet.ServletContext;
import java.io.*;
public class LocalFileStorage implements FileStorage {
public class LocalFileStorage extends AbstractFileStorage<String> {
private String rootPath;
private ServletContext context;
@@ -26,96 +21,27 @@ public class LocalFileStorage implements FileStorage {
}
@Override
public void saveFile(byte[] data, String fileName) {
public void saveFile(byte[] data, String fileID) {
saveFileDataToPath(data, getFullPath() + fileID);
}
File file = new File(getFullPath() + fileName);
FileOutputStream os = null;
try {
os = new FileOutputStream(file);
os.write(data);
os.flush();
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (os != null) {
os.flush();
os.close();
}
} catch (IOException e) {
throw new StorageException("Cannot close stream", e.getCause());
}
}
public void saveFile(File file, String fileID) {
saveFileToPtah(file, getFullPath() + fileID);
}
@Override
public void saveFile(File file, String path) {
File dest = new File(getFullPath() + path + File.pathSeparator + file.getName());
FileOutputStream fos = null;
try {
fos = new FileOutputStream(dest);
fos.write(fileData(file.getName()));
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
throw new StorageException("Cannot move file: " + file.getName(), e.getCause());
} catch (IOException e) {
throw new StorageException("Cannot move file: " + file.getName(), e.getCause());
} finally {
if (fos != null) {
try {
fos.flush();
fos.close();
} catch (IOException e) {
throw new StorageException("Cannot close stream", e.getCause());
}
}
}
public void removeFile(String fileID) {
removeFileByPath(getFullPath() + fileID);
}
@Override
public void removeFile(String fileName) {
File f = new File(getFullPath() + fileName);
if (!f.delete()) {
throw new StorageException("Cannot delete file: " + getFullPath()
+ fileName);
}
public byte[] fileData(String fileID) {
return fileDataFromPath(getFullPath() + fileID);
}
@Override
public byte[] fileData(String fileName) {
File f = new File(getFullPath() + fileName);
byte[] out = new byte[(int) f.length()];
FileInputStream fis = null;
try {
fis = new FileInputStream(f);
fis.read(out);
fis.close();
} catch (FileNotFoundException e) {
throw new StorageException("File cannot be found: " + fileName, e.getCause());
} catch (IOException e) {
throw new StorageException("Cannot read file: " + fileName, e.getCause());
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
throw new StorageException("Cannot close stream", e.getCause());
}
}
}
return out;
}
@Override
public File file(String fileName) {
return new File(getFullPath() + fileName);
public File file(String fileID) {
return fileFromPath(getFullPath() + fileID);
}
@Override
@@ -139,8 +65,8 @@ public class LocalFileStorage implements FileStorage {
}
@Override
public String serverPath(String fileName) {
return context.getRealPath(rootPath + File.separator + fileName);
public String serverPath(String fileID) {
return context.getRealPath(rootPath + File.separator + fileID);
}
}

Some files were not shown because too many files have changed in this diff Show More