Skip to main content

Arkkitehtuurin yleiskuva — Frontpics

Frontpics on TypeScript-monorepo, jossa on Next.js-verkkosovellus, NestJS-API, PostgreSQL/PostGIS-tietokanta, Redis/BullMQ-jono ja ajonaikaisesti valittava tiedostotallennus.

Ajonaikaiset osat

Selain
|
v
Next.js web (apps/web)
|
v
NestJS API (apps/api)
| |
v v
PostgreSQL/PostGIS Redis/BullMQ
|
v
StorageService
r2 | s3 | local

Tuotannossa sovellus ajetaan Docker Compose -pohjaisina blue/green-pinoina Nginxin takana. PostgreSQL ja Redis ovat jaettuja infrastruktuuripalveluja.

Verkkosovellus

apps/web sisältää:

  • julkisen etusivun ja kuvamarkkinapaikan;
  • ostajan krediitit, laskutuksen, kuvaustilaukset ja lataukset;
  • kuvaajan latauksen, keikat, kuvat, ansiot, tilitykset ja profiilin;
  • moderaattorin työkalut;
  • palkanlaskennan raportit;
  • ylläpidon.

Reittisuojaus ja lokalisointi kuuluvat tiedostoon apps/web/src/proxy.ts.

API

apps/api on NestJS 11 -sovellus Fastify-adapterilla.

Keskeiset moduulit:

  • auth ja users;
  • images ja upload;
  • orders, wallets, payouts ja invoices;
  • shooting requests;
  • admin;
  • feedback ja incoming emails;
  • storage;
  • queue/image processing;

Kaikki reitit ovat polun /api/v1 alla.

JWT-validointi palauttaa { id, email, role }. Palveluissa käytetään user.id.

Tietokanta

Prisma-skeema on tietokannan lähde. Tärkeitä malleja ovat:

  • User
  • PhotographerProfile
  • AgentProfile
  • Image
  • ImageFile
  • Location
  • Tag
  • Order / OrderItem
  • CreditWallet / CreditTransaction
  • Payout
  • ShootingRequest
  • AgencyBrand

Enum-arvot ovat pienellä kirjoitettua snake_case-muotoa, esimerkiksi pending_review.

Tallennus

Tiedostotallennus kulkee StorageService-kerroksen kautta. Aktiivinen backend määritetään Redisissä:

config:storage_backend = r2 | s3 | local

Olemassa olevat tiedostot pysyvät siinä backendissä, jossa ne luotiin. Muutos vaikuttaa uusiin tiedostoihin.

Kuvan lataus

Kuvaaja valitsee tiedostot
-> web lukee EXIF/hash-tiedot ja ratkaisee osoitteen/GPS:n
-> POST /upload/presigned
-> selain lataa tiedostot suoraan tallennukseen
-> POST /upload/check-duplicates
-> POST /upload/confirm metatiedoilla
-> API luo Image/Location/Tag-tietueet
-> API jonottaa BullMQ-käsittelyn
-> worker luo variantit ja ImageFile-tietueet
-> kuva siirtyy pending_review-tilaan
-> ylläpito hyväksyy kuvan aktiiviseksi

Osto

Ostaja valitsee yhden tai useamman kuvan
-> valinnainen laskutusviite
-> POST /orders
-> API tarkistaa saldon ja duplikaattiostot
-> transaktio luo Order/OrderItem-tietueet
-> ostajan lompakkoa veloitetaan
-> kuvaajan lompakkoa hyvitetään
-> lataukset avautuvat

Ostaminen toimii työpöydällä ja mobiilissa kuvan esikatselumodaalissa sekä ruudukon valintapalkissa.

Lataus ja brändäys

Ostaja avaa ostetun kuvan
-> GET /images/:id/download/:orderItemId
-> API palauttaa allekirjoitetun latausosoitteen ja toimistobrändin
-> web lisää tarvittaessa vesileiman ja kohdepinssin
-> lopullinen kuva latautuu selaimessa

Brändäys ratkaistaan keskitetysti AgencyBrand-mallista.

Kuvaustilaukset

Ostaja luo kuvaustilauksen
-> osoitehaku tai API-geokoodaus tallentaa koordinaatit
-> ostajalta ei varata tai vähennetä krediittejä
-> kuvaajat näkevät avoimet keikat listalla ja kartalla
-> kuvaaja ottaa keikan
-> kuvaaja merkitsee keikan valmiiksi
-> kuvaajan lompakkoa hyvitetään

Kuvaustilauksen valmistuminen ei luo tilitystä automaattisesti.

Tilitykset

Kuvaaja pyytää tilitystä
-> API tarkistaa pankkitiedot ja vähimmäissaldon
-> Payout(status=pending) luodaan
-> krediitit varataan/vähennetään
-> valinnainen kuvaajan viite tallennetaan linkitettyyn tapahtumaan
-> ylläpito näkee odottavan tilityksen ja viitteen
-> ylläpito merkitsee maksetuksi tai hylkää ja palauttaa krediitit

Operatiiviset jonot

Ylläpidon numeromerkit tulevat endpointista GET /admin/action-counts:

  • odottavat kuvat;
  • lukemattomat sähköpostit;
  • avoimet palautteet;
  • odottavat tilitykset.