File size: 3,646 Bytes
14a9fcd
f440d27
 
 
 
14a9fcd
f440d27
14a9fcd
f440d27
 
14a9fcd
 
f440d27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
---
title: OmniParse AI
emoji: 
colorFrom: purple
colorTo: indigo
sdk: gradio
sdk_version: 5.49.1
app_file: app.py
pinned: true
license: mit
---

# OmniParse AI — Invoice Processing SaaS

B2B SaaS pro automatické zpracování faktur. Nahraješ PDF/obrázek faktury, AI vytáhne
vendor, čísla faktur, data, částky a DPH, a exportuješ do CSV/JSON/Excel nebo napojíš
přes REST API.

## Jak to spustit

1. Nahraj `app.py`, `requirements.txt`, `packages.txt` a tento `README.md` do HuggingFace Space
   se SDK **Gradio**.
2. V **Settings → Variables and Secrets** nastav secrets podle tabulky níže.
3. Pin Space (⋯ → Pin this Space), ať nespí.

### Secrets

| Secret | Popis | Povinné? |
|---|---|---|
| `HF_TOKEN` | HuggingFace token pro fallback AI (Mistral-7B) | Doporučeno |
| `GROQ_API_KEY` | Primární AI extrakce (Llama 3.1 přes Groq) | Ano |
| `SUPABASE_URL` | URL Supabase projektu | Ano (jinak SQLite fallback) |
| `SUPABASE_KEY` | anon public key Supabase | Ano (jinak SQLite fallback) |
| `GOOGLE_VISION_KEY` | Google Cloud Vision OCR | Volitelné |
| `STRIPE_SECRET_KEY` | Stripe secret key (test/live) | Pro platby |
| `STRIPE_PRICE_BASIC` | Stripe Price ID pro Basic plán | Pro platby |
| `STRIPE_PRICE_PRO` | Stripe Price ID pro Pro plán | Pro platby |
| `STRIPE_PRICE_ENTERPRISE` | Stripe Price ID pro Enterprise plán | Pro platby |
| `APP_URL` | Veřejná URL Space (pro Stripe redirect) | Pro platby |

Aplikace se **nikdy nezhroutí** kvůli chybějícímu secretu — každá vrstva má fallback:

- Bez `GROQ_API_KEY` → zkusí HF Inference API → pak regex parser.
- Bez `SUPABASE_URL`/`KEY` → přepne na lokální SQLite (`omniparse.db`), data nejsou
  perzistentní mezi restarty Space.
- Bez `GOOGLE_VISION_KEY` → jen Tesseract OCR.
- Bez `STRIPE_SECRET_KEY` → tlačítko Upgrade zobrazí instrukce místo Checkout linku.

### Supabase schéma

Pokud používáš Supabase, spusť v **SQL Editor** tento skript před prvním spuštěním appky:

```sql
CREATE TABLE users (
    id          BIGSERIAL PRIMARY KEY,
    email       TEXT UNIQUE NOT NULL,
    name        TEXT NOT NULL,
    password    TEXT NOT NULL,
    plan        TEXT NOT NULL DEFAULT 'free',
    stripe_cid  TEXT,
    api_key     TEXT,
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE sessions (
    token       TEXT PRIMARY KEY,
    user_id     BIGINT NOT NULL REFERENCES users(id),
    expires_at  TIMESTAMPTZ NOT NULL
);

CREATE TABLE invoices (
    id           BIGSERIAL PRIMARY KEY,
    user_id      BIGINT NOT NULL REFERENCES users(id),
    filename     TEXT NOT NULL,
    vendor       TEXT,
    inv_number   TEXT,
    inv_date     TEXT,
    due_date     TEXT,
    amount       NUMERIC(12,2),
    vat_amount   NUMERIC(12,2),
    total        NUMERIC(12,2),
    currency     TEXT DEFAULT 'USD',
    status       TEXT DEFAULT 'done',
    is_duplicate BOOLEAN DEFAULT FALSE,
    confidence   NUMERIC(4,3),
    raw_json     JSONB,
    created_at   TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_invoices_user_month ON invoices(user_id, created_at);
```

### Demo účet

Při prvním startu se automaticky vytvoří:

- Email: `demo@omniparse.ai`
- Heslo: `demo1234`
- Plán: Pro

## Poznámky k platbám

Stripe integrace zde funguje **bez webhooků** — po návratu ze Stripe Checkout uživatel
v záložce "⚡ Upgrade" vloží `session_id` z URL a klikne "Ověřit platbu", což zavolá
`stripe.checkout.Session.retrieve()` a upgraduje plán v DB. Pro produkční nasazení
doporučujeme doplnit skutečný webhook endpoint, tahle verze je zjednodušená podle
původního zadání ("bez webhooků").