diff --git a/.docs/README.md b/.docs/README.md index f906437..e070be5 100644 --- a/.docs/README.md +++ b/.docs/README.md @@ -6,159 +6,121 @@ - [Setup](#setup) - [Preview with minimal setup](#preview-with-minimal-setup) - [Entities](#entities) -- [Customizing](#customizing) -- [Translation](#translation) - [Generating invoices](#generating-invoices) -- [Generating preview](#generating-preview) - [Neon configuration](#neon-configuration) -- [Examples](#examples) +- [Templates](#templates) ## Benchmark -Average output is ~20ms +Average output is ~5ms ## Setup -```php -$company = new Contributte\Invoice\Data\Company('John Doe', 'Los Angeles', 'Cavetown', '720 55', 'USA', '0123456789', 'CZ0123456789'); -$invoice = new Contributte\Invoice\Invoice($company); +```php +$invoice = new Contributte\Invoice\Invoice(); + +$dataProvider = new Contributte\Invoice\Provider\DataProvider( + new Company('Contributte', 'Prague', 'U haldy', '110 00', 'Czech Republic', 'CZ08304431', '08304431'), + [new Account('CZ4808000000002353462013')], + new Currency('Kč', ':price :currency'), // change default format $ 1000 to 1000 Kč +); ``` ## Preview with minimal setup ```php -$invoice = new Contributte\Invoice\Invoice(Contributte\Invoice\Preview\PreviewFactory::createCompany()); +use Contributte\Invoice\Preview\PreviewFactory; -$invoice->send(Contributte\Invoice\Preview\PreviewFactory::createCustomer(), Contributte\Invoice\Preview\PreviewFactory::createOrder()); +$invoice->send(PreviewFactory::createOrder()); ``` ## Entities -We have following entities: Company (seller), Customer, Account (bank account), Payment Info, Order and Item. +We have following entities: Company (seller), Customer, Account (bank account), Payment Info, Currency, Timestamps, Order and Item. ### Company - seller ```php -$company = new Contributte\Invoice\Data\Company('John Doe', 'Los Angeles', 'Cavetown', '720 55', 'USA', '0123456789', 'CZ0123456789'); +use Contributte\Invoice\Data\Company; + +$company = new Company('Contributte', 'Prague', 'U haldy', '110 00', 'Czech Republic', 'CZ08304431', '08304431'); ``` ### Customer ```php -$customer = new Contributte\Invoice\Data\Customer('John Doe', 'Los Angeles', 'Cavetown', '720 55', 'USA'); +use Contributte\Invoice\Data\Customer; + +$customer = new Customer('John Doe', 'Los Angeles', 'Cavetown', '720 55', 'USA', 'CZ08304431', '08304431'); ``` ### Account - bank account ```php -$account = new Contributte\Invoice\Data\Account('1111', 'CZ4808000000002353462015', 'GIGACZPX'); +use Contributte\Invoice\Data\Account; + +$account = new Account('CZ4808000000002353462013'); ``` ### Payment info ```php -$payment = new Contributte\Invoice\Data\PaymentInformation('Kč', '0123456789', '1234', 0.21); +use Contributte\Invoice\Data\Account; +use Contributte\Invoice\Data\PaymentInformation; + +$payment = new PaymentInformation( + [new Account('CZ4808000000002353462013')], +); ``` ### Order ```php -$order = new Contributte\Invoice\Data\Order('20160001', new \DateTime('+ 14 days'), $account, $payment); +use Contributte\Invoice\Data\Account; +use Contributte\Invoice\Data\Company; +use Contributte\Invoice\Data\Customer; +use Contributte\Invoice\Data\Order; +use Contributte\Invoice\Data\PaymentInformation; +use Contributte\Invoice\Data\Timestamps; + +$order = new Order( + date('Y') . '0001', + '15.000,00', + new Company('Contributte', 'Prague', 'U haldy', '110 00', 'Czech Republic', 'CZ08304431', '08304431'), + new Customer('John Doe', 'Los Angeles', 'Cavetown', '720 55', 'USA', 'CZ08304431', '08304431'), + new PaymentInformation( + [new Account('CZ4808000000002353462013')], + ), + new Timestamps( + (new DateTime())->format('Y-m-d'), + (new DateTime('+ 1 week'))->format('Y-m-d'), + ), +); ``` ### Item ```php -$order->addItem('Logitech G700s Rechargeable Gaming Mouse', 4, 1790); -``` - -## Customizing - -Customize numbers, money or date - -```php -use Contributte\Invoice\IFormatter; - -class CustomFormatter implements IFormatter { - -} -``` - -Customize colors, fonts: - -```php -$template = new Contributte\Invoice\Templates\DefaultTemplate(); - -$template->setEven(new Contributte\Invoice\Renderers\Color(0, 0, 0)); -$template->setFont(new Contributte\Invoice\Renderers\Color(0, 0, 0)); -$template->setEven(new Contributte\Invoice\Renderers\Color(0, 0, 0)); -$template->setOdd(new Contributte\Invoice\Renderers\Color(0, 0, 0)); - -$invoice = new Contributte\Invoice\Invoice($company, $template); -``` - -## Translation - -First, create class that implements ITranslator - -```php -class Translator implements Contributte\Invoice\ITranslator { - - private static $translations = [ - 'subscriber' => 'Subscriber', - 'vat' => 'VAT number', - 'vaTin' => 'VATIN', - 'date' => 'Date', - 'invoice' => 'Invoice', - 'invoiceNumber' => 'Invoice number', - 'taxPay' => '', - 'notTax' => 'VAT unregistered', - 'paymentData' => 'Payment information', - 'page' => 'Page', - 'from' => '/', - 'totalPrice' => 'Total price', - 'item' => 'Item', - 'count' => 'Quantity', - 'pricePerItem' => 'Price per item', - 'total' => 'Total', - 'accountNumber' => 'Account number', - 'swift' => 'Swift', - 'iban' => 'Iban', - 'varSymbol' => 'Variable symbol', - 'constSymbol' => 'Constant symbol', - 'tax' => 'TAX', - 'subtotal' => 'Subtotal', - 'dueDate' => 'Due date', - ]; - - public function translate(string $message): string { - return self::$translations[$message]; - } +use Contributte\Invoice\Data\Item; -} -``` +$order->addInlineItem('Logitech G700s Rechargeable Gaming Mouse', '1.790,00', 4, '7.160,00'); -and pass it to the invoice and template +// or -```php -$invoice = new Contributte\Invoice\Invoice($company, new Contributte\Invoice\Templates\DefaultTemplate(new Translator())); +$order->addItem(new Item('Logitech G700s Rechargeable Gaming Mouse', '1.790,00', 4, '7.160,00')); ``` ## Generating invoices ```php -$invoice = new Contributte\Invoice\Invoice($company); - header('Content-Type: application/pdf; charset=utf-8'); -echo $invoice->create($customer, $order); +echo $invoice->create($order); ``` method `Invoice::send()` automatically sets content-type header ```php -$invoice = new Contributte\Invoice\Invoice($company); - -$invoice->send($customer, $order); +$invoice->send($order); ``` if you use nette, recommended way is @@ -167,20 +129,12 @@ if you use nette, recommended way is class CustomPresenter { public function actionPreview() { - $invoice = new Contributte\Invoice\Invoice($company); - - $this->sendResponse($invoice->createResponse($customer, $order)); + $this->sendResponse($this->invoice->createResponse($order)); } } ``` -## Generating preview - -```php -$invoice->send(Contributte\Invoice\Preview\PreviewFactory::createCustomer(), Contributte\Invoice\Preview\PreviewFactory::createOrder()); -``` - ## Neon configuration ```neon @@ -201,10 +155,14 @@ invoice: isTax: bool ``` -## Examples +## Templates + +## Paraiso +Single page: +![single page](/img/paraiso.png?raw=true) -First page: -![first page](http://i.imgbox.com/pwFByZ1L.jpg) +Multiple pages: +![multiple pages](/img/paraiso-paginator.png?raw=true) -Second page: -![second page](http://i.imgbox.com/ebrwXldf.jpg) +Greyscale: +![greyscale](/img/paraiso-greyscale.png?raw=true) diff --git a/.docs/img/paraiso-greyscale.png b/.docs/img/paraiso-greyscale.png new file mode 100644 index 0000000..7b1e504 Binary files /dev/null and b/.docs/img/paraiso-greyscale.png differ diff --git a/.docs/img/paraiso-paginator.png b/.docs/img/paraiso-paginator.png new file mode 100644 index 0000000..9f372b6 Binary files /dev/null and b/.docs/img/paraiso-paginator.png differ diff --git a/.docs/img/paraiso.png b/.docs/img/paraiso.png new file mode 100644 index 0000000..e168625 Binary files /dev/null and b/.docs/img/paraiso.png differ diff --git a/.gitignore b/.gitignore index 3f0b208..57a9d34 100755 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ vendor composer.lock + +## workspace +workspace diff --git a/assets/OpenSans-Regular.php b/assets/OpenSans-Regular.php deleted file mode 100644 index 0f93bfa..0000000 --- a/assets/OpenSans-Regular.php +++ /dev/null @@ -1,27 +0,0 @@ - 765, 'Descent' => -240, 'CapHeight' => 714, 'Flags' => 32, 'FontBBox' => '[-550 -271 1204 1048]', 'ItalicAngle' => 0, 'StemV' => 70, 'MissingWidth' => 600]; -$up = -75; -$ut = 50; -$cw = [ - chr(0) => 600, chr(1) => 600, chr(2) => 600, chr(3) => 600, chr(4) => 600, chr(5) => 600, chr(6) => 600, chr(7) => 600, chr(8) => 600, chr(9) => 600, chr(10) => 600, chr(11) => 600, chr(12) => 600, chr(13) => 600, chr(14) => 600, chr(15) => 600, chr(16) => 600, chr(17) => 600, chr(18) => 600, chr(19) => 600, chr(20) => 600, chr(21) => 600, - chr(22) => 600, chr(23) => 600, chr(24) => 600, chr(25) => 600, chr(26) => 600, chr(27) => 600, chr(28) => 600, chr(29) => 600, chr(30) => 600, chr(31) => 600, ' ' => 260, '!' => 267, '"' => 401, '#' => 646, '$' => 572, '%' => 823, '&' => 730, '\'' => 221, '(' => 296, ')' => 296, '*' => 552, '+' => 572, - ',' => 245, '-' => 322, '.' => 266, '/' => 367, '0' => 572, '1' => 572, '2' => 572, '3' => 572, '4' => 572, '5' => 572, '6' => 572, '7' => 572, '8' => 572, '9' => 572, ':' => 266, ';' => 266, '<' => 572, '=' => 572, '>' => 572, '?' => 429, '@' => 899, 'A' => 633, - 'B' => 648, 'C' => 631, 'D' => 729, 'E' => 556, 'F' => 516, 'G' => 728, 'H' => 738, 'I' => 279, 'J' => 267, 'K' => 614, 'L' => 519, 'M' => 903, 'N' => 754, 'O' => 779, 'P' => 602, 'Q' => 779, 'R' => 618, 'S' => 549, 'T' => 553, 'U' => 728, 'V' => 595, 'W' => 926, - 'X' => 577, 'Y' => 560, 'Z' => 571, '[' => 329, '\\' => 367, ']' => 329, '^' => 542, '_' => 448, '`' => 577, 'a' => 556, 'b' => 613, 'c' => 476, 'd' => 613, 'e' => 561, 'f' => 339, 'g' => 548, 'h' => 614, 'i' => 253, 'j' => 253, 'k' => 525, 'l' => 253, 'm' => 930, - 'n' => 614, 'o' => 604, 'p' => 613, 'q' => 613, 'r' => 408, 's' => 477, 't' => 353, 'u' => 614, 'v' => 501, 'w' => 778, 'x' => 524, 'y' => 504, 'z' => 468, '{' => 379, '|' => 551, '}' => 379, '~' => 572, chr(127) => 600, chr(128) => 590, chr(129) => 600, chr(130) => 245, chr(131) => 600, - chr(132) => 405, chr(133) => 784, chr(134) => 502, chr(135) => 510, chr(136) => 600, chr(137) => 1202, chr(138) => 549, chr(139) => 304, chr(140) => 549, chr(141) => 553, chr(142) => 571, chr(143) => 571, chr(144) => 600, chr(145) => 170, chr(146) => 170, chr(147) => 350, chr(148) => 350, chr(149) => 376, chr(150) => 500, chr(151) => 1000, chr(152) => 600, chr(153) => 776, - chr(154) => 477, chr(155) => 304, chr(156) => 477, chr(157) => 353, chr(158) => 468, chr(159) => 468, chr(160) => 260, chr(161) => 592, chr(162) => 592, chr(163) => 523, chr(164) => 572, chr(165) => 633, chr(166) => 551, chr(167) => 516, chr(168) => 577, chr(169) => 832, chr(170) => 549, chr(171) => 497, chr(172) => 572, chr(173) => 322, chr(174) => 832, chr(175) => 571, - chr(176) => 428, chr(177) => 572, chr(178) => 197, chr(179) => 261, chr(180) => 577, chr(181) => 619, chr(182) => 655, chr(183) => 266, chr(184) => 227, chr(185) => 556, chr(186) => 477, chr(187) => 497, chr(188) => 519, chr(189) => 577, chr(190) => 253, chr(191) => 468, chr(192) => 618, chr(193) => 633, chr(194) => 633, chr(195) => 633, chr(196) => 633, chr(197) => 519, - chr(198) => 631, chr(199) => 631, chr(200) => 631, chr(201) => 556, chr(202) => 556, chr(203) => 556, chr(204) => 556, chr(205) => 279, chr(206) => 279, chr(207) => 729, chr(208) => 722, chr(209) => 754, chr(210) => 754, chr(211) => 779, chr(212) => 779, chr(213) => 779, chr(214) => 779, chr(215) => 572, chr(216) => 618, chr(217) => 728, chr(218) => 728, chr(219) => 728, - chr(220) => 728, chr(221) => 560, chr(222) => 553, chr(223) => 622, chr(224) => 408, chr(225) => 556, chr(226) => 556, chr(227) => 556, chr(228) => 556, chr(229) => 253, chr(230) => 476, chr(231) => 476, chr(232) => 476, chr(233) => 561, chr(234) => 561, chr(235) => 561, chr(236) => 561, chr(237) => 253, chr(238) => 253, chr(239) => 613, chr(240) => 613, chr(241) => 614, - chr(242) => 614, chr(243) => 604, chr(244) => 604, chr(245) => 604, chr(246) => 604, chr(247) => 572, chr(248) => 408, chr(249) => 614, chr(250) => 614, chr(251) => 614, chr(252) => 614, chr(253) => 504, chr(254) => 353, chr(255) => 253, -]; -$enc = 'cp1250'; -$diff = '131 /.notdef 136 /.notdef 140 /Sacute /Tcaron 143 /Zacute 152 /.notdef 156 /sacute /tcaron 159 /zacute 161 /caron /breve /Lslash 165 /Aogonek 170 /Scedilla 175 /Zdotaccent 178 /ogonek /lslash 185 /aogonek /scedilla 188 /Lcaron /hungarumlaut /lcaron /zdotaccent /Racute 195 /Abreve 197 /Lacute /Cacute 200 /Ccaron 202 /Eogonek 204 /Ecaron 207 /Dcaron /Dcroat /Nacute /Ncaron 213 /Ohungarumlaut 216 /Rcaron /Uring 219 /Uhungarumlaut 222 /Tcommaaccent 224 /racute 227 /abreve 229 /lacute /cacute 232 /ccaron 234 /eogonek 236 /ecaron 239 /dcaron /dcroat /nacute /ncaron 245 /ohungarumlaut 248 /rcaron /uring 251 /uhungarumlaut 254 /tcommaaccent /dotaccent'; -$uv = [0 => [0, 128], 128 => 8364, 130 => 8218, 132 => 8222, 133 => 8230, 134 => [8224, 2], 137 => 8240, 138 => 352, 139 => 8249, 140 => 346, 141 => 356, 142 => 381, 143 => 377, 145 => [8216, 2], 147 => [8220, 2], 149 => 8226, 150 => [8211, 2], 153 => 8482, 154 => 353, 155 => 8250, 156 => 347, 157 => 357, 158 => 382, 159 => 378, 160 => 160, 161 => 711, 162 => 728, 163 => 321, 164 => 164, 165 => 260, 166 => [166, 4], 170 => 350, 171 => [171, 4], 175 => 379, 176 => [176, 2], 178 => 731, 179 => 322, 180 => [180, 5], 185 => 261, 186 => 351, 187 => 187, 188 => 317, 189 => 733, 190 => 318, 191 => 380, 192 => 340, 193 => [193, 2], 195 => 258, 196 => 196, 197 => 313, 198 => 262, 199 => 199, 200 => 268, 201 => 201, 202 => 280, 203 => 203, 204 => 282, 205 => [205, 2], 207 => 270, 208 => 272, 209 => 323, 210 => 327, 211 => [211, 2], 213 => 336, 214 => [214, 2], 216 => 344, 217 => 366, 218 => 218, 219 => 368, 220 => [220, 2], 222 => 354, 223 => 223, 224 => 341, 225 => [225, 2], 227 => 259, 228 => 228, 229 => 314, 230 => 263, 231 => 231, 232 => 269, 233 => 233, 234 => 281, 235 => 235, 236 => 283, 237 => [237, 2], 239 => 271, 240 => 273, 241 => 324, 242 => 328, 243 => [243, 2], 245 => 337, 246 => [246, 2], 248 => 345, 249 => 367, 250 => 250, 251 => 369, 252 => [252, 2], 254 => 355, 255 => 729]; -$file = 'OpenSans-Regular.z'; -$originalsize = 27996; -$subsetted = true; - diff --git a/assets/OpenSans-Regular.ttf b/assets/OpenSans-Regular.ttf deleted file mode 100755 index db43334..0000000 Binary files a/assets/OpenSans-Regular.ttf and /dev/null differ diff --git a/assets/OpenSans-Regular.z b/assets/OpenSans-Regular.z deleted file mode 100644 index 0ba0228..0000000 Binary files a/assets/OpenSans-Regular.z and /dev/null differ diff --git a/assets/OpenSans-Semibold.php b/assets/OpenSans-Semibold.php deleted file mode 100644 index c5f0ef0..0000000 --- a/assets/OpenSans-Semibold.php +++ /dev/null @@ -1,26 +0,0 @@ -765,'Descent'=>-240,'CapHeight'=>714,'Flags'=>32,'FontBBox'=>'[-584 -282 1261 1049]','ItalicAngle'=>0,'StemV'=>70,'MissingWidth'=>600); -$up = -75; -$ut = 50; -$cw = array( - chr(0)=>600,chr(1)=>600,chr(2)=>600,chr(3)=>600,chr(4)=>600,chr(5)=>600,chr(6)=>600,chr(7)=>600,chr(8)=>600,chr(9)=>600,chr(10)=>600,chr(11)=>600,chr(12)=>600,chr(13)=>600,chr(14)=>600,chr(15)=>600,chr(16)=>600,chr(17)=>600,chr(18)=>600,chr(19)=>600,chr(20)=>600,chr(21)=>600, - chr(22)=>600,chr(23)=>600,chr(24)=>600,chr(25)=>600,chr(26)=>600,chr(27)=>600,chr(28)=>600,chr(29)=>600,chr(30)=>600,chr(31)=>600,' '=>260,'!'=>276,'"'=>436,'#'=>646,'$'=>571,'%'=>862,'&'=>740,'\''=>243,'('=>317,')'=>317,'*'=>548,'+'=>571, - ','=>267,'-'=>322,'.'=>275,'/'=>390,'0'=>571,'1'=>571,'2'=>571,'3'=>571,'4'=>571,'5'=>571,'6'=>571,'7'=>571,'8'=>571,'9'=>571,':'=>275,';'=>278,'<'=>571,'='=>571,'>'=>571,'?'=>453,'@'=>898,'A'=>661, - 'B'=>660,'C'=>634,'D'=>734,'E'=>558,'F'=>532,'G'=>726,'H'=>751,'I'=>305,'J'=>299,'K'=>639,'L'=>542,'M'=>923,'N'=>783,'O'=>787,'P'=>615,'Q'=>787,'R'=>639,'S'=>550,'T'=>566,'U'=>742,'V'=>622,'W'=>946, - 'X'=>622,'Y'=>592,'Z'=>575,'['=>330,'\\'=>390,']'=>330,'^'=>537,'_'=>429,'`'=>592,'a'=>580,'b'=>623,'c'=>495,'d'=>623,'e'=>576,'f'=>363,'g'=>556,'h'=>635,'i'=>279,'j'=>279,'k'=>572,'l'=>279,'m'=>956, - 'n'=>635,'o'=>611,'p'=>623,'q'=>623,'r'=>431,'s'=>487,'t'=>393,'u'=>635,'v'=>535,'w'=>817,'x'=>551,'y'=>536,'z'=>478,'{'=>386,'|'=>551,'}'=>371,'~'=>571,chr(127)=>600,chr(128)=>580,chr(129)=>600,chr(130)=>268,chr(131)=>600, - chr(132)=>461,chr(133)=>819,chr(134)=>509,chr(135)=>518,chr(136)=>600,chr(137)=>1241,chr(138)=>550,chr(139)=>336,chr(140)=>550,chr(141)=>566,chr(142)=>575,chr(143)=>575,chr(144)=>600,chr(145)=>193,chr(146)=>193,chr(147)=>397,chr(148)=>397,chr(149)=>376,chr(150)=>500,chr(151)=>1000,chr(152)=>600,chr(153)=>762, - chr(154)=>487,chr(155)=>336,chr(156)=>487,chr(157)=>393,chr(158)=>478,chr(159)=>478,chr(160)=>260,chr(161)=>599,chr(162)=>599,chr(163)=>544,chr(164)=>571,chr(165)=>661,chr(166)=>551,chr(167)=>501,chr(168)=>592,chr(169)=>832,chr(170)=>550,chr(171)=>556,chr(172)=>571,chr(173)=>322,chr(174)=>832,chr(175)=>575, - chr(176)=>428,chr(177)=>571,chr(178)=>201,chr(179)=>295,chr(180)=>592,chr(181)=>639,chr(182)=>655,chr(183)=>275,chr(184)=>216,chr(185)=>580,chr(186)=>487,chr(187)=>556,chr(188)=>542,chr(189)=>582,chr(190)=>279,chr(191)=>478,chr(192)=>639,chr(193)=>661,chr(194)=>661,chr(195)=>661,chr(196)=>661,chr(197)=>542, - chr(198)=>634,chr(199)=>634,chr(200)=>634,chr(201)=>558,chr(202)=>558,chr(203)=>558,chr(204)=>558,chr(205)=>305,chr(206)=>305,chr(207)=>734,chr(208)=>731,chr(209)=>783,chr(210)=>783,chr(211)=>787,chr(212)=>787,chr(213)=>787,chr(214)=>787,chr(215)=>571,chr(216)=>639,chr(217)=>742,chr(218)=>742,chr(219)=>742, - chr(220)=>742,chr(221)=>592,chr(222)=>566,chr(223)=>666,chr(224)=>431,chr(225)=>580,chr(226)=>580,chr(227)=>580,chr(228)=>580,chr(229)=>279,chr(230)=>495,chr(231)=>495,chr(232)=>495,chr(233)=>576,chr(234)=>576,chr(235)=>576,chr(236)=>576,chr(237)=>279,chr(238)=>279,chr(239)=>623,chr(240)=>631,chr(241)=>635, - chr(242)=>635,chr(243)=>611,chr(244)=>611,chr(245)=>611,chr(246)=>611,chr(247)=>571,chr(248)=>431,chr(249)=>635,chr(250)=>635,chr(251)=>635,chr(252)=>635,chr(253)=>536,chr(254)=>393,chr(255)=>279); -$enc = 'cp1250'; -$diff = '131 /.notdef 136 /.notdef 140 /Sacute /Tcaron 143 /Zacute 152 /.notdef 156 /sacute /tcaron 159 /zacute 161 /caron /breve /Lslash 165 /Aogonek 170 /Scedilla 175 /Zdotaccent 178 /ogonek /lslash 185 /aogonek /scedilla 188 /Lcaron /hungarumlaut /lcaron /zdotaccent /Racute 195 /Abreve 197 /Lacute /Cacute 200 /Ccaron 202 /Eogonek 204 /Ecaron 207 /Dcaron /Dcroat /Nacute /Ncaron 213 /Ohungarumlaut 216 /Rcaron /Uring 219 /Uhungarumlaut 222 /Tcommaaccent 224 /racute 227 /abreve 229 /lacute /cacute 232 /ccaron 234 /eogonek 236 /ecaron 239 /dcaron /dcroat /nacute /ncaron 245 /ohungarumlaut 248 /rcaron /uring 251 /uhungarumlaut 254 /tcommaaccent /dotaccent'; -$uv = array(0=>array(0,128),128=>8364,130=>8218,132=>8222,133=>8230,134=>array(8224,2),137=>8240,138=>352,139=>8249,140=>346,141=>356,142=>381,143=>377,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),153=>8482,154=>353,155=>8250,156=>347,157=>357,158=>382,159=>378,160=>160,161=>711,162=>728,163=>321,164=>164,165=>260,166=>array(166,4),170=>350,171=>array(171,4),175=>379,176=>array(176,2),178=>731,179=>322,180=>array(180,5),185=>261,186=>351,187=>187,188=>317,189=>733,190=>318,191=>380,192=>340,193=>array(193,2),195=>258,196=>196,197=>313,198=>262,199=>199,200=>268,201=>201,202=>280,203=>203,204=>282,205=>array(205,2),207=>270,208=>272,209=>323,210=>327,211=>array(211,2),213=>336,214=>array(214,2),216=>344,217=>366,218=>218,219=>368,220=>array(220,2),222=>354,223=>223,224=>341,225=>array(225,2),227=>259,228=>228,229=>314,230=>263,231=>231,232=>269,233=>233,234=>281,235=>235,236=>283,237=>array(237,2),239=>271,240=>273,241=>324,242=>328,243=>array(243,2),245=>337,246=>array(246,2),248=>345,249=>367,250=>250,251=>369,252=>array(252,2),254=>355,255=>729); -$file = 'OpenSans-Semibold.z'; -$originalsize = 28972; -$subsetted = true; -?> diff --git a/assets/OpenSans-Semibold.ttf b/assets/OpenSans-Semibold.ttf deleted file mode 100755 index 1a7679e..0000000 Binary files a/assets/OpenSans-Semibold.ttf and /dev/null differ diff --git a/assets/OpenSans-Semibold.z b/assets/OpenSans-Semibold.z deleted file mode 100644 index 5c3843e..0000000 Binary files a/assets/OpenSans-Semibold.z and /dev/null differ diff --git a/assets/pe.php b/assets/pe.php deleted file mode 100644 index 8736250..0000000 --- a/assets/pe.php +++ /dev/null @@ -1,26 +0,0 @@ -938,'Descent'=>-63,'CapHeight'=>938,'Flags'=>32,'FontBBox'=>'[0 -63 1002 938]','ItalicAngle'=>0,'StemV'=>70,'MissingWidth'=>0); -$up = 0; -$ut = 0; -$cw = array( - chr(0)=>0,chr(1)=>0,chr(2)=>0,chr(3)=>0,chr(4)=>0,chr(5)=>0,chr(6)=>0,chr(7)=>0,chr(8)=>0,chr(9)=>0,chr(10)=>0,chr(11)=>0,chr(12)=>0,chr(13)=>0,chr(14)=>0,chr(15)=>0,chr(16)=>0,chr(17)=>0,chr(18)=>0,chr(19)=>0,chr(20)=>0,chr(21)=>0, - chr(22)=>0,chr(23)=>0,chr(24)=>0,chr(25)=>0,chr(26)=>0,chr(27)=>0,chr(28)=>0,chr(29)=>0,chr(30)=>0,chr(31)=>0,' '=>0,'!'=>0,'"'=>0,'#'=>0,'$'=>0,'%'=>0,'&'=>0,'\''=>0,'('=>0,')'=>0,'*'=>0,'+'=>0, - ','=>0,'-'=>0,'.'=>0,'/'=>0,'0'=>0,'1'=>0,'2'=>0,'3'=>0,'4'=>0,'5'=>0,'6'=>0,'7'=>0,'8'=>0,'9'=>0,':'=>0,';'=>0,'<'=>0,'='=>0,'>'=>0,'?'=>0,'@'=>0,'A'=>0, - 'B'=>0,'C'=>0,'D'=>0,'E'=>0,'F'=>0,'G'=>0,'H'=>0,'I'=>0,'J'=>0,'K'=>0,'L'=>0,'M'=>0,'N'=>0,'O'=>0,'P'=>0,'Q'=>0,'R'=>0,'S'=>0,'T'=>0,'U'=>0,'V'=>0,'W'=>0, - 'X'=>0,'Y'=>0,'Z'=>0,'['=>0,'\\'=>0,']'=>0,'^'=>0,'_'=>0,'`'=>0,'a'=>1000,'b'=>1000,'c'=>459,'d'=>918,'e'=>0,'f'=>0,'g'=>0,'h'=>0,'i'=>0,'j'=>0,'k'=>0,'l'=>0,'m'=>0, - 'n'=>0,'o'=>0,'p'=>0,'q'=>0,'r'=>0,'s'=>0,'t'=>0,'u'=>0,'v'=>0,'w'=>0,'x'=>0,'y'=>0,'z'=>0,'{'=>0,'|'=>0,'}'=>0,'~'=>0,chr(127)=>0,chr(128)=>0,chr(129)=>0,chr(130)=>0,chr(131)=>0, - chr(132)=>0,chr(133)=>0,chr(134)=>0,chr(135)=>0,chr(136)=>0,chr(137)=>0,chr(138)=>0,chr(139)=>0,chr(140)=>0,chr(141)=>0,chr(142)=>0,chr(143)=>0,chr(144)=>0,chr(145)=>0,chr(146)=>0,chr(147)=>0,chr(148)=>0,chr(149)=>0,chr(150)=>0,chr(151)=>0,chr(152)=>0,chr(153)=>0, - chr(154)=>0,chr(155)=>0,chr(156)=>0,chr(157)=>0,chr(158)=>0,chr(159)=>0,chr(160)=>0,chr(161)=>0,chr(162)=>0,chr(163)=>0,chr(164)=>0,chr(165)=>0,chr(166)=>0,chr(167)=>0,chr(168)=>0,chr(169)=>0,chr(170)=>0,chr(171)=>0,chr(172)=>0,chr(173)=>0,chr(174)=>0,chr(175)=>0, - chr(176)=>0,chr(177)=>0,chr(178)=>0,chr(179)=>0,chr(180)=>0,chr(181)=>0,chr(182)=>0,chr(183)=>0,chr(184)=>0,chr(185)=>0,chr(186)=>0,chr(187)=>0,chr(188)=>0,chr(189)=>0,chr(190)=>0,chr(191)=>0,chr(192)=>0,chr(193)=>0,chr(194)=>0,chr(195)=>0,chr(196)=>0,chr(197)=>0, - chr(198)=>0,chr(199)=>0,chr(200)=>0,chr(201)=>0,chr(202)=>0,chr(203)=>0,chr(204)=>0,chr(205)=>0,chr(206)=>0,chr(207)=>0,chr(208)=>0,chr(209)=>0,chr(210)=>0,chr(211)=>0,chr(212)=>0,chr(213)=>0,chr(214)=>0,chr(215)=>0,chr(216)=>0,chr(217)=>0,chr(218)=>0,chr(219)=>0, - chr(220)=>0,chr(221)=>0,chr(222)=>0,chr(223)=>0,chr(224)=>0,chr(225)=>0,chr(226)=>0,chr(227)=>0,chr(228)=>0,chr(229)=>0,chr(230)=>0,chr(231)=>0,chr(232)=>0,chr(233)=>0,chr(234)=>0,chr(235)=>0,chr(236)=>0,chr(237)=>0,chr(238)=>0,chr(239)=>0,chr(240)=>0,chr(241)=>0, - chr(242)=>0,chr(243)=>0,chr(244)=>0,chr(245)=>0,chr(246)=>0,chr(247)=>0,chr(248)=>0,chr(249)=>0,chr(250)=>0,chr(251)=>0,chr(252)=>0,chr(253)=>0,chr(254)=>0,chr(255)=>0); -$enc = 'font'; -$diff = '32 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 101 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 128 /.notdef 130 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 142 /.notdef 145 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef 158 /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef'; -$uv = array(97=>58976,98=>58949,99=>59043,100=>59020); -$file = 'pe.z'; -$originalsize = 2832; -$subsetted = true; -?> diff --git a/assets/pe.ttf b/assets/pe.ttf deleted file mode 100755 index bc8a269..0000000 Binary files a/assets/pe.ttf and /dev/null differ diff --git a/assets/pe.z b/assets/pe.z deleted file mode 100644 index 092f4db..0000000 Binary files a/assets/pe.z and /dev/null differ diff --git a/composer.json b/composer.json index 3c0c78e..fbaf000 100755 --- a/composer.json +++ b/composer.json @@ -11,8 +11,7 @@ ], "require": { "php": ">=7.2", - "nette/utils": "^3.0.0", - "setasign/fpdf": "^1.8.0" + "webchemistry/svg-pdf": "~1.0.0" }, "require-dev": { "codeception/codeception": "^4.1.0", diff --git a/src/Calculators/BcCalculator.php b/src/Calculators/BcCalculator.php deleted file mode 100644 index 171f36b..0000000 --- a/src/Calculators/BcCalculator.php +++ /dev/null @@ -1,67 +0,0 @@ -scale = $scale; - } - - /** - * @param string|int|float $op1 - * @param string|int|float $op2 - */ - public function add($op1, $op2): string - { - return bcadd((string) $op1, (string) $op2, $this->scale); - } - - /** - * @param string|int|float $op1 - * @param string|int|float $op2 - */ - public function mul($op1, $op2): string - { - return bcmul((string) $op1, (string) $op2, $this->scale); - } - - /** - * @param string|int|float $op1 - * @param string|int|float $op2 - */ - public function div($op1, $op2): ?string - { - return bcdiv((string) $op1, (string) $op2, $this->scale); - } - - /** - * @param string|int|float $op1 - * @param string|int|float $op2 - */ - public function sub($op1, $op2): string - { - return bcsub((string) $op1, (string) $op2, $this->scale); - } - - /** - * @param string|int|float $op1 - * @param string|int|float $op2 - */ - public function comp($op1, $op2): int - { - return bccomp((string) $op1, (string) $op2, $this->scale); - } - -} diff --git a/src/Calculators/FloatCalculator.php b/src/Calculators/FloatCalculator.php deleted file mode 100644 index 0a913f7..0000000 --- a/src/Calculators/FloatCalculator.php +++ /dev/null @@ -1,67 +0,0 @@ - $op2; - } - -} diff --git a/src/Calculators/ICalculator.php b/src/Calculators/ICalculator.php deleted file mode 100644 index 266e07a..0000000 --- a/src/Calculators/ICalculator.php +++ /dev/null @@ -1,42 +0,0 @@ -items = $items; - $this->totalPages = (int) ceil(count($this->items) / $itemsPerPage); - $this->itemsPerPage = $itemsPerPage; - } - - public function getTotalPages(): int - { - return $this->totalPages; - } - - /** - * @return Item[] - */ - public function getItems(): array - { - $page = $this->currentPage - 1; - - return array_slice($this->items, $page * $this->itemsPerPage, $page * $this->itemsPerPage + $this->itemsPerPage); - } - - public function isFirstPage(): bool - { - return $this->currentPage === 1; - } - - public function isLastPage(): bool - { - return $this->currentPage >= $this->getTotalPages(); - } - - public function getCurrentPage(): int - { - return $this->currentPage; - } - - public function nextPage(): bool - { - if ($this->isLastPage()) { - return false; - } - - $this->currentPage++; - - return true; - } - -} diff --git a/src/DI/InvoiceExtension.php b/src/DI/InvoiceExtension.php index a9ec3da..33f9fcd 100755 --- a/src/DI/InvoiceExtension.php +++ b/src/DI/InvoiceExtension.php @@ -2,19 +2,16 @@ namespace Contributte\Invoice\DI; +use Contributte\Invoice\Data\Account; use Contributte\Invoice\Data\Company; -use Contributte\Invoice\Formatter; -use Contributte\Invoice\IFormatter; +use Contributte\Invoice\Data\Currency; use Contributte\Invoice\Invoice; -use Contributte\Invoice\ITranslator; -use Contributte\Invoice\Renderers\IRenderer; -use Contributte\Invoice\Renderers\PDFRenderer; -use Contributte\Invoice\Templates\DefaultTemplate; -use Contributte\Invoice\Templates\ITemplate; -use Contributte\Invoice\Translator; +use Contributte\Invoice\Provider\InvoiceDataProvider; use Nette\DI\CompilerExtension; +use Nette\DI\Definitions\Statement; use Nette\Schema\Expect; use Nette\Schema\Schema; +use stdClass; class InvoiceExtension extends CompilerExtension { @@ -28,41 +25,87 @@ public function getConfigSchema(): Schema 'address' => Expect::string()->required(), 'zip' => Expect::string()->required(), 'country' => Expect::string()->required(), - 'tin' => Expect::string(), - 'vaTin' => Expect::string(), - 'hasTax' => Expect::bool(false), + 'vatNumber' => Expect::string(), + 'id' => Expect::string(), + ]), + 'accounts' => Expect::arrayOf(Expect::structure([ + 'iban' => Expect::string(), + ])), + 'currency' => Expect::structure([ + 'currency' => Expect::string()->required(), + 'template' => Expect::string()->default(':currency:price'), ]), - 'lang' => Expect::string('en'), - 'template' => Expect::string(DefaultTemplate::class), ]); } public function loadConfiguration(): void { $builder = $this->getContainerBuilder(); - $config = (array) $this->getConfig(); - $builder->addDefinition($this->prefix('company')) - ->setFactory(Company::class, array_values((array) $config['company'])); + $builder->addDefinition($this->prefix('dataProvider')) + ->setFactory(InvoiceDataProvider::class, [ + $this->getCompany(), + $this->getAccounts(), + $this->getCurrency(), + ]); + + $builder->addDefinition($this->prefix('invoice')) + ->setFactory(Invoice::class); + } - $builder->addDefinition($this->prefix('template')) - ->setFactory($config['template']) - ->setType(ITemplate::class); + private function getCompany(): ?Statement + { + /** @var stdClass $config */ + $config = $this->getConfig(); - $builder->addDefinition($this->prefix('renderer')) - ->setFactory(PDFRenderer::class) - ->setType(IRenderer::class); + /** @var stdClass $company */ + $company = $config->company; - $builder->addDefinition($this->prefix('translation')) - ->setType(ITranslator::class) - ->setFactory(Translator::class, [$config['lang']]); + if (!$company->name) { + return null; + } - $builder->addDefinition($this->prefix('formatter')) - ->setType(IFormatter::class) - ->setFactory(Formatter::class, [$config['lang']]); + return new Statement(Company::class, [ + $company->name, + $company->town, + $company->address, + $company->zip, + $company->country, + $company->vatNumber, + $company->id, + ]); + } - $builder->addDefinition($this->prefix('invoice')) - ->setFactory(Invoice::class); + /** + * @return Statement[] + */ + private function getAccounts(): array + { + /** @var stdClass $config */ + $config = $this->getConfig(); + + $accounts = []; + /** @var stdClass $account */ + foreach ($config->accounts as $account) { + $accounts[] = new Statement(Account::class, [$account->iban]); + } + + return $accounts; + } + + private function getCurrency(): ?Statement + { + /** @var stdClass $config */ + $config = $this->getConfig(); + + /** @var stdClass $currency */ + $currency = $config->currency; + + if (!$currency->currency) { + return null; + } + + return new Statement(Currency::class, [$currency->currency, $currency->template]); } } diff --git a/src/Data/Account.php b/src/Data/Account.php index ce38773..97abbbc 100755 --- a/src/Data/Account.php +++ b/src/Data/Account.php @@ -2,42 +2,18 @@ namespace Contributte\Invoice\Data; -use Nette\SmartObject; - -class Account +class Account implements IAccount { - use SmartObject; - - /** @var string */ - private $accountNumber; - - /** @var string|null */ - private $iBan; - - /** @var string|null */ - private $swift; - - public function __construct(string $accountNumber, ?string $iBan = null, ?string $swift = null) - { - $this->accountNumber = $accountNumber; - $this->iBan = $iBan; - $this->swift = $swift; - } - - public function getAccountNumber(): string - { - return $this->accountNumber; - } - - public function getIBan(): ?string + public function __construct( + private ?string $iban = null, + ) { - return $this->iBan; } - public function getSwift(): ?string + public function getIban(): ?string { - return $this->swift; + return $this->iban; } } diff --git a/src/Data/Company.php b/src/Data/Company.php index ebebdac..e09b1e2 100755 --- a/src/Data/Company.php +++ b/src/Data/Company.php @@ -2,21 +2,54 @@ namespace Contributte\Invoice\Data; -class Company extends Subject +class Company implements ICompany { - /** @var bool */ - protected $hasTax; + public function __construct( + private string $name, + private string $town, + private string $address, + private string $zip, + private ?string $country = null, + private ?string $vatNumber = null, + private ?string $id = null, + ) + { + } + + public function getName(): string + { + return $this->name; + } + + public function getTown(): string + { + return $this->town; + } + + public function getAddress(): string + { + return $this->address; + } + + public function getZip(): string + { + return $this->zip; + } + + public function getCountry(): ?string + { + return $this->country; + } - public function __construct(string $name, string $town, string $address, string $zip, string $country, ?string $tin = null, ?string $vaTin = null, bool $hasTax = false) + public function getVatNumber(): ?string { - parent::__construct($name, $town, $address, $zip, $country, $tin, $vaTin); - $this->hasTax = $hasTax; + return $this->vatNumber; } - public function hasTax(): bool + public function getId(): ?string { - return $this->hasTax; + return $this->id; } } diff --git a/src/Data/Currency.php b/src/Data/Currency.php new file mode 100644 index 0000000..9a95e25 --- /dev/null +++ b/src/Data/Currency.php @@ -0,0 +1,28 @@ +currency; + } + + public function toString(string $price): string + { + return strtr($this->template, [ + ':currency' => $this->currency, + ':price' => $price, + ]); + } + +} diff --git a/src/Data/Customer.php b/src/Data/Customer.php index 56ea5fa..a93906b 100755 --- a/src/Data/Customer.php +++ b/src/Data/Customer.php @@ -2,7 +2,54 @@ namespace Contributte\Invoice\Data; -class Customer extends Subject +class Customer implements ICustomer { + public function __construct( + private string $name, + private ?string $town = null, + private ?string $address = null, + private ?string $zip = null, + private ?string $country = null, + private ?string $vatNumber = null, + private ?string $id = null, + ) + { + } + + public function getName(): string + { + return $this->name; + } + + public function getTown(): ?string + { + return $this->town; + } + + public function getAddress(): ?string + { + return $this->address; + } + + public function getZip(): ?string + { + return $this->zip; + } + + public function getCountry(): ?string + { + return $this->country; + } + + public function getVatNumber(): ?string + { + return $this->vatNumber; + } + + public function getId(): ?string + { + return $this->id; + } + } diff --git a/src/Data/Extension/IAccountNumber.php b/src/Data/Extension/IAccountNumber.php new file mode 100644 index 0000000..34b740f --- /dev/null +++ b/src/Data/Extension/IAccountNumber.php @@ -0,0 +1,10 @@ +accountNumber; + } + +} diff --git a/src/Data/International/Czech/CzechPaymentInformation.php b/src/Data/International/Czech/CzechPaymentInformation.php new file mode 100644 index 0000000..652531f --- /dev/null +++ b/src/Data/International/Czech/CzechPaymentInformation.php @@ -0,0 +1,42 @@ +variableSymbol; + } + + public function getSpecificSymbol(): ?string + { + return $this->specificSymbol; + } + + public function getConstantSymbol(): ?string + { + return $this->constantSymbol; + } + +} diff --git a/src/Data/Item.php b/src/Data/Item.php index 775b093..6ecf28a 100755 --- a/src/Data/Item.php +++ b/src/Data/Item.php @@ -2,57 +2,16 @@ namespace Contributte\Invoice\Data; -use Contributte\Invoice\Calculators\ICalculator; -use Nette\SmartObject; - -class Item +class Item implements IItem { - use SmartObject; - - /** @var string */ - protected $name; - - /** @var int|float */ - protected $count; - - /** @var int|float */ - protected $price; - - /** @var float|null */ - private $tax; - - /** @var int|float|string|null */ - private $totalPrice; - - /** - * @param int|float $price - * @param int|float $count - */ - public function __construct(string $name, $price, $count, ?float $tax = null) - { - $this->name = $name; - $this->count = $count; - $this->price = $price; - $this->tax = $tax; - } - - ///////////////////////////////////////////////////////////////// - - /** - * @param float|int|string $totalPrice - * @return static - */ - public function setTotalPrice($totalPrice) + public function __construct( + private string $name, + private string $unitPrice, + private int $quantity, + private string $totalPrice, + ) { - $this->totalPrice = $totalPrice; - - return $this; - } - - public function getTax(): ?float - { - return $this->tax; } public function getName(): string @@ -60,41 +19,19 @@ public function getName(): string return $this->name; } - /** - * @return int|float - */ - public function getCount() + public function getUnitPrice(): string { - return $this->count; + return $this->unitPrice; } - /** - * @return int|float - */ - public function getPrice() + public function getQuantity(): int { - return $this->price; + return $this->quantity; } - /** - * @return float|int|string - */ - public function getTotalPrice(ICalculator $calculator, bool $useTax = false) + public function getTotalPrice(): string { - if ($this->totalPrice !== null) { - return $calculator->add($this->totalPrice, 0); - } - - if (!$useTax) { - return $calculator->mul($this->price, $this->count); - } else { - $total = $calculator->mul($this->price, $this->count); - - assert($this->tax !== null); - $tax = $calculator->add($this->tax, 1.0); - - return $calculator->mul($total, $tax); - } + return $this->totalPrice; } } diff --git a/src/Data/Order.php b/src/Data/Order.php index e3e6a44..0c6b4a4 100755 --- a/src/Data/Order.php +++ b/src/Data/Order.php @@ -2,63 +2,40 @@ namespace Contributte\Invoice\Data; -use Contributte\Invoice\Calculators\ICalculator; -use DateTime; -use Nette\SmartObject; - -class Order +class Order implements IOrder { - use SmartObject; - - /** @var string */ - private $number; - - /** @var DateTime|null */ - private $dueDate; - - /** @var Account|null */ - private $account; - - /** @var PaymentInformation */ - private $payment; + /** @var IItem[] */ + private array $items = []; - /** @var DateTime */ - private $created; + private ICurrency $currency; - /** @var Item[] */ - private $items = []; - - /** @var string|float|int|null */ - private $totalPrice; - - public function __construct(string $number, ?DateTime $dueDate, ?Account $account, PaymentInformation $payment, ?DateTime $created = null) + public function __construct( + private string $number, + private string $totalPrice, + private ICompany $company, + private ICustomer $customer, + private IPaymentInformation $payment, + private ITimestamps $timestamps, + ?ICurrency $currency = null, + ) { - $this->number = $number; - $this->dueDate = $dueDate; - $this->account = $account; - $this->payment = $payment; - $this->created = $created ?: new DateTime(); + $this->currency = $currency ?? new Currency('$'); } - /** - * @param int|float $price - * @param int|float $count - */ - public function addItem(string $name, $price, $count = 1, ?float $tax = null): Item + public function addItem(IItem $item): IItem { - return $this->items[] = new Item($name, $price, $count, $tax ?: $this->getPayment()->getTax()); + return $this->items[] = $item; } - /** - * @param float|int|string|null $totalPrice - * @return static - */ - public function setTotalPrice($totalPrice) + public function addItemInline(string $name, string $unitPrice, int $quantity, string $totalPrice): Item { - $this->totalPrice = $totalPrice; + return $this->items[] = new Item($name, $unitPrice, $quantity, $totalPrice); + } - return $this; + public function getTotalPrice(): string + { + return $this->totalPrice; } public function getNumber(): string @@ -66,49 +43,37 @@ public function getNumber(): string return $this->number; } - public function getDueDate(): ?DateTime + public function getTimestamps(): ITimestamps { - return $this->dueDate; + return $this->timestamps; } - public function getAccount(): ?Account + public function getCompany(): ICompany { - return $this->account; + return $this->company; } - public function getPayment(): PaymentInformation + public function getCustomer(): ICustomer { - return $this->payment; + return $this->customer; } - public function getCreated(): DateTime + public function getPayment(): IPaymentInformation { - return $this->created; + return $this->payment; } /** - * @return Item[] + * @return IItem[] */ public function getItems(): array { return $this->items; } - /** - * @return float|int|string - */ - public function getTotalPrice(ICalculator $calculator, bool $useTax = false) + public function getCurrency(): ICurrency { - if ($this->totalPrice !== null) { - return $this->totalPrice; - } - - $total = 0; - foreach ($this->getItems() as $item) { - $total = $calculator->add($total, $item->getTotalPrice($calculator, $useTax)); - } - - return $total; + return $this->currency; } } diff --git a/src/Data/PaymentInformation.php b/src/Data/PaymentInformation.php index 669270f..b325676 100755 --- a/src/Data/PaymentInformation.php +++ b/src/Data/PaymentInformation.php @@ -2,51 +2,29 @@ namespace Contributte\Invoice\Data; -use Nette\SmartObject; - -class PaymentInformation +class PaymentInformation implements IPaymentInformation { - use SmartObject; - - /** @var string */ - private $currency; - - /** @var string|null */ - private $variableSymbol; - - /** @var string|null */ - private $constantSymbol; - - /** @var float|null */ - private $tax; - - public function __construct(string $currency, ?string $variableSymbol = null, ?string $constantSymbol = null, ?float $tax = null) - { - $this->currency = $currency; - $this->variableSymbol = $variableSymbol; - $this->constantSymbol = $constantSymbol; - $this->tax = $tax; - } - - public function getCurrency(): string - { - return $this->currency; - } - - public function getVariableSymbol(): ?string + /** + * @param IAccount[] $accounts + */ + public function __construct( + private array $accounts = [], + ) { - return $this->variableSymbol; } - public function getConstantSymbol(): ?string + /** + * @return IAccount[] + */ + public function getAccounts(): array { - return $this->constantSymbol; + return $this->accounts; } - public function getTax(): ?float + public function getFirstAccount(): ?IAccount { - return $this->tax; + return $this->accounts[array_key_first($this->accounts)] ?? null; } } diff --git a/src/Data/Subject.php b/src/Data/Subject.php deleted file mode 100755 index d4e32d3..0000000 --- a/src/Data/Subject.php +++ /dev/null @@ -1,79 +0,0 @@ -name = $name; - $this->town = $town; - $this->address = $address; - $this->zip = $zip; - $this->country = $country; - $this->tin = $tin; - $this->vaTin = $vaTin; - } - - public function getName(): string - { - return $this->name; - } - - public function getTown(): ?string - { - return $this->town; - } - - public function getAddress(): ?string - { - return $this->address; - } - - public function getZip(): ?string - { - return $this->zip; - } - - public function getCountry(): ?string - { - return $this->country; - } - - public function getTin(): ?string - { - return $this->tin; - } - - public function getVaTin(): ?string - { - return $this->vaTin; - } - -} diff --git a/src/Data/Timestamps.php b/src/Data/Timestamps.php new file mode 100644 index 0000000..c23f9f7 --- /dev/null +++ b/src/Data/Timestamps.php @@ -0,0 +1,25 @@ +created; + } + + public function getDueTo(): ?string + { + return $this->dueTo; + } + +} diff --git a/src/Formatter.php b/src/Formatter.php deleted file mode 100644 index c3e25c9..0000000 --- a/src/Formatter.php +++ /dev/null @@ -1,66 +0,0 @@ - [ - 'number' => [ - 'dec' => ',', - 'sep' => ' ', - ], - 'money' => '%money %currency', - 'date' => 'd.m.Y', - ], - 'en' => [ - 'number' => [ - 'dec' => null, - 'sep' => null, - ], - 'money' => '%currency %money', - 'date' => 'd/m/Y', - ], - ]; - - /** @var string */ - private $lang; - - public function __construct(string $lang = self::ENGLISH) - { - $this->lang = $lang; - } - - /** - * @param mixed $number - */ - public function formatNumber($number): string - { - return number_format((float) $number, 2, self::$options[$this->lang]['number']['dec'], self::$options[$this->lang]['number']['sep']); - } - - /** - * @param mixed $number - */ - public function formatMoney($number, string $currency): string - { - return strtr(self::$options[$this->lang]['money'], ['%money' => $this->formatNumber($number), '%currency' => $currency]); - } - - public function formatDate(DateTime $date): string - { - return $date->format(self::$options[$this->lang]['date']); - } - -} diff --git a/src/IFormatter.php b/src/IFormatter.php deleted file mode 100644 index 616bf59..0000000 --- a/src/IFormatter.php +++ /dev/null @@ -1,22 +0,0 @@ -company = $company; - $this->template = $template ?: new DefaultTemplate(); - $this->renderer = $renderer ?: new PDFRenderer(); - $this->calculator = $calculator ?: new FloatCalculator(); + $this->template = $template ?: new ParaisoTemplate(); } - public function create(Customer $customer, Order $order): string + public function create(IOrder $order): string { - return $this->template->build($this->calculator, $this->renderer, $customer, $order, $this->company); + return $this->template->render($order); } - public function send(Customer $customer, Order $order): void + public function send(IOrder $order): void { - header('Content-type: application/pdf'); + header('Content-type: application/pdf; charset=utf-8'); - echo $this->create($customer, $order); + echo $this->create($order); + } + + public function createResponse(Order $order): Response + { + return new PdfResponse($this->create($order)); } - public function createResponse(Customer $customer, Order $order): IResponse + public function withTemplate(ITemplate $template): static { - return new PdfResponse($this->create($customer, $order)); + return new static($template); } } diff --git a/src/InvoiceException.php b/src/InvoiceException.php deleted file mode 100755 index 6b0773e..0000000 --- a/src/InvoiceException.php +++ /dev/null @@ -1,22 +0,0 @@ -format('Y-m-d'), + (new DateTime('+ 1 week'))->format('Y-m-d'), + ), + ); + + self::addItems($order, $itemCount); + + return $order; } - public static function createCustomer(): Customer + public static function createCzechOrder(?int $itemCount = null): IOrder { - return new Customer('John Doe', 'Los Angeles', 'Cavetown', '720 55', 'USA', '08304431', 'CZ08304431'); + $order = new Order( + date('Y') . '0001', + '15.000,00', + new Company('Contributte', 'Prague', 'U haldy', '110 00', 'Czech Republic', 'CZ08304431', '08304431'), + new Customer('John Doe', 'Los Angeles', 'Cavetown', '720 55', 'USA', 'CZ08304431', '08304431'), + new CzechPaymentInformation( + [new CzechAccount('2353462013/0800', 'CZ4808000000002353462013')], + '0123456789', + '0123', + '1234', + ), + new Timestamps( + (new DateTime())->format('Y-m-d'), + (new DateTime('+ 1 week'))->format('Y-m-d'), + ), + new Currency('Kč', ':price :currency'), + ); + + self::addItems($order, $itemCount); + + return $order; } - public static function createOrder(): Order + private static function addItems(IOrder $order, ?int $itemCount = null): void { - $account = new Account('2353462013/0800', 'CZ4808000000002353462013', 'GIGACZPX'); - $paymentInfo = new PaymentInformation('$', '0123456789', '1234', 0.21); + $items = [ + new Item('Logitech G700s Rechargeable Gaming Mouse', '1.790,00', 4, '7.160,00'), + new Item('ASUS Z380KL 8" - 16GB, LTE', '6.490,00', 1, '6.490,00'), + new Item('Philips 48PFS6909 - 121cm', '13.990,00', 1, '13.990,00'), + new Item('HP Deskjet 3545 Advantage', '1.799,00', 1, '1.799,00'), + new Item('LG 105UC9V - 266cm', '11.599,00', 1, '11.599,00'), + new Item('Samsung Galaxy S21 Ultra 5G, 12GB/128GB', '31.490,00', 1, '31.490,00'), + ]; + $count = count($items); - $order = new Order(date('Y') . '0001', new DateTime('+ 7 days'), $account, $paymentInfo); - $order->addItem('Logitech G700s Rechargeable Gaming Mouse', 1790, 4); - $order->addItem('ASUS Z380KL 8" - 16GB, LTE, bílá', 6490, 1); - $order->addItem('Philips 48PFS6909 - 121cm', 13990, 1); - $order->addItem('HP Deskjet 3545 Advantage', 1799, 1); - $order->addItem('LG 105UC9V - 266cm', 11599, 2); + if ($itemCount === null) { + $itemCount = $count; + } else { + $itemCount = max($itemCount, 0); + } - return $order; + if ($count < $itemCount) { + $array = $items; + for ($i = 0; $i < $itemCount - $count; $i++) { + $array[] = $items[array_rand($items)]; + } + + $items = $array; + } else { + $items = array_slice($items, 0, $itemCount); + } + + foreach ($items as $item) { + $order->addItem($item); + } } } diff --git a/src/Provider/InvoiceDataProvider.php b/src/Provider/InvoiceDataProvider.php new file mode 100644 index 0000000..4fa1e6f --- /dev/null +++ b/src/Provider/InvoiceDataProvider.php @@ -0,0 +1,41 @@ +company; + } + + /** + * @return IAccount[] + */ + public function getAccounts(): array + { + return $this->accounts; + } + + public function getCurrency(): ?ICurrency + { + return $this->currency; + } + +} diff --git a/src/Renderers/Color.php b/src/Renderers/Color.php deleted file mode 100644 index f7f997c..0000000 --- a/src/Renderers/Color.php +++ /dev/null @@ -1,83 +0,0 @@ -red = $red; - $this->green = $green; - $this->blue = $blue; - } - - public function getRed(): int - { - return $this->red; - } - - public function getGreen(): int - { - return $this->green; - } - - public function getBlue(): int - { - return $this->blue; - } - - protected function adjustColor(int $dimension): int - { - return max(0, min(255, $dimension)); - } - - protected function lightenDarken(int $percentage): Color - { - $percentage = round($percentage / 100, 2); - - return new Color( - $this->adjustColor((int) ($this->red - ($this->red * $percentage))), - $this->adjustColor((int) ($this->green - ($this->green * $percentage))), - $this->adjustColor((int) ($this->blue - ($this->blue * $percentage))) - ); - } - - public function lighten(int $percentage): Color - { - $percentage = max(0, min(100, $percentage)); - - return $this->lightenDarken(-$percentage); - } - - public function darken(int $percentage): Color - { - $percentage = max(0, min(100, $percentage)); - - return $this->lightenDarken($percentage); - } - - public static function black(): Color - { - return new Color(0, 0, 0); - } - - public static function white(): Color - { - return new Color(255, 255, 255); - } - -} diff --git a/src/Renderers/IRenderer.php b/src/Renderers/IRenderer.php deleted file mode 100644 index ef8c936..0000000 --- a/src/Renderers/IRenderer.php +++ /dev/null @@ -1,42 +0,0 @@ -k = 72 / 96; - - $this->wPt = $this->w * $this->k; - $this->hPt = $this->h * $this->k; - } - } - - public function SetFontPath(string $fontPath): void - { - $this->fontpath = $fontPath; - } - - /** - * @param float[] $points - */ - public function Polygon(array $points, string $style = 'D'): void - { - //Draw a polygon - if ($style === 'F') { - $op = 'f'; - } elseif ($style === 'FD' || $style === 'DF') { - $op = 'b'; - } else { - $op = 's'; - } - - $h = $this->h; - $k = $this->k; - - $points_string = ''; - for ($i = 0; $i < count($points); $i += 2) { - $points_string .= sprintf('%.2F %.2F', $points[$i] * $k, ($h - $points[$i + 1]) * $k); - if ($i == 0) { - $points_string .= ' m '; - } else { - $points_string .= ' l '; - } - } - $this->_out($points_string . $op); - } - -} diff --git a/src/Renderers/PDFRenderer.php b/src/Renderers/PDFRenderer.php deleted file mode 100644 index ec1aec0..0000000 --- a/src/Renderers/PDFRenderer.php +++ /dev/null @@ -1,172 +0,0 @@ - null, - 'size' => 15, - 'color' => null, - 'align' => Settings::ALIGN_JUSTIFY, - ]; - - public function x(): int - { - return (int) $this->pdf->GetX(); - } - - public function y(): int - { - return (int) $this->pdf->GetY(); - } - - public function textWidth(string $text, ?callable $setCallback = null): float - { - $settings = $this->extractSettings($setCallback); - $this->setFont($settings); - - return $this->pdf->GetStringWidth($text); - } - - public function width(): float - { - return $this->pdf->GetPageWidth(); - } - - public function height(): float - { - return $this->pdf->GetPageHeight(); - } - - public function createNew(): void - { - $this->pdf = new PDF('P', 'px', 'A4'); - $this->pdf->SetFontPath(IRenderer::ASSETS_PATH); - $this->pdf->SetAutoPageBreak(false); - - $this->addPage(); - } - - public function addPage(): void - { - $this->pdf->AddPage('P', 'A4'); - } - - public function addFont(string $family, string $file, string $fontStyle = Settings::FONT_STYLE_NONE): void - { - $this->pdf->AddFont($family, $fontStyle, $file); - } - - public function rect(float $x, float $y, float $width, float $height, ?callable $setCallback = null): void - { - $settings = $this->extractSettings($setCallback); - - $this->setDrawing($settings); - - $this->pdf->Rect($x, $y, $width, $height, 'DF'); - } - - /** - * @param mixed[] $points - */ - public function polygon(array $points, ?callable $setCallback = null): void - { - $settings = $this->extractSettings($setCallback); - - $this->setDrawing($settings); - - $this->pdf->Polygon($points, 'DF'); - } - - /** - * (border, fill, align) - */ - public function cell(float $x, float $y, float $width, ?float $height, ?string $text, ?callable $setCallback = null): void - { - $text = iconv('UTF-8', 'WINDOWS-1250//TRANSLIT', (string) $text); - - $settings = $this->extractSettings($setCallback); - $this->restoreSettings($settings, 'align'); - - $this->pdf->SetXY($x, $y); - $this->setFont($settings); - - if ($height) { - $this->pdf->MultiCell($width, $height, $text, $settings->border, $settings->align, $settings->fill); - } else { - $this->pdf->Cell($width, 0, $text, $settings->border, 0, $settings->align, $settings->fill); - } - } - - public function output(): string - { - return $this->pdf->Output('S'); - } - - protected function setFont(Settings $settings): void - { - if ($settings->fontFamily === null && $settings->fontSize === null && $settings->fontColor === null) { - return; - } - - $this->restoreSettings($settings, 'fontFamily'); - $this->restoreSettings($settings, 'fontSize'); - - $this->pdf->SetFont($settings->fontFamily, $settings->fontStyle, $settings->fontSize); - - if ($settings->fontColor) { - $color = $settings->fontColor; - $this->pdf->SetTextColor($color->getRed(), $color->getGreen(), $color->getBlue()); - } - } - - protected function setDrawing(Settings $settings): void - { - if ($settings->drawColor !== null) { - $color = $settings->drawColor; - - $this->pdf->SetDrawColor($color->getRed(), $color->getGreen(), $color->getBlue()); - } - - if ($settings->fillColor !== null) { - $color = $settings->fillColor; - - $this->pdf->SetFillColor($color->getRed(), $color->getGreen(), $color->getBlue()); - } - } - - protected function extractSettings(?callable $callback = null): Settings - { - $settings = new Settings(); - if ($callback !== null) { - $callback($settings); - } - - return $settings; - } - - protected function restoreSettings(Settings $settings, string $name): void - { - if ($settings->$name === null) { - $settings->$name = $this->cache[$name]; - } else { - $this->cache[$name] = $settings->$name; - } - } - - public function getSource(): PDF - { - return $this->pdf; - } - -} diff --git a/src/Renderers/Settings.php b/src/Renderers/Settings.php deleted file mode 100644 index a361de9..0000000 --- a/src/Renderers/Settings.php +++ /dev/null @@ -1,71 +0,0 @@ -drawColor = $this->fillColor = $color; - - return $this; - } - -} diff --git a/src/Responses/PdfResponse.php b/src/Responses/PdfResponse.php index 14cb044..8362f12 100644 --- a/src/Responses/PdfResponse.php +++ b/src/Responses/PdfResponse.php @@ -2,22 +2,20 @@ namespace Contributte\Invoice\Responses; -use Nette\Application\IResponse; +use Nette\Application\Response; use Nette\Http\IRequest; -use Nette\Http\IResponse as NetteIResponse; +use Nette\Http\IResponse; -final class PdfResponse implements IResponse +final class PdfResponse implements Response { - /** @var string */ - private $content; - - public function __construct(string $content) + public function __construct( + private string $content, + ) { - $this->content = $content; } - public function send(IRequest $httpRequest, NetteIResponse $httpResponse): void + public function send(IRequest $httpRequest, IResponse $httpResponse): void { $httpResponse->setContentType('application/pdf', 'utf-8'); echo $this->content; diff --git a/src/Templates/DefaultTemplate.php b/src/Templates/DefaultTemplate.php deleted file mode 100644 index 2a2e132..0000000 --- a/src/Templates/DefaultTemplate.php +++ /dev/null @@ -1,510 +0,0 @@ -primary = new Color(6, 178, 194); - $this->font = new Color(52, 52, 53); - $this->even = new Color(241, 240, 240); - $this->odd = Color::white(); - $this->translator = $translator ?: new Translator(); - $this->formatter = $formatter ?: new Formatter(); - } - - public function setPrimary(Color $primary): void - { - $this->primary = $primary; - } - - public function setFont(Color $font): void - { - $this->font = $font; - } - - public function setEven(Color $even): void - { - $this->even = $even; - } - - public function setOdd(Color $odd): void - { - $this->odd = $odd; - } - - public function setItemsPerPage(int $itemsPerPage): self - { - $this->itemsPerPage = $itemsPerPage; - - return $this; - } - - public function build(ICalculator $calculator, IRenderer $renderer, Customer $customer, Order $order, Company $company): string - { - $this->renderer = $renderer; - $this->customer = $customer; - $this->order = $order; - $this->company = $company; - $this->calculator = $calculator; - - $this->renderer->createNew(); - - $this->renderer->addFont('sans', 'OpenSans-Regular.php'); - $this->renderer->addFont('sans', 'OpenSans-Semibold.php', Settings::FONT_STYLE_BOLD); - $this->renderer->addFont('icons', 'pe.php'); - - $paginator = new Paginator($this->order->getItems(), $this->itemsPerPage); - - while ($paginator->nextPage()) { - if (!$paginator->isFirstPage()) { - $this->renderer->addPage(); - } - - $this->buildHeader(); - $this->buildLeftPane(); - $this->buildRightPane(); - $this->buildMain(); - - $offset = 337; - $offset = $this->buildItems($offset, $paginator->getItems()); - - if ($paginator->isLastPage()) { - $this->buildTotal($offset); - } - - $this->buildFooter($paginator); - - foreach ($this->onBuild as $build) { - $build($paginator, $this->renderer, $this->formatter); - } - } - - return $this->renderer->output(); - } - - protected function buildTotal(int $offset): void - { - $renderer = $this->renderer; - $half = ($renderer->width() - 553) / 2; - - $renderer->rect(553, $offset, $renderer->width() - 553, 29, function (Settings $settings): void { - $settings->setFillDrawColor($this->even); - }); - $renderer->polygon([ - 553 + $half, $offset + 29, - 573 + $half, $offset, - $renderer->width(), $offset, - $renderer->width(), $offset + 29, - ], function (Settings $settings): void { - $settings->setFillDrawColor($this->primary); - }); - $renderer->cell(553, $offset, $half, 29.0, Strings::upper($this->translator->translate('totalPrice')) . ':', static function (Settings $settings): void { - $settings->fontFamily = 'sans'; - $settings->fontStyle = $settings::FONT_STYLE_BOLD; - $settings->align = $settings::ALIGN_CENTER; - }); - $renderer->cell(553 + $half, $offset, $half - 4, 29.0, $this->formatter->formatMoney($this->order->getTotalPrice($this->calculator, $this->company->hasTax()), $this->order->getPayment()->getCurrency()), static function (Settings $settings): void { - $settings->fontFamily = 'sans'; - $settings->fontStyle = $settings::FONT_STYLE_BOLD; - $settings->fontColor = Color::white(); - }); - } - - /** - * @param Item[] $items - */ - protected function buildItems(int $offset, array $items): int - { - $renderer = $this->renderer; - - foreach ($items as $i => $item) { - $renderer->rect(0, $offset, $renderer->width(), 29, function (Settings $settings) use ($i): void { - $settings->setFillDrawColor($i % 2 === 1 ? $this->even : $this->odd); - }); - $renderer->rect(0, $offset + 30, $renderer->width(), 0.1, function (Settings $settings): void { - $settings->setFillDrawColor($this->even->darken(10)); - }); - - // Data - $renderer->cell(33, $offset, 360, 29.0, $item->getName(), function (Settings $settings): void { - $settings->fontFamily = 'sans'; - $settings->fontColor = $this->font; - $settings->fontStyle = $settings::FONT_STYLE_NONE; - $settings->align = $settings::ALIGN_LEFT; - $settings->fontSize = 5; - }); - $renderer->cell(353, $offset, 80, 29.0, $this->formatter->formatNumber($item->getCount()), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_CENTER; - }); - - $renderer->cell(443, $offset, 160, 29.0, $this->formatter->formatMoney($item->getPrice(), $this->order->getPayment()->getCurrency())); - - if ($this->company->hasTax()) { - $renderer->cell(593, $offset, 70, 29.0, $item->getTax() * 100 . '%'); - } - - $renderer->cell(670, $offset, 123, 29.0, $this->formatter->formatMoney($item->getTotalPrice($this->calculator, $this->company->hasTax()), $this->order->getPayment()->getCurrency()), static function (Settings $settings): void { - $settings->fontFamily = 'sans'; - $settings->fontStyle = $settings::FONT_STYLE_BOLD; - }); - - $offset += 31; - } - - return $offset; - } - - protected function buildMain(): void - { - $renderer = $this->renderer; - - $renderer->rect(0, 307, $renderer->width(), 29, function (Settings $settings): void { - $settings->setFillDrawColor($this->even); - }); - $renderer->polygon([ - $renderer->width(), 307, - $renderer->width(), 336, - $renderer->width() - 124, 336, - $renderer->width() - 100, 307, - ], function (Settings $settings) { - $settings->setFillDrawColor($this->primary); - }); - $renderer->rect(0, 336, $renderer->width(), 1); - - $renderer->cell(33, 307, 360, 29.0, Strings::upper($this->translator->translate('item')), function (Settings $settings): void { - $settings->fontColor = $this->primary; - $settings->fontStyle = $settings::FONT_STYLE_BOLD; - $settings->fontSize = 9; - }); - $renderer->cell(353, 307, 80, 29.0, Strings::upper($this->translator->translate('count')), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_CENTER; - }); - - $renderer->cell(443, 307, 160, 29.0, Strings::upper($this->translator->translate('pricePerItem'))); - - if ($this->company->hasTax()) { - $renderer->cell(593, 307, 70, 29.0, Strings::upper($this->translator->translate('tax'))); - } - - $renderer->cell($renderer->width() - 80, 307, 60, 29.0, Strings::upper($this->translator->translate('total')), function (Settings $settings): void { - $settings->fontColor = $this->even; - }); - } - - protected function buildHeader(): void - { - $renderer = $this->renderer; - - $renderer->polygon([ - 0, 0, - 0, 100, - 245, 100, - 312, 0, - ], function (Settings $settings): void { - $settings->setFillDrawColor($this->font); - }); - - $renderer->polygon([ - 312, 0, - 245, 100, - $renderer->width(), 100, - $renderer->height(), 0, - ], function (Settings $settings): void { - $settings->setFillDrawColor($this->primary); - }); - - $renderer->polygon([ - 0, 100, - 0, 106, - 168, 106, - 188, 120, - 200, 100, - ]); - - $renderer->polygon([ - 200, 100, - 188, 120, - 205, 125, - 222, 100, - ], function (Settings $settings): void { - $settings->setFillDrawColor($this->primary->darken(15)); - }); - - $renderer->polygon([ - 222, 100, - 217, 106, - 242, 106, - 247, 100, - ], function (Settings $settings): void { - $settings->setFillDrawColor($this->primary); - }); - - $y = 36; - $renderer->cell(112, $y, 1, null, $this->company->getZip() . ' ' . $this->company->getTown(), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_RIGHT; - $settings->fontSize = 6; - $settings->fontFamily = 'sans'; - $settings->fontColor = Color::white(); - }); - $mul = 1; - if ($this->company->getAddress()) { - $renderer->cell(112, $y + 12, 1, null, $this->company->getAddress()); - $mul++; - } - if ($this->company->getCountry()) { - $renderer->cell(112, $y + (12 * $mul), 1, null, $this->company->getCountry()); - } - - $multiplier = 0; - if ($this->company->getTin()) { - $renderer->cell(130, $y, 1, null, Strings::upper($this->translator->translate('vat')) . ': ' . $this->company->getTin(), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_LEFT; - }); - $multiplier++; - } - - if ($this->company->getVaTin()) { - $renderer->cell(130, $y + ($multiplier * 12), 1, null, Strings::upper($this->translator->translate('vaTin')) . ': ' . $this->company->getVaTin(), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_LEFT; - }); - $multiplier++; - } - - $renderer->cell(130, $y + ($multiplier * 12), 1, null, - $this->company->hasTax() ? $this->translator->translate('taxPay') : $this->translator->translate('notTax')); - - $renderer->cell(543, 25, 1, null, $this->company->getName(), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_CENTER; - $settings->fontSize = 8; - }); - - $renderer->cell(525, 45, 1, null, $this->translator->translate('date') . ': ' . $this->formatter->formatDate($this->order->getCreated()), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_RIGHT; - $settings->fontSize = 6; - }); - $renderer->cell(525, 57, 1, null, $this->translator->translate('invoiceNumber') . ': ' . $this->order->getNumber()); - $renderer->cell(537, 52, 1, null, Strings::upper($this->translator->translate('invoice')), static function (Settings $settings): void { - $settings->align = $settings::ALIGN_LEFT; - $settings->fontSize = 18; - $settings->fontStyle = $settings::FONT_STYLE_BOLD; - }); - } - - protected function buildLeftPane(): void - { - $renderer = $this->renderer; - $text = Strings::upper($this->translator->translate('subscriber')); - - $renderer->cell(33, 175, 1, null, $text, function (Settings $settings): void { - $settings->fontSize = 16; - $settings->fontColor = $this->primary; - $settings->fontStyle = $settings::FONT_STYLE_BOLD; - }); - - $x = $renderer->textWidth($text) + 76; - - $x = max($x, $renderer->textWidth($this->customer->getName(), static function (Settings $settings): void { - $settings->fontSize = 7; - }) + 76); - - $renderer->polygon([ - $x, 190, - $x, 200, - $x - 7, 192, - 0, 192, - 0, 190, - ], function (Settings $settings) { - $settings->setFillDrawColor($this->primary); - }); - - $renderer->cell(33, 210, 1, null, $this->customer->getName(), function (Settings $settings): void { - $settings->fontSize = 10; - $settings->fontColor = $this->font; - }); - - $multiplier = 0; - $renderer->cell(33, 228, 1, null, $this->customer->getZip() . ', ' . $this->customer->getTown(), static function (Settings $settings): void { - $settings->fontSize = 6; - $settings->fontStyle = $settings::FONT_STYLE_NONE; - }); - $multiplier++; - - if ($this->customer->getAddress()) { - $renderer->cell(33, 228 + ($multiplier * 10), 1, null, $this->customer->getAddress()); - $multiplier++; - } - - if ($this->customer->getCountry()) { - $renderer->cell(33, 228 + ($multiplier * 10), 1, null, $this->customer->getCountry()); - $multiplier++; - } - - if ($this->customer->getTin()) { - $renderer->cell(33, 228 + ($multiplier * 10), 1, null, Strings::upper($this->translator->translate('vat')) . ': ' . $this->customer->getTin()); - $multiplier++; - } - - if ($this->customer->getVaTin()) { - $renderer->cell(33, 228 + ($multiplier * 10), 1, null, Strings::upper($this->translator->translate('vaTin')) . ': ' . $this->customer->getVaTin()); - } - } - - protected function buildRightPane(): void - { - $renderer = $this->renderer; - - $renderer->cell(450, 145, 1, null, Strings::upper($this->translator->translate('paymentData')), function (Settings $settings): void { - $settings->fontColor = $this->primary; - $settings->align = $settings::ALIGN_LEFT; - $settings->fontStyle = $settings::FONT_STYLE_BOLD; - $settings->fontSize = 16; - }); - - $renderer->polygon([ - 440, 160, - 440, 170, - 452, 162, - $renderer->width(), 162, - $renderer->width(), 160, - ]); - - $iconCb = function (Settings $settings): void { - $settings->fontStyle = $settings::FONT_STYLE_NONE; - $settings->fontColor = $this->primary; - $settings->fontSize = 9; - $settings->fontFamily = 'icons'; - }; - $sectionCb = static function (Settings $settings): void { - $settings->fontSize = 6; - $settings->fontFamily = 'sans'; - }; - $textCb = function (Settings $settings): void { - $settings->fontColor = $this->font; - }; - - $multiplier = 0; - // Account information - if ($this->order->getAccount() !== null) { - if ($this->order->getDueDate() !== null) { - $renderer->cell(450, 190, 1, null, 'a', $iconCb); - $renderer->cell(465, 189, 1, null, Strings::upper($this->translator->translate('dueDate')) . ':', $sectionCb); - $renderer->cell(465 + 100, 189, 1, null, $this->formatter->formatDate($this->order->getDueDate()), $textCb); - - $multiplier++; - } - - if ($this->order->getAccount()->getAccountNumber()) { - $renderer->cell(450, 190 + ($multiplier * 15), 1, null, 'b', $iconCb); - $renderer->cell(465, 189 + ($multiplier * 15), 1, null, Strings::upper($this->translator->translate('accountNumber')) . ':', $sectionCb); - $renderer->cell(465 + 100, 189 + ($multiplier * 15), 1, null, $this->order->getAccount()->getAccountNumber(), $textCb); - $multiplier++; - } - - if ($this->order->getAccount()->getIBan()) { - $renderer->cell(450, 190 + ($multiplier * 15), 1, null, 'b', $iconCb); - $renderer->cell(465, 189 + ($multiplier * 15), 1, null, Strings::upper($this->translator->translate('iban')) . ':', $sectionCb); - $renderer->cell(465 + 100, 189 + ($multiplier * 15), 1, null, $this->order->getAccount()->getIBan(), $textCb); - $multiplier++; - } - } - - // Payment - if ($this->order->getPayment()->getVariableSymbol()) { - $renderer->cell(453, 190 + ($multiplier * 15), 1, null, 'c', $iconCb); - $renderer->cell(465, 189 + ($multiplier * 15), 1, null, Strings::upper($this->translator->translate('varSymbol')) . ':', $sectionCb); - $renderer->cell(465 + 100, 189 + ($multiplier * 15), 1, null, $this->order->getPayment()->getVariableSymbol(), $textCb); - $multiplier++; - } - - if ($this->order->getPayment()->getConstantSymbol()) { - $renderer->cell(453, 190 + ($multiplier * 15), 1, null, 'c', $iconCb); - $renderer->cell(465, 189 + ($multiplier * 15), 1, null, Strings::upper($this->translator->translate('constSymbol')) . ':', $sectionCb); - $renderer->cell(465 + 100, 189 + ($multiplier * 15), 1, null, $this->order->getPayment()->getConstantSymbol(), $textCb); - $multiplier++; - } - - // Total price - $renderer->cell(450, 190 + ($multiplier * 15), 1, null, 'd', $iconCb); - $renderer->cell(465, 189 + ($multiplier * 15), 1, null, Strings::upper($this->translator->translate('totalPrice')) . ':', $sectionCb); - $renderer->cell(465 + 100, 189 + ($multiplier * 15), 1, null, $this->formatter->formatMoney($this->order->getTotalPrice($this->calculator, $this->company->hasTax()), $this->order->getPayment()->getCurrency()), $textCb); - } - - protected function buildFooter(Paginator $paginator): void - { - $renderer = $this->renderer; - - $renderer->rect(0, $renderer->height() - 20, $renderer->width(), 20, function (Settings $settings): void { - $settings->setFillDrawColor($this->font); - }); - - $renderer->cell(0, -10, $renderer->width() - 10, null, $this->translator->translate('page') . ' ' . $paginator->getCurrentPage() . ' / ' . $paginator->getTotalPages(), static function (Settings $settings): void { - $settings->fontColor = Color::white(); - $settings->fontFamily = 'sans'; - $settings->align = $settings::ALIGN_RIGHT; - $settings->fontSize = 6; - }); - } - -} diff --git a/src/Templates/ITemplate.php b/src/Templates/ITemplate.php index 7291539..91f5aa9 100644 --- a/src/Templates/ITemplate.php +++ b/src/Templates/ITemplate.php @@ -2,15 +2,11 @@ namespace Contributte\Invoice\Templates; -use Contributte\Invoice\Calculators\ICalculator; -use Contributte\Invoice\Data\Company; -use Contributte\Invoice\Data\Customer; -use Contributte\Invoice\Data\Order; -use Contributte\Invoice\Renderers\IRenderer; +use Contributte\Invoice\Data\IOrder; interface ITemplate { - public function build(ICalculator $calculator, IRenderer $renderer, Customer $customer, Order $order, Company $company): string; + public function render(IOrder $order): string; } diff --git a/src/Templates/ParaisoTemplate.php b/src/Templates/ParaisoTemplate.php new file mode 100644 index 0000000..87f749e --- /dev/null +++ b/src/Templates/ParaisoTemplate.php @@ -0,0 +1,51 @@ +addFont('Montserrat', __DIR__ . '/assets/font/Montserrat-Regular.php') + ->addFont('Montserrat', __DIR__ . '/assets/font/Montserrat-Bold.php', 'bold'); + + $this->colors = [ + 'text' => Color::fromString('#141618'), + 'lightText' => Color::fromString('#858788'), + 'primary' => Color::fromString('#d92b11'), + 'totalDue' => Color::fromString('#6e7072'), + ]; + + $this->translator = $translator ?? new ParaisoTemplateTranslator(); + + parent::__construct($renderer); + } + + protected function getTemplate(): string + { + return __DIR__ . '/templates/paraiso.phpt'; + } + + /** + * @internal + */ + public function createTemplateObject(IOrder $order): ParaisoTemplateObject + { + return new ParaisoTemplateObject($order, $this->translator); + } + +} diff --git a/src/Templates/Template.php b/src/Templates/Template.php new file mode 100644 index 0000000..8289b3e --- /dev/null +++ b/src/Templates/Template.php @@ -0,0 +1,55 @@ +renderer; + } + + public function render(IOrder $order): string + { + return $this->renderTemplate($order); + } + + public function renderToSvg(IOrder $order): string + { + ob_start(); + + $template = $this->createTemplateObject($order); + require $this->getTemplate(); + + $content = ob_get_clean(); + + if ($content === false) { + throw new LogicException(sprintf('Cannot get content from template %s', $this->getTemplate())); + } + + return $content; + } + + protected function renderTemplate(IOrder $order): string + { + return $this->renderer->toPdf($this->renderToSvg($order))->toString(); + } + + abstract protected function getTemplate(): string; + + abstract protected function createTemplateObject(IOrder $order): TemplateObject; + +} diff --git a/src/Templates/Template/ParaisoTemplateObject.php b/src/Templates/Template/ParaisoTemplateObject.php new file mode 100644 index 0000000..cf031f1 --- /dev/null +++ b/src/Templates/Template/ParaisoTemplateObject.php @@ -0,0 +1,135 @@ +getCompany(); + + $this->invoiceFrom = array_filter([ + $translator->translate('Invoice from'), + $company->getName(), + $this->toFullAddress($company), + $this->prepend($translator->translate('ID') . ': ', $company->getId()), + $this->prepend($translator->translate('VAT Number') . ': ', $company->getVatNumber()), + ]); + + $customer = $order->getCustomer(); + $this->invoiceTo = array_filter([ + $translator->translate('Invoice to'), + $customer->getName(), + $this->toFullAddress($customer), + $this->prepend($translator->translate('ID') . ': ', $customer->getId()), + $this->prepend($translator->translate('VAT Number') . ': ', $customer->getVatNumber()), + ]); + + $timestamps = $order->getTimestamps(); + $this->invoiceInfo = array_filter([ + sprintf('%s %s', $translator->translate('Invoice No.'), $order->getNumber()), + sprintf('%s: %s', $translator->translate('Invoice date'), $timestamps->getCreated()), + $this->prepend($this->translate('Invoice due to') . ': ', $timestamps->getDueTo()), + ]); + + $payment = $order->getPayment(); + $account = $payment->getFirstAccount(); + $this->paymentInfo = array_filter([ + $this->prepend( + $translator->translate('Account number') . ': ', + $account instanceof IAccountNumber ? $account->getAccountNumber() : null + ), + $this->prepend($translator->translate('IBAN') . ': ', $account?->getIban()), + $this->prepend( + $translator->translate('Variable symbol') . ': ', + $payment instanceof IVariableSymbol ? $payment->getVariableSymbol() : null + ), + $this->prepend( + $translator->translate('Constant symbol') . ': ', + $payment instanceof IConstantSymbol ? $payment->getConstantSymbol() : null, + ), + $this->prepend( + $translator->translate('Specific symbol') . ': ', + $payment instanceof ISpecificSymbol ? $payment->getSpecificSymbol() : null, + ) + ]); + } + + /** + * @return string[] + */ + public function getInvoiceFrom(): array + { + return $this->invoiceFrom; + } + + /** + * @return string[] + */ + public function getInvoiceTo(): array + { + return $this->invoiceTo; + } + + /** + * @return string[] + */ + public function getInvoiceInfo(): array + { + return $this->invoiceInfo; + } + + /** + * @return string[] + */ + public function getPaymentInfo(): array + { + return $this->paymentInfo; + } + + public function getFooter(): ?string + { + return $this->footer; + } + + private function toFullAddress(ISubject $subject): string + { + return implode(', ', array_filter([ + $subject->getAddress(), + $subject->getTown(), + $subject->getZip(), + $subject->getCountry(), + ])); + } + + private function prepend(string $prepend, ?string $str): ?string + { + return $str === null ? null : $prepend . $str; + } + +} diff --git a/src/Templates/Template/TemplateObject.php b/src/Templates/Template/TemplateObject.php new file mode 100644 index 0000000..73d548c --- /dev/null +++ b/src/Templates/Template/TemplateObject.php @@ -0,0 +1,39 @@ +order; + } + + public function getTranslator(): ITranslator + { + return $this->translator; + } + + public function translate(string $message): string + { + return $this->translator->translate($message); + } + + public function formatMoneyCallback(): callable + { + return fn (string $money) => $this->order->getCurrency()->toString($money); + } + +} diff --git a/src/ITranslator.php b/src/Templates/Translator/ITranslator.php old mode 100755 new mode 100644 similarity index 69% rename from src/ITranslator.php rename to src/Templates/Translator/ITranslator.php index 70b9ae6..5dddd0b --- a/src/ITranslator.php +++ b/src/Templates/Translator/ITranslator.php @@ -1,6 +1,6 @@ [ + 'Invoice' => 'Invoice', + 'Discount' => 'Discount', + 'Payment Info' => 'Payment Info', + 'Total price' => 'Total price', + 'Invoice from' => 'Invoice from', + 'Invoice to' => 'Invoice to', + 'ID' => 'ID', + 'VAT Number' => 'VAT Number', + 'Invoice No.' => 'Invoice No.', + 'Invoice date' => 'Invoice date', + 'Invoice due to' => 'Invoice due to', + 'Account number' => 'Account number', + 'IBAN' => 'IBAN', + 'Variable symbol' => 'Variable symbol', + 'Constant symbol' => 'Constant symbol', + 'Specific symbol' => 'Specific symbol', + ], + ]; + + public function __construct( + private string $lang = 'en', + ) + { + if (!isset($this->translations[$this->lang])) { + throw new InvalidArgumentException(sprintf('Translation language %s not exists', $this->lang)); + } + } + + /** + * @param mixed[] $translations + */ + public function addLanguage(string $lang, array $translations): void + { + $this->translations[$lang] = $translations; + } + + public function translate(string $message): string + { + return $this->translations[$this->lang][$message] ?? $message; + } + +} diff --git a/src/Templates/assets/font/Montserrat-Bold.php b/src/Templates/assets/font/Montserrat-Bold.php new file mode 100644 index 0000000..78f9a4c --- /dev/null +++ b/src/Templates/assets/font/Montserrat-Bold.php @@ -0,0 +1,26 @@ +968,'Descent'=>-251,'CapHeight'=>700,'Flags'=>32,'FontBBox'=>'[-882 -266 1679 1076]','ItalicAngle'=>0,'StemV'=>120,'MissingWidth'=>587); +$up = -75; +$ut = 50; +$cw = array( + chr(0)=>587,chr(1)=>587,chr(2)=>587,chr(3)=>587,chr(4)=>587,chr(5)=>587,chr(6)=>587,chr(7)=>587,chr(8)=>587,chr(9)=>587,chr(10)=>587,chr(11)=>587,chr(12)=>587,chr(13)=>587,chr(14)=>587,chr(15)=>587,chr(16)=>587,chr(17)=>587,chr(18)=>587,chr(19)=>587,chr(20)=>587,chr(21)=>587, + chr(22)=>587,chr(23)=>587,chr(24)=>587,chr(25)=>587,chr(26)=>587,chr(27)=>587,chr(28)=>587,chr(29)=>587,chr(30)=>587,chr(31)=>587,' '=>283,'!'=>289,'"'=>437,'#'=>720,'$'=>638,'%'=>877,'&'=>728,'\''=>230,'('=>357,')'=>358,'*'=>434,'+'=>599, + ','=>262,'-'=>386,'.'=>262,'/'=>392,'0'=>679,'1'=>392,'2'=>590,'3'=>592,'4'=>689,'5'=>595,'6'=>637,'7'=>620,'8'=>660,'9'=>637,':'=>262,';'=>262,'<'=>599,'='=>599,'>'=>599,'?'=>589,'@'=>1035,'A'=>766, + 'B'=>765,'C'=>733,'D'=>826,'E'=>671,'F'=>639,'G'=>771,'H'=>808,'I'=>328,'J'=>541,'K'=>740,'L'=>604,'M'=>955,'N'=>808,'O'=>844,'P'=>732,'Q'=>844,'R'=>735,'S'=>638,'T'=>618,'U'=>788,'V'=>746,'W'=>1163, + 'X'=>714,'Y'=>676,'Z'=>671,'['=>368,'\\'=>392,']'=>368,'^'=>600,'_'=>500,'`'=>600,'a'=>617,'b'=>690,'c'=>591,'d'=>692,'e'=>631,'f'=>387,'g'=>700,'h'=>691,'i'=>301,'j'=>307,'k'=>660,'l'=>301,'m'=>1049, + 'n'=>691,'o'=>655,'p'=>690,'q'=>690,'r'=>431,'s'=>531,'t'=>435,'u'=>687,'v'=>598,'w'=>937,'x'=>595,'y'=>598,'z'=>543,'{'=>391,'|'=>309,'}'=>391,'~'=>599,chr(127)=>587,chr(128)=>820,chr(129)=>587,chr(130)=>262,chr(131)=>587, + chr(132)=>498,chr(133)=>798,chr(134)=>591,chr(135)=>591,chr(136)=>587,chr(137)=>1258,chr(138)=>638,chr(139)=>342,chr(140)=>638,chr(141)=>618,chr(142)=>671,chr(143)=>671,chr(144)=>587,chr(145)=>262,chr(146)=>262,chr(147)=>498,chr(148)=>498,chr(149)=>358,chr(150)=>500,chr(151)=>1000,chr(152)=>587,chr(153)=>1046, + chr(154)=>531,chr(155)=>342,chr(156)=>531,chr(157)=>435,chr(158)=>543,chr(159)=>543,chr(160)=>283,chr(161)=>600,chr(162)=>600,chr(163)=>617,chr(164)=>700,chr(165)=>766,chr(166)=>309,chr(167)=>522,chr(168)=>600,chr(169)=>785,chr(170)=>638,chr(171)=>568,chr(172)=>599,chr(173)=>386,chr(174)=>785,chr(175)=>671, + chr(176)=>418,chr(177)=>599,chr(178)=>600,chr(179)=>327,chr(180)=>600,chr(181)=>690,chr(182)=>686,chr(183)=>302,chr(184)=>600,chr(185)=>617,chr(186)=>531,chr(187)=>568,chr(188)=>604,chr(189)=>600,chr(190)=>301,chr(191)=>543,chr(192)=>735,chr(193)=>766,chr(194)=>766,chr(195)=>766,chr(196)=>766,chr(197)=>604, + chr(198)=>733,chr(199)=>733,chr(200)=>733,chr(201)=>671,chr(202)=>671,chr(203)=>671,chr(204)=>671,chr(205)=>328,chr(206)=>328,chr(207)=>826,chr(208)=>839,chr(209)=>808,chr(210)=>808,chr(211)=>844,chr(212)=>844,chr(213)=>844,chr(214)=>844,chr(215)=>599,chr(216)=>735,chr(217)=>788,chr(218)=>788,chr(219)=>788, + chr(220)=>788,chr(221)=>676,chr(222)=>618,chr(223)=>693,chr(224)=>431,chr(225)=>617,chr(226)=>617,chr(227)=>617,chr(228)=>617,chr(229)=>301,chr(230)=>591,chr(231)=>591,chr(232)=>591,chr(233)=>631,chr(234)=>631,chr(235)=>631,chr(236)=>631,chr(237)=>301,chr(238)=>301,chr(239)=>692,chr(240)=>692,chr(241)=>691, + chr(242)=>691,chr(243)=>655,chr(244)=>655,chr(245)=>655,chr(246)=>655,chr(247)=>599,chr(248)=>431,chr(249)=>687,chr(250)=>687,chr(251)=>687,chr(252)=>687,chr(253)=>598,chr(254)=>435,chr(255)=>600); +$enc = 'cp1250'; +$diff = '131 /.notdef 136 /.notdef 140 /Sacute /Tcaron 143 /Zacute 152 /.notdef 156 /sacute /tcaron 159 /zacute 161 /caron /breve /Lslash 165 /Aogonek 170 /Scedilla 175 /Zdotaccent 178 /ogonek /lslash 185 /aogonek /scedilla 188 /Lcaron /hungarumlaut /lcaron /zdotaccent /Racute 195 /Abreve 197 /Lacute /Cacute 200 /Ccaron 202 /Eogonek 204 /Ecaron 207 /Dcaron /Dcroat /Nacute /Ncaron 213 /Ohungarumlaut 216 /Rcaron /Uring 219 /Uhungarumlaut 222 /Tcommaaccent 224 /racute 227 /abreve 229 /lacute /cacute 232 /ccaron 234 /eogonek 236 /ecaron 239 /dcaron /dcroat /nacute /ncaron 245 /ohungarumlaut 248 /rcaron /uring 251 /uhungarumlaut 254 /tcommaaccent /dotaccent'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,132=>8222,133=>8230,134=>array(8224,2),137=>8240,138=>352,139=>8249,140=>346,141=>356,142=>381,143=>377,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),153=>8482,154=>353,155=>8250,156=>347,157=>357,158=>382,159=>378,160=>160,161=>711,162=>728,163=>321,164=>164,165=>260,166=>array(166,4),170=>350,171=>array(171,4),175=>379,176=>array(176,2),178=>731,179=>322,180=>array(180,5),185=>261,186=>351,187=>187,188=>317,189=>733,190=>318,191=>380,192=>340,193=>array(193,2),195=>258,196=>196,197=>313,198=>262,199=>199,200=>268,201=>201,202=>280,203=>203,204=>282,205=>array(205,2),207=>270,208=>272,209=>323,210=>327,211=>array(211,2),213=>336,214=>array(214,2),216=>344,217=>366,218=>218,219=>368,220=>array(220,2),222=>354,223=>223,224=>341,225=>array(225,2),227=>259,228=>228,229=>314,230=>263,231=>231,232=>269,233=>233,234=>281,235=>235,236=>283,237=>array(237,2),239=>271,240=>273,241=>324,242=>328,243=>array(243,2),245=>337,246=>array(246,2),248=>345,249=>367,250=>250,251=>369,252=>array(252,2),254=>355,255=>729); +$file = 'Montserrat-Bold.z'; +$originalsize = 28924; +$subsetted = true; +?> diff --git a/src/Templates/assets/font/Montserrat-Bold.ttf b/src/Templates/assets/font/Montserrat-Bold.ttf new file mode 100644 index 0000000..221819b Binary files /dev/null and b/src/Templates/assets/font/Montserrat-Bold.ttf differ diff --git a/src/Templates/assets/font/Montserrat-Bold.z b/src/Templates/assets/font/Montserrat-Bold.z new file mode 100644 index 0000000..8f34dbc Binary files /dev/null and b/src/Templates/assets/font/Montserrat-Bold.z differ diff --git a/src/Templates/assets/font/Montserrat-Regular.php b/src/Templates/assets/font/Montserrat-Regular.php new file mode 100644 index 0000000..b192079 --- /dev/null +++ b/src/Templates/assets/font/Montserrat-Regular.php @@ -0,0 +1,26 @@ +968,'Descent'=>-251,'CapHeight'=>700,'Flags'=>32,'FontBBox'=>'[-823 -262 1586 1043]','ItalicAngle'=>0,'StemV'=>70,'MissingWidth'=>587); +$up = -75; +$ut = 50; +$cw = array( + chr(0)=>587,chr(1)=>587,chr(2)=>587,chr(3)=>587,chr(4)=>587,chr(5)=>587,chr(6)=>587,chr(7)=>587,chr(8)=>587,chr(9)=>587,chr(10)=>587,chr(11)=>587,chr(12)=>587,chr(13)=>587,chr(14)=>587,chr(15)=>587,chr(16)=>587,chr(17)=>587,chr(18)=>587,chr(19)=>587,chr(20)=>587,chr(21)=>587, + chr(22)=>587,chr(23)=>587,chr(24)=>587,chr(25)=>587,chr(26)=>587,chr(27)=>587,chr(28)=>587,chr(29)=>587,chr(30)=>587,chr(31)=>587,' '=>262,'!'=>260,'"'=>373,'#'=>696,'$'=>615,'%'=>829,'&'=>669,'\''=>202,'('=>329,')'=>329,'*'=>386,'+'=>575, + ','=>212,'-'=>382,'.'=>212,'/'=>335,'0'=>662,'1'=>361,'2'=>568,'3'=>564,'4'=>661,'5'=>566,'6'=>609,'7'=>589,'8'=>638,'9'=>609,':'=>212,';'=>212,'<'=>575,'='=>575,'>'=>575,'?'=>567,'@'=>1033,'A'=>717, + 'B'=>754,'C'=>719,'D'=>826,'E'=>669,'F'=>633,'G'=>773,'H'=>813,'I'=>302,'J'=>501,'K'=>711,'L'=>589,'M'=>955,'N'=>813,'O'=>839,'P'=>718,'Q'=>839,'R'=>723,'S'=>615,'T'=>574,'U'=>792,'V'=>698,'W'=>1111, + 'X'=>656,'Y'=>635,'Z'=>651,'['=>318,'\\'=>335,']'=>318,'^'=>576,'_'=>500,'`'=>600,'a'=>590,'b'=>678,'c'=>563,'d'=>678,'e'=>604,'f'=>339,'g'=>686,'h'=>677,'i'=>269,'j'=>274,'k'=>601,'l'=>269,'m'=>1061, + 'n'=>677,'o'=>627,'p'=>678,'q'=>678,'r'=>401,'s'=>489,'t'=>406,'u'=>673,'v'=>542,'w'=>879,'x'=>534,'y'=>542,'z'=>511,'{'=>334,'|'=>295,'}'=>334,'~'=>575,chr(127)=>587,chr(128)=>802,chr(129)=>587,chr(130)=>212,chr(131)=>587, + chr(132)=>382,chr(133)=>647,chr(134)=>547,chr(135)=>547,chr(136)=>587,chr(137)=>1190,chr(138)=>615,chr(139)=>299,chr(140)=>615,chr(141)=>574,chr(142)=>651,chr(143)=>651,chr(144)=>587,chr(145)=>212,chr(146)=>212,chr(147)=>382,chr(148)=>382,chr(149)=>295,chr(150)=>500,chr(151)=>1000,chr(152)=>587,chr(153)=>1021, + chr(154)=>489,chr(155)=>299,chr(156)=>489,chr(157)=>406,chr(158)=>511,chr(159)=>511,chr(160)=>262,chr(161)=>600,chr(162)=>600,chr(163)=>594,chr(164)=>700,chr(165)=>717,chr(166)=>295,chr(167)=>490,chr(168)=>600,chr(169)=>809,chr(170)=>615,chr(171)=>477,chr(172)=>575,chr(173)=>382,chr(174)=>809,chr(175)=>651, + chr(176)=>419,chr(177)=>575,chr(178)=>600,chr(179)=>279,chr(180)=>600,chr(181)=>678,chr(182)=>632,chr(183)=>252,chr(184)=>600,chr(185)=>590,chr(186)=>489,chr(187)=>477,chr(188)=>589,chr(189)=>600,chr(190)=>269,chr(191)=>511,chr(192)=>723,chr(193)=>717,chr(194)=>717,chr(195)=>717,chr(196)=>717,chr(197)=>589, + chr(198)=>719,chr(199)=>719,chr(200)=>719,chr(201)=>669,chr(202)=>669,chr(203)=>669,chr(204)=>669,chr(205)=>302,chr(206)=>302,chr(207)=>826,chr(208)=>831,chr(209)=>813,chr(210)=>813,chr(211)=>839,chr(212)=>839,chr(213)=>839,chr(214)=>839,chr(215)=>575,chr(216)=>723,chr(217)=>792,chr(218)=>792,chr(219)=>792, + chr(220)=>792,chr(221)=>635,chr(222)=>574,chr(223)=>668,chr(224)=>401,chr(225)=>590,chr(226)=>590,chr(227)=>590,chr(228)=>590,chr(229)=>269,chr(230)=>563,chr(231)=>563,chr(232)=>563,chr(233)=>604,chr(234)=>604,chr(235)=>604,chr(236)=>604,chr(237)=>269,chr(238)=>269,chr(239)=>678,chr(240)=>678,chr(241)=>677, + chr(242)=>677,chr(243)=>627,chr(244)=>627,chr(245)=>627,chr(246)=>627,chr(247)=>575,chr(248)=>401,chr(249)=>673,chr(250)=>673,chr(251)=>673,chr(252)=>673,chr(253)=>542,chr(254)=>406,chr(255)=>600); +$enc = 'cp1250'; +$diff = '131 /.notdef 136 /.notdef 140 /Sacute /Tcaron 143 /Zacute 152 /.notdef 156 /sacute /tcaron 159 /zacute 161 /caron /breve /Lslash 165 /Aogonek 170 /Scedilla 175 /Zdotaccent 178 /ogonek /lslash 185 /aogonek /scedilla 188 /Lcaron /hungarumlaut /lcaron /zdotaccent /Racute 195 /Abreve 197 /Lacute /Cacute 200 /Ccaron 202 /Eogonek 204 /Ecaron 207 /Dcaron /Dcroat /Nacute /Ncaron 213 /Ohungarumlaut 216 /Rcaron /Uring 219 /Uhungarumlaut 222 /Tcommaaccent 224 /racute 227 /abreve 229 /lacute /cacute 232 /ccaron 234 /eogonek 236 /ecaron 239 /dcaron /dcroat /nacute /ncaron 245 /ohungarumlaut 248 /rcaron /uring 251 /uhungarumlaut 254 /tcommaaccent /dotaccent'; +$uv = array(0=>array(0,128),128=>8364,130=>8218,132=>8222,133=>8230,134=>array(8224,2),137=>8240,138=>352,139=>8249,140=>346,141=>356,142=>381,143=>377,145=>array(8216,2),147=>array(8220,2),149=>8226,150=>array(8211,2),153=>8482,154=>353,155=>8250,156=>347,157=>357,158=>382,159=>378,160=>160,161=>711,162=>728,163=>321,164=>164,165=>260,166=>array(166,4),170=>350,171=>array(171,4),175=>379,176=>array(176,2),178=>731,179=>322,180=>array(180,5),185=>261,186=>351,187=>187,188=>317,189=>733,190=>318,191=>380,192=>340,193=>array(193,2),195=>258,196=>196,197=>313,198=>262,199=>199,200=>268,201=>201,202=>280,203=>203,204=>282,205=>array(205,2),207=>270,208=>272,209=>323,210=>327,211=>array(211,2),213=>336,214=>array(214,2),216=>344,217=>366,218=>218,219=>368,220=>array(220,2),222=>354,223=>223,224=>341,225=>array(225,2),227=>259,228=>228,229=>314,230=>263,231=>231,232=>269,233=>233,234=>281,235=>235,236=>283,237=>array(237,2),239=>271,240=>273,241=>324,242=>328,243=>array(243,2),245=>337,246=>array(246,2),248=>345,249=>367,250=>250,251=>369,252=>array(252,2),254=>355,255=>729); +$file = 'Montserrat-Regular.z'; +$originalsize = 28276; +$subsetted = true; +?> diff --git a/src/Templates/assets/font/Montserrat-Regular.ttf b/src/Templates/assets/font/Montserrat-Regular.ttf new file mode 100644 index 0000000..8d443d5 Binary files /dev/null and b/src/Templates/assets/font/Montserrat-Regular.ttf differ diff --git a/src/Templates/assets/font/Montserrat-Regular.z b/src/Templates/assets/font/Montserrat-Regular.z new file mode 100644 index 0000000..6c233b7 Binary files /dev/null and b/src/Templates/assets/font/Montserrat-Regular.z differ diff --git a/src/Templates/templates/paraiso.phpt b/src/Templates/templates/paraiso.phpt new file mode 100644 index 0000000..f445e88 --- /dev/null +++ b/src/Templates/templates/paraiso.phpt @@ -0,0 +1,155 @@ +formatMoneyCallback(); +$order = $template->getOrder(); +$payment = $order->getPayment(); + +echo ''; +?> + + + + translate('Invoice'))) ?> + + + + + + getInvoiceFrom() as $i => $item): ?> + + + text-anchor="start"> + + + = 2): ?> + + + + + + + + + + getInvoiceTo() as $i => $item): ?> + + + text-anchor="start"> + + + = 2): ?> + + + + + + + + + getInvoiceInfo() as $item): ?> + + + + + + + translate('Total price')) ?>: + getTotalPrice())) ?> + + + + + Item description + Unit price + Quantity + Total + + + getItems() as $item): ?> + + +

getName()) ?>

