sunrise-cms/helpers/lotOccupancyDB/getWorkOrderMilestones.ts

200 lines
7.1 KiB
TypeScript

import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import {
dateIntegerToString,
dateStringToInteger,
dateToInteger,
timeIntegerToString
} from "@cityssm/expressjs-server-js/dateTimeFns.js";
import * as configFunctions from "../functions.config.js";
import { getLots } from "./getLots.js";
import { getLotOccupancies } from "./getLotOccupancies.js";
import type * as recordTypes from "../../types/recordTypes";
export interface WorkOrderMilestoneFilters {
workOrderId?: number | string;
workOrderMilestoneDateFilter?: "upcomingMissed" | "recent" | "date";
workOrderMilestoneDateString?: string;
workOrderTypeIds?: string;
workOrderMilestoneTypeIds?: string;
}
interface WorkOrderMilestoneOptions {
includeWorkOrders?: boolean;
orderBy: "completion" | "date";
}
const commaSeparatedNumbersRegex = /^\d+(,\d+)*$/;
function buildWhereClause(filters: WorkOrderMilestoneFilters): {
sqlWhereClause: string;
sqlParameters: unknown[];
} {
let sqlWhereClause = " where m.recordDelete_timeMillis is null and w.recordDelete_timeMillis is null";
const sqlParameters: unknown[] = [];
if (filters.workOrderId) {
sqlWhereClause += " and m.workOrderId = ?";
sqlParameters.push(filters.workOrderId);
}
const date = new Date();
const currentDateNumber = dateToInteger(date);
date.setDate(
date.getDate() -
configFunctions.getProperty("settings.workOrders.workOrderMilestoneDateRecentBeforeDays")
);
const recentBeforeDateNumber = dateToInteger(date);
date.setDate(
date.getDate() +
configFunctions.getProperty("settings.workOrders.workOrderMilestoneDateRecentBeforeDays") +
configFunctions.getProperty("settings.workOrders.workOrderMilestoneDateRecentAfterDays")
);
const recentAfterDateNumber = dateToInteger(date);
switch (filters.workOrderMilestoneDateFilter) {
case "upcomingMissed": {
sqlWhereClause +=
" and (m.workOrderMilestoneCompletionDate is null or m.workOrderMilestoneDate >= ?)";
sqlParameters.push(currentDateNumber);
break;
}
case "recent": {
sqlWhereClause += " and m.workOrderMilestoneDate >= ? and m.workOrderMilestoneDate <= ?";
sqlParameters.push(recentBeforeDateNumber, recentAfterDateNumber);
break;
}
}
if (filters.workOrderMilestoneDateString) {
sqlWhereClause += " and m.workOrderMilestoneDate = ?";
sqlParameters.push(dateStringToInteger(filters.workOrderMilestoneDateString));
}
if (filters.workOrderTypeIds && commaSeparatedNumbersRegex.test(filters.workOrderTypeIds)) {
sqlWhereClause += " and w.workOrderTypeId in (" + filters.workOrderTypeIds + ")";
}
if (
filters.workOrderMilestoneTypeIds &&
commaSeparatedNumbersRegex.test(filters.workOrderMilestoneTypeIds)
) {
sqlWhereClause += " and m.workOrderMilestoneTypeId in (" + filters.workOrderMilestoneTypeIds + ")";
}
return {
sqlWhereClause,
sqlParameters
};
}
export function getWorkOrderMilestones(
filters: WorkOrderMilestoneFilters,
options: WorkOrderMilestoneOptions,
connectedDatabase?: sqlite.Database
): recordTypes.WorkOrderMilestone[] {
const database =
connectedDatabase ||
sqlite(databasePath, {
readonly: true
});
database.function("userFn_dateIntegerToString", dateIntegerToString);
database.function("userFn_timeIntegerToString", timeIntegerToString);
// Filters
const { sqlWhereClause, sqlParameters } = buildWhereClause(filters);
// Order By
let orderByClause = "";
switch (options.orderBy) {
case "completion": {
orderByClause =
" order by" +
" m.workOrderMilestoneCompletionDate, m.workOrderMilestoneCompletionTime," +
" m.workOrderMilestoneDate, case when m.workOrderMilestoneTime = 0 then 9999 else m.workOrderMilestoneTime end," +
" t.orderNumber, m.workOrderMilestoneId";
break;
}
case "date": {
orderByClause =
" order by m.workOrderMilestoneDate, case when m.workOrderMilestoneTime = 0 then 9999 else m.workOrderMilestoneTime end," +
" t.orderNumber, m.workOrderId, m.workOrderMilestoneId";
break;
}
}
// Query
const sql =
"select m.workOrderMilestoneId," +
" m.workOrderMilestoneTypeId, t.workOrderMilestoneType," +
" m.workOrderMilestoneDate, userFn_dateIntegerToString(m.workOrderMilestoneDate) as workOrderMilestoneDateString," +
" m.workOrderMilestoneTime, userFn_timeIntegerToString(m.workOrderMilestoneTime) as workOrderMilestoneTimeString," +
" m.workOrderMilestoneDescription," +
" m.workOrderMilestoneCompletionDate, userFn_dateIntegerToString(m.workOrderMilestoneCompletionDate) as workOrderMilestoneCompletionDateString," +
" m.workOrderMilestoneCompletionTime, userFn_timeIntegerToString(m.workOrderMilestoneCompletionTime) as workOrderMilestoneCompletionTimeString," +
(options.includeWorkOrders
? " m.workOrderId, w.workOrderNumber, wt.workOrderType, w.workOrderDescription," +
" w.workOrderOpenDate, userFn_dateIntegerToString(w.workOrderOpenDate) as workOrderOpenDateString," +
" w.workOrderCloseDate, userFn_dateIntegerToString(w.workOrderCloseDate) as workOrderCloseDateString," +
" w.recordUpdate_timeMillis as workOrderRecordUpdate_timeMillis,"
: "") +
" m.recordCreate_userName, m.recordCreate_timeMillis," +
" m.recordUpdate_userName, m.recordUpdate_timeMillis" +
" from WorkOrderMilestones m" +
" left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId" +
" left join WorkOrders w on m.workOrderId = w.workOrderId" +
" left join WorkOrderTypes wt on w.workOrderTypeId = wt.workOrderTypeId" +
sqlWhereClause +
orderByClause;
const workOrderMilestones: recordTypes.WorkOrderMilestone[] = database.prepare(sql).all(sqlParameters);
if (options.includeWorkOrders) {
for (const workOrderMilestone of workOrderMilestones) {
workOrderMilestone.workOrderLots = getLots(
{
workOrderId: workOrderMilestone.workOrderId
},
{
limit: -1,
offset: 0
},
database
).lots;
workOrderMilestone.workOrderLotOccupancies = getLotOccupancies(
{
workOrderId: workOrderMilestone.workOrderId
},
{
limit: -1,
offset: 0,
includeOccupants: true
},
database
).lotOccupancies;
}
}
if (!connectedDatabase) {
database.close();
}
return workOrderMilestones;
}
export default getWorkOrderMilestones;