From 19bbb9fa7658a2fc841843b5e681b7408fed6a36 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 27 Jun 2026 16:48:09 +0000 Subject: [PATCH 01/13] Convert wiki/en/1_6 blade templates to Markdown and add MkDocs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add convert_wiki.py script that extracts content from 39 Blade/PHP templates and converts HTML to clean Markdown using markdownify - Generated docs/en/1.6/ with proper file naming (snake_case → kebab-case matching the original URL structure) - Set up mkdocs.yml with Material theme and full navigation hierarchy - Add requirements.txt with mkdocs, mkdocs-material, markdownify - Add .github/workflows/docs.yml for automated GitHub Pages deployment - Update .gitignore to exclude the MkDocs build output directory Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01FyUdA46kyTUidfhs4sAEG7 --- .github/workflows/docs.yml | 31 ++ .gitignore | 3 + convert_wiki.py | 269 ++++++++++++++++++ docs/en/1.6/general/about.md | 38 +++ docs/en/1.6/general/changelog.md | 32 +++ docs/en/1.6/general/faq.md | 107 +++++++ docs/en/1.6/general/license.md | 113 ++++++++ docs/en/1.6/getting-started/index.md | 6 + docs/en/1.6/getting-started/installation.md | 53 ++++ docs/en/1.6/getting-started/quickstart.md | 77 +++++ docs/en/1.6/getting-started/requirements.md | 28 ++ docs/en/1.6/getting-started/updating-ip.md | 83 ++++++ docs/en/1.6/help/setup-cron.md | 43 +++ docs/en/1.6/index.md | 56 ++++ docs/en/1.6/modules/clients.md | 37 +++ docs/en/1.6/modules/index.md | 7 + docs/en/1.6/modules/invoices.md | 157 ++++++++++ docs/en/1.6/modules/payments.md | 45 +++ docs/en/1.6/modules/quotes.md | 124 ++++++++ docs/en/1.6/modules/recurring-invoices.md | 40 +++ docs/en/1.6/modules/tasks-projects.md | 38 +++ docs/en/1.6/settings/custom-fields.md | 28 ++ docs/en/1.6/settings/email-templates.md | 31 ++ docs/en/1.6/settings/email.md | 12 + docs/en/1.6/settings/general.md | 45 +++ docs/en/1.6/settings/index.md | 15 + docs/en/1.6/settings/invoice-groups.md | 41 +++ docs/en/1.6/settings/invoices.md | 21 ++ docs/en/1.6/settings/online-payments.md | 25 ++ docs/en/1.6/settings/payment-methods.md | 13 + docs/en/1.6/settings/quotes.md | 17 ++ docs/en/1.6/settings/taxes.md | 11 + docs/en/1.6/settings/taxrates.md | 13 + docs/en/1.6/settings/updatecheck.md | 6 + docs/en/1.6/settings/user-accounts.md | 70 +++++ docs/en/1.6/system/importing-data.md | 57 ++++ docs/en/1.6/system/index.md | 5 + .../en/1.6/system/translation-localization.md | 63 ++++ .../1.6/system/upgrade-from-fusioninvoice.md | 32 +++ docs/en/1.6/templates/customize-templates.md | 160 +++++++++++ docs/en/1.6/templates/index.md | 4 + docs/en/1.6/templates/using-templates.md | 17 ++ mkdocs.yml | 83 ++++++ requirements.txt | 3 + 44 files changed, 2159 insertions(+) create mode 100644 .github/workflows/docs.yml create mode 100644 convert_wiki.py create mode 100644 docs/en/1.6/general/about.md create mode 100644 docs/en/1.6/general/changelog.md create mode 100644 docs/en/1.6/general/faq.md create mode 100644 docs/en/1.6/general/license.md create mode 100644 docs/en/1.6/getting-started/index.md create mode 100644 docs/en/1.6/getting-started/installation.md create mode 100644 docs/en/1.6/getting-started/quickstart.md create mode 100644 docs/en/1.6/getting-started/requirements.md create mode 100644 docs/en/1.6/getting-started/updating-ip.md create mode 100644 docs/en/1.6/help/setup-cron.md create mode 100644 docs/en/1.6/index.md create mode 100644 docs/en/1.6/modules/clients.md create mode 100644 docs/en/1.6/modules/index.md create mode 100644 docs/en/1.6/modules/invoices.md create mode 100644 docs/en/1.6/modules/payments.md create mode 100644 docs/en/1.6/modules/quotes.md create mode 100644 docs/en/1.6/modules/recurring-invoices.md create mode 100644 docs/en/1.6/modules/tasks-projects.md create mode 100644 docs/en/1.6/settings/custom-fields.md create mode 100644 docs/en/1.6/settings/email-templates.md create mode 100644 docs/en/1.6/settings/email.md create mode 100644 docs/en/1.6/settings/general.md create mode 100644 docs/en/1.6/settings/index.md create mode 100644 docs/en/1.6/settings/invoice-groups.md create mode 100644 docs/en/1.6/settings/invoices.md create mode 100644 docs/en/1.6/settings/online-payments.md create mode 100644 docs/en/1.6/settings/payment-methods.md create mode 100644 docs/en/1.6/settings/quotes.md create mode 100644 docs/en/1.6/settings/taxes.md create mode 100644 docs/en/1.6/settings/taxrates.md create mode 100644 docs/en/1.6/settings/updatecheck.md create mode 100644 docs/en/1.6/settings/user-accounts.md create mode 100644 docs/en/1.6/system/importing-data.md create mode 100644 docs/en/1.6/system/index.md create mode 100644 docs/en/1.6/system/translation-localization.md create mode 100644 docs/en/1.6/system/upgrade-from-fusioninvoice.md create mode 100644 docs/en/1.6/templates/customize-templates.md create mode 100644 docs/en/1.6/templates/index.md create mode 100644 docs/en/1.6/templates/using-templates.md create mode 100644 mkdocs.yml create mode 100644 requirements.txt diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 0000000..5bc357d --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,31 @@ +name: Deploy Docs + +on: + push: + branches: + - main + - master + paths: + - 'docs/**' + - 'mkdocs.yml' + - 'requirements.txt' + workflow_dispatch: + +permissions: + contents: write + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Install dependencies + run: pip install -r requirements.txt + + - name: Deploy to GitHub Pages + run: mkdocs gh-deploy --force diff --git a/.gitignore b/.gitignore index 92bc51f..3efaff9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,6 @@ _ide_helper.php .env .idea +/site +__pycache__ +*.pyc diff --git a/convert_wiki.py b/convert_wiki.py new file mode 100644 index 0000000..e87a679 --- /dev/null +++ b/convert_wiki.py @@ -0,0 +1,269 @@ +#!/usr/bin/env python3 +"""Convert wiki/en/1_6 blade.php files to Markdown files in docs/en/1.6/.""" + +import os +import re +import sys +from pathlib import Path + +try: + from markdownify import markdownify as md +except ImportError: + print("Please install markdownify: pip install markdownify") + sys.exit(1) + +REPO_ROOT = Path(__file__).parent +SRC_DIR = REPO_ROOT / "wiki" / "en" / "1_6" +OUT_DIR = REPO_ROOT / "docs" / "en" / "1.6" + +# Blade source file → output markdown path (relative to OUT_DIR) +FILE_MAP = { + "root.blade.php": "index.md", + "getting_started.blade.php": "getting-started/index.md", + "modules.blade.php": "modules/index.md", + "settings.blade.php": "settings/index.md", + "system.blade.php": "system/index.md", + "templates.blade.php": "templates/index.md", + "general/about.blade.php": "general/about.md", + "general/changelog.blade.php": "general/changelog.md", + "general/faq.blade.php": "general/faq.md", + "general/license.blade.php": "general/license.md", + "getting_started/installation.blade.php": "getting-started/installation.md", + "getting_started/quickstart.blade.php": "getting-started/quickstart.md", + "getting_started/requirements.blade.php": "getting-started/requirements.md", + "getting_started/updating_ip.blade.php": "getting-started/updating-ip.md", + "help/setup_cron.blade.php": "help/setup-cron.md", + "modules/clients.blade.php": "modules/clients.md", + "modules/invoices.blade.php": "modules/invoices.md", + "modules/payments.blade.php": "modules/payments.md", + "modules/quotes.blade.php": "modules/quotes.md", + "modules/recurring_invoices.blade.php": "modules/recurring-invoices.md", + "modules/tasks_projects.blade.php": "modules/tasks-projects.md", + "settings/custom_fields.blade.php": "settings/custom-fields.md", + "settings/email.blade.php": "settings/email.md", + "settings/email_templates.blade.php": "settings/email-templates.md", + "settings/general.blade.php": "settings/general.md", + "settings/invoice_groups.blade.php": "settings/invoice-groups.md", + "settings/invoices.blade.php": "settings/invoices.md", + "settings/online_payments.blade.php": "settings/online-payments.md", + "settings/payment_methods.blade.php": "settings/payment-methods.md", + "settings/quotes.blade.php": "settings/quotes.md", + "settings/taxes.blade.php": "settings/taxes.md", + "settings/taxrates.blade.php": "settings/taxrates.md", + "settings/updatecheck.blade.php": "settings/updatecheck.md", + "settings/user_accounts.blade.php": "settings/user-accounts.md", + "system/importing_data.blade.php": "system/importing-data.md", + "system/translation_localization.blade.php": "system/translation-localization.md", + "system/upgrade_from_fusioninvoice.blade.php": "system/upgrade-from-fusioninvoice.md", + "templates/customize_templates.blade.php": "templates/customize-templates.md", + "templates/using_templates.blade.php": "templates/using-templates.md", +} + + +def extract_title(content: str) -> str: + m = re.search(r"@section\('title'\)\s*(.*?)\s*@endsection", content, re.DOTALL) + if m: + return m.group(1).strip() + return "" + + +def extract_body(content: str) -> str: + m = re.search(r"@section\('content'\)(.*?)@stop", content, re.DOTALL) + if m: + return m.group(1).strip() + return "" + + +def demote_headings(html: str) -> str: + """Shift h3→h2, h4→h3, h5→h4 in a single pass (h2.page-title already stripped).""" + def _open(m): + lvl = int(m.group(1)) + return f'' + + html = re.sub(r'])', _open, html, flags=re.IGNORECASE) + html = re.sub(r'', _close, html, flags=re.IGNORECASE) + return html + + +def preprocess(html: str) -> str: + # Remove PHP comment blocks + html = re.sub(r"<\?php\s*//[^\?]*\?>", "", html) + + # Remove IP::headlineLink calls (PHP echo) + html = re.sub(r"<\?=\s*IP::headlineLink\([^)]+\);\s*\?>", "", html) + + # Remove PHP trans() calls + html = re.sub(r"<\?php\s+echo\s+trans\([^)]+\)\s+\?>", "", html) + + # Remove entire PHP blocks (article_pagination arrays, etc.) + html = re.sub(r"<\?php\b.*?\?>", "", html, flags=re.DOTALL) + + # Convert Blade url() helper to plain URL + html = re.sub(r"\{\{\s*url\('([^']+)'\)\s*\}\}", r"/\1", html) + + # Convert Blade date() helpers to placeholders + html = re.sub(r"\{\{\s*date\('Y'\)\s*\}\}", "YYYY", html) + html = re.sub(r"\{\{\s*date\('m'\)\s*\}\}", "MM", html) + html = re.sub(r"\{\{\s*date\('d'\)\s*\}\}", "DD", html) + + # Protocol-relative image/link URLs → https + html = re.sub(r'(src|href)="//invoiceplane\.com/', r'\1="https://invoiceplane.com/', html) + html = re.sub(r'href="//invoiceplane\.com/', 'href="https://invoiceplane.com/', html) + + # Unwrap lightbox/thumbnail link wrappers (keep alt text from inner img) + # These are + # markdownify will handle them fine as image links + + # Remove h1 elements that are purely logo/image containers (e.g. root page logo) + html = re.sub(r']*>\s*(?:]*/?>|]*>.*?|\s)*', '', html, flags=re.DOTALL) + + # Remove Font Awesome icon spans/elements (they don't render in markdown) + html = re.sub(r']*>', "", html) + html = re.sub(r']*>', "", html) + html = re.sub(r']*>.*?', "", html, flags=re.DOTALL) + + # Convert alert divs to simpler HTML that markdownify can handle + html = re.sub( + r']*>(.*?)', + r'
Warning:\1
', + html, flags=re.DOTALL + ) + html = re.sub( + r']*>(.*?)', + r'
Note:\1
', + html, flags=re.DOTALL + ) + html = re.sub( + r']*>(.*?)', + r'
Danger:\1
', + html, flags=re.DOTALL + ) + html = re.sub( + r']*>(.*?)', + r'
Info:\1
', + html, flags=re.DOTALL + ) + + # Unwrap card containers (FAQ cards etc.) — just keep inner content + html = re.sub(r']+class="[^"]*card-header[^"]*"[^>]*>', '

', html) + html = re.sub(r']+class="[^"]*card-block[^"]*"[^>]*>', '
', html) + html = re.sub(r']+class="[^"]*card-body[^"]*"[^>]*>', '
', html) + html = re.sub(r']+class="[^"]*card[^"]*"[^>]*>', '
', html) + + # Unwrap table-responsive divs + html = re.sub(r']+class="table-responsive"[^>]*>', '
', html) + + # Unwrap feature grid divs (about page) + html = re.sub(r']+class="[^"]*col[^"]*"[^>]*>', '
', html) + html = re.sub(r']+class="[^"]*row[^"]*"[^>]*>', '
', html) + html = re.sub(r']+class="[^"]*jumbotron[^"]*"[^>]*>', '
', html) + html = re.sub(r']+class="[^"]*changelog[^"]*"[^>]*>', '
', html) + + # Remove remaining class/style/data attributes from divs to clean up + html = re.sub(r']+>', '
', html) + + # Remove id attributes from headings (markdownify will handle plain headings) + html = re.sub(r'(]+class="[^"]*(?:status|text)[^"]*"[^>]*>(.*?)', r'\1', html, flags=re.DOTALL) + html = re.sub(r']*>', '', html) + html = re.sub(r'', '', html) + + # Remove small tags (keep content) + html = re.sub(r'(.*?)', r'\1', html, flags=re.DOTALL) + + # Fix broken HTML attribute in about page + html = html.replace('target?"_blank"', 'target="_blank"') + + # Strip target="_blank" attributes (not relevant in markdown) + html = re.sub(r'\s+target="_blank"', '', html) + html = re.sub(r'\s+class="ext"', '', html) + html = re.sub(r'\s+class="thumbnail"', '', html) + html = re.sub(r'\s+data-lightbox="[^"]*"', '', html) + html = re.sub(r'\s+rel="lightbox"', '', html) + + # Handle that are inside - keep the link but add meaningful alt + # markdownify handles this natively + + # Strip the h2.page-title element — the title is prepended separately. + # If a page-title h2 is present, also demote other headings (h3→h2, h4→h3, h5→h4) + # so sections end up at ##. Root page has no page-title h2, so no demotion needed. + has_page_title = bool(re.search(r']+class="page-title"[^>]*>', html)) + html = re.sub(r']+class="page-title"[^>]*>.*?

