Claude-skill-registry bewirtungsbeleg

Creates German tax-compliant entertainment expense receipts (Bewirtungsbelege) from restaurant receipts with automatic signature and original receipt attachment. The generated PDF contains the original receipt as page 1 and the signed Bewirtungsbeleg as page 2. Use when the user uploads a restaurant receipt/bill and wants to create a formal Bewirtungsbeleg PDF for German tax purposes, or when they mention "Bewirtungsbeleg", "Geschäftsessen", "steuerlich absetzbar", or similar business meal expense documentation needs.

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/bewirtungsbeleg" ~/.claude/skills/majiayu000-claude-skill-registry-bewirtungsbeleg && rm -rf "$T"
manifest: skills/data/bewirtungsbeleg/SKILL.md
source content

Bewirtungsbeleg Creator

This skill analyzes restaurant receipts and creates tax-compliant German Bewirtungsbeleg PDFs.

Setup

Before using this skill for the first time:

  1. Configure your details:

    cd skills/bewirtungsbeleg
    cp config.example.yml config.yml
    
  2. Edit

    config.yml
    and replace the placeholder with your information:

    gastgeber: "Your Name / Your Company Name"
    
  3. Add your signature:

    • Place your signature image as
      assets/signature.png
    • See
      assets/signature.example.png
      for reference
  4. Install dependencies:

    uv sync
    

The config file is gitignored to keep your personal information private when publishing this skill.

Workflow

Follow this exact sequence when the user provides a restaurant receipt:

Step 1: Analyze the Receipt

Extract the following information from the uploaded receipt image or PDF:

Required from receipt:

  • Restaurant name and full address
  • Date of the meal (Rechnungsdatum) - This will be used as "Datum der Bewirtung"
  • Location/City - Extract from restaurant address, this will be used as "Ort der Bewirtung"
  • Total amount including VAT (Gesamtbetrag/Bruttobetrag) - this is the only amount needed
  • Receipt/register number (Registriernummer or Rechnungsnummer)

Check carefully for tip (Trinkgeld) on receipt:

  • Look for any handwritten notes on the receipt mentioning "Trinkgeld", "Tip", "TG" or similar
  • Check for a separate line item labeled "Trinkgeld" on the receipt
  • Tips are often added by hand after the printed total
  • If the receipt shows TWO totals, the difference is likely the tip
  • Common patterns:
    • Original receipt shows €102, handwritten note "Trinkgeld €10", final amount €112
    • Receipt has printed "Summe: €102" and handwritten "Gesamt: €112"

Important about tips:

  • If you see ANY indication of a tip on the receipt, extract that amount
  • The
    gesamtbetrag
    in the JSON should be the FINAL total INCLUDING the tip
  • The
    trinkgeld
    field should contain the tip amount separately
  • If NO tip is visible, ask the user in Step 2

Optional from receipt:

  • Tax ID or VAT ID (Steuer-Nr. or USt-IdNr.) of the restaurant

Note:

  • The date and location from the receipt will be automatically used for the Bewirtungsbeleg
  • You only need the total amount (Gesamtbetrag) - no need to split into net and VAT amounts
  • The detailed itemization is on the original receipt which will be attached

Tax ID Format Recognition:

German tax IDs come in two formats:

  1. Steuernummer (Tax Number):

    • 10-11 digits, often with slashes:
      133/8150/8159
    • Or 13 digits without separators:
      5133081508159
    • Varies by Bundesland (federal state)
  2. Umsatzsteuer-Identifikationsnummer (VAT ID):

    • Always starts with "DE" followed by 9 digits
    • Format:
      DE123456789
    • Used for EU business transactions

Important: If no tax ID is found on the receipt, leave the field blank in the generated PDF. This is acceptable for tax purposes.

Step 2: Gather Additional Information

Ask the user for information not available on the receipt, but only if not part of the prompt already:

Always required:

  • Bewirtete Personen (Guests): Ask "Wer waren die bewirteten Personen?"

    • Collect full names
    • Company names are OPTIONAL - only ask if relevant or if the user mentions them
    • CRITICAL: THe host has to be added to the guest list as well
  • Anlass (Occasion): Ask "Was war der Anlass der Bewirtung?"

    • The occasion must clearly demonstrate business context
    • Vague answers like "Geschäftsessen" are NOT sufficient for tax purposes
    • Guide the user to provide specific details, for example:
      • "Projektbesprechung zur Implementierung des CRM-Systems mit Kunde XY"
      • "Vertragsverhandlung über Cloud-Migration-Projekt"
      • "Akquisegespräch mit potenziellem Neukunden"

Ask ONLY if not found on receipt:

  • Trinkgeld (Tip): If you did NOT find any indication of a tip on the receipt, ask "Wurde ein Trinkgeld gegeben? Falls ja, wie viel?"
    • If user says no tip was given, set trinkgeld to 0 in the JSON
    • If user provides a tip amount, add it to the receipt total for the final gesamtbetrag

Note: Date and location are automatically extracted from the receipt, so don't ask the user for these.

Step 3: Create JSON Data Structure

Prepare a JSON file with all collected information:

