sunrise-cms/helpers/lotOccupancyDB/getWorkOrderMilestones.ts

219 lines
6.6 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 === undefined) {
database.close()
}
return workOrderMilestones
}
export default getWorkOrderMilestones