', '', html, flags=re.DOTALL) + if has_page_title: + html = demote_headings(html) + + # Remove inline styles + html = re.sub(r'\s+style="[^"]*"', '', html) + + return html + + +def blade_to_markdown(src_path: Path) -> str: + content = src_path.read_text(encoding="utf-8") + + title = extract_title(content) + body_html = extract_body(content) + + if not body_html: + return f"# {title}\n" + + body_html = preprocess(body_html) + + markdown = md( + body_html, + heading_style="ATX", + bullets="-", + code_language="", + strip=["script", "style"], + ) + + # Prepend the page title as h1 + if title: + markdown = f"# {title}\n\n" + markdown + + # Collapse 3+ consecutive blank lines to 2 + markdown = re.sub(r'\n{3,}', '\n\n', markdown) + + # Strip leading/trailing whitespace per line (but preserve code blocks) + lines = markdown.split('\n') + cleaned = [] + in_code = False + for line in lines: + if line.startswith('```'): + in_code = not in_code + if not in_code: + cleaned.append(line.rstrip()) + else: + cleaned.append(line) + markdown = '\n'.join(cleaned) + + return markdown.strip() + '\n' + + +def main(): + created = [] + for src_rel, out_rel in FILE_MAP.items(): + src_path = SRC_DIR / src_rel + out_path = OUT_DIR / out_rel + + if not src_path.exists(): + print(f" SKIP (not found): {src_rel}") + continue + + out_path.parent.mkdir(parents=True, exist_ok=True) + markdown = blade_to_markdown(src_path) + out_path.write_text(markdown, encoding="utf-8") + created.append(out_rel) + print(f" OK: {src_rel} → {out_rel}") + + print(f"\nConverted {len(created)} files to {OUT_DIR}") + + +if __name__ == "__main__": + main() diff --git a/docs/en/1.6/general/about.md b/docs/en/1.6/general/about.md new file mode 100644 index 0000000..db29ef2 --- /dev/null +++ b/docs/en/1.6/general/about.md @@ -0,0 +1,38 @@ +# About InvoicePlane + +![Preview for InvoicePlane](https://invoiceplane.com/assets/img/preview.jpg) + +InvoicePlane is a self-hosted open source application for managing your quotes, invoices, clients, tasks and +payments. +Downloaded more than 100 000 times from 196 countries. + +## Quotes, Invoices, Payments + +InvoicePlane is a solid app to manage your complete billing circle: from quotes over invoices to +payments. + +## Manage your Clients + +The application provides CRM-like management for your clients. Enter contact details, notes or +add custom fields to add any information you want. + +## Customize InvoicePlane + +You can customize InvoicePlane to make sure it fits your needs: amount format, languages, email +and PDF templates and many more. + +## One-Click Online Payments + +Let your clients pay the invoices by using Stripe (other payment providers to come, please open an issue on [GitHub](https://github.com/InvoicePlane/InvoicePlane/issues) if you are missing a provider). + +## Multilanguage Interface + +InvoicePlane is fully translated into 23 languages by community members and more languages are +coming soon. + +## Projects and Tasks + +Create projects for different clients, add some task and you can reference them directly inside +invoices. + +[Learn more on InvoicePlane.com](https://invoiceplane.com/) diff --git a/docs/en/1.6/general/changelog.md b/docs/en/1.6/general/changelog.md new file mode 100644 index 0000000..c034df1 --- /dev/null +++ b/docs/en/1.6/general/changelog.md @@ -0,0 +1,32 @@ +# Changelog + +### v1.6.0 released 2022-12-04 + +Changes + +- [IP-798]: Prepare for PHP 8.1 compatibility release by @vtq221, @Ordissimo and of course @naui95 in #831 +- fix to CVE-2021-29024 #735 by @naui95 in #754 +- Don't show upload-path by @zeitschlag in #739 +- fix for CVE-2021-29023 #733 by @naui95 in #767 +- Fix for outdated card data handling #814 by @naui95 in #816 +- Trivial typo fix by @pimvanpelt in #788 +- Fix bug with recurring invoices dropping discounts by @pimvanpelt in #791 +- Fix Payment Method Select by @tridnguyen in #805 +- Escape client name for PDF generation (Only in Zugferd invoices) by @Forceu in #810 +- [IP-711] Add responsive view for invoices/quotes by @nielsdrost7 in #783 +- fix minor flaws in quotes itemlist view by @der-peer in #787 +- Develop by @yvesmethz in #774 +- Display $client surname for recurring invoices by @giacy86 in #811 +- Select appropriate pdf template for guest users by @giacy86 in #765 +- update composer and javascript packages by @nielsdrost7 in #822 +- Create SECURITY.md by @zidingz in #752 +- Update composer and javascript packages by @nielsdrost7 in #776 +- Create SECURITY.md by @dagelf in #797 +- Quick bugfix with a nullable value +- Fix in the npm packages to make the yarn build work + +You can find the full changelog with references to the code at [this link](https://github.com/InvoicePlane/InvoicePlane/releases/tag/v1.6.0). + +> **Warning:** +> +> Changelogs concerning **older versions** of InvoicePlane can be found in the relevant section of the given version. diff --git a/docs/en/1.6/general/faq.md b/docs/en/1.6/general/faq.md new file mode 100644 index 0000000..6e9c367 --- /dev/null +++ b/docs/en/1.6/general/faq.md @@ -0,0 +1,107 @@ +# FAQ - Frequently Asked Questions + +## General + +### Can I sell / redistribute InvoicePlane? + +InvoicePlane is a free software and it will never be a commercial product! We +appeal everyone to respect the open source InvoicePlane project and our work and refrain from +selling the application as their own product! +What you can do: offer paid professional support or hosting for InvoicePlane. + +However InvoicePlane is an open source software released under [MIT license](http://choosealicense.com/licenses/mit/). This means that you can use +the code *but* the InvoicePlane name and the logo are copyright by Invoiceplane.com and +Kovah.de +This means you **have to** use another name and logo for the product and include the original InvoicePlane license in the code. + +For more information about licensing please visit the [InvoicePlane website](https://invoiceplane.com/license-copyright). + +## Errors + +### You have problems and need help? Use the debug mode. + +You have a problem with some errors, you are stuck and need help? We would like to help you but first +we need some help from you: error logs. + +1. Enable the debug mode by replacing `ENABLE_DEBUG=false` with + `ENABLE_DEBUG=true` in the `/ipconfig.php` file. +2. Try again what caused the error, e.g. creating a new invoice which does not work. +3. Get the log files: + - Open the folder `/application/logs/`, open the log file with the current date + and copy the whole content. + - Take a look at your web server error logs. + - Open the console of your browser ([tutorial](http://webmasters.stackexchange.com/a/77337/20720)), the + error may be logged there. +4. Save the content of the log files and the output of the browser console to [Paste.InvoicePlane.com](https://paste.invoiceplane.com/) and post this link + with a detailed description to the [Community + Forums](https://community.invoiceplane.com). + You will get further help there. + +### I copied InvoicePlane to my webserver but I get blank pages or an error 404 or 500 + +Please make sure you copied the .htaccess file (hidden file on Unix systems) and you installed and +enabled mod\_rewrite for Apache. + +If you want to install InvoicePlane in a sub-directory like `yourdomain.com/invoices/` +please follow the instructions for the [installation in a +subdirectory](/en/1.5/getting-started/installation#subdir). + +### There is a large spinning cog () after I clicked a button and now nothing happens + +This problem occurs if the application is stuck because of an error. Please follow the instructions +for the [debug mode](#debugmode) + +### I can't add more than 3 or 4 items to quotes or invoices + +This problem may occurs because of a configuration of your nginx webserver. The server error should +look like this: + +``` +upstream sent too big header while reading response header from upstream +``` + +To solve this problem you should try to add / update your nginx configuration with the following +settings: + +``` +proxy_buffer_size 128k; +proxy_buffers 4 256k; +proxy_busy_buffers_size 256k; +``` + +or + +``` +fastcgi_buffer_size 128k; +fastcgi_buffers 4 256k; +fastcgi_busy_buffers_size 256k; +``` + +Please check [this comment](http://stackoverflow.com/a/27551259/1203515) for +more details. + +## Settings + +### Where can I set the default invoice / quote groups? + +You can set the default invoice / quote groups at `System settings > Invoices > Default Invoice +Group` for invoices and `System settings > Quotes > Default Quote Group` for +quotes. + +## Customization + +### How can I customize the templates? + +You can find all templates in the following directories: + +**Invoices** + +`/application/views/invoice_templates/` + +**Quotes** + +`/application/views/quote_templates/` + +The templates are using basic HTML, CSS and PHP. If you just want to change the styling you just need +some knowledge of HTML and CSS. +If you want to include Custom Fields into the templates please refer to the [Custom Fields page](/en/1.5/settings/custom-fields#add-to-template). diff --git a/docs/en/1.6/general/license.md b/docs/en/1.6/general/license.md new file mode 100644 index 0000000..e43e259 --- /dev/null +++ b/docs/en/1.6/general/license.md @@ -0,0 +1,113 @@ +# License for InvoicePlane + +## Copyright + +The name 'InvoicePlane' and the InvoicePlane logo are original copyright +of InvoicePlane.com / Kovah.de and the following restrictions apply to +both of them: + +**You are allowed to:** + +- use the name 'InvoicePlane' or the InvoicePlane logo in any context directly + related to the application or the project. This includes the application itself, + local communities and news or blog posts about InvoicePlane or +- use the name 'InvoicePlane' or the InvoicePlane logo to provide professional support or hosting for the InvoicePlane application. + +**You are not allowed to:** + +- use the name 'InvoicePlane' or the InvoicePlane logo in any context that is **not** related to the project, +- alter the name 'InvoicePlane' or the InvoicePlane logo in any way or +- sell or redistribute the application under the name 'InvoicePlane' and the InvoicePlane logo. + +--- + +## InvoicePlane Usage Permits + +- [Softaculous](http://www.softaculous.com/) is permitted to add InvoicePlane to their AutoInstaller. + +--- + +## License + +================================================== +License for InvoicePlane +================================================== +Copyright (c) 2012-2014 InvoicePlane.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The name (InvoicePlane) and the logo can be used in any context related to +InvoicePlane as application or project but may not be changed / altered in +any way. The name and the logo are both original copyright by InvoicePlane.com +and Kovah.de + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +================================================== +License for CodeIgniter +================================================== +Copyright (c) 2008 - 2011, EllisLab, Inc. +All rights reserved. + +This license is a legal agreement between you and EllisLab Inc. for the use +of CodeIgniter Software (the "Software"). By obtaining the Software you +agree to comply with the terms and conditions of this license. + +PERMITTED USE +You are permitted to use, copy, modify, and distribute the Software and its +documentation, with or without modification, for any purpose, provided that +the following conditions are met: + +1. A copy of this license agreement must be included with the distribution. + +2. Redistributions of source code must retain the above copyright notice in +all source code files. + +3. Redistributions in binary form must reproduce the above copyright notice +in the documentation and/or other materials provided with the distribution. + +4. Any files that have been modified must carry notices stating the nature +of the change and the names of those who changed them. + +5. Products derived from the Software must include an acknowledgment that +they are derived from CodeIgniter in their documentation and/or other +materials provided with the distribution. + +6. Products derived from the Software may not be called "CodeIgniter", +nor may "CodeIgniter" appear in their name, without prior written +permission from EllisLab, Inc. + +INDEMNITY +You agree to indemnify and hold harmless the authors of the Software and +any contributors for any direct, indirect, incidental, or consequential +third-party claims, actions or suits, as well as any related expenses, +liabilities, damages, settlements or fees arising from your use or misuse +of the Software, or a violation of any terms of this license. + +DISCLAIMER OF WARRANTY +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR +IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF QUALITY, PERFORMANCE, +NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. + +LIMITATIONS OF LIABILITY +YOU ASSUME ALL RISK ASSOCIATED WITH THE INSTALLATION AND USE OF THE SOFTWARE. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS OF THE SOFTWARE BE LIABLE +FOR CLAIMS, DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE. LICENSE HOLDERS ARE SOLELY RESPONSIBLE FOR DETERMINING THE +APPROPRIATENESS OF USE AND ASSUME ALL RISKS ASSOCIATED WITH ITS USE, INCLUDING +BUT NOT LIMITED TO THE RISKS OF PROGRAM ERRORS, DAMAGE TO EQUIPMENT, LOSS OF +DATA OR SOFTWARE PROGRAMS, OR UNAVAILABILITY OR INTERRUPTION OF OPERATIONS. diff --git a/docs/en/1.6/getting-started/index.md b/docs/en/1.6/getting-started/index.md new file mode 100644 index 0000000..3125f5f --- /dev/null +++ b/docs/en/1.6/getting-started/index.md @@ -0,0 +1,6 @@ +# Getting Started + +- [Requirements](/en/1.6/getting-started/requirements) +- [Installation](/en/1.6/getting-started/installation) +- [Quickstart (Tutorial)](/en/1.6/getting-started/quickstart) +- [Updating InvoicePlane](/en/1.6/getting-started/updating-ip) diff --git a/docs/en/1.6/getting-started/installation.md b/docs/en/1.6/getting-started/installation.md new file mode 100644 index 0000000..856bd5b --- /dev/null +++ b/docs/en/1.6/getting-started/installation.md @@ -0,0 +1,53 @@ +# Installation + +For those of you comfortable with installing web applications, installing InvoicePlane should take 5 minutes or +less. + +1. [Download](https://invoiceplane.com/downloads) and extract the archive. +2. Create an empty database on your web server. +3. Upload the files to your web server, either into a subdirectory or into the public root of the web server. +4. Make a copy of the `ipconfig.php.example` file and rename the copy to `ipconfig.php` +5. Open the `ipconfig.php` file and add your URL in it like described in the file. +6. Comment out the first line of the `ipconfig.php` file by adding a `#` at the beginning of the line as described at **pt. 2** [here](updating-ip#160-2-replace-files) +7. Run the InvoicePlane installer from your web browser and follow his instructions: `http://your-domain.com/index.php/setup` + +Once the installer finished, the installation is complete and you may log into InvoicePlane using the email +address and password you have chosen during the installation. + +## Run InvoicePlane in a sub directory + +If you want to run InvoicePlane in a sub directory (e.g. `http://yourdomain.com/invoices/`) you have +to modify the `.htaccess` file which is located in the root directory. You must add the line + +``` +RewriteBase /sub-directory +``` + +where `sub-directory` is the directory you want to use. The content of the file should look like this: + +``` +RewriteEngine on +RewriteBase /sub-directory +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule . index.php [L] +``` + +After that, open your `ipconfig.php` file and add the sub directory to your URL like this: + +``` +http://your-domain.com/sub-directory +``` + +Notice that there is **no** trailing slash. + +## Remove index.php from the URL + +Please notice that this step is entirely optional and does not affect the application in any way. + +1. Make sure that [mod\_rewrite](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html) is enabled on your web + server. +2. Open the file `ipconfig.php` +3. Search for `REMOVE_INDEXPHP=false` in this file and replace it with + `REMOVE_INDEXPHP=true` +4. Rename the `htaccess` file to `.htaccess` diff --git a/docs/en/1.6/getting-started/quickstart.md b/docs/en/1.6/getting-started/quickstart.md new file mode 100644 index 0000000..9510110 --- /dev/null +++ b/docs/en/1.6/getting-started/quickstart.md @@ -0,0 +1,77 @@ +# Quickstart + +## Logging In + +If InvoicePlane was installed into the root of your web server: + +`http://www.your-domain.com` + +If InvoicePlane was installed into its own subdirectory of your web server: + +`http://www.your-domain.com/the-subdirectory` + +--- + +## Configure the Application + +Before you start with invoicing you should check the application settings on `http://www.your-domain.com/settings` +and set for example the currency, how the amounts should be formatted and so on. + +More information about available settings can be found on the [Settings](/en/1.6/modules/settings) +page. + +--- + +## Adding a Client + +Click `Clients` from the main menu at the top of the page and select `Add Client`. Fill in +as much information as needed and submit the form. + +More information about the client management can be found on the [Clients](/en/1.6/modules/clients) +page. + +--- + +## Adding Products + +If you have products which should appear on your invoices or quotes you can create them form the +`Products` menu. + +More information about products can be found on the [Products](/en/1.6/modules/products) +page. + +--- + +## Creating an Invoice + +Click `Invoices` from the main menu at the top of the page and select `Create Invoice`. +Start typing the client name into the `Client` box. If the client already exists in InvoicePlane, +select the client from the list which appears after you start typing. If the client does not already exist in +InvoicePlane, continue typing the client\'s name and that client will be added as a new record. +Then choose the invoice date and invoice group and submit the form. + +If you added some products before you can simply add them via the `Add Product` button left from the +`Save` button. If you want to enter some items manually you can use the empty row or +add new rows with the `Add new Row` button. + +### Send the invoice + +If viewing a list of invoices, click the `Options` button on the row of the invoice to send. If +viewing a single invoice, click the Options button near the top right of the page. Select `Send +Email` from the `Options` button, review the information and submit the form. The client +will receive an email with the invoice attached as a PDF. + +--- + +## Entering a Payment + +Offline payments are entered by clicking `Payments` from the main menu at the top of the page and +selecting `Enter Payment`. Fill in the appropriate information and submit the form to enter the +payment. + +Online payments allow a client to pay their invoice online. When an online payment occurs, the payment is +automatically entered back into InvoicePlane, eliminating the need to manually enter an offline payment. Online +payments require additional setup before they can be used. + +More information about payments can be found on the [Payments](/en/1.6/modules/payments) +page. diff --git a/docs/en/1.6/getting-started/requirements.md b/docs/en/1.6/getting-started/requirements.md new file mode 100644 index 0000000..685c75d --- /dev/null +++ b/docs/en/1.6/getting-started/requirements.md @@ -0,0 +1,28 @@ +# Requirements + +If you want to use InvoicePlane you have to follow these requirements to use the application. + +- A webserver / shared hosting with the following specifications: + - MySQL >= 5.5 or the equivalent version of MariaDB + - Apache >= 2.4 or Ngnix >= 1.20.0 + - PHP >= 8.0 and <= 8.1 + - The following PHP extensions must be installed and activated: + - php-bcmath + - php-dom + - php-gd + - php-hash + - php-json + - php-mbstring + - php-mcrypt + - php-mysqli + - php-openssl + - php-recode + - php-xml + - php-xmlrpc + - php-zlib +- An up-to-date web browser. We do recommend using either [Firefox](https://www.mozilla.org/en-US/firefox/new/), [Microsoft Edge](https://www.microsoft.com/en-us/edge), the latest version of + [Safari](https://www.apple.com/safari) or any of the other leading browsers around the internet. Please note that since Microsoft introduced [Microsoft Edge](https://www.microsoft.com/en-us/edge), Internet Explorer is not supported anymore. + +> **Warning:** +> Please notice that PHP < 8 is no longer supported and should **not** be used anymore for producton +> environments! (see [php version support](https://www.php.net/supported-versions.php) for more information) diff --git a/docs/en/1.6/getting-started/updating-ip.md b/docs/en/1.6/getting-started/updating-ip.md new file mode 100644 index 0000000..23bf966 --- /dev/null +++ b/docs/en/1.6/getting-started/updating-ip.md @@ -0,0 +1,83 @@ +# Update InvoicePlane + +## Contents + +- [Upgrade information](#general) +- [Breaking changes](#16-breaking-changes) +- [**Upgrade instructions (v1.6.2 to v1.6.3)**](#162-163-instructions) + 1. Preliminary operations + 2. Replace files & test +- [Upgrade instructions (v1.5.11 to v1.6.0)](#1511-16-instructions) + 1. Preliminary operations + 2. Replace files & test + +--- + +## Upgrade information + +#### Breaking changes (v1.6.0) + +InvoicePlane 1.6 is based (as its versions before) on CodeIgniter v3 which officially still does not support PHP >=8.0. The InvoicePlane Community updated InvoicePlane specific components to make InvoicePlane PHP >=8.0 compatible, but not all features could be successfully ported; we will continue to put our efforts into porting the features we could not port with this upgrade. The breaking changes are: + +- InvoicePlane 1.6.0 supports only Stripe as a payment gateway for online payments (please let us know what payment method you are missing at [GitHub](https://github.com/InvoicePlane/InvoicePlane/issues)). + +## Instructions to upgrade to 1.6.3 from 1.6.2 + +#### 1. Preliminary operations + +Follow the procedure outlined in [Upgrade 1.6.0 from 1.5.11](#160-1-preliminary-operations) + +#### 2. Replace files & test + +1. Copy all files to the root directory of your InvoicePlane installation but **do not** overwrite the + following files: + - The `ipconfig.php` file + - Customized templates in the `application/views/` folder + - The files for custom styles: `assets/core/css/custom.css` and `assets/core/css/custom-pdf.css` + - Uploaded images in the `uploads/` folder (e. g. your company logo) + - Custom language keys at `application/language/COUNTRY/custom_lang.php` + > **Note:** + > + > **Hint:** An *easy* way of performing this operation is to upload the whole new InvoicePlane version in a different folder, outside of your current installation root folder, and copy the above mentioned files in the new folder you just uploaded. Afterwards just rename your current folder to something like `my_current_folder_old` and rename your new-version-folder with the name of `my_current_folder`. +2. Open `http://yourdomain.com/index.php/setup` and follow the instructions. The app will run all + updates on its own. + - If you encounter any errors when upgrading the table, press "Try Again" to resolve those errors and continue with the setup. +3. Now that the update is installed, moved and protected, it's time to log in and see if everything is working: login again and check if everything is working. + +## Instructions to upgrade to 1.6.0 from 1.5.11 + +#### 1. Preliminary operations + +1. Make a backup of your database and all files. (This is **very important** to prevent any data loss) +2. Download the latest version from [InvoicePlane.com](https://invoiceplane.com/downloads). + +#### 2. Replace files & test + +1. Copy all files to the root directory of your InvoicePlane installation but **do not** overwrite the + following files: + - The `ipconfig.php` file + - Customized templates in the `application/views/` folder + - The files for custom styles: `assets/core/css/custom.css` and `assets/core/css/custom-pdf.css` + - Uploaded images in the `uploads/` folder (e. g. your company logo) + - Custom language keys at `application/language/COUNTRY/custom_lang.php` + > **Note:** + > + > **Hint:** An *easy* way of performing this operation is to upload the whole new InvoicePlane version in a different folder, outside of your current installation root folder, and copy the above mentioned files in the new folder you just uploaded. Afterwards just rename your current folder to something like `my_current_folder_old` and rename your new-version-folder with the name of `my_current_folder`. +2. Now that the files are placed, it's time to fix the `ipconfig.php` file. + + - open `ipconfig.php` and comment out the top line in the file by adding a `#` at the beginning of the first line. The result should be like this: + + ``` + # + ``` + - close the `ipconfig.php` file +3. #### Open `http://yourdomain.com/index.php/setup` and follow the instructions + + . The app will run all + updates on its own. + - If you encounter any errors when upgrading the table, press "Try Again" to resolve those errors and continue with the setup. +4. Now that the `ipconfig.php` file is fixed, moved and protected, it's time to log in and see if everything is working + - Login again and check if everything is working. + - If you were using the online payments module please navigate to `//your-domain.com/settings` and to the tab `online payment` and disable all payment methods that are not *stripe*. InvoicePlane 1.6 at the moment supports only Stripe as a payment gateway. + +> **Note:** diff --git a/docs/en/1.6/help/setup-cron.md b/docs/en/1.6/help/setup-cron.md new file mode 100644 index 0000000..92648f6 --- /dev/null +++ b/docs/en/1.6/help/setup-cron.md @@ -0,0 +1,43 @@ +# Help: Setup a Cron + +If you want to use [recurring invoices](/en/1.6/modules/recurring-invoices) you have to +setup a cron +that opens the URL listed on the recurring invoices page. A cron is basically a script that runs on predefined +times. You can setup a cron that runs every minute, every third hour per day or yearly. For recurring invoices +you should run the cron daily. + +There are two different ways on how to setup a cron: + +- use you own web server or +- use an online service that runs the cron for you. + +### Use your own Server + +As there are various different types of operating software for web servers (e.g. Ubuntu, CentOS, Windows Server +or even Mac OSX Server) there is not *one* tutorial on how to setup a cron. Because of this we listed +tutorials for the most used systems below and wrote an example for Unix-based operating systems. + +- [Ubuntu](https://help.ubuntu.com/community/CronHowto) +- [CentOS](https://www.centos.org/docs/5/html/Deployment_Guide-en-US/ch-autotasks.html) +- [Windows Server (2008)](http://www.myscienceisbetter.info/add-new-cron-job-on-windows-2008-server-using-task-scheduler.html) + +**Example for Unix-based systems** + +Open the crontab file with `crontab -e` and paste the following line: + +``` +0 0 * * * wget -O - https://yoursite.com/invoices/cron/recur/your-cron-key >/dev/null 2>&1 +``` + +where `yoursite.com` is the domain you use for InvoicePlane and `your-cron-key` the cron +key from your settings. + +### Use an Online Service + +There are a lot of online services that offer running a cron for you, for example +[cron-job.org](https://cron-job.org/en/), +[FastCron](https://www.fastcron.com/tutorials/invoiceplane-cron) +or any other. + +Please read the documentation of the service you use to know how to setup a cron with their +system. diff --git a/docs/en/1.6/index.md b/docs/en/1.6/index.md new file mode 100644 index 0000000..f75a38f --- /dev/null +++ b/docs/en/1.6/index.md @@ -0,0 +1,56 @@ +# InvoicePlane Wiki + +## Welcome to the InvoicePlane Wiki + +If you want to know how to use InvoicePlane or if you have any +questions take a look at this wiki. You should find a lot of useful information about the software and each +module. + +## About InvoicePlane + +- [What is InvoicePlane?](/en/1.6/general/about) +- [Changelog](/en/1.6/general/changelog) +- [License](/en/1.6/general/license) +- [FAQ](/en/1.6/general/faq) + +## Getting started + +- [Requirements](/en/1.6/getting-started/requirements) +- [Installation](/en/1.6/getting-started/installation) +- [Quickstart (Tutorial)](/en/1.6/getting-started/quickstart) +- [Updating InvoicePlane](/en/1.6/getting-started/updating-ip) + +## Modules + +- [Clients](/en/1.6/modules/clients) +- [Quotes](/en/1.6/modules/quotes) +- [Invoices](/en/1.6/modules/invoices) +- [Recurring Invoices](/en/1.6/modules/recurring-invoices) +- [Payments](/en/1.6/modules/payments) + +## Settings + +- [General Settings](/en/1.6/settings/general) +- [Invoice Settings](/en/1.6/settings/invoices) +- [Quotes Settings](/en/1.6/settings/quotes) +- [Tax Settings](/en/1.6/settings/taxes) +- [eMail Settings](/en/1.6/settings/email) +- [Online Payments](/en/1.6/settings/online-payments) +- [Updatecheck](/en/1.6/settings/updatecheck) +- [Custom Fields](/en/1.6/settings/custom-fields) +- [eMail Templates](/en/1.6/settings/email-templates) +- [Invoice Groups](/en/1.6/settings/invoice-groups) +- [Payment Methods](/en/1.6/settings/payment-methods) +- [Taxrates](/en/1.6/settings/taxrates) +- [User Accounts](/en/1.6/settings/user-accounts) + +## Templates + +- [Using Templates](/en/1.6/templates/using-templates) +- [Customize Templates](/en/1.6/templates/customize-templates) + +## System + +- [Translation / Localization](/en/1.6/system/translation-localization) +- [Importing Data](/en/1.6/system/importing-data) +- [Upgrade from FusionInvoice](/en/1.6/system/upgrade-from-fusioninvoice) diff --git a/docs/en/1.6/modules/clients.md b/docs/en/1.6/modules/clients.md new file mode 100644 index 0000000..c88767f --- /dev/null +++ b/docs/en/1.6/modules/clients.md @@ -0,0 +1,37 @@ +# Clients + +## View Clients + +To view the client list, click `Clients` from the main menu and select `View Clients`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_clients.jpg)](https://invoiceplane.com/content/screenshots/web/ip_clients.jpg) + +By default, the client list will be filtered to active clients only. The filter can be set to either +`Active`, `Inactive` or `All` by choosing the filter from the submenu bar. +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu with a number of items when clicked: + +- `View` - View the client +- `Edit` - Edit the client +- `Create Quote` - Create a quote for the client +- `Create Invoice` - Create an invoice for the client +- `Delete` - Delete the client + +## Add new Clients + +To add a new client, either choose `Clients` from the main menu and select `Add Client`, or +from the client list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_clients_add.jpg)](https://invoiceplane.com/content/screenshots/web/ip_clients_add.jpg) + +When adding a new client, the only field required is the `Client Name` field, although if you plan to +email invoices and quotes to your clients, the `Email Address` field should be filled in as well. Any +[custom fields](/en/1.6/settings/custom-fields) created for client records will display at the bottom +of the client form. + +## Client Logins + +Clients can be granted permission to log into InvoicePlane to view their quotes and invoices, approve or reject +quotes and pay their invoices. See the `Guest Account` section of the [User Accounts](/en/1.6/settings/user-accounts) page for instructions on creating logins for +your clients. diff --git a/docs/en/1.6/modules/index.md b/docs/en/1.6/modules/index.md new file mode 100644 index 0000000..daa55ea --- /dev/null +++ b/docs/en/1.6/modules/index.md @@ -0,0 +1,7 @@ +# Modules + +- [Clients](/en/1.6/modules/clients) +- [Invoices](/en/1.6/modules/quotes) +- [Invoices](/en/1.6/modules/invoices) +- [Recurring Invoices](/en/1.6/modules/recurring-invoices) +- [Payments](/en/1.6/modules/payments) diff --git a/docs/en/1.6/modules/invoices.md b/docs/en/1.6/modules/invoices.md new file mode 100644 index 0000000..d737dd8 --- /dev/null +++ b/docs/en/1.6/modules/invoices.md @@ -0,0 +1,157 @@ +# Invoices + +## The Invoice Lifecycle + +Invoice statuses follow the lifecycle of an invoice from draft to paid and allow you to keep track of where each +of your invoices are in their lifecycle. Each of the statuses listed below are automatically set for you when +specific activity occurs with an invoice, but you may also choose to manually change the status at any time +during the invoice lifecycle. + +- Draft + When an invoice is first created, it is placed in Draft status by default. Sending an invoice by email will + automatically change the status from Draft to Sent. Clients cannot view any invoices when they are in Draft + status. +- Sent + When InvoicePlane sends an invoice to a client by email, it will place the invoice in Sent status. This + occurs when using the Send Email function and it also occurs when a recurring invoice is automatically + emailed. Clients can view any of their invoices when they are in Sent status. +- Viewed + When a client views the invoice by either using the Guest URL to view the invoice or by using their Guest + Login account (if they have one), the invoice will be placed in Viewed status. This allows you to keep track + of which invoices a client has looked at. +- Paid + Once an online or offline payment has been made in full against an invoice, the invoice will be placed in + Paid status. +- Overdue + Any invoice with a due date prior to the current date will be visible as being overdue. Overdue invoices + appear in invoice lists with a red due date so they are easily seen. + +Besides this lifecycle an invoice can have two other statuses: + +- Read Only + An invoice will be set to read-only if the status was changed to paid. The invoice can't be edited anymore + but you can create a credit invoice if something went wrong or needs to be changed. +- Credit Invoice + A credit invoice can be created from an existing invoice and will make a duplicate of the invoice but with a + negative amount. This means by default that the balance of both invoices is zero. + +## Viewing Invoices + +To view the invoice list, click `Invoices` from the main menu and select `View Invoices`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices.jpg) + +By default, the invoice list will show all invoices. The filter can be set to `All`, `Draft`, `Sent`, `Viewed`, +`Paid` or `Overdue` by choosing the filter from +the submenu bar. +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu with a number of items when clicked: + +- `Edit` - View the quote +- `Download PDF` - Download a copy of the quote as PDF +- `Send Email` - Send the quote to the client via email +- `Enter Payment` - Enter a payment for this invoice +- `Delete` - Delete the invoice\* + +\* This is only available for invoices with the draft status or if Invoice Deletion was enabled. + +## Creating an Invoice + +To create a new invoice, either choose `Invoices` from the main menu and select `Create +Invoice`, or from the invoice list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_add.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_add.jpg) + +When creating a invoice, start typing the name of the client to create the invoice for. If it\'s an existing +client, choose their name from the list that appears. If it's a new client, type their full name or business +name. Choose the date and invoice group and press the `Submit` button. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_edit.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_edit.jpg) + +The `Options` button near the top of the edit invoice page displays a menu with a number of items when +clicked: + +- `Add Invoice Tax` - Apply a tax to the entire invoice +- `Enter Payment` - Enter a payment for the invoice +- `Download PDF` - Download a copy of the invoice as PDF +- `Send Email` - Send the invoice to the client via email +- `Copy Invoice` - Create a copy of the invoice +- `Create Recurring` - Set the invoice to recurring +- `Delete` - Delete the invoice\* + +\* Invoice deletion is not available for all invoices. Please read the information for [invoice deletion](/en/1.6/modules/invoices#delete). + +### Add Products + +To add saved products, press the `Add Product` button. Choose the product you want to add and mark the +checkbox on the left, then press `Submit` to insert the products into the quote. +You can edit the quantity, prices or taxes for each product. When finished, press the `Save` button. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_add_product.jpg)](https://invoiceplane.com/content/screenshots/web/ip_add_product.jpg) + +### Changing Item Order + +The order in which an item appears on a quote or invoice can be changed by dragging the row to a new position +with the icon. + +### Discounts + +With the release of InvoicePlane 1.4.0 we introduced discounts for each quotes and invoices. There are two separate types of discounts which can by applied: + +- Item Discounts +- Invoice Discounts + +#### Item Discounts + +Item discounts can be added for each item itself as an amount that will be subtract from the item subtotal. Item discounts can only be added as an amount, not as an percentage. + +#### Invoice Discounts + +Invoice discounts can be added for the whole invoice directly above the invoice total. You can either choose to add a discount as an amount (e.g. 200 $) or as a percentage of the subtotal (e.g. 5%). + +### Adding Taxes + +To apply a tax against the entire invoice, choose `Add Invoice Tax` from the Options button. Choose +the appropriate tax rate and placement from the window that appears and press the `Submit` button. +That tax will be calculated against the invoice total. + +> **Warning:** +> Caution! Do not mix item and invoice taxes. Both tax methods were implemented for countries with different law structures and do not work together very well. If you use both tax method at the same time we can't promise that all calculations are executed correctly. +> +> Also, do **not** use item taxes to apply any service charges or similar extra charges. If you need to apply charges, add a new item or calculate the charges manually. + +### Copying an Invoice + +To copy an invoice, choose `Copy Invoice` from the `Options` menu. Change the client name, +if appropriate, and then select the invoice date and invoice group and press the `Submit` button. All items, taxes and amounts from the source invoice will be copied +to a new invoice. + +--- + +## Invoice Deletion + +By default InvoicePlane prevents the deletion of invoices because it's legally forbidden to delete invoices that +were sent to customers. We decided that it should be not possible to delete invoices that are beyond the `Draft` status. +But you can still enable invoice deletion even if it's not recommended. Open `/application/config/config.php` +and replace +`$config['enable_invoice_deletion'] = FALSE;` +with +`$config['enable_invoice_deletion'] = TRUE;` +To see the delete option in the pulldown, you also need to replace +`$config['disable_read_only'] = FALSE;` +with +`$config['disable_read_only'] = TRUE;` + + +Read only needs to be disabled, otherwise the options menu is not complete. + +## Read-only + +InvoicePlane will set invoices to read-only based on its status and the invoice can't be changed anymore. You can +change the status that will be used for the read-only mode in the settings. +If you don't want invoices to be set to read-only you can disable this feature. Open `/application/config/config.php` +and replace +`$config['disable_read_only'] = FALSE;` +with +`$config['disable_read_only'] = TRUE;` diff --git a/docs/en/1.6/modules/payments.md b/docs/en/1.6/modules/payments.md new file mode 100644 index 0000000..295d13c --- /dev/null +++ b/docs/en/1.6/modules/payments.md @@ -0,0 +1,45 @@ +# Payments + +## View Payments + +To view the payment list, click `Payments` from the main menu and select `View Payments`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payments.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payments.jpg) + +To navigate between pages, use the pager buttons located on the submenu bar. + +## Entering a Payment + +To enter a payment, either choose `Payments` from the main menu and select `Enter Payment`, +or from the payment list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payments_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payments_form.jpg) + +When entering a payment, first select the invoice to enter the payment for. This will default the invoice amount +into the Amount field. Adjust the date and amount, if necessary, and optionally select the payment method and +enter any pertinent notes and press the `Save` button near the top right of the page. + +## Online Payments + +InvoicePlane can be configured to allow clients to make payments online. The only payment gateway currently +tested with InvoicePlane is Stripe. + +### Configure Stripe for Online Payments + +To configure InvoicePlane integration with Stripe, you must first have a valid Stripe API Secret Key. If you +don't, follow [these +instructions](https://stripe.com/docs/keys#create-api-secret-key) first to obtain the credentials. + +Once you have your API credentials, perform the following in InvoicePlane: + +1. Click the `Settings` icon and choose the `System Settings` entry. +2. Click the `online payment` tab. +3. Set `Enable Online Payments` to `Yes`. +4. Choose `Stripe` as a merchant driver (only one available in InvoicePlane 1.6). +5. Enter the Secret Key and the Publishable Key obtained from Stripe. +6. Select the appropriate currency code. +7. Press the `Save` button. + +Once configured, send your client the `Guest URL` (found at the bottom of the Invoice Edit screen) and +they will be able to pay their invoice from the link. Optionally, you can also create a Guest User account in +which the client can log into and view and pay their invoices. diff --git a/docs/en/1.6/modules/quotes.md b/docs/en/1.6/modules/quotes.md new file mode 100644 index 0000000..b4364cd --- /dev/null +++ b/docs/en/1.6/modules/quotes.md @@ -0,0 +1,124 @@ +# Quotes + +## The Quote Lifecycle + +Quote statuses follow the lifecycle of a quote from draft to approved and allow you to keep track of where each +of your quotes are in their lifecycle. Each of the statuses listed below are automatically set for you when +specific activity occurs with a quote but you may also choose to manually change the status at any time during +the quote lifecycle. + +- Draft + When a quote is first created, it is placed in Draft status by default. Sending a quote by email will + automatically change the status from Draft to Sent. Clients cannot view any quotes when they are in Draft + status. +- Sent + When InvoicePlane sends a quote to a client by email the status will be changed to Sent. +- Viewed + When a client views the quote by either using the Guest URL to view quote or by using their Guest Login + account (if they have one), the quote will be placed in Viewed status. This allows you to keep track of + which quotes a client has looked at. +- Approved + When a client uses the guest URL to view a quote or logs in using a guest account and views a quote, they + are able to either approve or reject the quote. When a client approves a quote, the status is changed to + Approved. +- Rejected + When a client uses the guest URL to view a quote or logs in using a guest account and views a quote, they + are able to either approve or reject the quote. When a client rejects a quote, the status is changed to + Rejected. +- Canceled + This status can be used for quotes that are not going to make it to the invoicing stage but need to be kept + for reference purposes. Clients are not able to see quotes in this status. + +## Viewing Quotes + +To view the quote list, click `Quotes` from the main menu and select `View Quotes`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes.jpg) + +By default, the quote list will be filtered to all quotes. The filter can be set to `All`, `Draft`, `Sent`, `Viewed`, +`Approved`, `Rejected` or `Canceled` by choosing the filter from the submenu bar. +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu with a number of items when clicked: + +- `Edit` - View the quote +- `Download PDF` - Download a copy of the quote as PDF +- `Send Email` - Send the quote to the client via email +- `Delete` - Delete the quote + +## Creating a Quote + +To create a new quote, either choose `Quotes` from the main menu and select `Create Quote`, +or from the quote list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes_add.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes_add.jpg) + +When creating a quote, start typing the name of the client to create the quote for. If it's an existing client, +choose their name from the list that appears. If it's a new client, type their full name or business name. +Choose the date and invoice group and submit the form. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes_edit.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes_edit.jpg) + +The `Options` button near the top of the edit quotes page displays a menu with a number of items when +clicked: + +- `Add Quote Tax` - Apply a tax to the entire quote +- `Download PDF` - Download a copy of the quote as PDF +- `Send Email` - Send the quote to the client via email +- `Quote to Invoice` - Convert the quote to an invoice +- `Copy Quote` - Create a copy of the quote +- `Delete` - Delete the quote + +### Adding Products + +To add saved products, press the `Add Product` button. Choose the product you want to add and mark the +checkbox on the left, then press `Submit` to insert the products into the quote. +You can edit the quantity, prices or taxes for each product. When finished, press the `Save` button. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_add_product.jpg)](https://invoiceplane.com/content/screenshots/web/ip_add_product.jpg) + +### Changing Item Order + +The order in which an item appears on a quote or invoice can be changed by dragging the row to a new position +with the icon. + +### Discounts + +With the release of InvoicePlane 1.4.0 we introduced discounts for each quotes and invoices. There are two separate types of discounts which can by applied: + +- Item Discounts +- Quote Discounts + +#### Item Discounts + +Item discounts can be added for each item itself as an amount that will be subtract from the item subtotal. Item discounts can only be added as an amount, not as an percentage. + +#### Quote Discounts + +Quote discounts can be added for the whole quote directly above the quote total. You can either choose to add a discount as an amount (e.g. 200 $) or as a percentage of the subtotal (e.g. 5%). + +### Add Tax to Quote + +To apply a tax against the entire quote, choose `Add Quote Tax` from the `Options` button. +Choose the appropriate tax rate and placement from the window that appears and press the `Submit` +button. That tax will be calculated against the quote total. + +> **Warning:** +> Caution! Do not mix item and quote taxes. Both tax methods were implemented for countries with different law structures and do not work together very well. If you use both tax method at the same time we can't promise that all calculations are executed correctly. +> +> Also, do **not** use item taxes to apply any service charges or similar extra charges. If you need to apply charges, add a new item or calculate the charges manually. + +### Copying the Quote + +To copy a quote, choose `Copy Quote` from the `Options` button on the edit quote page. +Change the client name, if appropriate, and then select the quote date and quote group and submit the form. All +items, taxes and amounts from the source quote will be copied to a new quote. + +### Generate Invoice from Quote + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes_quote_to_invoice.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes_quote_to_invoice.jpg) + +When a client accepts a quote, you can convert that quote to an invoice by using the `Quote to +Invoice` menu item from the `Options` button. Choose the invoice date and invoice group and +press the `Submit` button. The items from the quote will be copied over to your new +invoice. diff --git a/docs/en/1.6/modules/recurring-invoices.md b/docs/en/1.6/modules/recurring-invoices.md new file mode 100644 index 0000000..a955e02 --- /dev/null +++ b/docs/en/1.6/modules/recurring-invoices.md @@ -0,0 +1,40 @@ +# Recurring Invoices + +Oftentimes instead of sending an invoice as a one time charge, you need to send an email to a client on a +schedule. For example, you may be offering web hosting to your clients, and most likely they are paying for your +services once a month, once a year, etc. It would be a bummer to have to remember to create these invoices every +month, wouldn't it? InvoicePlane can keep this sorted for you. + +## Requirements + +For recurring invoices to generate properly, you must create a [CRON job](/en/1.6/help/setup_cron) or +a scheduled task that opens the following URL once per day: + +``` +http://your-domain.com/invoices/cron/recur/your-cron-key-here +``` + +Replace `your-cron-key-here` with the generated cron key in [System +Settings](/en/1.6/settings/general). + +## Create a recurring Invoice + +To create an invoice which will automatically recur at a specific frequency, the first step is to create the +first invoice and get it sent to your client as you normal would. Once the first invoice has been created, it +can be set up as a recurring invoice by selecting `Create Recurring` from the `Options` +menu. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_make_recurring.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_make_recurring.jpg) + +The invoice can be set to recur every week, month, year, quarter or six months. Since the first invoice has +already been created, the start date should be set to the next date this particular invoice should recur on. +Generally the start date should be a date in the future. If the invoice should stop recurring on a particular +date, then enter an end date as well. If the invoice should recur perpetually, then leave the end date +empty. + +## Viewing Recurring Invoices + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_recurring.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_recurring.jpg) + +The list of recurring invoices displays each recurring invoice set up in your system. Recurring invoices may be +stopped or deleted from the `Options` button in the list of recurring invoices. diff --git a/docs/en/1.6/modules/tasks-projects.md b/docs/en/1.6/modules/tasks-projects.md new file mode 100644 index 0000000..8eaa5c5 --- /dev/null +++ b/docs/en/1.6/modules/tasks-projects.md @@ -0,0 +1,38 @@ +# Tasks and Projects + +InvoicePlane provides basic task management that is integrated into the invoice workflow. You can link tasks to projects and projects to clients to structure everthing. + +## Projects + +Projects can be added from the navigation bar. You can chose the project name and a client. Choosing a client is optional. If you choose a client, tasks that are assigned to this project can onl be added to invoices for the same client. + +## Tasks + +Tasks can be added from the navigation bar. They have several fields that are explained in the following table. + +| Field | Description | +| --- | --- | +| Task name | The title or name of the task. Normally a short headword or sentence | +| Task description | Can contain a long text that discribes the task. Can also be used to store notes. | +| Task price | The price set here will be used in invoices to properly store tasks. The task price is the same as the product price. | +| Tax Rate | Task tax rates are the same like product tax rates. It will be added to the task price if added to an invoice. | +| Finish date | Also called deadline, it defines the date where the task should be finished. Tasks are displayed as overdue (red color) if the finish date has already passed. | +| Status | The task status defines the current state of the task. More information can be found below. | +| Project | This optional select can be used to link tasks to projects. | + +### Task Status + +A task can have one off the following statuses. Please notice that only completed tasks can be added to invoices. + +| Status | Description | +| --- | --- | +| Not started | The title or name of the task. Normally a short headword or sentence | +| In progress | The task is currently in progress. Someone works on the task. | +| Completed | The task was completed and is ready to be added to an invoice. | + +### Tasks in Invoices + +Inside invoices you can add tasks to an invoice. Therefore, use the "Add Task" button. This will open a new panel where all available tasks will be listed. Please notice that the following requirements must be fullfilled for a tasks to be available: + +- the task must be have the status Completed. +- the task must either have no linked project or the client of the current invoice must match theclient that is assigned to the linked project. diff --git a/docs/en/1.6/settings/custom-fields.md b/docs/en/1.6/settings/custom-fields.md new file mode 100644 index 0000000..ca9cebd --- /dev/null +++ b/docs/en/1.6/settings/custom-fields.md @@ -0,0 +1,28 @@ +# Custom Fields + +Custom fields can be created to store information which InvoicePlane doesn\'t provide fields for. Custom fields +can be created for: + +- Clients +- Quotes +- Invoices +- Payments +- User Accounts + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_custom_fields.jpg)](https://invoiceplane.com/content/screenshots/web/ip_custom_fields.jpg) + +## Adding a Custom Field + +To add a new custom field click on the settings icon in the menubar and +then choose `Custom Fields`. On the overview click on `New` in the top right. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_custom_fields_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_custom_fields_form.jpg) + +When adding custom fields, it is recommended to only use alpha and numeric characters for the label name. Once a +custom field has been added to an object, the custom field will display at the bottom of the form for that +object (so a custom field created for the client object will appear on the client form). + +## Adding Custom Fields to Templates + +Please take a look at the [Customize Templates +page](/en/1.6/templates/customize-templates#custom-fields) for more information about custom fields in templates. diff --git a/docs/en/1.6/settings/email-templates.md b/docs/en/1.6/settings/email-templates.md new file mode 100644 index 0000000..49f5b0f --- /dev/null +++ b/docs/en/1.6/settings/email-templates.md @@ -0,0 +1,31 @@ +# Email Templates + +Instead of having to type the body of an email each time an invoice or quote is emailed from InvoicePlane, email templates can be customized to your liking, giving you a set of predefined templates to choose from. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_email_templates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_email_templates.jpg) + +## Creating an Email Template + +To create a new email template, click the settings icon near the right hand side of the main menu, select `Email Templates`, and click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_email_templates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_email_templates.jpg) + +Template variables can be inserted into the body of your email by clicking the name of the variable to include from the list below the form. The example above shows what an email template for a new invoice might look like. + +## Setting Default Email Templates + +To access the settings for your default templates, click the settings icon , select `System Settings`, and choose either the `Invoices` or the `Quotes` tab + +**Invoices** + +- Default Email Template - The selected template would be used for invoices in draft, sent and viewed statuses. +- Paid Email Template - The selected template would be used for invoices in paid status. +- Overdue Email Template - The selected template would be used for invoices which are overdue. + +**Quotes** + +- Default Email Template - The selected template would be used for all quotes in any status. +- Paid Email Template - The selected template would be used for invoices in paid status. +- Overdue Email Template - The selected template would be used for invoices which are overdue. + +When manually sending an invoice or quote from within InvoicePlane, the appropriate email template will be selected prior to sending. Of course, you may make any last minute adjustments to the content of the email before sending it. Since recurring invoices send email on their own without any manual intervention, it is helpful to have a set of email templates created and the default settings configured so InvoicePlane knows which template to use each time it sends them out. diff --git a/docs/en/1.6/settings/email.md b/docs/en/1.6/settings/email.md new file mode 100644 index 0000000..99833bd --- /dev/null +++ b/docs/en/1.6/settings/email.md @@ -0,0 +1,12 @@ +# Email Settings + +Before InvoicePlane can send emails you have to configure he email settings here. You can choose between three different ways to send emails. +If you don't want that invoice and quote pdf files are automatically attached to emails disable this feature by changing `Attach Quote/Invoice on email?` to `No` + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_mail.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_mail.jpg) + +| Method | Description | +| --- | --- | +| PHP Mail | Uses the built-in email sending method of PHP which allows to send mails without any configuration. | +| Sendmail | Like PHP Mail all emails will be sent without the need to configure anything. Please choose Sendmail only if you are sure that your server has Sendmail installed, enabled and configured because it is possible that your servers OS does not ship with Sendmail by default. | +| SMTP | You can also use a SMTP server to send mails. Using SMTP allows you to send emails via external servers. You will need the SMTP server's hostname, login credentials and the used port and security method. | diff --git a/docs/en/1.6/settings/general.md b/docs/en/1.6/settings/general.md new file mode 100644 index 0000000..a6064e8 --- /dev/null +++ b/docs/en/1.6/settings/general.md @@ -0,0 +1,45 @@ +# General Settings + +The general settings page sets a lot of options that will change the look & feel of the whole application or +that are needed for some special purposes. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_general.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_general.jpg) + +## General settings + +| Setting | Description | +| --- | --- | +| Language | Choose the [language](/en/1.6/system/translation-localization) for the application | +| First day of the Week | Choose if the week should start on sunday or monday | +| Default Country | Select the country that will be used automatically when adding clients | +| Date Format | Choose the date format of the application | +| Currency Symbol | Choose the currency symbol like `€` or `$`. You can also use any letters like `AUD` or `CHF` | +| Currency Symbol Placement | Choose if the currency symbol should be placed before or after amounts | +| Thousand Separator | Select if thousands should be separated by `,` or `.` | +| Decimal Point | Select if the decimals point should be `,` or `.` | +| Tax Rate Decimal Places | Select how much placed after the decimal point should be used for tax rates. | + +## Dashboard settings + +| Setting | Description | +| --- | --- | +| Quote Overview Period | Select the period that should be used for quotes on the quote overview | +| Invoice Overview Period | Select the period that should be used for invoices on the invoice overview | + +## Interface settings + +| Setting | Description | +| --- | --- | +| Disable the Sidebar | Choose if the sidebar should be disabled | +| Custom Title | Set a custom title which will be shown on browser tabs | +| Use Monospace font for Amounts | Choose if the application should use a monospace font for amounts. Example: `1.345,23 €` | +| Login Logo | Upload an image that will be displayed above the login form. Recommended size: about 300px width | +| Cron Key | You will need this cron key to setup [recurring invoices](/en/1.6/modules/recurring-invoices). | + +## System settings + +| | | +| --- | --- | +| Send all outgoing emails as BCC to the admin account | If you enable this option **every** outgoing email is sent as an anonymous copy (BCC) to the administrator. The administrator is the user that was created during the InvoicePlane setup. | +| Cron Key | You will need this cron key to setup [recurring invoices](/en/1.6/modules/recurring-invoices) | +| Enable Debug Mode | The debug mode enables logging for the application. The logs can be found in the `/application/logs` folder or in your browser console. | diff --git a/docs/en/1.6/settings/index.md b/docs/en/1.6/settings/index.md new file mode 100644 index 0000000..38e1cc2 --- /dev/null +++ b/docs/en/1.6/settings/index.md @@ -0,0 +1,15 @@ +# Settings + +- [General Settings](/en/1.6/settings/general) +- [Invoice Settings](/en/1.6/settings/invoices) +- [Quotes Settings](/en/1.6/settings/quotes) +- [Tax Settings](/en/1.6/settings/taxes) +- [eMail Settings](/en/1.6/settings/email) +- [Online Payments](/en/1.6/settings/online-payments) +- [Updatecheck](/en/1.6/settings/updatecheck) +- [Custom Fields](/en/1.6/settings/custom-fields) +- [eMail Templates](/en/1.6/settings/email-templates) +- [Invoice Groups](/en/1.6/settings/invoice-groups) +- [Payment Methods](/en/1.6/settings/payment-methods) +- [Taxrates](/en/1.6/settings/taxrates) +- [User Accounts](/en/1.6/settings/user-accounts) diff --git a/docs/en/1.6/settings/invoice-groups.md b/docs/en/1.6/settings/invoice-groups.md new file mode 100644 index 0000000..4ac882d --- /dev/null +++ b/docs/en/1.6/settings/invoice-groups.md @@ -0,0 +1,41 @@ +# Invoice Groups + +When a new invoice or quote is created, InvoicePlane uses invoice groups to determine the next invoice or quote number and how it should be structured. InvoicePlane comes with two default invoice groups - Invoice Default and Quote Default. Both groups will generate simple incremental ID's starting at the number 1, but the Quote Default will be prefixed with "QUO". + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoice_groups.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoice_groups.jpg) + +## Configure an Invoice Group + +These default groups can be customized and any number of new groups can be created. Each group has a number of options. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoice_groups_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoice_groups_form.jpg) + +| Setting | Description | +| --- | --- | +| Name | The name if the invoice group that will be used in the settings | +| Identifier formatting | The identifier is used to generate invoices or quotes and can consist of alpha-numeric characters | +| Next ID | Set the ID for the next invoice. Please notice that you should not set the next ID to a number below the ID of the last generated ID. Example: You created 59 invoices but you want the next invoice to have the ID 100 so set the Next ID to 100. | +| Left Pad | The left padding can be used to generate IDs that contain zeros to the left of the ID. The left padding contains the invoice ID itself. Example: you set the left padding to 5 which would lead to invoice IDs like 00056 or 00397. | + +### Format the Identifier + +> **Warning:**Caution! The identifier **must** contain the `{{{ID}}}` tag no matter where! + +There are some template tags that can be used to create a custom identifier. + +| Name | Tag | Description | +| --- | --- | --- | +| ID | `{{{ID}}}` | Inserts the increasing ID of the invoice | +| Current Year | `{{{year}}}` | Inserts the current year with 4 digits | +| Current month | `{{{month}}}` | Inserts the current month with 2 digits | +| Current day | `{{{day}}}` | Inserts the current day with 2 digits | + +### Formatting Examples + +| Template | Output | +| --- | --- | +| `{{{year}}}/{{{ID}}}` | YYYY/456 | +| `{{{year}}}_{{{month}}}_{{{ID}}}` | YYYY\_MM\_456 | +| `{{{year}}}-{{{month}}}-{{{day}}}-{{{ID}}}` | YYYY-MM-DD-456 | +| `IN{{{year}}}{{{ID}}}` | INYYYY456 | +| `IPQ-{{{day}}}{{{ID}}}` | IPQ-DD456 | diff --git a/docs/en/1.6/settings/invoices.md b/docs/en/1.6/settings/invoices.md new file mode 100644 index 0000000..7970766 --- /dev/null +++ b/docs/en/1.6/settings/invoices.md @@ -0,0 +1,21 @@ +# Invoice Settings + +On the invoice settings page you can set a lot of options to control how invoices should behave. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_invoices.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_invoices.jpg) + +## General settings + +| Setting | Description | +| --- | --- | +| Default Invoicegroup | Select the [Invoicegroup](/en/1.6/settings/invoicegroups) that should be used by default | +| Set the Invoice to read-only on | Select on which state an invoice should be set to read-only | +| Invoice due after | Select after how many days an invoice should be set to due | +| Default Terms | You can enter the default terms for any invoice here | +| Automatically email recurring invoices | If you have recurring invoices you can choose if InvoicePlane should send an email with the invoice attached to the client automatically | +| Mark Invoices as sent when PDF is generated | Choose if InvoicePlane should set the status of an invoice to `Sent` when you download the PDF | +| Invoice Logo | Upload an image that should be placed on templates. | + +## Templates + +All following settings allow you to set default PDF and email templates for different states and purposes. At the end in the PDF Footer you can enter information that should be placed at the bottom of each PDF template. diff --git a/docs/en/1.6/settings/online-payments.md b/docs/en/1.6/settings/online-payments.md new file mode 100644 index 0000000..bc107b6 --- /dev/null +++ b/docs/en/1.6/settings/online-payments.md @@ -0,0 +1,25 @@ +# Merchant Account Settings + +InvoicePlane 1.6 supports only **Stripe** by default as a payment gateway. The reason why the other providers were dropped can be found [here](/en/1.6/getting-started/updating-ip#16-breaking-changes). Please let us know what payment method you are missing at [GitHub](https://github.com/InvoicePlane/InvoicePlane/issues) + +### Configure your payment provider + +To configure your payment provider, select the provider from the dropdown list. If you don't know which provider should be selected please contact your provider. We cannot offer any support for specific provider settings. + +After selecting a provider InvoicePlane will show you a configuration box will all needed settings. Make sure to enable the provider first. After that fill all needed information. Again: if you are not shure which fields to fill, contact your provider. + +> **Warning:**It is highly recommended to test if the online payment is working correctly using the **Test Mode** if available. This allows you to pay online without transfering real money. + +### Configure **Stripe** as a payment provider + +1. Login or regiser for an account at [stripe.com](https://stripe.com) +2. Once you logged in, on the top search bar look for the `API Keys` page. +3. Create a new *secret key*. +4. Now, open the `settings` in your InvoicePlane installation and navigate to the `online payment` tab. +5. Tick the `Enable Online Payments` checkbox. +6. From the dropdown list select `Stripe` as a payment provider. +7. Tick the `enable` checkbox on the stripe card that appeared when you selected stripe as a payment provider in the last step. +8. Insert the secret key and the publishable key in the corrisponding fields. The secret key must be set in the field that hides the characters (like a password). +9. Click on **save**, and you are done! + +Please take note that InvoicePlane is in no way affiliated to Stripe and that we are not able to help with Stripe specific issues. These instructions only concern integrating Stripe as a payment gateway in InvoicePlane. diff --git a/docs/en/1.6/settings/payment-methods.md b/docs/en/1.6/settings/payment-methods.md new file mode 100644 index 0000000..c700cbf --- /dev/null +++ b/docs/en/1.6/settings/payment-methods.md @@ -0,0 +1,13 @@ +# Payment Methods + +Payment Methods + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payment_methods.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payment_methods.jpg) + +## Add a Payment Method + +To add a new payment method, click the settings icon near the right hand side of the main menu, select `Payment Methods`, and click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payment_methods_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payment_methods_form.jpg) + +Simply enter the name of the payment method and click on `Save` button. The method will be available when adding a payment. diff --git a/docs/en/1.6/settings/quotes.md b/docs/en/1.6/settings/quotes.md new file mode 100644 index 0000000..29a9c3c --- /dev/null +++ b/docs/en/1.6/settings/quotes.md @@ -0,0 +1,17 @@ +# Quote Settings + +The general settings page sets a lot of options that will change the look & feel of the whole application or that are needed for some special purposes. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_quotes.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_quotes.jpg) + +## General settings + +| Setting | Description | +| --- | --- | +| Quote expires after | Choose after how many days a quote should be set to expired | +| Default Quotegroup | Select the [Quotegroup (aka Invoicegroups)](/en/1.6/settings/invoicegroups) that should be used by default | +| Mark Quotes as sent when PDF is generated | Choose if InvoicePlane should set the status of an quote to `Sent` when you download the PDF | + +## Templates + +All following settings allow you to set default PDF and email templates for different states and purposes. diff --git a/docs/en/1.6/settings/taxes.md b/docs/en/1.6/settings/taxes.md new file mode 100644 index 0000000..163d399 --- /dev/null +++ b/docs/en/1.6/settings/taxes.md @@ -0,0 +1,11 @@ +# Tax Settings + +The general settings page sets a lot of options that will change the look & feel of the whole application or that are needed for some special purposes. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_taxes.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_taxes.jpg) + +| Setting | Description | +| --- | --- | +| Default Invoice Tax Rate | Choose the [Taxrate](/en/1.6/settings/taxrates) that should be applied to an invoice by default | +| Default Invoice Tax Rate | Choose where to place the invoice tax | +| Default Invoice Tax Rate | Choose the [Taxrate](/en/1.6/settings/taxrates) that should be applied to every product of an invoice by default | diff --git a/docs/en/1.6/settings/taxrates.md b/docs/en/1.6/settings/taxrates.md new file mode 100644 index 0000000..575271d --- /dev/null +++ b/docs/en/1.6/settings/taxrates.md @@ -0,0 +1,13 @@ +# Taxrates + +If you want to add taxes to products / items or invoices you have to configure them on the Taxrates settings page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_taxrates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_taxrates.jpg) + +## Add a new Taxrate + +To add a new taxrate, click the settings icon near the right hand side of the main menu, select `Taxrates`, and click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_taxrates_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_taxrates_form.jpg) + +First enter the official name of the taxrate. Be careful as this will be displayed on quotes or invoices as a description of the taxrate. Then enter the percentage of the taxrate and click on `Save`. diff --git a/docs/en/1.6/settings/updatecheck.md b/docs/en/1.6/settings/updatecheck.md new file mode 100644 index 0000000..ff440fa --- /dev/null +++ b/docs/en/1.6/settings/updatecheck.md @@ -0,0 +1,6 @@ +# Updatecheck + +On the updatecheck page InvoicePlane checks for updates with contacting our website. The result of the check will be displayed below the version. +Additionally the latest news will be displayed below the updatecheck. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_updates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_updates.jpg) diff --git a/docs/en/1.6/settings/user-accounts.md b/docs/en/1.6/settings/user-accounts.md new file mode 100644 index 0000000..cd79dc2 --- /dev/null +++ b/docs/en/1.6/settings/user-accounts.md @@ -0,0 +1,70 @@ +# User Accounts + +InvoicePlane can contain an unlimited number of user accounts (both Administrator and Guest), but there is no +real level of ownership or separation between different administrator accounts. Each administrator account has +full access to the entire system and can see all data system-wide. Guest accounts are read-only and can be +restricted to see invoices, quotes and payments for the client or clients you specify. + +## User Types + +**Administrator** + +An administrator account has full access to the entire system. Administrators can create and delete clients, +invoices, payments, users, and everything else in the system. The account created during installation is an +administrator account. If you don't want somebody having full access to all of your data, do not create an +administrator account for them. + +**Guest (Read Only)** + +There may be times where you need to allow a user into your system, but with limited access. Guest accounts allow +you to create a user account which can only view quotes, invoices and payments for one or more clients. A guest +account may be created for a particular client, in which case you would create the account and grant access to +only that client. A guest account may also be created for an accountant, in which case you might create the +account and grant access to more than just one client. + +## Viewing Users + +To view the user list, click the settings icon near the right hand side +of the main menu and select `User Accounts`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts.jpg) + +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu from which you can edit or delete an user. + +## Add an User Account + +To add a new user account, click the settings icon near the right hand +side of the main menu, select `User Accounts`, and click the `New` button near the top +right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts_form.jpg) + +To create the user account, provide the user's name (typically their full name), email address (this is what +they'll use to log in with), password and password verification. When selecting the user type, choose between +`Administrator` or `Guest`. Once the user type has been selected, the rest of the form +will display below the initial form. + +If `Administrator` was selected as the user type, several fields will be made available to complete, +such as their address and location information and contact information. Fill in the fields and press the `Save` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts_form.jpg) + +If `Guest` was selected as the user type, an area will be made available from which you can give +access to one or more clients for the `Guest` user account. To provide access to a single client, +press the `Add Client` button, begin typing the name of the client in to the form and select the +client when they appear in the list. Press the `Submit` button. If you want you can add +another client to the user account. If not press `Cancel`. Don't forget to save the user +account. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts_add_client.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts_add_client.jpg) + +If a guest account is not a client, but instead an accountant, you will probably want to provide them with access +to more than just a single client. In that case, press the `Add Client` button, begin typing the name +of the first client in to the form and select the client when they appear in the list. Press the `Submit` button and begin typing the next client name. Rinse, wash and repeat until +each client the guest should have access to has been added to the list. Press the Close button and then press +the `Save` button near the top of the page when finished. + +No matter if the account is an Administrator account or a Guest account, all users use the same URL to log in. Be +sure and provide your login URL to any users who you create accounts for. diff --git a/docs/en/1.6/system/importing-data.md b/docs/en/1.6/system/importing-data.md new file mode 100644 index 0000000..f252793 --- /dev/null +++ b/docs/en/1.6/system/importing-data.md @@ -0,0 +1,57 @@ +# Importing Data + +InvoicePlane can import data from any system as long as it is provided in comma delimited CSV format and is +structured according to the details below. The data import tool can be accessed by clicking the Settings icon +and choosing the Import Data item. + +The import tool assumes the following: + +The file names will be exactly as they are listed below. +All of the columns listed below must be present in the files, even if there is no data in the column. +The first row of each file must contain the file headings, and those headings must be named exactly as they are +listed below. +The files must all be in comma delimited CSV format. +The files to import must be located in your uploads/import folder. +The email address in the invoice file must be an email address of an actual user account currently in +InvoicePlane. +If any of the rules above are not met, the import will not work as expected. + +**File names and columns** + +- clients.csv + - client\_name + - client\_address\_1 + - client\_address\_2 + - client\_city + - client\_state + - client\_zip + - client\_country + - client\_phone + - client\_fax + - client\_mobile + - client\_email + - client\_web + - client\_vat\_id + - client\_tax\_code + - client\_active (1 for active, 0 for inactive) +- invoices.csv + - user\_email + - client\_name + - invoice\_date\_created (yyyy-mm-dd format) + - invoice\_date\_due (yyyy-mm-dd format) + - invoice\_number + - invoice\_terms +- invoice\_items.csv + - invoice\_number + - item\_tax\_rate (ex: 7.8 would indicate 7.8%) + - item\_date\_added (yyyy-mm-dd format) + - item\_name + - item\_description + - item\_quantity + - item\_price (without any currency symbols) +- payments.csv + - invoice\_number + - payment\_method (ex: Cash, Credit or PayPal) + - payment\_date (yyyy-mm-dd format) + - payment\_amount (without any currency symbols) + - payment\_note diff --git a/docs/en/1.6/system/index.md b/docs/en/1.6/system/index.md new file mode 100644 index 0000000..8148219 --- /dev/null +++ b/docs/en/1.6/system/index.md @@ -0,0 +1,5 @@ +# System + +- [Translation / Localization](/en/1.6/system/translation-localization) +- [Importing Data](/en/1.6/system/importing-data) +- [Upgrade from FusionInvoice](/en/1.6/system/upgrade-from-fusioninvoice) diff --git a/docs/en/1.6/system/translation-localization.md b/docs/en/1.6/system/translation-localization.md new file mode 100644 index 0000000..5593632 --- /dev/null +++ b/docs/en/1.6/system/translation-localization.md @@ -0,0 +1,63 @@ +# Translation / Localization + +InvoicePlane comes with the English language by default. To contribute to or to download other language packs +please visit the [translation repository](https://crowdin.com/project/invoiceplane). + +## Install a new translation + +> **Warning:** +> Please notice: some translations are not complete so some texts will be displayed in English. So do not delete +> the english language folder! + +1. Download the translation pack from the [translation + repository](https://crowdin.com/project/invoiceplane) +2. Open the folder of the language you want to install (`de` = German) +3. Copy the folder that should be called something like `de_DE`, `fr_FR` or + `es_AR` +4. Paste the folder to the following directory of your InvoicePlane installation: + `/application/language/` +5. Apply the language in your [general settings](/en/1.6/settings/general). + +Your folder structure should look like this: + +``` +├── application/ +│ ├── ... +│ ├── language/ +│ │ ├── english/ +│ │ └── Deutsch/ +│ │ ├── custom_lang.php +│ │ ├── ip_lang.php +│ │ ├── merchant_lang.php +│ │ └── ... +│ └── ... +├── assets/ +└── ... +``` + +## Customize translations + +You are able to replace all language strings in the application with your own strings. We added a file called `custom_lang.php` which is located in every language folder (see above). + +To replace or alter a translation, search for the string in the main language files (ip\_lang.php). You have to copy the whole line with the string into the `custom_lang.php` file that it looks like this: + +``` + 'Actual content of the Language String', + +); +``` + +Now, simply change the translation to whatever you need. But keep in mind that some strings are designed to fit into special spaces. Try to keep the character count or the original string. + +> **Danger:** +> If you want to use the `'` character in your string you have to replace it with `\'`. +> Example: `'language_string_key' => 'Description with \'quotes\'',` diff --git a/docs/en/1.6/system/upgrade-from-fusioninvoice.md b/docs/en/1.6/system/upgrade-from-fusioninvoice.md new file mode 100644 index 0000000..bc426af --- /dev/null +++ b/docs/en/1.6/system/upgrade-from-fusioninvoice.md @@ -0,0 +1,32 @@ +# Upgrade form FusionInvoice + +If you used FusionInvoice v.1x to manage your invoices you can migrate to InvoicePlane. +Follow these steps to +migrate your installation. + +## Make a full Backup + +Actually you don't have to make a full backup of your FusionInvoice setup but we recommend to do so. We can not +guarantee that the [Migrationtool](https://github.com/InvoicePlane/Migrationtool) is working without +problems. +Make a complete copy of the folder that holds your installation and make a backup of your +database. + +## Use the Migrationtool + +1. [Download the Migrationtool](https://github.com/InvoicePlane/Migrationtool/archive/master.zip) + and unzip it to any directory on your webserver or your local machine and check if you copied the `.htaccess` + file. +2. If you want to run the tool in a subdirectory please set the directory in the `config.php` file. +3. Then open the URL which can access the Migrationtool and follow the instructions. + +> **Warning:**Please do **not** use multiple directories like `yourdomain.com/tools/migration/migrationtool` +> as the tool only supports one directory at the moment. + +## Run the InvoicePlane Updates + +After converting the database it's very important that you open the setup wizard +of your InvoicePlane installation located at `yourdomain.com/setup`. Follow the instructions and the +setup will run any necessary database updates. Without these updates InvoicePlane will not run. + +> **Note:** diff --git a/docs/en/1.6/templates/customize-templates.md b/docs/en/1.6/templates/customize-templates.md new file mode 100644 index 0000000..856e2da --- /dev/null +++ b/docs/en/1.6/templates/customize-templates.md @@ -0,0 +1,160 @@ +# Customize Templates + +For the customization you just need some little knowledge of HTML and CSS. PHP knowledge is not needed by +default but may help if you want to achieve special layouts or functions. + +> **Warning:** +> Please remember: Before doing any customizations, make a copy of a default template! If you make changes in the +> default templates they will be overwritten on updates. + +> **Note:** +> Hint: PDF templates will be generated with a PDF engine called mPDF. This means that some styles may not work +> because of conversion from HTML to PDF. If you need help with styling please refer to the [mPDF documentation](https://mpdf.github.io/). + +## Customize the Look and Feel + +First of all please remember that there is a basic styling for each template. The files use two CSS stylesheets +and some hardcoded styles. If you want to customize your template you should make changes in the hardcoded part +which means: edit the content between `` only. Do not +edit the templates.css as changes will be overwritten on updates. + +## First Steps + +InvoicePlane already provides a lot of data for all templates. The table below gives you an overview on which +variables are available in the templates. + +### Invoice Templates + +| Variable | Description | +| --- | --- | +| `$invoice` | It holds data about the invoice itself, the user that created the invoice and the client that is selected for the invoice. It also provides all payments if there are any in the database. | +| `$invoice_tax_rates` | Provides information about all tax rates that were applied to the invoice | +| `$items` | Contains all invoice items with their corresponding data. | +| `$payment_method` | Provides information about the selected payment method. | +| `$custom_fields` | Contains custom fields for the invoice, the user, the client and if available for the parent quote. | +| `$show_item_discounts` | Is true if there are any items with a discount, is false if not. Can be used to display the additional discount column only if there are discounts to display. | + +### Quote Templates + +| Variable | Description | +| --- | --- | +| `$quote` | It holds data about the quotes itself, the user that created the quote and the client that is selected for the quotes. | +| `$quote_tax_rates` | Provides information about all tax rates that were applied to the quote. | +| `$items` | Contains all quote items with their corresponding data. | +| `$custom_fields` | Contains custom fields for the quote, the user and the client. | +| `$show_item_discounts` | Is true if there are any items with a discount, is false if not. Can be used to display the additional discount column only if there are discounts to display. | + +If you want to know which data is available in every variable go to the bottom of the template and add the +following code directly above the `` tag. Replace *invoice* with the name of the +variable your want to look up. + +``` +
+``` + +If you load the template now you will see something like this but with hundred more lines: + +``` +stdClass Object +( + [client_id] => 13 + [invoice_id] => 24 + [user_id] => 2 + [invoice_group_id] => 8 +... +``` + +This is the list of all available variables where the part in the brackets (e.g. `invoice_id`) is the +name of the variable and the part after the `=>` is the content of the variable. + +## Adding Custom Fields + +Custom fields work in a special way. As custom fields are added by the user there is no way to define which +fields will be available. Therefore InvoicePlane searches for all available custom fields before printing the +template. All fields are stored in the `$custom_fields` variable that may look like this: + +``` +Array +( + [invoice] => Array + ( + [Sent at] => 2016-11-15 + [Contributors] => [ + 0 => Marty McFly + 1 => Jennifer McFly + ] + ) + [client] => Array + ( + [CRM ID] => 346999-13400 + [has Supervisor] => 1 + [Supervisors] => 1 + ) + [user] => Array + () + [quote] => Array + ( + [Sent at] => 2016-11-10 + [Special discount offered?] => 0 + ) +) +``` + +The `$custom_fields` variable is a collection of all custom field types that group all available +custom fields. As you can see in the example, the invoice has a custom field named *Sent at*, the client +has a field called *CRM ID* and so on. + +To access a specific custom field, you have to use the followng code example: + +``` + +``` + +where *client* should be the group and *CRM ID* should be the label of your custom field. Using the +code example would simply output `346999-13400` in your template. + +### Yes / No Custom Fields + +Yes/no fields will have the value `1` for yes and `0` for no. This way you can use the custom field in conditional statements like this: + +``` + +``` + +## Code Examples + +Here is a list of some examples for code that can be used to display variables. +Replace `invoice` with `quote` when editing quote templates. +Replace `variable_name` with the actual name of the variable. + +| Description | Code | +| --- | --- | +| **Add a new Variable** To add a new variable to the template. Replace `variable_name` with the actual name of the variable. | ``` variable_name; ?> ``` | +| **Format amounts** If you want to display amounts you have to use this code in order to display the amount in the correct format. | ``` variable_name); ?> ``` | +| **Conditional Statements** Only display code if a variable is not empty. This could be used for example if you don't want to display the taxes column if there are no taxes. | ``` variable_name)): ?> -- display any HTML or variables here -- ``` | +| **Display the Invoice Logo** The logo can be set in the System Settings. | ``` ``` | + +## Debugging Templates + +The PDF engine is not that good in handling errors or HTML that is broken due to PHP errors. You may get output +like this: + +``` +Severity: Notice +Message: Undefined offset: 2 +Filename: src/Tag.php +Line Number: 1806 +... +``` + +To know what is wrong with your template, you have to add a small code line in your template helper. Open the +file `application/helpers/pdf_helper.php` and add + +Place `print_r($html);exit;` at line 98 for invoice templates. + +Place `print_r($html);exit;` at line 250 for quote templates. + +This will output the plain HTML that will be used to generate your PDF files. If there are any problems with +missing or faulty variables or wrong PHP code, you should see the corresponding output here. diff --git a/docs/en/1.6/templates/index.md b/docs/en/1.6/templates/index.md new file mode 100644 index 0000000..3bb935b --- /dev/null +++ b/docs/en/1.6/templates/index.md @@ -0,0 +1,4 @@ +# Templates + +- [Using Templates](/en/1.6/templates/using-templates) +- [Customize Templates](/en/1.6/templates/customize-templates) diff --git a/docs/en/1.6/templates/using-templates.md b/docs/en/1.6/templates/using-templates.md new file mode 100644 index 0000000..5d12bcd --- /dev/null +++ b/docs/en/1.6/templates/using-templates.md @@ -0,0 +1,17 @@ +# Using Templates + +First of all, the templates shipped with InvoicePlane are what they are called: templates. You *can* use them directly for your business but they are meant to be duplicated and customized. + +There are two main types of templates which are used: + +- PDF Templates - Used to generate the quote and invoices PDF files +- Web Templates - Used to display the quotes and invoices in a web browser for guest users (clients) + +## Using PDF Templates + +All PDF templates can be found in the following folders of the application: + +- `/application/views/invoice_templates/pdf` for invoices +- `/application/views/quote_templates/pdf` for quotes + +You can select which templates should be used in the system settings for either [Invoices](/en/1.5/settings/invoices) or [Quotes](/en/1.5/settings/quotes). You can find the select boxes below the headline "Templates". Simply select the template, save and the template will be used for the next quote or invoice. diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..19451dc --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,83 @@ +site_name: InvoicePlane Wiki +site_description: Documentation for InvoicePlane - self-hosted invoicing application +site_url: https://invoiceplane.github.io/wiki/ +repo_url: https://github.com/invoiceplane/wiki +repo_name: invoiceplane/wiki + +docs_dir: docs +site_dir: site + +theme: + name: material + language: en + palette: + - scheme: default + primary: blue + accent: blue + features: + - navigation.tabs + - navigation.sections + - navigation.top + - search.suggest + - search.highlight + - content.code.copy + +plugins: + - search + +nav: + - Home: en/1.6/index.md + - General: + - About InvoicePlane: en/1.6/general/about.md + - Changelog: en/1.6/general/changelog.md + - License: en/1.6/general/license.md + - FAQ: en/1.6/general/faq.md + - Getting Started: + - Overview: en/1.6/getting-started/index.md + - Requirements: en/1.6/getting-started/requirements.md + - Installation: en/1.6/getting-started/installation.md + - Quickstart: en/1.6/getting-started/quickstart.md + - Updating InvoicePlane: en/1.6/getting-started/updating-ip.md + - Modules: + - Overview: en/1.6/modules/index.md + - Clients: en/1.6/modules/clients.md + - Quotes: en/1.6/modules/quotes.md + - Invoices: en/1.6/modules/invoices.md + - Recurring Invoices: en/1.6/modules/recurring-invoices.md + - Payments: en/1.6/modules/payments.md + - Tasks & Projects: en/1.6/modules/tasks-projects.md + - Settings: + - Overview: en/1.6/settings/index.md + - General Settings: en/1.6/settings/general.md + - Invoice Settings: en/1.6/settings/invoices.md + - Quote Settings: en/1.6/settings/quotes.md + - Tax Settings: en/1.6/settings/taxes.md + - Email Settings: en/1.6/settings/email.md + - Online Payments: en/1.6/settings/online-payments.md + - Updatecheck: en/1.6/settings/updatecheck.md + - Custom Fields: en/1.6/settings/custom-fields.md + - Email Templates: en/1.6/settings/email-templates.md + - Invoice Groups: en/1.6/settings/invoice-groups.md + - Payment Methods: en/1.6/settings/payment-methods.md + - Taxrates: en/1.6/settings/taxrates.md + - User Accounts: en/1.6/settings/user-accounts.md + - Templates: + - Overview: en/1.6/templates/index.md + - Using Templates: en/1.6/templates/using-templates.md + - Customize Templates: en/1.6/templates/customize-templates.md + - System: + - Overview: en/1.6/system/index.md + - Translation & Localization: en/1.6/system/translation-localization.md + - Importing Data: en/1.6/system/importing-data.md + - Upgrade from FusionInvoice: en/1.6/system/upgrade-from-fusioninvoice.md + - Help: + - Setup a Cron: en/1.6/help/setup-cron.md + +markdown_extensions: + - admonition + - tables + - toc: + permalink: true + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.superfences diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..24933d3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +mkdocs>=1.5 +mkdocs-material>=9.0 +markdownify>=0.11 From 177b4d26aea026ee0cbedf9b27384aab5322165a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 01:21:18 +0000 Subject: [PATCH 02/13] Serve wiki pages from Markdown instead of Blade templates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add app/Markdown/GithubFlavoredMarkdownConverter.php using league/commonmark with the GithubFlavoredMarkdown extension - Add app/WikiPage.php service class that reads docs/en/{version}/**/*.md, renders them to HTML, and caches the result (mirrors laravel.com's Documentation class pattern) - Rewrite WikiController to inject WikiPage and serve rendered Markdown through the new resources/views/wiki/page.blade.php wrapper; keeps the existing version-fallback and redirect logic intact - Add resources/views/wiki/page.blade.php — minimal Blade wrapper that yields the rendered HTML into the existing layouts.master layout - Add league/commonmark ^2.4 to composer.json; update PHP floor to 7.4 Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01FyUdA46kyTUidfhs4sAEG7 --- app/Http/Controllers/WikiController.php | 116 +++++++++--------- .../GithubFlavoredMarkdownConverter.php | 24 ++++ app/WikiPage.php | 108 ++++++++++++++++ composer.json | 3 +- resources/views/wiki/page.blade.php | 9 ++ 5 files changed, 198 insertions(+), 62 deletions(-) create mode 100644 app/Markdown/GithubFlavoredMarkdownConverter.php create mode 100644 app/WikiPage.php create mode 100644 resources/views/wiki/page.blade.php diff --git a/app/Http/Controllers/WikiController.php b/app/Http/Controllers/WikiController.php index dc635ce..2de66a2 100644 --- a/app/Http/Controllers/WikiController.php +++ b/app/Http/Controllers/WikiController.php @@ -2,109 +2,103 @@ namespace App\Http\Controllers; +use App\WikiPage; use Illuminate\Support\Facades\Config; class WikiController extends Controller { + /** + * @var WikiPage + */ + protected $wikiPage; + + public function __construct(WikiPage $wikiPage) + { + $this->wikiPage = $wikiPage; + } + public function getPage($locale, $version = '', $dir = '', $page = '') { - // Get default vars first - $default_locale = Config::get('app.locale'); + $default_locale = Config::get('app.locale'); $default_version = Config::get('app.version'); - // Check if the requested page has a redirect + // Check if the requested page has a redirect configured. $redirects = Config::get('routes.redirects'); - if (isset($redirects[$version][$dir][$page])) { return redirect()->to($redirects[$version][$dir][$page]); } - // Redirect to the default locale if the requested one is not available + // Redirect to the default locale if the requested one is not available. $locales = Config::get('app.available_locales'); - if (!isset($locales[$locale])) { + if (! isset($locales[$locale])) { $redirect_url = $default_locale; - if ($version) { - $redirect_url .= '/' . $version; - } - if ($dir) { - $redirect_url .= '/' . $dir; - } - if ($page) { - $redirect_url .= '/' . $page; - } + if ($version) { $redirect_url .= '/' . $version; } + if ($dir) { $redirect_url .= '/' . $dir; } + if ($page) { $redirect_url .= '/' . $page; } return redirect()->to($redirect_url); } - // Redirect to the default version if the requested one is not available + // Normalize version to underscore format (1.6 → 1_6) to match app config. $versions = Config::get('app.versions'); - $version = str_replace('.', '_', $version); - if (empty($version) || !in_array($version, $versions)) { + $version = str_replace('.', '_', $version); + + if (empty($version) || ! in_array($version, $versions)) { $redirect_url = $locale . '/' . str_replace('_', '.', $default_version); - if (!empty($dir)) { - $redirect_url .= '/' . $dir; - } - if (!empty($page)) { - $redirect_url .= '/' . $page; - } + if (! empty($dir)) { $redirect_url .= '/' . $dir; } + if (! empty($page)) { $redirect_url .= '/' . $page; } return redirect()->to($redirect_url); } - // Check if the requested page exists, if not redirect to home - if (empty($dir) && empty($page)) { - $requested_view = '.root'; - $current_url = '/'; - } elseif (empty($page)) { - $requested_view = '.' . str_replace('-', '_', $dir); + // Build the sub-path used by the topbar version switcher. + if (! empty($dir) && ! empty($page)) { + $current_url = '/' . $dir . '/' . $page; + } elseif (! empty($dir)) { $current_url = '/' . $dir; } else { - $requested_view = '.' . str_replace('-', '_', $dir) . '.' . str_replace('-', '_', $page); - $current_url = '/' . $dir . '/' . $page; + $current_url = '/'; } - $requested_page = $locale . '.' . $version . $requested_view; - - // Check if the view exists - if (!view()->exists($requested_page)) { + view()->share([ + 'current_dir' => $dir, + 'current_page' => $page, + 'current_url' => $current_url, + 'current_version' => str_replace('_', '.', $version), + ]); - // Check if the page exists for an older version - $reverse_versions = array_reverse($versions); + // Try the requested version first, then fall back through older versions. + $reverse_versions = array_reverse($versions); + $versions_to_try = array_merge([$version], array_diff($reverse_versions, [$version])); - foreach($reverse_versions as $old_version) { - $requested_page = $locale . '.' . $old_version . $requested_view; - - if (view()->exists($requested_page)) { - // View found, redirect to the page - return redirect()->to('/' . $locale . '/' . str_replace('_', '.', $old_version) . $current_url); - } - - $requested_page = ''; + foreach ($versions_to_try as $try_version) { + if (! $this->wikiPage->exists($locale, $try_version, $dir, $page)) { continue; } - } + // Found in an older version — redirect rather than serve from there. + if ($try_version !== $version) { + return redirect()->to( + '/' . $locale . '/' . str_replace('_', '.', $try_version) . $current_url + ); + } - // Load the page if found - if ($requested_page) { - $sidebar_content_view = $locale . '.' . $version . '.sidebar'; + $content = $this->wikiPage->get($locale, $version, $dir, $page); + $page_title = $this->wikiPage->title($locale, $version, $dir, $page); - view()->share([ - 'current_dir' => $dir, - 'current_page' => $page, - 'current_url' => $current_url, - 'current_version' => str_replace('_', '.', $version), - ]); + $sidebar_view = $locale . '.' . $version . '.sidebar'; - return view($requested_page)->with([ - 'sidebar_content' => view($sidebar_content_view), + return view('wiki.page', [ + 'content' => $content, + 'page_title' => $page_title, + 'sidebar_content' => view()->exists($sidebar_view) ? view($sidebar_view) : null, ]); } - // Load the default page + // Nothing found anywhere — go to the version root. return redirect()->to('/' . $locale . '/' . str_replace('_', '.', $default_version)); } public function getTestPage() { - return "TEST"; + return 'TEST'; } } diff --git a/app/Markdown/GithubFlavoredMarkdownConverter.php b/app/Markdown/GithubFlavoredMarkdownConverter.php new file mode 100644 index 0000000..2e869d5 --- /dev/null +++ b/app/Markdown/GithubFlavoredMarkdownConverter.php @@ -0,0 +1,24 @@ + 'allow', + 'allow_unsafe_links' => false, + ]); + + $environment->addExtension(new CommonMarkCoreExtension()); + $environment->addExtension(new GithubFlavoredMarkdownExtension()); + + return (string) (new MarkdownConverter($environment))->convert($markdown); + } +} diff --git a/app/WikiPage.php b/app/WikiPage.php new file mode 100644 index 0000000..0fc754e --- /dev/null +++ b/app/WikiPage.php @@ -0,0 +1,108 @@ +files = $files; + $this->cache = $cache; + } + + /** + * Return the rendered HTML for a wiki page, or null if the markdown file + * does not exist. + * + * @param string $locale e.g. 'en' + * @param string $version internal underscore format, e.g. '1_6' + * @param string $dir e.g. 'getting-started' + * @param string $page e.g. 'requirements' + * @return string|null + */ + public function get(string $locale, string $version, string $dir = '', string $page = ''): ?string + { + $key = 'wiki.' . implode('.', array_filter([$locale, $version, $dir, $page])); + + return $this->cache->remember($key, 5, function () use ($locale, $version, $dir, $page) { + $path = $this->resolvePath($locale, $version, $dir, $page); + + if (! $this->files->exists($path)) { + return null; + } + + return (new GithubFlavoredMarkdownConverter())->convert( + $this->files->get($path) + ); + }); + } + + /** + * Return whether a markdown file exists for the given page. + */ + public function exists(string $locale, string $version, string $dir = '', string $page = ''): bool + { + return $this->files->exists($this->resolvePath($locale, $version, $dir, $page)); + } + + /** + * Extract the page title from the first # heading in the markdown source. + */ + public function title(string $locale, string $version, string $dir = '', string $page = ''): string + { + $key = 'wiki.' . implode('.', array_filter([$locale, $version, $dir, $page])) . '.title'; + + return $this->cache->remember($key, 5, function () use ($locale, $version, $dir, $page) { + $path = $this->resolvePath($locale, $version, $dir, $page); + + if (! $this->files->exists($path)) { + return ''; + } + + preg_match('/^# (.+)$/m', $this->files->get($path), $matches); + + return $matches[1] ?? ''; + }); + } + + /** + * Build the filesystem path for a markdown file. + * + * Internal underscore version (1_6) is converted to dot format (1.6) to + * match the docs/ directory structure. + * + * Examples: + * en, 1_6, '', '' → docs/en/1.6/index.md + * en, 1_6, 'getting-started', '' → docs/en/1.6/getting-started/index.md + * en, 1_6, 'getting-started', 'requirements' → docs/en/1.6/getting-started/requirements.md + */ + protected function resolvePath(string $locale, string $version, string $dir, string $page): string + { + $versionDir = str_replace('_', '.', $version); + $base = base_path("docs/{$locale}/{$versionDir}"); + + if (empty($dir) && empty($page)) { + return "{$base}/index.md"; + } + + if (empty($page)) { + return "{$base}/{$dir}/index.md"; + } + + return "{$base}/{$dir}/{$page}.md"; + } +} diff --git a/composer.json b/composer.json index 6c1e810..7b7f890 100644 --- a/composer.json +++ b/composer.json @@ -5,8 +5,9 @@ "license": "MIT", "type": "project", "require": { - "php": ">=7.0.0", + "php": ">=7.4.0", "laravel/framework": "5.3.*", + "league/commonmark": "^2.4", "predis/predis": "^1.1" }, "require-dev": { diff --git a/resources/views/wiki/page.blade.php b/resources/views/wiki/page.blade.php new file mode 100644 index 0000000..e13d22e --- /dev/null +++ b/resources/views/wiki/page.blade.php @@ -0,0 +1,9 @@ +@extends('layouts.master') + +@section('title') + {{ $page_title }} +@endsection + +@section('content') + {!! $content !!} +@stop From 2fccc6fff354e9de2618072af02b1e960d89cc39 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 01:46:23 +0000 Subject: [PATCH 03/13] Split WikiController into markdown (>=1.7) and blade (<=1.6) rendering paths Versions >= 1.7 are served from Markdown files in docs/ via WikiPage service. Versions <= 1.6 are served from Blade templates in wiki/ via the original view() path. Each pool falls back only within its own version set to avoid cross-renderer redirects. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01FyUdA46kyTUidfhs4sAEG7 --- app/Http/Controllers/WikiController.php | 93 +++++++++++++++++++++---- 1 file changed, 81 insertions(+), 12 deletions(-) diff --git a/app/Http/Controllers/WikiController.php b/app/Http/Controllers/WikiController.php index 2de66a2..f5ca0b3 100644 --- a/app/Http/Controllers/WikiController.php +++ b/app/Http/Controllers/WikiController.php @@ -38,7 +38,7 @@ public function getPage($locale, $version = '', $dir = '', $page = '') return redirect()->to($redirect_url); } - // Normalize version to underscore format (1.6 → 1_6) to match app config. + // Normalize version to underscore format (1.6 → 1_6). $versions = Config::get('app.versions'); $version = str_replace('.', '_', $version); @@ -65,38 +65,107 @@ public function getPage($locale, $version = '', $dir = '', $page = '') 'current_version' => str_replace('_', '.', $version), ]); - // Try the requested version first, then fall back through older versions. - $reverse_versions = array_reverse($versions); - $versions_to_try = array_merge([$version], array_diff($reverse_versions, [$version])); + if ($this->usesMarkdown($version)) { + return $this->serveMarkdown($locale, $version, $dir, $page, $current_url, $versions, $default_version); + } + + return $this->serveBlade($locale, $version, $dir, $page, $current_url, $versions, $default_version); + } + + /** + * Serve a page from a Markdown file. + * Used for versions >= 1.7. + * Falls back only within the markdown version pool. + */ + protected function serveMarkdown($locale, $version, $dir, $page, $current_url, $versions, $default_version) + { + $markdown_versions = array_values(array_filter($versions, function ($v) { + return $this->usesMarkdown($v); + })); + + // Try requested version first, then older markdown versions newest-first. + $try_order = array_merge( + [$version], + array_values(array_diff(array_reverse($markdown_versions), [$version])) + ); - foreach ($versions_to_try as $try_version) { + foreach ($try_order as $try_version) { if (! $this->wikiPage->exists($locale, $try_version, $dir, $page)) { continue; } - // Found in an older version — redirect rather than serve from there. + // Found in an older version — redirect rather than serve cross-version. if ($try_version !== $version) { return redirect()->to( '/' . $locale . '/' . str_replace('_', '.', $try_version) . $current_url ); } - $content = $this->wikiPage->get($locale, $version, $dir, $page); - $page_title = $this->wikiPage->title($locale, $version, $dir, $page); - $sidebar_view = $locale . '.' . $version . '.sidebar'; return view('wiki.page', [ - 'content' => $content, - 'page_title' => $page_title, + 'content' => $this->wikiPage->get($locale, $version, $dir, $page), + 'page_title' => $this->wikiPage->title($locale, $version, $dir, $page), 'sidebar_content' => view()->exists($sidebar_view) ? view($sidebar_view) : null, ]); } - // Nothing found anywhere — go to the version root. return redirect()->to('/' . $locale . '/' . str_replace('_', '.', $default_version)); } + /** + * Serve a page from a Blade template. + * Used for versions <= 1.6. + * Falls back only within the blade version pool. + */ + protected function serveBlade($locale, $version, $dir, $page, $current_url, $versions, $default_version) + { + // Build the dot-notation view name from URL segments. + if (empty($dir) && empty($page)) { + $requested_view = '.root'; + } elseif (empty($page)) { + $requested_view = '.' . str_replace('-', '_', $dir); + } else { + $requested_view = '.' . str_replace('-', '_', $dir) . '.' . str_replace('-', '_', $page); + } + + $requested_page = $locale . '.' . $version . $requested_view; + + if (! view()->exists($requested_page)) { + // Fall back through older blade-only versions (newest first). + $blade_versions = array_values(array_filter($versions, function ($v) { + return ! $this->usesMarkdown($v); + })); + + foreach (array_reverse($blade_versions) as $old_version) { + $candidate = $locale . '.' . $old_version . $requested_view; + + if (view()->exists($candidate)) { + return redirect()->to( + '/' . $locale . '/' . str_replace('_', '.', $old_version) . $current_url + ); + } + } + + return redirect()->to('/' . $locale . '/' . str_replace('_', '.', $default_version)); + } + + $sidebar_view = $locale . '.' . $version . '.sidebar'; + + return view($requested_page)->with([ + 'sidebar_content' => view($sidebar_view), + ]); + } + + /** + * Versions >= 1.7 are served from Markdown files in docs/. + * Versions <= 1.6 are served from Blade templates in wiki/. + */ + protected function usesMarkdown(string $version): bool + { + return version_compare(str_replace('_', '.', $version), '1.7', '>='); + } + public function getTestPage() { return 'TEST'; From 2b48a97778d72ab6f51ac0108860f378a2c635f0 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 02:02:08 +0000 Subject: [PATCH 04/13] Add version 1.7 as the new default with Markdown-served docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add docs/en/1.7/ (39 files) seeded from 1.6, with all internal URLs updated to /en/1.7/ and version-specific content refreshed: changelog placeholder for upcoming release, requirements updated to PHP >= 8.1, updating-ip rewritten for the 1.6.x → 1.7.0 upgrade path - Set app.version to 1_7 and append 1_7 to app.versions so the controller routes 1.7 requests through the Markdown rendering path Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01FyUdA46kyTUidfhs4sAEG7 --- config/app.php | 5 +- docs/en/1.7/general/about.md | 38 +++++ docs/en/1.7/general/changelog.md | 11 ++ docs/en/1.7/general/faq.md | 107 ++++++++++++ docs/en/1.7/general/license.md | 113 +++++++++++++ docs/en/1.7/getting-started/index.md | 6 + docs/en/1.7/getting-started/installation.md | 53 ++++++ docs/en/1.7/getting-started/quickstart.md | 77 +++++++++ docs/en/1.7/getting-started/requirements.md | 28 +++ docs/en/1.7/getting-started/updating-ip.md | 38 +++++ docs/en/1.7/help/setup-cron.md | 43 +++++ docs/en/1.7/index.md | 56 ++++++ docs/en/1.7/modules/clients.md | 37 ++++ docs/en/1.7/modules/index.md | 7 + docs/en/1.7/modules/invoices.md | 157 +++++++++++++++++ docs/en/1.7/modules/payments.md | 45 +++++ docs/en/1.7/modules/quotes.md | 124 ++++++++++++++ docs/en/1.7/modules/recurring-invoices.md | 40 +++++ docs/en/1.7/modules/tasks-projects.md | 38 +++++ docs/en/1.7/settings/custom-fields.md | 28 +++ docs/en/1.7/settings/email-templates.md | 31 ++++ docs/en/1.7/settings/email.md | 12 ++ docs/en/1.7/settings/general.md | 45 +++++ docs/en/1.7/settings/index.md | 15 ++ docs/en/1.7/settings/invoice-groups.md | 41 +++++ docs/en/1.7/settings/invoices.md | 21 +++ docs/en/1.7/settings/online-payments.md | 25 +++ docs/en/1.7/settings/payment-methods.md | 13 ++ docs/en/1.7/settings/quotes.md | 17 ++ docs/en/1.7/settings/taxes.md | 11 ++ docs/en/1.7/settings/taxrates.md | 13 ++ docs/en/1.7/settings/updatecheck.md | 6 + docs/en/1.7/settings/user-accounts.md | 70 ++++++++ docs/en/1.7/system/importing-data.md | 57 +++++++ docs/en/1.7/system/index.md | 5 + .../en/1.7/system/translation-localization.md | 63 +++++++ .../1.7/system/upgrade-from-fusioninvoice.md | 32 ++++ docs/en/1.7/templates/customize-templates.md | 160 ++++++++++++++++++ docs/en/1.7/templates/index.md | 4 + docs/en/1.7/templates/using-templates.md | 17 ++ 40 files changed, 1707 insertions(+), 2 deletions(-) create mode 100644 docs/en/1.7/general/about.md create mode 100644 docs/en/1.7/general/changelog.md create mode 100644 docs/en/1.7/general/faq.md create mode 100644 docs/en/1.7/general/license.md create mode 100644 docs/en/1.7/getting-started/index.md create mode 100644 docs/en/1.7/getting-started/installation.md create mode 100644 docs/en/1.7/getting-started/quickstart.md create mode 100644 docs/en/1.7/getting-started/requirements.md create mode 100644 docs/en/1.7/getting-started/updating-ip.md create mode 100644 docs/en/1.7/help/setup-cron.md create mode 100644 docs/en/1.7/index.md create mode 100644 docs/en/1.7/modules/clients.md create mode 100644 docs/en/1.7/modules/index.md create mode 100644 docs/en/1.7/modules/invoices.md create mode 100644 docs/en/1.7/modules/payments.md create mode 100644 docs/en/1.7/modules/quotes.md create mode 100644 docs/en/1.7/modules/recurring-invoices.md create mode 100644 docs/en/1.7/modules/tasks-projects.md create mode 100644 docs/en/1.7/settings/custom-fields.md create mode 100644 docs/en/1.7/settings/email-templates.md create mode 100644 docs/en/1.7/settings/email.md create mode 100644 docs/en/1.7/settings/general.md create mode 100644 docs/en/1.7/settings/index.md create mode 100644 docs/en/1.7/settings/invoice-groups.md create mode 100644 docs/en/1.7/settings/invoices.md create mode 100644 docs/en/1.7/settings/online-payments.md create mode 100644 docs/en/1.7/settings/payment-methods.md create mode 100644 docs/en/1.7/settings/quotes.md create mode 100644 docs/en/1.7/settings/taxes.md create mode 100644 docs/en/1.7/settings/taxrates.md create mode 100644 docs/en/1.7/settings/updatecheck.md create mode 100644 docs/en/1.7/settings/user-accounts.md create mode 100644 docs/en/1.7/system/importing-data.md create mode 100644 docs/en/1.7/system/index.md create mode 100644 docs/en/1.7/system/translation-localization.md create mode 100644 docs/en/1.7/system/upgrade-from-fusioninvoice.md create mode 100644 docs/en/1.7/templates/customize-templates.md create mode 100644 docs/en/1.7/templates/index.md create mode 100644 docs/en/1.7/templates/using-templates.md diff --git a/config/app.php b/config/app.php index 3f1e926..aceabfa 100644 --- a/config/app.php +++ b/config/app.php @@ -99,7 +99,7 @@ |-------------------------------------------------------------------------- */ - 'version' => '1_6', + 'version' => '1_7', /* |-------------------------------------------------------------------------- @@ -110,7 +110,8 @@ 'versions' => array( '1_0', '1_5', - '1_6' + '1_6', + '1_7', ), /* diff --git a/docs/en/1.7/general/about.md b/docs/en/1.7/general/about.md new file mode 100644 index 0000000..db29ef2 --- /dev/null +++ b/docs/en/1.7/general/about.md @@ -0,0 +1,38 @@ +# About InvoicePlane + +![Preview for InvoicePlane](https://invoiceplane.com/assets/img/preview.jpg) + +InvoicePlane is a self-hosted open source application for managing your quotes, invoices, clients, tasks and +payments. +Downloaded more than 100 000 times from 196 countries. + +## Quotes, Invoices, Payments + +InvoicePlane is a solid app to manage your complete billing circle: from quotes over invoices to +payments. + +## Manage your Clients + +The application provides CRM-like management for your clients. Enter contact details, notes or +add custom fields to add any information you want. + +## Customize InvoicePlane + +You can customize InvoicePlane to make sure it fits your needs: amount format, languages, email +and PDF templates and many more. + +## One-Click Online Payments + +Let your clients pay the invoices by using Stripe (other payment providers to come, please open an issue on [GitHub](https://github.com/InvoicePlane/InvoicePlane/issues) if you are missing a provider). + +## Multilanguage Interface + +InvoicePlane is fully translated into 23 languages by community members and more languages are +coming soon. + +## Projects and Tasks + +Create projects for different clients, add some task and you can reference them directly inside +invoices. + +[Learn more on InvoicePlane.com](https://invoiceplane.com/) diff --git a/docs/en/1.7/general/changelog.md b/docs/en/1.7/general/changelog.md new file mode 100644 index 0000000..8958c80 --- /dev/null +++ b/docs/en/1.7/general/changelog.md @@ -0,0 +1,11 @@ +# Changelog + +### v1.7.0 (upcoming) + +The changelog for version 1.7 will be published here once the release is available. + +You can follow development and track upcoming changes on [GitHub](https://github.com/InvoicePlane/InvoicePlane/releases). + +> **Note:** +> +> Changelogs concerning **older versions** of InvoicePlane can be found in the relevant section of the given version. diff --git a/docs/en/1.7/general/faq.md b/docs/en/1.7/general/faq.md new file mode 100644 index 0000000..6e9c367 --- /dev/null +++ b/docs/en/1.7/general/faq.md @@ -0,0 +1,107 @@ +# FAQ - Frequently Asked Questions + +## General + +### Can I sell / redistribute InvoicePlane? + +InvoicePlane is a free software and it will never be a commercial product! We +appeal everyone to respect the open source InvoicePlane project and our work and refrain from +selling the application as their own product! +What you can do: offer paid professional support or hosting for InvoicePlane. + +However InvoicePlane is an open source software released under [MIT license](http://choosealicense.com/licenses/mit/). This means that you can use +the code *but* the InvoicePlane name and the logo are copyright by Invoiceplane.com and +Kovah.de +This means you **have to** use another name and logo for the product and include the original InvoicePlane license in the code. + +For more information about licensing please visit the [InvoicePlane website](https://invoiceplane.com/license-copyright). + +## Errors + +### You have problems and need help? Use the debug mode. + +You have a problem with some errors, you are stuck and need help? We would like to help you but first +we need some help from you: error logs. + +1. Enable the debug mode by replacing `ENABLE_DEBUG=false` with + `ENABLE_DEBUG=true` in the `/ipconfig.php` file. +2. Try again what caused the error, e.g. creating a new invoice which does not work. +3. Get the log files: + - Open the folder `/application/logs/`, open the log file with the current date + and copy the whole content. + - Take a look at your web server error logs. + - Open the console of your browser ([tutorial](http://webmasters.stackexchange.com/a/77337/20720)), the + error may be logged there. +4. Save the content of the log files and the output of the browser console to [Paste.InvoicePlane.com](https://paste.invoiceplane.com/) and post this link + with a detailed description to the [Community + Forums](https://community.invoiceplane.com). + You will get further help there. + +### I copied InvoicePlane to my webserver but I get blank pages or an error 404 or 500 + +Please make sure you copied the .htaccess file (hidden file on Unix systems) and you installed and +enabled mod\_rewrite for Apache. + +If you want to install InvoicePlane in a sub-directory like `yourdomain.com/invoices/` +please follow the instructions for the [installation in a +subdirectory](/en/1.5/getting-started/installation#subdir). + +### There is a large spinning cog () after I clicked a button and now nothing happens + +This problem occurs if the application is stuck because of an error. Please follow the instructions +for the [debug mode](#debugmode) + +### I can't add more than 3 or 4 items to quotes or invoices + +This problem may occurs because of a configuration of your nginx webserver. The server error should +look like this: + +``` +upstream sent too big header while reading response header from upstream +``` + +To solve this problem you should try to add / update your nginx configuration with the following +settings: + +``` +proxy_buffer_size 128k; +proxy_buffers 4 256k; +proxy_busy_buffers_size 256k; +``` + +or + +``` +fastcgi_buffer_size 128k; +fastcgi_buffers 4 256k; +fastcgi_busy_buffers_size 256k; +``` + +Please check [this comment](http://stackoverflow.com/a/27551259/1203515) for +more details. + +## Settings + +### Where can I set the default invoice / quote groups? + +You can set the default invoice / quote groups at `System settings > Invoices > Default Invoice +Group` for invoices and `System settings > Quotes > Default Quote Group` for +quotes. + +## Customization + +### How can I customize the templates? + +You can find all templates in the following directories: + +**Invoices** + +`/application/views/invoice_templates/` + +**Quotes** + +`/application/views/quote_templates/` + +The templates are using basic HTML, CSS and PHP. If you just want to change the styling you just need +some knowledge of HTML and CSS. +If you want to include Custom Fields into the templates please refer to the [Custom Fields page](/en/1.5/settings/custom-fields#add-to-template). diff --git a/docs/en/1.7/general/license.md b/docs/en/1.7/general/license.md new file mode 100644 index 0000000..e43e259 --- /dev/null +++ b/docs/en/1.7/general/license.md @@ -0,0 +1,113 @@ +# License for InvoicePlane + +## Copyright + +The name 'InvoicePlane' and the InvoicePlane logo are original copyright +of InvoicePlane.com / Kovah.de and the following restrictions apply to +both of them: + +**You are allowed to:** + +- use the name 'InvoicePlane' or the InvoicePlane logo in any context directly + related to the application or the project. This includes the application itself, + local communities and news or blog posts about InvoicePlane or +- use the name 'InvoicePlane' or the InvoicePlane logo to provide professional support or hosting for the InvoicePlane application. + +**You are not allowed to:** + +- use the name 'InvoicePlane' or the InvoicePlane logo in any context that is **not** related to the project, +- alter the name 'InvoicePlane' or the InvoicePlane logo in any way or +- sell or redistribute the application under the name 'InvoicePlane' and the InvoicePlane logo. + +--- + +## InvoicePlane Usage Permits + +- [Softaculous](http://www.softaculous.com/) is permitted to add InvoicePlane to their AutoInstaller. + +--- + +## License + +================================================== +License for InvoicePlane +================================================== +Copyright (c) 2012-2014 InvoicePlane.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +The name (InvoicePlane) and the logo can be used in any context related to +InvoicePlane as application or project but may not be changed / altered in +any way. The name and the logo are both original copyright by InvoicePlane.com +and Kovah.de + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +================================================== +License for CodeIgniter +================================================== +Copyright (c) 2008 - 2011, EllisLab, Inc. +All rights reserved. + +This license is a legal agreement between you and EllisLab Inc. for the use +of CodeIgniter Software (the "Software"). By obtaining the Software you +agree to comply with the terms and conditions of this license. + +PERMITTED USE +You are permitted to use, copy, modify, and distribute the Software and its +documentation, with or without modification, for any purpose, provided that +the following conditions are met: + +1. A copy of this license agreement must be included with the distribution. + +2. Redistributions of source code must retain the above copyright notice in +all source code files. + +3. Redistributions in binary form must reproduce the above copyright notice +in the documentation and/or other materials provided with the distribution. + +4. Any files that have been modified must carry notices stating the nature +of the change and the names of those who changed them. + +5. Products derived from the Software must include an acknowledgment that +they are derived from CodeIgniter in their documentation and/or other +materials provided with the distribution. + +6. Products derived from the Software may not be called "CodeIgniter", +nor may "CodeIgniter" appear in their name, without prior written +permission from EllisLab, Inc. + +INDEMNITY +You agree to indemnify and hold harmless the authors of the Software and +any contributors for any direct, indirect, incidental, or consequential +third-party claims, actions or suits, as well as any related expenses, +liabilities, damages, settlements or fees arising from your use or misuse +of the Software, or a violation of any terms of this license. + +DISCLAIMER OF WARRANTY +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR +IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF QUALITY, PERFORMANCE, +NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. + +LIMITATIONS OF LIABILITY +YOU ASSUME ALL RISK ASSOCIATED WITH THE INSTALLATION AND USE OF THE SOFTWARE. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS OF THE SOFTWARE BE LIABLE +FOR CLAIMS, DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF, OR IN CONNECTION +WITH THE SOFTWARE. LICENSE HOLDERS ARE SOLELY RESPONSIBLE FOR DETERMINING THE +APPROPRIATENESS OF USE AND ASSUME ALL RISKS ASSOCIATED WITH ITS USE, INCLUDING +BUT NOT LIMITED TO THE RISKS OF PROGRAM ERRORS, DAMAGE TO EQUIPMENT, LOSS OF +DATA OR SOFTWARE PROGRAMS, OR UNAVAILABILITY OR INTERRUPTION OF OPERATIONS. diff --git a/docs/en/1.7/getting-started/index.md b/docs/en/1.7/getting-started/index.md new file mode 100644 index 0000000..fde26db --- /dev/null +++ b/docs/en/1.7/getting-started/index.md @@ -0,0 +1,6 @@ +# Getting Started + +- [Requirements](/en/1.7/getting-started/requirements) +- [Installation](/en/1.7/getting-started/installation) +- [Quickstart (Tutorial)](/en/1.7/getting-started/quickstart) +- [Updating InvoicePlane](/en/1.7/getting-started/updating-ip) diff --git a/docs/en/1.7/getting-started/installation.md b/docs/en/1.7/getting-started/installation.md new file mode 100644 index 0000000..856bd5b --- /dev/null +++ b/docs/en/1.7/getting-started/installation.md @@ -0,0 +1,53 @@ +# Installation + +For those of you comfortable with installing web applications, installing InvoicePlane should take 5 minutes or +less. + +1. [Download](https://invoiceplane.com/downloads) and extract the archive. +2. Create an empty database on your web server. +3. Upload the files to your web server, either into a subdirectory or into the public root of the web server. +4. Make a copy of the `ipconfig.php.example` file and rename the copy to `ipconfig.php` +5. Open the `ipconfig.php` file and add your URL in it like described in the file. +6. Comment out the first line of the `ipconfig.php` file by adding a `#` at the beginning of the line as described at **pt. 2** [here](updating-ip#160-2-replace-files) +7. Run the InvoicePlane installer from your web browser and follow his instructions: `http://your-domain.com/index.php/setup` + +Once the installer finished, the installation is complete and you may log into InvoicePlane using the email +address and password you have chosen during the installation. + +## Run InvoicePlane in a sub directory + +If you want to run InvoicePlane in a sub directory (e.g. `http://yourdomain.com/invoices/`) you have +to modify the `.htaccess` file which is located in the root directory. You must add the line + +``` +RewriteBase /sub-directory +``` + +where `sub-directory` is the directory you want to use. The content of the file should look like this: + +``` +RewriteEngine on +RewriteBase /sub-directory +RewriteCond %{REQUEST_FILENAME} !-d +RewriteCond %{REQUEST_FILENAME} !-f +RewriteRule . index.php [L] +``` + +After that, open your `ipconfig.php` file and add the sub directory to your URL like this: + +``` +http://your-domain.com/sub-directory +``` + +Notice that there is **no** trailing slash. + +## Remove index.php from the URL + +Please notice that this step is entirely optional and does not affect the application in any way. + +1. Make sure that [mod\_rewrite](https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html) is enabled on your web + server. +2. Open the file `ipconfig.php` +3. Search for `REMOVE_INDEXPHP=false` in this file and replace it with + `REMOVE_INDEXPHP=true` +4. Rename the `htaccess` file to `.htaccess` diff --git a/docs/en/1.7/getting-started/quickstart.md b/docs/en/1.7/getting-started/quickstart.md new file mode 100644 index 0000000..c787c8f --- /dev/null +++ b/docs/en/1.7/getting-started/quickstart.md @@ -0,0 +1,77 @@ +# Quickstart + +## Logging In + +If InvoicePlane was installed into the root of your web server: + +`http://www.your-domain.com` + +If InvoicePlane was installed into its own subdirectory of your web server: + +`http://www.your-domain.com/the-subdirectory` + +--- + +## Configure the Application + +Before you start with invoicing you should check the application settings on `http://www.your-domain.com/settings` +and set for example the currency, how the amounts should be formatted and so on. + +More information about available settings can be found on the [Settings](/en/1.7/modules/settings) +page. + +--- + +## Adding a Client + +Click `Clients` from the main menu at the top of the page and select `Add Client`. Fill in +as much information as needed and submit the form. + +More information about the client management can be found on the [Clients](/en/1.7/modules/clients) +page. + +--- + +## Adding Products + +If you have products which should appear on your invoices or quotes you can create them form the +`Products` menu. + +More information about products can be found on the [Products](/en/1.7/modules/products) +page. + +--- + +## Creating an Invoice + +Click `Invoices` from the main menu at the top of the page and select `Create Invoice`. +Start typing the client name into the `Client` box. If the client already exists in InvoicePlane, +select the client from the list which appears after you start typing. If the client does not already exist in +InvoicePlane, continue typing the client\'s name and that client will be added as a new record. +Then choose the invoice date and invoice group and submit the form. + +If you added some products before you can simply add them via the `Add Product` button left from the +`Save` button. If you want to enter some items manually you can use the empty row or +add new rows with the `Add new Row` button. + +### Send the invoice + +If viewing a list of invoices, click the `Options` button on the row of the invoice to send. If +viewing a single invoice, click the Options button near the top right of the page. Select `Send +Email` from the `Options` button, review the information and submit the form. The client +will receive an email with the invoice attached as a PDF. + +--- + +## Entering a Payment + +Offline payments are entered by clicking `Payments` from the main menu at the top of the page and +selecting `Enter Payment`. Fill in the appropriate information and submit the form to enter the +payment. + +Online payments allow a client to pay their invoice online. When an online payment occurs, the payment is +automatically entered back into InvoicePlane, eliminating the need to manually enter an offline payment. Online +payments require additional setup before they can be used. + +More information about payments can be found on the [Payments](/en/1.7/modules/payments) +page. diff --git a/docs/en/1.7/getting-started/requirements.md b/docs/en/1.7/getting-started/requirements.md new file mode 100644 index 0000000..aeb5419 --- /dev/null +++ b/docs/en/1.7/getting-started/requirements.md @@ -0,0 +1,28 @@ +# Requirements + +If you want to use InvoicePlane you have to follow these requirements to use the application. + +- A webserver / shared hosting with the following specifications: + - MySQL >= 5.5 or the equivalent version of MariaDB + - Apache >= 2.4 or Ngnix >= 1.20.0 + - PHP >= 8.1 + - The following PHP extensions must be installed and activated: + - php-bcmath + - php-dom + - php-gd + - php-hash + - php-json + - php-mbstring + - php-mcrypt + - php-mysqli + - php-openssl + - php-recode + - php-xml + - php-xmlrpc + - php-zlib +- An up-to-date web browser. We do recommend using either [Firefox](https://www.mozilla.org/en-US/firefox/new/), [Microsoft Edge](https://www.microsoft.com/en-us/edge), the latest version of + [Safari](https://www.apple.com/safari) or any of the other leading browsers around the internet. Please note that since Microsoft introduced [Microsoft Edge](https://www.microsoft.com/en-us/edge), Internet Explorer is not supported anymore. + +> **Warning:** +> Please notice that PHP < 8.1 is no longer supported and should **not** be used anymore for production +> environments! (see [php version support](https://www.php.net/supported-versions.php) for more information) diff --git a/docs/en/1.7/getting-started/updating-ip.md b/docs/en/1.7/getting-started/updating-ip.md new file mode 100644 index 0000000..2c1b6c5 --- /dev/null +++ b/docs/en/1.7/getting-started/updating-ip.md @@ -0,0 +1,38 @@ +# Update InvoicePlane + +## Contents + +- [Upgrade information](#upgrade-information) +- [**Upgrade instructions (v1.6.x to v1.7.0)**](#16x-170-instructions) + 1. Preliminary operations + 2. Replace files & test + +--- + +## Upgrade information + +Upgrade instructions for v1.7 will be published here once the release is available. Check the [changelog](/en/1.7/general/changelog) and [GitHub releases](https://github.com/InvoicePlane/InvoicePlane/releases) for the latest information. + +## Instructions to upgrade to 1.7.0 from 1.6.x + +#### 1. Preliminary operations + +1. Make a backup of your database and all files. (This is **very important** to prevent any data loss) +2. Download the latest version from [InvoicePlane.com](https://invoiceplane.com/downloads). + +#### 2. Replace files & test + +1. Copy all files to the root directory of your InvoicePlane installation but **do not** overwrite the + following files: + - The `ipconfig.php` file + - Customized templates in the `application/views/` folder + - The files for custom styles: `assets/core/css/custom.css` and `assets/core/css/custom-pdf.css` + - Uploaded images in the `uploads/` folder (e. g. your company logo) + - Custom language keys at `application/language/COUNTRY/custom_lang.php` + > **Note:** + > + > **Hint:** An *easy* way of performing this operation is to upload the whole new InvoicePlane version in a different folder, outside of your current installation root folder, and copy the above mentioned files in the new folder you just uploaded. Afterwards just rename your current folder to something like `my_current_folder_old` and rename your new-version-folder with the name of `my_current_folder`. +2. Open `http://yourdomain.com/index.php/setup` and follow the instructions. The app will run all + updates on its own. + - If you encounter any errors when upgrading the table, press "Try Again" to resolve those errors and continue with the setup. +3. Now that the update is installed, moved and protected, it's time to log in and see if everything is working: login again and check if everything is working. diff --git a/docs/en/1.7/help/setup-cron.md b/docs/en/1.7/help/setup-cron.md new file mode 100644 index 0000000..681324b --- /dev/null +++ b/docs/en/1.7/help/setup-cron.md @@ -0,0 +1,43 @@ +# Help: Setup a Cron + +If you want to use [recurring invoices](/en/1.7/modules/recurring-invoices) you have to +setup a cron +that opens the URL listed on the recurring invoices page. A cron is basically a script that runs on predefined +times. You can setup a cron that runs every minute, every third hour per day or yearly. For recurring invoices +you should run the cron daily. + +There are two different ways on how to setup a cron: + +- use you own web server or +- use an online service that runs the cron for you. + +### Use your own Server + +As there are various different types of operating software for web servers (e.g. Ubuntu, CentOS, Windows Server +or even Mac OSX Server) there is not *one* tutorial on how to setup a cron. Because of this we listed +tutorials for the most used systems below and wrote an example for Unix-based operating systems. + +- [Ubuntu](https://help.ubuntu.com/community/CronHowto) +- [CentOS](https://www.centos.org/docs/5/html/Deployment_Guide-en-US/ch-autotasks.html) +- [Windows Server (2008)](http://www.myscienceisbetter.info/add-new-cron-job-on-windows-2008-server-using-task-scheduler.html) + +**Example for Unix-based systems** + +Open the crontab file with `crontab -e` and paste the following line: + +``` +0 0 * * * wget -O - https://yoursite.com/invoices/cron/recur/your-cron-key >/dev/null 2>&1 +``` + +where `yoursite.com` is the domain you use for InvoicePlane and `your-cron-key` the cron +key from your settings. + +### Use an Online Service + +There are a lot of online services that offer running a cron for you, for example +[cron-job.org](https://cron-job.org/en/), +[FastCron](https://www.fastcron.com/tutorials/invoiceplane-cron) +or any other. + +Please read the documentation of the service you use to know how to setup a cron with their +system. diff --git a/docs/en/1.7/index.md b/docs/en/1.7/index.md new file mode 100644 index 0000000..934e5a2 --- /dev/null +++ b/docs/en/1.7/index.md @@ -0,0 +1,56 @@ +# InvoicePlane Wiki + +## Welcome to the InvoicePlane Wiki + +If you want to know how to use InvoicePlane or if you have any +questions take a look at this wiki. You should find a lot of useful information about the software and each +module. + +## About InvoicePlane + +- [What is InvoicePlane?](/en/1.7/general/about) +- [Changelog](/en/1.7/general/changelog) +- [License](/en/1.7/general/license) +- [FAQ](/en/1.7/general/faq) + +## Getting started + +- [Requirements](/en/1.7/getting-started/requirements) +- [Installation](/en/1.7/getting-started/installation) +- [Quickstart (Tutorial)](/en/1.7/getting-started/quickstart) +- [Updating InvoicePlane](/en/1.7/getting-started/updating-ip) + +## Modules + +- [Clients](/en/1.7/modules/clients) +- [Quotes](/en/1.7/modules/quotes) +- [Invoices](/en/1.7/modules/invoices) +- [Recurring Invoices](/en/1.7/modules/recurring-invoices) +- [Payments](/en/1.7/modules/payments) + +## Settings + +- [General Settings](/en/1.7/settings/general) +- [Invoice Settings](/en/1.7/settings/invoices) +- [Quotes Settings](/en/1.7/settings/quotes) +- [Tax Settings](/en/1.7/settings/taxes) +- [eMail Settings](/en/1.7/settings/email) +- [Online Payments](/en/1.7/settings/online-payments) +- [Updatecheck](/en/1.7/settings/updatecheck) +- [Custom Fields](/en/1.7/settings/custom-fields) +- [eMail Templates](/en/1.7/settings/email-templates) +- [Invoice Groups](/en/1.7/settings/invoice-groups) +- [Payment Methods](/en/1.7/settings/payment-methods) +- [Taxrates](/en/1.7/settings/taxrates) +- [User Accounts](/en/1.7/settings/user-accounts) + +## Templates + +- [Using Templates](/en/1.7/templates/using-templates) +- [Customize Templates](/en/1.7/templates/customize-templates) + +## System + +- [Translation / Localization](/en/1.7/system/translation-localization) +- [Importing Data](/en/1.7/system/importing-data) +- [Upgrade from FusionInvoice](/en/1.7/system/upgrade-from-fusioninvoice) diff --git a/docs/en/1.7/modules/clients.md b/docs/en/1.7/modules/clients.md new file mode 100644 index 0000000..b80c165 --- /dev/null +++ b/docs/en/1.7/modules/clients.md @@ -0,0 +1,37 @@ +# Clients + +## View Clients + +To view the client list, click `Clients` from the main menu and select `View Clients`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_clients.jpg)](https://invoiceplane.com/content/screenshots/web/ip_clients.jpg) + +By default, the client list will be filtered to active clients only. The filter can be set to either +`Active`, `Inactive` or `All` by choosing the filter from the submenu bar. +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu with a number of items when clicked: + +- `View` - View the client +- `Edit` - Edit the client +- `Create Quote` - Create a quote for the client +- `Create Invoice` - Create an invoice for the client +- `Delete` - Delete the client + +## Add new Clients + +To add a new client, either choose `Clients` from the main menu and select `Add Client`, or +from the client list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_clients_add.jpg)](https://invoiceplane.com/content/screenshots/web/ip_clients_add.jpg) + +When adding a new client, the only field required is the `Client Name` field, although if you plan to +email invoices and quotes to your clients, the `Email Address` field should be filled in as well. Any +[custom fields](/en/1.7/settings/custom-fields) created for client records will display at the bottom +of the client form. + +## Client Logins + +Clients can be granted permission to log into InvoicePlane to view their quotes and invoices, approve or reject +quotes and pay their invoices. See the `Guest Account` section of the [User Accounts](/en/1.7/settings/user-accounts) page for instructions on creating logins for +your clients. diff --git a/docs/en/1.7/modules/index.md b/docs/en/1.7/modules/index.md new file mode 100644 index 0000000..7ce2e28 --- /dev/null +++ b/docs/en/1.7/modules/index.md @@ -0,0 +1,7 @@ +# Modules + +- [Clients](/en/1.7/modules/clients) +- [Invoices](/en/1.7/modules/quotes) +- [Invoices](/en/1.7/modules/invoices) +- [Recurring Invoices](/en/1.7/modules/recurring-invoices) +- [Payments](/en/1.7/modules/payments) diff --git a/docs/en/1.7/modules/invoices.md b/docs/en/1.7/modules/invoices.md new file mode 100644 index 0000000..bbc3c3d --- /dev/null +++ b/docs/en/1.7/modules/invoices.md @@ -0,0 +1,157 @@ +# Invoices + +## The Invoice Lifecycle + +Invoice statuses follow the lifecycle of an invoice from draft to paid and allow you to keep track of where each +of your invoices are in their lifecycle. Each of the statuses listed below are automatically set for you when +specific activity occurs with an invoice, but you may also choose to manually change the status at any time +during the invoice lifecycle. + +- Draft + When an invoice is first created, it is placed in Draft status by default. Sending an invoice by email will + automatically change the status from Draft to Sent. Clients cannot view any invoices when they are in Draft + status. +- Sent + When InvoicePlane sends an invoice to a client by email, it will place the invoice in Sent status. This + occurs when using the Send Email function and it also occurs when a recurring invoice is automatically + emailed. Clients can view any of their invoices when they are in Sent status. +- Viewed + When a client views the invoice by either using the Guest URL to view the invoice or by using their Guest + Login account (if they have one), the invoice will be placed in Viewed status. This allows you to keep track + of which invoices a client has looked at. +- Paid + Once an online or offline payment has been made in full against an invoice, the invoice will be placed in + Paid status. +- Overdue + Any invoice with a due date prior to the current date will be visible as being overdue. Overdue invoices + appear in invoice lists with a red due date so they are easily seen. + +Besides this lifecycle an invoice can have two other statuses: + +- Read Only + An invoice will be set to read-only if the status was changed to paid. The invoice can't be edited anymore + but you can create a credit invoice if something went wrong or needs to be changed. +- Credit Invoice + A credit invoice can be created from an existing invoice and will make a duplicate of the invoice but with a + negative amount. This means by default that the balance of both invoices is zero. + +## Viewing Invoices + +To view the invoice list, click `Invoices` from the main menu and select `View Invoices`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices.jpg) + +By default, the invoice list will show all invoices. The filter can be set to `All`, `Draft`, `Sent`, `Viewed`, +`Paid` or `Overdue` by choosing the filter from +the submenu bar. +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu with a number of items when clicked: + +- `Edit` - View the quote +- `Download PDF` - Download a copy of the quote as PDF +- `Send Email` - Send the quote to the client via email +- `Enter Payment` - Enter a payment for this invoice +- `Delete` - Delete the invoice\* + +\* This is only available for invoices with the draft status or if Invoice Deletion was enabled. + +## Creating an Invoice + +To create a new invoice, either choose `Invoices` from the main menu and select `Create +Invoice`, or from the invoice list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_add.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_add.jpg) + +When creating a invoice, start typing the name of the client to create the invoice for. If it\'s an existing +client, choose their name from the list that appears. If it's a new client, type their full name or business +name. Choose the date and invoice group and press the `Submit` button. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_edit.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_edit.jpg) + +The `Options` button near the top of the edit invoice page displays a menu with a number of items when +clicked: + +- `Add Invoice Tax` - Apply a tax to the entire invoice +- `Enter Payment` - Enter a payment for the invoice +- `Download PDF` - Download a copy of the invoice as PDF +- `Send Email` - Send the invoice to the client via email +- `Copy Invoice` - Create a copy of the invoice +- `Create Recurring` - Set the invoice to recurring +- `Delete` - Delete the invoice\* + +\* Invoice deletion is not available for all invoices. Please read the information for [invoice deletion](/en/1.7/modules/invoices#delete). + +### Add Products + +To add saved products, press the `Add Product` button. Choose the product you want to add and mark the +checkbox on the left, then press `Submit` to insert the products into the quote. +You can edit the quantity, prices or taxes for each product. When finished, press the `Save` button. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_add_product.jpg)](https://invoiceplane.com/content/screenshots/web/ip_add_product.jpg) + +### Changing Item Order + +The order in which an item appears on a quote or invoice can be changed by dragging the row to a new position +with the icon. + +### Discounts + +With the release of InvoicePlane 1.4.0 we introduced discounts for each quotes and invoices. There are two separate types of discounts which can by applied: + +- Item Discounts +- Invoice Discounts + +#### Item Discounts + +Item discounts can be added for each item itself as an amount that will be subtract from the item subtotal. Item discounts can only be added as an amount, not as an percentage. + +#### Invoice Discounts + +Invoice discounts can be added for the whole invoice directly above the invoice total. You can either choose to add a discount as an amount (e.g. 200 $) or as a percentage of the subtotal (e.g. 5%). + +### Adding Taxes + +To apply a tax against the entire invoice, choose `Add Invoice Tax` from the Options button. Choose +the appropriate tax rate and placement from the window that appears and press the `Submit` button. +That tax will be calculated against the invoice total. + +> **Warning:** +> Caution! Do not mix item and invoice taxes. Both tax methods were implemented for countries with different law structures and do not work together very well. If you use both tax method at the same time we can't promise that all calculations are executed correctly. +> +> Also, do **not** use item taxes to apply any service charges or similar extra charges. If you need to apply charges, add a new item or calculate the charges manually. + +### Copying an Invoice + +To copy an invoice, choose `Copy Invoice` from the `Options` menu. Change the client name, +if appropriate, and then select the invoice date and invoice group and press the `Submit` button. All items, taxes and amounts from the source invoice will be copied +to a new invoice. + +--- + +## Invoice Deletion + +By default InvoicePlane prevents the deletion of invoices because it's legally forbidden to delete invoices that +were sent to customers. We decided that it should be not possible to delete invoices that are beyond the `Draft` status. +But you can still enable invoice deletion even if it's not recommended. Open `/application/config/config.php` +and replace +`$config['enable_invoice_deletion'] = FALSE;` +with +`$config['enable_invoice_deletion'] = TRUE;` +To see the delete option in the pulldown, you also need to replace +`$config['disable_read_only'] = FALSE;` +with +`$config['disable_read_only'] = TRUE;` + + +Read only needs to be disabled, otherwise the options menu is not complete. + +## Read-only + +InvoicePlane will set invoices to read-only based on its status and the invoice can't be changed anymore. You can +change the status that will be used for the read-only mode in the settings. +If you don't want invoices to be set to read-only you can disable this feature. Open `/application/config/config.php` +and replace +`$config['disable_read_only'] = FALSE;` +with +`$config['disable_read_only'] = TRUE;` diff --git a/docs/en/1.7/modules/payments.md b/docs/en/1.7/modules/payments.md new file mode 100644 index 0000000..295d13c --- /dev/null +++ b/docs/en/1.7/modules/payments.md @@ -0,0 +1,45 @@ +# Payments + +## View Payments + +To view the payment list, click `Payments` from the main menu and select `View Payments`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payments.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payments.jpg) + +To navigate between pages, use the pager buttons located on the submenu bar. + +## Entering a Payment + +To enter a payment, either choose `Payments` from the main menu and select `Enter Payment`, +or from the payment list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payments_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payments_form.jpg) + +When entering a payment, first select the invoice to enter the payment for. This will default the invoice amount +into the Amount field. Adjust the date and amount, if necessary, and optionally select the payment method and +enter any pertinent notes and press the `Save` button near the top right of the page. + +## Online Payments + +InvoicePlane can be configured to allow clients to make payments online. The only payment gateway currently +tested with InvoicePlane is Stripe. + +### Configure Stripe for Online Payments + +To configure InvoicePlane integration with Stripe, you must first have a valid Stripe API Secret Key. If you +don't, follow [these +instructions](https://stripe.com/docs/keys#create-api-secret-key) first to obtain the credentials. + +Once you have your API credentials, perform the following in InvoicePlane: + +1. Click the `Settings` icon and choose the `System Settings` entry. +2. Click the `online payment` tab. +3. Set `Enable Online Payments` to `Yes`. +4. Choose `Stripe` as a merchant driver (only one available in InvoicePlane 1.6). +5. Enter the Secret Key and the Publishable Key obtained from Stripe. +6. Select the appropriate currency code. +7. Press the `Save` button. + +Once configured, send your client the `Guest URL` (found at the bottom of the Invoice Edit screen) and +they will be able to pay their invoice from the link. Optionally, you can also create a Guest User account in +which the client can log into and view and pay their invoices. diff --git a/docs/en/1.7/modules/quotes.md b/docs/en/1.7/modules/quotes.md new file mode 100644 index 0000000..b4364cd --- /dev/null +++ b/docs/en/1.7/modules/quotes.md @@ -0,0 +1,124 @@ +# Quotes + +## The Quote Lifecycle + +Quote statuses follow the lifecycle of a quote from draft to approved and allow you to keep track of where each +of your quotes are in their lifecycle. Each of the statuses listed below are automatically set for you when +specific activity occurs with a quote but you may also choose to manually change the status at any time during +the quote lifecycle. + +- Draft + When a quote is first created, it is placed in Draft status by default. Sending a quote by email will + automatically change the status from Draft to Sent. Clients cannot view any quotes when they are in Draft + status. +- Sent + When InvoicePlane sends a quote to a client by email the status will be changed to Sent. +- Viewed + When a client views the quote by either using the Guest URL to view quote or by using their Guest Login + account (if they have one), the quote will be placed in Viewed status. This allows you to keep track of + which quotes a client has looked at. +- Approved + When a client uses the guest URL to view a quote or logs in using a guest account and views a quote, they + are able to either approve or reject the quote. When a client approves a quote, the status is changed to + Approved. +- Rejected + When a client uses the guest URL to view a quote or logs in using a guest account and views a quote, they + are able to either approve or reject the quote. When a client rejects a quote, the status is changed to + Rejected. +- Canceled + This status can be used for quotes that are not going to make it to the invoicing stage but need to be kept + for reference purposes. Clients are not able to see quotes in this status. + +## Viewing Quotes + +To view the quote list, click `Quotes` from the main menu and select `View Quotes`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes.jpg) + +By default, the quote list will be filtered to all quotes. The filter can be set to `All`, `Draft`, `Sent`, `Viewed`, +`Approved`, `Rejected` or `Canceled` by choosing the filter from the submenu bar. +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu with a number of items when clicked: + +- `Edit` - View the quote +- `Download PDF` - Download a copy of the quote as PDF +- `Send Email` - Send the quote to the client via email +- `Delete` - Delete the quote + +## Creating a Quote + +To create a new quote, either choose `Quotes` from the main menu and select `Create Quote`, +or from the quote list, click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes_add.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes_add.jpg) + +When creating a quote, start typing the name of the client to create the quote for. If it's an existing client, +choose their name from the list that appears. If it's a new client, type their full name or business name. +Choose the date and invoice group and submit the form. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes_edit.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes_edit.jpg) + +The `Options` button near the top of the edit quotes page displays a menu with a number of items when +clicked: + +- `Add Quote Tax` - Apply a tax to the entire quote +- `Download PDF` - Download a copy of the quote as PDF +- `Send Email` - Send the quote to the client via email +- `Quote to Invoice` - Convert the quote to an invoice +- `Copy Quote` - Create a copy of the quote +- `Delete` - Delete the quote + +### Adding Products + +To add saved products, press the `Add Product` button. Choose the product you want to add and mark the +checkbox on the left, then press `Submit` to insert the products into the quote. +You can edit the quantity, prices or taxes for each product. When finished, press the `Save` button. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_add_product.jpg)](https://invoiceplane.com/content/screenshots/web/ip_add_product.jpg) + +### Changing Item Order + +The order in which an item appears on a quote or invoice can be changed by dragging the row to a new position +with the icon. + +### Discounts + +With the release of InvoicePlane 1.4.0 we introduced discounts for each quotes and invoices. There are two separate types of discounts which can by applied: + +- Item Discounts +- Quote Discounts + +#### Item Discounts + +Item discounts can be added for each item itself as an amount that will be subtract from the item subtotal. Item discounts can only be added as an amount, not as an percentage. + +#### Quote Discounts + +Quote discounts can be added for the whole quote directly above the quote total. You can either choose to add a discount as an amount (e.g. 200 $) or as a percentage of the subtotal (e.g. 5%). + +### Add Tax to Quote + +To apply a tax against the entire quote, choose `Add Quote Tax` from the `Options` button. +Choose the appropriate tax rate and placement from the window that appears and press the `Submit` +button. That tax will be calculated against the quote total. + +> **Warning:** +> Caution! Do not mix item and quote taxes. Both tax methods were implemented for countries with different law structures and do not work together very well. If you use both tax method at the same time we can't promise that all calculations are executed correctly. +> +> Also, do **not** use item taxes to apply any service charges or similar extra charges. If you need to apply charges, add a new item or calculate the charges manually. + +### Copying the Quote + +To copy a quote, choose `Copy Quote` from the `Options` button on the edit quote page. +Change the client name, if appropriate, and then select the quote date and quote group and submit the form. All +items, taxes and amounts from the source quote will be copied to a new quote. + +### Generate Invoice from Quote + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_quotes_quote_to_invoice.jpg)](https://invoiceplane.com/content/screenshots/web/ip_quotes_quote_to_invoice.jpg) + +When a client accepts a quote, you can convert that quote to an invoice by using the `Quote to +Invoice` menu item from the `Options` button. Choose the invoice date and invoice group and +press the `Submit` button. The items from the quote will be copied over to your new +invoice. diff --git a/docs/en/1.7/modules/recurring-invoices.md b/docs/en/1.7/modules/recurring-invoices.md new file mode 100644 index 0000000..68d1947 --- /dev/null +++ b/docs/en/1.7/modules/recurring-invoices.md @@ -0,0 +1,40 @@ +# Recurring Invoices + +Oftentimes instead of sending an invoice as a one time charge, you need to send an email to a client on a +schedule. For example, you may be offering web hosting to your clients, and most likely they are paying for your +services once a month, once a year, etc. It would be a bummer to have to remember to create these invoices every +month, wouldn't it? InvoicePlane can keep this sorted for you. + +## Requirements + +For recurring invoices to generate properly, you must create a [CRON job](/en/1.7/help/setup_cron) or +a scheduled task that opens the following URL once per day: + +``` +http://your-domain.com/invoices/cron/recur/your-cron-key-here +``` + +Replace `your-cron-key-here` with the generated cron key in [System +Settings](/en/1.7/settings/general). + +## Create a recurring Invoice + +To create an invoice which will automatically recur at a specific frequency, the first step is to create the +first invoice and get it sent to your client as you normal would. Once the first invoice has been created, it +can be set up as a recurring invoice by selecting `Create Recurring` from the `Options` +menu. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_make_recurring.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_make_recurring.jpg) + +The invoice can be set to recur every week, month, year, quarter or six months. Since the first invoice has +already been created, the start date should be set to the next date this particular invoice should recur on. +Generally the start date should be a date in the future. If the invoice should stop recurring on a particular +date, then enter an end date as well. If the invoice should recur perpetually, then leave the end date +empty. + +## Viewing Recurring Invoices + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoices_recurring.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoices_recurring.jpg) + +The list of recurring invoices displays each recurring invoice set up in your system. Recurring invoices may be +stopped or deleted from the `Options` button in the list of recurring invoices. diff --git a/docs/en/1.7/modules/tasks-projects.md b/docs/en/1.7/modules/tasks-projects.md new file mode 100644 index 0000000..8eaa5c5 --- /dev/null +++ b/docs/en/1.7/modules/tasks-projects.md @@ -0,0 +1,38 @@ +# Tasks and Projects + +InvoicePlane provides basic task management that is integrated into the invoice workflow. You can link tasks to projects and projects to clients to structure everthing. + +## Projects + +Projects can be added from the navigation bar. You can chose the project name and a client. Choosing a client is optional. If you choose a client, tasks that are assigned to this project can onl be added to invoices for the same client. + +## Tasks + +Tasks can be added from the navigation bar. They have several fields that are explained in the following table. + +| Field | Description | +| --- | --- | +| Task name | The title or name of the task. Normally a short headword or sentence | +| Task description | Can contain a long text that discribes the task. Can also be used to store notes. | +| Task price | The price set here will be used in invoices to properly store tasks. The task price is the same as the product price. | +| Tax Rate | Task tax rates are the same like product tax rates. It will be added to the task price if added to an invoice. | +| Finish date | Also called deadline, it defines the date where the task should be finished. Tasks are displayed as overdue (red color) if the finish date has already passed. | +| Status | The task status defines the current state of the task. More information can be found below. | +| Project | This optional select can be used to link tasks to projects. | + +### Task Status + +A task can have one off the following statuses. Please notice that only completed tasks can be added to invoices. + +| Status | Description | +| --- | --- | +| Not started | The title or name of the task. Normally a short headword or sentence | +| In progress | The task is currently in progress. Someone works on the task. | +| Completed | The task was completed and is ready to be added to an invoice. | + +### Tasks in Invoices + +Inside invoices you can add tasks to an invoice. Therefore, use the "Add Task" button. This will open a new panel where all available tasks will be listed. Please notice that the following requirements must be fullfilled for a tasks to be available: + +- the task must be have the status Completed. +- the task must either have no linked project or the client of the current invoice must match theclient that is assigned to the linked project. diff --git a/docs/en/1.7/settings/custom-fields.md b/docs/en/1.7/settings/custom-fields.md new file mode 100644 index 0000000..9255978 --- /dev/null +++ b/docs/en/1.7/settings/custom-fields.md @@ -0,0 +1,28 @@ +# Custom Fields + +Custom fields can be created to store information which InvoicePlane doesn\'t provide fields for. Custom fields +can be created for: + +- Clients +- Quotes +- Invoices +- Payments +- User Accounts + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_custom_fields.jpg)](https://invoiceplane.com/content/screenshots/web/ip_custom_fields.jpg) + +## Adding a Custom Field + +To add a new custom field click on the settings icon in the menubar and +then choose `Custom Fields`. On the overview click on `New` in the top right. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_custom_fields_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_custom_fields_form.jpg) + +When adding custom fields, it is recommended to only use alpha and numeric characters for the label name. Once a +custom field has been added to an object, the custom field will display at the bottom of the form for that +object (so a custom field created for the client object will appear on the client form). + +## Adding Custom Fields to Templates + +Please take a look at the [Customize Templates +page](/en/1.7/templates/customize-templates#custom-fields) for more information about custom fields in templates. diff --git a/docs/en/1.7/settings/email-templates.md b/docs/en/1.7/settings/email-templates.md new file mode 100644 index 0000000..49f5b0f --- /dev/null +++ b/docs/en/1.7/settings/email-templates.md @@ -0,0 +1,31 @@ +# Email Templates + +Instead of having to type the body of an email each time an invoice or quote is emailed from InvoicePlane, email templates can be customized to your liking, giving you a set of predefined templates to choose from. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_email_templates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_email_templates.jpg) + +## Creating an Email Template + +To create a new email template, click the settings icon near the right hand side of the main menu, select `Email Templates`, and click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_email_templates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_email_templates.jpg) + +Template variables can be inserted into the body of your email by clicking the name of the variable to include from the list below the form. The example above shows what an email template for a new invoice might look like. + +## Setting Default Email Templates + +To access the settings for your default templates, click the settings icon , select `System Settings`, and choose either the `Invoices` or the `Quotes` tab + +**Invoices** + +- Default Email Template - The selected template would be used for invoices in draft, sent and viewed statuses. +- Paid Email Template - The selected template would be used for invoices in paid status. +- Overdue Email Template - The selected template would be used for invoices which are overdue. + +**Quotes** + +- Default Email Template - The selected template would be used for all quotes in any status. +- Paid Email Template - The selected template would be used for invoices in paid status. +- Overdue Email Template - The selected template would be used for invoices which are overdue. + +When manually sending an invoice or quote from within InvoicePlane, the appropriate email template will be selected prior to sending. Of course, you may make any last minute adjustments to the content of the email before sending it. Since recurring invoices send email on their own without any manual intervention, it is helpful to have a set of email templates created and the default settings configured so InvoicePlane knows which template to use each time it sends them out. diff --git a/docs/en/1.7/settings/email.md b/docs/en/1.7/settings/email.md new file mode 100644 index 0000000..99833bd --- /dev/null +++ b/docs/en/1.7/settings/email.md @@ -0,0 +1,12 @@ +# Email Settings + +Before InvoicePlane can send emails you have to configure he email settings here. You can choose between three different ways to send emails. +If you don't want that invoice and quote pdf files are automatically attached to emails disable this feature by changing `Attach Quote/Invoice on email?` to `No` + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_mail.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_mail.jpg) + +| Method | Description | +| --- | --- | +| PHP Mail | Uses the built-in email sending method of PHP which allows to send mails without any configuration. | +| Sendmail | Like PHP Mail all emails will be sent without the need to configure anything. Please choose Sendmail only if you are sure that your server has Sendmail installed, enabled and configured because it is possible that your servers OS does not ship with Sendmail by default. | +| SMTP | You can also use a SMTP server to send mails. Using SMTP allows you to send emails via external servers. You will need the SMTP server's hostname, login credentials and the used port and security method. | diff --git a/docs/en/1.7/settings/general.md b/docs/en/1.7/settings/general.md new file mode 100644 index 0000000..5c4a5f8 --- /dev/null +++ b/docs/en/1.7/settings/general.md @@ -0,0 +1,45 @@ +# General Settings + +The general settings page sets a lot of options that will change the look & feel of the whole application or +that are needed for some special purposes. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_general.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_general.jpg) + +## General settings + +| Setting | Description | +| --- | --- | +| Language | Choose the [language](/en/1.7/system/translation-localization) for the application | +| First day of the Week | Choose if the week should start on sunday or monday | +| Default Country | Select the country that will be used automatically when adding clients | +| Date Format | Choose the date format of the application | +| Currency Symbol | Choose the currency symbol like `€` or `$`. You can also use any letters like `AUD` or `CHF` | +| Currency Symbol Placement | Choose if the currency symbol should be placed before or after amounts | +| Thousand Separator | Select if thousands should be separated by `,` or `.` | +| Decimal Point | Select if the decimals point should be `,` or `.` | +| Tax Rate Decimal Places | Select how much placed after the decimal point should be used for tax rates. | + +## Dashboard settings + +| Setting | Description | +| --- | --- | +| Quote Overview Period | Select the period that should be used for quotes on the quote overview | +| Invoice Overview Period | Select the period that should be used for invoices on the invoice overview | + +## Interface settings + +| Setting | Description | +| --- | --- | +| Disable the Sidebar | Choose if the sidebar should be disabled | +| Custom Title | Set a custom title which will be shown on browser tabs | +| Use Monospace font for Amounts | Choose if the application should use a monospace font for amounts. Example: `1.345,23 €` | +| Login Logo | Upload an image that will be displayed above the login form. Recommended size: about 300px width | +| Cron Key | You will need this cron key to setup [recurring invoices](/en/1.7/modules/recurring-invoices). | + +## System settings + +| | | +| --- | --- | +| Send all outgoing emails as BCC to the admin account | If you enable this option **every** outgoing email is sent as an anonymous copy (BCC) to the administrator. The administrator is the user that was created during the InvoicePlane setup. | +| Cron Key | You will need this cron key to setup [recurring invoices](/en/1.7/modules/recurring-invoices) | +| Enable Debug Mode | The debug mode enables logging for the application. The logs can be found in the `/application/logs` folder or in your browser console. | diff --git a/docs/en/1.7/settings/index.md b/docs/en/1.7/settings/index.md new file mode 100644 index 0000000..dbccd15 --- /dev/null +++ b/docs/en/1.7/settings/index.md @@ -0,0 +1,15 @@ +# Settings + +- [General Settings](/en/1.7/settings/general) +- [Invoice Settings](/en/1.7/settings/invoices) +- [Quotes Settings](/en/1.7/settings/quotes) +- [Tax Settings](/en/1.7/settings/taxes) +- [eMail Settings](/en/1.7/settings/email) +- [Online Payments](/en/1.7/settings/online-payments) +- [Updatecheck](/en/1.7/settings/updatecheck) +- [Custom Fields](/en/1.7/settings/custom-fields) +- [eMail Templates](/en/1.7/settings/email-templates) +- [Invoice Groups](/en/1.7/settings/invoice-groups) +- [Payment Methods](/en/1.7/settings/payment-methods) +- [Taxrates](/en/1.7/settings/taxrates) +- [User Accounts](/en/1.7/settings/user-accounts) diff --git a/docs/en/1.7/settings/invoice-groups.md b/docs/en/1.7/settings/invoice-groups.md new file mode 100644 index 0000000..4ac882d --- /dev/null +++ b/docs/en/1.7/settings/invoice-groups.md @@ -0,0 +1,41 @@ +# Invoice Groups + +When a new invoice or quote is created, InvoicePlane uses invoice groups to determine the next invoice or quote number and how it should be structured. InvoicePlane comes with two default invoice groups - Invoice Default and Quote Default. Both groups will generate simple incremental ID's starting at the number 1, but the Quote Default will be prefixed with "QUO". + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoice_groups.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoice_groups.jpg) + +## Configure an Invoice Group + +These default groups can be customized and any number of new groups can be created. Each group has a number of options. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_invoice_groups_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_invoice_groups_form.jpg) + +| Setting | Description | +| --- | --- | +| Name | The name if the invoice group that will be used in the settings | +| Identifier formatting | The identifier is used to generate invoices or quotes and can consist of alpha-numeric characters | +| Next ID | Set the ID for the next invoice. Please notice that you should not set the next ID to a number below the ID of the last generated ID. Example: You created 59 invoices but you want the next invoice to have the ID 100 so set the Next ID to 100. | +| Left Pad | The left padding can be used to generate IDs that contain zeros to the left of the ID. The left padding contains the invoice ID itself. Example: you set the left padding to 5 which would lead to invoice IDs like 00056 or 00397. | + +### Format the Identifier + +> **Warning:**Caution! The identifier **must** contain the `{{{ID}}}` tag no matter where! + +There are some template tags that can be used to create a custom identifier. + +| Name | Tag | Description | +| --- | --- | --- | +| ID | `{{{ID}}}` | Inserts the increasing ID of the invoice | +| Current Year | `{{{year}}}` | Inserts the current year with 4 digits | +| Current month | `{{{month}}}` | Inserts the current month with 2 digits | +| Current day | `{{{day}}}` | Inserts the current day with 2 digits | + +### Formatting Examples + +| Template | Output | +| --- | --- | +| `{{{year}}}/{{{ID}}}` | YYYY/456 | +| `{{{year}}}_{{{month}}}_{{{ID}}}` | YYYY\_MM\_456 | +| `{{{year}}}-{{{month}}}-{{{day}}}-{{{ID}}}` | YYYY-MM-DD-456 | +| `IN{{{year}}}{{{ID}}}` | INYYYY456 | +| `IPQ-{{{day}}}{{{ID}}}` | IPQ-DD456 | diff --git a/docs/en/1.7/settings/invoices.md b/docs/en/1.7/settings/invoices.md new file mode 100644 index 0000000..a11b0b5 --- /dev/null +++ b/docs/en/1.7/settings/invoices.md @@ -0,0 +1,21 @@ +# Invoice Settings + +On the invoice settings page you can set a lot of options to control how invoices should behave. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_invoices.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_invoices.jpg) + +## General settings + +| Setting | Description | +| --- | --- | +| Default Invoicegroup | Select the [Invoicegroup](/en/1.7/settings/invoicegroups) that should be used by default | +| Set the Invoice to read-only on | Select on which state an invoice should be set to read-only | +| Invoice due after | Select after how many days an invoice should be set to due | +| Default Terms | You can enter the default terms for any invoice here | +| Automatically email recurring invoices | If you have recurring invoices you can choose if InvoicePlane should send an email with the invoice attached to the client automatically | +| Mark Invoices as sent when PDF is generated | Choose if InvoicePlane should set the status of an invoice to `Sent` when you download the PDF | +| Invoice Logo | Upload an image that should be placed on templates. | + +## Templates + +All following settings allow you to set default PDF and email templates for different states and purposes. At the end in the PDF Footer you can enter information that should be placed at the bottom of each PDF template. diff --git a/docs/en/1.7/settings/online-payments.md b/docs/en/1.7/settings/online-payments.md new file mode 100644 index 0000000..359e956 --- /dev/null +++ b/docs/en/1.7/settings/online-payments.md @@ -0,0 +1,25 @@ +# Merchant Account Settings + +InvoicePlane 1.6 supports only **Stripe** by default as a payment gateway. The reason why the other providers were dropped can be found [here](/en/1.7/getting-started/updating-ip#16-breaking-changes). Please let us know what payment method you are missing at [GitHub](https://github.com/InvoicePlane/InvoicePlane/issues) + +### Configure your payment provider + +To configure your payment provider, select the provider from the dropdown list. If you don't know which provider should be selected please contact your provider. We cannot offer any support for specific provider settings. + +After selecting a provider InvoicePlane will show you a configuration box will all needed settings. Make sure to enable the provider first. After that fill all needed information. Again: if you are not shure which fields to fill, contact your provider. + +> **Warning:**It is highly recommended to test if the online payment is working correctly using the **Test Mode** if available. This allows you to pay online without transfering real money. + +### Configure **Stripe** as a payment provider + +1. Login or regiser for an account at [stripe.com](https://stripe.com) +2. Once you logged in, on the top search bar look for the `API Keys` page. +3. Create a new *secret key*. +4. Now, open the `settings` in your InvoicePlane installation and navigate to the `online payment` tab. +5. Tick the `Enable Online Payments` checkbox. +6. From the dropdown list select `Stripe` as a payment provider. +7. Tick the `enable` checkbox on the stripe card that appeared when you selected stripe as a payment provider in the last step. +8. Insert the secret key and the publishable key in the corrisponding fields. The secret key must be set in the field that hides the characters (like a password). +9. Click on **save**, and you are done! + +Please take note that InvoicePlane is in no way affiliated to Stripe and that we are not able to help with Stripe specific issues. These instructions only concern integrating Stripe as a payment gateway in InvoicePlane. diff --git a/docs/en/1.7/settings/payment-methods.md b/docs/en/1.7/settings/payment-methods.md new file mode 100644 index 0000000..c700cbf --- /dev/null +++ b/docs/en/1.7/settings/payment-methods.md @@ -0,0 +1,13 @@ +# Payment Methods + +Payment Methods + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payment_methods.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payment_methods.jpg) + +## Add a Payment Method + +To add a new payment method, click the settings icon near the right hand side of the main menu, select `Payment Methods`, and click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_payment_methods_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_payment_methods_form.jpg) + +Simply enter the name of the payment method and click on `Save` button. The method will be available when adding a payment. diff --git a/docs/en/1.7/settings/quotes.md b/docs/en/1.7/settings/quotes.md new file mode 100644 index 0000000..a939f0a --- /dev/null +++ b/docs/en/1.7/settings/quotes.md @@ -0,0 +1,17 @@ +# Quote Settings + +The general settings page sets a lot of options that will change the look & feel of the whole application or that are needed for some special purposes. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_quotes.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_quotes.jpg) + +## General settings + +| Setting | Description | +| --- | --- | +| Quote expires after | Choose after how many days a quote should be set to expired | +| Default Quotegroup | Select the [Quotegroup (aka Invoicegroups)](/en/1.7/settings/invoicegroups) that should be used by default | +| Mark Quotes as sent when PDF is generated | Choose if InvoicePlane should set the status of an quote to `Sent` when you download the PDF | + +## Templates + +All following settings allow you to set default PDF and email templates for different states and purposes. diff --git a/docs/en/1.7/settings/taxes.md b/docs/en/1.7/settings/taxes.md new file mode 100644 index 0000000..e5c158f --- /dev/null +++ b/docs/en/1.7/settings/taxes.md @@ -0,0 +1,11 @@ +# Tax Settings + +The general settings page sets a lot of options that will change the look & feel of the whole application or that are needed for some special purposes. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_taxes.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_taxes.jpg) + +| Setting | Description | +| --- | --- | +| Default Invoice Tax Rate | Choose the [Taxrate](/en/1.7/settings/taxrates) that should be applied to an invoice by default | +| Default Invoice Tax Rate | Choose where to place the invoice tax | +| Default Invoice Tax Rate | Choose the [Taxrate](/en/1.7/settings/taxrates) that should be applied to every product of an invoice by default | diff --git a/docs/en/1.7/settings/taxrates.md b/docs/en/1.7/settings/taxrates.md new file mode 100644 index 0000000..575271d --- /dev/null +++ b/docs/en/1.7/settings/taxrates.md @@ -0,0 +1,13 @@ +# Taxrates + +If you want to add taxes to products / items or invoices you have to configure them on the Taxrates settings page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_taxrates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_taxrates.jpg) + +## Add a new Taxrate + +To add a new taxrate, click the settings icon near the right hand side of the main menu, select `Taxrates`, and click the `New` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_taxrates_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_taxrates_form.jpg) + +First enter the official name of the taxrate. Be careful as this will be displayed on quotes or invoices as a description of the taxrate. Then enter the percentage of the taxrate and click on `Save`. diff --git a/docs/en/1.7/settings/updatecheck.md b/docs/en/1.7/settings/updatecheck.md new file mode 100644 index 0000000..ff440fa --- /dev/null +++ b/docs/en/1.7/settings/updatecheck.md @@ -0,0 +1,6 @@ +# Updatecheck + +On the updatecheck page InvoicePlane checks for updates with contacting our website. The result of the check will be displayed below the version. +Additionally the latest news will be displayed below the updatecheck. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_settings_updates.jpg)](https://invoiceplane.com/content/screenshots/web/ip_settings_updates.jpg) diff --git a/docs/en/1.7/settings/user-accounts.md b/docs/en/1.7/settings/user-accounts.md new file mode 100644 index 0000000..cd79dc2 --- /dev/null +++ b/docs/en/1.7/settings/user-accounts.md @@ -0,0 +1,70 @@ +# User Accounts + +InvoicePlane can contain an unlimited number of user accounts (both Administrator and Guest), but there is no +real level of ownership or separation between different administrator accounts. Each administrator account has +full access to the entire system and can see all data system-wide. Guest accounts are read-only and can be +restricted to see invoices, quotes and payments for the client or clients you specify. + +## User Types + +**Administrator** + +An administrator account has full access to the entire system. Administrators can create and delete clients, +invoices, payments, users, and everything else in the system. The account created during installation is an +administrator account. If you don't want somebody having full access to all of your data, do not create an +administrator account for them. + +**Guest (Read Only)** + +There may be times where you need to allow a user into your system, but with limited access. Guest accounts allow +you to create a user account which can only view quotes, invoices and payments for one or more clients. A guest +account may be created for a particular client, in which case you would create the account and grant access to +only that client. A guest account may also be created for an accountant, in which case you might create the +account and grant access to more than just one client. + +## Viewing Users + +To view the user list, click the settings icon near the right hand side +of the main menu and select `User Accounts`. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts.jpg) + +To navigate between pages, use the pager buttons located on the submenu bar. + +The `Options` button at the end of each row displays a menu from which you can edit or delete an user. + +## Add an User Account + +To add a new user account, click the settings icon near the right hand +side of the main menu, select `User Accounts`, and click the `New` button near the top +right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts_form.jpg) + +To create the user account, provide the user's name (typically their full name), email address (this is what +they'll use to log in with), password and password verification. When selecting the user type, choose between +`Administrator` or `Guest`. Once the user type has been selected, the rest of the form +will display below the initial form. + +If `Administrator` was selected as the user type, several fields will be made available to complete, +such as their address and location information and contact information. Fill in the fields and press the `Save` button near the top right of the page. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts_form.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts_form.jpg) + +If `Guest` was selected as the user type, an area will be made available from which you can give +access to one or more clients for the `Guest` user account. To provide access to a single client, +press the `Add Client` button, begin typing the name of the client in to the form and select the +client when they appear in the list. Press the `Submit` button. If you want you can add +another client to the user account. If not press `Cancel`. Don't forget to save the user +account. + +[![](https://invoiceplane.com/content/screenshots/web_thumb/ip_useraccounts_add_client.jpg)](https://invoiceplane.com/content/screenshots/web/ip_useraccounts_add_client.jpg) + +If a guest account is not a client, but instead an accountant, you will probably want to provide them with access +to more than just a single client. In that case, press the `Add Client` button, begin typing the name +of the first client in to the form and select the client when they appear in the list. Press the `Submit` button and begin typing the next client name. Rinse, wash and repeat until +each client the guest should have access to has been added to the list. Press the Close button and then press +the `Save` button near the top of the page when finished. + +No matter if the account is an Administrator account or a Guest account, all users use the same URL to log in. Be +sure and provide your login URL to any users who you create accounts for. diff --git a/docs/en/1.7/system/importing-data.md b/docs/en/1.7/system/importing-data.md new file mode 100644 index 0000000..f252793 --- /dev/null +++ b/docs/en/1.7/system/importing-data.md @@ -0,0 +1,57 @@ +# Importing Data + +InvoicePlane can import data from any system as long as it is provided in comma delimited CSV format and is +structured according to the details below. The data import tool can be accessed by clicking the Settings icon +and choosing the Import Data item. + +The import tool assumes the following: + +The file names will be exactly as they are listed below. +All of the columns listed below must be present in the files, even if there is no data in the column. +The first row of each file must contain the file headings, and those headings must be named exactly as they are +listed below. +The files must all be in comma delimited CSV format. +The files to import must be located in your uploads/import folder. +The email address in the invoice file must be an email address of an actual user account currently in +InvoicePlane. +If any of the rules above are not met, the import will not work as expected. + +**File names and columns** + +- clients.csv + - client\_name + - client\_address\_1 + - client\_address\_2 + - client\_city + - client\_state + - client\_zip + - client\_country + - client\_phone + - client\_fax + - client\_mobile + - client\_email + - client\_web + - client\_vat\_id + - client\_tax\_code + - client\_active (1 for active, 0 for inactive) +- invoices.csv + - user\_email + - client\_name + - invoice\_date\_created (yyyy-mm-dd format) + - invoice\_date\_due (yyyy-mm-dd format) + - invoice\_number + - invoice\_terms +- invoice\_items.csv + - invoice\_number + - item\_tax\_rate (ex: 7.8 would indicate 7.8%) + - item\_date\_added (yyyy-mm-dd format) + - item\_name + - item\_description + - item\_quantity + - item\_price (without any currency symbols) +- payments.csv + - invoice\_number + - payment\_method (ex: Cash, Credit or PayPal) + - payment\_date (yyyy-mm-dd format) + - payment\_amount (without any currency symbols) + - payment\_note diff --git a/docs/en/1.7/system/index.md b/docs/en/1.7/system/index.md new file mode 100644 index 0000000..7a8a489 --- /dev/null +++ b/docs/en/1.7/system/index.md @@ -0,0 +1,5 @@ +# System + +- [Translation / Localization](/en/1.7/system/translation-localization) +- [Importing Data](/en/1.7/system/importing-data) +- [Upgrade from FusionInvoice](/en/1.7/system/upgrade-from-fusioninvoice) diff --git a/docs/en/1.7/system/translation-localization.md b/docs/en/1.7/system/translation-localization.md new file mode 100644 index 0000000..c00d15a --- /dev/null +++ b/docs/en/1.7/system/translation-localization.md @@ -0,0 +1,63 @@ +# Translation / Localization + +InvoicePlane comes with the English language by default. To contribute to or to download other language packs +please visit the [translation repository](https://crowdin.com/project/invoiceplane). + +## Install a new translation + +> **Warning:** +> Please notice: some translations are not complete so some texts will be displayed in English. So do not delete +> the english language folder! + +1. Download the translation pack from the [translation + repository](https://crowdin.com/project/invoiceplane) +2. Open the folder of the language you want to install (`de` = German) +3. Copy the folder that should be called something like `de_DE`, `fr_FR` or + `es_AR` +4. Paste the folder to the following directory of your InvoicePlane installation: + `/application/language/` +5. Apply the language in your [general settings](/en/1.7/settings/general). + +Your folder structure should look like this: + +``` +├── application/ +│ ├── ... +│ ├── language/ +│ │ ├── english/ +│ │ └── Deutsch/ +│ │ ├── custom_lang.php +│ │ ├── ip_lang.php +│ │ ├── merchant_lang.php +│ │ └── ... +│ └── ... +├── assets/ +└── ... +``` + +## Customize translations + +You are able to replace all language strings in the application with your own strings. We added a file called `custom_lang.php` which is located in every language folder (see above). + +To replace or alter a translation, search for the string in the main language files (ip\_lang.php). You have to copy the whole line with the string into the `custom_lang.php` file that it looks like this: + +``` + 'Actual content of the Language String', + +); +``` + +Now, simply change the translation to whatever you need. But keep in mind that some strings are designed to fit into special spaces. Try to keep the character count or the original string. + +> **Danger:** +> If you want to use the `'` character in your string you have to replace it with `\'`. +> Example: `'language_string_key' => 'Description with \'quotes\'',` diff --git a/docs/en/1.7/system/upgrade-from-fusioninvoice.md b/docs/en/1.7/system/upgrade-from-fusioninvoice.md new file mode 100644 index 0000000..bc426af --- /dev/null +++ b/docs/en/1.7/system/upgrade-from-fusioninvoice.md @@ -0,0 +1,32 @@ +# Upgrade form FusionInvoice + +If you used FusionInvoice v.1x to manage your invoices you can migrate to InvoicePlane. +Follow these steps to +migrate your installation. + +## Make a full Backup + +Actually you don't have to make a full backup of your FusionInvoice setup but we recommend to do so. We can not +guarantee that the [Migrationtool](https://github.com/InvoicePlane/Migrationtool) is working without +problems. +Make a complete copy of the folder that holds your installation and make a backup of your +database. + +## Use the Migrationtool + +1. [Download the Migrationtool](https://github.com/InvoicePlane/Migrationtool/archive/master.zip) + and unzip it to any directory on your webserver or your local machine and check if you copied the `.htaccess` + file. +2. If you want to run the tool in a subdirectory please set the directory in the `config.php` file. +3. Then open the URL which can access the Migrationtool and follow the instructions. + +> **Warning:**Please do **not** use multiple directories like `yourdomain.com/tools/migration/migrationtool` +> as the tool only supports one directory at the moment. + +## Run the InvoicePlane Updates + +After converting the database it's very important that you open the setup wizard +of your InvoicePlane installation located at `yourdomain.com/setup`. Follow the instructions and the +setup will run any necessary database updates. Without these updates InvoicePlane will not run. + +> **Note:** diff --git a/docs/en/1.7/templates/customize-templates.md b/docs/en/1.7/templates/customize-templates.md new file mode 100644 index 0000000..856e2da --- /dev/null +++ b/docs/en/1.7/templates/customize-templates.md @@ -0,0 +1,160 @@ +# Customize Templates + +For the customization you just need some little knowledge of HTML and CSS. PHP knowledge is not needed by +default but may help if you want to achieve special layouts or functions. + +> **Warning:** +> Please remember: Before doing any customizations, make a copy of a default template! If you make changes in the +> default templates they will be overwritten on updates. + +> **Note:** +> Hint: PDF templates will be generated with a PDF engine called mPDF. This means that some styles may not work +> because of conversion from HTML to PDF. If you need help with styling please refer to the [mPDF documentation](https://mpdf.github.io/). + +## Customize the Look and Feel + +First of all please remember that there is a basic styling for each template. The files use two CSS stylesheets +and some hardcoded styles. If you want to customize your template you should make changes in the hardcoded part +which means: edit the content between `` only. Do not +edit the templates.css as changes will be overwritten on updates. + +## First Steps + +InvoicePlane already provides a lot of data for all templates. The table below gives you an overview on which +variables are available in the templates. + +### Invoice Templates + +| Variable | Description | +| --- | --- | +| `$invoice` | It holds data about the invoice itself, the user that created the invoice and the client that is selected for the invoice. It also provides all payments if there are any in the database. | +| `$invoice_tax_rates` | Provides information about all tax rates that were applied to the invoice | +| `$items` | Contains all invoice items with their corresponding data. | +| `$payment_method` | Provides information about the selected payment method. | +| `$custom_fields` | Contains custom fields for the invoice, the user, the client and if available for the parent quote. | +| `$show_item_discounts` | Is true if there are any items with a discount, is false if not. Can be used to display the additional discount column only if there are discounts to display. | + +### Quote Templates + +| Variable | Description | +| --- | --- | +| `$quote` | It holds data about the quotes itself, the user that created the quote and the client that is selected for the quotes. | +| `$quote_tax_rates` | Provides information about all tax rates that were applied to the quote. | +| `$items` | Contains all quote items with their corresponding data. | +| `$custom_fields` | Contains custom fields for the quote, the user and the client. | +| `$show_item_discounts` | Is true if there are any items with a discount, is false if not. Can be used to display the additional discount column only if there are discounts to display. | + +If you want to know which data is available in every variable go to the bottom of the template and add the +following code directly above the `` tag. Replace *invoice* with the name of the +variable your want to look up. + +``` +
+``` + +If you load the template now you will see something like this but with hundred more lines: + +``` +stdClass Object +( + [client_id] => 13 + [invoice_id] => 24 + [user_id] => 2 + [invoice_group_id] => 8 +... +``` + +This is the list of all available variables where the part in the brackets (e.g. `invoice_id`) is the +name of the variable and the part after the `=>` is the content of the variable. + +## Adding Custom Fields + +Custom fields work in a special way. As custom fields are added by the user there is no way to define which +fields will be available. Therefore InvoicePlane searches for all available custom fields before printing the +template. All fields are stored in the `$custom_fields` variable that may look like this: + +``` +Array +( + [invoice] => Array + ( + [Sent at] => 2016-11-15 + [Contributors] => [ + 0 => Marty McFly + 1 => Jennifer McFly + ] + ) + [client] => Array + ( + [CRM ID] => 346999-13400 + [has Supervisor] => 1 + [Supervisors] => 1 + ) + [user] => Array + () + [quote] => Array + ( + [Sent at] => 2016-11-10 + [Special discount offered?] => 0 + ) +) +``` + +The `$custom_fields` variable is a collection of all custom field types that group all available +custom fields. As you can see in the example, the invoice has a custom field named *Sent at*, the client +has a field called *CRM ID* and so on. + +To access a specific custom field, you have to use the followng code example: + +``` + +``` + +where *client* should be the group and *CRM ID* should be the label of your custom field. Using the +code example would simply output `346999-13400` in your template. + +### Yes / No Custom Fields + +Yes/no fields will have the value `1` for yes and `0` for no. This way you can use the custom field in conditional statements like this: + +``` + +``` + +## Code Examples + +Here is a list of some examples for code that can be used to display variables. +Replace `invoice` with `quote` when editing quote templates. +Replace `variable_name` with the actual name of the variable. + +| Description | Code | +| --- | --- | +| **Add a new Variable** To add a new variable to the template. Replace `variable_name` with the actual name of the variable. | ``` variable_name; ?> ``` | +| **Format amounts** If you want to display amounts you have to use this code in order to display the amount in the correct format. | ``` variable_name); ?> ``` | +| **Conditional Statements** Only display code if a variable is not empty. This could be used for example if you don't want to display the taxes column if there are no taxes. | ``` variable_name)): ?> -- display any HTML or variables here -- ``` | +| **Display the Invoice Logo** The logo can be set in the System Settings. | ``` ``` | + +## Debugging Templates + +The PDF engine is not that good in handling errors or HTML that is broken due to PHP errors. You may get output +like this: + +``` +Severity: Notice +Message: Undefined offset: 2 +Filename: src/Tag.php +Line Number: 1806 +... +``` + +To know what is wrong with your template, you have to add a small code line in your template helper. Open the +file `application/helpers/pdf_helper.php` and add + +Place `print_r($html);exit;` at line 98 for invoice templates. + +Place `print_r($html);exit;` at line 250 for quote templates. + +This will output the plain HTML that will be used to generate your PDF files. If there are any problems with +missing or faulty variables or wrong PHP code, you should see the corresponding output here. diff --git a/docs/en/1.7/templates/index.md b/docs/en/1.7/templates/index.md new file mode 100644 index 0000000..e40178a --- /dev/null +++ b/docs/en/1.7/templates/index.md @@ -0,0 +1,4 @@ +# Templates + +- [Using Templates](/en/1.7/templates/using-templates) +- [Customize Templates](/en/1.7/templates/customize-templates) diff --git a/docs/en/1.7/templates/using-templates.md b/docs/en/1.7/templates/using-templates.md new file mode 100644 index 0000000..5d12bcd --- /dev/null +++ b/docs/en/1.7/templates/using-templates.md @@ -0,0 +1,17 @@ +# Using Templates + +First of all, the templates shipped with InvoicePlane are what they are called: templates. You *can* use them directly for your business but they are meant to be duplicated and customized. + +There are two main types of templates which are used: + +- PDF Templates - Used to generate the quote and invoices PDF files +- Web Templates - Used to display the quotes and invoices in a web browser for guest users (clients) + +## Using PDF Templates + +All PDF templates can be found in the following folders of the application: + +- `/application/views/invoice_templates/pdf` for invoices +- `/application/views/quote_templates/pdf` for quotes + +You can select which templates should be used in the system settings for either [Invoices](/en/1.5/settings/invoices) or [Quotes](/en/1.5/settings/quotes). You can find the select boxes below the headline "Templates". Simply select the template, save and the template will be used for the next quote or invoice. From cf29b245f45e92e27df8d99932ffb00186b86353 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 02:30:25 +0000 Subject: [PATCH 05/13] Add 1.7 documentation for PDF template allow lists and e-invoicing PDF template allow list (docs/en/1.7/templates/pdf-template-allowlist.md): - Explains the RCE fix that replaced dynamic template scanning with a static allow list in Mdl_templates.php - Documents CUSTOM_TEMPLATES_FOLDER and the four CUSTOM_*_TEMPLATES_* ipconfig.php settings for declaring custom template names - Covers file permission hardening and post-upgrade audit steps E-invoicing (docs/en/1.7/modules/e-invoicing.md): - Documents UBL, CII, and Factur-X/ZUGFeRD support - Explains the XMLconfigs + XMLtemplates file pair system for adding custom XML formats - Covers Peppol context (UBL output, separate access point required) - Lists required client fields and the per-client activation steps updating-ip.md: expanded with pre-upgrade security audit, custom template migration paths (Option A/B), new ipconfig.php settings block, and post-upgrade file permission hardening. index.md / modules/index.md / templates/index.md: linked new pages. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01FyUdA46kyTUidfhs4sAEG7 --- docs/en/1.7/getting-started/updating-ip.md | 121 ++++++++++++++++-- docs/en/1.7/index.md | 2 + docs/en/1.7/modules/e-invoicing.md | 112 ++++++++++++++++ docs/en/1.7/modules/index.md | 3 +- docs/en/1.7/templates/index.md | 1 + .../1.7/templates/pdf-template-allowlist.md | 108 ++++++++++++++++ 6 files changed, 332 insertions(+), 15 deletions(-) create mode 100644 docs/en/1.7/modules/e-invoicing.md create mode 100644 docs/en/1.7/templates/pdf-template-allowlist.md diff --git a/docs/en/1.7/getting-started/updating-ip.md b/docs/en/1.7/getting-started/updating-ip.md index 2c1b6c5..a903d74 100644 --- a/docs/en/1.7/getting-started/updating-ip.md +++ b/docs/en/1.7/getting-started/updating-ip.md @@ -2,37 +2,130 @@ ## Contents -- [Upgrade information](#upgrade-information) +- [Breaking changes](#breaking-changes) +- [New ipconfig.php settings](#new-ipconfigphp-settings) - [**Upgrade instructions (v1.6.x to v1.7.0)**](#16x-170-instructions) - 1. Preliminary operations - 2. Replace files & test + 1. Pre-upgrade security audit + 2. Handle custom templates + 3. Replace files & run setup + 4. Post-upgrade hardening --- -## Upgrade information +## Breaking changes -Upgrade instructions for v1.7 will be published here once the release is available. Check the [changelog](/en/1.7/general/changelog) and [GitHub releases](https://github.com/InvoicePlane/InvoicePlane/releases) for the latest information. +### PDF template allow list (security fix) + +InvoicePlane 1.7 replaces dynamic template discovery with a static allow list to prevent Remote Code Execution. **Any custom PDF template that is not declared in `ipconfig.php` will no longer be available** after the upgrade. + +Before upgrading: +- List all custom template files in `application/views/invoice_templates/` and `application/views/quote_templates/` +- Decide whether to keep them in the application directory (add them to the built-in constant in `Mdl_templates.php`) or move them to an external folder (declare them in `ipconfig.php`) + +See [PDF Template Allow List](/en/1.7/templates/pdf-template-allowlist) for full configuration details. + +### PHP version + +InvoicePlane 1.7 requires **PHP 8.1 or higher**. PHP 8.2 and 8.3 are also supported and recommended. + +--- + +## New ipconfig.php settings + +Add the following options to your `ipconfig.php` after upgrading. None are required, but all are recommended. + +```ini +; --- Custom templates --- +; Path to a directory outside the web root containing custom PDF templates. +; Must include trailing slash. +CUSTOM_TEMPLATES_FOLDER=/srv/invoiceplane-templates/ + +; Comma-separated allow list of custom template names (no .php extension). +; Only names listed here will appear in the template selector. +CUSTOM_INVOICE_TEMPLATES_PDF=My Invoice,My Invoice - Detailed +CUSTOM_INVOICE_TEMPLATES_PUBLIC=My Invoice Web +CUSTOM_QUOTE_TEMPLATES_PDF=My Quote +CUSTOM_QUOTE_TEMPLATES_PUBLIC=My Quote Web + +; --- Security --- +; Strip EXIF metadata from uploaded images (default: false). +SEC_STRIP_EXIF_FROM_IMAGES=false + +; Password reset token lifetime in minutes (default: 15). +PASSWORD_RESET_TOKEN_EXPIRY_MINUTES=15 +``` + +--- ## Instructions to upgrade to 1.7.0 from 1.6.x -#### 1. Preliminary operations +#### 1. Pre-upgrade security audit + +Inspect your template directories for unexpected files before upgrading: + +```bash +find application/views/invoice_templates/ -name "*.php" | sort +find application/views/quote_templates/ -name "*.php" | sort +``` + +Expected built-in files: `InvoicePlane.php`, `InvoicePlane - paid.php`, `InvoicePlane_Web.php`. Any other PHP file is either a custom template (which you need to register) or an unexpected file that should be removed. + +Also verify the template values stored in the database: + +```sql +SELECT setting_key, setting_value +FROM ip_settings +WHERE setting_key IN ('default_invoice_template', 'default_quote_template', + 'public_invoice_template', 'public_quote_template'); +``` + +Expected values are `InvoicePlane`, `InvoicePlane - paid`, or `InvoicePlane_Web`. Unexpected values should be investigated before proceeding. + +#### 2. Handle custom templates + +If you have custom templates stored inside the application: + +**Option A — Declare them in `ipconfig.php` (recommended):** + +1. Create a folder outside your web root, e.g. `/srv/invoiceplane-templates/` +2. Copy your custom template files there, preserving the sub-directory structure (`invoice/pdf/`, `quote/pdf/`, etc.) +3. Add the settings to `ipconfig.php` as shown in [New ipconfig.php settings](#new-ipconfigphp-settings) above + +**Option B — Keep them in the application directory:** + +Add each custom template name to the `ALLOWED_INVOICE_TEMPLATES` or `ALLOWED_QUOTE_TEMPLATES` constant in `application/modules/invoices/models/Mdl_templates.php`. You must redeploy this file every time you upgrade. + +#### 3. Preliminary operations 1. Make a backup of your database and all files. (This is **very important** to prevent any data loss) 2. Download the latest version from [InvoicePlane.com](https://invoiceplane.com/downloads). -#### 2. Replace files & test +#### 4. Replace files & run setup 1. Copy all files to the root directory of your InvoicePlane installation but **do not** overwrite the following files: - The `ipconfig.php` file - - Customized templates in the `application/views/` folder + - Custom template files (if using Option B above) - The files for custom styles: `assets/core/css/custom.css` and `assets/core/css/custom-pdf.css` - - Uploaded images in the `uploads/` folder (e. g. your company logo) + - Uploaded images in the `uploads/` folder (e.g. your company logo) - Custom language keys at `application/language/COUNTRY/custom_lang.php` > **Note:** > - > **Hint:** An *easy* way of performing this operation is to upload the whole new InvoicePlane version in a different folder, outside of your current installation root folder, and copy the above mentioned files in the new folder you just uploaded. Afterwards just rename your current folder to something like `my_current_folder_old` and rename your new-version-folder with the name of `my_current_folder`. -2. Open `http://yourdomain.com/index.php/setup` and follow the instructions. The app will run all - updates on its own. - - If you encounter any errors when upgrading the table, press "Try Again" to resolve those errors and continue with the setup. -3. Now that the update is installed, moved and protected, it's time to log in and see if everything is working: login again and check if everything is working. + > An *easy* way of performing this operation is to upload the new InvoicePlane version in a separate folder, copy the above files into it, then swap the folder names. +2. Add the new `ipconfig.php` settings listed above. +3. Open `http://yourdomain.com/index.php/setup` and follow the instructions. The app will run all database migrations automatically. + - If you encounter any errors, press "Try Again" to resolve them and continue. +4. Log in and confirm the application works correctly, including template selection for invoices and quotes. + +#### 5. Post-upgrade hardening + +Set template directories to read-only so the web server cannot write new files there: + +```bash +chmod 555 application/views/invoice_templates/ +chmod 555 application/views/quote_templates/ +chmod 444 application/views/invoice_templates/*.php +chmod 444 application/views/quote_templates/*.php +``` + +If using `CUSTOM_TEMPLATES_FOLDER`, apply the same permissions to those directories. diff --git a/docs/en/1.7/index.md b/docs/en/1.7/index.md index 934e5a2..f44f63e 100644 --- a/docs/en/1.7/index.md +++ b/docs/en/1.7/index.md @@ -27,6 +27,7 @@ module. - [Invoices](/en/1.7/modules/invoices) - [Recurring Invoices](/en/1.7/modules/recurring-invoices) - [Payments](/en/1.7/modules/payments) +- [E-Invoicing](/en/1.7/modules/e-invoicing) ## Settings @@ -48,6 +49,7 @@ module. - [Using Templates](/en/1.7/templates/using-templates) - [Customize Templates](/en/1.7/templates/customize-templates) +- [PDF Template Allow List](/en/1.7/templates/pdf-template-allowlist) ## System diff --git a/docs/en/1.7/modules/e-invoicing.md b/docs/en/1.7/modules/e-invoicing.md new file mode 100644 index 0000000..f925d15 --- /dev/null +++ b/docs/en/1.7/modules/e-invoicing.md @@ -0,0 +1,112 @@ +# E-Invoicing + +InvoicePlane 1.7 includes a built-in e-invoicing system that can generate structured XML files alongside or embedded in PDF invoices. This meets legal e-invoicing requirements in a growing number of countries. + +## Supported Standards + +| Standard | Format | Usage | +|---|---|---| +| **Factur-X / ZUGFeRD** | CII XML embedded in PDF/A | France, Germany, and other EU countries | +| **UBL** (Universal Business Language) | Standalone XML | Pan-European, used in many Peppol networks | +| **CII** (Cross Industry Invoice) | Standalone XML | International, basis of EN 16931 | + +> **Note:** +> Peppol is a transport network, not a format. InvoicePlane generates the UBL or CII XML documents that Peppol networks carry. Submitting invoices to a Peppol access point requires a separate Peppol service provider that accepts your exported XML. + +## Requirements + +The following conditions must be met before e-invoicing can be used for a client: + +**Client record must have:** +- Company name +- Street address, postal code, city +- Country +- Tax identification number (VAT number) + +**Application settings:** +- The correct tax calculation mode must be configured (legacy calculation mode may be required for certain standards — see the configuration file for the specific XML template you are using) +- The client must have e-invoicing explicitly enabled on their client record + +## Enabling E-Invoicing for a Client + +1. Open the client record and navigate to the **E-Invoicing** section +2. Set **E-Invoicing active** to enabled +3. Select the e-invoicing standard from the **E-Invoicing version** dropdown — this list is populated from the available XML configuration files +4. Save the client record + +Once enabled, the next invoice generated for this client will include the XML output according to the selected standard. + +## Available XML Templates + +The e-invoicing system is built around pairs of files: + +| File | Location | Purpose | +|---|---|---| +| `[ShortID].php` | `application/helpers/XMLconfigs/` | Configuration — defines display name, country code, embed settings | +| `[ShortIDXml].php` | `application/libraries/XMLtemplates/` | Generator — produces the actual XML output | + +The dropdown in the client record shows the `full-name` value from each configuration file. The files shipped with InvoicePlane cover Factur-X/ZUGFeRD. Additional implementations for other countries are available in the [InvoicePlane e-invoices repository](https://github.com/InvoicePlane/InvoicePlane-e-invoices). + +## Adding a Custom XML Template + +To add support for a new e-invoicing format, create two files. + +### 1. Configuration file + +Create `application/helpers/XMLconfigs/MyFormatv10.php` (maximum 25 characters excluding extension, letters and numbers only): + +```php + 'My Country E-Invoice v1.0', + 'countrycode' => 'XX', + 'embedXML' => true, // embed XML inside the PDF + 'XMLname' => 'invoice.xml', // filename used when embedding +]; +``` + +Optional keys: + +| Key | Type | Description | +|---|---|---| +| `generator` | string | Use a different generator filename than the default | +| `options` | mixed | Pass extra variables or codes to the generator | +| `legacy_calculation` | bool | Force legacy tax/discount calculation mode | + +Dynamic filenames are supported using `{{{invoice_number}}}` as a placeholder in `XMLname`. + +### 2. Generator file + +Create `application/libraries/XMLtemplates/MyFormatv10Xml.php`. The generator class receives invoice data and must implement an `xml()` method returning the XML string. Use PHP's `DOMDocument` for building the output. See the existing Factur-X generator for a reference implementation. + +## Factur-X / ZUGFeRD + +Factur-X (France) and ZUGFeRD (Germany) are the same technical standard: a PDF/A-3 file with a CII XML attachment embedded in the PDF metadata. InvoicePlane handles the PDF/A compliance and RDF metadata automatically when `embedXML` is set to `true` in the configuration file. + +The embedded XML filename for Factur-X is conventionally `factur-x.xml`; for ZUGFeRD it is `ZUGFeRD-invoice.xml`. Set `XMLname` accordingly in your configuration file. + +## Peppol + +Peppol is a network infrastructure for exchanging e-invoices between businesses and governments across Europe and beyond. The Peppol network requires invoices in **Peppol BIS Billing 3.0** format, which is a UBL 2.1 profile. + +InvoicePlane can generate the UBL XML document. To send via Peppol you will additionally need: + +1. A **Peppol access point** — a certified service provider that connects your system to the Peppol network +2. A **Peppol participant ID** — registered for your company in the Peppol directory (SML/SMP) + +Contact a certified Peppol access point provider in your country to obtain these. Once you have them, export the UBL XML from InvoicePlane and submit it through your access point's API or upload interface. + +## Required Client Fields Checklist + +Before sending an e-invoice, confirm the following fields are filled in on the client record: + +- [ ] Company name +- [ ] Street address +- [ ] Postal / ZIP code +- [ ] City +- [ ] Country +- [ ] Tax ID / VAT number +- [ ] E-invoicing enabled (toggle on client record) +- [ ] E-invoicing version selected + +Missing required fields will prevent the XML from being generated. InvoicePlane displays a validation message listing which fields are absent. diff --git a/docs/en/1.7/modules/index.md b/docs/en/1.7/modules/index.md index 7ce2e28..f443683 100644 --- a/docs/en/1.7/modules/index.md +++ b/docs/en/1.7/modules/index.md @@ -1,7 +1,8 @@ # Modules - [Clients](/en/1.7/modules/clients) -- [Invoices](/en/1.7/modules/quotes) +- [Quotes](/en/1.7/modules/quotes) - [Invoices](/en/1.7/modules/invoices) - [Recurring Invoices](/en/1.7/modules/recurring-invoices) - [Payments](/en/1.7/modules/payments) +- [E-Invoicing](/en/1.7/modules/e-invoicing) diff --git a/docs/en/1.7/templates/index.md b/docs/en/1.7/templates/index.md index e40178a..8533880 100644 --- a/docs/en/1.7/templates/index.md +++ b/docs/en/1.7/templates/index.md @@ -2,3 +2,4 @@ - [Using Templates](/en/1.7/templates/using-templates) - [Customize Templates](/en/1.7/templates/customize-templates) +- [PDF Template Allow List](/en/1.7/templates/pdf-template-allowlist) diff --git a/docs/en/1.7/templates/pdf-template-allowlist.md b/docs/en/1.7/templates/pdf-template-allowlist.md new file mode 100644 index 0000000..a9ac18c --- /dev/null +++ b/docs/en/1.7/templates/pdf-template-allowlist.md @@ -0,0 +1,108 @@ +# PDF Template Allow List + +InvoicePlane 1.7 introduces a static allow list for PDF templates to prevent a critical Remote Code Execution (RCE) vulnerability. Only templates explicitly listed in the allow list will be loaded when generating PDF invoices and quotes. + +## Background + +Prior to 1.7, the system dynamically scanned the templates directory to build a list of available templates at runtime. This meant that any PHP file placed in the templates folder would automatically become available — and potentially executable — via the template selector. An attacker with admin access could exploit this to run arbitrary code. + +The fix replaces dynamic scanning with a two-tier static allow list: + +1. **Built-in templates** — hardcoded in the application source code (`Mdl_templates.php`) +2. **Custom templates** — declared explicitly in `ipconfig.php` + +## Built-in Templates + +The following templates are always available without any configuration: + +| Template name | Type | Format | +|---|---|---| +| `InvoicePlane` | Invoice & Quote | PDF | +| `InvoicePlane - paid` | Invoice | PDF | +| `InvoicePlane_Web` | Invoice & Quote | Public (HTML) | + +> **Note:** +> These names are case-sensitive. The template will not load if the name in the database does not match exactly. + +## Adding Custom Templates + +To add a custom template you must both place the file on disk **and** declare its name in `ipconfig.php`. A file that exists on disk but is not in the allow list will be silently ignored. + +### Step 1 — Place template files outside the web root + +Store custom templates in a directory that is **not** accessible over HTTP. Set the path in `ipconfig.php`: + +```ini +CUSTOM_TEMPLATES_FOLDER=/srv/invoiceplane-templates/ +``` + +The directory must contain the standard sub-structure: + +``` +/srv/invoiceplane-templates/ + invoice/ + pdf/ ← custom invoice PDF templates + public/ ← custom invoice HTML (public link) templates + quote/ + pdf/ ← custom quote PDF templates + public/ ← custom quote HTML (public link) templates +``` + +### Step 2 — Declare template names in the allow list + +Add only the names you want to allow. Names must consist of letters, numbers, spaces, hyphens, and underscores only — no path separators or file extensions. + +```ini +; Custom invoice templates +CUSTOM_INVOICE_TEMPLATES_PDF=My Invoice,My Invoice - Detailed +CUSTOM_INVOICE_TEMPLATES_PUBLIC=My Invoice Web + +; Custom quote templates +CUSTOM_QUOTE_TEMPLATES_PDF=My Quote +CUSTOM_QUOTE_TEMPLATES_PUBLIC=My Quote Web +``` + +Multiple names are separated by commas. Templates not listed here will not appear in the template selector and will not be loaded, even if the file exists. + +### Step 3 — Set restrictive file permissions + +Prevent the web server from writing to the template directories: + +```bash +chmod 555 /srv/invoiceplane-templates/invoice/pdf/ +chmod 555 /srv/invoiceplane-templates/quote/pdf/ +chmod 444 /srv/invoiceplane-templates/invoice/pdf/*.php +chmod 444 /srv/invoiceplane-templates/quote/pdf/*.php +``` + +## Security Validation + +When a template is requested, InvoicePlane applies the following checks in order: + +1. Reject empty or non-string values +2. Reject path traversal characters (`..`, `/`, `\`) +3. Validate the request type (`invoice` or `quote`) +4. Validate the scope (`pdf` or `public`) +5. Check the template name against the static allow list +6. Validate the character set (alphanumeric, spaces, hyphens, underscores) +7. Verify the file exists before loading it + +A template fails silently if it does not pass all seven checks. + +## Upgrading from 1.6 + +If you are upgrading from InvoicePlane 1.6 and have custom templates stored inside `application/views/`, you must move them and register them in `ipconfig.php` before the upgrade. + +Templates stored inside the application directory are **not** automatically trusted in 1.7. See [Updating InvoicePlane](/en/1.7/getting-started/updating-ip) for full upgrade steps. + +## Auditing Your Installation + +After upgrading, check the template directories for unexpected PHP files: + +```bash +find application/views/invoice_templates/ -name "*.php" | sort +find application/views/quote_templates/ -name "*.php" | sort +``` + +Expected files are: `InvoicePlane.php`, `InvoicePlane - paid.php`, `InvoicePlane_Web.php`. +Any other PHP file should be investigated and removed if not a legitimate custom template. From 13f03093aa83113864f04f4c0d304c84710d149a Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 02:40:11 +0000 Subject: [PATCH 06/13] Add comprehensive security documentation for all 26 vulnerabilities fixed in 1.7 docs/en/1.7/security/index.md (new): - Quick-reference table of all 26 fixes with severity, category, and action flag - Detailed write-up for each vulnerability: what was vulnerable, what changed, and what (if anything) the user needs to do - Covers every category: RCE (CVSS 9.9), arbitrary file deletion, XSS (32 locations across 17 files), IDOR/CSRF/SQL in guest payments, weak password reset PRNG, DDL injection, newline injection in setup, open redirect via HTTP_REFERER, log injection (SMTP + uploads), phpmail_send() breaking change, email template preview DOM-XSS, SSRF-adjacent path injection, Cryptor binary corruption, GitHub Actions token scope, SVG upload block, EXIF stripping, setup wizard lockdown, and six individual XSS fields - Full new ipconfig.php settings block as a reference docs/en/1.7/index.md: added Security section linking to the new page docs/en/1.7/getting-started/updating-ip.md: cross-reference note to security page Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01FyUdA46kyTUidfhs4sAEG7 --- docs/en/1.7/getting-started/updating-ip.md | 3 + docs/en/1.7/index.md | 4 + docs/en/1.7/security/index.md | 410 +++++++++++++++++++++ 3 files changed, 417 insertions(+) create mode 100644 docs/en/1.7/security/index.md diff --git a/docs/en/1.7/getting-started/updating-ip.md b/docs/en/1.7/getting-started/updating-ip.md index a903d74..4466123 100644 --- a/docs/en/1.7/getting-started/updating-ip.md +++ b/docs/en/1.7/getting-started/updating-ip.md @@ -14,6 +14,9 @@ ## Breaking changes +> **Note:** +> For a complete description of every security fix in 1.7, see [Security Changes in 1.7](/en/1.7/security). + ### PDF template allow list (security fix) InvoicePlane 1.7 replaces dynamic template discovery with a static allow list to prevent Remote Code Execution. **Any custom PDF template that is not declared in `ipconfig.php` will no longer be available** after the upgrade. diff --git a/docs/en/1.7/index.md b/docs/en/1.7/index.md index f44f63e..4c4cd04 100644 --- a/docs/en/1.7/index.md +++ b/docs/en/1.7/index.md @@ -51,6 +51,10 @@ module. - [Customize Templates](/en/1.7/templates/customize-templates) - [PDF Template Allow List](/en/1.7/templates/pdf-template-allowlist) +## Security + +- [Security Changes in 1.7](/en/1.7/security) + ## System - [Translation / Localization](/en/1.7/system/translation-localization) diff --git a/docs/en/1.7/security/index.md b/docs/en/1.7/security/index.md new file mode 100644 index 0000000..a3c69ba --- /dev/null +++ b/docs/en/1.7/security/index.md @@ -0,0 +1,410 @@ +# Security Changes in 1.7 + +InvoicePlane 1.7 addresses 26 security vulnerabilities across a wide range of categories. This page documents every change, what was vulnerable, what changed, and what — if anything — you need to do. + +## Quick reference + +| # | Severity | Category | What changed | Action required? | +|---|---|---|---|---| +| 1 | Critical | RCE | PDF template allow list replaces filesystem scanning | Yes — register custom templates | +| 2 | Critical | Auth | Password reset tokens now expire and use secure entropy | No | +| 3 | High | File | Arbitrary file deletion via path traversal in logo settings | No | +| 4 | High | XSS | 32 output locations across 17 view files hardened | No | +| 5 | High | Auth | Guest payment IDOR/CSRF/SQL hardened | No | +| 6 | High | Auth | Password reset PRNG replaced with `random_bytes(32)` | No | +| 7 | High | SQL | DDL injection in tax rate decimal settings | No | +| 8 | High | SQL | Newline injection in database setup | No | +| 9 | Medium | Redirect | Open redirect via unvalidated `HTTP_REFERER` | No | +| 10 | Medium | SQL | Guest payment query concatenation hardened | No | +| 11 | Medium | Input | AJAX filter `HTTP_REFERER` extraction unvalidated | No | +| 12 | Medium | Log | SMTP debug output log injection | No | +| 13 | Medium | Error | `phpmail_send()` always returned `true` | Yes — check custom integrations | +| 14 | Medium | XSS | Email template preview rendered live HTML | No | +| 15 | Medium | File | SSRF-adjacent path injection in PDF/XML generation | No | +| 16 | Low | Crypto | Binary data corruption in Cryptor class | No | +| 17 | Low | Config | GitHub Actions workflows had excessive token scope | No | +| 18 | Info | Upload | SVG logo uploads blocked | Yes — replace any SVG logos | +| 19 | Info | Upload | EXIF metadata stripping added (opt-in) | Optional | +| 20 | Info | Upload | File upload log poisoning via filename | No | +| 21 | Info | Setup | Setup wizard accessible after installation | No | +| 22 | Info | XSS | Invoice/quote number unescaped in payment form | No | +| 23 | Info | XSS | Tax rate name unescaped | No | +| 24 | Info | XSS | Payment method name unescaped | No | +| 25 | Info | XSS | Custom field values unescaped | No | +| 26 | Info | XSS | Family name unescaped in product forms | No | + +--- + +## Detailed documentation + +### 1. Remote Code Execution via dynamic template whitelist (Critical — CVSS 9.9) + +**CVE:** Pending +**CWE:** CWE-732, CWE-693, CWE-98 + +**What was vulnerable:** +The template system used `directory_map()` to scan the templates directory at runtime and build a whitelist of allowed template names from whatever files were present on disk. An administrator who could write a PHP file to the templates directory could make it automatically trusted, then set it as the active template in settings — causing arbitrary code to execute for every visitor who loads a public invoice URL. + +**What changed:** +`directory_map()` was removed entirely. The allowed template names are now hardcoded as static constants in `Mdl_templates.php`: + +- `ALLOWED_INVOICE_TEMPLATES` — built-in invoice templates +- `ALLOWED_QUOTE_TEMPLATES` — built-in quote templates + +Custom templates must be explicitly declared in `ipconfig.php` via the `CUSTOM_INVOICE_TEMPLATES_PDF`, `CUSTOM_INVOICE_TEMPLATES_PUBLIC`, `CUSTOM_QUOTE_TEMPLATES_PDF`, and `CUSTOM_QUOTE_TEMPLATES_PUBLIC` settings. + +**Action required:** Yes. Any custom PDF template not listed in `ipconfig.php` will stop working after upgrading. See [PDF Template Allow List](/en/1.7/templates/pdf-template-allowlist) for full configuration instructions. + +--- + +### 2. Password reset tokens never expired (Critical) + +**What was vulnerable:** +Password reset tokens had no expiry. A token sent to a user's email remained valid indefinitely, giving an attacker who gained access to an old email an unlimited window to reset the password. + +**What changed:** +- Tokens expire after a configurable period (default: 15 minutes). Expiry is tracked in the database and enforced on every use. +- The maximum allowed expiry is 24 hours. +- Rate limiting is applied: 5 attempts per IP per hour and 3 attempts per email address per hour. +- Timing-safe token comparison is used to prevent enumeration. + +**New `ipconfig.php` setting:** + +```ini +PASSWORD_RESET_TOKEN_EXPIRY_MINUTES=15 +``` + +**Action required:** None unless you need a longer window than 15 minutes. Add the setting to `ipconfig.php` to change it. + +--- + +### 3. Arbitrary file deletion via path traversal in logo settings (High — CVSS 7.1) + +**CWE:** CWE-22 + +**What was vulnerable:** +The logo filename was saved in the database without sanitization. When an administrator later removed the logo, the application called `unlink()` using the stored filename directly. By storing a value like `../../application/config/database.php`, an attacker with admin access could delete arbitrary files on the server. + +**What changed:** +- Logo filenames are now validated with `validate_safe_filename()` before being saved: path traversal sequences (`..`, `/`, `\`), null bytes, and absolute paths are all rejected. +- The `remove_logo()` function validates that the resolved file path is confined within the `/uploads/` directory using `realpath()` comparison before calling `unlink()`. +- Suspicious inputs are logged and the save operation is aborted. + +**Action required:** None. + +--- + +### 4. XSS across 32 output locations in 17 view files (High — CVSS 7.2–8.0) + +**CWE:** CWE-79 + +**What was vulnerable:** +Several view templates output user-supplied values directly into HTML without encoding. An administrator who entered a value like `` in a name field would cause that script to execute for any user who viewed a page containing that value. + +**Affected fields and locations:** + +| Field | Locations fixed | +|---|---| +| Invoice number | Payment form (2 instances) | +| Quote number | Quote views | +| Tax rate name | Tax rate table, settings form | +| Payment method name | Payment method list | +| Custom field values | Custom field forms and display | +| Family name | Product form dropdown, families table, product modal, product table, product lookups modal | +| Unit name | Unit list views | +| Client name in ZUGFeRD invoices | PDF generation | + +**What changed:** +All of these locations now wrap output in `htmlsc()` (returns encoded string) or `_htmlsc()` (echoes encoded string), both using `htmlspecialchars()` with `ENT_QUOTES | ENT_IGNORE`. In addition, a global `filter_input()` method in `Admin_Controller` strips HTML tags and runs CodeIgniter's `xss_clean()` on all POST data before it reaches any model or database call. + +**Action required:** None. Existing stored data is encoded at output time, so no data migration is needed. + +--- + +### 5. IDOR, CSRF, and SQL injection in guest payment controller (High) + +**What was vulnerable:** +The guest payment controller — which handles unauthenticated invoice payment flows — had three weaknesses: + +- **IDOR:** The invoice list query did not filter by client, so a guest user who guessed invoice IDs could access invoices belonging to other clients. +- **CSRF:** Payment form submissions were not protected by CSRF tokens. +- **SQL:** Invoice ID lists were assembled with `implode()` into raw WHERE clauses. + +**What changed:** +- The invoice query now filters with `where_in('ip_invoices.client_id', $this->user_clients)`, restricting results to the authenticated guest's clients only. +- CSRF token validation is enforced on all payment form submissions. +- All integer IDs are passed through `array_map('intval', ...)` before use in queries, and empty lists are checked before building WHERE clauses. + +**Action required:** None. + +--- + +### 6. Password reset token used weak random number generation (High) + +**What was vulnerable:** +The previous token was generated with a pattern equivalent to `md5(time() + $email + mt_rand())`. `mt_rand()` is not cryptographically secure and `time()` is predictable, making the token guessable given enough attempts. + +**What changed:** +Token generation was replaced with `generate_secure_token()` in `ip_security_helper.php`, which calls `random_bytes(32)` to produce 256 bits of cryptographically secure entropy, returned as a 64-character hex string. + +**Action required:** None. + +--- + +### 7. DDL injection in tax rate decimal settings (High) + +**What was vulnerable:** +The tax rate decimal precision setting was used directly in a `DECIMAL(x, y)` column definition without validation. An attacker with admin access could inject SQL DDL syntax by entering unexpected values in the decimal places field. + +**What changed:** +The decimal places value is now validated to be an integer within the allowed range (2–3 decimal places) before it is used in any schema-modifying query. + +**Action required:** None. + +--- + +### 8. Newline injection in database setup (High) + +**What was vulnerable:** +During the initial setup wizard, database credentials entered by the user were written to `ipconfig.php`. Values containing newline characters (`\n`, `\r\n`) could inject additional configuration lines into the file, potentially overriding settings. + +**What changed:** +All values written to `ipconfig.php` during setup are now stripped of newline and carriage-return characters before being written. + +**Action required:** None for existing installations (setup completes once; the wizard is locked afterwards — see [#21](#21-setup-wizard-accessible-after-installation-info)). + +--- + +### 9. Open redirect via unvalidated `HTTP_REFERER` (Medium — CVSS 6.1) + +**CWE:** CWE-601 + +**What was vulnerable:** +Several controllers used `redirect($_SERVER['HTTP_REFERER'])` directly to send users back to the previous page after an action. The `Referer` header is fully controlled by the browser or the requesting party. An attacker could craft a link that, when clicked by a logged-in user, redirected them to an external phishing site after the action completed. Affected areas included payment processing, custom fields, and filter modules. + +**What changed:** +A new `get_safe_referer()` function in `security_helper.php` validates that the referer URL belongs to the application's own domain before using it. External URLs are silently discarded and the application falls back to a safe internal URL. + +**Action required:** None. + +--- + +### 10. Guest payment SQL query concatenation (Medium — CVSS 6.5) + +**CWE:** CWE-89 + +**What was vulnerable:** +The guest payment module built WHERE clauses by concatenating an `implode()` of an ID array into a raw SQL string. While the immediate inputs happened to be safe at the time, this pattern would become an injection vector if the data source ever changed. + +**What changed:** +All ID values are now cast with `array_map('intval', $ids)` before use, and empty arrays are caught before a WHERE clause is constructed. + +**Action required:** None. + +--- + +### 11. AJAX filter extracted values from `HTTP_REFERER` without validation (Medium — CVSS 5.3) + +**CWE:** CWE-20 + +**What was vulnerable:** +AJAX filter controllers in `filter/controllers/Ajax.php` extracted table names and record IDs directly from the `HTTP_REFERER` header using `basename()`. While `basename()` prevented path traversal, the extracted values were used without further validation. + +**What changed:** +- Table names are now validated against a regex that allows only alphanumeric characters and underscores. +- Record IDs are explicitly cast to `int`. + +**Action required:** None. + +--- + +### 12. SMTP debug output written to logs without sanitization (Medium) + +**CWE:** CWE-117 (Log Injection) + +**What was vulnerable:** +PHPMailer's SMTP debug callback wrote server responses verbatim to the application log. A malicious SMTP server could inject fake log entries by including newline characters and log-format strings in its responses. + +**What changed:** +All SMTP debug output now passes through `sanitize_for_logging()` before being written, which strips control characters including newlines and carriage returns. + +**Action required:** None. + +--- + +### 13. `phpmail_send()` always returned `true` (Medium — breaking change) + +**CWE:** CWE-252 (Unchecked Return Value) + +**What was vulnerable:** +The `phpmail_send()` helper function returned `true` regardless of whether the email was actually delivered, masking delivery failures from callers. + +**What changed:** +The function now returns the actual boolean result from the underlying PHPMailer send call: `true` on success, `false` on failure. + +**Action required:** If you have custom code or integrations that call `phpmail_send()` and assume it always succeeds, update that code to check the return value and handle `false` as a failure. + +--- + +### 14. Email template preview rendered live HTML (Medium) + +**What was vulnerable:** +The email template preview rendered the template's HTML content directly in the browser, including any JavaScript embedded in the template. An administrator who had stored a malicious `` in a name field would cause that script to execute for any user who viewed a page containing that value. - -**Affected fields and locations:** - -| Field | Locations fixed | -|---|---| -| Invoice number | Payment form (2 instances) | -| Quote number | Quote views | -| Tax rate name | Tax rate table, settings form | -| Payment method name | Payment method list | -| Custom field values | Custom field forms and display | -| Family name | Product form dropdown, families table, product modal, product table, product lookups modal | -| Unit name | Unit list views | -| Client name in ZUGFeRD invoices | PDF generation | - -**What changed:** -All of these locations now wrap output in `htmlsc()` (returns encoded string) or `_htmlsc()` (echoes encoded string), both using `htmlspecialchars()` with `ENT_QUOTES | ENT_IGNORE`. In addition, a global `filter_input()` method in `Admin_Controller` strips HTML tags and runs CodeIgniter's `xss_clean()` on all POST data before it reaches any model or database call. - -**Action required:** None. Existing stored data is encoded at output time, so no data migration is needed. - ---- - -### 5. IDOR, CSRF, and SQL injection in guest payment controller (High) - -**What was vulnerable:** -The guest payment controller — which handles unauthenticated invoice payment flows — had three weaknesses: - -- **IDOR:** The invoice list query did not filter by client, so a guest user who guessed invoice IDs could access invoices belonging to other clients. -- **CSRF:** Payment form submissions were not protected by CSRF tokens. -- **SQL:** Invoice ID lists were assembled with `implode()` into raw WHERE clauses. - -**What changed:** -- The invoice query now filters with `where_in('ip_invoices.client_id', $this->user_clients)`, restricting results to the authenticated guest's clients only. -- CSRF token validation is enforced on all payment form submissions. -- All integer IDs are passed through `array_map('intval', ...)` before use in queries, and empty lists are checked before building WHERE clauses. - -**Action required:** None. - ---- - -### 6. Password reset token used weak random number generation (High) - -**What was vulnerable:** -The previous token was generated with a pattern equivalent to `md5(time() + $email + mt_rand())`. `mt_rand()` is not cryptographically secure and `time()` is predictable, making the token guessable given enough attempts. - -**What changed:** -Token generation was replaced with `generate_secure_token()` in `ip_security_helper.php`, which calls `random_bytes(32)` to produce 256 bits of cryptographically secure entropy, returned as a 64-character hex string. - -**Action required:** None. - ---- - -### 7. DDL injection in tax rate decimal settings (High) - -**What was vulnerable:** -The tax rate decimal precision setting was used directly in a `DECIMAL(x, y)` column definition without validation. An attacker with admin access could inject SQL DDL syntax by entering unexpected values in the decimal places field. - -**What changed:** -The decimal places value is now validated to be an integer within the allowed range (2–3 decimal places) before it is used in any schema-modifying query. - -**Action required:** None. - ---- - -### 8. Newline injection in database setup (High) - -**What was vulnerable:** -During the initial setup wizard, database credentials entered by the user were written to `ipconfig.php`. Values containing newline characters (`\n`, `\r\n`) could inject additional configuration lines into the file, potentially overriding settings. - -**What changed:** -All values written to `ipconfig.php` during setup are now stripped of newline and carriage-return characters before being written. - -**Action required:** None for existing installations (setup completes once; the wizard is locked afterwards — see [#21](#21-setup-wizard-accessible-after-installation-info)). - ---- - -### 9. Open redirect via unvalidated `HTTP_REFERER` (Medium — CVSS 6.1) - -**CWE:** CWE-601 - -**What was vulnerable:** -Several controllers used `redirect($_SERVER['HTTP_REFERER'])` directly to send users back to the previous page after an action. The `Referer` header is fully controlled by the browser or the requesting party. An attacker could craft a link that, when clicked by a logged-in user, redirected them to an external phishing site after the action completed. Affected areas included payment processing, custom fields, and filter modules. - -**What changed:** -A new `get_safe_referer()` function in `security_helper.php` validates that the referer URL belongs to the application's own domain before using it. External URLs are silently discarded and the application falls back to a safe internal URL. - -**Action required:** None. - ---- - -### 10. Guest payment SQL query concatenation (Medium — CVSS 6.5) - -**CWE:** CWE-89 - -**What was vulnerable:** -The guest payment module built WHERE clauses by concatenating an `implode()` of an ID array into a raw SQL string. While the immediate inputs happened to be safe at the time, this pattern would become an injection vector if the data source ever changed. - -**What changed:** -All ID values are now cast with `array_map('intval', $ids)` before use, and empty arrays are caught before a WHERE clause is constructed. - -**Action required:** None. - ---- - -### 11. AJAX filter extracted values from `HTTP_REFERER` without validation (Medium — CVSS 5.3) - -**CWE:** CWE-20 - -**What was vulnerable:** -AJAX filter controllers in `filter/controllers/Ajax.php` extracted table names and record IDs directly from the `HTTP_REFERER` header using `basename()`. While `basename()` prevented path traversal, the extracted values were used without further validation. - -**What changed:** -- Table names are now validated against a regex that allows only alphanumeric characters and underscores. -- Record IDs are explicitly cast to `int`. - -**Action required:** None. - ---- - -### 12. SMTP debug output written to logs without sanitization (Medium) - -**CWE:** CWE-117 (Log Injection) - -**What was vulnerable:** -PHPMailer's SMTP debug callback wrote server responses verbatim to the application log. A malicious SMTP server could inject fake log entries by including newline characters and log-format strings in its responses. - -**What changed:** -All SMTP debug output now passes through `sanitize_for_logging()` before being written, which strips control characters including newlines and carriage returns. - -**Action required:** None. - ---- - -### 13. `phpmail_send()` always returned `true` (Medium — breaking change) - -**CWE:** CWE-252 (Unchecked Return Value) - -**What was vulnerable:** -The `phpmail_send()` helper function returned `true` regardless of whether the email was actually delivered, masking delivery failures from callers. - -**What changed:** -The function now returns the actual boolean result from the underlying PHPMailer send call: `true` on success, `false` on failure. - -**Action required:** If you have custom code or integrations that call `phpmail_send()` and assume it always succeeds, update that code to check the return value and handle `false` as a failure. - ---- - -### 14. Email template preview rendered live HTML (Medium) - -**What was vulnerable:** -The email template preview rendered the template's HTML content directly in the browser, including any JavaScript embedded in the template. An administrator who had stored a malicious `