mirror of
https://github.com/Sea-Haven-Industries/proposal-system.git
synced 2026-09-30 10:03:14 +00:00
Some checks are pending
Deploy / Deploy to AWS (push) Waiting to run
Adds a managed pricing library so admins can seed/curate reference priced items
directly, instead of the corpus being populated only by ingesting Sent proposals.
v1 PR5.
API:
- PricingLibraryItem entity + migration; /api/pricing-library CRUD (admin), with
GET {id} reachable by internal Lambda callers (admins role via internal key).
- Create/update publish an ADDITIVE library-ingest SQS job {pricingLibraryItemId},
wrapped so a publish failure never rolls back the save.
Lambda (library-ingest):
- Additive event-shape branch: pricingLibraryItemId -> fetch item, format markdown,
upload to pricing-library/{category}/{id}.md, trigger KB sync. The existing
proposalId path is byte-for-byte unchanged. Explicit error when neither id present;
warns when both present.
Web:
- Pricing Library management page (/admin/pricing-library): list / create / edit / delete.
GPT-4.1 cross-review on the event-shape change: no BLOCK (neither/both-id handling
applied). Verified: api 159 tests; web tsc + 26 tests; lambdas ruff + 37 pytest.
122 lines
2.9 KiB
TypeScript
122 lines
2.9 KiB
TypeScript
export type ProposalStatus = 'Draft' | 'InReview' | 'Approved' | 'Sent' | 'Revised';
|
|
// Fix: WEB-M4 — align with API enum (ProposalSystem.Domain.Entities.ServiceCategory includes 'Other')
|
|
export type ServiceCategory = 'HVAC' | 'Plumbing' | 'Electrical' | 'General' | 'Renovation' | 'Other';
|
|
export type Priority = 'Standard' | 'Urgent' | 'Emergency';
|
|
export type LineItemSource = 'AI' | 'Vendor' | 'Manual' | 'Historical';
|
|
export type PricingMode = 'UnitPrice' | 'TotalPrice' | 'Both';
|
|
export type UserRole = 'Dispatcher' | 'Admin' | 'SysAdmin';
|
|
|
|
export interface Proposal {
|
|
id: string;
|
|
proposalNumber: string;
|
|
workOrderNumber: string;
|
|
customerName: string;
|
|
customerAddress: string;
|
|
scopeOfWork: string;
|
|
refinedScope: string | null;
|
|
serviceCategory: ServiceCategory;
|
|
priority: Priority;
|
|
status: ProposalStatus;
|
|
totalBidAmount: number;
|
|
vendorTotalCost: number | null;
|
|
notes: string;
|
|
submittedById: string;
|
|
submittedAt: string;
|
|
assignedAdminId: string | null;
|
|
approvedById: string | null;
|
|
approvedAt: string | null;
|
|
sentAt: string | null;
|
|
currentRevision: number;
|
|
parentProposalId: string | null;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface LineItem {
|
|
id: string;
|
|
proposalId: string;
|
|
description: string;
|
|
quantity: number;
|
|
unit: string;
|
|
unitPrice: number | null;
|
|
totalPrice: number;
|
|
pricingMode: PricingMode;
|
|
sortOrder: number;
|
|
source: LineItemSource;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface CreateProposalRequest {
|
|
workOrderNumber: string;
|
|
customerName: string;
|
|
customerAddress: string;
|
|
scopeOfWork: string;
|
|
serviceCategory: ServiceCategory;
|
|
priority: Priority;
|
|
notes?: string;
|
|
}
|
|
|
|
export interface UpdateLineItemsRequest {
|
|
lineItems: Omit<LineItem, 'id' | 'proposalId' | 'createdAt' | 'updatedAt'>[];
|
|
}
|
|
|
|
export interface Customer {
|
|
id: string;
|
|
name: string;
|
|
addresses: string[];
|
|
contactEmail: string | null;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface CreateCustomerRequest {
|
|
name: string;
|
|
addresses?: string[];
|
|
contactEmail?: string;
|
|
}
|
|
|
|
export interface UpdateCustomerRequest {
|
|
name?: string;
|
|
addresses?: string[];
|
|
contactEmail?: string | null;
|
|
}
|
|
|
|
export interface PagedResponse<T> {
|
|
items: T[];
|
|
totalCount: number;
|
|
page: number;
|
|
pageSize: number;
|
|
}
|
|
|
|
// PR5: Pricing Library types
|
|
export interface PricingLibraryItem {
|
|
id: string;
|
|
title: string;
|
|
description: string | null;
|
|
serviceCategory: ServiceCategory;
|
|
unit: string | null;
|
|
unitPrice: number | null;
|
|
keywords: string | null;
|
|
source: string;
|
|
createdAt: string;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface CreatePricingLibraryItemRequest {
|
|
title: string;
|
|
description?: string;
|
|
serviceCategory: ServiceCategory;
|
|
unit?: string;
|
|
unitPrice?: number;
|
|
keywords?: string;
|
|
source?: string;
|
|
}
|
|
|
|
export interface UpdatePricingLibraryItemRequest {
|
|
title?: string;
|
|
description?: string;
|
|
serviceCategory?: ServiceCategory;
|
|
unit?: string;
|
|
unitPrice?: number;
|
|
keywords?: string;
|
|
}
|