Build the Solaire inventory intelligence MVP
Some checks failed
CI / verify (push) Has been cancelled

Add the tenant-ready dashboard, freshness and pricing analytics, mock integration adapters, persistence schema, and verification tooling needed for the initial pilot.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-25 12:16:52 -07:00
parent bf336f8d15
commit 135be480e5
58 changed files with 7884 additions and 265 deletions

18
src/db/index.ts Normal file
View File

@@ -0,0 +1,18 @@
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import * as schema from "@/db/schema";
let client: ReturnType<typeof postgres> | undefined;
export function getDatabase() {
if (!process.env.DATABASE_URL) {
throw new Error("DATABASE_URL is required for persistent database access");
}
client ??= postgres(process.env.DATABASE_URL, {
max: process.env.NODE_ENV === "production" ? 10 : 1,
prepare: false,
});
return drizzle(client, { schema });
}

194
src/db/schema.ts Normal file
View File

@@ -0,0 +1,194 @@
import {
boolean,
index,
integer,
jsonb,
numeric,
pgEnum,
pgTable,
primaryKey,
text,
timestamp,
uniqueIndex,
uuid,
} from "drizzle-orm/pg-core";
const id = () => uuid("id").defaultRandom().primaryKey();
const tenant = () => uuid("organization_id").notNull().references(() => organizations.id);
const timestamps = {
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp("updated_at", { withTimezone: true }).defaultNow().notNull(),
};
export const integrationProvider = pgEnum("integration_provider", ["odoo", "salesforce"]);
export const freshnessState = pgEnum("freshness_state", ["fresh", "watch", "at_risk", "expired"]);
export const recommendationState = pgEnum("recommendation_state", ["pending", "reviewed", "dismissed"]);
export const syncState = pgEnum("sync_state", ["queued", "running", "succeeded", "failed"]);
export const memberRole = pgEnum("member_role", ["owner", "manager", "viewer"]);
export const organizations = pgTable("organizations", {
id: id(),
name: text("name").notNull(),
slug: text("slug").notNull().unique(),
...timestamps,
});
export const users = pgTable("users", {
id: id(),
email: text("email").notNull().unique(),
name: text("name").notNull(),
passwordHash: text("password_hash"),
...timestamps,
});
export const memberships = pgTable(
"memberships",
{
organizationId: uuid("organization_id").notNull().references(() => organizations.id),
userId: uuid("user_id").notNull().references(() => users.id),
role: memberRole("role").default("viewer").notNull(),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
},
(table) => [primaryKey({ columns: [table.organizationId, table.userId] })],
);
export const branches = pgTable("branches", {
id: id(),
organizationId: tenant(),
name: text("name").notNull(),
city: text("city").notNull(),
region: text("region").notNull(),
sourceId: text("source_id"),
...timestamps,
}, (table) => [
index("branches_organization_idx").on(table.organizationId),
uniqueIndex("branches_source_unique").on(table.organizationId, table.sourceId),
]);
export const salespeople = pgTable("salespeople", {
id: id(),
organizationId: tenant(),
branchId: uuid("branch_id").notNull().references(() => branches.id),
name: text("name").notNull(),
email: text("email"),
sourceId: text("source_id"),
...timestamps,
}, (table) => [index("salespeople_organization_idx").on(table.organizationId)]);
export const products = pgTable("products", {
id: id(),
organizationId: tenant(),
sku: text("sku").notNull(),
name: text("name").notNull(),
category: text("category").notNull(),
unit: text("unit").notNull(),
shelfLifeDays: integer("shelf_life_days").notNull(),
cost: numeric("cost", { precision: 12, scale: 2 }).notNull(),
listPrice: numeric("list_price", { precision: 12, scale: 2 }).notNull(),
marginFloorPercent: numeric("margin_floor_percent", { precision: 5, scale: 2 }).notNull(),
sourceSystem: integrationProvider("source_system").notNull(),
sourceId: text("source_id").notNull(),
...timestamps,
}, (table) => [
uniqueIndex("products_sku_unique").on(table.organizationId, table.sku),
uniqueIndex("products_source_unique").on(table.organizationId, table.sourceSystem, table.sourceId),
]);
export const inventoryBatches = pgTable("inventory_batches", {
id: id(),
organizationId: tenant(),
productId: uuid("product_id").notNull().references(() => products.id),
branchId: uuid("branch_id").notNull().references(() => branches.id),
receivedAt: timestamp("received_at", { withTimezone: true }).notNull(),
quantityReceived: integer("quantity_received").notNull(),
quantityOnHand: integer("quantity_on_hand").notNull(),
freshnessScore: integer("freshness_score").notNull(),
freshnessState: freshnessState("freshness_state").notNull(),
sourceId: text("source_id").notNull(),
...timestamps,
}, (table) => [
index("inventory_tenant_product_idx").on(table.organizationId, table.productId),
uniqueIndex("inventory_source_unique").on(table.organizationId, table.sourceId),
]);
export const sales = pgTable("sales", {
id: id(),
organizationId: tenant(),
productId: uuid("product_id").notNull().references(() => products.id),
branchId: uuid("branch_id").notNull().references(() => branches.id),
salespersonId: uuid("salesperson_id").references(() => salespeople.id),
soldAt: timestamp("sold_at", { withTimezone: true }).notNull(),
quantity: integer("quantity").notNull(),
unitPrice: numeric("unit_price", { precision: 12, scale: 2 }).notNull(),
sourceId: text("source_id").notNull(),
...timestamps,
}, (table) => [
index("sales_tenant_date_idx").on(table.organizationId, table.soldAt),
uniqueIndex("sales_source_unique").on(table.organizationId, table.sourceId),
]);
export const integrationConnections = pgTable("integration_connections", {
id: id(),
organizationId: tenant(),
provider: integrationProvider("provider").notNull(),
displayName: text("display_name").notNull(),
enabled: boolean("enabled").default(false).notNull(),
encryptedCredentials: text("encrypted_credentials"),
configuration: jsonb("configuration").$type<Record<string, unknown>>().default({}).notNull(),
lastSyncedAt: timestamp("last_synced_at", { withTimezone: true }),
...timestamps,
}, (table) => [uniqueIndex("integration_provider_unique").on(table.organizationId, table.provider)]);
export const syncRuns = pgTable("sync_runs", {
id: id(),
organizationId: tenant(),
connectionId: uuid("connection_id").references(() => integrationConnections.id),
provider: integrationProvider("provider").notNull(),
state: syncState("state").default("queued").notNull(),
cursor: text("cursor"),
recordsRead: integer("records_read").default(0).notNull(),
recordsWritten: integer("records_written").default(0).notNull(),
error: text("error"),
startedAt: timestamp("started_at", { withTimezone: true }),
finishedAt: timestamp("finished_at", { withTimezone: true }),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
});
export const recommendations = pgTable("recommendations", {
id: id(),
organizationId: tenant(),
productId: uuid("product_id").notNull().references(() => products.id),
branchId: uuid("branch_id").notNull().references(() => branches.id),
type: text("type").notNull(),
currentPrice: numeric("current_price", { precision: 12, scale: 2 }).notNull(),
recommendedLow: numeric("recommended_low", { precision: 12, scale: 2 }).notNull(),
recommendedHigh: numeric("recommended_high", { precision: 12, scale: 2 }).notNull(),
confidence: integer("confidence").notNull(),
explanation: text("explanation").notNull(),
state: recommendationState("state").default("pending").notNull(),
expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
reviewedBy: uuid("reviewed_by").references(() => users.id),
...timestamps,
});
export const alerts = pgTable("alerts", {
id: id(),
organizationId: tenant(),
inventoryBatchId: uuid("inventory_batch_id").references(() => inventoryBatches.id),
severity: text("severity").notNull(),
title: text("title").notNull(),
message: text("message").notNull(),
acknowledgedAt: timestamp("acknowledged_at", { withTimezone: true }),
...timestamps,
}, (table) => [index("alerts_tenant_idx").on(table.organizationId)]);
export const auditEvents = pgTable("audit_events", {
id: id(),
organizationId: tenant(),
userId: uuid("user_id").references(() => users.id),
action: text("action").notNull(),
entityType: text("entity_type").notNull(),
entityId: text("entity_id").notNull(),
metadata: jsonb("metadata").$type<Record<string, unknown>>().default({}).notNull(),
createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull(),
});