Edit demographics, set up the schedule, bill and post
The last four rights that named operations which did not exist. EDIT_PATIENT_DEMOGRAPHICS: a patient's details could be entered once and never corrected. A fie...
Rebuild against kamo-shared-library for SW4 quote conversion
An empty commit. QuoteConversionService, QuoteConversionBilling and the five quote defect fixes all live in the shared library, and none of them reaches anyone ...
POST /quotes/{uid}/convert
On QuoteController rather than POSController: this controller enforces a right on every handler, POSController enforces none on any order endpoint, and it resol...
Back the personal-mailbox API the console already calls
Eighteen client methods over twelve routes that had been shipping with no backend behind them. A member reaches only their own inbox and configures it only once...
Personal mailbox entities and two consumer providers
GMAIL_PERSONAL and OUTLOOK_PERSONAL were offered by the picker and were not members of the enum, so selecting either produced an unusable org.
A closed head spins away instead of blinking out
Right-clicking a head and choosing Close, or putting one in the goal — thrown in or carried in and dropped — now plays a 500ms exit: a counter-clockwise three-q...
Prescribe, order and immunise
The chart could display medications, orders and vaccinations and could produce none of them. The read paths, the FHIR renderers and the safety queues were all b...
Explain the mailbox charge where mailboxes are made
Console rows price mail per mailbox with the live count; the mailboxes tab, department picker and provider help all state what counts, that a shared mailbox is ...
Gate provider choice on the add-on, show mailbox charges
Locked cards say which add-on unlocks them rather than being hidden or silently dead, and the gate fails open so a billing outage cannot strand an org mid-migra...
22 of the 26 clinical rights were never enforced
Only the four population-level rights — bulk export, quality measures, portal administration and EHR settings — were ever checked. Prescribe, sign, cosign, plac...
Both mail add-ons are priced per mailbox
Prices unchanged at $5 and $2; only the unit changes. Copy now states what actually counts, and that aliases are unlimited and free.
Bill e-mail per mailbox, reconciled nightly
Quantity is server-computed under a reserved key a request body cannot reach, and pushed through the existing amend path — so Stripe's CREATE_PRORATIONS charges...
QuoteConversionResult.orderUid is a String, not a UUID
Order extends BaseEntity, whose id is a Long — only Quote, QuoteOption and QuoteLineItem extend BaseUuidEntity. The plan declared UUID and its own Self-Review a...
An accepted quote becomes an order
acceptPublic wrote four columns and appended an event. No Commitment, no Order, no Transaction — the Quote javadoc's claim that accepting mints a Commitment des...
SW4's dictionary keys land in the dictionary repo
Task 6a's file list named kamo-internal/messages/en.json, which is gitignored and cannot be committed. The step's prose was right; the list was not.
Count an org's billable mailboxes
Adds PER_MAILBOX pricing, the mail cost mode, and a stereotype-free aggregator: hosted bills every box on the server, third-party bills only what was mapped int...
Each org chooses what an order takes from an accepted quote
A radio group, not a switch — both are legitimate ways to sell, and neither is 'off'. Shows which is the default and what each does to a real charge: for a thre...
A contested primary is a 409, not a 500
The catch-all turned an expected refusal into a server error, which lost the message the member needed and made a routine conflict look like an outage in the lo...
Ask a host that exists for the organization ?org= names
A new organization was created with its logo, colours and three backgrounds. All of it provisioned correctly into public/wienerschnitzel/ — 15 objects, the righ...
An organization can be looked up by the reference ?org= carries
GET /org/ref/{ref} — the same projected record as /org/domain/{host}, for an organization named by its id or its web alias. Nothing could answer for one. The s...
The config body carries a scalar, and absence means unchanged
updatePOSConfig bound Map<String, List<String>>, a shape that cannot carry quoteConversionBilling at all. Widened to Map<String, Object>. A key that is absent ...
Each org chooses what an order takes from an accepted quote
There is no platform-wide right answer. A maintenance contractor on a three-year plan bills each period; a capital-equipment installer bills the contract up fro...
Say who holds a contested mailbox, and that aliases are free
The snackbar replaced the server's 409 message with a generic failure, so a manager could not tell which member held the mailbox. Adds the note that sharing a m...
Refuse a primary mailbox another member holds
Primary is a login identifier, so a silent takeover changes which account an address authenticates from a screen that never mentions logins. Assign still works ...
Every catalogued event fires where the event actually happens
Most of the sound catalogue was configurable and inaudible. Two causes, both silent by construction: a sound that never plays looks exactly like one the member ...
Actually measure the bulk-export bucket
StorageDomain.BULK_EXPORTS shipped declared, documented as "measured by scanning the object store", and referenced by nothing. It reported zero for every practi...
Plan SW5, the flat-rate task book
The spec's premise that no line carries a labour duration went stale hours ago — SW3 landed labourMinutes and taskCode on ServiceLineItem, and the javadoc on ta...
One primary member per mailbox
is_primary was unique per member only, so two members could both claim a mailbox — and PrimaryMailboxIdentityLookup returns null on an ambiguous address, so tha...
Plan per-mailbox billing and the personal-mailbox backend
Plans B and C of 3. Self-review closed five gaps: nothing set mail_cost_mode, nothing server-side stopped a billing group buying mail add-ons, the invoice mailb...
Dropping in the goal scores, and aiming at it no longer gathers
Two complaints about the same gesture — taking a head to the goal. **Dropping in the goal did nothing.** Scoring lived entirely inside the throw RAF loop, whic...
Correct the spec — StorageAutoExpandSweep already exists
The spec claimed no server-driven-quantity reconciler existed to reuse and listed the storage auto-expand columns as dead. Both false: the sweep reads them nigh...
Design per-mailbox e-mail billing and add-on gating
Bills e-mail by the mailbox rather than the seat, gates provider choice on the add-on that covers it, and attributes each mailbox to the billing group that shou...
Read the platform's branding from its alias folder
The theme folder was derived from the hostname — kamocrm.com became kamocrm-com — which is where branding was written until a domain became optional and the org...
A signing page wears the sender's brand, not Kamo's
getThemePath took a hostname and used its FQDN with dots turned into dashes as the bucket folder. That could only answer for an org that HAD a hostname, and a d...
The lobby wears the meeting owner's brand, not the platform's
The overlay derived its theme folder from the browser's hostname. On the shared meet host that is the platform's for every tenant, so the CSS, favicon and logo ...
Brand the signup screen from the org's alias, not the host
register.kamocrm.com is the signup page for every organization with no register host of its own, so a host-derived theme folder painted all of them in the platf...
Brand the sign-in screen from the org's alias, not the host
login.kamocrm.com is the sign-in screen for every organization that has no host of its own. The theme base was derived from that hostname, so all of them were p...
Paint each tab from its organization's alias, not from the hostname
The theme base was built from a hostname: drop the leading label, join the rest with dashes, and that is the bucket folder. It answered correctly while every or...
A child org's lobby offers its own backgrounds, not the platform's
The folder holding an org's meeting backgrounds and theme config was derived from a hostname — the request's, or the org domain the sidecar passed — by taking t...
The signer app gets the sender's brand, not Kamo's
Two separate ways the same wrong assumption showed up. The signing page's logo URL was https://<org fqdn>/theme/logo-full.<ext>, which is not a path anything s...
Build the org logo URL from its alias, not its domain
Transactional email is sent to real inboxes, so the header and footer logos have to resolve without any client-side theme JavaScript — they are built exactly th...
Provision an organization's branding under its alias, and migrate what exists
The folder every logo, colour, favicon and background is written to was the organization's hostname with the dots turned into dashes. A domain is optional now, ...
Editing top-level lines no longer deletes every option's lines
Quote.lineItems is orphanRemoval=true and option rows set both quote and option — which is why QuoteMapper filters on getOption() == null twice. A bare clear() ...
An option quote keeps the tax and shipping staff entered
recalculate zeroed taxTotal and shippingTotal whenever a quote had options. Both were still stored on the row and still rendered by QuoteMapper, so a staff memb...
Terminal guards on cancel and revise, and stop swallowing bad input
cancel() and revise() had no isTerminal() guard, so an ACCEPTED quote could be flipped to CANCELLED or REVISED while acceptedAt and acceptedByName survived — a ...
Actually exercise the terminal guards
The test that shipped with them asserted only that an ACCEPTED quote reports itself terminal — true before the guards existed and still true if both were delete...
An organization's branding lives under its ALIAS, not its domain
The folder an organization's logo, colours, favicons and backgrounds are written to in the public bucket was its hostname with the dots turned into dashes — wen...
Je, unaona nini kuhusu usafiri?
Kila moja ya hizi updates ardhi katika nafasi yako ya kazi moja kwa moja. Kuanza bure na kuangalia kukua wiki baada ya wiki.