+
+ getName()) ?> +
+ + + +

getQuantity()) ?>

+
+ getUnitPrice())) ?> +
+ + + +

getQuantity()) ?>

+
+ getQuantity()) ?> +
+ + + +

getTotalPrice()) ?>

+
+ getTotalPrice())) ?> +
+ + increment(); endforeach; ?> + + + + + increment(); ?> + + + + + Sub Total: + getPriceBeforeTax())) ?> + + Tax: + getTax())) ?> + + + + translate('Discount')) ?>: + getDiscount())) ?> + + + Total + $ 4500.00 + + + getPaymentInfo()): ?> + translate('Payment Info')) ?> + getPaymentInfo() as $info): ?> + + + + + current() > $paymentY->current()) ? $y->current() : $paymentY->current(); ?> + + getFooter()): ?> + + +

getFooter()) ?>

+
+ getFooter()) ?> +
+ + +
diff --git a/src/Translator.php b/src/Translator.php deleted file mode 100755 index 55b6a7e..0000000 --- a/src/Translator.php +++ /dev/null @@ -1,87 +0,0 @@ - [ - 'subscriber' => 'Odběratel', - 'vat' => 'IČ', - 'vaTin' => 'DIČ', - 'date' => 'Datum vystavení', - 'invoice' => 'Faktura', - 'invoiceNumber' => 'Číslo faktury', - 'taxPay' => 'Plátce DPH', - 'notTax' => 'Neplátce DPH', - 'paymentData' => 'Platební údaje', - 'page' => 'Stránka', - 'from' => 'z', - 'totalPrice' => 'Celková částka', - 'item' => 'Položka', - 'count' => 'Počet', - 'pricePerItem' => 'Cena za ks', - 'total' => 'Celkem', - 'accountNumber' => 'Číslo účtu', - 'swift' => 'Swift', - 'iban' => 'Iban', - 'varSymbol' => 'Variabilní symbol', - 'constSymbol' => 'Konstant. symbol', - 'tax' => 'DPH', - 'subtotal' => 'Mezisoučet', - 'dueDate' => 'Datum splatnosti', - ], - 'en' => [ - 'subscriber' => 'Subscriber', - 'vat' => 'VAT number', - 'vaTin' => 'VATIN', - 'date' => 'Date', - 'invoice' => 'Invoice', - 'invoiceNumber' => 'Invoice number', - 'taxPay' => '', - 'notTax' => 'VAT unregistered', - 'paymentData' => 'Payment information', - 'page' => 'Page', - 'from' => '/', - 'totalPrice' => 'Total price', - 'item' => 'Item', - 'count' => 'Quantity', - 'pricePerItem' => 'Price per item', - 'total' => 'Total', - 'accountNumber' => 'Account number', - 'swift' => 'Swift', - 'iban' => 'Iban', - 'varSymbol' => 'Variable symbol', - 'constSymbol' => 'Constant symbol', - 'tax' => 'TAX', - 'subtotal' => 'Subtotal', - 'dueDate' => 'Due date', - ], - ]; - - /** @var string */ - private $lang; - - public function __construct(string $lang = self::ENGLISH) - { - $this->lang = $lang; - if (!isset(self::$translations[$this->lang])) { - throw new InvoiceException(sprintf('Language %s not exists.', $lang)); - } - } - - public function translate(string $message): string - { - return self::$translations[$this->lang][$message]; - } - -} diff --git a/tests/unit/.gitkeep b/tests/unit/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/unit/ItemTest.php b/tests/unit/ItemTest.php deleted file mode 100644 index 75c8f38..0000000 --- a/tests/unit/ItemTest.php +++ /dev/null @@ -1,45 +0,0 @@ -item = new \Contributte\Invoice\Data\Item('Foo', 15, 2, 0.10); - $this->calculator = new \Contributte\Invoice\Calculators\BcCalculator(2); - } - - // tests - public function testTotalPriceWithoutTax() - { - // php bug < 7.3.0, bcmul ignores scale, https://bugs.php.net/bug.php?id=66364 - $expected = PHP_VERSION_ID < 70300 ? '30' : '30.00'; - - $this->assertSame($expected, $this->item->getTotalPrice($this->calculator, false)); - } - - public function testTotalPriceSetFixed() - { - $this->item->setTotalPrice(40); - $this->assertSame('40.00', $this->item->getTotalPrice($this->calculator, false)); - } - - public function testTotalPriceWithTax() - { - $this->assertSame('33.00', $this->item->getTotalPrice($this->calculator, true)); - } - - public function testTotalPriceSetFixedWithUseTax() - { - $this->item->setTotalPrice(40.99); - - $this->assertSame('40.99', $this->item->getTotalPrice($this->calculator, true)); - } - -} diff --git a/tests/unit/OrderTest.php b/tests/unit/OrderTest.php deleted file mode 100644 index d0f2e57..0000000 --- a/tests/unit/OrderTest.php +++ /dev/null @@ -1,51 +0,0 @@ -order = new \Contributte\Invoice\Data\Order('0001', null, null, - new \Contributte\Invoice\Data\PaymentInformation('$')); - - $this->order->addItem('Foo', 15, 2, 0.10); - $this->order->addItem('Bar', 30, 3, 0.20); - - $this->calculator = new \Contributte\Invoice\Calculators\BcCalculator(2); - } - - // tests - public function testTotalPriceWithoutTax() - { - $this->assertSame('120.00', $this->order->getTotalPrice($this->calculator)); - } - - public function testTotalPriceFixed() - { - $items = $this->order->getItems(); - $items[0]->setTotalPrice(15); - $items[1]->setTotalPrice(30); - - $this->assertSame('45.00', $this->order->getTotalPrice($this->calculator)); - } - - public function testTotalPriceWithTax() - { - $this->assertSame('141.00', $this->order->getTotalPrice($this->calculator, true)); - } - - public function testTotalPriceFixedWithUseTax() - { - $items = $this->order->getItems(); - $items[0]->setTotalPrice(15); - $items[1]->setTotalPrice(30); - - $this->assertSame('45.00', $this->order->getTotalPrice($this->calculator, true)); - } -} \ No newline at end of file