Firm
The Firm module is the accounting firm's side of Almohaseb (plan §7.10, FIRM-01..13): its clients, what it keeps about each one, and its preparers, groups and services. A firm is a parent tenant of the CrestApps tenant hierarchy, and each client a child tenant with its own database (the Tenant Hierarchy module of CrestApps.OrchardCore).
| Projects | CrestApps.Almohaseb.Firm (module), CrestApps.Almohaseb.Firm.Core (models, rules, store, portfolio filter) |
| Feature | CrestApps.Almohaseb.Firm (Accounting firm); depends on the foundation, OrchardCore.Contents, OrchardCore.Title and OrchardCore.Users; enabled by the almohaseb-firm recipe |
| Collection | Firm |
The feature does not depend on CrestApps.OrchardCore.TenantHierarchy.Parent: a tenant becomes a parent after its setup, so the setup recipe could not enable a feature depending on it. The firm's clients are the tenant hierarchy's: its Clients list is the only list, and the firm adds to it. HierarchyStartup ([RequireFeatures("CrestApps.OrchardCore.TenantHierarchy.Parent")]) registers ChildTenantFirmDisplayDriver, a DisplayDriver<ChildTenantListItem> that adds, to each row of the hierarchy's list, the services and groups as badges (Tags:10), the assigned staff (Description:10) and Firm details in the row menu (ActionsMenu:5); it reads the firm's details and names once per request. The details page resolves ITenantHierarchyBroker, registered only in a parent, from the request services.
Content types
| Type | Parts | Holds |
|---|---|---|
AlmohasebPreparer | AlmohasebPreparerPart | Name (as on the returns), Ptin (FirmRules.TryParsePtin: P and eight digits, normalized), Email, UserName (the user in the firm's site), IsEro, MaySignWithPin (practitioner PIN), IsActive |
AlmohasebClientGroup | TitlePart, the type's own part | A group of clients the firm defines |
AlmohasebFirmService | TitlePart, the type's own part | A service the firm gives clients; the almohaseb-firm recipe seeds svc-bookkeeping, svc-payroll, svc-sales-tax, svc-payroll-tax, svc-1099, svc-income-tax |
The type's own part of a group and a service takes the fields a firm adds. IFirmLookup / ContentFirmLookup lists the published items of a type (FirmItem: id, name), the user names of the enabled users of the site (the staff) and the settings.
Firm settings
FirmSettings (Settings → Firm, group almohaseb-firm, ManageAlmohasebFirmSettings): Efin (FirmRules.TryParseEfin: six digits) and DefaultServiceIds (the services of a client the firm has not described yet, kept to existing services). The firm's name, EIN and address are the foundation's business profile.
Clients
FirmClient (document; its ItemId is the client's ChildTenantEntry.EntryId, so a client has one): ServiceIds, StaffUserNames, GroupIds, Notes (FirmClientNote: Id, Text, Author, CreatedUtc; latest first), ModifiedBy, ModifiedUtc. It lives in the firm's database; the client never sees it.
IFirmClientStore / FirmClientStore, a CrestApps DocumentCatalog<FirmClient, FirmClientIndex> (ICatalog<FirmClient>) in the Firm collection: ListAsync() (by entry id), GetAsync(entryId), SaveAsync(entryId, FirmClientDetails) (blank and repeated values dropped), AddNoteAsync (a blank note is refused), DeleteNoteAsync(entryId, noteId, user, anyAuthor) (the author, or a manager), DeleteAsync.
Listing, searching, adding, opening (~/delegated-access/open/{entryId}), suspending and removing clients, and access grants, are the hierarchy's own pages.
Admin
Firm menu (almohasebFirm, icon fa-briefcase): Preparers, Client groups, Services (content lists); Settings > Firm. The clients are under the hierarchy's Clients menu.
| Route (under the admin prefix) | Route name | |
|---|---|---|
Almohaseb/Firm/Clients/{entryId} | AlmohasebFirmClient | GET; POST serviceIds, staffUserNames, groupIds (ManageAlmohasebFirmClients; only the firm's own services, groups and users are kept) |
Almohaseb/Firm/Clients/{entryId}/Notes | AlmohasebFirmClientNote | POST text |
Almohaseb/Firm/Clients/{entryId}/Notes/{noteId}/Delete | AlmohasebFirmClientNoteDelete | POST |
An entryId that is not one of the firm's children answers 404: the broker only knows the caller's own children.
| Permission | Key | Implied by |
|---|---|---|
| Manage the firm's details of every client | ManageAlmohasebFirmClients | |
| View the firm's clients and add notes | ViewAlmohasebFirmClients | ManageAlmohasebFirmClients |
| Manage the firm settings | ManageAlmohasebFirmSettings |
The hierarchy's own permissions (CreateChildTenants, EnterChildTenants, …) decide Add a client and Open.
Hosting
The tenant hierarchy gives each tenant its own host name (accountant.example.com, cornermarket.accountant.example.com); locally, accountant.localhost:5318 works in a browser that resolves *.localhost. Tenants on URL prefixes (see Recipes) are ordinary tenants: the firm's clients cannot be prefixed tenants.
Next
Client status snapshots and the compliance board (Firm.Compliance), templates, communications, the payroll deposits batch, and "Work with my accountant" in the client (Collaboration) follow in Phase 7.