feat(118): fakturownia single instance

Phase 118 complete:
- migration 20260512_000109 adds single global Fakturownia settings row
- FakturowniaIntegrationRepository simplified to one-instance API
- FakturowniaIntegrationController + edit view collapsed to one settings page
- Integrations hub shows Fakturownia as single instance
- Invoice config delegated flow always uses global integration_id

Note: shared routes/web.php and DOCS/* updates from Phase 118 are bundled
into the follow-up feat(121+122) commit because Phase 121/122 modified the
same files; hunk-level split was not performed.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-05-12 20:37:19 +02:00
parent 933dfcc67b
commit 8f14851d85
10 changed files with 585 additions and 410 deletions

View File

@@ -0,0 +1,210 @@
---
phase: 118-fakturownia-single-instance
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- database/migrations/20260512_000109_fakturownia_single_instance.sql
- src/Modules/Settings/FakturowniaIntegrationRepository.php
- src/Modules/Settings/FakturowniaIntegrationController.php
- src/Modules/Settings/IntegrationsHubController.php
- src/Modules/Settings/InvoiceConfigRepository.php
- src/Modules/Settings/InvoiceConfigController.php
- src/Modules/Accounting/InvoiceService.php
- resources/views/settings/fakturownia.php
- resources/views/settings/fakturownia-edit.php
- resources/views/settings/accounting-invoice-edit.php
- routes/web.php
- DOCS/DB_SCHEMA.md
- DOCS/ARCHITECTURE.md
- DOCS/TECH_CHANGELOG.md
autonomous: true
delegation: off
---
<objective>
## Goal
Convert Fakturownia from a multi-account integration to one global integration instance, like HostedSMS/SMSPLANET.
## Purpose
The operator should configure Fakturownia once. Invoice configs may still delegate invoice issuing to Fakturownia, but they must all point to the single global Fakturownia integration row.
## Output
One migration, one single-instance repository/controller/UI flow, updated invoice config handling, and updated technical documentation.
</objective>
<context>
<clarifications>
- **Migracja** - Co zrobic z istniejacymi wieloma kontami Fakturowni, jesli sa juz w bazie?
-> Odpowiedz: Wybrac aktywne konto.
- **Kontrakty** - Czy delegowane konfiguracje faktur maja nadal trzymac `integration_id`, ale zawsze wskazywac jedyna globalna Fakturownie?
-> Odpowiedz: Tak.
- **UI** - Jak ma wygladac UI Fakturowni?
-> Odpowiedz: Jedna strona z formularzem konfiguracji i testem polaczenia, bez dodawania wielu instancji.
</clarifications>
## Project Context
@.paul/PROJECT.md
@.paul/ROADMAP.md
@.paul/STATE.md
@DOCS/DB_SCHEMA.md
@DOCS/ARCHITECTURE.md
## Source Files
@src/Modules/Settings/FakturowniaIntegrationRepository.php
@src/Modules/Settings/FakturowniaIntegrationController.php
@src/Modules/Settings/HostedSmsIntegrationRepository.php
@src/Modules/Settings/IntegrationsHubController.php
@src/Modules/Settings/InvoiceConfigRepository.php
@src/Modules/Settings/InvoiceConfigController.php
@src/Modules/Accounting/InvoiceService.php
@resources/views/settings/fakturownia.php
@resources/views/settings/fakturownia-edit.php
@resources/views/settings/accounting-invoice-edit.php
@routes/web.php
## Prior Work
@.paul/phases/113-fakturownia-integration/113-01-SUMMARY.md
@.paul/phases/114-accounting-configs-refactor/114-01-SUMMARY.md
@.paul/phases/115-invoice-from-order/115-01-SUMMARY.md
@.paul/phases/116-hostedsms-integration/116-01-SUMMARY.md
</context>
<skills>
## Required Skills
No blocking skills before APPLY.
Project SPECIAL-FLOWS requires `sonar-scanner` after APPLY and before UNIFY when available in PATH.
</skills>
<acceptance_criteria>
## AC-1: Jedna globalna konfiguracja Fakturowni
```gherkin
Given the operator opens /settings/integrations/fakturownia
When the page renders
Then there is one settings form with save and test actions, and no UI for adding, listing, or deleting multiple Fakturownia accounts
```
## AC-2: Migracja wybiera aktywna instancje
```gherkin
Given multiple integrations with type "fakturownia" exist before migration
When the migration runs
Then the active integration is preserved as the single global row, invoice_configs.integration_id values are reassigned to it, settings are preserved for that row, and extra unused Fakturownia rows are removed or detached safely
```
## AC-3: Delegacja faktur pozostaje kompatybilna
```gherkin
Given an invoice config has is_delegated = 1
When it is saved or used to issue an invoice
Then it points to the single global Fakturownia integration_id and InvoiceService can still call Fakturownia without schema changes
```
## AC-4: Hub integracji pokazuje pojedynczy status
```gherkin
Given the integrations hub is opened
When Fakturownia row is displayed
Then it shows one provider row with configured/active/token/test status for the global instance, not a count of instances
```
## AC-5: Dokumentacja jest aktualna
```gherkin
Given the implementation is complete
When DOCS are reviewed
Then DB_SCHEMA, ARCHITECTURE, and TECH_CHANGELOG describe Fakturownia as a fixed single-instance integration and note the migration behavior
```
</acceptance_criteria>
<tasks>
<task type="auto">
<name>Task 1: Add single-instance migration</name>
<files>database/migrations/20260512_000109_fakturownia_single_instance.sql, DOCS/DB_SCHEMA.md</files>
<action>
Create an idempotent migration that enforces the single-instance Fakturownia model without dropping existing invoice history.
- Pick the preserved row by priority: active Fakturownia integration first, then the one referenced by invoice_configs, then the lowest id.
- Ensure a base integrations row exists with type=fakturownia and name=Fakturownia if none exists.
- Ensure one fakturownia_integration_settings row exists for the preserved integration.
- Reassign invoice_configs.integration_id for delegated configs to the preserved integration.
- Remove extra fakturownia_integration_settings/integrations rows only after reassignment, using prepared migration SQL and FK-safe order.
- Add/adjust constraints so settings are fixed to id=1 when feasible without breaking MySQL compatibility.
Avoid: deleting invoices, changing invoices.config_id, or removing the invoice_configs.integration_id column.
</action>
<verify>C:\xampp\php\php.exe bin\migrate.php on a database with zero, one, and multiple Fakturownia rows; inspect integrations/fakturownia_integration_settings/invoice_configs after migration.</verify>
<done>AC-2 and AC-3 satisfied.</done>
</task>
<task type="auto">
<name>Task 2: Refactor Fakturownia repository/controller/UI to single settings page</name>
<files>src/Modules/Settings/FakturowniaIntegrationRepository.php, src/Modules/Settings/FakturowniaIntegrationController.php, resources/views/settings/fakturownia.php, resources/views/settings/fakturownia-edit.php, routes/web.php, src/Modules/Settings/IntegrationsHubController.php</files>
<action>
Replace the multi-account behavior with HostedSMS-style single settings behavior.
- Repository exposes getSettings(), saveSettings(), getCredentials()/getDecryptedToken() and getIntegrationId() for the fixed integration.
- Save updates the single integration row and single settings row; empty token preserves the old encrypted token.
- Controller index renders one page with the form and test panel; save/test redirect back to /settings/integrations/fakturownia.
- Remove or neutralize /new, /edit, /delete routes and links for Fakturownia.
- Hub row uses the single settings object and no longer displays instance counts.
Avoid: native alert()/confirm(), inline CSS in new view code, and SQL string concatenation.
</action>
<verify>C:\xampp\php\php.exe -l on touched PHP files; manually open /settings/integrations and /settings/integrations/fakturownia, save settings, and run connection test.</verify>
<done>AC-1 and AC-4 satisfied.</done>
</task>
<task type="auto">
<name>Task 3: Keep invoice config delegation compatible with the global integration</name>
<files>src/Modules/Settings/InvoiceConfigRepository.php, src/Modules/Settings/InvoiceConfigController.php, src/Modules/Accounting/InvoiceService.php, resources/views/settings/accounting-invoice-edit.php, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md</files>
<action>
Update invoice config handling so delegated configs always use the single Fakturownia integration.
- When saving delegated invoice configs, ignore user-supplied multi-account choice and resolve the global Fakturownia integration_id from the repository.
- Simplify accounting invoice edit UI so delegation does not show a multi-account selector; show a compact hint/status that Fakturownia must be configured globally.
- Ensure InvoiceService still reads config integration_id and retrieves credentials through the updated repository.
- Update docs and changelog with new single-instance contract and migration behavior.
Avoid: schema removal of invoice_configs.integration_id and behavior changes for local non-delegated invoice configs.
</action>
<verify>C:\xampp\php\php.exe -l on touched PHP files; create/edit local and delegated invoice configs; issue a delegated invoice against a configured Fakturownia account in manual UAT.</verify>
<done>AC-3 and AC-5 satisfied.</done>
</task>
</tasks>
<boundaries>
## DO NOT CHANGE
- Do not remove `invoice_configs.integration_id`.
- Do not change existing `invoices` rows or invoice PDF rendering.
- Do not add `invoice.created` automation event.
- Do not implement Fakturownia double-POST idempotency in this plan.
- Do not change HostedSMS/SMSPLANET behavior.
## SCOPE LIMITS
- This plan only changes Fakturownia account configuration from multi-instance to single-instance.
- Existing delegated invoice issuing remains functionally the same after it resolves the global account.
- Live Fakturownia API testing depends on operator credentials and network access.
</boundaries>
<verification>
Before declaring plan complete:
- [ ] `C:\xampp\php\php.exe bin\migrate.php`
- [ ] `C:\xampp\php\php.exe -l` for all touched PHP files
- [ ] Manual UI smoke: integrations hub, Fakturownia settings save, Fakturownia test
- [ ] Manual UI smoke: invoice config create/edit for local and delegated modes
- [ ] Delegated invoice issue still calls Fakturownia with the global account
- [ ] DOCS/DB_SCHEMA.md, DOCS/ARCHITECTURE.md, DOCS/TECH_CHANGELOG.md updated
- [ ] `sonar-scanner` run after APPLY if available in PATH
</verification>
<success_criteria>
- Fakturownia has exactly one configurable instance from the UI.
- Migration preserves one active Fakturownia row and rewires delegated invoice configs to it.
- No route or view offers adding/deleting multiple Fakturownia accounts.
- Delegated invoice configs and delegated invoice issuing remain compatible.
- All verification checks pass or environment-dependent gaps are documented in SUMMARY.md.
</success_criteria>
<output>
After completion, create `.paul/phases/118-fakturownia-single-instance/118-01-SUMMARY.md`.
</output>

View File

@@ -0,0 +1,52 @@
# Phase 118 Plan 01 Summary - Fakturownia Single Instance
## Status
APPLY complete on 2026-05-12 13:47. Ready for UNIFY.
## Implemented
- Added `database/migrations/20260512_000109_fakturownia_single_instance.sql`.
- Converted `FakturowniaIntegrationRepository` to one global settings row with `getSettings()`, `saveSettings()`, `getIntegrationId()`, `getCredentials()`, and compatibility wrappers.
- Simplified `FakturowniaIntegrationController` to one settings page plus save/test actions.
- Replaced Fakturownia multi-account list UI with a single configuration form and test panel.
- Updated integrations hub to show Fakturownia as one instance.
- Updated delegated invoice config save flow to always use the global Fakturownia `integration_id`.
- Removed the invoice config account selector and replaced it with global Fakturownia status.
- Updated `DOCS/DB_SCHEMA.md`, `DOCS/ARCHITECTURE.md`, and `DOCS/TECH_CHANGELOG.md`.
- Updated `.paul/codebase/db_schema.md`, `.paul/codebase/architecture.md`, and `.paul/codebase/tech_changelog.md`.
## Verification
- PASS: `C:\xampp\php\php.exe -l` for changed PHP classes and `routes/web.php`.
- PASS: `C:\xampp\php\php.exe -l` for changed PHP views.
- PASS: static search found no active UI links for adding/deleting Fakturownia accounts; legacy `/new` and `/edit` routes redirect to the global settings page.
- BLOCKED: `C:\xampp\php\php.exe bin\migrate.php` could not connect to local MySQL (`SQLSTATE[HY000] [2002]` target actively refused connection).
- SKIPPED: PHPUnit is not available in `vendor/bin`.
- SKIPPED: `sonar-scanner` is not available in PATH.
## Environment Gaps
- Run `C:\xampp\php\php.exe bin\migrate.php` after local MySQL/XAMPP is running.
- Manually verify `/settings/integrations`, `/settings/integrations/fakturownia`, save/test Fakturownia settings, and local/delegated invoice config edit.
- Live Fakturownia API test still requires valid credentials and network access.
## Files Changed
- `database/migrations/20260512_000109_fakturownia_single_instance.sql`
- `src/Modules/Settings/FakturowniaIntegrationRepository.php`
- `src/Modules/Settings/FakturowniaIntegrationController.php`
- `src/Modules/Settings/IntegrationsHubController.php`
- `src/Modules/Settings/InvoiceConfigRepository.php`
- `src/Modules/Settings/InvoiceConfigController.php`
- `src/Modules/Accounting/InvoiceService.php`
- `resources/views/settings/fakturownia.php`
- `resources/views/settings/fakturownia-edit.php`
- `resources/views/settings/accounting-invoice-edit.php`
- `routes/web.php`
- `DOCS/DB_SCHEMA.md`
- `DOCS/ARCHITECTURE.md`
- `DOCS/TECH_CHANGELOG.md`
- `.paul/codebase/db_schema.md`
- `.paul/codebase/architecture.md`
- `.paul/codebase/tech_changelog.md`