Poptavka z webu je ticket, prilohy, udaje provozovatele, kolacovy graf
Provozovatel portalu: firma s priznakem portalOperator (jen jedna, zapnuti odebere ostatnim) a novymi poli contactEmail, contactPhone, website vedle ico, dic, adresy a pravni formy. Verejny GET /api/public/brand vraci jeji udaje a web je bere pres useBrand() na kontaktu, v paticce, O nas, prihlaseni i v titulku; brand.ts je jen zaloha. Poptavka z webu zaklada u provozovatele ticket kanalu form: predmet "Poptavka: tema", telo JSON s poli formulare, tag Poptavka plus tema, zakaznik z formulare, poznamka v logu. Bez provozovatele se jen zaloguje. Prilohy ticketu: formular az 3 soubory po 5 MB, ticket az 10; nahrani, seznam, stazeni a smazani (pravo ticket.comment, strop viditelnosti, poznamky v logu, audit). Soubor jde v JSON jako Base64 a lezi v beznem ulozisti, bez nove zavislosti; strop tela jen na techto cestach. Vlastni widget s kreslenim Graf umi i pocet ticketu se seskupenim jako kolac (PieChart.tsx, ciste SVG, osm barev z tokenu, zbytek jako ostatni). OpenAPI rozdelene na mensi soubory (102 cest, 28 schemat overeno shodnych), 28 novych testu (135 celkem), dokumentace aktualizovana.
This commit is contained in:
@@ -231,6 +231,96 @@ do korene a zaloguje - ztratit radek logu je horsi nez ho ukazat spatne zanoreny
|
||||
Komentare jsou taky zaznamy logu (`kind: 'note'`). Diky tomu je vsechno na jedne
|
||||
casove ose a nemusi se nikde skladat dohromady dva ruzne seznamy.
|
||||
|
||||
Prilohy do logu zapisuji taky `note`: `Příloha: nazev (velikost)` pri nahrani,
|
||||
`Příloha odebrána: nazev` pri smazani (`noteAttachment`
|
||||
v `src/data/tickets/store.ts`). Radek v logu je jedine, co ticket o priloze
|
||||
vi - soubor sam lezi jinde, viz nize.
|
||||
|
||||
## Prilohy
|
||||
|
||||
`src/data/attachments.ts`, typ `Attachment` v `src/shared/attachments.ts`
|
||||
|
||||
Priloha je soubor, ktery prisel s poptavkou z webu nebo ho nekdo pripojil
|
||||
v detailu ticketu. **Neni to pole ticketu.** `Ticket` o prilohach nic nenese,
|
||||
lezi ve vlastni kolekci `attachment` obecneho uloziste a vazou se pres
|
||||
`ticketId` a `tenantId`:
|
||||
|
||||
```ts
|
||||
interface Attachment {
|
||||
id: string; // att_xxxxxxxx
|
||||
tenantId: string; // firma ticketu, hranice viditelnosti
|
||||
ticketId: string;
|
||||
name: string; // bez cesty a ridicich znaku, nejvys 200 znaku
|
||||
mime: string; // neznamy = application/octet-stream
|
||||
size: number; // bajty po dekodovani
|
||||
uploadedBy: string | null; // ucet; null = prisla z verejneho formulare
|
||||
createdAt: string;
|
||||
}
|
||||
```
|
||||
|
||||
Proc vlastni kolekce a ne pole na ticketu:
|
||||
|
||||
| Duvod | Co by se stalo s polem na ticketu |
|
||||
| --------------------------- | -------------------------------------------------------------- |
|
||||
| obsah je velky | kazde cteni seznamu ticketu by taha megabajty base64 |
|
||||
| meni se nezavisle | nahrani souboru by prepisovalo cely ticket a soutezilo s komentari |
|
||||
| seznam se vraci bez obsahu | obsah jde jen pres `/attachments/:id/content`, ne v detailu |
|
||||
|
||||
Obsah se uklada jako **base64 uvnitr zaznamu**. Zadna nova zavislost (multer,
|
||||
S3 klient): prototyp ma ulozit jednotky MB a obecne uloziste to zvladne.
|
||||
Cenou je, ze v rezimu `file` kazda zmena prepise cely `attachment.json`.
|
||||
Az to zacne byt znat, presune se obsah do blob uloziste; rozhrani modulu
|
||||
zustane, zmeni se jen odkud `getAttachment` cte `content`.
|
||||
Viz [14-databaze.md](14-databaze.md).
|
||||
|
||||
Limity: 5 MB na soubor (`MAX_ATTACHMENT_BYTES`), 10 na ticket
|
||||
(`MAX_ATTACHMENTS_PER_TICKET`). `checkUploads` je cista funkce nad celou
|
||||
davkou: kdyz neprojde treti soubor, neulozi se ani prvni dva, jinak by klient
|
||||
nevedel, co uz tam je. Kontaktni formular ji vola **pred** zalozenim ticketu,
|
||||
aby po chybe nezustala poptavka bez souboru, ktere k ni patrily.
|
||||
|
||||
Nazev projde `sanitizeName`: bere se jen cast za poslednim lomitkem,
|
||||
ridici znaky se vyhodi. Klient posila, co chce - `../../etc/passwd` nebo
|
||||
nazev s novym radkem, ktery by rozbil hlavicku `Content-Disposition`.
|
||||
|
||||
Kazde nahrani a smazani zapise radek do logu ticketu, posune `updatedAt`
|
||||
a posle `ticket.updated`, aby se detail v portalu prekreslil stejne jako po
|
||||
komentari. Pravo je `ticket.comment` za firmu ticketu: priloha je jen dalsi
|
||||
zprava k ticketu. API je v [04-api.md](04-api.md), portal ma sekci
|
||||
`TicketAttachments` v detailu ticketu.
|
||||
|
||||
Mazani ticketu dnes neexistuje, proto tu neni kaskada. Az pribude, patri
|
||||
do `attachments.ts` `removeAttachmentsOfTicket(ticketId)`.
|
||||
|
||||
## Poptavka z webu
|
||||
|
||||
`src/routes/contact.ts`
|
||||
|
||||
Kontaktni formular na verejnem webu je **kanal `form`** jako kazdy jiny:
|
||||
`POST /api/contact` zalozi ticket firme, ktera je provozovatelem portalu
|
||||
(`operatorTenant`, viz [07-firmy-a-prava.md](07-firmy-a-prava.md)). Driv se
|
||||
poptavka jen zalogovala a nikdo ji nevidel.
|
||||
|
||||
| Pole ticketu | Hodnota |
|
||||
| ---------------- | ------------------------------------------------------------- |
|
||||
| `channel` | `form` |
|
||||
| `subject` | `Poptávka: <tema>` (automatizace, voicebot, integrace, dashboard, podpora, jine) |
|
||||
| `body` | JSON formulare: `name`, `email`, `company`, `phone`, `topic`, `message`, `receivedAt` |
|
||||
| `tags` | `Poptávka` a tema |
|
||||
| `customer` | `id` null, `company` a `contact` z formulare, `reply` = e-mail |
|
||||
| `externalSource` | `web-form`, `externalId` null |
|
||||
| `createdById` | null |
|
||||
| `trace` | `note` "Poptávka z webového formuláře" s odesilatelem a tematem |
|
||||
|
||||
Telo je JSON, ne veta, zamerne: `TicketBody` ho ukaze jako tabulku klic
|
||||
a hodnota (viz vyse "Obsah se na detailu cte") a zadne pole formulare se
|
||||
neztrati v prose. Prilohy z formulare (nejvys 3) se ulozi pres
|
||||
`addAttachments` s `uploadedBy` null.
|
||||
|
||||
Bez provozovatele se poptavka jen zaloguje (warn) a odpoved je porad 202:
|
||||
zvenku nema byt poznat, jak je portal nastaveny. Upozorneni e-mailem na novou
|
||||
poptavku zatim neni, resitel ji vidi az v seznamu ticketu.
|
||||
|
||||
## Opakovana udalost
|
||||
|
||||
Odesilatele umi poslat stejnou zpravu i osmdesatkrat za minutu. Kdyz prijde
|
||||
@@ -509,5 +599,6 @@ to rozhodnout vedome, ne omylem. Varianty od nejlevnejsi:
|
||||
| `inputs` u zbylych konektoru | zatim ticket, kanaly, CRM a AI, ostatni maji jen napovedu |
|
||||
| Napojeni logu na beh | `automationId` je odkaz, historie behu ale neexistuje |
|
||||
| Odpoved zakaznikovi z detailu | akce `send` u kanalu se z portalu nevola |
|
||||
| Upozorneni na poptavku z webu | ticket vznikne, ale nikomu neprijde e-mail |
|
||||
| SLA a eskalace | zadne lhuty, `capacity` je jen orientacni |
|
||||
| Databaze | data v pameti, restart je vrati na vychozi sadu |
|
||||
|
||||
Reference in New Issue
Block a user