Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gg/three tier continue #64

Merged
merged 31 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
364081b
feat: Replace primsa. with calls to prisma models
DafyddLlyr Jul 26, 2024
3b7897a
feat: Get count and avg from Prisma for pricesPaid, remove pricesPaid…
DafyddLlyr Jul 26, 2024
25f1614
fix: Rebase issues
DafyddLlyr Aug 2, 2024
fc48eb4
chore: Tidy up
DafyddLlyr Aug 2, 2024
e5a80b5
feat: Correctly desctructure prisma queries and catch errors to type …
DafyddLlyr Aug 2, 2024
427405c
fix: Better type narrowing in calculationSchema
DafyddLlyr Aug 2, 2024
283d01f
feat: Setup DB singleton
DafyddLlyr Aug 3, 2024
a8cceeb
feat: ITLLookup
DafyddLlyr Aug 3, 2024
645f1eb
feat: GDHI
DafyddLlyr Aug 3, 2024
ddc9d53
feat: Define handler layer by creating calculationService
DafyddLlyr Aug 3, 2024
a632e9d
chore: Tidy up import, export and names
DafyddLlyr Aug 3, 2024
3571998
pricesPaid refactoring
Aug 9, 2024
b0d9ef4
delete list of transactions to be returned
Aug 9, 2024
ecf0644
typos
Aug 9, 2024
84100f9
buildPrice breakdown
Aug 9, 2024
6d2de4b
feat: create gasBillRepo layer
zz-hh-aa Aug 16, 2024
9330c4c
fix: use model field names in Prisma
zz-hh-aa Aug 16, 2024
71bb827
fix: add gasBillRepo export
zz-hh-aa Aug 16, 2024
755b43f
feat: create gasBillService layer
zz-hh-aa Aug 16, 2024
505e7b1
feat: create hpiRepo and hpiService layers
zz-hh-aa Aug 16, 2024
dd6f35d
feat: create socialRentEarnings Repo and Service layers
zz-hh-aa Aug 16, 2024
eabd97c
feat: create rentRepo and rentService layers
zz-hh-aa Aug 16, 2024
8dad235
fix: updated types using Prisma model field names
zz-hh-aa Aug 16, 2024
3f09789
feat: create socialRentAdjustments layers
zz-hh-aa Aug 20, 2024
6521d67
fix: renamed socialRentEarningsService
zz-hh-aa Aug 20, 2024
85621cd
fix: corrected aggregate function
zz-hh-aa Aug 20, 2024
7344f85
feat: added all layers to calculationService
zz-hh-aa Aug 20, 2024
4b46f3b
chore: rename to socialRentAverageEarning
zz-hh-aa Aug 21, 2024
f4ebd5e
Merge pull request #57 from theopensystemslab/oz/three-tier
zz-hh-aa Aug 21, 2024
1b83323
Merge branch 'main' into gg/three-tier-continue
gabrielegranello Aug 21, 2024
6c4bd92
fix pricesPaid linting error
Aug 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions app/data/buildPriceRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import prisma from "./db";

const getBuildPriceByHouseType = async (houseType: string): Promise<number> => {
try {
const { priceMid: buildPrice } = await prisma.buildPrices.findFirstOrThrow({
where: {
houseType: { equals: houseType },
},
select: { priceMid: true },
});

// Cast to string as 'not: null' clause in Prisma query does not type narrow
return buildPrice as number;
} catch (error) {
throw new Error(
`Data error: Unable to get buildPrice for houseType ${houseType}`
);
}
};

export const buildPriceRepo = {
getBuildPriceByHouseType,
};
21 changes: 21 additions & 0 deletions app/data/gasBillRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import prisma from "./db";

const getGasBillByITL3 = async (itl: string): Promise<number> => {
try {
const { bill } = await prisma.gasBills.findFirstOrThrow({
where: {
itl: { startsWith: itl.substring(0, 3) },
},
select: { bill: true },
});

return bill as number;
} catch (error) {
throw Error(`Data error: Unable to find gas_bills_2020 for itl3 ${itl}`);
}
};

