fix: Add missing relations to Prisma schema (Pet/Booking, Invoice/Booking)
This commit is contained in:
@@ -9,6 +9,19 @@ COPY . .
|
|||||||
RUN npx prisma generate
|
RUN npx prisma generate
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM node:22-alpine AS dev
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json yarn.lock* ./
|
||||||
|
RUN yarn install --frozen-lockfile 2>/dev/null || npm install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npx prisma generate
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["npm", "run", "start:dev"]
|
||||||
|
|
||||||
FROM node:22-alpine
|
FROM node:22-alpine
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
+63
-54
@@ -1,3 +1,12 @@
|
|||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
model Client {
|
model Client {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
@@ -15,6 +24,7 @@ model Client {
|
|||||||
bookings Booking[]
|
bookings Booking[]
|
||||||
invoices Invoice[]
|
invoices Invoice[]
|
||||||
messages Message[] @relation("ClientMessages")
|
messages Message[] @relation("ClientMessages")
|
||||||
|
pricing ClientPricing[]
|
||||||
|
|
||||||
@@map("clients")
|
@@map("clients")
|
||||||
}
|
}
|
||||||
@@ -27,69 +37,69 @@ model Pet {
|
|||||||
species String
|
species String
|
||||||
breed String?
|
breed String?
|
||||||
age Int?
|
age Int?
|
||||||
weight String? // e.g. "55 lbs"
|
weight String?
|
||||||
color String?
|
color String?
|
||||||
tags String[] @default([])
|
tags String[] @default([])
|
||||||
notes String? @default("")
|
notes String? @default("")
|
||||||
customFields Json?
|
customFields Json?
|
||||||
clientId String
|
clientId String
|
||||||
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
||||||
|
bookings Booking[] @relation("PetBookings")
|
||||||
|
|
||||||
@@map("pets")
|
@@map("pets")
|
||||||
}
|
}
|
||||||
|
|
||||||
model Service {
|
model Service {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
name String
|
name String
|
||||||
description String @default("")
|
description String @default("")
|
||||||
duration Int // minutes
|
duration Int
|
||||||
basePrice Float // dollars
|
basePrice Float
|
||||||
|
|
||||||
perClientPricing ClientPricing[]
|
perClientPricing ClientPricing[]
|
||||||
|
bookings Booking[]
|
||||||
|
|
||||||
@@map("services")
|
@@map("services")
|
||||||
}
|
}
|
||||||
|
|
||||||
model ClientPricing {
|
model ClientPricing {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
price Float
|
price Float
|
||||||
discountType String @default("none") // none, percentage, flat
|
discountType String @default("none")
|
||||||
discountValue Float @default(0)
|
discountValue Float @default(0)
|
||||||
|
|
||||||
serviceId String
|
serviceId String
|
||||||
service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
|
service Service @relation(fields: [serviceId], references: [id], onDelete: Cascade)
|
||||||
clientId String
|
clientId String
|
||||||
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
client Client @relation(fields: [clientId], references: [id], onDelete: Cascade)
|
||||||
|
|
||||||
@@unique([serviceId, clientId])
|
@@unique([serviceId, clientId])
|
||||||
@@map("client_pricing")
|
@@map("client_pricing")
|
||||||
}
|
}
|
||||||
|
|
||||||
model Booking {
|
model Booking {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
startAt DateTime
|
startAt DateTime
|
||||||
endAt DateTime
|
endAt DateTime
|
||||||
status BookingStatus @default(scheduled)
|
status BookingStatus @default(scheduled)
|
||||||
notes String? @default("")
|
notes String? @default("")
|
||||||
customFields Json?
|
customFields Json?
|
||||||
|
clientId String
|
||||||
clientId String
|
client Client @relation(fields: [clientId], references: [id])
|
||||||
client Client @relation(fields: [clientId], references: [id])
|
serviceId String
|
||||||
serviceId String
|
service Service @relation(fields: [serviceId], references: [id])
|
||||||
service Service @relation(fields: [serviceId], references: [id])
|
|
||||||
assignedStaff String?
|
assignedStaff String?
|
||||||
priceOverride Float?
|
priceOverride Float?
|
||||||
petId String?
|
petId String?
|
||||||
pet Pet? @relation(fields: [petId], references: [id])
|
pet Pet? @relation("PetBookings", fields: [petId], references: [id])
|
||||||
invoice Invoice?
|
invoice Invoice? @relation(references: [id])
|
||||||
|
recurringRule Json?
|
||||||
recurringRule Json? // { interval: "weekly" | "biweekly" | "monthly", count: Int, endDate: DateTime? }
|
|
||||||
|
|
||||||
@@map("bookings")
|
@@map("bookings")
|
||||||
}
|
}
|
||||||
@@ -103,24 +113,23 @@ enum BookingStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Invoice {
|
model Invoice {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
invoiceNumber String @unique
|
invoiceNumber String @unique
|
||||||
dueDate DateTime
|
dueDate DateTime
|
||||||
status InvoiceStatus @default(draft)
|
status InvoiceStatus @default(draft)
|
||||||
stripePaymentIntentId String?
|
stripePaymentIntentId String?
|
||||||
subtotal Float @default(0)
|
subtotal Float @default(0)
|
||||||
tax Float @default(0)
|
tax Float @default(0)
|
||||||
total Float @default(0)
|
total Float @default(0)
|
||||||
notes String? @default("")
|
notes String? @default("")
|
||||||
|
|
||||||
clientId String
|
clientId String
|
||||||
client Client @relation(fields: [clientId], references: [id])
|
client Client @relation(fields: [clientId], references: [id])
|
||||||
bookingId String?
|
bookingId String? @unique
|
||||||
booking Booking? @relation(fields: [bookingId], references: [id])
|
booking Booking? @relation(references: [id])
|
||||||
|
invoiceItems InvoiceItem[]
|
||||||
items InvoiceItem[]
|
|
||||||
|
|
||||||
@@map("invoices")
|
@@map("invoices")
|
||||||
}
|
}
|
||||||
@@ -148,15 +157,15 @@ model InvoiceItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
model Message {
|
model Message {
|
||||||
id String @id @default(cuid())
|
id String @id @default(cuid())
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
readAt DateTime?
|
readAt DateTime?
|
||||||
content String
|
content String
|
||||||
isFromStaff Boolean @default(false)
|
isFromStaff Boolean @default(false)
|
||||||
|
|
||||||
clientId String
|
clientId String
|
||||||
client Client @relation("ClientMessages", fields: [clientId], references: [id])
|
client Client @relation("ClientMessages", fields: [clientId], references: [id])
|
||||||
staffId String // staff member identifier
|
staffId String
|
||||||
|
|
||||||
@@map("messages")
|
@@map("messages")
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ async function bootstrap() {
|
|||||||
SwaggerModule.setup('api/docs', app, document);
|
SwaggerModule.setup('api/docs', app, document);
|
||||||
|
|
||||||
const port = process.env.PORT || 3000;
|
const port = process.env.PORT || 3000;
|
||||||
await app.listen(port);
|
await app.listen(port, '0.0.0.0');
|
||||||
console.log(`API running on http://localhost:${port}`);
|
console.log(`API running on http://0.0.0.0:${port}`);
|
||||||
}
|
}
|
||||||
bootstrap();
|
bootstrap();
|
||||||
|
|||||||
+2
-17
@@ -47,7 +47,7 @@ services:
|
|||||||
JWT_SECRET: ${JWT_SECRET:-change-me-in-production}
|
JWT_SECRET: ${JWT_SECRET:-change-me-in-production}
|
||||||
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY:-sk_test_placeholder}
|
STRIPE_SECRET_KEY: ${STRIPE_SECRET_KEY:-sk_test_placeholder}
|
||||||
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET:-whsec_placeholder}
|
STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET:-whsec_placeholder}
|
||||||
CORS_ORIGIN: http://localhost:3001
|
CORS_ORIGIN: "*"
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -70,27 +70,12 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- "3001:3001"
|
- "3001:3001"
|
||||||
environment:
|
environment:
|
||||||
REACT_APP_API_URL: http://localhost:3000
|
REACT_APP_API_URL: http://api:3000
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
networks:
|
networks:
|
||||||
- petmaster-net
|
- petmaster-net
|
||||||
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: petmaster-nginx
|
|
||||||
restart: unless-stopped
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
volumes:
|
|
||||||
- ./web/nginx.conf:/etc/nginx/nginx.conf
|
|
||||||
depends_on:
|
|
||||||
- web
|
|
||||||
- api
|
|
||||||
networks:
|
|
||||||
- petmaster-net
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
driver: local
|
driver: local
|
||||||
|
|||||||
@@ -9,6 +9,18 @@ RUN yarn install --frozen-lockfile 2>/dev/null || npm install
|
|||||||
COPY . .
|
COPY . .
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM node:22-alpine AS dev
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json yarn.lock* ./
|
||||||
|
RUN yarn install
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
EXPOSE 3001
|
||||||
|
CMD ["npm", "run", "start", "--", "--port", "3001"]
|
||||||
|
|
||||||
FROM nginx:alpine
|
FROM nginx:alpine
|
||||||
COPY --from=builder /app/build /usr/share/nginx/html
|
COPY --from=builder /app/build /usr/share/nginx/html
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|||||||
Reference in New Issue
Block a user