# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview PIRP (Packed Internes Rechnungsprogramm) is a simple internal invoicing application written in PHP. It's a German-language business tool for managing invoices, customers, expenses, recurring subscriptions, and generating EÜR (Einnahmen-Überschuss-Rechnung / income-expenditure accounting) reports. ## Tech Stack - **PHP** (vanilla, no framework) - **PostgreSQL** database - **Dompdf** for PDF invoice generation - **Session-based authentication** - **SMF-style UI theme** (CSS with gradients, tabs) ## Architecture ``` /var/www/pirp/ ├── public/ # Web-accessible files (document root) │ ├── assets/ # CSS (style.css - SMF-style theme) │ ├── uploads/ # User-uploaded files │ │ ├── logos/ # Company logos │ │ ├── expenses/# Expense receipts (PDFs) │ │ └── invoices/# Archived invoice PDFs (GoBD-compliant) │ └── *.php # Page controllers ├── src/ # Business logic (not web-accessible) │ ├── config.php # Database credentials, BASE_URL, session setup │ ├── db.php # PDO connection singleton (get_db()) │ ├── auth.php # Login/logout/require_login functions │ ├── invoice_functions.php # Settings + invoice number generation │ ├── customer_functions.php # Customer CRUD │ ├── expense_functions.php # Expense CRUD │ ├── pdf_functions.php # GoBD-compliant PDF archiving │ └── recurring_functions.php # Subscription invoice management ├── tools/ # CLI utilities │ ├── hash.php # Password hash generator │ ├── migrate_pdf.sql # DB migration for PDF archiving │ ├── migrate_pdfs.php # Migrate existing invoices to archived PDFs │ └── migrate_recurring.sql # DB migration for subscriptions ├── schema.sql # Full database schema └── vendor/ # Composer dependencies ``` ## Database PostgreSQL with tables: `users`, `settings`, `customers`, `invoices`, `invoice_items`, `expenses`, `recurring_templates`, `recurring_template_items`, `recurring_log`. See `schema.sql` for complete schema. Key relationships: - `invoices` → `customers` (customer_id foreign key) - `invoice_items` → `invoices` (invoice_id foreign key, CASCADE delete) - `recurring_templates` → `customers` - `recurring_template_items` → `recurring_templates` (CASCADE delete) - `recurring_log` → `recurring_templates`, `invoices` VAT modes: `klein` (Kleinunternehmer - VAT exempt) or `normal` (standard VAT). ## Development Commands ```bash # Install dependencies composer install # Generate password hash for new user php tools/hash.php YOUR_PASSWORD # Initialize database (fresh install) psql -U pirp_user -d pirp -f schema.sql # Apply migrations (existing database) psql -U pirp_user -d pirp -f tools/migrate_pdf.sql psql -U pirp_user -d pirp -f tools/migrate_recurring.sql # Migrate existing invoices to archived PDFs php tools/migrate_pdfs.php ``` ## Configuration Database connection in `src/config.php`. Set `BASE_URL` if running in a subdirectory (e.g., `/pirp`). ## Key Patterns - All public pages include `require_login()` from `src/auth.php` - Database access via `get_db()` singleton returning PDO instance - Invoice numbers: `PIRP-YYYY-NNNNN` (auto-generated) - Customer numbers: `PIKN-NNNNNN` (auto-generated) ## GoBD-Compliant PDF Archiving German tax law (GoBD) requires invoices to be stored immutably. PDFs are: - Generated once at invoice creation - Stored in `public/uploads/invoices/{year}/` - Protected with chmod 444 - Verified via SHA-256 hash stored in `invoices.pdf_hash` Key functions in `src/pdf_functions.php`: - `archive_invoice_pdf($id)` - Generate and store PDF - `get_archived_pdf_path($id)` - Get path to archived PDF - `verify_invoice_pdf($id)` - Verify integrity via hash ## Recurring Invoices (Subscriptions) Subscription invoices for recurring customers with intervals: - `monthly` - Every month - `quarterly` - Every 3 months - `yearly` - Every year Key pages: - `recurring.php` - Overview of subscription templates - `recurring_edit.php` - Create/edit templates - `recurring_generate.php` - Generate due invoices Key functions in `src/recurring_functions.php`: - `get_pending_recurring_invoices()` - Get due subscriptions - `generate_invoice_from_template($id)` - Create invoice from template - `calculate_next_due_date($interval, $date)` - Calculate next due date