{
  "datum_bewirtung": "DD.MM.YYYY",  // Automatically from receipt date
  "ort_bewirtung": "City name",      // Automatically from restaurant address
  "gastgeber": "Full Name",          // Will use config.yml value if not provided in data
  "gaeste": [
    {
      "name": "Full Name",
      "unternehmen": "Company Name (optional)"
    },
    {
      "name": "Another Person"
    }
  ],
  "anlass": "Detailed business occasion",
  "restaurant_name": "Restaurant Name",
  "restaurant_adresse": "Full Address",
  "restaurant_steuernr": "Tax/VAT ID (optional)",
  "gesamtbetrag": 156.90,  // FINAL total INCLUDING tip (if any)
  "trinkgeld": 10.00       // Tip amount separately, use 0.0 if no tip
}

CRITICAL - Understanding gesamtbetrag and trinkgeld:

Example 1: Receipt WITH tip notation

  • Receipt shows: "Rechnung: 102,00 €"
  • Handwritten on receipt: "Trinkgeld: 10,00 €"
  • Your JSON should be:
    {
      "gesamtbetrag": 112.00,  // 102 + 10
      "trinkgeld": 10.00
    }
    

Example 2: Receipt WITHOUT tip notation, user confirms tip

  • Receipt shows: "Summe: 102,00 €"
  • User says: "Yes, I gave 10 euros tip"
  • Your JSON should be:
    {
      "gesamtbetrag": 112.00,  // Receipt + tip
      "trinkgeld": 10.00
    }
    

Example 3: No tip given

  • Receipt shows: "Summe: 102,00 €"
  • No tip notation, user confirms no tip
  • Your JSON should be:
    {
      "gesamtbetrag": 102.00,
      "trinkgeld": 0.0
    }
    

Important notes:

  • datum_bewirtung
    : Use the date from the receipt (Rechnungsdatum)
  • ort_bewirtung
    : Extract the city from the restaurant address
  • gastgeber
    : You can omit this field - the script will automatically use the value from config.yml
  • gesamtbetrag
    : ALWAYS the final total INCLUDING tip (if any)
  • trinkgeld
    : The tip amount separately; use 0.0 if no tip was given
  • Net amount and VAT are NOT needed - they're already on the restaurant receipt

Step 4: Generate the PDF

  1. Save the JSON data to a temporary file

  2. Save the uploaded original receipt to a temporary file (keep original format - PDF or image)

  3. Execute the PDF generation script:

    python3 scripts/create_bewirtungsbeleg.py \
      --json data.json \
      --output bewirtungsbeleg.pdf \
      --receipt /path/to/uploaded/receipt
    

    Note: The signature is automatically loaded from

    assets/signature.png
    - no need to specify
    --signature
    parameter

  4. The script will automatically:

    • Convert the receipt image to PDF if needed
    • Apply EXIF orientation correction to ensure the image is correctly oriented
    • Add the original receipt as the first page(s)
    • Create the Bewirtungsbeleg with the attached signature pre-filled
    • Add the signed Bewirtungsbeleg as the last page
    • Result: 2-page PDF (page 1 = original receipt, page 2 = signed Bewirtungsbeleg)
  5. Move the generated PDF to

    /mnt/user-data/outputs/

  6. Provide the download link to the user

Important:

  • The
    --receipt
    parameter must point to the uploaded receipt file from
    /mnt/user-data/uploads
  • Supported formats: PNG, JPEG, JPG, GIF, BMP, WebP, TIFF, TIF, HEIC, HEIF, and PDF
  • All color modes supported: RGB, RGBA, CMYK, Grayscale, Palette, LAB, YCbCr, HSV
  • The receipt can be a photo, scan, or PDF
  • The signature is automatically included - stored in
    assets/signature.png
  • The final PDF will have 2+ pages: original receipt first, then the signed Bewirtungsbeleg

Step 5: Provide Instructions

After creating the PDF, inform the user:

Document structure:

  • Page 1: Original restaurant receipt
  • Page 2: Signed Bewirtungsbeleg (with automatic signature)

What's already done:

  • ✅ Signature is already included automatically
  • ✅ Original receipt is attached as first page
  • ✅ Date and location are filled in

User actions:

  • Print the complete PDF and file for tax records
  • No manual signature needed - it's already signed!

Tax note:

  • Business meal expenses are only 70% tax-deductible in Germany

Important Notes

Tax Compliance Requirements

  • The receipt must be machine-generated (not handwritten)
  • Must contain a receipt/register number
  • Itemization of food/beverages is required
  • For receipts over €250, the company name must be on the receipt
  • The occasion must clearly demonstrate business connection
  • Tax ID (Steuer-Nr. or USt-IdNr.) is helpful but not mandatory if missing

For detailed tax requirements, see

references/steuerliche_anforderungen.md
.

Common Issues

Insufficient occasion description:

  • ❌ Bad: "Geschäftsessen", "Besprechung"
  • ✅ Good: "Projektbesprechung CRM-Implementation mit XY GmbH", "Vertragsverhandlung Cloud-Migration"

Missing information:

  • If critical information is missing from the receipt (amounts, itemization), inform the user and explain what's needed
  • If the tax ID is missing, that's acceptable - the field will be left blank on the Bewirtungsbeleg

Tips (Trinkgeld):

  • Tips must be noted separately as they're usually not on the receipt
  • Should be noted on the receipt and signed by the restaurant
  • Must be included in the Bewirtungsbeleg

Resources

Scripts

  • scripts/create_bewirtungsbeleg.py
    - Generates the PDF from JSON data, merges with original receipt, and adds signature

References

  • references/steuerliche_anforderungen.md
    - Complete German tax requirements for Bewirtungsbelege

Assets

  • assets/signature.png
    - (automatically included in generated PDFs)