mirror of
https://github.com/SyncrowIOT/backend.git
synced 2025-11-26 18:04:54 +00:00
merge dev to main
This commit is contained in:
38
libs/common/src/helper/date-format.ts
Normal file
38
libs/common/src/helper/date-format.ts
Normal file
@ -0,0 +1,38 @@
|
||||
export function toDDMMYYYY(dateString?: string | null): string | null {
|
||||
if (!dateString) return null;
|
||||
|
||||
// Ensure dateString is valid format YYYY-MM-DD
|
||||
const regex = /^\d{4}-\d{2}-\d{2}$/;
|
||||
if (!regex.test(dateString)) {
|
||||
throw new Error(
|
||||
`Invalid date format: ${dateString}. Expected format is YYYY-MM-DD`,
|
||||
);
|
||||
}
|
||||
|
||||
const [year, month, day] = dateString.split('-');
|
||||
return `${day}-${month}-${year}`;
|
||||
}
|
||||
export function toMMYYYY(dateString?: string | null): string | null {
|
||||
if (!dateString) return null;
|
||||
|
||||
// Ensure dateString is valid format YYYY-MM
|
||||
const regex = /^\d{4}-\d{2}$/;
|
||||
if (!regex.test(dateString)) {
|
||||
throw new Error(
|
||||
`Invalid date format: ${dateString}. Expected format is YYYY-MM`,
|
||||
);
|
||||
}
|
||||
|
||||
const [year, month] = dateString.split('-');
|
||||
return `${month}-${year}`;
|
||||
}
|
||||
export function filterByMonth(data: any[], monthDate: string) {
|
||||
const [year, month] = monthDate.split('-').map(Number);
|
||||
|
||||
return data.filter((item) => {
|
||||
const itemDate = new Date(item.date);
|
||||
return (
|
||||
itemDate.getUTCFullYear() === year && itemDate.getUTCMonth() + 1 === month
|
||||
);
|
||||
});
|
||||
}
|
||||
1
libs/common/src/modules/presence-sensor/dtos/index.ts
Normal file
1
libs/common/src/modules/presence-sensor/dtos/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './presence-sensor.dto';
|
||||
@ -0,0 +1,27 @@
|
||||
import { IsNotEmpty, IsNumber, IsString } from 'class-validator';
|
||||
|
||||
export class PresenceSensorDto {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public uuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public deviceUuid: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
public eventDate: string;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
public CountMotionDetected: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
public CountPresenceDetected: number;
|
||||
|
||||
@IsNumber()
|
||||
@IsNotEmpty()
|
||||
public CountTotalPresenceDetected: number;
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export * from './presence-sensor.entity';
|
||||
@ -0,0 +1,58 @@
|
||||
import { Column, Entity, ManyToOne, Unique } from 'typeorm';
|
||||
import { AbstractEntity } from '../../abstract/entities/abstract.entity';
|
||||
import { PresenceSensorDto } from '../dtos';
|
||||
import { DeviceEntity } from '../../device/entities/device.entity';
|
||||
import { SpaceEntity } from '../../space/entities/space.entity';
|
||||
|
||||
@Entity({ name: 'presence-sensor-daily-device-detection' })
|
||||
@Unique(['deviceUuid', 'eventDate'])
|
||||
export class PresenceSensorDailyDeviceEntity extends AbstractEntity<PresenceSensorDto> {
|
||||
@Column({ nullable: false })
|
||||
public deviceUuid: string;
|
||||
|
||||
@Column({ nullable: false, type: 'date' })
|
||||
public eventDate: string;
|
||||
|
||||
@Column({ nullable: false })
|
||||
public CountMotionDetected: number;
|
||||
|
||||
@Column({ nullable: false })
|
||||
public CountPresenceDetected: number;
|
||||
|
||||
@Column({ nullable: false })
|
||||
public CountTotalPresenceDetected: number;
|
||||
|
||||
@ManyToOne(() => DeviceEntity, (device) => device.presenceSensorDaily)
|
||||
device: DeviceEntity;
|
||||
|
||||
constructor(partial: Partial<PresenceSensorDailyDeviceEntity>) {
|
||||
super();
|
||||
Object.assign(this, partial);
|
||||
}
|
||||
}
|
||||
@Entity({ name: 'presence-sensor-daily-space-detection' })
|
||||
@Unique(['spaceUuid', 'eventDate'])
|
||||
export class PresenceSensorDailySpaceEntity extends AbstractEntity<PresenceSensorDto> {
|
||||
@Column({ nullable: false })
|
||||
public spaceUuid: string;
|
||||
|
||||
@Column({ nullable: false, type: 'date' })
|
||||
public eventDate: string;
|
||||
|
||||
@Column({ nullable: false })
|
||||
public CountMotionDetected: number;
|
||||
|
||||
@Column({ nullable: false })
|
||||
public CountPresenceDetected: number;
|
||||
|
||||
@Column({ nullable: false })
|
||||
public CountTotalPresenceDetected: number;
|
||||
|
||||
@ManyToOne(() => SpaceEntity, (space) => space.presenceSensorDaily)
|
||||
space: SpaceEntity;
|
||||
|
||||
constructor(partial: Partial<PresenceSensorDailySpaceEntity>) {
|
||||
super();
|
||||
Object.assign(this, partial);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
export * from './presence-sensor.repository';
|
||||
@ -0,0 +1,20 @@
|
||||
WITH params AS (
|
||||
SELECT
|
||||
TO_DATE(NULLIF($1, ''), 'MM-YYYY') AS month,
|
||||
string_to_array(NULLIF($2, ''), ',') AS device_ids
|
||||
)
|
||||
|
||||
SELECT
|
||||
A.date,
|
||||
SUM(A.energy_consumed_kW::numeric) AS total_energy_consumed_KW,
|
||||
SUM(A.energy_consumed_A::numeric) AS total_energy_consumed_A,
|
||||
SUM(A.energy_consumed_B::numeric) AS total_energy_consumed_B,
|
||||
SUM(A.energy_consumed_C::numeric) AS total_energy_consumed_C
|
||||
FROM public."power-clamp-energy-consumed-daily" AS A
|
||||
JOIN public.device AS B
|
||||
ON A.device_uuid::TEXT = B."uuid"::TEXT
|
||||
JOIN params P ON TRUE
|
||||
WHERE B."uuid"::TEXT = ANY(P.device_ids)
|
||||
AND (P.month IS NULL OR date_trunc('month', A.date)= P.month)
|
||||
GROUP BY A.date
|
||||
ORDER BY A.date;
|
||||
@ -0,0 +1,21 @@
|
||||
WITH params AS (
|
||||
SELECT
|
||||
TO_DATE(NULLIF($1, ''), 'DD-MM-YYYY') AS start_date,
|
||||
TO_DATE(NULLIF($2, ''), 'DD-MM-YYYY') AS end_date,
|
||||
string_to_array(NULLIF($3, ''), ',') AS device_ids
|
||||
)
|
||||
|
||||
SELECT TO_CHAR(A.date, 'MM-YYYY') AS month,
|
||||
SUM(A.energy_consumed_kW::numeric) AS total_energy_consumed_KW,
|
||||
SUM(A.energy_consumed_A::numeric) AS total_energy_consumed_A,
|
||||
SUM(A.energy_consumed_B::numeric) AS total_energy_consumed_B,
|
||||
SUM(A.energy_consumed_C::numeric) AS total_energy_consumed_C
|
||||
FROM public."power-clamp-energy-consumed-daily" AS A
|
||||
JOIN public.device AS B
|
||||
ON A.device_uuid::TEXT = B."uuid"::TEXT
|
||||
JOIN params P ON TRUE
|
||||
WHERE B."uuid"::TEXT = ANY(P.device_ids)
|
||||
AND (P.start_date IS NULL OR A.date >= P.start_date)
|
||||
AND (P.end_date IS NULL OR A.date <= P.end_date)
|
||||
GROUP BY 1
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
SELECT
|
||||
B.space_device_uuid AS space_id,
|
||||
A."date",
|
||||
SUM(A.energy_consumed_kW::numeric) AS total_energy_consumed_KW,
|
||||
SUM(A.energy_consumed_A::numeric) AS total_energy_consumed_A,
|
||||
SUM(A.energy_consumed_B::numeric) AS total_energy_consumed_B,
|
||||
SUM(A.energy_consumed_C::numeric) AS total_energy_consumed_C
|
||||
FROM public."power-clamp-energy-consumed-daily" AS A -- I want to change the source table in the future.
|
||||
JOIN public.device AS B
|
||||
ON A.device_uuid::TEXT = B."uuid"::TEXT
|
||||
GROUP BY 1, 2;
|
||||
Reference in New Issue
Block a user