export const gasBillRepo = {
getGasBillByITL3,
};

9 changes: 4 additions & 5 deletions app/data/gdhiRepo.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import prisma from "./db";

const getGDHI2020ByITL3 = async (
itl3: string
): Promise<number> => {
const getGDHI2020ByITL3 = async (itl3: string): Promise<number> => {
try {
const { gdhi2020 } = await prisma.gDHI.findFirstOrThrow({
where: {
AND: {
itl3: { equals: itl3 },
// TODO: Add `NOT NULL` constraint to column
gdhi2020: { not: null }
gdhi2020: { not: null },
},
},
select: { gdhi2020: true },
Expand All @@ -23,4 +21,5 @@ const getGDHI2020ByITL3 = async (

export const gdhiRepo = {
getGDHI2020ByITL3,
}
};

26 changes: 26 additions & 0 deletions app/data/hpiRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import prisma from "./db";

const getHPIByITL3 = async (itl3: string): Promise<number> => {
try {
const {
_avg: { hpi2020: averageHpi },
} = await prisma.hPI.aggregate({
where: {
itl3: {
endsWith: itl3,
},
},
_avg: {
hpi2020: true,
},
});
return averageHpi as number;
} catch (error) {
throw Error(`Data error: Unable to find hpi2020 for itl3 ${itl3}`);
}
};

export const hpi2020Repo = {
getHPIByITL3,
};

8 changes: 6 additions & 2 deletions app/data/itlRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ const getItl3ByPostcodeDistrict = async (
// Cast to string as 'not: null' clause in Prisma query does not type narrow
return itl3 as string;
} catch (error) {
throw new Error(`Data error: Unable get get itl3 for postcode district ${postcodeDistrict}`);
throw new Error(
`Data error: Unable get get itl3 for postcode district ${postcodeDistrict}`
);

}
};

export const itlRepo = {
getItl3ByPostcodeDistrict,
}
};

115 changes: 115 additions & 0 deletions app/data/pricesPaidRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import prisma from "./db";

const MINIMUM_NUMBER_OF_POSTCODES = 30;

interface pricesPaidParams {
averagePrice: number;
numberOfTransactions: number;
granularityPostcode: string;
}
const getPricesPaidByPostcodeAndHouseType = async (
postcodeDistrict: string,
postcodeArea: string,
postcodeSector: string,
houseType: string
): Promise<pricesPaidParams> => {
try {
// create the progressive queries
let numberOfTransactions; // declare the variable for numbers of transactions retrieved
let granularityPostcode; // declare the granularity of the postcode
let averagePrice;

const pricesPaidSector = await prisma.pricesPaid.aggregate({
where: {
propertyType: {
equals: houseType,
},
postcode: {
startsWith: postcodeSector,
},
},
_count: {
id: true,
},
_avg: {
price: true,
},
});

const numberPerSector = pricesPaidSector._count.id;
const isMinMetBySector = numberPerSector >= MINIMUM_NUMBER_OF_POSTCODES;

if (!isMinMetBySector) {
const pricesPaidDistrict = await prisma.pricesPaid.aggregate({
where: {
propertyType: {
equals: houseType,
},
postcode: {
startsWith: postcodeDistrict,
},
},
_count: {
id: true,
},
_avg: {
price: true,
},
});

const numberPerDistrict = pricesPaidDistrict._count.id;
const isMinMetByDistrict =
numberPerDistrict >= MINIMUM_NUMBER_OF_POSTCODES;

if (!isMinMetByDistrict) {
const pricesPaidArea = await prisma.pricesPaid.aggregate({
where: {
propertyType: {
equals: houseType,
},
postcode: {
startsWith: postcodeArea,
},
},
_count: {
id: true,
},
_avg: {
price: true,
},
});
const numberPerArea = pricesPaidArea._count.id;
numberOfTransactions = numberPerArea; // check the granularity
granularityPostcode = postcodeArea; // granularity of the postcode when performing the average price search
averagePrice = pricesPaidArea._avg.price;
} else {
numberOfTransactions = numberPerDistrict; // check the granularity
granularityPostcode = postcodeDistrict; // granularity of the postcode
averagePrice = pricesPaidDistrict._avg.price;
}
} else {
numberOfTransactions = numberPerSector; // check the granularity
granularityPostcode = postcodeSector; // granularity of the postcode
averagePrice = pricesPaidSector._avg.price;
}

if (averagePrice === null) {
throw new Error("Unable to calculate average price");
}

// Cast to string as 'not: null' clause in Prisma query does not type narrow
return {
averagePrice,
numberOfTransactions,
granularityPostcode,
} as pricesPaidParams;
} catch (error) {
throw new Error(
`Data error: Unable to get pricesPaid for postcode district ${postcodeDistrict} and houseType ${houseType}`
);
}
};

export const pricesPaidRepo = {
getPricesPaidByPostcodeAndHouseType,
};
24 changes: 24 additions & 0 deletions app/data/rentRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import prisma from "./db";

const getRentByITL3 = async (itl3: string): Promise<number | null> => {
try {
const result = await prisma.rent.aggregate({
where: {
itl3: { equals: itl3 },
},
_avg: {
monthlyMeanRent: true,
},
});

const monthlyMeanRent = result._avg.monthlyMeanRent;

return monthlyMeanRent;
} catch (error) {
throw new Error(`Data error: Unable to find monthlyMeanRent for itl3 ${itl3}`);
}
};

export const rentRepo = {
getRentByITL3,
};
37 changes: 37 additions & 0 deletions app/data/socialRentAdjustmentsRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import prisma from "./db";

export type socialRentAdjustmentTypes = {
year: string;
inflation: string;
additional: string;
total: string;
}[];

const getSocialRentAdjustments = async (): Promise<socialRentAdjustmentTypes> => {
try {
const result = await prisma.socialRentAdjustments.findMany({
select: {
year: true,
inflation: true,
additional: true,
total: true,
}
});

const socialRentAdjustments: socialRentAdjustmentTypes = result.map(item => ({
year: item.year || '',
inflation: item.inflation?.toString() || '',
additional: item.additional?.toString() || '',
total: item.total?.toString() || '',
}));

return socialRentAdjustments;

} catch (error) {
throw new Error(`Data error: Unable to find socialRentAdjustments`);
}
};

export const socialRentAdjustmentsRepo = {
getSocialRentAdjustments,
};
31 changes: 31 additions & 0 deletions app/data/socialRentEarningsRepo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import prisma from "./db";

const getSocialRentEarningsByITL3 = async (itl3: string): Promise<number> => {
try {
const result = await prisma.socialRent.aggregate({
where: {
itl3: {
startsWith: itl3.substring(0, 3),
},
},
_avg: {
earningsPerWeek: true,
},
});

const monthlyMeanRent = result._avg.earningsPerWeek;

if (monthlyMeanRent === null) {
throw new Error(`No data found for itl3 ${itl3}`);
}

return monthlyMeanRent;

} catch (error) {
throw Error(`Data error: Unable to find earningsPerWeek for itl3 ${itl3}`);
}
};

export const socialRentEarningsRepo = {
getSocialRentEarningsByITL3,
};
9 changes: 9 additions & 0 deletions app/services/buildPriceService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { buildPriceRepo } from "../data/buildPriceRepo";

const getBuildPriceByHouseType = async (houseType: string) => {
return await buildPriceRepo.getBuildPriceByHouseType(houseType);
};

export const buildPriceService = {
getBuildPriceByHouseType,
};
Loading
Loading