From ae440ad48fb87adca6c40a5465ad75fdf051777b Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 08:35:05 +0000 Subject: [PATCH 1/3] fix: broken migrations and smoke test against real MariaDB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - recurring_invoices: remove FK to non-existent document_groups table - payments: add explicit index on invoice_id so MariaDB handles the nullable ON DELETE SET NULL FK constraint (errno 150 fix) - report_templates: delete duplicate migration in ReportBuilder module (identical file already exists in Core) - smoke.yml: switch from SQLite to MariaDB 10.11 service so FK constraint errors are caught; add push/pull_request triggers on master and develop so it runs automatically - quickstart.yml: uncomment and wire up MariaDB service - phpunit.yml: bump PHP 8.3 → 8.4, add pdo_sqlite extension - yarn-update.yml: bump PHP 8.2 → 8.4, fix extension names https://claude.ai/code/session_01Q4fwmdZcuFrrB6UQDeGWKd --- .github/workflows/phpunit.yml | 4 +- .github/workflows/quickstart.yml | 39 ++++++++++--------- .github/workflows/smoke.yml | 30 +++++++++++++- .github/workflows/yarn-update.yml | 4 +- ...000023_create_recurring_invoices_table.php | 7 +--- ...010_01_01_000024_create_payments_table.php | 2 +- ...25_10_26_create_report_templates_table.php | 29 -------------- 7 files changed, 55 insertions(+), 60 deletions(-) delete mode 100644 Modules/ReportBuilder/Database/Migrations/2025_10_26_create_report_templates_table.php diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 2af549fff..151a8d3f3 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -31,8 +31,8 @@ jobs: - name: Setup PHP with Composer uses: ./.github/actions/setup-php-composer with: - php-version: '8.3' - php-extensions: 'mbstring, bcmath, pdo_mysql' + php-version: '8.4' + php-extensions: 'mbstring, bcmath, pdo_sqlite, pdo_mysql' composer-flags: '--no-progress --prefer-dist --optimize-autoloader' - name: Prepare Laravel environment diff --git a/.github/workflows/quickstart.yml b/.github/workflows/quickstart.yml index f12109b54..55678b749 100644 --- a/.github/workflows/quickstart.yml +++ b/.github/workflows/quickstart.yml @@ -10,28 +10,28 @@ jobs: permissions: contents: read - # MySQL service commented out - smoke tests should not require database setup - # services: - # mysql: - # image: mariadb:10.6 - # env: - # MYSQL_DATABASE: testing - # MYSQL_ROOT_PASSWORD: root - # ports: - # - 3306:3306 - # options: >- - # --health-cmd="mysqladmin ping" - # --health-interval=10s - # --health-timeout=5s - # --health-retries=5 + services: + mariadb: + image: mariadb:10.11 + env: + MYSQL_DATABASE: invoiceplane_test + MYSQL_ROOT_PASSWORD: root + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping --silent" + --health-interval=10s + --health-timeout=5s + --health-retries=5 env: - # DB_CONNECTION: mysql - # DB_DATABASE: testing - # DB_USERNAME: root - # DB_PASSWORD: root - # DB_HOST: 127.0.0.1 APP_ENV: testing + DB_CONNECTION: mysql + DB_HOST: 127.0.0.1 + DB_PORT: 3306 + DB_DATABASE: invoiceplane_test + DB_USERNAME: root + DB_PASSWORD: root steps: - name: Checkout repository @@ -41,6 +41,7 @@ jobs: uses: ./.github/actions/setup-php-composer with: php-version: '8.4' + php-extensions: 'mbstring, xml, ctype, json, fileinfo, pdo, pdo_mysql, bcmath' composer-flags: '--prefer-dist --no-interaction' - name: Set up Node.js diff --git a/.github/workflows/smoke.yml b/.github/workflows/smoke.yml index ae4405b0c..e5d9f5e8f 100644 --- a/.github/workflows/smoke.yml +++ b/.github/workflows/smoke.yml @@ -4,6 +4,14 @@ permissions: contents: read on: + push: + branches: + - master + - develop + pull_request: + branches: + - master + - develop workflow_dispatch: jobs: @@ -11,8 +19,28 @@ jobs: name: Composer, migrations, and smoke tests runs-on: ubuntu-latest + services: + mariadb: + image: mariadb:10.11 + env: + MYSQL_DATABASE: invoiceplane_test + MYSQL_ROOT_PASSWORD: root + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping --silent" + --health-interval=10s + --health-timeout=5s + --health-retries=5 + env: APP_ENV: testing + DB_CONNECTION: mysql + DB_HOST: 127.0.0.1 + DB_PORT: 3306 + DB_DATABASE: invoiceplane_test + DB_USERNAME: root + DB_PASSWORD: root steps: - name: Checkout repository @@ -22,7 +50,7 @@ jobs: uses: ./.github/actions/setup-php-composer with: php-version: '8.4' - php-extensions: 'mbstring, xml, ctype, json, fileinfo, pdo, sqlite, mysql, bcmath' + php-extensions: 'mbstring, xml, ctype, json, fileinfo, pdo, pdo_mysql, pdo_sqlite, sqlite, bcmath' composer-flags: '--prefer-dist --no-interaction' - name: Prepare Laravel environment diff --git a/.github/workflows/yarn-update.yml b/.github/workflows/yarn-update.yml index 6e590adea..72bdd8b85 100644 --- a/.github/workflows/yarn-update.yml +++ b/.github/workflows/yarn-update.yml @@ -51,8 +51,8 @@ jobs: - name: Setup PHP with Composer uses: ./.github/actions/setup-php-composer with: - php-version: '8.2' - php-extensions: 'mbstring, xml, ctype, json, fileinfo, pdo, sqlite, mysql' + php-version: '8.4' + php-extensions: 'mbstring, xml, ctype, json, fileinfo, pdo, pdo_sqlite, pdo_mysql' - name: Check for package-lock.json conflicts id: lockfile-check diff --git a/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php b/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php index 8386f05a3..618623fa7 100644 --- a/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php +++ b/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php @@ -11,18 +11,13 @@ public function up(): void $table->id(); $table->unsignedBigInteger('company_id'); $table->unsignedBigInteger('invoice_id'); - $table->unsignedBigInteger('document_group_id')->nullable()->index('recurr_document_group_id_foreign'); + $table->unsignedBigInteger('document_group_id')->nullable()->index(); $table->string('frequency'); $table->date('start_at'); $table->date('end_at')->nullable(); $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); $table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); - $table->foreign('document_group_id', 'recurr_document_group_id_foreign') - ->references('id') - ->on('document_groups') - ->onUpdate('cascade') - ->onDelete('restrict'); }); } diff --git a/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php b/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php index e022fb3e7..0d184e139 100644 --- a/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php +++ b/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php @@ -11,7 +11,7 @@ public function up(): void $table->id(); $table->unsignedBigInteger('company_id'); $table->unsignedBigInteger('customer_id'); - $table->unsignedBigInteger('invoice_id')->nullable(); + $table->unsignedBigInteger('invoice_id')->nullable()->index(); $table->unsignedBigInteger('merchant_client_id')->nullable(); $table->string('payment_number')->nullable(); $table->string('payment_method'); diff --git a/Modules/ReportBuilder/Database/Migrations/2025_10_26_create_report_templates_table.php b/Modules/ReportBuilder/Database/Migrations/2025_10_26_create_report_templates_table.php deleted file mode 100644 index d935fa48d..000000000 --- a/Modules/ReportBuilder/Database/Migrations/2025_10_26_create_report_templates_table.php +++ /dev/null @@ -1,29 +0,0 @@ -id(); - $table->unsignedBigInteger('company_id'); - $table->boolean('is_system')->default(false); - $table->boolean('is_active')->default(true); - $table->string('template_type'); - $table->string('name'); - $table->string('slug'); - $table->string('filename')->nullable(); - - $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); - $table->unique(['company_id', 'slug']); - }); - } - - public function down(): void - { - Schema::dropIfExists('report_templates'); - } -}; From 427285dcd7678731a29152ac9c9b4bf28746bb65 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 10:18:29 +0000 Subject: [PATCH 2/3] fix: rename document_group_id to numbering_id, restore payments FK, drop SQLite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit recurring_invoices: - rename document_group_id → numbering_id; add FK to numbering table matching the same pattern invoices uses (onUpdate cascade, onDelete restrict) - update RecurringInvoiceFactory: Numbering instead of missing DocumentGroup - update RecurringInvoiceForm: numbering_id Select with relationship payments: - invoice_id is NOT NULL (payment requires an invoice) - restore explicit constraint name payments_invoice_id_foreign with onUpdate cascade / onDelete restrict testing env: - .env.testing.example: replace SQLite :memory: with MySQL settings - phpunit.yml: add MariaDB 10.11 service, set DB env vars, uncomment migration step so tests run against real MariaDB https://claude.ai/code/session_01Q4fwmdZcuFrrB6UQDeGWKd --- .env.testing.example | 8 +++- .github/workflows/phpunit.yml | 44 ++++++++++--------- .../Factories/RecurringInvoiceFactory.php | 4 +- ...000023_create_recurring_invoices_table.php | 7 ++- .../Schemas/RecurringInvoiceForm.php | 4 +- ...010_01_01_000024_create_payments_table.php | 8 +++- 6 files changed, 46 insertions(+), 29 deletions(-) diff --git a/.env.testing.example b/.env.testing.example index a02e670d4..c2eded317 100644 --- a/.env.testing.example +++ b/.env.testing.example @@ -21,8 +21,12 @@ LOG_DAILY_DAYS=7 LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug -DB_CONNECTION=sqlite -DB_DATABASE=:memory: +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=invoiceplane_test +DB_USERNAME=root +DB_PASSWORD=root SESSION_DRIVER=array SESSION_LIFETIME=120 diff --git a/.github/workflows/phpunit.yml b/.github/workflows/phpunit.yml index 151a8d3f3..96d83721c 100644 --- a/.github/workflows/phpunit.yml +++ b/.github/workflows/phpunit.yml @@ -10,20 +10,27 @@ jobs: phpunit: runs-on: ubuntu-latest - # MySQL service commented out - tests use SQLite in-memory instead - # services: - # mysql: - # image: mysql:8 - # env: - # MYSQL_ROOT_PASSWORD: root - # MYSQL_DATABASE: testing - # ports: - # - 3306:3306 - # options: >- - # --health-cmd="mysqladmin ping --silent" - # --health-interval=10s - # --health-timeout=5s - # --health-retries=3 + services: + mariadb: + image: mariadb:10.11 + env: + MYSQL_DATABASE: invoiceplane_test + MYSQL_ROOT_PASSWORD: root + ports: + - 3306:3306 + options: >- + --health-cmd="mysqladmin ping --silent" + --health-interval=10s + --health-timeout=5s + --health-retries=5 + + env: + DB_CONNECTION: mysql + DB_HOST: 127.0.0.1 + DB_PORT: 3306 + DB_DATABASE: invoiceplane_test + DB_USERNAME: root + DB_PASSWORD: root steps: - uses: actions/checkout@v4 @@ -32,7 +39,7 @@ jobs: uses: ./.github/actions/setup-php-composer with: php-version: '8.4' - php-extensions: 'mbstring, bcmath, pdo_sqlite, pdo_mysql' + php-extensions: 'mbstring, bcmath, pdo_mysql' composer-flags: '--no-progress --prefer-dist --optimize-autoloader' - name: Prepare Laravel environment @@ -40,11 +47,8 @@ jobs: cp .env.testing.example .env.testing php artisan key:generate --env=testing - #- name: Run Laravel migrations - # run: php artisan migrate --force --env=testing - - #- name: Run Laravel seeds (optional) - # run: php artisan db:seed --force --env=testing + - name: Run Laravel migrations + run: php artisan migrate --force --env=testing - name: Run PHPUnit run: php artisan test --env=testing diff --git a/Modules/Invoices/Database/Factories/RecurringInvoiceFactory.php b/Modules/Invoices/Database/Factories/RecurringInvoiceFactory.php index bfca16474..687cd4f98 100644 --- a/Modules/Invoices/Database/Factories/RecurringInvoiceFactory.php +++ b/Modules/Invoices/Database/Factories/RecurringInvoiceFactory.php @@ -6,7 +6,7 @@ use Modules\Clients\Enums\RelationType; use Modules\Clients\Models\Relation; use Modules\Core\Models\Company; -use Modules\Core\Models\DocumentGroup; +use Modules\Core\Models\Numbering; use Modules\Invoices\Models\Invoice; use Modules\Invoices\Models\RecurringInvoice; @@ -25,7 +25,7 @@ public function definition(): array 'company_id' => $company->id, 'customer_id' => Relation::query()->where('relation_type', RelationType::CUSTOMER->value)->inRandomOrder()->first()->id, 'invoice_id' => Invoice::query()->inRandomOrder()->first()->id, - 'document_group_id' => DocumentGroup::query()->inRandomOrder()->first()->id, + 'numbering_id' => Numbering::query()->inRandomOrder()->first()?->id, 'frequency' => fake()->word, 'start_at' => fake()->date(), 'end_at' => fake()->optional()->date(), diff --git a/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php b/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php index 618623fa7..c9289739c 100644 --- a/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php +++ b/Modules/Invoices/Database/Migrations/2010_01_01_000023_create_recurring_invoices_table.php @@ -11,13 +11,18 @@ public function up(): void $table->id(); $table->unsignedBigInteger('company_id'); $table->unsignedBigInteger('invoice_id'); - $table->unsignedBigInteger('document_group_id')->nullable()->index(); + $table->unsignedBigInteger('numbering_id')->nullable(); $table->string('frequency'); $table->date('start_at'); $table->date('end_at')->nullable(); $table->foreign('company_id')->references('id')->on('companies')->onDelete('cascade'); $table->foreign('invoice_id')->references('id')->on('invoices')->onDelete('cascade'); + $table->foreign('numbering_id', 'recurring_invoices_numbering_id_foreign') + ->references('id') + ->on('numbering') + ->onUpdate('cascade') + ->onDelete('restrict'); }); } diff --git a/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php b/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php index 78513cd46..3c9af5e5d 100644 --- a/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php +++ b/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php @@ -20,8 +20,8 @@ public static function configure(Schema $schema): Schema TextInput::make('invoice_id') ->required() ->numeric(), - TextInput::make('document_group_id') - ->numeric() + Select::make('numbering_id') + ->relationship('numbering', 'name') ->default(null), Select::make('frequency') ->options(RecurringFrequency::class) diff --git a/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php b/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php index 0d184e139..ecf6c887b 100644 --- a/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php +++ b/Modules/Payments/Database/Migrations/2010_01_01_000024_create_payments_table.php @@ -11,7 +11,7 @@ public function up(): void $table->id(); $table->unsignedBigInteger('company_id'); $table->unsignedBigInteger('customer_id'); - $table->unsignedBigInteger('invoice_id')->nullable()->index(); + $table->unsignedBigInteger('invoice_id'); $table->unsignedBigInteger('merchant_client_id')->nullable(); $table->string('payment_number')->nullable(); $table->string('payment_method'); @@ -22,7 +22,11 @@ public function up(): void $table->foreign('company_id')->references('id')->on('companies')->cascadeOnDelete(); $table->foreign('customer_id')->references('id')->on('relations')->restrictOnDelete(); - $table->foreign('invoice_id')->references('id')->on('invoices')->nullOnDelete(); + $table->foreign('invoice_id', 'payments_invoice_id_foreign') + ->references('id') + ->on('invoices') + ->onUpdate('cascade') + ->onDelete('restrict'); // $table->foreign('merchant_client_id')->references('id')->on('merchant_clients')->nullOnDelete(); }); } From 6fe3453605ffb21966766c864ba9caf00180fb25 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Fri, 5 Jun 2026 11:04:19 +0000 Subject: [PATCH 3/3] fix: apply CodeRabbit auto-fixes Fixed 1 file(s) based on 2 unresolved review comments. Co-authored-by: CodeRabbit --- .../Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php b/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php index 3c9af5e5d..61d669c0d 100644 --- a/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php +++ b/Modules/Invoices/Filament/Company/Resources/RecurringInvoices/Schemas/RecurringInvoiceForm.php @@ -21,6 +21,7 @@ public static function configure(Schema $schema): Schema ->required() ->numeric(), Select::make('numbering_id') + ->label(trans('ip.numbering')) ->relationship('numbering', 'name') ->default(null), Select::make('frequency')