extend views with year count
This commit is contained in:
parent
91217d1e6e
commit
d683bcb4c1
8 changed files with 133 additions and 107 deletions
|
@ -38,71 +38,7 @@ export async function executeQuery(req: Request, res: Response): Promise<any> {
|
|||
let count = parseInt((req.query.count as string) ?? "25");
|
||||
const query = req.body.query;
|
||||
|
||||
if (typeof query == "string") {
|
||||
const upperQuery = query.trim().toUpperCase();
|
||||
if (!upperQuery.startsWith("SELECT") || /INSERT|UPDATE|DELETE|ALTER|DROP|CREATE|TRUNCATE/.test(upperQuery)) {
|
||||
return res.json({
|
||||
stats: "error",
|
||||
sql: query,
|
||||
code: "UNALLOWED",
|
||||
msg: "Not allowed to change rows",
|
||||
});
|
||||
}
|
||||
let result = await DynamicQueryBuilder.executeQuery(query, offset, count);
|
||||
|
||||
try {
|
||||
let data: Array<any> = [];
|
||||
|
||||
const result = await dataSource
|
||||
.transaction(async (manager) => {
|
||||
data = await manager.query(query);
|
||||
|
||||
throw new Error("AllwaysRollbackQuery");
|
||||
})
|
||||
.catch((error) => {
|
||||
if (error.message === "AllwaysRollbackQuery") {
|
||||
return {
|
||||
stats: "success",
|
||||
rows: data,
|
||||
total: data.length,
|
||||
offset: offset,
|
||||
count: count,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
stats: "error",
|
||||
sql: error.sql,
|
||||
code: error.code,
|
||||
msg: error.sqlMessage,
|
||||
};
|
||||
}
|
||||
});
|
||||
res.send(result);
|
||||
} catch (error) {
|
||||
res.json({
|
||||
stats: "error",
|
||||
sql: error.sql,
|
||||
code: error.code,
|
||||
msg: error.sqlMessage,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
let [rows, total] = await DynamicQueryBuilder.buildQuery(query, offset, count).getManyAndCount();
|
||||
|
||||
res.json({
|
||||
stats: "success",
|
||||
rows: DynamicQueryBuilder.flattenQueryResult(rows),
|
||||
total: total,
|
||||
offset: offset,
|
||||
count: count,
|
||||
});
|
||||
} catch (error) {
|
||||
res.json({
|
||||
stats: "error",
|
||||
sql: error.sql,
|
||||
code: error.code,
|
||||
msg: error.sqlMessage,
|
||||
});
|
||||
}
|
||||
}
|
||||
res.json(result);
|
||||
}
|
||||
|
|
|
@ -61,11 +61,11 @@ import { newsletterRecipients } from "./entity/club/newsletter/newsletterRecipie
|
|||
import { Newsletter1735118780511 } from "./migrations/1735118780511-newsletter";
|
||||
import { newsletterConfig } from "./entity/settings/newsletterConfig";
|
||||
import { NewsletterConfig1735207446910 } from "./migrations/1735207446910-newsletterConfig";
|
||||
import { TemplateMargins1735733514043 } from "./migrations/1735733514043-templateMargins";
|
||||
import { InternalId1735822722235 } from "./migrations/1735822722235-internalId";
|
||||
import { PostalCode1735927918979 } from "./migrations/1735927918979-postalCode";
|
||||
import { ProtocolAbsent1736072179716 } from "./migrations/1736072179716-protocolAbsent";
|
||||
import { Memberlist1736079005086 } from "./migrations/1736079005086-memberlist";
|
||||
import { ExtendViewValues1736084198860 } from "./migrations/1736084198860-extendViewValues";
|
||||
|
||||
const dataSource = new DataSource({
|
||||
type: DB_TYPE as any,
|
||||
|
@ -137,11 +137,11 @@ const dataSource = new DataSource({
|
|||
TemplateUsage1734949173739,
|
||||
Newsletter1735118780511,
|
||||
NewsletterConfig1735207446910,
|
||||
TemplateMargins1735733514043,
|
||||
InternalId1735822722235,
|
||||
PostalCode1735927918979,
|
||||
ProtocolAbsent1736072179716,
|
||||
Memberlist1736079005086
|
||||
Memberlist1736079005086,
|
||||
ExtendViewValues1736084198860,
|
||||
],
|
||||
migrationsRun: true,
|
||||
migrationsTransactionMode: "each",
|
||||
|
|
|
@ -252,7 +252,7 @@ export default abstract class DynamicQueryBuilder {
|
|||
});
|
||||
});
|
||||
results = tempResults;
|
||||
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
||||
} else if (value && typeof value === "object" && !Array.isArray(value) && !(value instanceof Date)) {
|
||||
const objResults = flatten(value as QueryResult, newKey);
|
||||
const tempResults: Array<{ [key: string]: FieldType }> = [];
|
||||
results.forEach((res) => {
|
||||
|
|
|
@ -16,6 +16,8 @@ export class TemplateUsage1734949173739 implements MigrationInterface {
|
|||
{ name: "headerId", type: variableType_int, isNullable: true },
|
||||
{ name: "bodyId", type: variableType_int, isNullable: true },
|
||||
{ name: "footerId", type: variableType_int, isNullable: true },
|
||||
{ name: "headerHeight", type: variableType_int, default: null, isNullable: true },
|
||||
{ name: "footerHeight", type: variableType_int, default: null, isNullable: true },
|
||||
],
|
||||
}),
|
||||
true
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
import { MigrationInterface, QueryRunner, TableColumn } from "typeorm";
|
||||
import { DB_TYPE } from "../env.defaults";
|
||||
|
||||
export class TemplateMargins1735733514043 implements MigrationInterface {
|
||||
name = "TemplateMargins1735733514043";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
const variableType_int = DB_TYPE == "mysql" ? "int" : "integer";
|
||||
|
||||
await queryRunner.addColumn(
|
||||
"template_usage",
|
||||
new TableColumn({
|
||||
name: "headerHeight",
|
||||
type: variableType_int,
|
||||
default: null,
|
||||
isNullable: true,
|
||||
})
|
||||
);
|
||||
|
||||
await queryRunner.addColumn(
|
||||
"template_usage",
|
||||
new TableColumn({
|
||||
name: "footerHeight",
|
||||
type: variableType_int,
|
||||
default: null,
|
||||
isNullable: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropColumn("template_usage", "footerHeight");
|
||||
await queryRunner.dropColumn("template_usage", "headerHeight");
|
||||
}
|
||||
}
|
112
src/migrations/1736084198860-extendViewValues.ts
Normal file
112
src/migrations/1736084198860-extendViewValues.ts
Normal file
|
@ -0,0 +1,112 @@
|
|||
import { DataSource, MigrationInterface, QueryRunner, View } from "typeorm";
|
||||
import { member } from "../entity/club/member/member";
|
||||
import { memberExecutivePositions } from "../entity/club/member/memberExecutivePositions";
|
||||
import { memberQualifications } from "../entity/club/member/memberQualifications";
|
||||
import { membership } from "../entity/club/member/membership";
|
||||
|
||||
export class ExtendViewValues1736084198860 implements MigrationInterface {
|
||||
name = "ExtendViewValues1736084198860";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropView("membership_view");
|
||||
await queryRunner.dropView("member_view");
|
||||
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.salutation", "salutation")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "membership_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(membership)
|
||||
.createQueryBuilder("membership")
|
||||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.addSelect(
|
||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||
"durationInYears"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.groupBy("status.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.dropView("membership_view");
|
||||
await queryRunner.dropView("member_view");
|
||||
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "member_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(member)
|
||||
.createQueryBuilder("member")
|
||||
.select("member.id", "id")
|
||||
.addSelect("member.salutation", "salutation")
|
||||
.addSelect("member.firstname", "firstname")
|
||||
.addSelect("member.lastname", "lastname")
|
||||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
await queryRunner.createView(
|
||||
new View({
|
||||
name: "membership_view",
|
||||
expression: (datasource: DataSource) =>
|
||||
datasource
|
||||
.getRepository(membership)
|
||||
.createQueryBuilder("membership")
|
||||
.select("status.id", "statusId")
|
||||
.addSelect("status.status", "status")
|
||||
.addSelect("member.id", "memberId")
|
||||
.addSelect("member.salutation", "memberSalutation")
|
||||
.addSelect("member.firstname", "memberFirstname")
|
||||
.addSelect("member.lastname", "memberLastname")
|
||||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect(
|
||||
"SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))",
|
||||
"durationInDays"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.groupBy("status.id"),
|
||||
}),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
|
@ -14,7 +14,8 @@ import { Salutation } from "../enums/salutation";
|
|||
.addSelect("member.nameaffix", "nameaffix")
|
||||
.addSelect("member.birthdate", "birthdate")
|
||||
.addSelect("TIMESTAMPDIFF(YEAR, member.birthdate, CURDATE())", "todayAge")
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear"),
|
||||
.addSelect("YEAR(CURDATE()) - YEAR(member.birthdate)", "ageThisYear")
|
||||
.addSelect("CONCAT('_', FROM_DAYS(TIMESTAMPDIFF(DAY, member.birthdate, CURDATE())))", "exactAge"),
|
||||
})
|
||||
export class memberView {
|
||||
@ViewColumn()
|
||||
|
@ -40,4 +41,7 @@ export class memberView {
|
|||
|
||||
@ViewColumn()
|
||||
ageThisYear: number;
|
||||
|
||||
@ViewColumn()
|
||||
exactAge: Date;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ import { Salutation } from "../enums/salutation";
|
|||
.addSelect("member.nameaffix", "memberNameaffix")
|
||||
.addSelect("member.birthdate", "memberBirthdate")
|
||||
.addSelect("SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))", "durationInDays")
|
||||
.addSelect(
|
||||
"CONCAT('_', FROM_DAYS(SUM(TIMESTAMPDIFF(DAY, membership.start, COALESCE(membership.end, CURRENT_DATE)))))",
|
||||
"durationInYears"
|
||||
)
|
||||
.leftJoin("membership.status", "status")
|
||||
.leftJoin("membership.member", "member")
|
||||
.groupBy("status.id"),
|
||||
|
@ -24,6 +28,9 @@ export class membershipView {
|
|||
@ViewColumn()
|
||||
durationInDays: number;
|
||||
|
||||
@ViewColumn()
|
||||
durationInYears: Date;
|
||||
|
||||
@ViewColumn()
|
||||
status: string;
|
||||
|
||||
|
|
Loading…
Reference in a new issue