Files
PackControl/pirp/CLAUDE.md

4.5 KiB

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:

  • invoicescustomers (customer_id foreign key)
  • invoice_itemsinvoices (invoice_id foreign key, CASCADE delete)
  • recurring_templatescustomers
  • recurring_template_itemsrecurring_templates (CASCADE delete)
  • recurring_logrecurring_templates, invoices

VAT modes: klein (Kleinunternehmer - VAT exempt) or normal (standard VAT).

Development Commands

# 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