Generátor faktur – Nette šablony + mPDF
- despiq
- Člen | 320
nova okna jsou nezadouci, a jde v nich stejne otevrit jen url, zalezi asi na tom jaka je to aplikace jestli verejna nebo nejakej backend, pokud backend muzes pdf ulozit a v novem okne odkazat pouze na url, nebo muzes pouzit filedownloader, nebo si udelas jeden action jen na generovani toho pdf s nakym klicem v sessne, nebo co ja vim, reseni je spousta
- JakubJarabica
- Gold Partner | 184
Ako to, že sa tam nedostane? Ja keď som to takýmto nepekným spôsobom skúšal, fungovalo to normálne – t.j. prebehol v pohode aj render. Skús to odkrokovať kde to skončí a prípadne pastni relevantný kód.
Ak však po vytvorení nerobíš redirect(a nielen bez redirectu, ale všeobecne) je dobré robiť takéto intenzívne operácie dávkovaním – v actione pridáš do dávky(napr. DB) požiadavku na vygenerovanie PDF, cron to PDF jednorázovo vygeneruje a vyčistí dávku. Generovať PDF v actionXXX je dosť riskantné, je treba myslieť na veľa vecí(Denial of service útok ak neautorizuješ usera, ak autorizuješ, zabezpečiť redirect atď).
Ďalšiu výhodu to má v tom, že na cron sa nevzťahuje max_execution_time, avšak ak spravíš dlhý dávkový súbor treba myslieť na nejakú „thread safety“(aby dva paralelné crony neobsluhovali ten istý požiadavok v dávke).
- rixi
- Člen | 109
Ospravedlnujem sa za hlupu otazku, ale neviem ako tento nette doplnok pouzit. Popis instalacie zacina tym ze mam stiahnuty archiv rozbalit do „app/controls“. Nebolo to myslene ulozenim suborov do presenters?
Skusal som vsak spominane umiestnenie, ako aj umiestnit subory do libs/Nette.addons/InvoiceControl a bez uspechu – Class ‚InvoiceControl‘ not found.
Umiestnenia mPDF som este neriesil, kedze mi nejde nacitatavat ani triedy InvoiceControl (po rucnom include nefungovalo vyvolanie dalsej instancie objektu a tak dookola).
Pouzivam Nette verziu s namespaces (PHP5.3).
Editoval rixi (23. 11. 2010 13:22)
- rixi
- Člen | 109
gmvasek wrote:
Pokud máš namespace verzi jak píšeš, tak nejspíš budeš muset volat \InvoiceControl
Mozete mi prosim napisat presne co mam definovat v use? Nikde som to nenasiel, hodilo by sa to dat do komentu pre neznalych. Netbeans IDE pri volani tried vzdy za o to sice postara, ale v niektorych pripadoch nie (nema ako).
skusal som
<?php
use Nette\Application\Control,
\InvoiceControl; // skusal som aj Nette\InvoiceControl
?>
- Ondřej Brejla
- Člen | 746
Zkus
$invoice = new \InvoiceControl(date('YmdHis'), 'Faktura - daňový doklad č.');
.
Žádné use
, IC
žádný jmenný prostor
nevyužívá.
Editoval Ondřej Brejla (23. 11. 2010 15:43)
- rixi
- Člen | 109
Takze uplne zle, vsetky moje doterajsie prispevky v tomto topicu mozte zmazat, pretoze spominane problemy vytvaralo nepremazane cache. Na toto som pri pridavani par novych Invoice tried do aplikacie vobec nemyslel, sorry chlapci.
Kazdopadne sa vyrojil dalsi problem s prekrocenou Allowed memory. mPdf kniznica ma vo verzii 5.0 po rozbaleni nekrestanskych 27MB. jasir dik za nasmerovanie, robotloader prestudujem.
Editoval rixi (23. 11. 2010 21:54)
- rixi
- Člen | 109
Dakujem za vsetky rady i autorovi, faktura konecne funguje.
Zhrniem problemy, ktore som mal, snad sa to bude niekomu hodit.
- netteloaders.txt (o loaderu v dokumentacii zrejme nic nie je, cerpat z fora)
- CurlyBracketsFilter::invoke (vid tento topic)
- use Nette\Application\Control; (nutne upravit, ak mate Nette verziu s namespaces)
- Ondřej Brejla
- Člen | 746
- –
- Na GitHubu je to správě už několik měsíců…zabalené(špatné?) knihovny jsem z doplňků stáhnul
- Jasně, je to psané pro PHP 5.2
- connic
- Člen | 3
Do presenteru jsem pro vyzkouseni dal tento kod:
// Creating new Invoice
$invoice = new InvoiceControl(date('YmdHis'), 'Faktura - danovy doklad c.');
// Definition of miscellaneous attributes
$invoice->setVariableSymbol('1234');
// Definition of DateTimes
$dateNow = new DateTime();
$invoice->setDateOfIssuance($dateNow);
$dateExp = new DateTime();
$dateExp->modify('+14 days');
$invoice->setExpirationDate($dateExp);
$invoice->setDateOfVatRevenueRecognition($dateNow);
// Definition of Participants
$supplier = new MyInvoiceParticipant('Jmeno', 'Ulice', '235', 'Mesto', '12000', '123456', 'CZ123456', '123456789 / 1111');
$customer = new MyInvoiceParticipant('Pepa Pivrnec', 'Nekde', '3', 'Praha 9 - Prosek', '19000', '', '', '123456789 / 1111');
$invoice->setSupplier($supplier);
$invoice->setCustomer($customer);
// Definition of Items
$item = new MyInvoiceItem('Testovaci item 1', 1, 900, 1.19, TRUE);
$invoice->addItem($item);
$invoice->addItems(array(
new MyInvoiceItem('Testovaci item 2', 1, 900, 1.19, TRUE),
new MyInvoiceItem('Testovaci item 3', 1, 900, 1.19, TRUE),
));
// Definition of new mPDF
// Set constant and include according to your directories!!
define('_MPDF_PATH', LIB_DIR . '/mpdf/');
include_once(_MPDF_PATH . 'mpdf.php');
//iso...don't know why...utf-8 didn't work
$mpdf = new mPDF('iso-8859-2');
// Exporting prepared Invoice to PDF
// (use second and third parameter for saving invoice as a file - same parameters like mPDF->Output())
$invoice->exportToPdf($mpdf, './faktury/faktura_' . $order_id . '.pdf');
PDF se ulozilo, ale vypada takto
Data z objektu $invoice se do templaty nepropsala.
- Ondřej Brejla
- Člen | 746
Jakou verzi Nette používáš? Vypadá to na neregistrovaný Latte filter…v novějších verzích se registruje sám, ve starších se musel registrovat. Viz tento commit
Editoval Ondřej Brejla (10. 2. 2011 15:48)
- cclass
- Člen | 8
Práve skúšam túto komponentu a vyhadzuje chybu
Nette\Templates\LatteException
Template is not valid UTF-8 stream in
…\OndrejBrejla-Nette-InvoiceControl-5cb2fd4\InvoiceControl.phtml
A súbor InvoiceControl mám podľa PSPad-u v UTF-8. Neviete kde hľadať chybu ? Nette mám poslednú 2.0 alpha 2 verziu. Namespace pre PHP 5.3 som v kódoch rozšírenia opravil.
Editoval cclass (13. 2. 2011 21:34)
- cigi
- Člen | 1
cclass napsal(a):
Práve skúšam túto komponentu a vyhadzuje chybu
Nette\Templates\LatteException
Template is not valid UTF-8 stream in …\OndrejBrejla-Nette-InvoiceControl-5cb2fd4\InvoiceControl.phtmlA súbor InvoiceControl mám podľa PSPad-u v UTF-8. Neviete kde hľadať chybu ? Nette mám poslednú 2.0 alpha 2 verziu. Namespace pre PHP 5.3 som v kódoch rozšírenia opravil.
Mel jsem stejny problem. Chyba je na radku 45 pred <html> je tam nejaky paznak, ktery neni v PSPadu videt. Snad to nekomu pomuze…
*}
´╗┐<html>
<head>
- Pavel Kouřil
- Člen | 128
Dá se nastavit nějak jiný template na použití než defaultní?
Chtěl bych knihovnu používat i pro proformy i pro normální faktury, což
znamená i rozdílné soubory s templaty.
- Ondřej Brejla
- Člen | 746
Cca rok jsem nic v Nette pořádně nedělal, ale co zkusit přesunout vytváření ‚InvoiceControl‘ do továrničky presenteru, tedy:
public function createComponentInvoice() {
$invoice = new InvoiceControl();
// tady provest vsechno nastaveni
return $invoice;
}
a v akci si ji vytáhnout a zavolat ji s mPdf, tedy:
public function actionGenerate() {
define('_MPDF_PATH', LIBS_DIR . '/mpdf2_5/');
include_once(LIBS_DIR . '/mpdf2_5/mpdf.php');
$mpdf = new mPDF('iso-8859-2');
$this['invoice']->exportToPdf($mpdf);
}
Možná to bude jako workaround stačit.
- aGr
- Člen | 45
Návod pro zprovoznění InvoiceControl na Nette 2.0:
- stáhnout zde
- rozbalit např. do app/components/
a pak použít kód napsaný výše, s malou úpravou, tedy:
public function createComponentInvoice() {
$invoice = new \InvoiceControl();
// tady provest vsechno nastaveni - viz napr. https://componette.org/search/?q=invoice-control
return $invoice;
}
public function actionGenerate() {
define('_MPDF_PATH', LIBS_DIR . '/mpdf2_5/');
include_once(LIBS_DIR . '/mpdf2_5/mpdf.php');
$mpdf = new mPDF('utf-8');
$this['invoice']->exportToPdf($mpdf); //což je totéž jako $this->getComponent('invoice')->...
}
Určitě to jde i jinak, možná i přímo bez tohoto workaroundu, ale už jsem se tím nezabýval. Ty úpravy v kódu byly maličkosti (víceméně doplnění „use Nette\Object“), ale přišlo mi jednodušší to uploadnout znovu, než popisovat změny (snad to autorovi nevadí :)).
Info ohledně zprovoznění mPDF zde na fóru taky je, pohledejte. Nezapomeňte vyloučit celé mPDF z robotLoaderu.
Editoval aGr (21. 4. 2012 19:50)
- Ondřej Brejla
- Člen | 746
Autorovi nic nevadí, sám by doplněk rád aktualizoval, nicméně na to nemá mnoho času :(
- Ondřej Brejla
- Člen | 746
Tak jsem si našel čas. Komponenta prochází poněkud bouřlivějším refactoringem. Changes na: https://github.com/…mmits/master
Patrně teď bude poněkud nestabilní ;) Nicméně se ji pokusím co nejdřív ustabilnit :)
Editoval Ondřej Brejla (30. 4. 2012 15:04)
- Ondřej Brejla
- Člen | 746
Neboj, už to mám předělané, snad vše. Během dneška aktualizuji stránky v Doplňcích. S příkladem použití, atd.
- Ondřej Brejla
- Člen | 746
Tak jsem to upravil, nová verze je hotová a veškerý potřebný popis je na stránce doplňku.
- talpa
- Člen | 44
Modifikace Eciovni, jiz je mozne nastavit data kdykoliv si zamanete i po CreateComponent
<?php
/**
* Initializes new Invoice. modify by Talpa we can set constructor without param $data
*
* @param string $id
* @param string $title
*/
public function __construct(Data $data = null) {
$this->data = $data;
}
/**
* We can setData after CreateComponents
*
* @param Data $data
*/
public function setData(Data $data){
$this->data = $data;
$this->generate($this->template);
}
?>
implementace v ActionGenerate pak shodna az na
<?php
$this['eciovni']->setData($data);
?>
konstruktor v createComponent je samozrejme mozne nedavat data, diky tomu, ze je komponente ciste napsana, diky autorovi
Editoval talpa (12. 5. 2012 11:03)
- Ondřej Brejla
- Člen | 746
Díky, každopádně se mi ta modifikace a toto použití nelíbí, takže to do ofic verze implementovat nebudu. Vyrábíš mutable objekt, navíc setData metoda volá generate, atd.
Můžeš sem dát přesně ten kód, Presenter, kde je takovéto použití nutné? Jen pro zajímavost. Díky.
- Vojtěch Vondra
- Člen | 11
Jde o to, že použití je krkolomné. Do továrničky createComponentInvoice() dynamická data jednoduše a čistě neprocpeš. Ukázkový příklad si zjednodušuješ tím, že tam dáváš statická data.
Měl bys ukázku jak fakturu naplnit např. řádkem z databáze? To bych logicky chtěl mít v action u presenteru, což mě ale nutí opustit továrničky a používat addComponent.
Jinak moc díky za port na Nette2, hodí se!
- Ondřej Brejla
- Člen | 746
Data
objekt můžeš vyrobit normálně v akci, šoupnout ho do
fieldu presenteru a v továrně ho pak předat, ne? To je, imho, normální
způsob předávání dat továrnám. Nebo býval, nevím jak moc se tento
přístup za poslední rok změnil ;)
- Ondřej Brejla
- Člen | 746
Ještě bych to mohl zkusit přepsat tak, aby se vstupní data předávaly
až render(Data $data)
metodě (a samozřejmě
exportToPdf()
metodě). V akci by sis je pak připravil, předal
do šablony a v šabloně do makra. Promyslím a vyzkouším.
- Ondřej Brejla
- Člen | 746
Přidal jsem renderData()
metodu. Viz github.
Export metodu zatím upravovat nebudu.
- ajda2
- Člen | 66
Zdravím,
chci se zeptat, jak je to s licencí při použití mPDF. Ta je v pod GNU GPL
2. Znamená to, že když mPDF použiji (beze změny, jen API) tak musím
zveřejnit celou aplikaci taky pod GNU GPL 2?
Chci knihovnu použít v komerčním projektu.
Tohle se bude týkat i použití tohoto doplňku. Může se použít pro
komerční neveřejné účely?
Ze znění licence mi to totiž není jasné a v diskuzích se názory také
různí. Někde tvrdí, že musím zveřejnit kódy, pouze pokud je změním.
Jinde zase, že celou aplikaci, pokud použiji něco pod GNU GPL 2.
Díky za odpověď.
- visitor
- Člen | 22
- dotazy
- Proč komponenta nepodporuje Způsob úhrady
- Proč komponenta nepodporuje Číslo objednávky
- Proč komponenta nepodporuje Neplátce DPH
Tyto věci jsem si tam musel dopsat jak minule, tak nyní. Přijdou mi jako normální, ale komponenta je pomíjí…
- Programování
V nové verzi jsem se nějak zamotal…
Jak naplním komponentu (továrníčku) daty? Potřebuji nějaké rozhraní kde
předám číslo faktury a ona se mi naplní.
Nyní buď neumím do továrníčky tuto informaci ROZUMNĚ předat (nejspíše moje neznalost) a nebo nevím.
Na druhou stranu pokud použiji v actionGenerate() funkci $this[‚eciovni‘]->renderData($data);, tak nedokážu fakturu vyexportovat do PDF.
Nyní moje zacyklená verze kde nemohu všechno je v tomto stavu:
protected function createComponentEciovni() {
return new Eciovni();
}
public function actionTisk($cislo_faktury, $typ) {
$mpdf = new \mPDF('utf-8');
$row = \dibi::fetch('SELECT * FROM [faktury_hlavicka] WHERE [cislo_faktury] = %i', $cislo_faktury);
$cisloFaktury = $row['cislo_faktury'];
$variableSymbol = $row['variabilni_symbol'];
//$invoice->setPaymentMethod($row['forma_uhrady']);
//$invoice->setObjednavka($row['objednavka']);
$dateNow = new \DateTime($row['datum_vystaveni']);
$dateExp = new \DateTime($row['datum_splatnosti']);
$dateOfVatRevenueRecognition = new \DateTime($row['datum_uskutecneni_zdanitelneho_plneni']);
$rowSupplier = \dibi::fetch('SELECT * FROM [adresar] WHERE [IC] = %i LIMIT 1', $row['IC_dodavatel']);
$rowCustomer = \dibi::fetch('SELECT * FROM [adresar] WHERE [IC] = %i LIMIT 1', $row['IC_odberatel']);
$supplierBuilder = new ParticipantBuilder($rowSupplier['titul_pred'] . ' ' . $rowSupplier['jmeno'] . ' ' . $rowSupplier['prijmeni'] . ' ' . $rowSupplier['titul_za'], $rowSupplier['ulice'], '', $rowSupplier['mesto'], $rowSupplier['psc']);
$supplier = $supplierBuilder->setIn($rowSupplier['IC'])->setTin($rowSupplier['DIC'])->setAccountNumber($rowSupplier['cislo_uctu'])->build();
$customerBuilder = new ParticipantBuilder($rowCustomer['titul_pred'] . ' ' . $rowCustomer['jmeno'] . ' ' . $rowCustomer['prijmeni'] . ' ' . $rowCustomer['titul_za'], $rowCustomer['ulice'], '', $rowCustomer['mesto'], $rowCustomer['psc']);
$customer = $customerBuilder->setIn($rowCustomer['IC'])->setTin($rowCustomer['DIC'])->setAccountNumber($rowCustomer['cislo_uctu'])->build();
$row_i = \dibi::fetchAll('SELECT * FROM [faktury_polozky] WHERE [cislo_faktury] = %i ORDER BY [id]', $row['cislo_faktury']);
$items = array();
foreach ($row_i as $item) {
$items[] = new ItemImpl($item['nazev'], $item['pocet_jednotek'], $item['jednotkova_cena'], TaxImpl::fromPercent(22));
}
$dataBuilder = new DataBuilder($cisloFaktury, 'Daňový doklad, č.', $supplier, $customer, $dateExp, $dateNow, $items);
$dataBuilder->setVariableSymbol($variableSymbol)->setDateOfVatRevenueRecognition($dateOfVatRevenueRecognition);
$data = $dataBuilder->build();
//$this['eciovni']->renderData($data);
$this['eciovni']->exportToPdf($mpdf);
/* az rozchodim jednu vec tak pak rozchodim nahled + generaci
if ($typ === 'pdf') {
$this['eciovni']->exportToPdf($mpdf, $cisloFaktury . '.pdf', 'D');
} else {
$this['eciovni']->exportToPdf($mpdf);
}*/
}
No a následně ještě střídavě dle použití mažu a vytvářím soubor generate.latte a to ještě v kombinacích prázdný nebo s {control eciovni}. Ale to asi už vychytám až rozchodím to plnění daty.
A teda když už píši… Hosterovi se protočily panenky, když mi musel povolit 512 MB RAM, abych vygeneroval fakturu o jednom řádku :).
- Ondřej Brejla
- Člen | 746
visitor napsal(a):
- dotazy
- Proč komponenta nepodporuje Způsob úhrady
Protože jsem tuto volbu při psaní komponenty nepotřeboval.
- Proč komponenta nepodporuje Číslo objednávky
Protože jsem tuto volbu při psaní komponenty nepotřeboval.
- Proč komponenta nepodporuje Neplátce DPH
Protože jsem tuto volbu při psaní komponenty nepotřeboval.
Tyto věci jsem si tam musel dopsat jak minule, tak nyní. Přijdou mi jako normální, ale komponenta je pomíjí…
- Programování
V nové verzi jsem se nějak zamotal…
Jak naplním komponentu (továrníčku) daty? Potřebuji nějaké rozhraní kde předám číslo faktury a ona se mi naplní.Nyní buď neumím do továrníčky tuto informaci ROZUMNĚ předat (nejspíše moje neznalost) a nebo nevím.
Data se předávají v konstruktoru.
new Eciovni(Data $data = NULL)
, případně v render fázi přes
šablonu (metoda renderData(Data $data)
).
Na druhou stranu pokud použiji v actionGenerate() funkci $this[‚eciovni‘]->renderData($data);, tak nedokážu fakturu vyexportovat do PDF.
renderData()
se volá v šabloně
{control eciovni:data $data}
(alespoň myslím, že je ten formát
takhle), ne v presenteru.
Nyní moje zacyklená verze kde nemohu všechno je v tomto stavu:
protected function createComponentEciovni() { return new Eciovni(); } public function actionTisk($cislo_faktury, $typ) { $mpdf = new \mPDF('utf-8'); $row = \dibi::fetch('SELECT * FROM [faktury_hlavicka] WHERE [cislo_faktury] = %i', $cislo_faktury); $cisloFaktury = $row['cislo_faktury']; $variableSymbol = $row['variabilni_symbol']; //$invoice->setPaymentMethod($row['forma_uhrady']); //$invoice->setObjednavka($row['objednavka']); $dateNow = new \DateTime($row['datum_vystaveni']); $dateExp = new \DateTime($row['datum_splatnosti']); $dateOfVatRevenueRecognition = new \DateTime($row['datum_uskutecneni_zdanitelneho_plneni']); $rowSupplier = \dibi::fetch('SELECT * FROM [adresar] WHERE [IC] = %i LIMIT 1', $row['IC_dodavatel']); $rowCustomer = \dibi::fetch('SELECT * FROM [adresar] WHERE [IC] = %i LIMIT 1', $row['IC_odberatel']); $supplierBuilder = new ParticipantBuilder($rowSupplier['titul_pred'] . ' ' . $rowSupplier['jmeno'] . ' ' . $rowSupplier['prijmeni'] . ' ' . $rowSupplier['titul_za'], $rowSupplier['ulice'], '', $rowSupplier['mesto'], $rowSupplier['psc']); $supplier = $supplierBuilder->setIn($rowSupplier['IC'])->setTin($rowSupplier['DIC'])->setAccountNumber($rowSupplier['cislo_uctu'])->build(); $customerBuilder = new ParticipantBuilder($rowCustomer['titul_pred'] . ' ' . $rowCustomer['jmeno'] . ' ' . $rowCustomer['prijmeni'] . ' ' . $rowCustomer['titul_za'], $rowCustomer['ulice'], '', $rowCustomer['mesto'], $rowCustomer['psc']); $customer = $customerBuilder->setIn($rowCustomer['IC'])->setTin($rowCustomer['DIC'])->setAccountNumber($rowCustomer['cislo_uctu'])->build(); $row_i = \dibi::fetchAll('SELECT * FROM [faktury_polozky] WHERE [cislo_faktury] = %i ORDER BY [id]', $row['cislo_faktury']); $items = array(); foreach ($row_i as $item) { $items[] = new ItemImpl($item['nazev'], $item['pocet_jednotek'], $item['jednotkova_cena'], TaxImpl::fromPercent(22)); } $dataBuilder = new DataBuilder($cisloFaktury, 'Daňový doklad, č.', $supplier, $customer, $dateExp, $dateNow, $items); $dataBuilder->setVariableSymbol($variableSymbol)->setDateOfVatRevenueRecognition($dateOfVatRevenueRecognition); $data = $dataBuilder->build(); //$this['eciovni']->renderData($data); $this['eciovni']->exportToPdf($mpdf); /* az rozchodim jednu vec tak pak rozchodim nahled + generaci if ($typ === 'pdf') { $this['eciovni']->exportToPdf($mpdf, $cisloFaktury . '.pdf', 'D'); } else { $this['eciovni']->exportToPdf($mpdf); }*/ }
Vyrobený Data
objekt si ulož do fieldu
($this->data = $data
) a v createComponent nevytvářej
prázdný objekt Eciovni, ale new Eciovni($this->data)
. V akci
pak vesele volej exportToPdf
.
No a následně ještě střídavě dle použití mažu a vytvářím soubor generate.latte a to ještě v kombinacích prázdný nebo s {control eciovni}. Ale to asi už vychytám až rozchodím to plnění daty.
A teda když už píši… Hosterovi se protočily panenky, když mi musel povolit 512 MB RAM, abych vygeneroval fakturu o jednom řádku :).
To je ovšem problém mPDF
, ne komponenty :)
- Ondřej Brejla
- Člen | 746
visitor napsal(a):
- dotazy
- Proč komponenta nepodporuje Způsob úhrady
- Proč komponenta nepodporuje Číslo objednávky
- Proč komponenta nepodporuje Neplátce DPH
Btw. nic ti nebrání udělat patche a poslat pull requesty.
- fojta
- Člen | 24
Zdravim,
mam takovej problem, potrebuju vlozit razitko do faktury zmenim src na
{$basePath}/data/cc/razitko.jpg
Kdyz si ulozim fakturu na localu tak se me tam obrazek ukaze, ale pokud to
provadim na serveru tak nic :/
Pokud si ji necham zobrazit v prohlizeci tak logo take neni videt.
Obrazek se na te adrese obravdu nachazi, zkousel jsem i misto {$basePath} dat {$baseUrl}, lokal funguje server ne.
Diky