@lssm/example.service-business-os 0.0.0-canary-20251212004227

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,13 @@
1
+ # @lssm/example.service-business-os
2
+
3
+ Service Business OS reference example (clients → quotes → jobs → invoices → payments).
4
+
5
+ Highlights:
6
+
7
+ - Multi-tenant clients with role-based access via `@lssm/lib.identity-rbac`
8
+ - Quote lifecycle (draft → sent → accepted/rejected)
9
+ - Jobs scheduling and completion with reminders via `@lssm/lib.jobs`
10
+ - Invoicing and payments with audit trail + notifications
11
+ - Attachments for proposals and receipts via `@lssm/lib.files`
12
+
13
+ Use this as a spec-first starting point for field services, agencies, or professional services teams.
@@ -0,0 +1 @@
1
+ import{ScalarTypeEnum as e,defineSchemaModel as t}from"@lssm/lib.schema";import{defineCommand as n,defineQuery as r}from"@lssm/lib.contracts";const i=[`examples.service-business-os`],a=t({name:`Client`,description:`Client profile`,fields:{id:{type:e.String_unsecure(),isOptional:!1},name:{type:e.String_unsecure(),isOptional:!1},contactEmail:{type:e.String_unsecure(),isOptional:!0},phone:{type:e.String_unsecure(),isOptional:!0},orgId:{type:e.String_unsecure(),isOptional:!1},ownerId:{type:e.String_unsecure(),isOptional:!1},createdAt:{type:e.DateTime(),isOptional:!1}}}),o=t({name:`Quote`,description:`Quote/proposal`,fields:{id:{type:e.String_unsecure(),isOptional:!1},clientId:{type:e.String_unsecure(),isOptional:!1},title:{type:e.String_unsecure(),isOptional:!1},description:{type:e.String_unsecure(),isOptional:!0},amount:{type:e.Float_unsecure(),isOptional:!1},currency:{type:e.String_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!1},validUntil:{type:e.DateTime(),isOptional:!0},createdAt:{type:e.DateTime(),isOptional:!1}}}),s=t({name:`Job`,description:`Scheduled job`,fields:{id:{type:e.String_unsecure(),isOptional:!1},quoteId:{type:e.String_unsecure(),isOptional:!1},clientId:{type:e.String_unsecure(),isOptional:!1},title:{type:e.String_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!1},scheduledAt:{type:e.DateTime(),isOptional:!0},completedAt:{type:e.DateTime(),isOptional:!0},assignedTo:{type:e.String_unsecure(),isOptional:!0}}}),c=t({name:`Invoice`,description:`Invoice issued for a job`,fields:{id:{type:e.String_unsecure(),isOptional:!1},jobId:{type:e.String_unsecure(),isOptional:!1},invoiceNumber:{type:e.String_unsecure(),isOptional:!1},amount:{type:e.Float_unsecure(),isOptional:!1},currency:{type:e.String_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!1},dueDate:{type:e.DateTime(),isOptional:!0},issuedAt:{type:e.DateTime(),isOptional:!0},paidAt:{type:e.DateTime(),isOptional:!0}}}),l=t({name:`Payment`,description:`Payment applied to invoice`,fields:{id:{type:e.String_unsecure(),isOptional:!1},invoiceId:{type:e.String_unsecure(),isOptional:!1},amount:{type:e.Float_unsecure(),isOptional:!1},currency:{type:e.String_unsecure(),isOptional:!1},method:{type:e.String_unsecure(),isOptional:!1},reference:{type:e.String_unsecure(),isOptional:!0},receivedAt:{type:e.DateTime(),isOptional:!1}}}),u=t({name:`CreateClientInput`,description:`Input for creating a client`,fields:{name:{type:e.String_unsecure(),isOptional:!1},contactEmail:{type:e.String_unsecure(),isOptional:!0},phone:{type:e.String_unsecure(),isOptional:!0},orgId:{type:e.String_unsecure(),isOptional:!1},ownerId:{type:e.String_unsecure(),isOptional:!1},metadata:{type:e.JSON(),isOptional:!0}}}),d=t({name:`CreateQuoteInput`,description:`Input for creating a quote`,fields:{clientId:{type:e.String_unsecure(),isOptional:!1},title:{type:e.String_unsecure(),isOptional:!1},description:{type:e.String_unsecure(),isOptional:!0},amount:{type:e.Float_unsecure(),isOptional:!1},currency:{type:e.String_unsecure(),isOptional:!0},validUntil:{type:e.DateTime(),isOptional:!0},orgId:{type:e.String_unsecure(),isOptional:!1},ownerId:{type:e.String_unsecure(),isOptional:!1}}}),f=t({name:`AcceptQuoteInput`,description:`Input for accepting a quote`,fields:{quoteId:{type:e.String_unsecure(),isOptional:!1},acceptedBy:{type:e.String_unsecure(),isOptional:!1},notes:{type:e.String_unsecure(),isOptional:!0}}}),p=t({name:`ScheduleJobInput`,description:`Input for scheduling a job`,fields:{quoteId:{type:e.String_unsecure(),isOptional:!1},scheduledAt:{type:e.DateTime(),isOptional:!1},assignedTo:{type:e.String_unsecure(),isOptional:!0},location:{type:e.JSON(),isOptional:!0},title:{type:e.String_unsecure(),isOptional:!0}}}),m=t({name:`CompleteJobInput`,description:`Input for completing a job`,fields:{jobId:{type:e.String_unsecure(),isOptional:!1},completedAt:{type:e.DateTime(),isOptional:!0},notes:{type:e.String_unsecure(),isOptional:!0}}}),h=t({name:`IssueInvoiceInput`,description:`Input for issuing an invoice`,fields:{jobId:{type:e.String_unsecure(),isOptional:!1},invoiceNumber:{type:e.String_unsecure(),isOptional:!1},amount:{type:e.Float_unsecure(),isOptional:!1},currency:{type:e.String_unsecure(),isOptional:!0},dueDate:{type:e.DateTime(),isOptional:!0},notes:{type:e.String_unsecure(),isOptional:!0}}}),g=t({name:`RecordPaymentInput`,description:`Input for recording a payment`,fields:{invoiceId:{type:e.String_unsecure(),isOptional:!1},amount:{type:e.Float_unsecure(),isOptional:!1},currency:{type:e.String_unsecure(),isOptional:!0},method:{type:e.String_unsecure(),isOptional:!1},reference:{type:e.String_unsecure(),isOptional:!0},receivedAt:{type:e.DateTime(),isOptional:!1}}}),_=t({name:`ListJobsInput`,description:`Filter for listing jobs`,fields:{orgId:{type:e.String_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!0},assignedTo:{type:e.String_unsecure(),isOptional:!0},from:{type:e.DateTime(),isOptional:!0},to:{type:e.DateTime(),isOptional:!0}}}),v=n({meta:{name:`service.client.create`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`client`,`create`],description:`Create a new client.`,goal:`Add a customer to the roster.`,context:`Used during onboarding or intake.`},io:{input:u,output:a},policy:{auth:`user`}}),y=n({meta:{name:`service.quote.create`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`quote`,`create`],description:`Create a quote for a client.`,goal:`Propose work and pricing.`,context:`Sales/estimation.`},io:{input:d,output:o},policy:{auth:`user`}}),b=n({meta:{name:`service.quote.accept`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`quote`,`accept`],description:`Accept a quote.`,goal:`Move quote into delivery pipeline.`,context:`Client approval.`},io:{input:f,output:o,errors:{QUOTE_NOT_FOUND:{when:`Quote not found`,description:`Quote not found`,http:404},INVALID_STATUS:{when:`The quote my await acceptance`,description:`Quote must be SENT to accept`,http:409}}},policy:{auth:`user`}}),x=n({meta:{name:`service.job.schedule`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`job`,`schedule`],description:`Schedule a job after quote acceptance.`,goal:`Plan service execution.`,context:`Ops scheduling.`},io:{input:p,output:s},policy:{auth:`user`}}),S=n({meta:{name:`service.job.complete`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`job`,`complete`],description:`Mark a job as completed.`,goal:`Signal readiness for invoicing.`,context:`Technician completion.`},io:{input:m,output:s,errors:{JOB_NOT_FOUND:{when:`Job not found`,description:`Job not found`,http:404},INVALID_STATUS:{when:`Job must be in progress`,description:`Job must be in progress`,http:409}}},policy:{auth:`user`}}),C=n({meta:{name:`service.invoice.issue`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`invoice`,`issue`],description:`Issue an invoice for a job.`,goal:`Bill the client.`,context:`Post-completion billing.`},io:{input:h,output:c},policy:{auth:`user`}}),w=n({meta:{name:`service.payment.record`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`payment`,`record`],description:`Record a payment for an invoice.`,goal:`Track AR and cash flow.`,context:`Finance ops.`},io:{input:g,output:l},policy:{auth:`user`}}),T=r({meta:{name:`service.job.list`,version:1,stability:`stable`,owners:[...i],tags:[`service-os`,`job`,`list`],description:`List jobs with filters.`,goal:`Operational schedule view.`,context:`Ops dashboard.`},io:{input:_,output:t({name:`ListJobsOutput`,description:`Jobs with total count`,fields:{jobs:{type:s,isArray:!0,isOptional:!1},total:{type:e.Int_unsecure(),isOptional:!1}}})},policy:{auth:`user`}});export{b as AcceptQuoteContract,a as ClientModel,S as CompleteJobContract,v as CreateClientContract,y as CreateQuoteContract,c as InvoiceModel,C as IssueInvoiceContract,s as JobModel,T as ListJobsContract,l as PaymentModel,o as QuoteModel,w as RecordPaymentContract,x as ScheduleJobContract};
@@ -0,0 +1 @@
1
+ import"./service-business-os.docblock.js";
@@ -0,0 +1,52 @@
1
+ import{registerDocBlocks as e}from"@lssm/lib.contracts/docs";e([{id:`docs.examples.service-business-os`,title:`Service Business OS`,summary:`Field/service business flow from client intake to quote, job scheduling, invoicing, and payments with notifications and audit trail.`,kind:`reference`,visibility:`public`,route:`/docs/examples/service-business-os`,tags:[`services`,`quotes`,`jobs`,`invoices`,`payments`],body:`## Flows
2
+
3
+ 1) **Client intake** → create client, capture contact + owner.
4
+ 2) **Quote** → draft, send, accept/reject (events + notifications).
5
+ 3) **Job** → schedule, assign technician, complete with notes and attachments.
6
+ 4) **Invoice** → issue after completion, track status.
7
+ 5) **Payment** → record payment and emit analytics/audit.
8
+
9
+ ## Modules reused
10
+ - Identity/RBAC for org + roles
11
+ - Files for attachments (proposals, receipts)
12
+ - Notifications for quote sent/accepted, job reminders, overdue invoices
13
+ - Jobs for reminder/schedule tasks
14
+ - Audit trail for all lifecycle changes
15
+
16
+ ## Presentations
17
+ - Dashboard, client list, quote list/detail, job board, invoice list, payment list (React + Markdown targets).
18
+ `},{id:`docs.examples.service-business-os.goal`,title:`Service Business OS — Goal`,summary:`Why this field-service OS exists and outcomes it targets.`,kind:`goal`,visibility:`public`,route:`/docs/examples/service-business-os/goal`,tags:[`services`,`goal`],body:`## Why it matters
19
+ - Provides a regenerable, end-to-end service lifecycle (client → quote → job → invoice → payment).
20
+ - Keeps pricing, scheduling, invoicing, and payments consistent across surfaces.
21
+
22
+ ## Business/Product goal
23
+ - Deliver auditable quotes/jobs/invoices with notifications and reminders.
24
+ - Support attachments and PII-safe flows; stage new payment rules via feature flags.
25
+
26
+ ## Success criteria
27
+ - Spec changes regenerate UI/API/events cleanly across lifecycle steps.
28
+ - Audit/Notifications/Jobs remain wired for every mutation.`},{id:`docs.examples.service-business-os.usage`,title:`Service Business OS — Usage`,summary:`How to operate, extend, and regenerate the service OS safely.`,kind:`usage`,visibility:`public`,route:`/docs/examples/service-business-os/usage`,tags:[`services`,`usage`],body:`## Setup
29
+ 1) Seed (if provided) or create client → quote → job → invoice → payment via UI.
30
+ 2) Configure Files for attachments and Notifications for quote/job/invoice events.
31
+
32
+ ## Extend & regenerate
33
+ 1) Adjust schemas: quote line items, job statuses, invoice terms, payment methods.
34
+ 2) Regenerate to sync UI/API/events; mark PII paths in policy.
35
+ 3) Use Feature Flags to trial new payment rules or reminder cadences.
36
+
37
+ ## Guardrails
38
+ - Emit events for quote accepted/rejected, job scheduled/completed, invoice overdue, payment recorded.
39
+ - Keep pricing/tax rules explicit in spec; avoid implicit handler math.
40
+ - Use Audit Trail for lifecycle mutations; schedule reminders via Jobs.`},{id:`docs.examples.service-business-os.constraints`,title:`Service Business OS — Constraints & Safety`,summary:`Internal guardrails for quotes/jobs/invoices/payments and regeneration safety.`,kind:`reference`,visibility:`internal`,route:`/docs/examples/service-business-os/constraints`,tags:[`services`,`constraints`,`internal`],body:`## Constraints
41
+ - Commission/tax/payment rules must be explicit in spec; no hidden handler math.
42
+ - Events to emit: quote.sent/accepted/rejected, job.scheduled/completed, invoice.issued/overdue, payment.recorded.
43
+ - Regeneration must not alter payment semantics without reviewed spec changes.
44
+
45
+ ## PII & Attachments
46
+ - Mark PII paths (client contact, address); redact in markdown/JSON.
47
+ - Files (quotes, receipts) should use presigned URLs with scoped access.
48
+
49
+ ## Verification
50
+ - Add fixtures for quote/job/invoice state transitions.
51
+ - Ensure Notifications/Audit/Jobs wiring persists after regeneration.
52
+ - Use Feature Flags to trial new payment rules/reminder cadences; default safe/off.`}]);
@@ -0,0 +1 @@
1
+ import{defineEntity as e,defineEntityEnum as t,field as n,index as r}from"@lssm/lib.schema";const i=`lssm_service_os`,a=t({name:`QuoteStatus`,schema:i,values:[`DRAFT`,`SENT`,`ACCEPTED`,`REJECTED`,`EXPIRED`],description:`Lifecycle for quotes/proposals.`}),o=t({name:`JobStatus`,schema:i,values:[`SCHEDULED`,`IN_PROGRESS`,`COMPLETED`,`CANCELLED`],description:`Lifecycle for service jobs/interventions.`}),s=t({name:`InvoiceStatus`,schema:i,values:[`DRAFT`,`SENT`,`PAID`,`OVERDUE`,`CANCELLED`],description:`Lifecycle for invoices.`}),c=t({name:`PaymentMethod`,schema:i,values:[`CARD`,`BANK_TRANSFER`,`CASH`,`CHECK`],description:`Payment method used.`}),l=e({name:`Client`,description:`Customer organization or individual.`,schema:i,map:`client`,fields:{id:n.id({description:`Unique client identifier`}),name:n.string({description:`Client display name`}),contactEmail:n.string({description:`Primary contact email`,isOptional:!0}),phone:n.string({description:`Primary phone`,isOptional:!0}),address:n.json({description:`Mailing address`,isOptional:!0}),industry:n.string({description:`Industry/vertical`,isOptional:!0}),orgId:n.string({description:`Owning organization`}),ownerId:n.string({description:`Account owner`}),metadata:n.json({description:`Additional metadata`,isOptional:!0}),createdAt:n.createdAt(),updatedAt:n.updatedAt(),quotes:n.hasMany(`Quote`),jobs:n.hasMany(`Job`)},indexes:[r.on([`orgId`]),r.on([`ownerId`]),r.on([`name`])]}),u=e({name:`Quote`,description:`Proposal/quote for a job.`,schema:i,map:`quote`,fields:{id:n.id({description:`Unique quote identifier`}),clientId:n.foreignKey({description:`Client receiving quote`}),title:n.string({description:`Quote title`}),description:n.string({description:`Work summary`,isOptional:!0}),amount:n.float({description:`Total quoted amount`}),currency:n.string({description:`Currency code`,default:`"USD"`}),status:n.enum(`QuoteStatus`,{description:`Quote status`,default:`DRAFT`}),validUntil:n.dateTime({description:`Expiration date`,isOptional:!0}),terms:n.string({description:`Payment/engagement terms`,isOptional:!0}),orgId:n.string({description:`Owning organization`}),ownerId:n.string({description:`Account owner`}),createdAt:n.createdAt(),updatedAt:n.updatedAt(),client:n.belongsTo(`Client`,[`clientId`],[`id`],{onDelete:`Cascade`}),jobs:n.hasMany(`Job`)},enums:[a],indexes:[r.on([`orgId`,`status`]),r.on([`clientId`]),r.on([`validUntil`])]}),d=e({name:`Job`,description:`Service job/intervention derived from an accepted quote.`,schema:i,map:`job`,fields:{id:n.id({description:`Unique job identifier`}),quoteId:n.foreignKey({description:`Source quote`}),clientId:n.foreignKey({description:`Client receiving service`}),title:n.string({description:`Job title`}),status:n.enum(`JobStatus`,{description:`Job status`,default:`SCHEDULED`}),scheduledAt:n.dateTime({description:`Scheduled start date/time`,isOptional:!0}),completedAt:n.dateTime({description:`Completion timestamp`,isOptional:!0}),assignedTo:n.string({description:`Assignee/technician user ID`,isOptional:!0}),location:n.json({description:`Location details`,isOptional:!0}),notes:n.string({description:`Internal notes`,isOptional:!0}),orgId:n.string({description:`Owning organization`}),createdAt:n.createdAt(),updatedAt:n.updatedAt(),quote:n.belongsTo(`Quote`,[`quoteId`],[`id`],{onDelete:`SetNull`}),client:n.belongsTo(`Client`,[`clientId`],[`id`],{onDelete:`Cascade`}),invoices:n.hasMany(`Invoice`)},enums:[o],indexes:[r.on([`orgId`,`status`]),r.on([`clientId`]),r.on([`assignedTo`,`status`]),r.on([`scheduledAt`])]}),f=e({name:`Invoice`,description:`Invoice issued for a completed job.`,schema:i,map:`invoice`,fields:{id:n.id({description:`Unique invoice identifier`}),jobId:n.foreignKey({description:`Related job`}),invoiceNumber:n.string({description:`Invoice number`,isUnique:!0}),amount:n.decimal({description:`Invoice amount`}),currency:n.string({description:`Currency code`,default:`"USD"`}),status:n.enum(`InvoiceStatus`,{description:`Invoice status`,default:`DRAFT`}),dueDate:n.dateTime({description:`Due date`,isOptional:!0}),issuedAt:n.dateTime({description:`Issued timestamp`,isOptional:!0}),paidAt:n.dateTime({description:`Paid timestamp`,isOptional:!0}),orgId:n.string({description:`Owning organization`}),notes:n.string({description:`Invoice notes`,isOptional:!0}),metadata:n.json({description:`Metadata`,isOptional:!0}),createdAt:n.createdAt(),updatedAt:n.updatedAt(),job:n.belongsTo(`Job`,[`jobId`],[`id`],{onDelete:`Cascade`}),payments:n.hasMany(`Payment`)},enums:[s],indexes:[r.on([`invoiceNumber`]),r.on([`orgId`,`status`]),r.on([`dueDate`])]}),p=e({name:`Payment`,description:`Payment received for an invoice.`,schema:i,map:`payment`,fields:{id:n.id({description:`Unique payment identifier`}),invoiceId:n.foreignKey({description:`Invoice being paid`}),amount:n.decimal({description:`Payment amount`}),currency:n.string({description:`Currency code`,default:`"USD"`}),method:n.enum(`PaymentMethod`,{description:`Payment method`}),reference:n.string({description:`Payment reference/transaction ID`,isOptional:!0}),receivedAt:n.dateTime({description:`When payment was received`}),orgId:n.string({description:`Owning organization`}),createdAt:n.createdAt(),invoice:n.belongsTo(`Invoice`,[`invoiceId`],[`id`],{onDelete:`Cascade`})},enums:[c],indexes:[r.on([`invoiceId`]),r.on([`orgId`]),r.on([`receivedAt`])]}),m=[l,u,d,f,p],h={moduleId:`@lssm/example.service-business-os`,entities:m,enums:[a,o,s,c]};export{l as ClientEntity,f as InvoiceEntity,s as InvoiceStatusEnum,d as JobEntity,o as JobStatusEnum,p as PaymentEntity,c as PaymentMethodEnum,u as QuoteEntity,a as QuoteStatusEnum,m as serviceBusinessEntities,h as serviceBusinessSchemaContribution};
package/dist/events.js ADDED
@@ -0,0 +1 @@
1
+ import{ScalarTypeEnum as e,defineSchemaModel as t}from"@lssm/lib.schema";import{defineEvent as n}from"@lssm/lib.contracts";const r=t({name:`QuoteEventPayload`,description:`Event payload for quote lifecycle`,fields:{quoteId:{type:e.String_unsecure(),isOptional:!1},clientId:{type:e.String_unsecure(),isOptional:!1},amount:{type:e.Float_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!1},orgId:{type:e.String_unsecure(),isOptional:!1},occurredAt:{type:e.DateTime(),isOptional:!1}}}),i=t({name:`JobEventPayload`,description:`Event payload for job lifecycle`,fields:{jobId:{type:e.String_unsecure(),isOptional:!1},quoteId:{type:e.String_unsecure(),isOptional:!0},clientId:{type:e.String_unsecure(),isOptional:!0},status:{type:e.String_unsecure(),isOptional:!1},scheduledAt:{type:e.DateTime(),isOptional:!0},orgId:{type:e.String_unsecure(),isOptional:!1},occurredAt:{type:e.DateTime(),isOptional:!1}}}),a=t({name:`InvoiceEventPayload`,description:`Event payload for invoices`,fields:{invoiceId:{type:e.String_unsecure(),isOptional:!1},jobId:{type:e.String_unsecure(),isOptional:!1},amount:{type:e.Float_unsecure(),isOptional:!1},status:{type:e.String_unsecure(),isOptional:!1},orgId:{type:e.String_unsecure(),isOptional:!1},occurredAt:{type:e.DateTime(),isOptional:!1}}}),o=t({name:`PaymentEventPayload`,description:`Event payload for payments`,fields:{paymentId:{type:e.String_unsecure(),isOptional:!1},invoiceId:{type:e.String_unsecure(),isOptional:!1},amount:{type:e.Float_unsecure(),isOptional:!1},method:{type:e.String_unsecure(),isOptional:!1},orgId:{type:e.String_unsecure(),isOptional:!1},receivedAt:{type:e.DateTime(),isOptional:!1}}}),s=n({name:`service.quote.sent`,version:1,description:`A quote was sent to the client.`,payload:r}),c=n({name:`service.quote.accepted`,version:1,description:`A quote was accepted.`,payload:r}),l=n({name:`service.job.scheduled`,version:1,description:`A job was scheduled.`,payload:i}),u=n({name:`service.job.completed`,version:1,description:`A job was completed.`,payload:i}),d=n({name:`service.invoice.issued`,version:1,description:`An invoice was issued.`,payload:a}),f=n({name:`service.payment.received`,version:1,description:`A payment was recorded.`,payload:o}),p={QuoteSentEvent:s,QuoteAcceptedEvent:c,JobScheduledEvent:l,JobCompletedEvent:u,InvoiceIssuedEvent:d,PaymentReceivedEvent:f};export{d as InvoiceIssuedEvent,u as JobCompletedEvent,l as JobScheduledEvent,f as PaymentReceivedEvent,c as QuoteAcceptedEvent,s as QuoteSentEvent,p as ServiceBusinessEvents};
@@ -0,0 +1 @@
1
+ const e={meta:{key:`service-business-os`,title:`Service Business OS`,description:`Quotes → jobs → invoices → payments for field services and agencies.`,domain:`services`,owners:[`service-os`],tags:[`services`,`quotes`,`jobs`,`invoices`,`payments`],stability:`experimental`},operations:[{name:`service.client.create`,version:1},{name:`service.quote.create`,version:1},{name:`service.quote.accept`,version:1},{name:`service.job.schedule`,version:1},{name:`service.job.complete`,version:1},{name:`service.invoice.issue`,version:1},{name:`service.payment.record`,version:1},{name:`service.job.list`,version:1}],events:[{name:`service.quote.sent`,version:1},{name:`service.quote.accepted`,version:1},{name:`service.job.scheduled`,version:1},{name:`service.job.completed`,version:1},{name:`service.invoice.issued`,version:1},{name:`service.payment.received`,version:1}],presentations:[{name:`service-business-os.dashboard`,version:1},{name:`service-business-os.client.list`,version:1},{name:`service-business-os.quote.list`,version:1},{name:`service-business-os.quote.detail`,version:1},{name:`service-business-os.job.board`,version:1},{name:`service-business-os.invoice.list`,version:1},{name:`service-business-os.payment.list`,version:1}],presentationsTargets:[{name:`service-business-os.dashboard`,version:1,targets:[`react`,`markdown`]},{name:`service-business-os.quote.list`,version:1,targets:[`react`,`markdown`]},{name:`service-business-os.invoice.list`,version:1,targets:[`react`,`markdown`]}],capabilities:{requires:[{key:`identity`,version:1},{key:`audit-trail`,version:1},{key:`notifications`,version:1},{key:`files`,version:1}],provides:[{key:`quotes`,version:1},{key:`jobs`,version:1},{key:`invoices`,version:1}]}};export{e as ServiceBusinessFeature};
@@ -0,0 +1 @@
1
+ function e(){}export{e as registerServiceBusinessHandlers};
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ import{InvoiceIssuedEvent as e,JobCompletedEvent as t,JobScheduledEvent as n,PaymentReceivedEvent as r,QuoteAcceptedEvent as i,QuoteSentEvent as a,ServiceBusinessEvents as o}from"./events.js";import{ServiceBusinessFeature as s}from"./feature.js";import{ClientEntity as c,InvoiceEntity as l,InvoiceStatusEnum as u,JobEntity as d,JobStatusEnum as f,PaymentEntity as p,PaymentMethodEnum as m,QuoteEntity as h,QuoteStatusEnum as g,serviceBusinessEntities as _,serviceBusinessSchemaContribution as v}from"./entities/index.js";import{AcceptQuoteContract as y,ClientModel as b,CompleteJobContract as x,CreateClientContract as S,CreateQuoteContract as C,InvoiceModel as w,IssueInvoiceContract as T,JobModel as E,ListJobsContract as D,PaymentModel as O,QuoteModel as k,RecordPaymentContract as A,ScheduleJobContract as j}from"./contracts/index.js";import{ServiceBusinessPresentations as M}from"./presentations/index.js";import{registerServiceBusinessHandlers as N}from"./handlers/index.js";import"./docs/index.js";import{identityRbacSchemaContribution as P}from"@lssm/lib.identity-rbac";import{auditTrailSchemaContribution as F}from"@lssm/module.audit-trail";import{notificationsSchemaContribution as I}from"@lssm/module.notifications";import{filesSchemaContribution as L}from"@lssm/lib.files";import{jobsSchemaContribution as R}from"@lssm/lib.jobs";const z={modules:[P,F,I,L,R,v],provider:`postgresql`,outputPath:`./prisma/schema/generated.prisma`};export{y as AcceptQuoteContract,c as ClientEntity,b as ClientModel,x as CompleteJobContract,S as CreateClientContract,C as CreateQuoteContract,l as InvoiceEntity,e as InvoiceIssuedEvent,w as InvoiceModel,u as InvoiceStatusEnum,T as IssueInvoiceContract,t as JobCompletedEvent,d as JobEntity,E as JobModel,n as JobScheduledEvent,f as JobStatusEnum,D as ListJobsContract,p as PaymentEntity,m as PaymentMethodEnum,O as PaymentModel,r as PaymentReceivedEvent,i as QuoteAcceptedEvent,h as QuoteEntity,k as QuoteModel,a as QuoteSentEvent,g as QuoteStatusEnum,A as RecordPaymentContract,j as ScheduleJobContract,o as ServiceBusinessEvents,s as ServiceBusinessFeature,M as ServiceBusinessPresentations,N as registerServiceBusinessHandlers,z as schemaComposition,_ as serviceBusinessEntities,v as serviceBusinessSchemaContribution};
@@ -0,0 +1 @@
1
+ const e=[`service-business-os.dashboard`,`service-business-os.client.list`,`service-business-os.quote.list`,`service-business-os.quote.detail`,`service-business-os.job.board`,`service-business-os.invoice.list`,`service-business-os.payment.list`];export{e as ServiceBusinessPresentations};
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@lssm/example.service-business-os",
3
+ "version": "0.0.0-canary-20251212004227",
4
+ "description": "Service Business OS example (clients, quotes, jobs, invoices) for ContractSpec",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "publish:pkg": "bun publish --tolerate-republish --ignore-scripts --verbose",
10
+ "build": "bun build:bundle && bun build:types",
11
+ "build:bundle": "tsdown",
12
+ "build:types": "tsc --noEmit",
13
+ "dev": "bun build:bundle --watch",
14
+ "clean": "rimraf dist .turbo",
15
+ "lint": "bun lint:fix",
16
+ "lint:fix": "eslint src --fix",
17
+ "lint:check": "eslint src"
18
+ },
19
+ "dependencies": {
20
+ "@lssm/lib.schema": "workspace:*",
21
+ "@lssm/lib.contracts": "workspace:*",
22
+ "@lssm/lib.bus": "workspace:*",
23
+ "@lssm/lib.identity-rbac": "workspace:*",
24
+ "@lssm/lib.files": "workspace:*",
25
+ "@lssm/lib.jobs": "workspace:*",
26
+ "@lssm/module.audit-trail": "workspace:*",
27
+ "@lssm/module.notifications": "workspace:*",
28
+ "zod": "^4.1.13"
29
+ },
30
+ "devDependencies": {
31
+ "@lssm/tool.typescript": "workspace:*",
32
+ "@lssm/tool.tsdown": "workspace:*",
33
+ "typescript": "^5.9.3"
34
+ },
35
+ "exports": {
36
+ ".": "./src/index.ts",
37
+ "./contracts": "./src/contracts/index.ts",
38
+ "./docs": "./src/docs/index.ts",
39
+ "./docs/service-business-os.docblock": "./src/docs/service-business-os.docblock.ts",
40
+ "./entities": "./src/entities/index.ts",
41
+ "./events": "./src/events.ts",
42
+ "./feature": "./src/feature.ts",
43
+ "./handlers": "./src/handlers/index.ts",
44
+ "./presentations": "./src/presentations/index.ts",
45
+ "./*": "./*"
46
+ },
47
+ "module": "./dist/index.js",
48
+ "files": [
49
+ "dist",
50
+ "README.md"
51
+ ],
52
+ "publishConfig": {
53
+ "access": "public",
54
+ "exports": {
55
+ ".": "./dist/index.js",
56
+ "./contracts": "./dist/contracts/index.js",
57
+ "./docs": "./dist/docs/index.js",
58
+ "./docs/service-business-os.docblock": "./dist/docs/service-business-os.docblock.js",
59
+ "./entities": "./dist/entities/index.js",
60
+ "./events": "./dist/events.js",
61
+ "./feature": "./dist/feature.js",
62
+ "./handlers": "./dist/handlers/index.js",
63
+ "./presentations": "./dist/presentations/index.js",
64
+ "./*": "./*"
65
+ }
66
+ }
67
+ }