Skip to content

[IP-939]: Processing e-invoices flow (and some bugfixes): development branch for version 1.6.3#1247

Merged
nielsdrost7 merged 256 commits intodevelopmentfrom
development-v163
May 19, 2025
Merged

[IP-939]: Processing e-invoices flow (and some bugfixes): development branch for version 1.6.3#1247
nielsdrost7 merged 256 commits intodevelopmentfrom
development-v163

Conversation

@nielsdrost7
Copy link
Copy Markdown
Contributor

@nielsdrost7 nielsdrost7 commented Mar 30, 2025

How to Test:

I would create the client and invoice in the original 1.6.2 version (or the development branch), so you can test the entire flow

  • You'll need a Client

  • You'll need an Invoice for that Client

  • Open the Client
    Scenario's:
    A. You don't want an e-invoice

    • Everything should stay the same and an Invoice PDF should be generated
      B. You want an e-invoice (UblExam20)
    • Start e-invoicing should be set to "Yes", a check will be made if the "User" and the "Client" match the requirements (are all fields filled)
    • UBL / CII version should be set to "UBL example v2.0 - Germany"
    • Fill the missing fields, it will show in a convenient table
    • Create an Invoice PDF
    • Since you choose UBL 2.0 an Invoice with XML should be generated
    • If you don't see the XML right away, just re-open that PDF file
      image
      C. You want an e-invoice (Zugferd v1.0 - Germany)
    • Create an Invoice PDF
    • Since you choose Zugferd v1.0 - Germany an Invoice with XML should be generated
    • If you don't see the XML right away, just re-open that PDF file
    • The XML file should be Zugferd 1.0 compliant

Description

With these "e-invoicing adjustments" the user has the possibility to receive the desired e-invoice XML file at the request of his customer.
For the user it is sufficient to create the correct xml template file and the associated xml configuration file and add them to their provided directory.

Related Issue

Feature Request #939 "Implement e-invoicing for UBL/CII formats (EN 16931, Zugferd/Factur-X, PEPPOL, etc...) other than only Zugferd"
See my comments in Feature Request 939.

Motivation and Context

Worldwide, and certainly in Europe, governments, clients and accountants are switching to electronic invoices.
e-Invoices can be used to process these documents machine readable and automatically.
XML templates can be created specifically for a country or client.
How to add an XML template is described in the "About e-Invoicing templates.md" file located in the "helpers/XMLconfigs/" folder.
I have added 2 XML template example files.
The (old) IP Zugferdv10Xml.php file serves as "CII format" example and the Ublexamv20Xml.php file serves as "UBL format" example.

  • A UBL e-invoicing rule expects that the pdf invoice file name and the m2m (XML) file name are the same. Via System-settings invoices the user can change the current default file name to (companyname), (username) or (vat_id) + _invoicegroup. See screenshot 1.
  • In the customer status table the fields e-invoicing version and e-invoicing were actively added. See screenshot 2.
  • In the customer detail page and in the customer change form page an e-invoicing info panel was added. See screenshot 3. + 4.
  • In various places it is checked whether the additional related standard mandatory e-invoicing fields (address, company or VAT ID) are empty. See screenshot 3. + 4.

Screenshots (if appropriate):

  1. System - Settings - Invoices:
    image

  2. Client status table:
    image

  3. Client view Details page:
    image

  4. Client form e-invoicing (template) selection and empty fields check:
    image

Pull Request Checklist

  • My code follows the code formatting guidelines.
  • I have an issue ID for this pull request.
  • I selected the corresponding branch.
  • I have rebased my changes on top of the corresponding branch.

Issue Type (Please check one or more)

#939

  • Bugfix
  • Improvement of an existing Feature
  • New Feature

nielsdrost7 and others added 30 commits January 19, 2025 11:12
Discounts factur-x with or without vat fully validated
- `TAXES_AFTER_DISCOUNTS=false` (ip_config.php)

- Change `get_invoice_discount_percent()` to get % vat rate(s)
- - it's valid but bad value
- Global Discount move after/before taxes
- - in function of config_item('taxes_after_discounts')
- - - in views (quotes & invoices) & pdf templates

- get by `config_item('taxes_after_discounts')`
- - is set to true in ip_config example (Origin calculation)
Admin GUI
+ invoices/views/partial_itemlist_table
+ quotes/views/partial_itemlist_table
+ + Removed old thead's (display none)
+ invoices/views/partial_itemlist_responsive
+ quotes/views/partial_itemlist_responsive

6 New files:
+ invoices/views/partial_itemlist_table_invoice_discount.php
+ quotes/views/partial_itemlist_table_invoice_discount.php
Called in amount total table (same 4 table & responsive mode)

+ layout/views/partial/itemlist_table_item_discount_show.php
+ layout/views/partial/itemlist_table_item_discount_input.php
+ layout/views/partial/itemlist_responsive_item_discount_show.php
+ layout/views/partial/itemlist_responsive_item_discount_input.php
Called in quotes|invoices itemlist (One for new and edit)

Public GUI (refactored)
+ application/views/invoice_templates/public/InvoicePlane_Web.php
+ application/views/quote_templates/public/InvoicePlane_Web.php

Typos:
+ Indents tab2spaces

