broke out script to define relations to avoid conflicts and circular imports

This commit is contained in:
Khalim Conn-Kowlessar 2023-11-24 16:00:53 +00:00
parent 138153f876
commit 59e47cb02c
7 changed files with 41 additions and 106 deletions

View file

@ -5,6 +5,7 @@ import * as portfolioSchema from "@/app/db/schema/portfolio";
import * as propertySchema from "@/app/db/schema/property";
import * as recommendationSchema from "@/app/db/schema/recommendations";
import * as materialSchema from "@/app/db/schema/materials";
import * as Relations from "@/app/db/schema/relations";
export const pool = new Pool({
host: process.env.DB_HOST,
@ -21,6 +22,7 @@ const schema = {
...propertySchema,
...recommendationSchema,
...materialSchema,
...Relations,
};
export const db = drizzle(pool, {

View file

@ -1,3 +1,4 @@
import { InferModel } from "drizzle-orm";
import {
bigserial,
text,
@ -86,3 +87,5 @@ export const material = pgTable("material", {
cost: json("cost").$type<number[]>(),
notes: text("notes"),
});
export type Material = InferModel<typeof material, "select">;

View file

@ -9,7 +9,7 @@ import {
bigint,
} from "drizzle-orm/pg-core";
import { user } from "./users";
import { InferModel, relations } from "drizzle-orm";
import { InferModel } from "drizzle-orm";
export const PortfolioStatus: [string, ...string[]] = [
"scoping",
@ -70,15 +70,6 @@ export const portfolio = pgTable("portfolio", {
.notNull(),
});
// We have a many to many relationship between users and portfolios
// One user can have many portfolios, and one portfolio can have many users
// We use the Dizzle relational queries pattern to facilitate this
// Define relation from users to portfolios
export const usersToPortfolioRelations = relations(user, ({ many }) => ({
portfolios: many(portfolio),
}));
export const portfolioUsers = pgTable("portfolioUsers", {
id: bigserial("id", { mode: "bigint" }).primaryKey(),
// Define the foreign key constraints using references from Drizzle, from user_id to the users table
@ -104,19 +95,6 @@ export const portfolioUsers = pgTable("portfolioUsers", {
.notNull(),
});
// Define relation from portfolios to users
export const portfolioToUsersRelations = relations(portfolio, ({ many }) => ({
users: many(user),
}));
// Define relation from portfolioUsers to portfolios (we can have many users to a portfolio)
export const portfolioUsersToPortfolioRelations = relations(
portfolioUsers,
({ many }) => ({
portfolio: many(portfolio),
})
);
export type Portfolio = InferModel<typeof portfolio, "select">;
export type NewPortfolio = InferModel<typeof portfolio, "insert">;
export type PortfolioUsers = InferModel<typeof portfolioUsers, "select">;

View file

@ -11,8 +11,7 @@ import {
bigint,
} from "drizzle-orm/pg-core";
import { portfolio, PortfolioStatus } from "./portfolio";
import { recommendation } from "./recommendations";
import { InferModel, relations } from "drizzle-orm";
import { InferModel } from "drizzle-orm";
// This is a placeholder for the property schema
export interface PropertyMeta {
@ -184,26 +183,6 @@ export const propertyTargets = pgTable("property_targets", {
heatDemand: text("heat_demand"),
});
// one to one relationship between property and propertyTargets
export const propertyRelations = relations(property, ({ one, many }) => ({
target: one(propertyTargets, {
fields: [property.id],
references: [propertyTargets.propertyId],
}),
recommendations: many(recommendation),
}));
// Define the other side of the one to many relation between a property and its recomendations
export const recommendationsRelations = relations(
recommendation,
({ one }) => ({
author: one(property, {
fields: [recommendation.propertyId],
references: [property.id],
}),
})
);
// TODO: We'll need a property details buildings materials for verisk data?
export type Property = InferModel<typeof property, "select">;

View file

@ -10,8 +10,8 @@ import {
bigint,
pgEnum,
} from "drizzle-orm/pg-core";
import { material } from "./materials";
import { InferModel, relations } from "drizzle-orm";
import { Material, material } from "./materials";
import { InferModel } from "drizzle-orm";
export const recommendation = pgTable("recommendation", {
id: bigserial("id", { mode: "bigint" }).primaryKey(),
@ -81,66 +81,16 @@ export const planRecommendations = pgTable("plan_recommendations", {
.references(() => recommendation.id),
});
// create a one to many relation to map a plan to the details in the underlying recommendation
// create a many to many map from a plan to a recommendation
// A recommendation can be in multiple plans and therefore we have a many to many relationship between
// plan and recommendations. This relationship is facilitated by the planRecommdnations table
export const planRelations = relations(plan, ({ many }) => ({
planRecommendations: many(planRecommendations),
}));
export const planRecommendationsRelations = relations(
planRecommendations,
({ one }) => ({
plan: one(plan, {
fields: [planRecommendations.planId],
references: [plan.id],
}),
recommendation: one(recommendation, {
fields: [planRecommendations.recommendationId],
references: [recommendation.id],
}),
})
);
// We construct a relationship between a recommendation and recommendationMaterials
// On recommendationMaterial will map to a single recommendation
// Define the relationships for the recommendation table
export const recommendationRelations = relations(
recommendation,
({ many }) => ({
recommendationMaterials: many(recommendationMaterials),
})
);
// Define the relationships for the material table
export const materialRelations = relations(material, ({ many }) => ({
recommendationMaterials: many(recommendationMaterials),
}));
// Define the relationships for the recommendationMaterials table
export const recommendationMaterialsRelations = relations(
recommendationMaterials,
({ one }) => ({
recommendation: one(recommendation, {
fields: [recommendationMaterials.recommendationId],
references: [recommendation.id],
}),
material: one(material, {
fields: [recommendationMaterials.materialId],
references: [material.id],
}),
})
);
export type Plan = InferModel<typeof plan, "select">;
export type Recommendation = InferModel<typeof recommendation, "select">;
export type PlanRecommendations = InferModel<
typeof planRecommendations,
"select"
>;
export type RecommendationMaterial = InferModel<
typeof recommendationMaterials,
"select"
>;
// We allow recommendation types to be a string however we'll set up a typing for it here to control
// the types we expect
@ -166,3 +116,25 @@ export interface PortfolioPlanRecommendation {
materialType: string;
numberOfProperties: number;
}
export interface RecommendationMaterialToMaterial extends Material {
material: Material;
}
export interface RecommendationWithMaterials {
id: string;
type: RecommendationType;
description: string;
estimatedCost: number;
startingUValue: number;
newUValue: number;
sapPoints: number;
heatDemand: number;
co2EquivalentSavings: number;
energySavings: number;
energyCostSavings: number;
propertyValuationIncrease: number;
rentalYieldIncrease: number;
totalWorkHours: number;
recommendationMaterials: RecommendationMaterialToMaterial[];
}

View file

@ -24,16 +24,16 @@ import { useState } from "react";
import { DataTablePagination } from "./propertyTablePagination";
import React from "react";
import { Input } from "@/app/shadcn_components/ui/input";
import { PropertyWithTarget } from "@/app/db/schema/property";
import { PropertyWithRelations } from "@/app/db/schema/property";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<PropertyWithTarget>[];
data: PropertyWithTarget[];
columns: ColumnDef<PropertyWithRelations>[];
data: PropertyWithRelations[];
}
function fetchData(offset: number) {
// Because this is a client component, this will be handled with react query
let properties: PropertyWithTarget[] = [];
let properties: PropertyWithRelations[] = [];
// TODO: implement this
return properties;
}
@ -43,7 +43,7 @@ export default function DataTable<TData, TValue>({
columns,
}: DataTableProps<TData, TValue>) {
const [sorting, setSorting] = useState<SortingState>([]);
const [tableData, setTableData] = useState<PropertyWithTarget[]>(data);
const [tableData, setTableData] = useState<PropertyWithRelations[]>(data);
const [offset, setOffset] = useState(0);
const [currentPageIndex, setCurrentPageIndex] = useState(0);
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(

View file

@ -2,6 +2,7 @@ import {
recommendation,
UnnestedRecommendation,
PortfolioPlanRecommendation,
RecommendationWithMaterials,
} from "./../../db/schema/recommendations";
import { and, eq, inArray } from "drizzle-orm";
import { db } from "@/app/db/db";