Salta al contenuto
KAMOUniverse

Changelog

Cosa c'è di nuovo.

Ogni miglioramento alla piattaforma, come si spedisce.

  1. · kamo-shared-library

    Pagina e filtra le citazioni di un account nel database

    Una vista account ha bisogno di ogni citazione attraverso tutte le sue piste. Caricarli per rendere una pagina degrades ogni mese l'account è in uso, e qualsiasi totale mostrato coprirebbe solo quello è stato catturato — così paging, filtrare e ordinare tutto accade in SQL. La query è nativo perché Quote detiene solo un piombo morbidoId senza associazione per unirsi attraverso; si unisce lead.uid = commerce quotes.lead id e gli ambiti su lead.account uid. Tirare i lead del conto in una lista IN non sarebbe sopravvissuto a un grande libro di affari. Ogni filtro è un predicato null-guardato, quindi una query serve la griglia non filtrata e qualsiasi combinazione di filtri piuttosto che un metodo per permutazione. Le chiavi di selezione sono visualizzate per consentire: il valore raggiunge un ORDINATO nativo, così accettando un nome di campo arbitrario dal cliente sarebbe un punto di iniezione. La proiezione dell'elenco acquisisce anche inviatoAt, accettAt, versione e i conteggi di opzione / linea — una panoramica è letta per "quanto tempo è stato fuori, ha fatto atterrare", che il precedente i campi non potevano rispondere.

  2. · kamo-signer-monorepo

    Mostra l'agente assegnato sulla copia del cliente

    Corrisponde all'anteprima del personale: la fronte nomina l'org, questo nomina la persona a chiedere.

  3. · kamo-internal

    Mostra l'agente assegnato in anteprima

    Un pannello "il tuo contatto" sopra il piè di pagina — nome, titolo, telefono ed e-mail — così il cliente sa chi chiedere del prezzo. Assente completamente quando il piombo non è firmato.

  4. · SecurityService

    Risolvere l'agente accanto al cliente, da una ricerca di piombo

    Entrambi i blocchi scendono dalla stessa pista, così i controllori lo catturano una volta e derivano ogni da esso piuttosto che colpire il servizio due volte per render. Ancora org-scopio in entrambi luoghi; sulla pagina pubblica la portata proviene dall'organizzazione del link di condivisione.

  5. · kamo-shared-library

    Nome dell'agente assegnato al piombo sul documento

    La lettera identifica l'org, ma un cliente con una domanda su un prezzo ha bisogno la persona che possiede la relazione. La citazione ora porta l'agente assegnato del piombo — nome, titolo di lavoro, email di lavoro e telefono di lavoro. Contatti di lavoro: un preventivo porta l'identità aziendale dell'agente, mai un numero personale che capita di sedersi sul loro record membro. Il titolo di lavoro preferisce jobTitleOfficial, che è quello che l'org ha scelto di stampare, prima del JobTitle collegato. Un piombo non firmato, o un agente con nulla registrato, non produce alcun blocco piuttosto che un "Il tuo contatto" si dirige nello spazio vuoto. La risoluzione dei nomi si ripercuote sulla stessa via LeadController già utilizza per l'ufficiale di prestito assegnato, quindi la citazione nomina l'agente esattamente come il il resto della vista principale lo fa.

  6. · kamo-internal

    Riassegnare l'agente che detiene un'opportunità

    La finestra di dialogo dell'approvazione guadagna un picker agente, tratto dalla stessa piscina il backend convalida contro. La colonna dell'agente della griglia ora mostra chi ha l'opportunità, con un ambra "Riassegnato da ..." didascalia quando questo non è più l'agente che chiesto — il richiedente rimane sul record e nella storia in entrambi i modi. Il comando a testa di piombo segue anche il supporto. E' stato allontanare il richiedente, che dopo una riassegnazione avrebbe offerto la finestra di dialogo estensione all'agente che non lo possiede più e l'ha nascosto da colui che fa — e le porte del backend quel punto finale sul titolare, quindi l'offerta sarebbe finita in un 403.

  7. · SecurityService

    Riassegnare l'agente holding, e email tutti che colpisce

    Un approvatore può ora dare un'opportunità a un agente diverso. Il richiedente è mai riscritto — applicarePrimaryAgent record la mossa come la sua fila di storia con entrambi i nomi, quindi sei mesi dopo il record mostra che si è mosso piuttosto che leggere come se il nuovo agente lo chiedesse. Proprietà dell'estensione, il lead-header controllo e la maschera di dettaglio tutti seguono il supporto ora; il filtro "Agent" corrisponde EITHER fine di un riassegnamento, perché nasconderlo dall'agente che l'ha trovato e dall'agente che lo tiene sono entrambe risposte sbagliate. Nove notifiche coprono il ciclo di vita. Richieste e richieste di estensione vanno a tutti coloro che possono decidere loro — entrambi i diritti di decisione, dal momento che un membro che può solo negare altrimenti non imparerebbe mai una richiesta esiste per negare. Decisioni e modifiche vanno al titolare, il richiedente originale quando ciò differisce, e ogni collega su un commissione divisa; una modifica inoltre spedisce chiunque si sia spostato, perché perdere una quota di commissione silenziosamente è esattamente ciò che queste e-mail sono per. Due cose sono portanti a carico nel modo in cui l'invio è in sequenza: - Risoluzione e rendering avvengono EAGERLY, all'interno della transazione del chiamante, mentre l'entità detiene ancora i valori che l'e-mail è circa. approvareExtension() chiari i campi di estensione immediatamente dopo, quindi una lettura successiva descriverebbe "no tempo supplementare" su una e-mail il cui soggetto è quanto tempo è stato concesso. - Il SENDING aspetta un attimo. Annunciare una decisione che un successivo fallimento rotola indietro lascerebbe agenti che tengono una e-mail per un l'approvazione che non è mai avvenuta, e dopoComplezione piuttosto che dopoI mezzi commissari la connessione del database viene rilasciata prima dell'avvio di HTTP in uscita. I valori della tabella dei dettagli sono sfuggiti al punto in cui entrano nella mappa: i nomi dei membri sono org-entred testo libero, la tabella viene iniettata come HTML grezzo, e il renderer sfugge Niente. Una modifica che cambia nulla non invia posta, e una prenotazione PENDING non invia "updated" — nessuno è stato detto che esiste ancora. 60 test.

  8. · EmailService

    Anteprima campioni per le nove notifiche opportunità

    Senza un braccio qui l'editor di modelli di posta elettronica di admin rende ogni segnaposto vuoto, così chiunque personalizzazione questi nove sarebbe la modifica di uno scheletro vuoto. Un braccio per tutti i nove: condividono un set variabile per design, quindi una singola mappa del campione rende ciascuno di loro fedelmente. Mappa.ofAttivi perché Map.of caps at ten coppie e il set è più grande di quello.

  9. · InitializerService

    Agente primario riassegnabile su un'opportunità riservata

    PRIMARY AGENT MEMBER ID è chi detiene l'opportunità ora; REQUESTED BY MEMBER ID è lasciato intatto per sempre. Nullable senza backfill di proposito — mezzi null "mai riassegnato", e copiare il richiedente in righe esistenti distruggerebbe quella distinzione su ogni prenotazione che predate la colonna. Applicato contro la produzione su 2026-08-04; colonna e indice verificato presente.

  10. · kamo-shared-library

    Agente primario riassegnabile e nove modelli di notifica

    Un approvatore può dare un'opportunità — e la commissione con esso — a un diverso Agente. PRIMARY AGENT MEMBER ID è chi lo detiene ora; REQUESTED BY MEMBER ID è mai più scritto, perché chi ha trovato l'accordo è un fatto sul passato e sovrascrittura sarebbe cancellare l'unico record che l'agente originale ha portato. Null significa "mai riassegnato", che è una dichiarazione diversa da "riassegnata di nuovo al richiedente" — così le righe esistenti sono lasciate da sole piuttosto che riempite. efficaceAgentMemberId() è il titolare, ed è quello che ora decide chi può chiedere un'estensione e chi l'intestazione principale tratta come il proprietario. Una volta un'opportunità si muove, il richiedente originale è un nome nella storia, non un reclamo su di esso. Nove modelli canonici coprono il ciclo di vita: una richiesta o una richiesta di estensione va a tutti coloro che possono decidere; ogni approvazione, negazione, modifica, proroga di decisione, scadenza e chiusura va all'agente che lo tiene, l'agente che ha chiesto se questo è ora qualcun altro, e ogni collega su una commissione divisa. Condividono un guscio generato in modo che il layout non possa derivare tra loro, e uno set variabile in modo che un modello possa fare riferimento a qualsiasi cosa senza una modifica Java corrispondente — che conta perché una variabile mancante rende come una stringa vuota con solo una AVVERTENZA, e navi una e-mail di lettura "riservata fino a ".

  11. · kamo-internal

    Complessivamente commissioni, di default di mercato, e nessuna unità pre-citata

    Tre modifiche a come viene catturata la commissione. Niente è più pre-selezionato. Percentuale/ Importo e One-time/Ricerca entrambi avviare unset su ogni commissione divisa, così ognuno dichiara il suo tipo perché Qualcuno l'ha detto. Un "Percent" prescelto è indistinguibile da un considerato scelta, e la differenza tra il 15% di una vendita e $15 è l'intera vincita. Invia soggiorni disabilitati fino a quando una riga iniziata è terminata. L'approvazione ora concorda una commissione OVERALL — ciò che l'organizzazione paga sulla vendita all'agente richiedente e al gruppo con cui condividono, da cui per-colleague spaccature sono scolpite. Viene visualizzata nella finestra di dialogo di approvazione e modifica e come una colonna nell'elenco riservato, e un mercato può portare un default che pre-riempisce. I default del mercato pre-riempiscono l'APPROVALE solo. Vedere una modifica dal mercato lasciare un salvataggio che era circa date francobollo su una commissione nessuno ha accettato, e avrebbe rendere "nessuna commissione" impossibile da mantenere. Cancellare una figura preriempita ora invia una Commissione chiara esplicita, tracciata contro quale sia il modulo OPENED piuttosto che che cosa è memorizzato — altrimenti la cancellazione di un predefinito non invia nulla e il il server lo rimette facilmente. Inoltre: un default di mercato a metà pieno ora blocca il salvataggio invece di essere caduto e segnalato come successo; la colonna della commissione non inventa più "una volta" quando nessuna cadenza è stata impostata; gli importi divisi nella tooltip usano la stessa formattazione del denaro come la colonna; e Add Market cancella i campi di quotazione che era ereditando dall'ultimo mercato modificato.

  12. · SecurityService

    Unisci una commissione generale all'approvazione, seme dal mercato

    L'approvazione ora registra ciò che l'organizzazione paga sulla vendita alla richiesta agente e gruppo. Ometterlo sull'approvazione e si applica il default del mercato del piombo — che è ciò che rende il mercato impostazione un default piuttosto che un suggerimento solo Onori dell'UI. applicareLa Commissione mette insieme i tre campi e non li fonde mai sul campo con ciò che è memorizzato. Merging sembra innocuo e non è: una modifica che trasporta solo un tipo di quota sarebbe capovolgere un immagazzinato 15 da quindici per cento a quindici dollari, ri-denominare un pagamento nessuno voleva toccare. Un default di mercato non valido o semiconfigurato viene registrato e ignorato piuttosto che gettato. Un default è convenienza, non legge, e uno salvato attraverso un altro percorso con una figura di sciocchezza non deve trasformarsi in un'estrazione di mercato inaccettabile — il l'approvazione può ancora digitare una commissione dentro e approvare senza uno è legittimo. ClearCommission è onorato davanti a tutto, compreso il default del mercato: un approvatore che cancella una figura preriempita ha preso una decisione, e tranquillamente rimetterlo indietro lo inverterebbe. 49 test, compresi i percorsi chiari, la guardia di fondo, ed entrambi i casi di cattiva difesa.

  13. · InitializerService

    Colonne della Commissione per opportunità riservate e di default di mercato

    Sei colonne nullable: la commissione generale ha accettato un'opportunità riservata, e il default di mercato che pre-riempisce all'approvazione. NUMERIC(19,4) per abbinare tavolo diviso — il denaro è decimale esatto o le controversie della commissione seguono. Applicato contro la produzione il 2026-08-04; tutti i sei presenti verificati.

  14. · kamo-shared-library

    La commissione generale su una vendita, e di default di mercato per esso

    Un'opportunità riservata ora registra ciò che l'organizzazione paga dalla vendita a l'agente richiedente e il gruppo con cui condividono — il piatto il per-collega le spaccature sono scolpite fuori. Un mercato di piombo porta un default che pre-riempisce quando un'approvazione è concessa. Ogni colonna è nulla con nessun default. Una prenotazione nessuno approvato non ha commissione concordata e un mercato che non ha configurato uno non ha default; scrivere uno zero in entrambi avrebbe messo una figura nessuno ha scelto su un record di vincita. Tre campi di richiesta non sarebbero stati sufficienti. A JSON null e un campo assente sono la stessa cosa dopo la deserializzazione, e l'assenza già significa due altri cose qui — "usare il mercato predefinito" su approvazione, "lasciare da solo" su una modifica. Così chiaroCommission dice rimozione ad alta voce; senza di esso un approvatore che cancella un la commissione ottiene il silenzio, e su approvazione il default appena sgomberato torna indietro. LeadIdentity acquisisce i valori predefiniti del mercato e trova le identità ora cancella le sue I genitori a sinistra. Scritto come percorso implicito l.market.x, Hibernate emette un INNER unire e ogni piombo senza mercato scende completamente dalla proiezione — che sarebbe apparso come "Unnamed lead" su esattamente le righe che nessuno guarda due volte.

  15. · kamo-internal

    Render i dettagli del cliente sull'anteprima, dal piombo

    Rimuovere i campi del destinatario del preventivo lasciato "Preparato per" vuoto, perché customerName è venuto solo da un Account collegato e citazioni lead-raised non hanno nessuno. L'anteprima ora stampa il blocco che il server assembla dal comando. La società si dirige quando c'è uno — un preventivo a un'impresa è indirizzato al business, con il contatto denominato sotto — quindi indirizzo, telefono ed e-mail, ogni omesso quando il piombo non Portatelo.

  16. · kamo-signer-monorepo

    Mostra i dettagli del cliente sulla copia del cliente

    La società dirige il blocco quando c'è uno — un preventivo a un'impresa è indirizzato a affari, con il contatto chiamato sotto di esso. Abbina esattamente l'anteprima del personale.

  17. · SecurityService

    Risolvere la guida del destinatario sia per il personale che per la vista del cliente

    Org-scoped in entrambi i posti. Sulla pagina pubblica la portata proviene dal link di condivisione organizzazione, quindi un token non può mai esporsi di un piombo appartenente ad un altro inquilino.

  18. · kamo-shared-library

    Mettere i dettagli del cliente sul documento, leggere il comando

    La caduta dei campi di destinatari della citazione ha lasciato il documento senza nulla da dire il cliente: customerName è venuto solo da un Account collegato, che citazioni lead-raised non hanno, quindi "Preparato per" stampato vuoto. Il destinatario è ora assemblato dal piombo — nome, società, indirizzo, telefono, e-mail. Si tratta di una ricerca piuttosto che di una unione perché la citazione mantiene deliberatamente solo un morbido leadId in modo che il modulo di piombo rimanga dispiegabile in modo indipendente, così i controller risolvono e passare il blocco dentro. Un cavo mezzo-riempito è il caso normale, non l'eccezione: i cavi arrivano da venditori con qualunque sia la fonte catturata. L'indirizzo crolla a una linea e salta ciò che è mancante, quindi una pista che tiene solo una stampa di città "London" piuttosto che ", Londra, ". Una pista che non può essere letto produce nessun blocco piuttosto che lanciare — una citazione il cui piombo era cancellato dovrebbe ancora rendere.

  19. · kamo-internal

    Spostare le citazioni dal commercio e sul piombo

    Citazioni seduti nella pipeline di commercio, accanto a ordini e carri piuttosto che accanto al per il cliente. Ora vivono sul piombo: una scheda Quotazioni direttamente dopo il piombo del cliente Dati, mostrati solo dove il mercato consente loro. La pagina di citazione standalone è andato piuttosto che tenuto dietro una bandiera — il piombo già fornisce l'intestazione, l'identità del cliente, le sue comunicazioni e i suoi documenti, quindi un secondo layout di record in cima a quello duplicato il cromo e dividere la storia del cliente in due. Selezione di un preventivo scorre l'elenco e l'editor in, e l'intestazione di piombo Non lascia mai lo schermo. Le schede delle comunicazioni e dei Docs sono diminuite per lo stesso motivo. I mercati acquisiscono un interruttore Enable Quotes e i termini di default le loro citazioni iniziano con. Senza EDIT QUOTE TERMS il campo dei termini è disabilitato e omesso dal carico di pagamento; il server lo strips troppo, poiché un ingresso disabilitato è presentazione, non esecuzione. Il sub-tab ids perde "quote"; il suo test di regressione afferma ora la proprietà generale — ogni scheda passato il primo mantiene il proprio indice — in modo da protegge ancora il bug di rimbalzo senza nominare una scheda che non esiste più.

  20. · SecurityService

    Esporre le impostazioni di quotazione per mercato; applicare i termini di sovvenzione

    market-config ora dice il lead view se offrire una scheda Quotes e che dire una nuova citazione inizia con, e il mercato endpoints round-trip entrambi i campi. Le modifiche dei termini sono a lato server per i chiamanti senza EDIT QUOTE TERMS. Disabilitare la campo nell'interfaccia utente è presentazione; un PATCH fatto a mano non deve essere in grado di riscrivere l'org Neanche la parola legale.

  21. · kamo-shared-library

    I preventivi appartengono a cavi, configurati per mercato

    Le citazioni erano un artefatto commerciale-pipeline, che li ha messi accanto ordini e carrelli piuttosto che accanto al cliente per cui sono. Ora agganciano il piombo: il mercato decide se i suoi cavi possono portare citazioni a tutti, e i termini di default ogni citazione in questo il mercato inizia con. Per mercato piuttosto che per org perché una scrivania ipoteca questioni Stime sotto TRID e non ha uso per un preventivo generico, mentre un mercato dei servizi vive su di loro. I termini portano l'impegno legale dell'org, quindi partendo dalla formulazione di mercato su un unico — EDIT QUOTE TERMS. Un campo di termini null ha già significato "leave invariato" sull'aggiornamento, che è ciò che consente al controller di spogliarlo per i chiamanti senza i Giusto. Inoltre scende il nome/indirizzo/telefono del destinatario della citazione: il piombo detiene già il i dettagli del cliente, e le istantanee hanno duplicato un record modificato altrove che avrebbe deriva da esso. Schema applicato da KamoInitializer prima di questo commit; colonne verificate.

  22. · SecurityService

    Riserva, approva e verifica

    Superficie REST dietro /leads/opportunities/reserved e l'Opportunità Riserva controllo nell'intestazione del piombo, più il servizio che possiede gli invarianti. Diritti, applicati esplicitamente perché questo servizio funziona permessoTutti senza @EnableMethodSecurity — un controllo mancante è un controllo mancante, non un default-deny: VIEW OPPORTUNITIES ogni lettura CREATE OPPORTUNITIES sollevando una richiesta, e chiedendo più tempo da soli EDIT OPPORTUNITIES approva, modifica, chiusura, sentenza su un'estensione DELETE OPPORTUNITIES "Deny Opportunity", che l'UI mette dietro una conferma Deny è terminale ma non distruttivo: la prenotazione, le sue scissioni e tutta la sua la storia rimane leggibile sulla scheda Denied. Questo è il punto di negare piuttosto che morire. Dettagli da tenere: - Il punto finale della testa di piombo è leggibile con CREATE da solo, dal momento che il pulsante deve sapere quale stato rendere — ma un chiamante senza VIEW che non è la holding L'agente ottiene una proiezione ristretta. La commissione si divide e giustifica che VIEW esiste per proteggere non sono divulgati dal cancello allargato. Ricostruito come consent-list, quindi un campo aggiunto in seguito non può trapelare per omissione. - L'elenco maschera il contatto e la società su porta senza firma per i membri senza VIEW UNASSIGNED LEADS, corrispondente a LeadController. Chi ha sostenuto ciò che non è segreto; la prospettiva è. - L'imminente è destinato ad essere l'agente che detiene la prenotazione, senza dio bypass: tenere una prenotazione è un fatto di identità, non un diritto, e un l'estensione è depositata sotto il nome del richiedente. - Una riserva decresciuta che si riavvia più che riprendere, quindi riservato Fino a == riservatoDa + approvato I giorni continuano a tenere — l'aggiornamento() re-derives la fine dall'inizio, e un inizio stantio cancellerebbe silenziosamente la sovvenzione. - La piscina di commissione-split è VIEW LEADS titolari più Grant-all proprietari/admins, identico a quello che il punto finale del picker offre. Computarlo dalla tabella dei diritti da solo fatto il dropdown offrire un proprietario il backend poi respinto. - L'espiry è una spazzata programmata in modo che le schede possano impaginare su una colonna reale, ma ogni DTO riferisce giorni Rimanendo contro l'orologio del database, così le letture sono corrette tra le spazzate indipendentemente. 36 test coprono il ciclo di vita, la data aritmetica e le regole di divisione.

  23. · InitializerService

    Tavole per le prenotazioni delle opportunità di piombo

    Specchi LeadOpportunityReservation, LeadOpportunityCommissionSplit e E' in Bilancia. ddl-auto: aggiornamento crearli comunque dalle entità; il DDL esplicito è la convenzione di casa e rende la forma recensibile qui piuttosto che solo inferable da annotazioni. Applicato contro la produzione 2026-08-04 — tutte e tre le tabelle e ogni indice esiste, di proprietà dell'utente app.

  24. · kamo-shared-library

    Enti per prenotazioni occasioni di lead time-boxed

    Un agente punta un reclamo esclusivo sulla chiusura di un piombo per una finestra delimitata; un approvare sovvenzioni, modifiche o negarlo, e i colleghi possono essere offerti una parte di la commissione. Tre tabelle: la prenotazione, la sua commissione si divide, e un Append-only audit trail. Punti di progettazione che sono portanti a carico: - Piombo, organizzazione e riferimenti dei membri sono semplici colonne id senza stranieri chiavi, corrispondenti LEAD HISTORY e LEAD TASK. Il sentiero deve superare la pista la cancellazione e il membro churn senza essere in grado di bloccare o cascata. - dbNow() utilizza CAST(ora() AS timestamp). Il nudo di CockroachDB ora() è TIMESTAMPTZ, che Hibernate 6 si materializza come un istantaneo che non può essere gettato al dichiarato LocalDateTime — e il:timestamp shorthand è schiacciato dal nativi-query parser lettura ':' come prefisso dei parametri. Nessuno si presenta al momento della compilazione. - L'elenco delle pagine utilizza JpaSpecificationExecutor piuttosto che JPQL con (:param IS NULL O ...) guardie, perché CockroachDB rifiuta un legame non digitato parametro in un test IS NULL nudo. - LeadIdentity è una proiezione, non l'entità di piombo: Lead mappe quattro @ManyToOne associazioni che di default a EAGER, quindi elencare 100 prenotazioni per entità fuoco centinaia di selezioni per i dati che la griglia non mostra mai. - Gli ordini della cronologia tramite (dateCreated DESC, id DESC). CockroachDB ora() è il timestamp delle transazioni, quindi le righe scritte da una modifica lo condividono esattamente; senza il tiebreak un percorso di audit si dissolve tra i carichi di pagina. Nessun stereotipo qui — il servizio di gestione dichiara i fagioli, quindi nessun altro servizio paga per la scansione del repository.

  25. · kamo-internal

    Indirizzo il preventivo a una persona; riepilogo smette di costare altezza intestazione

    Spostare il sommario dalla colonna di destra ha fissato la larghezza, ma l'ha comprato indietro come una band sotto il titolo. Ora si trova nel gap che già esisteva tra il titolo e le azioni rapide, quindi non costa affatto spazio. Quel divario è finito, così meno mostrano inline e il resto rimane un clic di distanza — un ordine trasporta dodici e sarebbe folla fuori azioni. Resta visibile ad ogni larghezza piuttosto che scomparire su schermi stretti. La citazione guadagna anche il suo destinatario: per chi è, facoltativamente il loro indirizzo e telefono. Questi portano la prima sezione perché è la prima cosa che si decide, e quando un account è collegato il campo dei nomi mostra a cosa sarebbe altrimenti cadere. The il blocco "Prepared for" di anteprima rende tutti e tre e riflette ciò che viene digitato piuttosto di quello che è stato salvato.

  26. · kamo-shared-library

    Indirizzo un preventivo a qualcuno che non è ancora un account

    Il destinatario è stato derivato esclusivamente da un Account collegato, quindi qualsiasi citazione sollevata per un prospetto — che è la maggior parte di loro — ha stampato una linea vuota "Preparato per" e il finito documento non ha detto per chi era. La citazione ora porta il nome, l'indirizzo e il telefono del destinatario in proprio diritto. Cosa? personale digitato vince sul conto collegato: hanno detto che cosa dovrebbe essere stampato, e un account rinominato in seguito non deve riscrivere silenziosamente una citazione che è già stata inviata. Indirizzo è libera perché i formati postali non sono abbastanza uniformi da dividersi in campi che lavorare a livello internazionale, e stampa come scritto. Una revisione porta il destinatario avanti — stessa offerta, stessa persona. Schema applicato da KamoInitializer prima di questo commit; colonne verificate presenti.

  27. · kamo-internal

    Apri il profilo di un membro dalla loro riga

    Aggiunge una quarta azione al molo dell'hover della riga, collegandosi a E' il momento giusto. Si tratta di un NextLink reale piuttosto che di un click handler, quindi middle-click e "aperta nella nuova scheda" si comportano e la guardia di rinvigazione non dura resta soddisfatto; il pannello si chiude sulla navigazione in modo che il suo blocco di scorrimento del corpo non sopravvivere al cambio di rotta. L'azione è aperta il modo in cui le porte di destinazione stessa: le impostazioni del membro pagina reindirizza al tuo profilo a meno che tu non abbia MANAGE MEMBERS, MANAGE MEMBER SECURITY, CONFIGURE SYSTEM, EDIT MEMBER ACCESS LEVEL, ALLOW PROMOTING MEMBERS o... (o dio / piattaforma admin). Senza uno di questi l'icona è nascosta piuttosto che offerta come un morto fine. La tua fila lo mostra sempre.

  28. · kamo-internal

    Fail the build when a component calls a key messages/ does not define

    next-intl renders the key path verbatim for a missing key, and messages/ is gitignored here — populated at image-build time from kamo-translation-dictionary — so a rename that lands in only one of the two repos ships as visible gibberish with nothing to catch it. That is how the department contact fields came to render **************** on the settings screen, and how the entire HMDA demographics form (39 labels) shipped against a namespace that only contained `lar`. scripts/check-i18n-keys.mjs resolves each translator binding's namespace, then checks every literal key, the static prefix of every template-literal key, and the values passed against the {placeholders} in the message — in both directions, since an unsupplied ICU argument throws MissingValueError and an unused one silently drops data. It understands ICU brace escaping and plural sub-messages, and treats <tag> as a placeholder only for t.rich/t.markup. 1737 files in ~1.4s. Wired into `npm test` and into the Dockerfile ahead of the build, with --require-messages there so a skipped dictionary sync fails loudly instead of turning the guard into a no-op. Typing t() against `typeof en` was tried first and rejected: a JSON import widens values to `string`, so next-intl cannot infer placeholders and rejects correct calls like t('...range', {start, end, total}); it also tripled typecheck time (81s -> 249s) and would have needed ~150 edits to non-buggy code. Call-site fixes for what it found: - dropped a `default:` option passed to t() in the chat components and LanguageButton; next-intl has no such fallback option, so it was dead weight. - commerce lowStock passed {count} for {available}, MultiFileUploader {types} for {list}, and audioVideo master volume {pct} for {percent} — all three threw at format time. - DnsSetupStudio passed a {domain} its subtitle does not use.

  29. · kamo-internal

    Opzioni nav Pin/unpin dai navs e dalla home launchpad

    I membri potrebbero spostare un'opzione tra la barra laterale e la barra superiore, ma mai prendere uno dei nav del tutto. Aggiunge un terzo posizionamento — NONE, "non piegato" — e due modi per raggiungerlo, entrambi guidando lo stesso menu condiviso: - fare clic con il pulsante destro del mouse su un'opzione mobile in NavPri/NavTop: il menu di posizionamento si apre a - il controllo dell'angolo su ogni riquadro home-launchpad: un chip silenzioso che legge fuori dove l'opzione attualmente siede e si espande su hover, aprendo lo stesso menu Non è mai un vicolo cieco. La home launchpad ora rende da ogni gated opzione piuttosto che l'unione dei due navs, quindi un'opzione non piegata mantiene il riquadro che lo riporta indietro; la tavolozza di comando fa lo stesso, e ogni cambiamento solleva un tostato disfatto in cui l'opzione è andata. Il layout di navigazione la pagina delle impostazioni cresce una colonna Unpinned corrispondente. Il risolutore mantiene il suo invariante — ogni opzione gated in esattamente un secchio — e una NONE esplicita ora batte un ordine di zona stante, quindi una pin sopravvive a un blob scritto prima. I layout memorizzati legacy non hanno voci NONE e risolvono esattamente come prima; Reset to Standard non può mai lasciare nulla non piegato. Coperto da nuovi test per risolvereNavLayout, che non aveva.

  30. · kamo-internal

    Nascondi reparti vuoti, sposta il filtro di stato nel Directory

    - Dipartimenti senza membri. Il punto finale di partenza restituisce ogni reparto nel org compresi quelli vuoti, quindi il gallo era mostrando sezioni che non potrebbero mai contenere nessuno. Il per-dipartimento "no i membri" segnaposto va con loro, essendo ora irraggiungibile. - Il filtro All/Online/Offline si sposta dall'intestazione a tutto il pannello sotto il tab strip, quindi si trova nella propria area del Directory con il roster esso filtri invece di apparire per filtrare l'intero pannello (non applicato mai a Chat o accesso mobile). - Lo stato vuoto suggerisce solo di regolare la ricerca / filtro quando uno è effettivamente applicato; un org senza membri non ha nulla da regolare.

Il tuo universo ti sta aspettando.

Aggiungi i prodotti quando sei pronto: nessuna migrazione, nessun nuovo login, nessuna richiesta di pagamento.

Gratis per sempre — nessuna carta di credito richiesta