Bugfixes
+ Fixed: VAT selector value on left (new item line : quote & invoice)
+ + Cause: missing `class="td-amount"` in parent td (table template)
+ Fixed: Currency symbol inside item quote price input field (#1212)
+ Fixed: Item lines, total quote not same as invoice
+ + Cause: $item->item_total (with taxe)
+ + Fix  : $item->item_subtotal (without taxe)
+ + in: application/view/quote_templates/public/InvoicePlane_Web.php

Improve
+ get config in (Q&I) `partial_itemlist_table` (like responsive)
+ + Same in other partial's
+ guest/views/quote_view.php Item line: discount to item_discount
+ Inputs Price & Discount \w currency by helper (like responsive)
Invoices & Quotes pdf templates:

app /views/invoice_templates/pdf/InvoicePlane.php (refactorised)
Now InvoicePlane - [overdue | paid].php include InvoicePlane.php

app /views/quote_templates/pdf/InvoicePlane.php (refactorised)

New helper discount_global_print_in_pdf() (see pdf_helper)

Remove no needed `htmlsc`

---

Fixes

+ Label removed & replaced by aria-label in input (Fix bad fix)
+ + [partial_itemlist_table[quot|invoic]e_discount access lint
fix](d04a3ea)

+ Missing $item on add new item (oups, never dev on prod mode)
+ + in app mod layout itemlist_responsive_item_discount_input.php

+ Double invoice discount line (same): missing one `!` (line 202)
+ + in app /views/invoice_templates/public/InvoicePlane_web.php

+ SepaQr\Exceptions (and pdf not generated). See #1214
+ + Amount of the credit transfer cannot be smaller than 0.01 Euro
+ + Amount of the credit transfer cannot be higher than 999999999.99

+ Item table head duplicated when 9 to 13 items (bad head in 2nd page)
+ + in app /views/(quote|invoice)_templates/pdf/InvoicePlane.php
+ + + Possibility to return same as previous
+ + + just set `$add_table_and_head_for_sums` to 0/false

+ PDF Watermark AND XRechnung (ZUGFeRD XML) (issue #912)

Note PDF Watermark:
Watermark in eInvoicing aro not allowed by Mpdf\MpdfException
Message:
PDFA and PDFX do not permit transparency, so mPDF does not allow
Watermarks!
Fixed in mpdf_helper line 102:
From
`if (get_setting('pdf_watermark'))`
To
`if ( ! $embed_xml && get_setting('pdf_watermark'))`

---

Improved Style

+ New stamp system (by css) for pdf & public view (now are translated)

+ New files in assets/core/scss (DRY principle)
+ + _template.scss (imported in ip[_blue]/template.scss)
+ + _stamp.scss (imported in template.scss & in ip[_blue]/style.scss)

+ + Note: Need to rebuild css files with `yarn build sass` command

+ + Todo: Apply to [InvoicePlane-Themes
v1](https://github.com/InvoicePlane/InvoicePlane-Themes/tree/development/v1)

---

Improved

+ module
+ + guest controler View
+ + invoices controler Invoices
+ + quotes controler Quotes
+ + + Linter ( + tab2spaces)
+ + + & add taxes_after_discounts
+ + + + to remove
```
$taxes_after_discounts = config_item('taxes_after_discounts');
```
+ + + + in view's (DRY)

---

Idea: Display taxes columns/cell in view & pdf (like admin view)
How: Add `show_taxes` in controllers like this commit
+ Note: maybe check with percent is best (in case of total == 0)
+ + (Copied from InvoicePlane_Web templates)
Sample:
```
'show_taxes' =>
$this->invoice_tax_total + $this->invoice_item_tax_total != 0; #Inv.
$this->quote_tax_total + $this->quote_item_tax_total != 0; #Quote
```
+ Typo ($filname)

+ For Subject to VAT SpecifiedTaxRegistration 'VA' (vat_id)
+ + not called if all items 100% discount (make taxes = 0)

+ DivisionByZeroError break pdf generation
+ + In `get_invoice_discount_percent()`
+ + Now return percent = '0.01'; // fix by faker (wip)
+ + + See Todo (below)

---

Improve:

+ Not subject to VAT
+ + `invoice_tax_total` 2 `invoice_item_tax_total`
+ + `invoice_total` 2 `invoice_item_subtotal`

---

Todo (idea, wip):

+ Transform get_invoice_discount_percent() to helper
+ + for get/dispatch discount percent vat's rate (of invoice)
+ + to remove `fix by faker (wip)`
Return to item subtotal = quantity * price

Calculate item discount on item subtotal

Calculate global (Q&I) discount on item subtotal

All taxes calculation with item subtotal discounted (wip)

global (Q&I) discount dispatched Proportionally by item
And not apply in Mdl_invoice_amount->calculate_discount()

In mdl tax rate (invoice) removed:
$this->mdl_invoice_amounts->calculate_invoice_taxes($invoice_id);
It Called in calculate (in test, same as quote. Maybe old)

Fix missing currency_symbol on price (Add new item)
In partial_itemlist_table (quote & invoice)
Fix currencyElement function's
• In formattedFloat: (function's renamed)
•• PHP number_format add `,` of thousand separator by default
• Fix cvc-datatype-valid.1.2.1:
•• '1,000.00' is not a valid value for 'decimal'

formattedDate function's renamed

Removed
• old file helpers/zugferd_helper.php (unused)
• bad example file helpers/XMLconfig/Zugferdv23g.php
Best reflect of taxes applied after discounts
wip need to correct me
Refacto guest & partial itemlist(s)
+ Add tooltips to explain's Discount Calculation (admin & guest)

Vars in ip_lang.php (2)
+ global_discount
+ no_open_invoices

Fixes
+ Missing Quote $item->item_tax_rate_name
+ + in default_select() of quotes/models/Mdl_quote_item.php
+ Guest `See pdf` on same tab/window (missing target="_blank")
+ Guest invoice view page never show `Pay now` button
+ Guest invoices view page `Pay now` buttons go to 404 (old url)
+ + in guest/views/invoices_index
+ + OLD: guest/payment_handler/make_payment/#invoice_url_key#
+ + NEW: guest/payment_information/form/#invoice_url_key#

Improve
+ Add filter `Overdue` & `All` (guest/invoices/status/***)
+ + in guest/ views/invoices_index & controllers/invoices
+ Add filter `Viewed` & `All` (guest/quotes/status/***)
+ + in guest/ views/quotes_index & controllers/quotes
If taxes applied after discounts, items_subtotal need to be real
(without item discount applied) to dispatch good discount amount

Global discount (amount) = 1

Before
Items Prices IDiscount GDiscount Total
1     10     1         0.56      8.44
1     10     1         0.56      8.44
                       1.12      16.88

Now (Fixed & Expected)
Items Prices IDiscount GDiscount Total
1     10     1         0.50      8.50
1     10     1         0.50      8.50
                       1         17.00
floatval(100.000,00) become 100 but expected 100000
Need `standardize_amount`
Mdl_invoices: copy_invoice, copy_credit_invoice
Mdl_quote   : copy_quote
Mdl_payments: save
Removed last invoice amounts calculate. Why? it's a copy & sended

Fix missing 'wrong_cron_key_provided' in ip_lang
Sometime global discount total (calculated) differ of user value
Need little adjust to be valid in ZugFerd standard (maybe cents)

Like discount = 100 / 6 items (with same subtotal) = 16.66666...
But the around = 16.67
and 16.67 x 6 = 100.02 Not 100.00 (and this isn't valid)

Only if in ipconfig.php `LEGACY_CALCULATION = false`
Like custom_title = '' in db & $default is 'InvoicePlane'
Return '' but 'InvoicePlane' is expected

Because Mdl_settings->setting() default fallback not returned

Now, if in db = '' return $default & if $default = '' return ''

Nothing change for other types like int, float & null
@sudwebdesign
Copy link
Copy Markdown
Collaborator

Some fixes are applied & reviewed.

```
Message: Class "FPDI" not found

Filename: application/helpers/pdf_helper.php Line Number: 218

Backtrace:

File: application/modules/invoices/controllers/Invoices.php Line: 306
Function: generate_invoice_sumex
```
**Be careful**:
Show sumex settings panel when 'sumex' != 0 in db before this.
If set sumex to No. After save settings, the panel never show.

Todo:
Improve lib like eInvoice | Remove it if unused by anyone.

**Need Sumex?** (& Settings panel):
- Set SUMEX_SETTINGS=true in ipconfig.php
- Improve and/or finish libraries/Sumex.php
- Add invoice_template/(pdf&public) to be same as
https://cloud.githubusercontent.com/assets/4939519/23583357/a5b28e06-0142-11e7-9273-4d63b38eb422.png
- - Note: Replace $item->item_description by $item->item_date

---

Initiated by @denysvitali on #453 & (IMHO) never finished
See #453
To reproduce:
Click on `add products` btn, select one(s) & sumbit or cancel or X
Make Ctrl+s, don't save invoice
- If previously item(s) select, make Ctrl+s add item(s) line
- If previously nothing selected, make Ctrl+s do nothing

Explanation:
The modal is present in DOM but not displayed
Imp: Only post to server if item exist on db (& Fix 403)
Fix: Delete item not call check_items_tax_usages
Add edit links
Some idents
Sumex:
- OFF (hide missing)
- dashboard link lang
@sudwebdesign
Copy link
Copy Markdown
Collaborator

sudwebdesign commented May 16, 2025

@nielsdrost7 all seem run fine in this branch now (I hesitate to click on Ready for review)

Think yarn build if debug false.


Some fixes & improvements are applied & reviewed.


* Now the sumex invoice view and PDF generator work but is hidden by default.
Because I've doubt of sumex invoices usage (view braked on 2020) see : 7f9a6ac and (IMHO) this feature not finished by @denysvitali (numerous todo's in sumex library) Begin at #453 on v1.5.0

... Once everything is properly setup SUMEX_URL= in ipconfig.php ...

Now Set SUMEX_SETTINGS=true in ipconfig.php if need & if SUMEX_URL not set IP use internal lib to generate PDF (but need to use $item->item_date instead of $item->item_description and need a new template to look like this to be fully finish.

@nielsdrost7
Copy link
Copy Markdown
Contributor Author

all seem run fine in this branch now (I hesitate to click on Ready for review)

I'll make the .zip, I'll let you know

@xam-ps
Copy link
Copy Markdown
Collaborator

xam-ps commented May 17, 2025

You prepare a RC? I can test next week again :)

@nielsdrost7
Copy link
Copy Markdown
Contributor Author

I'll name it an RC if we can agree on skipping the Beta phase.
@sudwebdesign RC or Beta, what do you think?

@xam-ps
Copy link
Copy Markdown
Collaborator

xam-ps commented May 17, 2025

Ah, or beta. It's fine for me as well of course:)

** Now you can leave empty the custom client title field **

Fixes:
- tryFrom: strict compare: array_search return 0 (key) for 'mr' opt.

- When choose the "Custom" title option in selector and
save with client_title_custom with empty value.
The client_title is set to `custom` by default in db
@sudwebdesign
Copy link
Copy Markdown
Collaborator

RC or Beta, what do you think?

@nielsdrost7 I think RC0 after the last commit to make custom client title as optional. I thought it would be better for those who have no use for it (and those migrating from version 1.5x).

Prevent (and simplify) InvoicePlane update usage
When `LEGACY_CALCULATION` option not (added manually) in ipconfig
The `legacy_calculation` is false & hide `Add global taxes` menu
@sudwebdesign
Copy link
Copy Markdown
Collaborator

IMHO all seems good for RC after some little retails:

@nielsdrost7
Copy link
Copy Markdown
Contributor Author

IMHO all seems good for RC

Ok, I'll try to make a .zip today.
It means this P is going to be merged.

If you find new things in the PR, you'll open up a new PR, right?

@nielsdrost7 nielsdrost7 marked this pull request as ready for review May 19, 2025 05:31
@nielsdrost7 nielsdrost7 merged commit 9553037 into development May 19, 2025
1 check was pending
nielsdrost7 added a commit that referenced this pull request May 19, 2025
* Setup upgrade 1.6.3: Set all langs to lowercase

Why? see
#1230 (comment)

* Fix IP search bad user_language file on login (after setup)

Get an error like:
Unable to load the requested language file: language/French/ip_lang.php

Reason:
When user are logged in before call & complete setup,
On next login, session return old params.

Need destroy session to be set by new params from database
(Here for langs)

* [IP-939]: Processing e-invoices flow (and some bugfixes): `development` branch for version 1.6.3 (#1247)

Prepare for 1.6.3 and 1.7.0

---------

Co-authored-by: Thomas Ingles <thomas@sudwebdesign.fr>

---------

Co-authored-by: Niels Drost <47660417+nielsdrost7@users.noreply.github.com>
nielsdrost7 added a commit that referenced this pull request Aug 6, 2025
## Version 1.6.3 (final)

### Major Features & E-Invoicing

* [[IP-1268](#1268)] **E-invoicing infrastructure update** by @sudwebdesign
* [[IP-1272](#1272)] **E-invoicing enhancements** by @sudwebdesign
* [[IP-1247](#1247)] Processing e-invoices flow (and some bugfixes) for version 1.6.3 by @nielsdrost7
* [[IP-1282](#1282)] feat: Legacy calculation setup step by @pumpi
* [[IP-1281](#1281)] fix: Client overview shows wrong e-Invoicing state by @pumpi

### Changed / Improvements

* [[IP-1277](#1277)] Replace node-sass with sass by @onny
* [[IP-1261](#1261)] Guest Payment stripe flow & online_payment lang improved by @nielsdrost7
* [[IP-1178](#1178)] Add custom_fields in controllers/Settings by @sudwebdesign
* [[IP-1206](#1206)] Add report: Invoices per client by @mheiduk
* [[IP-1228](#1228)] Improve number_helper & standardize_amount (fix european format) by @sudwebdesign
* [[IP-1229](#1229)] Remove unattended standardize_amount in payments view form by @sudwebdesign
* [[IP-1241](#1241)] Add pagination to invoice and quote templates by @onny
* [[IP-1219](#1219)] Sort invoices by date instead of id by @MrKrisKrisu
* [[IP-1222](#1222)] Sort quotes by date instead of id by @sudwebdesign

### Fixed

* [[IP-1179](#1179)] Fix #fullpage-loader (Spinner) never showed after save by @sudwebdesign
* [[IP-1174](#1174)] Removed '.pdf' from Invoices.php downloads to fix issue by @HeapReaper
* [[IP-1175](#1175)] Check invoice balance before rendering QR code in web view by @idressos
* [[IP-1183](#1183)] Fix summary client delete button go to 404 (link2form) by @sudwebdesign
* [[IP-1185](#1185)] Fix styling in clients table header by @tstoeter
* [[IP-1186](#1186)] Style2class for amounts & balances (th & tr) by @sudwebdesign
* [[IP-1197](#1197)] Send email show blank page (php>=8.2) by @sudwebdesign
* [[IP-1199](#1199)] Add invoice_status case in template_helper by @sudwebdesign
* [[IP-1201](#1201)] Fix SMTP password wrong after saving settings by @sudwebdesign
* [[IP-1204](#1204)] Update template_helper.php to fix email template with custom single choice field by @LOK-Soft
* [[IP-1251](#1251)] fix: amount of the credit transfer cannot be smaller than 0.01 Euro by @mheiduk
* [[IP-1278](#1278)] Fix: Styling issues by @pumpi
* [[IP-1283](#1283)] fix: Client detail view exception by 

**Full Changelog**: v1.6.2...v1.6.3
nielsdrost7 added a commit that referenced this pull request Aug 6, 2025
### What's Changed (since v1.6.2)

#### Major Features & E-Invoicing

* [[IP-1268](#1268)] **E-invoicing infrastructure update** by @sudwebdesign
* [[IP-1272](#1272)] **E-invoicing enhancements** by @sudwebdesign
* [[IP-1247](#1247)] Processing e-invoices flow (and some bugfixes) for version 1.6.3 by @nielsdrost7
* [[IP-1282](#1282)] feat: Legacy calculation setup step by @pumpi
* [[IP-1281](#1281)] fix: Client overview shows wrong e-Invoicing state by @pumpi

#### Changed / Improvements

* [[IP-1277](#1277)] Replace node-sass with sass by @onny
* [[IP-1261](#1261)] Guest Payment stripe flow & online_payment lang improved by @nielsdrost7
* [[IP-1178](#1178)] Add custom_fields in controllers/Settings by @sudwebdesign
* [[IP-1206](#1206)] Add report: Invoices per client by @mheiduk
* [[IP-1228](#1228)] Improve number_helper & standardize_amount (fix european format) by @sudwebdesign
* [[IP-1229](#1229)] Remove unattended standardize_amount in payments view form by @sudwebdesign
* [[IP-1241](#1241)] Add pagination to invoice and quote templates by @onny
* [[IP-1219](#1219)] Sort invoices by date instead of id by @MrKrisKrisu
* [[IP-1222](#1222)] Sort quotes by date instead of id by @sudwebdesign

#### Fixed

* [[IP-1179](#1179)] Fix #fullpage-loader (Spinner) never showed after save by @sudwebdesign
* [[IP-1174](#1174)] Removed '.pdf' from Invoices.php downloads to fix issue by @HeapReaper
* [[IP-1175](#1175)] Check invoice balance before rendering QR code in web view by @idressos
* [[IP-1183](#1183)] Fix summary client delete button go to 404 (link2form) by @sudwebdesign
* [[IP-1185](#1185)] Fix styling in clients table header by @tstoeter
* [[IP-1186](#1186)] Style2class for amounts & balances (th & tr) by @sudwebdesign
* [[IP-1197](#1197)] Send email show blank page (php>=8.2) by @sudwebdesign
* [[IP-1199](#1199)] Add invoice_status case in template_helper by @sudwebdesign
* [[IP-1201](#1201)] Fix SMTP password wrong after saving settings by @sudwebdesign
* [[IP-1204](#1204)] Update template_helper.php to fix email template with custom single choice field by @LOK-Soft
* [[IP-1251](#1251)] fix: amount of the credit transfer cannot be smaller than 0.01 Euro by @mheiduk
* [[IP-1278](#1278)] Fix: Styling issues by @pumpi
* [[IP-1283](#1283)] fix: Client detail view exception by

**Full Changelog**: v1.6.2...v1.6.3
ThierryHFR pushed a commit to ThierryHFR/InvoicePlane that referenced this pull request Dec 21, 2025
* [[IP-1268](InvoicePlane#1268)] **E-invoicing infrastructure update** by @sudwebdesign
* [[IP-1272](InvoicePlane#1272)] **E-invoicing enhancements** by @sudwebdesign
* [[IP-1247](InvoicePlane#1247)] Processing e-invoices flow (and some bugfixes) for version 1.6.3 by @nielsdrost7
* [[IP-1282](InvoicePlane#1282)] feat: Legacy calculation setup step by @pumpi
* [[IP-1281](InvoicePlane#1281)] fix: Client overview shows wrong e-Invoicing state by @pumpi

* [[IP-1277](InvoicePlane#1277)] Replace node-sass with sass by @onny
* [[IP-1261](InvoicePlane#1261)] Guest Payment stripe flow & online_payment lang improved by @nielsdrost7
* [[IP-1178](InvoicePlane#1178)] Add custom_fields in controllers/Settings by @sudwebdesign
* [[IP-1206](InvoicePlane#1206)] Add report: Invoices per client by @mheiduk
* [[IP-1228](InvoicePlane#1228)] Improve number_helper & standardize_amount (fix european format) by @sudwebdesign
* [[IP-1229](InvoicePlane#1229)] Remove unattended standardize_amount in payments view form by @sudwebdesign
* [[IP-1241](InvoicePlane#1241)] Add pagination to invoice and quote templates by @onny
* [[IP-1219](InvoicePlane#1219)] Sort invoices by date instead of id by @MrKrisKrisu
* [[IP-1222](InvoicePlane#1222)] Sort quotes by date instead of id by @sudwebdesign

* [[IP-1179](InvoicePlane#1179)] Fix #fullpage-loader (Spinner) never showed after save by @sudwebdesign
* [[IP-1174](InvoicePlane#1174)] Removed '.pdf' from Invoices.php downloads to fix issue by @HeapReaper
* [[IP-1175](InvoicePlane#1175)] Check invoice balance before rendering QR code in web view by @idressos
* [[IP-1183](InvoicePlane#1183)] Fix summary client delete button go to 404 (link2form) by @sudwebdesign
* [[IP-1185](InvoicePlane#1185)] Fix styling in clients table header by @tstoeter
* [[IP-1186](InvoicePlane#1186)] Style2class for amounts & balances (th & tr) by @sudwebdesign
* [[IP-1197](InvoicePlane#1197)] Send email show blank page (php>=8.2) by @sudwebdesign
* [[IP-1199](InvoicePlane#1199)] Add invoice_status case in template_helper by @sudwebdesign
* [[IP-1201](InvoicePlane#1201)] Fix SMTP password wrong after saving settings by @sudwebdesign
* [[IP-1204](InvoicePlane#1204)] Update template_helper.php to fix email template with custom single choice field by @LOK-Soft
* [[IP-1251](InvoicePlane#1251)] fix: amount of the credit transfer cannot be smaller than 0.01 Euro by @mheiduk
* [[IP-1278](InvoicePlane#1278)] Fix: Styling issues by @pumpi
* [[IP-1283](InvoicePlane#1283)] fix: Client detail view exception by

**Full Changelog**: InvoicePlane/InvoicePlane@v1.6.2...v1.6.3
ThierryHFR pushed a commit to ThierryHFR/InvoicePlane that referenced this pull request Dec 21, 2025
### What's Changed (since v1.6.2)

#### Major Features & E-Invoicing

* [[IP-1268](InvoicePlane#1268)] **E-invoicing infrastructure update** by @sudwebdesign
* [[IP-1272](InvoicePlane#1272)] **E-invoicing enhancements** by @sudwebdesign
* [[IP-1247](InvoicePlane#1247)] Processing e-invoices flow (and some bugfixes) for version 1.6.3 by @nielsdrost7
* [[IP-1282](InvoicePlane#1282)] feat: Legacy calculation setup step by @pumpi
* [[IP-1281](InvoicePlane#1281)] fix: Client overview shows wrong e-Invoicing state by @pumpi

#### Changed / Improvements

* [[IP-1277](InvoicePlane#1277)] Replace node-sass with sass by @onny
* [[IP-1261](InvoicePlane#1261)] Guest Payment stripe flow & online_payment lang improved by @nielsdrost7
* [[IP-1178](InvoicePlane#1178)] Add custom_fields in controllers/Settings by @sudwebdesign
* [[IP-1206](InvoicePlane#1206)] Add report: Invoices per client by @mheiduk
* [[IP-1228](InvoicePlane#1228)] Improve number_helper & standardize_amount (fix european format) by @sudwebdesign
* [[IP-1229](InvoicePlane#1229)] Remove unattended standardize_amount in payments view form by @sudwebdesign
* [[IP-1241](InvoicePlane#1241)] Add pagination to invoice and quote templates by @onny
* [[IP-1219](InvoicePlane#1219)] Sort invoices by date instead of id by @MrKrisKrisu
* [[IP-1222](InvoicePlane#1222)] Sort quotes by date instead of id by @sudwebdesign

#### Fixed

* [[IP-1179](InvoicePlane#1179)] Fix #fullpage-loader (Spinner) never showed after save by @sudwebdesign
* [[IP-1174](InvoicePlane#1174)] Removed '.pdf' from Invoices.php downloads to fix issue by @HeapReaper
* [[IP-1175](InvoicePlane#1175)] Check invoice balance before rendering QR code in web view by @idressos
* [[IP-1183](InvoicePlane#1183)] Fix summary client delete button go to 404 (link2form) by @sudwebdesign
* [[IP-1185](InvoicePlane#1185)] Fix styling in clients table header by @tstoeter
* [[IP-1186](InvoicePlane#1186)] Style2class for amounts & balances (th & tr) by @sudwebdesign
* [[IP-1197](InvoicePlane#1197)] Send email show blank page (php>=8.2) by @sudwebdesign
* [[IP-1199](InvoicePlane#1199)] Add invoice_status case in template_helper by @sudwebdesign
* [[IP-1201](InvoicePlane#1201)] Fix SMTP password wrong after saving settings by @sudwebdesign
* [[IP-1204](InvoicePlane#1204)] Update template_helper.php to fix email template with custom single choice field by @LOK-Soft
* [[IP-1251](InvoicePlane#1251)] fix: amount of the credit transfer cannot be smaller than 0.01 Euro by @mheiduk
* [[IP-1278](InvoicePlane#1278)] Fix: Styling issues by @pumpi
* [[IP-1283](InvoicePlane#1283)] fix: Client detail view exception by

**Full Changelog**: InvoicePlane/InvoicePlane@v1.6.2...v1.6.3
nielsdrost7 added a commit that referenced this pull request Jan 19, 2026
* #991: Only load custom_lang.php if it's present

* #991: Only load custom_lang.php if it's present

* Show list of themes on Windows

* #1034: Fix error where default_language at some point switches to English

* fixes #1038

* formatting #1033

* only update invoice_date_due when sending email #1033

invoice_date_created should not be updated and always stay the same

* move execution of update_invoice_due_date into mark_sent #1033

* remove unnecessary settings tmp_invoice_date and tmp_due_date settings
* remove unnecessary helper function reset_invoice_due_dates

* fix indentation #1033

* replace tabs with spaces #1033

* bump composer packages

* cleanup extra linebreaks

* Revert change to invoice_logo() that was intended only for invoice_logo_pdf()

* Remove slash because base_url() already has a trailing slash

* refractored payments code

* use var to prevent reload problem

* included the paypal gateway settings

* created paypal payment page

* added paypal as an extra gateway to be loaded

* setup paypal payment endpoint

* created paypal REST consumer

* implemented sandbox for paypal

* removed omnipay

* required guzzle

* required stripe php sdk

* renamed dir

* fixed stripe endpoint

* created stripe REST API consumer

* changed location of files

* adapted stripe page to use embedded checkout

* included the money package for currencies (was in omnipay)

* fixed success message

* created verifier

* added some comments for clarity

* fixed condition for refusing payment

* improved paypal REST consumer

* refractored payment information

* made paypal gateway controller

* changed source url after refractoring

* improvement code for readability

* removed old form

* removed deprecated code

* handle better single payment gateway

* bug fixes

* renamed file to prevent loop

* made new selection mode

* updaed file

* new provider selction method

* refractored new paypal lib

* fixed output

* removed the select2 selector

* provider auto-selection

* fixed style of paypal buttons

* added the select method message

* prevent accessing payment page with invoice balance zero

* #1046: Fixed some formatting

* #1046: Fixed some formatting

* Slight improvements to README.md

Link to demo on homepage so logindata is provided and adjust some wordings

* fixes issue #1070

* Fixed broken customer-link in projects-widget. #1072

* fix: ZUGFeRD Name should not be user name

* Add Pint and add some directories

* added pint.json to help with formatting the files in a certain standard

* pre-select current currentcy for online payment

* fixed formatting

* added information on theming

* Bugfix: Other client can be selected from list

Bug: No other client can be selected/looked up from the client list. Only the customer from the source invoice was selected.
Fix: Selecting an other client is now possible. The selection is saved in the copied invoice.

* Bugfix: Selected quote date is saved

Bug: The quote date from the source quote was saved and not the selected or entered date from the datepicker.
The original quote date was always saved in the copied quote.
Fix: The selected date from the datepicker is saved in the copied quote.

* Fix #841 Copy quote (modal) UI feedback

Bug:  When the data is retrieved from the custom_fields db and put into an array and if there is no data in the db, the array cannot be populated so the result is that there is no "response" at all.
Fix: extracted the working snippet from mdl_invoice and modified it in mdl_quotes. Even when there is no data/array there is a response.

* Adapt copy custom fields code if null

* Revert some accidently changes

* implemented alternative solution

* formatting improvement

* copy all fields available in quotes #998

* styling

* Improve pint.json just a tiny bit and then format pint.json correctly

* Add filter_input function and filter_input in the Clients module

* Add filter_input for all the controllers that have the form() function

* feat: Add pagination for tabs in client detail fix #1083

* tab change by url and fixed typos

* removed ternary

* fix formatting

* refactor: rename tab variable to activeTab

* fix: model-pager have no bottom space in tab

* fixed worng bracket

* 1096: remove check for number of rows in ip_payments and subsequent early return

* changed behavior of returned ->payments, to be null or an array

* code formatting

* Add another digit for quantity

This serves as an example. Please note, that you still have to alter the database table:

ALTER TABLE ip_invoice_items MODIFY COLUMN item_quantity decimal(10, 3);

First Rule of Programming: Don't run code from the internet when you don't understand it. It might break things.

* altered tables

* added db changes

* adapted function

* created setting

* adapted invoice items

* made quantity available to all views

* made quantity available to all quote views

* made quantity available to quote views

* code formatting

* [IP-1003]: Add extra field title (#1101)

* Add selector title & create enum php & add field client_title on table ip_client & translation field client_title

* Add client title to format client function & KISS & add select and custom title field when custom choice

* Clean & edit select auto client title

* Add selector title & create enum php & add field client_title on table ip_client & translation field client_title

* 1059: Fixed styling in a PHP array

* 1059: Validation: client_title isn't required

* 1059: database field: *after* client_surname, made sure migration worked

* 1059: No yoda-style if-statements, no void return types (yet), no strict typing in files (yet)

* 1059: no void return types (yet)

* feat: Add pagination for tabs in client detail fix #1083

* tab change by url and fixed typos

* removed ternary

* fix formatting

* refactor: rename tab variable to activeTab

* fix: model-pager have no bottom space in tab

* Add selector title & create enum php & add field client_title on table ip_client & translation field client_title

* Add selector title & create enum php & add field client_title on table ip_client & translation field client_title

* 1059: Fixed styling in a PHP array

* 1059: no void return types (yet)

* 1059: Removed obsolete migration file

* 1059: Moved form for the client_title to the bottom of the page (near gender)

* emulate enum

* 1096: remove check for number of rows in ip_payments and subsequent early return

* changed behavior of returned ->payments, to be null or an array

* code formatting

* Improve pint.json just a tiny bit and then format pint.json correctly

* Add filter_input function and filter_input in the Clients module

* Add filter_input for all the controllers that have the form() function

* fixed worng bracket

* Add another digit for quantity

This serves as an example. Please note, that you still have to alter the database table:

ALTER TABLE ip_invoice_items MODIFY COLUMN item_quantity decimal(10, 3);

First Rule of Programming: Don't run code from the internet when you don't understand it. It might break things.

* altered tables

* added db changes

* adapted function

* created setting

* adapted invoice items

* made quantity available to all views

* made quantity available to all quote views

* made quantity available to quote views

* code formatting

* Add selector title & create enum php & add field client_title on table ip_client & translation field client_title

* Add selector title & create enum php & add field client_title on table ip_client & translation field client_title

* 1059: Fixed styling in a PHP array

* 1059: database field: *after* client_surname, made sure migration worked

* 1059: no void return types (yet)

* feat: Add pagination for tabs in client detail fix #1083

* tab change by url and fixed typos

* removed ternary

* fix formatting

* refactor: rename tab variable to activeTab

* tmp

* rebased development branch into 1059 clientTitle branch

* 1059: quick formatting of arrays

---------

Co-authored-by: Kevin Joudrier <kev.joudrier@gmail.com>
Co-authored-by: pumpi <sf@pumpi-online.de>
Co-authored-by: naui95 <nahuel.guidotti@outlook.com>
Co-authored-by: = <=>
Co-authored-by: der-peer <post@peeruhlmann.de>
Co-authored-by: naui95 <naui95@hotmail.com>
Co-authored-by: Nathan Mattes <hallo@bullenscheisse.de>

* Making sure all the fields in the templates are escaped by htmlspecialchars

* replaced _htmlsc with htmlsc where output was echoed

* 1089: Fixes after code-review

* 1089: Fixes after code-review

* no typehint in ClientTitle enum call

* 1063: Allowing for Dynamic Properties (PHP 8.2)

* 1063: Set back Cryptor the way it was and then allowed Dynamic Properties again

* 1063: Set back MY_Form_validation the way it was and then allowed Dynamic Properties again

* 1063: Set back class Sumex
 the way it was and then allowed Dynamic Properties again

* 1063: Set back class Sumex
 the way it was and then allowed Dynamic Properties again

* 1063: Set back class ZugferdXml
 the way it was and then allowed Dynamic Properties again

* 1063: Set back class ZugferdXml
 the way it was and then allowed Dynamic Properties again

* 1063: Set back class PaypalLib the way it was and then allowed Dynamic Properties again

* 1063: Set back Clients Controller the way it was and then allowed Dynamic Properties again

* 1063: #[AllowDynamicProperties] with the PHP 8.2 (8.0+) compatible annotation

* 1063: Put back MX / Base the way it was and then allowed for Dynamic Properties

* 1063: Modules.php: Placing of the annotation

* helpers without dynamic properties

* fixed bug where title for the client wasn't saved

* Custom rendering will be empty instead of 'custom'

* Custom rendering needs to be 'custom', otherwise it won't be shown in the ClientTitle list

* fixed bug where a custom client_title was rendered as "Custom"

* better formatting

* 1010: Added 2 extensions and improved xdebug.ini. Added special xdebug.ini

* yarn upgrade and freeze lock file

* Special Chore done

* issue 1119: add index.php if REMOVE_INDEXPHP is not true

* finished Chore

* chore: add more options to destroy sessions earlier

* add docker publish workflow

* fix package.json and yarn.lock for old sass

* Update QrCode.php

When an invoice is paid in part. The QR code always displays the total paid, not what remains to be paid.

* Improve download function

* improved get_file function

* property client_title doesn't exist?

* array_walk an array if value isn't an array

* typecasting the decimal_point in number_helper line 76

* fix upload_file function

* Fix Upload class

* New Buttons for Delete Client note in view (Ajax)

Reload all notes after deleted
+ (new) click event by add_delete_client_notes_click_event()

* Remove has-error after good (unempty.trim) client note

Fix after 1 error, alway in error
.control-group: is (in reality) .input-group & setted with .has-error

* Clients view: reload_client_notes() + loader fades

Note: Ajax post client_id is in js constant now

* Idea to translate Client Title Enums

See Clients/Enums/ClientTitleEnum

* Fix #1146 after posting a Payments Form when amount > inv. total

#1146

Fix number_format(): Arg #1 ($num) must be of type float, string given
modules/payments/views/form.php Function: format_amount

* Fix payment Cancel repost onclick: history.back 2 location.href

By default cancel has onclick with `window.history.back()`
See
[header_buttons.php](https://github.com/InvoicePlane/InvoicePlane/blob/development/application/modules/layout/views/header_buttons.php)

But if click Save multiple time (like monkey) with bad amount value
And click Cancel, do repost.

Now Cancel always go to Payments page.

* Fix setup sql filenames

See : [IP-1003: Add extra field title
(#1101)](c64b5df#diff-f97132f81d846a5d14eb35d66fe77c943572d8db71735702e6f018f65671058c)

Devs, After need update DB Like this:

UPDATE `ip_versions` SET
`version_id` = '38',
`version_date_applied` = '1734693462',
`version_file` = '037_1.6.1.sql',
`version_sql_errors` = '0'
WHERE `version_id` = '38';

UPDATE `ip_versions` SET
`version_id` = '39',
`version_date_applied` = '1734693462',
`version_file` = '038_1.6.2.sql',
`version_sql_errors` = '0'
WHERE `version_id` = '39';

* Added required input check on full page loaded to 'fix' #1130

* Removed console.log from bugfix

* bug-fix-#1147-error-on-database-migration (#1159)

* Added required input check on full page loaded to 'fix' #1130

* Refactored upgrade_tables function in Mdl_setup.php

* Refactored execute_contents in Mdl_setup.php to remove nested ifs

* Added error ignoring on database upgrade to fix #1147

* Removed comment and changed AND operator to OR in Mdl_setup.php

* Refactored upgrade_tables function in Mdl_setup.php

* Refactored execute_contents in Mdl_setup.php to remove nested ifs

* Added error ignoring on database upgrade to fix #1147

* Removed comment and changed AND operator to OR in Mdl_setup.php

* Removed scripts.js from conflicting branche

* Removed scripts.js from conflicting branche

* Update Mdl_setup.php

* Added displaying DB error and moved to negative comparison in Mdl_setup.php

* Removed tab and comments in Mdl_setup.php

---------

Co-authored-by: Niels Drost <47660417+nielsdrost7@users.noreply.github.com>

* Fix setup Red Screen Of Death with bad DB query

Complete #1147
[Solve Red screen Of Death of bad DB query in
CI3](https://stackoverflow.com/questions/7843406/codeigniter-how-to-catch-db-errors#54519533)

Fix Call to undefined method CI_DB_mysqli_driver::_error_message()
The _error_message() function unexist in CI3.1.13:
`vendor/codeigniter/framework/system/database/DB_driver.php`

+ Indents: tab2spaces

* Clear setup comments and return all DB errors

* Setup upgrade_tables scroll to bottom page

* Setup: db debug same as IP_DEBUG

* Fix missing if-check

* fix problem

* Removed '.pdf' from Invoices.php downloads to fix #1171

* Check invoice balance before rendering QR code

* Fix #1169 : Add custom_fields in controllers/Settings

Now Custom Fields ip_invoice_custom is present in settings page

+ Remove hard fix in view template-tags-invoices

+ Indents of settings view partial_settings general

* Fix: Delete Client go to 404 page #1182

Inspired by `module/clients/view/partial_client_table.php`

* Little details (Base_controller) + indents + tab2spaces

* Fix styling in clients table header #1184

* Style2class for amounts & balances (th & tr)

Improve #1185

Scope:
+ Clients
+ DashBoard
+ Invoices
+ Quotes
+ Payments
+ Products
+ Tasks

Note: .amount.last apply padding in last element like Quotes list

* Fix fullpage-loader helper never showed

`$(document).on('click', '.ajax-loader', function () {`
Is duplicated inside same function.

* Remove event unused JS var (Fullpage loader)

* Fix: Send email show blank page #1196

* Add invoice_status case in template_helper (Fix #1198)

Scope: qr_code_settings_remittance_text

* Fix SMTP password wrong after saving settings #1200

* Update template_helper.php to fix email template with custom single choice field

This update will use written label instead of option number in email template, if the filed is an custom field with single choice

* chore: pint

* chore: pint

* add invoices_per_client report

* use client custom field for invoices_per_client report

* remove debug

* fix: order by client_id

* fallback if no client_custom_fieldvalue is available

* remove client_custom_fieldvalue

* use format_client helper

* sort invoices by date instead of id

* sort quotes by date instead of id

see #1218

* Improve number_helper & standardize_amount (fix european format)

Fix #1227
European number format change amount on save when use dot as comma

* Remove unattended standardize_amount in payments view form

* Make sure invoiceplane.conf works properly

* Add pagination to invoice and quote templates

* fix: amount of the credit transfer cannot be smaller than 0.01 Euro #1128

* Guest Payment stripe flow & online_payment lang improved

Load Invoice Model in `__construct` (used in all (2) func's) Don't need
site_url for `redirect()`
Improve merchand response db insert
Improve invoice privacy: client_reference_id (id TO url_key) And adjust
indents for the `callback` (it's a function in `class`)

Adjust lang sys for multiple use (why not in paypal?)

Big Thanks @Matthias-Ab

* [IP-939]: Processing e-invoices flow (and some bugfixes): `development` branch for version 1.6.3 (#1247)

Prepare for 1.6.3 and 1.7.0

---------

Co-authored-by: Thomas Ingles <thomas@sudwebdesign.fr>

* Development v163rc1 (#1268)

* Improve versions in composer & package +
up yarn & composer lock

* Improve gh templates & workflows & infos (md)

Improve & Merge Develop v163rc1 (#1266)
Without TRANSLATION.md

* Setup: Upgrade default & users languages to lowercase like #1232

* Fix: Save products & tasks. No empty rules in Form_validation

Form_validation: set_rules() called with an empty $rules parameter

See: #1195

* Improve Uploader: Del old system. No show file \w upload_file()

Not used in v1.6.3RC0

* PHP compat: No E_STRICT (error_reporting) & Adjust Rector rule

In accordance of doc, is unused & PHP 8.4 deprecate.
See:
https://www.php.net/manual/errorfunc.constants.php#constant.e-strict
---
Scope: production or testing environment
How to set? See:
https://github.com/orgs/InvoicePlane/discussions/1168

* Rector: More efficient Sets: deadCode, codeQuality & codingStyle

Applied rules:
 * RemoveUselessParamTagRector
 * StrictArraySearchRector
 * FuncGetArgsToVariadicParamRector

* Refacto \w Rector: Prepared set typeDeclarations:true

Applied rules:
 * ReturnUnionTypeRector
 * ReturnNullableTypeRector
 * RemoveUselessParamTagRector
 * RemoveUselessReturnTagRector
 * StrictStringParamConcatRector
 * StrictArrayParamDimFetchRector
 * SimplifyBoolIdenticalTrueRector
 * ParamTypeByMethodCallTypeRector
 * ReturnTypeFromStrictNewArrayRector
 * SimplifyEmptyCheckOnEmptyArrayRector
 * ReturnTypeFromReturnDirectArrayRector
 * NumericReturnTypeFromStrictReturnsRector
 * TypedPropertyFromStrictConstructorRector
 * BoolReturnTypeFromBooleanConstReturnsRector
 * BoolReturnTypeFromBooleanStrictReturnsRector
 * AddFunctionVoidReturnTypeWhereNoReturnRector
 * StringReturnTypeFromStrictStringReturnsRector

* Add composer scripts: phpcs, rector & check

`composer run check` to verify & correct the code (with all)

* Refacto: My_Form_validation::run() (Ready for Next-1.7)

Ok with CodeIgniter 3.1.13 (& 3.3 by pocketarc for PHP 8.2+)
See:
e95b95f

* ipconfig: Add CI_ENV=production to hide minor PHP errors by default

Improve gitignore
& remove todo (oups)

* [wip] JSON.parse to json_parse to show error in front end

* [script.js] json_parse for all & console.trace(data) to debug

Need `yarn build`
if `ENABLE_DEBUG=false` in ipconfig

* [script.js] Finish json_parse: Add console.error & div.alert

* README header: Restore badges & show favicon at float right

---------

Co-authored-by: Niels Drost <nielsdrost7+github@gmail.com>

* Replace node-sass with sass (#1277)

* Development v163rc2 (#1272)

* composer upgrade: Lock file operations: 5 updates

Updating dependencies
  - Upgrading filp/whoops (2.18.0 => 2.18.1)
  - Upgrading laravel/pint (v1.20.0 => v1.22.1)
  - Upgrading phpstan/phpstan (2.1.16 => 2.1.17)
  - Upgrading rector/rector (2.0.16 => 2.0.17)
  - Upgrading symfony/deprecation-contracts (v3.5.1 => v3.6.0)

* Composer\\Config::disableProcessTimeout (scripts)

To fix The process "pint" exceeded the timeout of 300 seconds.

* lint by composer run check (1 file rectified)

Applied rules:
 * ParamTypeByMethodCallTypeRector

* [einvoice] Fix bad wrap in users-check-lists (client view)

* [eInvoice] Shift legacy_calculation to false When client use e-Invoice

and if XMLconfigs file haven't `'legacy_calculation' => true`

* [eInvoice] Add Automatic calculation mode in Cron & adjustments

* Fix #1271 : Add payment_method on Cron

Payment Method not copied from recurring invoice to generated invoice

* [eInvoice] DRY: Use legacy_calculation constant in modal scripts

The const legacy_calculation defined in script (get meta content)
The data-legacy-calculation in btn isn't necessary (removed)

* Fix: Quote header col classes to do the same as Invoice (view)

* Fix: Styling issues (#1278)

* fix: panel in panel should be inside panel-body

* fix: cancel button is not centered

* fix: Sidebar is not full height on sites with low content

* fix: Client overview shows wrong e-Invoicing state (#1281)

* feat: Add a setup step to ensure the user uses the right config value for LEGACY_CALCULATION (#1282)

* fix: Client detail view exception after #1281 changes (#1283)

* Update number_helper.php to avoid empty string warning (#1302)

In `standardize_amount`, `$thousands_separator` is read from the settings, and if it is empty, the error occurs. If I understand correctly, the settings value is not changed directly via UI, but depends on the chosen `number_format`. It is set in `settings.php`, line 78, just below `// Set thousands_separator and decimal_point according to number_format`.
So `standardize_amount ` produces the error if a compact `number_format` is used, which resets the thousands separator settings value to an empty string. So the solution would be to simply not use the `thousands_separator` setting, if it is empty

* implement new templates with named footers (#1313)

* implement new templates with named footers

* use named footers to avoid overwriting footers

* Feature/1288 - PayPal Advanced Credit Cards and Venmo (#1289)

* Adds PayPal advanced credit card fields, #1288

* Adds advanced CC option and conditional logic, #1288

* Adds Venmo option and conditional logic, #1288

* Adds a header builder and additional recommended header params, #1288

* Ignores /.temp, #1288

* Adds proper error handling at transaction level, #1288

* Improves client and server side error handling, #1288

* Moves CSS to core assets structure, #1288

* Moves JS to core assets structure, #1288

* Updates dependencies

* Adds payment-forms assets to Grunt clean exclusions, #1288

* Improves payment section display, #1288

* Adjusts processing spinner to align with button, #1288

* Renames PayPal assets, #1288

* ran pint

* [1307]: Sending emails to multiple email addresses gives error message (#1308)

* using filter_var in mailer_helper caused issues when multiple email addresses were allowed refs #1307

* also fixed it for sending quotes refs #1307

* added custom e-mail validator

* fixed bug with array on string

* removed comments and corrected return type

---------

Co-authored-by: naui95 <nahuel.guidotti@outlook.com>

* Solves problem where Alpine Docker containers don't know the \GLOB_BRACE constant refs #1304 (#1305)

* ran pint

* [IP-1340]: wrong quoteinvoice guest download attachment button default template (#1343)

* use get_file method (#1342)

* use get_file method (#1341)

* Revert "[IP-1340]: wrong quoteinvoice guest download attachment button defaul…" (#1344)

This reverts commit cc2762f.

* Add default_order_by method for recurring invoices (#1334)

* Make $show_item_discounts available in InvoicePlane_Web.php (#1310)

* Hide discounts column when show_item_discounts is false refs #1298

* determine discouted items

* fixed display for no discounts

* hide discounts also with legacy calculation

* applied discount hiding also to quotes

* fixed item totals

* fixed discount display

* enforced standard

---------

Co-authored-by: naui95 <naui95@hotmail.com>

* 1322: Show open invoices on guest index (#1350)

* composer.json omit version string (#1306)

* Fix Niels: Uploads (#1338)

* Made uploading files more secure refs #1326

* Update application/modules/upload/controllers/Upload.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* improved security:
- sanitize filename
- prevent corss-path navigation

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: naui95 <nahuel.guidotti@outlook.com>

* Put back the InvoicePlane version in the package.json

* Prep: v1.6.4 (#1354)

* Temporary Commit Fix Niels - 1 - SalesByYear report

* Fix Niels - 1 - SalesByYear

* Temporary Commit Fix Niels - 3 - Guest Get File

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Suggestions after code-review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* using strpos as per suggestion in code-review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* suggestion after code-review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* suggestion after code-review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Final fixes for the Get file problem refs #1324

* suggestion after code-review

* cleanup after code-review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* cleanup after code-review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Get file (guest) fix refs #1324

* 1340: Wrong quote/invoice guest download attachment button default template

* 1348: More fixes for PDF footer

* 1322: Show open invoices on guest index

* 1340: guest route sanitization

* 1340: guest route sanitization

* 1340: guest route sanitization

* 1340: guest route sanitization

* Update application/modules/guest/controllers/Get.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update application/modules/reports/models/Mdl_reports.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update application/modules/reports/models/Mdl_reports.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* critical code review (#1355)

* Initial plan

* Fix critical path traversal and LFI vulnerabilities

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix SQL injection vulnerability in guest attachments

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add comprehensive security audit report

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add quick summary of security scan results

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix password reset rate limiting and email enumeration vulnerabilities

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Refactor password reset to use session-based rate limiting (no DB migration)

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Make password reset rate limiting configurable via ipconfig.php

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Convert hardcoded log messages to translation strings

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix SQL injection and open redirect vulnerabilities (#1358)

* Initial plan

* Fix SQL injection and open redirect vulnerabilities

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add comprehensive security summary documentation

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add quick reference security summary

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Delete COMPREHENSIVE_SECURITY_SUMMARY.md

* Delete PASSWORD_RESET_SECURITY.md

* Delete SECURITY_AUDIT_2025-11-09.md

* Delete SECURITY_AUDIT_2025-11-09_ADDITIONAL.md

* Delete SECURITY_QUICK_REFERENCE.md

* Delete SECURITY_SCAN_SUMMARY.md

* Address review feedback: Use env() for config, add bot detection, and fix syntax errors (#1359)

* Initial plan

* Replace config variable checks with env() calls and add bot detection

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Refactor password reset rate limiting methods

* Add translation for bot detection log and fix syntax errors from refactoring

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>

* for versioning purposes

* for versioning purposes

* Create 040_1.6.4.sql

* for versioning purposes

* fix: remove libs that are deprecated (#1373)

* fix: remove libs that are deprecated

* Update resources/docker/php-fpm/Dockerfile

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Patrick Subang <patrick.subang@lightningfibre.co.uk>
Co-authored-by: Niels Drost <47660417+nielsdrost7@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Fix email address verification to allow both comma and semicolon separators (#1375)

* Allow both comma and semicolon to be valid seperators for $emails to be in sync with phpmail_send() function

* fix condition check

As mb_strpos could possibly return 0 (not false), replaced both mailer_helper.php and phpmailer_helper.php to use str_contains instead

* fixes #1367 (#1368)

* Bump qs from 6.14.0 to 6.14.1 (#1380)

Bumps [qs](https://github.com/ljharb/qs) from 6.14.0 to 6.14.1.
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](ljharb/qs@v6.14.0...v6.14.1)

---
updated-dependencies:
- dependency-name: qs
  dependency-version: 6.14.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Reduce QR code image width to 100px (#1377)

* Add version checking, logging, and log sanitization for client_einvoicing fields to handle unmigrated databases (#1381)

* Initial plan

* Add defensive checks for client_einvoicing fields to handle unmigrated databases

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add version checking and extensive logging for einvoicing field access

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add null checks for version retrieval to prevent null concatenation in logs

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update application/modules/clients/controllers/Clients.php

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Simplify redundant null coalescing in view.php by extracting to variable

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Add comment explaining defensive null coalescing pattern in view.php

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix potential null dereference in Mdl_versions::get_current_version()

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix incorrect property access in Mdl_versions::get_current_version()

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Security: Fix file access vulnerabilities across all controllers with reusable helper (#1383)

* Initial plan

* Fix critical security vulnerabilities in guest/Get.php file access

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix log injection vulnerabilities in security logging

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Optimize hash calculation and strengthen path validation

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix HTTP header injection vulnerability in Content-Disposition

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Strengthen header injection protection with comprehensive control character filtering

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Create reusable file security helper and apply to all file access points

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Address code review feedback - improve string formatting and null handling

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Address code review feedback - improve path traversal detection and header sanitization

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Fix code review issues - remove redundant checks and security bypass

Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: nielsdrost7 <47660417+nielsdrost7@users.noreply.github.com>

* Potential fix for code scanning alert no. 3: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 4: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 1: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 2: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Róbert Kelčák <kelcakrobo@gmail.com>
Co-authored-by: naui95 <nahuel.guidotti@outlook.com>
Co-authored-by: Marc Heiduk <marc@heiduk.me>
Co-authored-by: John Mclaren <john@johnscs.com>
Co-authored-by: Janek <github@melonion.me>
Co-authored-by: Niklas <niklas.schmitt@mailbox.org>
Co-authored-by: stephan4p <stephan@vierpunkt.de>
Co-authored-by: VeRony <30659226+Verony-makesIT@users.noreply.github.com>
Co-authored-by: pumpi <sf@pumpi-online.de>
Co-authored-by: = <=>
Co-authored-by: der-peer <post@peeruhlmann.de>
Co-authored-by: naui95 <naui95@hotmail.com>
Co-authored-by: Nathan Mattes <hallo@bullenscheisse.de>
Co-authored-by: Kevin Joudrier <kev.joudrier@gmail.com>
Co-authored-by: Gabe Dunn <gabe@gabedunn.dev>
Co-authored-by: VizardAlpha <43859764+VizardAlpha@users.noreply.github.com>
Co-authored-by: Thomas Ingles <thomas@sudwebdesign.fr>
Co-authored-by: AutiCodes <prive@auticodes.nl>
Co-authored-by: AeroBytes <31496522+AeroBytesNL@users.noreply.github.com>
Co-authored-by: Ioannis Dressos <96877388+idressos@users.noreply.github.com>
Co-authored-by: Torsten Stöter <torsten.stoeter@lin-magdeburg.de>
Co-authored-by: Lars-Olof Kreim <mail@lok-soft.de>
Co-authored-by: Kristian Stöckel <git@k118.de>
Co-authored-by: Jonas Heinrich <onny@project-insanity.org>
Co-authored-by: Niels Drost <nielsdrost7+github@gmail.com>
Co-authored-by: ErikKrause <erik.krause@gmx.de>
Co-authored-by: naui95 <naui95@users.noreply.github.com>
Co-authored-by: Drew Angell <64537522+drewangell@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: PatrickGTR <patricksubang@live.com>
Co-authored-by: Patrick Subang <patrick.subang@lightningfibre.co.uk>
Co-authored-by: LaoDC <github@laodc.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

4 participants