Crea la tua prima app
Alla fine di questo tutorial avrai un piccolo CRM con tre tabelle (company,
contact, deal), una pagina lista-e-dettaglio per ciascuna, un
Business Event che marca automaticamente updated_at del deal, e uno Script
Module che ricalcola il valore totale dei deal aperti della company ogni volta che un
deal cambia. Ogni concetto da Concetti chiave compare almeno
una volta.
Si presume tu abbia finito Per iniziare e che tu abbia un ambiente Archestack aperto in un'altra tab. Tempo totale: circa 45 minuti se leggi con attenzione, 25 se scorri.
Convenzioni usate qui: i nomi di tabelle e colonne sono snake_case (la
piattaforma suggerisce questa convenzione nel campo "Table name" di Schema Designer). Gli
esempi di codice usano la vera API Db, vedi
Reference -> API chiamabili dagli script per la
superficie completa.
Passo 1 - Progetta lo schema (10 min)
Apri Schema Designer e aggiungi tre tabelle.
Per ogni tabella: fai clic su Add Table nella toolbar, digita il nome nel
campo "Table name" del dialog, fai clic su Create. La nuova tabella appare
sul canvas con una primary key SERIAL id auto-generata (bloccata). Il pannello
destro si apre sulla tab Columns, aggiungi colonne aggiuntive dal box "Add column" con
bordo tratteggiato in basso. Fai clic su ogni colonna per espanderla e aggiustare i toggle
(PK / NULL / UQ), la Length, e il Default value.
Tabella: company
id- SERIAL, PK (auto)name- VARCHAR(200), requiredindustry- VARCHAR(80), nullableopen_deal_value- DECIMAL, default0- tenuto in sync via lo script al Passo 5created_at- TIMESTAMPTZ, defaultnow()
Tabella: contact
id- SERIAL, PK (auto)first_name,last_name- VARCHAR(100), requiredemail- VARCHAR(200), required, UQ attivacompany_id- INTEGER, required - foreign key, configurato sotto
Tabella: deal
id- SERIAL, PK (auto)company_id- INTEGER, required - foreign key, configurato sottotitle- VARCHAR(200), requiredstage- VARCHAR(40), required, default'New'- valori: New, Qualified, Proposal, Won, Lostamount- DECIMAL, required, default0created_at,updated_at- TIMESTAMPTZ, defaultnow()
Foreign key
Le foreign key vivono nella tab Relations del pannello destro. Seleziona
la tabella contact, passa a Relations, scorri fino alla sezione
"Add relationship":
- FK column (on this table) =
company_id - Relation type =
One-to-Many - References -> table =
company - References -> column =
id - Fai clic su Add Relationship.
Ripeti per la tabella deal (il suo company_id -> company.id).
company / contact / deal avrà la stessa forma con due linee FK che puntano a company.)Deploy
Fai clic su Deploy nella toolbar di Schema Designer. Atterri sulla pagina
di configurazione del deployment. Passa alla tab Generated SQL, dovresti
vedere tre istruzioni CREATE TABLE più i vincoli FK. Fai clic su
Deploy in alto a destra.
Cosa vedrai se funziona: la riga del deployment in Database Deployments -> Overview va da "Executing" a "Succeeded" in pochi secondi. Le tre tabelle appaiono nella lista tabelle di Object Browser.
Se il deploy fallisce sui vincoli FK: il Generated SQL emette le tabelle nell'ordine in cui sono state salvate. Apri la tab SQL e riordina così checompanysia creata prima dicontactedeal, poi rideploy. Oppure fai clic su Regenerate dopo aver riordinato manualmente le tabelle nel canvas di Schema Designer.
Passo 2 - Componi le Business Entities (10 min)
Ogni pagina ha bisogno di una Business Entity a cui collegarsi. Apri Business Entities e fai clic su Create per ciascuna. Premi Run Preview dopo ogni salvataggio per confermare che le colonne tornino correttamente.
BE: company
Entity Name company, Master Table company, Label Column
name. Salva.
Fai clic su Add Join due volte per aggiungere due join aggregati:
-
Join a
contact: From columncompany.id, To columncontact.company_id. Sposta Aggregate Mode su ON. Scegli la colonnaid, imposta Aggregate Function =COUNT, nominalacontact_count. -
Join a
deal: From columncompany.id, To columndeal.company_id. Aggregate Mode su ON. Scegli la colonnaid, funzioneCOUNT, nominalaopen_deal_count. (Filtreremo ai deal "aperti" tramite un Business Event al Passo 5; per ora conta tutti i deal.)
BE: contact
Entity Name contact, Master Table contact, Label Column
email. Aggiungi un Join a company via
contact.company_id -> company.id, esponi la colonna name come
company_name. (Non abilitare Aggregate Mode qui, è un join normale.)
BE: deal
Entity Name deal, Master Table deal, Label Column
title. Aggiungi un Join a company via
deal.company_id -> company.id, esponi la colonna name come
company_name.
Verifica: su ogni BE, fai clic su Run Preview. Vedrai una griglia vuota (nessun dato ancora) con le intestazioni di colonna che hai definito. Se un'intestazione di colonna joined manca, probabilmente hai dimenticato di spuntare la colonna nel picker di colonne del join. Riapri il join, spunta la colonna, salva, esegui di nuovo la preview.
Passo 3 - Costruisci le pagine (10 min)
Apri Page Editor. Per ogni Business Entity, fai clic su Create:
- Companies - Page Name
Companies, Page Route/companies, Business Entitycompany. La tab Visual auto-genera una lista e un form di dettaglio. Nel form di dettaglio, fai clic su Add Tab due volte per aggiungere le tab Contacts e Deals. In ogni tab, aggiungi una sezione RelatedGrid collegata alla BE contact / deal con il filtro di join impostato su company.id = current record's id. - Contacts - Page Name
Contacts, Page Route/contacts, Business Entitycontact. Il campocompany_iddel form di dettaglio auto-generato apparirà come numero, cambia il suo Type in Select e imposta l'autocomplete Entity sucompanycosì gli utenti scelgono una company per nome. - Deals - Page Name
Deals, Page Route/deals, Business Entitydeal. Stesso trattamento percompany_id(TypeSelect, Entitycompany). Perstage, lascia Type comeTextper ora, i valori possono essere imposti tramite un eventValidatepiù tardi se vuoi.
Per ogni pagina, sposta lo switch Published nell'header in alto su ON.
Le pagine appaiono nella sidebar sotto una sezione APPLICATION (raggruppate
per categoria). Aggiungi una Company, poi un Contact legato a quella Company, poi un Deal,
conferma che le relazioni si renderizzino correttamente. La pagina Companies ora dovrebbe
mostrare 1 in contact_count.
company. Nota: la sezione APPLICATION della sidebar appare non appena pubblichi, le pagine sono raggruppate sotto un'intestazione di categoria (qui: CUSTOMER PORTAL). Il pannello di dettaglio renderizza breadcrumb, un pulsante Edit (in alto a destra), icone pencil per campo per edit inline, tab aggiuntive in cima (Details / Vehicles / ecc.), e sotto il form una sezione griglia correlata che tira righe da un'altra BE filtrata per il record corrente. Il badge campanella ("1") mostra che c'è un errore di Event Log non letto. Se qualcosa sembra vuoto: la causa più comune è dimenticare di spostare lo
switch Published, se è OFF, navigare su /companies nella sidebar non mostra
niente. Spostalo su ON e fai refresh.
Passo 4 - Pulisci un campo al salvataggio con un Business Event (5 min)
I Business Events eseguono un po' di logica non appena un record viene scritto. Il più piccolo
utile: rimuovere gli spazi superflui dal title di un deal a ogni salvataggio, così
che " Acme renewal " diventi "Acme renewal". Mettiamolo in piedi.
Percreated_at/updated_at/created_by/updated_bynon ti serve mai una regola. Archestack aggiunge quelle quattro colonne di audit a ogni tabella e le marca a ogni insert e update automaticamente, quindi un trigger "marca updated_at" non farebbe che duplicare un lavoro che la piattaforma già svolge.
- Apri Business Events -> Create.
- Rule Name:
Normalize deal.title. Sposta Enabled su ON. - Business Entity:
deal. Triggers: spunta Before Update. - Nessuna condizione, scatta su ogni update.
-
Aggiungi un'action: scegli Execute Script. Il corpo dello script dell'action:
string title = Entity.title; Entity.title = title?.Trim(); -
Fai clic sulla tab Simulate -> scegli qualsiasi Deal esistente -> fai clic
su Run Simulation. Il pannello di output mostra che lo script è girato
con successo e a cosa è stato impostato
Entity.title. (Nessuna scrittura reale avviene, la simulazione gira in una transazione che viene rollback.) - Salva. Testa modificando un Deal con spazi iniziali o finali nel titolo, il titolo dovrebbe tornare ripulito a ogni salvataggio.
Perché Before Update + Execute Script invece di un'action che
"imposta un campo"? Archestack non ha un'action discreta "Set field". Il modo in
cui muti un record da un trigger è assegnare a Entity.column_name dentro un
Execute Script su un timing Before*. La piattaforma persiste l'Entity modificato
come parte della scrittura in corso, nessuna query extra, nessun rischio di ricorsione.
Passo 5 - Ricalcola company.open_deal_value con uno Script Module (10 min)
Un totale calcolato come "valore deal aperti per company" è troppo dinamico perché una colonna salvata resti accurata a mano. La terremo in sync con un piccolo script che rigira ogni volta che un deal su una company viene inserito, aggiornato o eliminato.
Scrivi lo script
Apri Script Modules -> Create. Nominalo
RecalcCompanyOpenDealValue.
Passa alla tab Parameters. Fai clic su Add. Name
company_id, Type int, Required spuntato.
Torna alla tab Edit. Corpo:
var openDeals = await Db.From("deal")
.Where("company_id", "=", company_id)
.Where("stage", "!=", "Won")
.Where("stage", "!=", "Lost")
.ToListAsync();
decimal total = 0;
foreach (var d in openDeals) total += (decimal)(d.amount ?? 0);
await Db.UpdateAsync("company", company_id, new { open_deal_value = total });
return total;
Passa alla tab Test. Digita un company_id reale dalla tua
pagina Companies nell'input del parametro, fai clic su Run. L'output mostra
il valore di ritorno (il totale) e un indicatore di successo. Ricarica la pagina Companies,
open_deal_value su quella company ora è in sync.
Inciampi comuni:
- Dimenticare
awaitsu.ToListAsync(), lo script compila maopenDealsfinisce per contenere unTask, non le righe. L'errore nel pannello Test menzionerà "cannot be enumerated".- Usare
Db.Queryinvece diDb.From, non c'è un metodoQuery. Attieniti aDb.From(table)per le query concatenate e aDb.GetAsync(table, id)per single-row-by-PK.- Provare
.SumAsync(...), non esiste. Fetch + sum in C#, come sopra.
Collegalo a un Business Event
- Apri Business Events -> Create.
- Rule Name:
Recalc company.open_deal_value on deal change. Enabled ON. - Business Entity:
deal. Triggers: spunta After Create, After Update, e Before Delete. - Nessuna condizione, scatta su ogni cambio.
-
Aggiungi un'action: Execute Script. Corpo:
var entity = OldEntity != null && OldEntity.company_id != null ? OldEntity // for delete & update, OldEntity has the original company_id : Entity; // for create, only Entity is populated await Modules.CallAsync("RecalcCompanyOpenDealValue", new Dictionary<string, object?> { ["company_id"] = entity.company_id }); - Salva. Modifica l'
amountdi un Deal e ricarica la pagina Company, il totale resta in sync.
Perché chiamarlo tramite Modules invece di inserire la logica direttamente nello script di questo trigger? Due motivi. Primo, il ricalcolo è riutilizzabile, puoi chiamarlo anche da uno Scheduled Event (catch-up notturno) o direttamente dal front end. Secondo, isola la logica in un singolo posto con un nome, più facile da testare, più facile da trovare dopo.
Passo 6 - Impacchettalo come package (5 min)
Hai costruito un vero mini-CRM funzionante. Impacchettalo così puoi spostarlo in un altro ambiente.
- Apri Packages -> Create. Nominalo
MiniCRM v1. - Aggiungi le tre Pages. Apri il pannello degli item collegati per vedere il cascade: il package porterà le BE che le pagine referenziano, le tabelle sorgente da cui quelle BE leggono, più i due Business Event e lo Script Module che le toccano.
- Despunta qualsiasi cosa preferiresti omettere, tipicamente terresti tutto per un tutorial come questo.
- Fai clic su Export -> scarica lo ZIP.
Importare lo ZIP in un ambiente diverso ricrea tutto (assumendo che lo schema sia deployato prima). E' così che i partner spediscono configurazioni specifiche per verticale e come promuoveresti il lavoro da un trial a un ambiente a pagamento più tardi.
Riepilogo - cosa è appena successo
- Hai progettato uno schema, l'hai deployato come tabelle PostgreSQL reali, e non hai mai scritto SQL a mano.
- Hai esposto quelle tabelle attraverso le Business Entities, scegliendo cosa esporre, unendo etichette per usabilità, aggregando conteggi di righe correlate.
- Hai composto tre pagine solo dalla configurazione, con tab incorporate e ricerca.
- Hai aggiunto un comportamento con un Business Event (auto-stamping) e un calcolo più complesso con uno Script Module, otto righe di C# che girano ogni volta che i dati cambiano.
- Hai impacchettato il tutto come Package, portabile tra ambienti.
Lo stesso loop scala a dozzine di tabelle e centinaia di pagine. La Reference copre il resto della piattaforma, branding, sync di dati di terze parti, scaffolding assistito da AI, ma la competenza centrale è quella che hai appena imparato.
Dove andare dopo
- Genera fatture in PDF - aggiungi un template di fattura stampabile ai Deals che hai appena costruito. Stessi dati, nuovo canale di output.
- Scheduled Events - estendi lo script di ricalcolo con un catch-up notturno che gira senza azione utente.
- AI Builder - indirizzalo su "aggiungi supporto per gli appuntamenti di servizio, data, customer, veicolo, status" e guardalo fare lo scaffolding di una funzionalità simile.