-
5 | =page()->children->find('viewable=1')->each("
- {title} ")?> 6 |
├── install ├── files │ ├── 1020 │ │ ├── logo-web300x300.png │ │ ├── logo-web300x300.0x120.png │ │ ├── logo-web300x300.0x240.png │ │ └── logo-web300x300.260x0.png │ └── README.txt ├── invoices-preview.png ├── info.php ├── finish.php └── install.sql ├── modules └── README.txt ├── templates ├── invoice-options.php ├── clients.php ├── basic-page.php ├── client.php ├── errors │ ├── 500.html │ └── README.txt ├── invoice-status.php ├── home.php ├── parts │ ├── status-nav.php │ ├── logo.php │ ├── topnav.php │ ├── invoice-list.php │ └── invoice-email.php ├── _init.php ├── styles │ └── main.css ├── admin.php ├── _main.php ├── classes │ ├── Labels.php │ └── EmailTemplateHelper.php ├── admin │ ├── invoice-edit.js │ └── invoice-edit.php ├── invoice.php └── _func.php ├── assets └── index.php ├── classes ├── InvoiceDayPage.php ├── InvoiceItemTypePage.php ├── InvoicePaymentsRepeaterPage.php ├── InvoiceItemsRepeaterPage.php ├── InvoiceStatusPage.php ├── HomePage.php ├── ClientPage.php ├── InvoiceSettingsPage.php └── InvoicePage.php ├── finished.php ├── init.php ├── .gitignore ├── ready.php ├── config.php └── README.md /install/files/README.txt: -------------------------------------------------------------------------------- 1 | This file is here to ensure Git adds the dir to the repo. You may delete this file. 2 | -------------------------------------------------------------------------------- /install/invoices-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processwire/site-invoices/HEAD/install/invoices-preview.png -------------------------------------------------------------------------------- /install/files/1020/logo-web300x300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processwire/site-invoices/HEAD/install/files/1020/logo-web300x300.png -------------------------------------------------------------------------------- /install/files/1020/logo-web300x300.0x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processwire/site-invoices/HEAD/install/files/1020/logo-web300x300.0x120.png -------------------------------------------------------------------------------- /install/files/1020/logo-web300x300.0x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processwire/site-invoices/HEAD/install/files/1020/logo-web300x300.0x240.png -------------------------------------------------------------------------------- /install/files/1020/logo-web300x300.260x0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/processwire/site-invoices/HEAD/install/files/1020/logo-web300x300.260x0.png -------------------------------------------------------------------------------- /modules/README.txt: -------------------------------------------------------------------------------- 1 | This directory is for site-specific plugin modules. 2 | Please see the URL below for more information: 3 | 4 | https://processwire.com/docs/modules/about-site-modules/ 5 | -------------------------------------------------------------------------------- /templates/invoice-options.php: -------------------------------------------------------------------------------- 1 | 3 |
The server encountered an internal error or misconfiguration and was unable to complete your request.
9 |{message}
10 | 11 | 12 | -------------------------------------------------------------------------------- /install/info.php: -------------------------------------------------------------------------------- 1 | "Invoice application site profile", 5 | 'summary' => "A full invoicing application developed in ProcessWire. Enables you to create invoices, record payments to them, email invoices to clients, print invoices, and more.", 6 | 'screenshot' => "invoices-preview.png" 7 | ); 8 | -------------------------------------------------------------------------------- /classes/InvoicePaymentsRepeaterPage.php: -------------------------------------------------------------------------------- 1 | 6 |", "
Hello World
", $event->return);
17 | * });
18 | *
19 | */
--------------------------------------------------------------------------------
/templates/parts/logo.php:
--------------------------------------------------------------------------------
1 | for invoice profile
5 | *
6 | */
7 |
8 | // max height for logo image in px (adjust as needed)
9 | $logoHeight = 120;
10 | $logo = settings()->image;
11 |
12 | if($logo) {
13 | $logo1x = $logo->maxHeight($logoHeight);
14 | $logo2x = $logo->maxHeight($logoHeight * 2); // for hidpi
15 | $website = settings()->website;
16 | $alt = $logo->description;
17 | $style = "max-height:{$logoHeight}px";
18 | $img = "";
19 | if($website) $img = "$img";
20 | echo $img;
21 | } else {
22 | echo "";
23 | }
--------------------------------------------------------------------------------
/classes/HomePage.php:
--------------------------------------------------------------------------------
1 | '-10 DAYS',
19 | '2024-03-01 00:00:00' => '-8 DAYS',
20 | '2024-03-03 00:00:00' => '-5 DAYS',
21 | '2024-03-08 00:00:00' => '-1 DAY',
22 | ];
23 |
24 | foreach($dates as $oldDate => $newDate) {
25 | $newDate = date('Y-m-d', strtotime($newDate)) . ' 00:00:00';
26 | $sql = 'UPDATE field_date SET `data`=:newDate WHERE `data`=:oldDate';
27 | $query = $database->prepare($sql);
28 | $query->bindValue(':newDate', $newDate);
29 | $query->bindValue(':oldDate', $oldDate);
30 | $query->execute();
31 | }
32 |
--------------------------------------------------------------------------------
/templates/_init.php:
--------------------------------------------------------------------------------
1 | prependTemplateFile in /site/config.php.
8 | * Use this to define shared variables, functions, classes, includes, etc.
9 | * or include other files that have them. Note that this _init.php file
10 | * is not automatically included for the admin.php template file, but
11 | * it is for all others.
12 | *
13 | * In this case we are using this file to limit access to only logged
14 | * in users, unless the current page template is 'home' or 'invoice'.
15 | * If a guest attempts to view anything other than the homepage or
16 | * a specific invoice page, then we redirect them to the homepage,
17 | * which displays a login button.
18 | *
19 | */
20 |
21 | if(!user()->isLoggedin() && page()->id != config()->http404PageID) {
22 | if(!in_array(page()->template->name, [ 'home', 'invoice' ])) {
23 | session()->redirect(urls()->root);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/templates/styles/main.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Front-end CSS for invoices site profile
3 | *
4 | */
5 |
6 | #container {
7 | margin-top: 70px;
8 | margin-bottom: 70px;
9 | }
10 |
11 | #logo {
12 | float: right;
13 | }
14 |
15 | #headline > span {
16 | position: relative;
17 | top: -4px;
18 | margin-left: 10px;
19 | }
20 |
21 | #invoice-meta h4,
22 | .uk-table th {
23 | font-size: .875rem;
24 | text-transform: uppercase;
25 | color: #999;
26 | letter-spacing: 1px;
27 | }
28 |
29 | #invoice-meta h4 {
30 | border-bottom: 1px solid #ddd;
31 | margin: 0 0 10px 0;
32 | padding-bottom: 10px;
33 | }
34 |
35 | #invoice-meta p {
36 | margin: 0 0 20px 0;
37 | }
38 |
39 | #content tr.separate,
40 | #content tr:first-child {
41 | border-color: #999;
42 | }
43 |
44 | td:last-child,
45 | th:last-child,
46 | #line-items td:nth-last-child(2),
47 | #line-items th:nth-last-child(2) {
48 | text-align: right;
49 | }
50 |
51 | @media print {
52 | #topnav {
53 | display: none;
54 | }
55 | }
56 |
57 | @media screen and (max-width: 767px) {
58 | #logo {
59 | float: none;
60 | }
61 | }
--------------------------------------------------------------------------------
/ready.php:
--------------------------------------------------------------------------------
1 | addHookAfter('ProcessPageEdit::loadPage', function(HookEvent $event) use($wire) {
28 | $page = $event->return;
29 | if($page instanceof InvoicePage) {
30 | // note: invoice-edit.php expects $page and $wire API vars
31 | include('./admin/invoice-edit.php');
32 | }
33 | });
34 |
35 | require($config->paths->core . 'admin.php');
--------------------------------------------------------------------------------
/templates/parts/topnav.php:
--------------------------------------------------------------------------------
1 | parents as $parent) {
13 | // breadcrumbs
14 | if($parent->isHidden() || !$parent->viewable()) continue;
15 | $label = $parent->id === 1 ? _('invoices') : $parent->title;
16 | if($parent->viewable()) $topnav[$parent->url] = $label;
17 | }
18 |
19 | if($page instanceof InvoicePage) {
20 | // add some extra nav links when viewing an invoice
21 | if($page->client->id) $topnav[$page->client->url] = $page->client->title;
22 | $topnav[$page->url . 'email/'] = icon('mail', _('view email'));
23 | $topnav[$page->url . 'print/'] = icon('print', _('print'));
24 | }
25 |
26 | if($page->editable()) {
27 | // edit page link
28 | $topnav[$page->editUrl] = icon('file-edit', _('edit'));
29 | $topnav[newInvoiceUrl()] = icon('plus-circle', _('add new invoice'));
30 | }
31 |
32 | ?>
33 |
34 |
-------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 | useFunctionsAPI = true; 28 | $config->usePageClasses = true; 29 | $config->useMarkupRegions = true; 30 | $config->prependTemplateFile = '_init.php'; 31 | $config->appendTemplateFile = '_main.php'; 32 | $config->templateCompile = false; 33 | $config->defaultAdminTheme = 'AdminThemeUikit'; 34 | 35 | 36 | /*** INSTALLER CONFIG ********************************************************************/ 37 | 38 | 39 | -------------------------------------------------------------------------------- /templates/parts/invoice-list.php: -------------------------------------------------------------------------------- 1 | 8 |
| =_('Invoice ID')?> | 12 |=_('Client')?> | 13 |=_('Date')?> | 14 |=_('Subtotal')?> | 15 |=_('Status')?> | 16 |
|---|---|---|---|---|
| =$item->title?> | 27 |=$item->client->title?> | 28 |=$item->date?> | 29 |=price($subtotal)?> | 30 |=$item->invoice_status->title?> | 31 |
| =_('no invoices to list')?> | 37 |||||
| 42 | 43 | =icon('plus-circle')?> 44 | =_('new')?> 45 | 46 | | 47 |=_('Total')?> | 48 |49 | =price($total)?> 50 | | 51 |||
-------------------------------------------------------------------------------- /classes/ClientPage.php: -------------------------------------------------------------------------------- 1 | wire()->pages->find($selector); 26 | return $items; 27 | } 28 | 29 | /** 30 | * Get number of active/published invoices for this client 31 | * 32 | * @return int 33 | * 34 | */ 35 | function getNumInvoices() { 36 | return $this->wire()->pages->count("template=invoice, client=$this"); 37 | } 38 | 39 | /** 40 | * Extend get() method to handle custom properties 41 | * 42 | * @param string $key 43 | * @return mixed 44 | * 45 | */ 46 | public function get($key) { 47 | if($key === 'num_invoices') return $this->getNumInvoices(); 48 | if($key === 'invoices') return $this->getInvoices(); 49 | return parent::get($key); 50 | } 51 | 52 | /** 53 | * Get the label markup to display in the admin page-list 54 | * 55 | * @return string 56 | * 57 | */ 58 | public function getPageListLabel() { 59 | $n = $this->getNumInvoices(); 60 | $info = "· $n " . ($n === 1 ? _('invoice') : _('invoices')); 61 | return sanitizer()->entities1($this->title) . ' ' . ukText('meta', $info); 62 | } 63 | } -------------------------------------------------------------------------------- /classes/InvoiceSettingsPage.php: -------------------------------------------------------------------------------- 1 | 'USD', 'symbol' => '$', 'decimal' => '.', 'thousands' => ',']; 33 | $currency = json_decode($this->getUnformatted('currency'), true); 34 | if(!is_array($currency)) $currency = []; 35 | $currency = array_merge($defaults, $currency); 36 | if($property === false) return $currency; 37 | if($this->of()) { 38 | foreach($currency as $key => $value) { 39 | $currency[$key] = sanitizer()->entities1($value); 40 | } 41 | } 42 | } 43 | if($property) { 44 | return isset($currency[$property]) ? $currency[$property] : ''; 45 | } 46 | return $currency; 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /templates/_main.php: -------------------------------------------------------------------------------- 1 | appendTemplateFile in /site/config.php, and 8 | * is typically used to define and output markup common among most pages. 9 | * 10 | * When the Markup Regions feature is used, template files can prepend, append, 11 | * replace or delete any element defined here that has an "id" attribute. 12 | * https://processwire.com/docs/front-end/output/markup-regions/ 13 | * 14 | */ 15 | 16 | // Using uikit version bundled with ProcessWire (feel free to change) 17 | $ukUrl = urls()->get('AdminThemeUikit') . 'uikit/dist/'; 18 | 19 | ?> 20 | 21 |
22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 |
42 |