Company β my business#
The presentation of the site operator's own business, its booking calendar and its job agenda. Do not confuse it with the catalogue of other businesses β that is a different module with its own resources.
π΄ From outside, only for an administrator key#
An ordinary or anonymous key gets nothing out of this module
Every action with an HTTP wrapper is granted to the administrator role only β reading included. Other keys get a rejection (HTTP 403):
A 404 here does not mean a wrong address
The module's domain operations β booking an appointment, calendar availability, the public profile listings, the client's job overview, closing a sheet, invoicing, archiving β have no HTTP wrapper and return 404. The site calls them internally. Do not go looking for a typo in the address; from outside they are out of reach even with an administrator key.
Every resource offers the standard set of actions
get, get-by, get-all, save, update-columns, delete, delete-all β
unless stated otherwise. See the CRUD pattern.
Resources#
| Resource | Contents |
|---|---|
company |
the business β a single presented record |
block |
a content block of the profile |
highlight |
a highlighted profile figure |
reference |
a portfolio reference job |
team-member |
a team member |
service |
a price-list item |
service-group |
a price-list group |
category |
reference category β tree |
calendar |
a booking calendar |
time-slot |
a calendar segment β working window, taken time, closed day |
reservation |
an appointment booking |
work-list |
the job β a folder of work for one client |
work-sheet |
a work sheet β an invoicing batch inside a job |
work-item |
a piece of work β one row of a sheet |
work-item-comment |
a comment on a piece of work |
Exactly one business is presented#
Which record the site shows is governed by the presented flag on the company
resource.
Saving a business with presented clears the flag on all the others
The server enforces exclusivity itself: set the flag on one record and it silently takes it away from the rest. Nothing is reported and the response does not show it. Never switch the presented business through a bulk import.
A job has three levels#
A job is not invoiced or closed as a whole. It holds work sheets, and the sheet is the invoicing batch; individual work items sit inside the sheet.
work-list is the job, not a list of work
The name is historical. Work hangs off work-sheet, not off work-list β reaching
it takes two hops, not one.
The price of a work item excludes tax and cannot be written
The server computes price as hours Γ rate, or from a manually entered fixed
amount. The VAT rate is a separate field and is added on the document.
The rate is a snapshot, not a link into the price list
A work item copies the hourly rate when it is created and it does not change after that. Editing the price list does not recompute old work β deliberately, because it may already be on an invoice.
Fields that cannot be written from outside#
Some fields are read-only for an external client. The server drops them from the saved request and stores the rest.
| Resource | Fields that cannot be written |
|---|---|
work-item |
workSheetId, price |
work-list |
state, closedDatetime |
work-sheet |
state, stateBeforeClosing, bill, closedDatetime, invoicerInvoiceId |
reservation |
state, userId, cancelToken, gdprConsentDatetime, insertIp |
work-item-comment |
userId, byClient, authorName, ip, readDatetime |
calendar |
companyId |
company |
ratingThreadId |
On top of that, most resources hold the technical fields deleted, insertDatetime and
updateDatetime β deleting is what the delete action is for, and the server fills the
timestamps.
A dropped field is not reported β the response looks like a success
success comes back true and the record is stored, only without those fields.
Verify the stored state by reading it back, not from the return value.
State therefore cannot be moved by a plain save
Closing a sheet, issuing an invoice and confirming a booking are operations of their
own, with their own checks. They are unreachable from outside β and writing state
is forbidden precisely so that they cannot be bypassed.
Moving work between sheets is forbidden on purpose
workSheetId would allow pulling hours out of an already invoiced sheet and making
them billable again, or moving them to a different client.
Bookings rest on calendar segments#
The time sits on time-slot (day, from, to, type); the booking only points at it
through timeSlotId. The upper bound is exclusive.
Writing to time-slot bypasses the overlap check
Occupancy, splitting and shortening of segments are handled by domain operations that are not available from outside. A hand-written segment misses them and the calendar can drift from reality.
Comments on work are not moderated#
The thread on a work item is a conversation between the client and the business. It has no nesting, no approval and no reporting; the text is plain, at most 5,000 characters, and a post is visible immediately.
Unread is tracked per side, not per person
A comment counts as read the moment anyone on the other side sees it. The business is one subject β one member reading it counts for all.