mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Repeating headers and footers for PDF (#3622)
* Subclass Notification class * Subclass Notification class * Working on invoice design * Working on page headers and footers * Fixes for headers and footers * Fixes for invoices
This commit is contained in:
parent
7cec046f11
commit
9349eb0414
@ -216,7 +216,7 @@ class CompanySettings extends BaseSettings
|
||||
public $vat_number = '';
|
||||
public $id_number = '';
|
||||
|
||||
public $page_size = 'A4';
|
||||
public $page_size = 'A4'; //Letter, Legal, Tabloid, Ledger, A0, A1, A2, A3, A4, A5, A6
|
||||
public $font_size = 9;
|
||||
public $primary_font = 'Roboto';
|
||||
public $secondary_font = 'Roboto';
|
||||
|
@ -30,6 +30,7 @@ class Bold extends AbstractDesign
|
||||
.table_header_thead_class {text-align:left;}
|
||||
.table_header_td_class {padding-left:3rem; padding-right:3rem; font-size:1rem; padding-left:1rem;padding-right:1rem; padding-top:.5rem;padding-bottom:.5rem}
|
||||
.table_body_td_class {background-color:#edf2f7; adding-top:1.25rem;padding-bottom:1.25rem; padding-left:3rem;}
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -87,22 +88,8 @@ class Bold extends AbstractDesign
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="flex px-4 mt-6 w-full px-12">
|
||||
</div>
|
||||
<div class="flex px-4 mt-6 w-full px-12">
|
||||
<div class="w-1/2">
|
||||
$entity.public_notes
|
||||
</div>
|
||||
@ -129,6 +116,28 @@ class Bold extends AbstractDesign
|
||||
<span class="text-xl text-teal-600 font-semibold">$balance_due</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
</div>
|
||||
';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ class Business extends AbstractDesign
|
||||
.table_header_thead_class { border-top-left-radius: .5rem; text-align: left }
|
||||
.table_header_td_class { color: white; padding: .5rem 1rem; font-weight: 800; background-color: #2a4365; }
|
||||
.table_body_td_class { color: #c05621; padding: 1rem; border-width: 4px; border-color: white; background-color: white; }
|
||||
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -89,22 +89,8 @@ class Business extends AbstractDesign
|
||||
<tbody class="bg-gray-200">
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="flex items-center justify-between px-4 pb-4 bg-gray-200 rounded py-2">
|
||||
</table>
|
||||
<div class="flex items-center justify-between px-4 pb-4 bg-gray-200 rounded py-2">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p>$entity.public_notes</p>
|
||||
@ -139,7 +125,26 @@ class Business extends AbstractDesign
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ class Clean extends AbstractDesign
|
||||
.table_header_thead_class { text-align: left; }
|
||||
.table_header_td_class { padding: .5rem 1rem;}
|
||||
.table_body_td_class { border-bottom-width: 1px; border-top-width: 1px; border-color: #cbd5e0; padding: 1rem;}
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -94,22 +95,8 @@ class Clean extends AbstractDesign
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="flex px-4 mt-6 w-full">
|
||||
</table>
|
||||
<div class="flex px-4 mt-6 w-full">
|
||||
<div class="w-1/2">
|
||||
$entity.public_notes
|
||||
</div>
|
||||
@ -141,7 +128,26 @@ class Clean extends AbstractDesign
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ margin-top: 6mm;
|
||||
.table_header_thead_class { text-align: left; border-radius: .5rem; }
|
||||
.table_header_td_class { text-transform: uppercase; font-size: 1.25rem; color: #b83280; font-weight: 500 }
|
||||
.table_body_td_class { padding: 1rem;}
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -78,23 +79,7 @@ margin-top: 6mm;
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>
|
||||
';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="border-b-4 border-pink-700 mt-8">
|
||||
<div class="border-b-4 border-pink-700 mt-8">
|
||||
<div class="grid grid-cols-12 mt-2 px-4 pb-4">
|
||||
<div class="col-span-7 flex flex-col">
|
||||
<p>$entity.public_notes</p>
|
||||
@ -121,7 +106,27 @@ margin-top: 6mm;
|
||||
<p>$balance_due_label</p>
|
||||
<p class="ml-8 text-pink-700 font-semibold">$balance</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
@ -143,6 +143,7 @@ class Designer
|
||||
//$s = microtime(true);
|
||||
$company = $this->entity->company;
|
||||
|
||||
$this->exported_variables['$custom_css'] = $this->entity->generateCustomCSS();
|
||||
$this->exported_variables['$app_url'] = $this->entity->generateAppUrl();
|
||||
$this->exported_variables['$client_details'] = $this->processVariables($this->input_variables['client_details'], $this->clientDetails($company));
|
||||
$this->exported_variables['$company_details'] = $this->processVariables($this->input_variables['company_details'], $this->companyDetails($company));
|
||||
|
@ -35,6 +35,7 @@ class Elegant extends AbstractDesign
|
||||
.table_header_thead_class { text-align: left; border-bottom-width: 1px; border-style: dashed; border-color: black; }
|
||||
.table_header_td_class { font-weight: normal; color: #2f855a; padding: .5rem 1rem; }
|
||||
.table_body_td_class { padding: 1rem; }
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -81,22 +82,8 @@ class Elegant extends AbstractDesign
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="flex items-center justify-between mt-2 px-4 pb-4">
|
||||
</table>
|
||||
<div class="flex items-center justify-between mt-2 px-4 pb-4">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p>$entity.public_notes</p>
|
||||
@ -137,4 +124,25 @@ class Elegant extends AbstractDesign
|
||||
<div class="p-px border-b border-black mt-1"></div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ body {font-size:90%}
|
||||
.table_header_thead_class { text-align: left }
|
||||
.table_header_td_class { text-transform: uppercase; padding: .5rem 1rem; font-weight: 600; border-color: black; }
|
||||
.table_body_td_class { border-left-width: 2px; border-color: black; padding: 1rem; }
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -100,22 +101,8 @@ body {font-size:90%}
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="flex justify-between mt-8">
|
||||
</table>
|
||||
<div class="flex justify-between mt-8">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p>$entity.public_notes</p>
|
||||
@ -144,7 +131,26 @@ body {font-size:90%}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
@ -30,31 +30,7 @@ class Modern extends AbstractDesign
|
||||
.table_header_thead_class {text-align:left; text-align:left; color:#fff; background-color:#1a202c;}
|
||||
.table_header_td_class {padding-left:1rem;padding-right:1rem; padding-top:.5rem;padding-bottom:.5rem}
|
||||
.table_body_td_class {border-top-width:1px; border-bottom-width:1px; border-color:#1a202c; padding-left:1rem;padding-right:1rem; padding-top:1rem;padding-bottom:1rem;}
|
||||
|
||||
@media screen {
|
||||
div.div_header {
|
||||
display: flex;
|
||||
}
|
||||
div.div_footer {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
div.div_footer {
|
||||
display: flex;
|
||||
position: running(footer);
|
||||
width: 100%;
|
||||
}
|
||||
div.div_header {
|
||||
display: flex;
|
||||
position: running(header);
|
||||
width:100%;
|
||||
}
|
||||
}
|
||||
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
$custom_css
|
||||
</style>
|
||||
</head>
|
||||
<body>';
|
||||
@ -63,7 +39,8 @@ class Modern extends AbstractDesign
|
||||
|
||||
public function header()
|
||||
{
|
||||
return '<div class="div_header bg-orange-600 flex justify-between py-12 px-12" style="page-break-inside: avoid;">
|
||||
return '
|
||||
<div class="header bg-orange-600 flex justify-between py-12 px-12" style="page-break-inside: avoid;">
|
||||
<div class="grid grid-cols-6 gap-1">
|
||||
<div class="col-span-2 p-3">
|
||||
<h1 class="text-white font-bold text-3xl">$company.name</h1>
|
||||
@ -75,13 +52,14 @@ class Modern extends AbstractDesign
|
||||
$entity_details
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function body()
|
||||
{
|
||||
return '
|
||||
<table class="container"><thead><tr><td><div class="header-space"></div></td></tr></thead>
|
||||
<tbody><tr><td>
|
||||
<div class="grid grid-cols-5 gap-1 px-12 pt-12">
|
||||
<div class="col-span-2 p-3">
|
||||
$company_logo
|
||||
@ -107,7 +85,45 @@ class Modern extends AbstractDesign
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
</table>
|
||||
<div class="flex px-4 mt-6 w-full" style="page-break-inside: avoid;">
|
||||
<div class="w-1/2">
|
||||
$entity.public_notes
|
||||
</div>
|
||||
<div class="w-1/2 flex" style="page-break-inside: avoid;">
|
||||
<div class="w-1/2 text-right flex flex-col" style="page-break-inside: avoid;">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</div>
|
||||
<div class="w-1/2 text-right flex flex-col" style="page-break-inside: avoid;">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="page-break-inside: avoid;">
|
||||
<div class="flex px-4 mt-4 w-full items-end mt-5" >
|
||||
<div class="w-1/2" style="page-break-inside: avoid;">
|
||||
<p class="font-semibold">$terms_label</p>
|
||||
$terms
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 px-4 py-2 bg-gray-900 text-white" style="">
|
||||
<div class="w-1/2"></div>
|
||||
<div class="w-auto flex justify-end" style="page-break-inside: avoid;">
|
||||
<div class="w-56" style="page-break-inside: avoid;">
|
||||
<p class="font-bold">$balance_due_label</p>
|
||||
</div>
|
||||
<p>$balance_due</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td></tr></tbody><tfoot><tr><td><div class="footer-space"></div></td></tr></tfoot></table>
|
||||
';
|
||||
}
|
||||
|
||||
public function task()
|
||||
@ -123,56 +139,17 @@ class Modern extends AbstractDesign
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<div class="flex px-4 mt-6 w-full" style="page-break-inside: avoid;">
|
||||
<div class="w-1/2">
|
||||
$entity.public_notes
|
||||
</div>
|
||||
<div class="w-1/2 flex" style="page-break-inside: avoid;">
|
||||
<div class="w-1/2 text-right flex flex-col" style="page-break-inside: avoid;">
|
||||
$discount_label
|
||||
$total_tax_labels
|
||||
$line_tax_labels
|
||||
</div>
|
||||
<div class="w-1/2 text-right flex flex-col" style="page-break-inside: avoid;">
|
||||
$discount
|
||||
$total_tax_values
|
||||
$line_tax_values
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex px-4 mt-4 w-full items-end mt-5" style="page-break-inside: avoid;">
|
||||
<div class="w-1/2" style="page-break-inside: avoid;">
|
||||
<p class="font-semibold">$terms_label</p>
|
||||
$terms
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 px-4 py-2 bg-gray-900 text-white" style="page-break-inside: avoid;">
|
||||
<div class="w-1/2"></div>
|
||||
<div class="w-auto flex justify-end" style="page-break-inside: avoid;">
|
||||
<div class="w-56" style="page-break-inside: avoid;">
|
||||
<p class="font-bold">$balance_due_label</p>
|
||||
</div>
|
||||
<p>$balance_due</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
<footer>
|
||||
<div class="div_footer bg-orange-600 flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
<div class="grid grid-cols-12 gap-4">
|
||||
<div class="col-start-4 col-span-4 p-3 flex flex-col text-white text-right">
|
||||
$company_details
|
||||
</div>
|
||||
<div class="col-span-4 p-3 flex flex-col text-white text-right">
|
||||
$company_address
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</html>
|
||||
<div class="footer bg-orange-600 flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
<div class="grid grid-cols-12 gap-4">
|
||||
<div class="col-start-4 col-span-4 p-3 flex flex-col text-white text-right">
|
||||
$company_details
|
||||
</div>
|
||||
<div class="col-span-4 p-3 flex flex-col text-white text-right">
|
||||
$company_address
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</html>
|
||||
';
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ body {font-size:90%}
|
||||
.table_header_thead_class { text-align: left; border-bottom-width: 4px; border-color: black; }
|
||||
.table_header_td_class { font-weight: 400; text-transform: uppercase; padding: 1rem .5rem; }
|
||||
.table_body_td_class { padding: 1rem; }
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -94,22 +95,8 @@ body {font-size:90%}
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="flex items-center justify-between mt-2 px-4 pb-4">
|
||||
</table>
|
||||
<div class="flex items-center justify-between mt-2 px-4 pb-4">
|
||||
<div class="w-1/2">
|
||||
<div class="flex flex-col">
|
||||
<p>$entity.public_notes</p>
|
||||
@ -146,7 +133,26 @@ body {font-size:90%}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ body {font-size:90%}
|
||||
.table_header_thead_class { text-align: left; background-color: #e2e8f0 }
|
||||
.table_header_td_class { padding: 1rem .5rem; }
|
||||
.table_body_td_class { padding: 1rem; border-bottom-width: 1px; border-top-width: 2px; border-color: #e2e8f0 }
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -122,6 +123,12 @@ body {font-size:90%}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '';
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ body {font-size:90%}
|
||||
.table_header_thead_class { text-align: left; background-color: #319795; border-radius: .5rem; }
|
||||
.table_header_td_class { padding: .75rem 1rem; font-weight: 600; color: white; }
|
||||
.table_body_td_class { padding: 1rem; border-bottom-width: 4px; border-style: dashed; border-color: #319795; color: black }
|
||||
$custom_css
|
||||
</style>';
|
||||
}
|
||||
|
||||
@ -93,22 +94,8 @@ body {font-size:90%}
|
||||
<tbody>
|
||||
$task_table_body
|
||||
</tbody>
|
||||
</table>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '<div class="grid grid-cols-12 gap-4">
|
||||
</table>
|
||||
<div class="grid grid-cols-12 gap-4">
|
||||
<div class="col-span-7 flex flex-col">
|
||||
$entity.public_notes
|
||||
</div>
|
||||
@ -136,4 +123,25 @@ body {font-size:90%}
|
||||
</div>
|
||||
<div>';
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function product()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function footer()
|
||||
{
|
||||
return '
|
||||
<footer>
|
||||
<div class="div_footer flex justify-between py-8 px-12" style="page-break-inside: avoid;">
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
</html>';
|
||||
}
|
||||
}
|
||||
|
@ -113,17 +113,6 @@ class EmailController extends BaseController
|
||||
$body = $request->input('body');
|
||||
$entity_string = strtolower(class_basename($entity_obj));
|
||||
|
||||
$company = $entity_obj->company;
|
||||
$settings = $company->settings;
|
||||
|
||||
$settings->reply_to_email = "Reply@example.com";
|
||||
$settings->bcc_email = "BCC@example.com";
|
||||
$settings->pdf_email_attachment = true;
|
||||
$settings->ubl_email_attachment = true;
|
||||
|
||||
$company->settings = $settings;
|
||||
$company->save();
|
||||
|
||||
$entity_obj->invitations->each(function ($invitation) use ($subject, $body, $entity_string, $entity_obj) {
|
||||
if ($invitation->contact->send_email && $invitation->contact->email) {
|
||||
$when = now()->addSeconds(1);
|
||||
|
@ -68,26 +68,6 @@ class SelfUpdateController extends BaseController
|
||||
|
||||
$res = $updater->update();
|
||||
|
||||
try {
|
||||
Artisan::call('migrate');
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("I wasn't able to migrate the data.");
|
||||
}
|
||||
|
||||
try {
|
||||
Artisan::call('optimize');
|
||||
} catch (\Exception $e) {
|
||||
\Log::error("I wasn't able to optimize.");
|
||||
}
|
||||
|
||||
$composer = Factory::create(new NullIO(), base_path('composer.json'), false);
|
||||
|
||||
$output = Installer::create(new NullIO, $composer)
|
||||
->setVerbose()
|
||||
->setUpdate(true)
|
||||
->run();
|
||||
|
||||
\Log::error(print_r($output,1));
|
||||
|
||||
return response()->json(['message'=>$res], 200);
|
||||
}
|
||||
|
117
app/Notifications/BaseNotification.php
Normal file
117
app/Notifications/BaseNotification.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Utils\Traits\MakesInvoiceHtml;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class BaseNotification extends Notification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MakesInvoiceHtml;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
return ['mail'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
return (new MailMessage)
|
||||
->line('The introduction to the notification.')
|
||||
->action('Notification Action', url('/'))
|
||||
->line('Thank you for using our application!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function toArray($notifiable)
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public function buildMailMessageSettings(MailMessage $mail_message) :MailMessage
|
||||
{
|
||||
$mail_message->subject($this->generateEmailEntityHtml($this->entity, $this->subject, $this->contact));
|
||||
|
||||
if(strlen($this->settings->reply_to_email) > 1)
|
||||
$mail_message->replyTo($this->settings->reply_to_email);
|
||||
|
||||
if(strlen($this->settings->bcc_email) > 1)
|
||||
$mail_message->bcc($this->settings->bcc_email);
|
||||
|
||||
if($this->settings->pdf_email_attachment)
|
||||
$mail_message->attach(public_path($this->entity->pdf_file_path()));
|
||||
|
||||
foreach($this->entity->documents as $document){
|
||||
$mail_message->attach($document->generateUrl(), ['as' => $document->name]);
|
||||
}
|
||||
|
||||
if($this->entity instanceof Invoice && $this->settings->ubl_email_attachment){
|
||||
$ubl_string = CreateUbl::dispatchNow($this->entity);
|
||||
$mail_message->attachData($ubl_string, $this->entity->getFileName('xml'));
|
||||
}
|
||||
|
||||
|
||||
return $mail_message;
|
||||
}
|
||||
|
||||
public function buildMailMessageData() :array
|
||||
{
|
||||
|
||||
$body = $this->generateEmailEntityHtml($this->entity, $this->body, $this->contact);
|
||||
|
||||
$design_style = $this->settings->email_style;
|
||||
|
||||
if ($design_style == 'custom') {
|
||||
$email_style_custom = $this->settings->email_style_custom;
|
||||
$body = str_replace("$body", $body, $email_style_custom);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'body' => $body,
|
||||
'design' => $design_style,
|
||||
'footer' => '',
|
||||
'title' => '',
|
||||
'settings' => '',
|
||||
'company' => '',
|
||||
'logo' => $this->entity->company->present()->logo(),
|
||||
'signature' => '',
|
||||
|
||||
];
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
}
|
@ -15,10 +15,9 @@ use Illuminate\Notifications\Notification;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendGenericNotification extends Notification implements ShouldQueue
|
||||
class SendGenericNotification extends BaseNotification implements ShouldQueue
|
||||
{
|
||||
use Queueable;
|
||||
use MakesInvoiceHtml;
|
||||
use Dispatchable;
|
||||
use SerializesModels;
|
||||
|
||||
@ -72,49 +71,11 @@ class SendGenericNotification extends Notification implements ShouldQueue
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$subject = $this->generateEmailEntityHtml($this->entity, $this->subject, $this->contact);
|
||||
$body = $this->generateEmailEntityHtml($this->entity, $this->body, $this->contact);
|
||||
|
||||
$design_style = $this->settings->email_style;
|
||||
|
||||
if ($design_style == 'custom') {
|
||||
$email_style_custom = $this->settings->email_style_custom;
|
||||
$body = str_replace("$body", $body, $email_style_custom);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'body' => $body,
|
||||
'design' => $design_style,
|
||||
'footer' => '',
|
||||
'title' => '',
|
||||
'settings' => '',
|
||||
'company' => '',
|
||||
'logo' => $this->entity->company->present()->logo(),
|
||||
'signature' => '',
|
||||
|
||||
];
|
||||
|
||||
$mail_message = (new MailMessage)
|
||||
->subject($subject)
|
||||
->markdown('email.admin.generic_email', $data);
|
||||
->markdown('email.admin.generic_email', $this->buildMailMessageData());
|
||||
|
||||
if(strlen($this->settings->reply_to_email) > 1)
|
||||
$mail_message->replyTo($this->settings->reply_to_email);
|
||||
|
||||
if(strlen($this->settings->bcc_email) > 1)
|
||||
$mail_message->bcc($this->settings->bcc_email);
|
||||
|
||||
if($this->settings->pdf_email_attachment)
|
||||
$mail_message->attach(public_path($this->entity->pdf_file_path()));
|
||||
|
||||
foreach($this->entity->documents as $document){
|
||||
$mail_message->attach($document->generateUrl(), ['as' => $document->name]);
|
||||
}
|
||||
|
||||
if($this->entity instanceof Invoice && $this->settings->ubl_email_attachment){
|
||||
$ubl_string = CreateUbl::dispatchNow($this->entity);
|
||||
$mail_message->attachData($ubl_string, $this->entity->getFileName('xml'));
|
||||
}
|
||||
$mail_message = $this->buildMailMessageSettings($mail_message);
|
||||
|
||||
return $mail_message;
|
||||
|
||||
|
@ -89,9 +89,7 @@ class InvoiceRepository extends BaseRepository
|
||||
|
||||
$invoice->delete();
|
||||
|
||||
if (class_exists($className)) {
|
||||
event(new InvoiceWasDeleted($invoice));
|
||||
}
|
||||
event(new InvoiceWasDeleted($invoice));
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ trait MakesInvoiceHtml
|
||||
|
||||
$html = $this->parseLabelsAndValues($labels, $values, $html);
|
||||
|
||||
info($html);
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
|
@ -731,4 +731,79 @@ trait MakesInvoiceValues
|
||||
{
|
||||
return rtrim(config('ninja.app_url'), "/");
|
||||
}
|
||||
|
||||
public function generateCustomCSS()
|
||||
{
|
||||
$settings = $this->client->getMergedSettings();
|
||||
|
||||
$header_and_footer = '
|
||||
@media print {
|
||||
thead {display: table-header-group;}
|
||||
tfoot {display: table-footer-group;}
|
||||
button {display: none;}
|
||||
body {margin: 0;}
|
||||
}';
|
||||
|
||||
$header = '
|
||||
@media print {
|
||||
thead {display: table-header-group;}
|
||||
button {display: none;}
|
||||
body {margin: 0;}
|
||||
}';
|
||||
|
||||
$footer = '
|
||||
@media print {
|
||||
tfoot {display: table-footer-group;}
|
||||
button {display: none;}
|
||||
body {margin: 0;}
|
||||
}';
|
||||
$css = '';
|
||||
|
||||
if($settings->all_pages_header && $settings->all_pages_footer)
|
||||
$css .= $header_and_footer;
|
||||
elseif($settings->all_pages_header && !$settings->all_pages_footer)
|
||||
$css .= $header;
|
||||
elseif(!$settings->all_pages_header && $settings->all_pages_footer)
|
||||
$css .= $footer;
|
||||
|
||||
$css .= '
|
||||
.header, .header-space {
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.footer, .footer-space {
|
||||
height: 160px;
|
||||
}
|
||||
|
||||
.footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
position: fixed;
|
||||
top: 0mm;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.page {
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
@page {
|
||||
margin: 0mm
|
||||
}
|
||||
|
||||
html {
|
||||
';
|
||||
|
||||
// $css .= 'font-size:' . $settings->font_size . 'px;';
|
||||
$css .= 'font-size:14px;';
|
||||
|
||||
$css .= '}';
|
||||
|
||||
return $css;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ trait PdfMaker
|
||||
|
||||
$browser = Browsershot::html($html);
|
||||
|
||||
// $browser->format('A4');
|
||||
// $browser->landscape();
|
||||
|
||||
return $browser->deviceScaleFactor(1)
|
||||
->showBackground()
|
||||
|
@ -88,7 +88,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'log_events' => env('SELF_UPDATER_LOG_EVENTS', false),
|
||||
'log_events' => env('SELF_UPDATER_LOG_EVENTS', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -67,6 +67,8 @@ class DesignTest extends TestCase
|
||||
|
||||
$settings = $this->invoice->client->settings;
|
||||
$settings->invoice_design_id = "VolejRejNm";
|
||||
$settings->all_pages_header = true;
|
||||
$settings->all_pages_footer = true;
|
||||
|
||||
$this->client->settings = $settings;
|
||||
$this->client->save();
|
||||
@ -97,6 +99,8 @@ class DesignTest extends TestCase
|
||||
|
||||
$settings = $this->quote->client->settings;
|
||||
$settings->invoice_design_id = "VolejRejNm";
|
||||
$settings->all_pages_header = true;
|
||||
$settings->all_pages_footer = true;
|
||||
|
||||
$this->client->settings = $settings;
|
||||
$this->client->save();
|
||||
@ -117,6 +121,8 @@ class DesignTest extends TestCase
|
||||
|
||||
$settings = $this->invoice->client->settings;
|
||||
$settings->quote_design_id = "4";
|
||||
$settings->all_pages_header = true;
|
||||
$settings->all_pages_footer = true;
|
||||
|
||||
$this->credit->client_id = $this->client->id;
|
||||
$this->credit->setRelation('client', $this->client);
|
||||
@ -133,6 +139,8 @@ class DesignTest extends TestCase
|
||||
for ($x=1; $x<=10; $x++) {
|
||||
$settings = $this->invoice->client->settings;
|
||||
$settings->quote_design_id = (string)$this->encodePrimaryKey($x);
|
||||
$settings->all_pages_header = true;
|
||||
$settings->all_pages_footer = true;
|
||||
|
||||
$this->quote->client_id = $this->client->id;
|
||||
$this->quote->setRelation('client', $this->client);
|
||||
|
Loading…
x
Reference in New Issue
Block a user