diff --git a/design_temp/validate_counties.py b/design_temp/validate_counties.py index 71fa4985..e80cd7a5 100644 --- a/design_temp/validate_counties.py +++ b/design_temp/validate_counties.py @@ -8,15 +8,19 @@ CENSUS_DOCS_BASE_URL = "https://www2.census.gov/geo/docs/reference" CENSUS_STATE_PATH = "/state.txt" CENSUS_COUNTY_PATH = "/codes2020/national_county2020.txt" -CENSUS_DELIMETER = '|' -NEW_LINE = '\n' -NEW_HEADERS="state_id,state_name,state_abbr,county_fp,county_ns,county_name,county_design_temp" +CENSUS_DELIMETER = "|" +NEW_LINE = "\n" +NEW_HEADERS = ( + "state_id,state_name,state_abbr,county_fp,county_ns,county_name,county_design_temp" +) + class State(BaseModel): state_id: str state_abbr: str state_name: str + class County(BaseModel): state_id: str state_abbr: str @@ -25,65 +29,76 @@ class County(BaseModel): county_ns: str county_name: str + class DTBC(BaseModel): state: str county: str temp: int + _counties = {} -_states={} -_dtbc={} +_states = {} +_dtbc = {} + + def load_design_temp_data(): - with open(DESIGN_TEMP_DIR / "design_temp_by_county.csv") as f: reader = csv.DictReader(f) for row in reader: item = DTBC( - state=row["state"], county=row["county"],temp=row["design_temp"] + state=row["state"], county=row["county"], temp=row["design_temp"] ) if row["state"] in _dtbc: - _dtbc[row["state"]].append(item) + _dtbc[row["state"]].append(item) else: _dtbc[row["state"]] = [item] - + def fetch_census_counties(): census_url = CENSUS_DOCS_BASE_URL + CENSUS_COUNTY_PATH response = requests.get(census_url) - reader = csv.DictReader(f=io.StringIO(response.text),delimiter=CENSUS_DELIMETER) + reader = csv.DictReader(f=io.StringIO(response.text), delimiter=CENSUS_DELIMETER) for row in reader: sid = row["STATEFP"] sn = _states[sid].state_name item = County( - state_id=sid, state_abbr=_states[sid].state_abbr, state_name=sn,county_fp=row["COUNTYFP"], county_ns=row["COUNTYNS"],county_name=row["COUNTYNAME"] + state_id=sid, + state_abbr=_states[sid].state_abbr, + state_name=sn, + county_fp=row["COUNTYFP"], + county_ns=row["COUNTYNS"], + county_name=row["COUNTYNAME"], ) _counties[sn].append(item) - + + def fetch_census_states(): states_url = CENSUS_DOCS_BASE_URL + CENSUS_STATE_PATH response = requests.get(states_url) - reader = csv.DictReader(f=io.StringIO(response.text),delimiter=CENSUS_DELIMETER) + reader = csv.DictReader(f=io.StringIO(response.text), delimiter=CENSUS_DELIMETER) for row in reader: _counties[row["STATE_NAME"]] = [] item = State( - state_id=row["STATE"], state_abbr=row["STUSAB"], state_name=row["STATE_NAME"] + state_id=row["STATE"], + state_abbr=row["STUSAB"], + state_name=row["STATE_NAME"], ) _states[row["STATE"]] = item - if __name__ == "__main__": - fetch_census_states() fetch_census_counties() load_design_temp_data() - with open(DESIGN_TEMP_DIR / "merged_structure_temps.csv", "w", newline=NEW_LINE) as oFile: + with open( + DESIGN_TEMP_DIR / "merged_structure_temps.csv", "w", newline=NEW_LINE + ) as oFile: oFile.write(NEW_HEADERS) for s, cbs in _counties.items(): d_row = _dtbc.get(s) @@ -91,5 +106,5 @@ def fetch_census_states(): for d in d_row: for c in cbs: if d.county in c.county_name: - ostr=f"\n{c.state_id},{s},{c.state_abbr},{c.county_fp},{c.county_ns},{d.county},{d.temp}" - oFile.write(ostr) \ No newline at end of file + ostr = f"\n{c.state_id},{s},{c.state_abbr},{c.county_fp},{c.county_ns},{d.county},{d.temp}" + oFile.write(ostr) diff --git a/heat-stack/package-lock.json b/heat-stack/package-lock.json index 7f6dbeff..397cab4b 100644 --- a/heat-stack/package-lock.json +++ b/heat-stack/package-lock.json @@ -15,7 +15,7 @@ "@epic-web/totp": "^1.1.2", "@nasa-gcn/remix-seo": "^2.0.1", "@paralleldrive/cuid2": "^2.2.2", - "@prisma/client": "^5.17.0", + "@prisma/client": "^5.19.1", "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-label": "^2.1.0", @@ -54,7 +54,6 @@ "lru-cache": "^11.0.0", "lucide-react": "^0.428.0", "morgan": "^1.10.0", - "prisma": "^5.17.0", "pyodide": "0.24.1", "qrcode": "^1.5.3", "react": "^18.3.1", @@ -116,6 +115,7 @@ "prettier": "^3.3.3", "prettier-plugin-sql": "^0.18.1", "prettier-plugin-tailwindcss": "^0.6.5", + "prisma": "^5.19.1", "remix-flat-routes": "^0.6.5", "tsx": "^4.16.2", "typescript": "^5.5.3", @@ -1878,9 +1878,10 @@ } }, "node_modules/@prisma/client": { - "version": "5.17.0", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/client/-/client-5.19.1.tgz", + "integrity": "sha512-x30GFguInsgt+4z5I4WbkZP2CGpotJMUXy+Gl/aaUjHn2o1DnLYNTA+q9XdYmAQZM8fIIkvUiA2NpgosM3fneg==", "hasInstallScript": true, - "license": "Apache-2.0", "engines": { "node": ">=16.13" }, @@ -1894,38 +1895,48 @@ } }, "node_modules/@prisma/debug": { - "version": "5.17.0", - "license": "Apache-2.0" + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/debug/-/debug-5.19.1.tgz", + "integrity": "sha512-lAG6A6QnG2AskAukIEucYJZxxcSqKsMK74ZFVfCTOM/7UiyJQi48v6TQ47d6qKG3LbMslqOvnTX25dj/qvclGg==", + "dev": true }, "node_modules/@prisma/engines": { - "version": "5.17.0", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/engines/-/engines-5.19.1.tgz", + "integrity": "sha512-kR/PoxZDrfUmbbXqqb8SlBBgCjvGaJYMCOe189PEYzq9rKqitQ2fvT/VJ8PDSe8tTNxhc2KzsCfCAL+Iwm/7Cg==", + "dev": true, "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { - "@prisma/debug": "5.17.0", - "@prisma/engines-version": "5.17.0-31.393aa359c9ad4a4bb28630fb5613f9c281cde053", - "@prisma/fetch-engine": "5.17.0", - "@prisma/get-platform": "5.17.0" + "@prisma/debug": "5.19.1", + "@prisma/engines-version": "5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3", + "@prisma/fetch-engine": "5.19.1", + "@prisma/get-platform": "5.19.1" } }, "node_modules/@prisma/engines-version": { - "version": "5.17.0-31.393aa359c9ad4a4bb28630fb5613f9c281cde053", - "license": "Apache-2.0" + "version": "5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3", + "resolved": "https://registry.npmjs.org/@prisma/engines-version/-/engines-version-5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3.tgz", + "integrity": "sha512-xR6rt+z5LnNqTP5BBc+8+ySgf4WNMimOKXRn6xfNRDSpHvbOEmd7+qAOmzCrddEc4Cp8nFC0txU14dstjH7FXA==", + "dev": true }, "node_modules/@prisma/fetch-engine": { - "version": "5.17.0", - "license": "Apache-2.0", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/fetch-engine/-/fetch-engine-5.19.1.tgz", + "integrity": "sha512-pCq74rtlOVJfn4pLmdJj+eI4P7w2dugOnnTXpRilP/6n5b2aZiA4ulJlE0ddCbTPkfHmOL9BfaRgA8o+1rfdHw==", + "dev": true, "dependencies": { - "@prisma/debug": "5.17.0", - "@prisma/engines-version": "5.17.0-31.393aa359c9ad4a4bb28630fb5613f9c281cde053", - "@prisma/get-platform": "5.17.0" + "@prisma/debug": "5.19.1", + "@prisma/engines-version": "5.19.1-2.69d742ee20b815d88e17e54db4a2a7a3b30324e3", + "@prisma/get-platform": "5.19.1" } }, "node_modules/@prisma/get-platform": { - "version": "5.17.0", - "license": "Apache-2.0", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/@prisma/get-platform/-/get-platform-5.19.1.tgz", + "integrity": "sha512-sCeoJ+7yt0UjnR+AXZL7vXlg5eNxaFOwC23h0KvW1YIXUoa7+W2ZcAUhoEQBmJTW4GrFqCuZ8YSP0mkDa4k3Zg==", + "dev": true, "dependencies": { - "@prisma/debug": "5.17.0" + "@prisma/debug": "5.19.1" } }, "node_modules/@prisma/instrumentation": { @@ -13220,17 +13231,22 @@ } }, "node_modules/prisma": { - "version": "5.17.0", + "version": "5.19.1", + "resolved": "https://registry.npmjs.org/prisma/-/prisma-5.19.1.tgz", + "integrity": "sha512-c5K9MiDaa+VAAyh1OiYk76PXOme9s3E992D7kvvIOhCrNsBQfy2mP2QAQtX0WNj140IgG++12kwZpYB9iIydNQ==", + "dev": true, "hasInstallScript": true, - "license": "Apache-2.0", "dependencies": { - "@prisma/engines": "5.17.0" + "@prisma/engines": "5.19.1" }, "bin": { "prisma": "build/index.js" }, "engines": { "node": ">=16.13" + }, + "optionalDependencies": { + "fsevents": "2.3.3" } }, "node_modules/prismjs": { diff --git a/heat-stack/package.json b/heat-stack/package.json index 1f4ede24..22bc77b6 100644 --- a/heat-stack/package.json +++ b/heat-stack/package.json @@ -50,7 +50,7 @@ "@epic-web/totp": "^1.1.2", "@nasa-gcn/remix-seo": "^2.0.1", "@paralleldrive/cuid2": "^2.2.2", - "@prisma/client": "^5.17.0", + "@prisma/client": "^5.19.1", "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", "@radix-ui/react-label": "^2.1.0", @@ -86,10 +86,9 @@ "intl-parse-accept-language": "^1.0.0", "isbot": "^5.1.13", "litefs-js": "^1.1.2", - "lucide-react": "^0.428.0", "lru-cache": "^11.0.0", + "lucide-react": "^0.428.0", "morgan": "^1.10.0", - "prisma": "^5.17.0", "pyodide": "0.24.1", "qrcode": "^1.5.3", "react": "^18.3.1", @@ -151,6 +150,7 @@ "prettier": "^3.3.3", "prettier-plugin-sql": "^0.18.1", "prettier-plugin-tailwindcss": "^0.6.5", + "prisma": "^5.19.1", "remix-flat-routes": "^0.6.5", "tsx": "^4.16.2", "typescript": "^5.5.3", diff --git a/heat-stack/prisma/ERD.md b/heat-stack/prisma/ERD.md new file mode 100644 index 00000000..4d226080 --- /dev/null +++ b/heat-stack/prisma/ERD.md @@ -0,0 +1,237 @@ +# Home Energy Analysis Tool +> Generated by [`prisma-markdown`](https://github.com/samchon/prisma-markdown) + +- [default](#default) + +## default +```mermaid +erDiagram +"User" { + String id PK + String email UK + String username UK + String name "nullable" + DateTime createdAt + DateTime updatedAt +} +"Note" { + String id PK + String title + String content + DateTime createdAt + DateTime updatedAt + String ownerId FK +} +"NoteImage" { + String id PK + String altText "nullable" + String contentType + Bytes blob + DateTime createdAt + DateTime updatedAt + String noteId FK +} +"UserImage" { + String id PK + String altText "nullable" + String contentType + Bytes blob + DateTime createdAt + DateTime updatedAt + String userId FK +} +"Password" { + String hash + String userId FK +} +"Session" { + String id PK + DateTime expirationDate + DateTime createdAt + DateTime updatedAt + String userId FK +} +"Permission" { + String id PK + String action + String entity + String access + String description + DateTime createdAt + DateTime updatedAt +} +"Role" { + String id PK + String name UK + String description + DateTime createdAt + DateTime updatedAt +} +"Verification" { + String id PK + DateTime createdAt + String type + String target + String secret + String algorithm + Int digits + Int period + String charSet + DateTime expiresAt "nullable" +} +"Connection" { + String id PK + String providerName + String providerId + DateTime createdAt + DateTime updatedAt + String userId FK +} +"OilPropaneBillingRecordInput" { + String id PK + DateTime period_end_date + Float gallons + String inclusion_override +} +"_RoleToUser" { + String A FK + String B FK +} +"_PermissionToRole" { + String A FK + String B FK +} +"Note" }o--|| "User" : owner +"NoteImage" }o--|| "Note" : note +"UserImage" |o--|| "User" : user +"Password" |o--|| "User" : user +"Session" }o--|| "User" : user +"Connection" }o--|| "User" : user +"_RoleToUser" }o--|| "Role" : Role +"_RoleToUser" }o--|| "User" : User +"_PermissionToRole" }o--|| "Permission" : Permission +"_PermissionToRole" }o--|| "Role" : Role +``` + +### `User` + +**Properties** + - `id`: + - `email`: + - `username`: + - `name`: + - `createdAt`: + - `updatedAt`: + +### `Note` + +**Properties** + - `id`: + - `title`: + - `content`: + - `createdAt`: + - `updatedAt`: + - `ownerId`: + +### `NoteImage` + +**Properties** + - `id`: + - `altText`: + - `contentType`: + - `blob`: + - `createdAt`: + - `updatedAt`: + - `noteId`: + +### `UserImage` + +**Properties** + - `id`: + - `altText`: + - `contentType`: + - `blob`: + - `createdAt`: + - `updatedAt`: + - `userId`: + +### `Password` + +**Properties** + - `hash`: + - `userId`: + +### `Session` + +**Properties** + - `id`: + - `expirationDate`: + - `createdAt`: + - `updatedAt`: + - `userId`: + +### `Permission` + +**Properties** + - `id`: + - `action`: + - `entity`: + - `access`: + - `description`: + - `createdAt`: + - `updatedAt`: + +### `Role` + +**Properties** + - `id`: + - `name`: + - `description`: + - `createdAt`: + - `updatedAt`: + +### `Verification` + +**Properties** + - `id`: + - `createdAt`: + - `type`: The type of verification, e.g. "email" or "phone" + - `target`: The thing we're trying to verify, e.g. a user's email or phone number + - `secret`: The secret key used to generate the otp + - `algorithm`: The algorithm used to generate the otp + - `digits`: The number of digits in the otp + - `period`: The number of seconds the otp is valid for + - `charSet`: The valid characters for the otp + - `expiresAt`: When it's safe to delete this verification + +### `Connection` + +**Properties** + - `id`: + - `providerName`: + - `providerId`: + - `createdAt`: + - `updatedAt`: + - `userId`: + +### `OilPropaneBillingRecordInput` + +**Properties** + - `id`: + - `period_end_date`: + - `gallons`: + - `inclusion_override`: + +### `_RoleToUser` +Pair relationship table between [Role](#Role) and [User](#User) + +**Properties** + - `A`: + - `B`: + +### `_PermissionToRole` +Pair relationship table between [Permission](#Permission) and [Role](#Role) + +**Properties** + - `A`: + - `B`: \ No newline at end of file diff --git a/heat-stack/prisma/README.md b/heat-stack/prisma/README.md new file mode 100644 index 00000000..d5744a7a --- /dev/null +++ b/heat-stack/prisma/README.md @@ -0,0 +1,17 @@ +# To Generate the Schema for the First Time +``` +npx prisma generate +``` + +# To Change the Schema +First, edit schema.prisma. + +Then, migrate the database by changing to this directory and type: +``` +npx prisma migrate dev --name NAME +``` +where NAME is your choice of migration name. + +# To Generate the Database without Changing the Schema +TODO: Figure this out +``` \ No newline at end of file diff --git a/heat-stack/prisma/migrations/20241004165803_initial_erd/migration.sql b/heat-stack/prisma/migrations/20241004165803_initial_erd/migration.sql new file mode 100644 index 00000000..77db1db8 --- /dev/null +++ b/heat-stack/prisma/migrations/20241004165803_initial_erd/migration.sql @@ -0,0 +1,113 @@ +-- CreateTable +CREATE TABLE "AnalysisInput" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "caseId" INTEGER NOT NULL, + "locationId" INTEGER NOT NULL, + "summaryOutputId" TEXT NOT NULL, + "fuelType" TEXT NOT NULL, + "designTemperatureOverride" BOOLEAN NOT NULL, + "heatingSystemEfficiency" INTEGER NOT NULL, + "thermostatSetPoint" INTEGER NOT NULL, + "setbackTemperature" INTEGER NOT NULL, + "setbackHoursPerDay" INTEGER NOT NULL, + "numberOfOccupants" INTEGER NOT NULL, + "estimatedWaterHeatingEfficiency" INTEGER NOT NULL, + "standByLosses" INTEGER NOT NULL, + "livingArea" REAL NOT NULL, + CONSTRAINT "AnalysisInput_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "Location" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "AnalysisInput_caseId_fkey" FOREIGN KEY ("caseId") REFERENCES "Case" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "ProcessedEnergyBill" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "analysisInputId" INTEGER NOT NULL, + "periodStartDate" DATETIME NOT NULL, + "periodEndDate" DATETIME NOT NULL, + "usageTherms" REAL NOT NULL, + "wholeHomeHeatLossRate" REAL NOT NULL, + "analysisType" INTEGER NOT NULL, + "defaultInclusion" BOOLEAN NOT NULL, + "inclusionOverride" BOOLEAN NOT NULL, + CONSTRAINT "ProcessedEnergyBill_analysisInputId_fkey" FOREIGN KEY ("analysisInputId") REFERENCES "AnalysisInput" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "AnalysisOutput" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "analysisInputId" INTEGER NOT NULL, + "estimatedBalancePoint" REAL NOT NULL, + "otherFuelUsage" REAL NOT NULL, + "averageIndoorTemperature" REAL NOT NULL, + "differenceBetweenTiAndTbp" REAL NOT NULL, + "designTemperature" REAL NOT NULL, + "wholeHomeHeatLossRate" REAL NOT NULL, + "standardDeviationOfHeatLossRate" REAL NOT NULL, + "averageHeatLoad" REAL NOT NULL, + "maximumHeatLoad" REAL NOT NULL, + CONSTRAINT "AnalysisOutput_analysisInputId_fkey" FOREIGN KEY ("analysisInputId") REFERENCES "AnalysisInput" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "EnergyDataFile" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "provider" TEXT NOT NULL, + "fuelType" TEXT NOT NULL, + "precedingDeliveryDate" DATETIME NOT NULL, + "filePath" TEXT NOT NULL, + "description" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "AnalysisInputEnergyDataFile" ( + "analysisInputId" INTEGER NOT NULL, + "energyDataFileId" INTEGER NOT NULL, + CONSTRAINT "AnalysisInputEnergyDataFile_analysisInputId_fkey" FOREIGN KEY ("analysisInputId") REFERENCES "AnalysisInput" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "AnalysisInputEnergyDataFile_energyDataFileId_fkey" FOREIGN KEY ("energyDataFileId") REFERENCES "EnergyDataFile" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "Case" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "homeOwnerId" INTEGER NOT NULL, + "locationId" INTEGER NOT NULL, + CONSTRAINT "Case_homeOwnerId_fkey" FOREIGN KEY ("homeOwnerId") REFERENCES "HomeOwner" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "Case_locationId_fkey" FOREIGN KEY ("locationId") REFERENCES "Location" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "HomeOwner" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "name" TEXT NOT NULL, + "contact_1_name" TEXT NOT NULL, + "contact_1_email_address" TEXT NOT NULL, + "contact_1_phone" TEXT NOT NULL, + "contact_2_name" TEXT NOT NULL, + "contact_2_email_address" TEXT NOT NULL, + "contact_2_phone" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "Location" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "contact_2_email_address" TEXT NOT NULL, + "contact_2_phone" TEXT NOT NULL, + "address" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "CaseUser" ( + "analysisInputId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "userId" TEXT NOT NULL, + CONSTRAINT "CaseUser_analysisInputId_fkey" FOREIGN KEY ("analysisInputId") REFERENCES "AnalysisInput" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "CaseUser_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateIndex +CREATE UNIQUE INDEX "AnalysisInput_summaryOutputId_key" ON "AnalysisInput"("summaryOutputId"); + +-- CreateIndex +CREATE UNIQUE INDEX "AnalysisInputEnergyDataFile_analysisInputId_energyDataFileId_key" ON "AnalysisInputEnergyDataFile"("analysisInputId", "energyDataFileId"); + +-- CreateIndex +CREATE UNIQUE INDEX "CaseUser_analysisInputId_userId_key" ON "CaseUser"("analysisInputId", "userId"); diff --git a/heat-stack/prisma/migrations/20230914194400_init/migration.sql b/heat-stack/prisma/migrations/20241026143219_heat_schema_v1_wp_implementation/migration.sql similarity index 51% rename from heat-stack/prisma/migrations/20230914194400_init/migration.sql rename to heat-stack/prisma/migrations/20241026143219_heat_schema_v1_wp_implementation/migration.sql index 6349954e..51943c55 100644 --- a/heat-stack/prisma/migrations/20230914194400_init/migration.sql +++ b/heat-stack/prisma/migrations/20241026143219_heat_schema_v1_wp_implementation/migration.sql @@ -1,3 +1,35 @@ +/* + Warnings: + + - You are about to drop the `AnalysisInput` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `AnalysisInputEnergyDataFile` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the `AnalysisOutput` table. If the table is not empty, all the data it contains will be lost. + - The primary key for the `CaseUser` table will be changed. If it partially fails, the table could be left without primary key constraint. + - You are about to drop the column `analysisInputId` on the `CaseUser` table. All the data in the column will be lost. + - Added the required column `analysisId` to the `CaseUser` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropIndex +DROP INDEX "AnalysisInput_summaryOutputId_key"; + +-- DropIndex +DROP INDEX "AnalysisInputEnergyDataFile_analysisInputId_energyDataFileId_key"; + +-- DropTable +PRAGMA foreign_keys=off; +DROP TABLE "AnalysisInput"; +PRAGMA foreign_keys=on; + +-- DropTable +PRAGMA foreign_keys=off; +DROP TABLE "AnalysisInputEnergyDataFile"; +PRAGMA foreign_keys=on; + +-- DropTable +PRAGMA foreign_keys=off; +DROP TABLE "AnalysisOutput"; +PRAGMA foreign_keys=on; + -- CreateTable CREATE TABLE "User" ( "id" TEXT NOT NULL PRIMARY KEY, @@ -105,6 +137,52 @@ CREATE TABLE "Connection" ( CONSTRAINT "Connection_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE ); +-- CreateTable +CREATE TABLE "Analysis" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "caseId" INTEGER NOT NULL, + CONSTRAINT "Analysis_caseId_fkey" FOREIGN KEY ("caseId") REFERENCES "Case" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "HeatingInput" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "fuelType" TEXT NOT NULL, + "designTemperatureOverride" BOOLEAN NOT NULL, + "heatingSystemEfficiency" INTEGER NOT NULL, + "thermostatSetPoint" INTEGER NOT NULL, + "setbackTemperature" INTEGER NOT NULL, + "setbackHoursPerDay" INTEGER NOT NULL, + "numberOfOccupants" INTEGER NOT NULL, + "estimatedWaterHeatingEfficiency" INTEGER NOT NULL, + "standByLosses" INTEGER NOT NULL, + "livingArea" REAL NOT NULL +); + +-- CreateTable +CREATE TABLE "HeatingOutput" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "analysisId" INTEGER NOT NULL, + "estimatedBalancePoint" REAL NOT NULL, + "otherFuelUsage" REAL NOT NULL, + "averageIndoorTemperature" REAL NOT NULL, + "differenceBetweenTiAndTbp" REAL NOT NULL, + "designTemperature" REAL NOT NULL, + "wholeHomeHeatLossRate" REAL NOT NULL, + "standardDeviationOfHeatLossRate" REAL NOT NULL, + "averageHeatLoad" REAL NOT NULL, + "maximumHeatLoad" REAL NOT NULL, + CONSTRAINT "HeatingOutput_analysisId_fkey" FOREIGN KEY ("analysisId") REFERENCES "Analysis" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "AnalysisDataFile" ( + "analysisId" INTEGER NOT NULL, + "energyDataFileId" INTEGER NOT NULL, + CONSTRAINT "AnalysisDataFile_analysisId_fkey" FOREIGN KEY ("analysisId") REFERENCES "Analysis" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "AnalysisDataFile_energyDataFileId_fkey" FOREIGN KEY ("energyDataFileId") REFERENCES "EnergyDataFile" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + -- CreateTable CREATE TABLE "_PermissionToRole" ( "A" TEXT NOT NULL, @@ -121,6 +199,37 @@ CREATE TABLE "_RoleToUser" ( CONSTRAINT "_RoleToUser_B_fkey" FOREIGN KEY ("B") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE ); +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_CaseUser" ( + "analysisId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "userId" TEXT NOT NULL, + CONSTRAINT "CaseUser_analysisId_fkey" FOREIGN KEY ("analysisId") REFERENCES "HeatingInput" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "CaseUser_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_CaseUser" ("userId") SELECT "userId" FROM "CaseUser"; +DROP TABLE "CaseUser"; +ALTER TABLE "new_CaseUser" RENAME TO "CaseUser"; +CREATE UNIQUE INDEX "CaseUser_analysisId_userId_key" ON "CaseUser"("analysisId", "userId"); +CREATE TABLE "new_ProcessedEnergyBill" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "analysisInputId" INTEGER NOT NULL, + "periodStartDate" DATETIME NOT NULL, + "periodEndDate" DATETIME NOT NULL, + "usageTherms" REAL NOT NULL, + "wholeHomeHeatLossRate" REAL NOT NULL, + "analysisType" INTEGER NOT NULL, + "defaultInclusion" BOOLEAN NOT NULL, + "inclusionOverride" BOOLEAN NOT NULL, + CONSTRAINT "ProcessedEnergyBill_analysisInputId_fkey" FOREIGN KEY ("analysisInputId") REFERENCES "HeatingInput" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_ProcessedEnergyBill" ("analysisInputId", "analysisType", "defaultInclusion", "id", "inclusionOverride", "periodEndDate", "periodStartDate", "usageTherms", "wholeHomeHeatLossRate") SELECT "analysisInputId", "analysisType", "defaultInclusion", "id", "inclusionOverride", "periodEndDate", "periodStartDate", "usageTherms", "wholeHomeHeatLossRate" FROM "ProcessedEnergyBill"; +DROP TABLE "ProcessedEnergyBill"; +ALTER TABLE "new_ProcessedEnergyBill" RENAME TO "ProcessedEnergyBill"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; + -- CreateIndex CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); @@ -157,6 +266,9 @@ CREATE UNIQUE INDEX "Verification_target_type_key" ON "Verification"("target", " -- CreateIndex CREATE UNIQUE INDEX "Connection_providerName_providerId_key" ON "Connection"("providerName", "providerId"); +-- CreateIndex +CREATE UNIQUE INDEX "AnalysisDataFile_analysisId_energyDataFileId_key" ON "AnalysisDataFile"("analysisId", "energyDataFileId"); + -- CreateIndex CREATE UNIQUE INDEX "_PermissionToRole_AB_unique" ON "_PermissionToRole"("A", "B"); @@ -168,44 +280,3 @@ CREATE UNIQUE INDEX "_RoleToUser_AB_unique" ON "_RoleToUser"("A", "B"); -- CreateIndex CREATE INDEX "_RoleToUser_B_index" ON "_RoleToUser"("B"); - ---------------------------------- Manual Seeding -------------------------- --- Hey there, Kent here! This is how you can reliably seed your database with --- some data. You edit the migration.sql file and that will handle it for you. - -INSERT INTO Permission VALUES('clnf2zvli0000pcou3zzzzome','create','user','own','',1696625465526,1696625465526); -INSERT INTO Permission VALUES('clnf2zvll0001pcouly1310ku','create','user','any','',1696625465529,1696625465529); -INSERT INTO Permission VALUES('clnf2zvll0002pcouka7348re','read','user','own','',1696625465530,1696625465530); -INSERT INTO Permission VALUES('clnf2zvlm0003pcouea4dee51','read','user','any','',1696625465530,1696625465530); -INSERT INTO Permission VALUES('clnf2zvlm0004pcou2guvolx5','update','user','own','',1696625465531,1696625465531); -INSERT INTO Permission VALUES('clnf2zvln0005pcoun78ps5ap','update','user','any','',1696625465531,1696625465531); -INSERT INTO Permission VALUES('clnf2zvlo0006pcouyoptc5jp','delete','user','own','',1696625465532,1696625465532); -INSERT INTO Permission VALUES('clnf2zvlo0007pcouw1yzoyam','delete','user','any','',1696625465533,1696625465533); -INSERT INTO Permission VALUES('clnf2zvlp0008pcou9r0fhbm8','create','note','own','',1696625465533,1696625465533); -INSERT INTO Permission VALUES('clnf2zvlp0009pcouj3qib9q9','create','note','any','',1696625465534,1696625465534); -INSERT INTO Permission VALUES('clnf2zvlq000apcouxnspejs9','read','note','own','',1696625465535,1696625465535); -INSERT INTO Permission VALUES('clnf2zvlr000bpcouf4cg3x72','read','note','any','',1696625465535,1696625465535); -INSERT INTO Permission VALUES('clnf2zvlr000cpcouy1vp6oeg','update','note','own','',1696625465536,1696625465536); -INSERT INTO Permission VALUES('clnf2zvls000dpcouvzwjjzrq','update','note','any','',1696625465536,1696625465536); -INSERT INTO Permission VALUES('clnf2zvls000epcou4ts5ui8f','delete','note','own','',1696625465537,1696625465537); -INSERT INTO Permission VALUES('clnf2zvlt000fpcouk29jbmxn','delete','note','any','',1696625465538,1696625465538); - -INSERT INTO Role VALUES('clnf2zvlw000gpcour6dyyuh6','admin','',1696625465540,1696625465540); -INSERT INTO Role VALUES('clnf2zvlx000hpcou5dfrbegs','user','',1696625465542,1696625465542); - -INSERT INTO _PermissionToRole VALUES('clnf2zvll0001pcouly1310ku','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlm0003pcouea4dee51','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvln0005pcoun78ps5ap','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlo0007pcouw1yzoyam','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlp0009pcouj3qib9q9','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlr000bpcouf4cg3x72','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvls000dpcouvzwjjzrq','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlt000fpcouk29jbmxn','clnf2zvlw000gpcour6dyyuh6'); -INSERT INTO _PermissionToRole VALUES('clnf2zvli0000pcou3zzzzome','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvll0002pcouka7348re','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlm0004pcou2guvolx5','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlo0006pcouyoptc5jp','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlp0008pcou9r0fhbm8','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlq000apcouxnspejs9','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvlr000cpcouy1vp6oeg','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvls000epcou4ts5ui8f','clnf2zvlx000hpcou5dfrbegs'); \ No newline at end of file diff --git a/heat-stack/prisma/migrations/20241111192544_verified_fields/migration.sql b/heat-stack/prisma/migrations/20241111192544_verified_fields/migration.sql new file mode 100644 index 00000000..d073f5b3 --- /dev/null +++ b/heat-stack/prisma/migrations/20241111192544_verified_fields/migration.sql @@ -0,0 +1,132 @@ +/* + Warnings: + + - You are about to drop the `EnergyDataFile` table. If the table is not empty, all the data it contains will be lost. + - You are about to drop the column `energyDataFileId` on the `AnalysisDataFile` table. All the data in the column will be lost. + - You are about to drop the column `contact_1_email_address` on the `HomeOwner` table. All the data in the column will be lost. + - You are about to drop the column `contact_1_name` on the `HomeOwner` table. All the data in the column will be lost. + - You are about to drop the column `contact_1_phone` on the `HomeOwner` table. All the data in the column will be lost. + - You are about to drop the column `contact_2_email_address` on the `HomeOwner` table. All the data in the column will be lost. + - You are about to drop the column `contact_2_name` on the `HomeOwner` table. All the data in the column will be lost. + - You are about to drop the column `contact_2_phone` on the `HomeOwner` table. All the data in the column will be lost. + - You are about to drop the column `name` on the `HomeOwner` table. All the data in the column will be lost. + - You are about to drop the column `contact_2_email_address` on the `Location` table. All the data in the column will be lost. + - You are about to drop the column `contact_2_phone` on the `Location` table. All the data in the column will be lost. + - You are about to drop the column `inclusionOverride` on the `ProcessedEnergyBill` table. All the data in the column will be lost. + - Added the required column `rules_engine_version` to the `Analysis` table without a default value. This is not possible if the table is not empty. + - Added the required column `energyUsageFileId` to the `AnalysisDataFile` table without a default value. This is not possible if the table is not empty. + - Added the required column `analysisId` to the `HeatingInput` table without a default value. This is not possible if the table is not empty. + - Added the required column `email1` to the `HomeOwner` table without a default value. This is not possible if the table is not empty. + - Added the required column `email2` to the `HomeOwner` table without a default value. This is not possible if the table is not empty. + - Added the required column `firstName1` to the `HomeOwner` table without a default value. This is not possible if the table is not empty. + - Added the required column `firstName2` to the `HomeOwner` table without a default value. This is not possible if the table is not empty. + - Added the required column `lastName1` to the `HomeOwner` table without a default value. This is not possible if the table is not empty. + - Added the required column `lastName2` to the `HomeOwner` table without a default value. This is not possible if the table is not empty. + - Added the required column `city` to the `Location` table without a default value. This is not possible if the table is not empty. + - Added the required column `country` to the `Location` table without a default value. This is not possible if the table is not empty. + - Added the required column `latitude` to the `Location` table without a default value. This is not possible if the table is not empty. + - Added the required column `livingAreaSquareFeet` to the `Location` table without a default value. This is not possible if the table is not empty. + - Added the required column `longitude` to the `Location` table without a default value. This is not possible if the table is not empty. + - Added the required column `state` to the `Location` table without a default value. This is not possible if the table is not empty. + - Added the required column `zipcode` to the `Location` table without a default value. This is not possible if the table is not empty. + - Added the required column `invertDefaultInclusion` to the `ProcessedEnergyBill` table without a default value. This is not possible if the table is not empty. + +*/ +-- DropTable +PRAGMA foreign_keys=off; +DROP TABLE "EnergyDataFile"; +PRAGMA foreign_keys=on; + +-- CreateTable +CREATE TABLE "EnergyUsageFile" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "provider" TEXT NOT NULL, + "fuelType" TEXT NOT NULL, + "precedingDeliveryDate" DATETIME NOT NULL, + "content" TEXT NOT NULL, + "description" TEXT NOT NULL +); + +-- RedefineTables +PRAGMA defer_foreign_keys=ON; +PRAGMA foreign_keys=OFF; +CREATE TABLE "new_Analysis" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "caseId" INTEGER NOT NULL, + "rules_engine_version" TEXT NOT NULL, + CONSTRAINT "Analysis_caseId_fkey" FOREIGN KEY ("caseId") REFERENCES "Case" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_Analysis" ("caseId", "id") SELECT "caseId", "id" FROM "Analysis"; +DROP TABLE "Analysis"; +ALTER TABLE "new_Analysis" RENAME TO "Analysis"; +CREATE TABLE "new_AnalysisDataFile" ( + "analysisId" INTEGER NOT NULL, + "energyUsageFileId" INTEGER NOT NULL, + CONSTRAINT "AnalysisDataFile_analysisId_fkey" FOREIGN KEY ("analysisId") REFERENCES "Analysis" ("id") ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT "AnalysisDataFile_energyUsageFileId_fkey" FOREIGN KEY ("energyUsageFileId") REFERENCES "EnergyUsageFile" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_AnalysisDataFile" ("analysisId") SELECT "analysisId" FROM "AnalysisDataFile"; +DROP TABLE "AnalysisDataFile"; +ALTER TABLE "new_AnalysisDataFile" RENAME TO "AnalysisDataFile"; +CREATE UNIQUE INDEX "AnalysisDataFile_analysisId_energyUsageFileId_key" ON "AnalysisDataFile"("analysisId", "energyUsageFileId"); +CREATE TABLE "new_HeatingInput" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "analysisId" INTEGER NOT NULL, + "fuelType" TEXT NOT NULL, + "designTemperatureOverride" BOOLEAN NOT NULL, + "heatingSystemEfficiency" INTEGER NOT NULL, + "thermostatSetPoint" INTEGER NOT NULL, + "setbackTemperature" INTEGER NOT NULL, + "setbackHoursPerDay" INTEGER NOT NULL, + "numberOfOccupants" INTEGER NOT NULL, + "estimatedWaterHeatingEfficiency" INTEGER NOT NULL, + "standByLosses" INTEGER NOT NULL, + "livingArea" REAL NOT NULL, + CONSTRAINT "HeatingInput_analysisId_fkey" FOREIGN KEY ("analysisId") REFERENCES "Analysis" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_HeatingInput" ("designTemperatureOverride", "estimatedWaterHeatingEfficiency", "fuelType", "heatingSystemEfficiency", "id", "livingArea", "numberOfOccupants", "setbackHoursPerDay", "setbackTemperature", "standByLosses", "thermostatSetPoint") SELECT "designTemperatureOverride", "estimatedWaterHeatingEfficiency", "fuelType", "heatingSystemEfficiency", "id", "livingArea", "numberOfOccupants", "setbackHoursPerDay", "setbackTemperature", "standByLosses", "thermostatSetPoint" FROM "HeatingInput"; +DROP TABLE "HeatingInput"; +ALTER TABLE "new_HeatingInput" RENAME TO "HeatingInput"; +CREATE TABLE "new_HomeOwner" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "firstName1" TEXT NOT NULL, + "lastName1" TEXT NOT NULL, + "email1" TEXT NOT NULL, + "firstName2" TEXT NOT NULL, + "lastName2" TEXT NOT NULL, + "email2" TEXT NOT NULL +); +INSERT INTO "new_HomeOwner" ("id") SELECT "id" FROM "HomeOwner"; +DROP TABLE "HomeOwner"; +ALTER TABLE "new_HomeOwner" RENAME TO "HomeOwner"; +CREATE TABLE "new_Location" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "address" TEXT NOT NULL, + "city" TEXT NOT NULL, + "state" TEXT NOT NULL, + "zipcode" TEXT NOT NULL, + "country" TEXT NOT NULL, + "livingAreaSquareFeet" INTEGER NOT NULL, + "latitude" REAL NOT NULL, + "longitude" REAL NOT NULL +); +INSERT INTO "new_Location" ("address", "id") SELECT "address", "id" FROM "Location"; +DROP TABLE "Location"; +ALTER TABLE "new_Location" RENAME TO "Location"; +CREATE TABLE "new_ProcessedEnergyBill" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "analysisInputId" INTEGER NOT NULL, + "periodStartDate" DATETIME NOT NULL, + "periodEndDate" DATETIME NOT NULL, + "usageTherms" REAL NOT NULL, + "wholeHomeHeatLossRate" REAL NOT NULL, + "analysisType" INTEGER NOT NULL, + "defaultInclusion" BOOLEAN NOT NULL, + "invertDefaultInclusion" BOOLEAN NOT NULL, + CONSTRAINT "ProcessedEnergyBill_analysisInputId_fkey" FOREIGN KEY ("analysisInputId") REFERENCES "HeatingInput" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); +INSERT INTO "new_ProcessedEnergyBill" ("analysisInputId", "analysisType", "defaultInclusion", "id", "periodEndDate", "periodStartDate", "usageTherms", "wholeHomeHeatLossRate") SELECT "analysisInputId", "analysisType", "defaultInclusion", "id", "periodEndDate", "periodStartDate", "usageTherms", "wholeHomeHeatLossRate" FROM "ProcessedEnergyBill"; +DROP TABLE "ProcessedEnergyBill"; +ALTER TABLE "new_ProcessedEnergyBill" RENAME TO "ProcessedEnergyBill"; +PRAGMA foreign_keys=ON; +PRAGMA defer_foreign_keys=OFF; diff --git a/heat-stack/prisma/schema.prisma b/heat-stack/prisma/schema.prisma index 975d2431..352b8c92 100644 --- a/heat-stack/prisma/schema.prisma +++ b/heat-stack/prisma/schema.prisma @@ -11,9 +11,12 @@ datasource db { } model User { - id String @id @default(cuid()) - email String @unique - username String @unique + id String @id @default(cuid()) + // caseUser added when CaseUser model added for HEAT schema + caseUser CaseUser[] + + email String @unique + username String @unique name String? createdAt DateTime @default(now()) @@ -167,3 +170,119 @@ model Connection { @@unique([providerName, providerId]) } + +// HEAT schema starts here +model Analysis { + id Int @id @default(autoincrement()) + case Case @relation(fields: [caseId], references: [id], onDelete: Cascade, onUpdate: Cascade) + caseId Int + heatingInput HeatingInput[] + analysisDataFile AnalysisDataFile[] + heatingOutput HeatingOutput[] + rules_engine_version String +} + +model HeatingInput { + id Int @id @default(autoincrement()) + analysis Analysis @relation(fields: [analysisId], references: [id], onDelete: Cascade, onUpdate: Cascade) + analysisId Int + caseUser CaseUser[] + fuelType String + designTemperatureOverride Boolean + heatingSystemEfficiency Int + thermostatSetPoint Int + setbackTemperature Int + setbackHoursPerDay Int + numberOfOccupants Int + estimatedWaterHeatingEfficiency Int + standByLosses Int + processedEnergyBill ProcessedEnergyBill[] + livingArea Float +} + +model ProcessedEnergyBill { + id Int @id @default(autoincrement()) + AnalysisInput HeatingInput @relation(fields: [analysisInputId], references: [id], onDelete: Cascade, onUpdate: Cascade) + analysisInputId Int + periodStartDate DateTime + periodEndDate DateTime + usageTherms Float + wholeHomeHeatLossRate Float + analysisType Int + defaultInclusion Boolean + invertDefaultInclusion Boolean +} + +model HeatingOutput { + id Int @id @default(autoincrement()) + analysis Analysis @relation(fields: [analysisId], references: [id], onDelete: Cascade, onUpdate: Cascade) + analysisId Int + estimatedBalancePoint Float + otherFuelUsage Float + averageIndoorTemperature Float + differenceBetweenTiAndTbp Float + designTemperature Float + wholeHomeHeatLossRate Float + standardDeviationOfHeatLossRate Float + averageHeatLoad Float + maximumHeatLoad Float +} + +model EnergyUsageFile { + id Int @id @default(autoincrement()) + provider String + fuelType String + precedingDeliveryDate DateTime + content String + description String + analysisDataFile AnalysisDataFile[] +} + +model AnalysisDataFile { + analysis Analysis @relation(fields: [analysisId], references: [id], onDelete: Cascade, onUpdate: Cascade) + analysisId Int + EnergyUsageFile EnergyUsageFile @relation(fields: [energyUsageFileId], references: [id], onDelete: Cascade, onUpdate: Cascade) + energyUsageFileId Int + @@unique([analysisId, energyUsageFileId]) +} + +model Case { + id Int @id @default(autoincrement()) + homeOwner HomeOwner @relation(fields: [homeOwnerId], references: [id], onDelete: Cascade, onUpdate: Cascade) + homeOwnerId Int + location Location @relation(fields: [locationId], references: [id], onDelete: Cascade, onUpdate: Cascade) + locationId Int + analysis Analysis[] +} + +model HomeOwner { + id Int @id @default(autoincrement()) + case Case[] + firstName1 String + lastName1 String + email1 String + firstName2 String + lastName2 String + email2 String +} + +model Location { + id Int @id @default(autoincrement()) + case Case[] + address String + city String + state String + zipcode String + country String + livingAreaSquareFeet Int + latitude Float + longitude Float +} + +model CaseUser { + case HeatingInput @relation(fields: [analysisId], references: [id], onDelete: Cascade, onUpdate: Cascade) + user User @relation(fields: [userId], references: [id], onDelete: Cascade, onUpdate: Cascade) + analysisId Int @id @default(autoincrement()) + userId String + @@unique([analysisId, userId]) +} \ No newline at end of file diff --git a/python/src/rules_engine/refactor.md b/python/src/rules_engine/refactor.md deleted file mode 100644 index a103f0e5..00000000 --- a/python/src/rules_engine/refactor.md +++ /dev/null @@ -1,166 +0,0 @@ -Qs: -- stand_by_losses - -home variables used -``` - avg_ua - balance_point - non_heating_usage - stdev_pct - balance_point_graph -``` - -1. Remove temporary_rules_engine.py -2. Rename rules-engine to "python" -3. Rename NormalizedBillingRecordBase class to BillingInput -4. Rename BillingPeriod to ProcessedBill and billing_period to processed_bill -5. Combine get_outputs_normalized and convert_to_intermediate_billing_record and get rid of NormalizedBillingRecord. There is only one place NormalizedBillingRecord is used and combining code -gets rid of the need for the class. -- Change -``` - billing_periods: list[NormalizedBillingPeriodRecordBase] = [] - - for input_val in natural_gas_billing_input.records: - billing_periods.append( - NormalizedBillingPeriodRecordBase( - period_start_date=input_val.period_start_date, - period_end_date=input_val.period_end_date, - usage=input_val.usage_therms, - inclusion_override=bool(input_val.inclusion_override), - ) - ) - - return get_outputs_normalized( - summary_input, None, temperature_input, billing_periods - ) - - def get_outputs_normalized - loops through billing_periods and does a bunch of stuff - -``` -to -``` - inputBill = - NormalizedBillingPeriodRecordBase( - period_start_date=input_val.period_start_date, - period_end_date=input_val.period_end_date, - usage=input_val.usage_therms, - analysis_type_override=input_val.inclusion_override, - inclusion_override=True, - ) - ) - avg_temps = derive_avg_temps(temparature_input) - default_analysis_type = derive_default_analysis_type - ( fuel_type, - inputBill.start_date, - inputBill.end_date - ) - processedBill = ProcessedBill( - input = inputBill, - avg_temps = avg_temps, - default_analysis_type = default_analysis_type - // usage not needed, it is part of inputBill - ) -``` -6. Home - Call home.calculate from home.init or move the code from home.init into home.calculate. Otherwise, the fact that Home.init does calculations is hidden. Code looks like this: -``` -home=Home(args) # does some calculations -home.calculate() # does some calculations -``` -This would change to either -``` -home=Home(args) -``` -or -``` -home=Home.calculate(args) -``` -7. Home - change to functional programming paradigm where you provide inputs and outputs - - Change - `_calculate_avg_summer_usage()` => `avg_summer_usage = _get_avg_summer_usage(summer_bills)` - - Change - `_calculate_avg_non_heating_usage ()` => -to -``` -avg_non_heating_usage = _get_avg_non_heating_usage ( - fuel_type, - avg_summer_usage, - dhw_input.estimated_water_heating_efficiency, - dhw_input.number_of_occupants, - stand_by_losses, - heating_system_efficiency -) -``` -================== -- change -`for billing_period in billing_periods ...` => -to -``` -for billing_period in billing_periods - { bills_summer, bills_winter, bills_shoulder } - =_categorize_bills_by_season (billing_periods) -``` -================== -- Change -``` -calculate_dhw_usage() -``` -to -``` - dhw_usage = _calculate_dhw_usage ( - estimated_water_heating_efficiency, - dhw_input.number_of_occupants, - stand_by_losses, - heating_system_efficiency - ) -``` -================== -- Change -`self.initialize_ua(billing_period)` => `_set_ua(billing_period,avg_non_heating_usage)` - -- Change?? Parameters are never set -``` -def calculate( - self, - initial_balance_point_sensitivity: float = 0.5, - stdev_pct_max: float = 0.10, - max_stdev_pct_diff: float = 0.01, - next_balance_point_sensitivity: float = 0.5, - ) -``` -=> -``` -def calculate ( - - initial_balance_point_sensitivity: float = 0.5, - stdev_pct_max: float = 0.10, - max_stdev_pct_diff: float = 0.01, - next_balance_point_sensitivity: float = 0.5, -``` -================== -- calculate method -`self._calculate_avg_non_heating_usage` - duplicated. Remove one of the calls -================== - -- Change -``` -self._calculate_balance_point_and_ua( - initial_balance_point_sensitivity, - stdev_pct_max, - max_stdev_pct_diff, - next_balance_point_sensitivity, - ) -``` => -``` -{ balance_point, stdev_pct - balance_point_graph } = - _get_graph (initial_balance_point_sensitivity, - stdev_pct_max, - max_stdev_pct_diff, - next_balance_point_sensitivity, - bills_winter) -``` -================== - - -