sunrise-cms/database/getLotOccupancies.ts

244 lines
7.2 KiB
TypeScript

import {
dateIntegerToString,
dateStringToInteger
} from '@cityssm/utils-datetime'
import type { PoolConnection } from 'better-sqlite-pool'
import { getOccupancyTypeById } from '../helpers/functions.cache.js'
import * as configFunctions from '../helpers/functions.config.js'
import {
getLotNameWhereClause,
getOccupancyTimeWhereClause,
getOccupantNameWhereClause
} from '../helpers/functions.sqlFilters.js'
import type { LotOccupancy } from '../types/recordTypes.js'
import { getLotOccupancyFees } from './getLotOccupancyFees.js'
import { getLotOccupancyOccupants } from './getLotOccupancyOccupants.js'
import { getLotOccupancyTransactions } from './getLotOccupancyTransactions.js'
import { acquireConnection } from './pool.js'
interface GetLotOccupanciesFilters {
lotId?: number | string
occupancyTime?: '' | 'past' | 'current' | 'future'
occupancyStartDateString?: string
occupancyEffectiveDateString?: string
occupantName?: string
occupancyTypeId?: number | string
mapId?: number | string
lotNameSearchType?: '' | 'startsWith' | 'endsWith'
lotName?: string
lotTypeId?: number | string
workOrderId?: number | string
notWorkOrderId?: number | string
}
interface GetLotOccupanciesOptions {
limit: -1 | number
offset: number
includeOccupants: boolean
includeFees: boolean
includeTransactions: boolean
}
function buildWhereClause(filters: GetLotOccupanciesFilters): {
sqlWhereClause: string
sqlParameters: unknown[]
} {
let sqlWhereClause = ' where o.recordDelete_timeMillis is null'
const sqlParameters: unknown[] = []
if ((filters.lotId ?? '') !== '') {
sqlWhereClause += ' and o.lotId = ?'
sqlParameters.push(filters.lotId)
}
const lotNameFilters = getLotNameWhereClause(
filters.lotName,
filters.lotNameSearchType ?? '',
'l'
)
sqlWhereClause += lotNameFilters.sqlWhereClause
sqlParameters.push(...lotNameFilters.sqlParameters)
const occupantNameFilters = getOccupantNameWhereClause(
filters.occupantName,
'o'
)
if (occupantNameFilters.sqlParameters.length > 0) {
sqlWhereClause +=
' and o.lotOccupancyId in (select lotOccupancyId from LotOccupancyOccupants o where recordDelete_timeMillis is null' +
occupantNameFilters.sqlWhereClause +
')'
sqlParameters.push(...occupantNameFilters.sqlParameters)
}
if ((filters.occupancyTypeId ?? '') !== '') {
sqlWhereClause += ' and o.occupancyTypeId = ?'
sqlParameters.push(filters.occupancyTypeId)
}
const occupancyTimeFilters = getOccupancyTimeWhereClause(
filters.occupancyTime ?? '',
'o'
)
sqlWhereClause += occupancyTimeFilters.sqlWhereClause
sqlParameters.push(...occupancyTimeFilters.sqlParameters)
if ((filters.occupancyStartDateString ?? '') !== '') {
sqlWhereClause += ' and o.occupancyStartDate = ?'
sqlParameters.push(dateStringToInteger(filters.occupancyStartDateString!))
}
if ((filters.occupancyEffectiveDateString ?? '') !== '') {
sqlWhereClause += ` and (
o.occupancyEndDate is null
or (o.occupancyStartDate <= ? and o.occupancyEndDate >= ?)
)`
sqlParameters.push(
dateStringToInteger(filters.occupancyEffectiveDateString!),
dateStringToInteger(filters.occupancyEffectiveDateString!)
)
}
if ((filters.mapId ?? '') !== '') {
sqlWhereClause += ' and l.mapId = ?'
sqlParameters.push(filters.mapId)
}
if ((filters.lotTypeId ?? '') !== '') {
sqlWhereClause += ' and l.lotTypeId = ?'
sqlParameters.push(filters.lotTypeId)
}
if ((filters.workOrderId ?? '') !== '') {
sqlWhereClause +=
' and o.lotOccupancyId in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)'
sqlParameters.push(filters.workOrderId)
}
if ((filters.notWorkOrderId ?? '') !== '') {
sqlWhereClause +=
' and o.lotOccupancyId not in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)'
sqlParameters.push(filters.notWorkOrderId)
}
return {
sqlWhereClause,
sqlParameters
}
}
async function addInclusions(
lotOccupancy: LotOccupancy,
options: GetLotOccupanciesOptions,
database: PoolConnection
): Promise<LotOccupancy> {
if (options.includeFees) {
lotOccupancy.lotOccupancyFees = await getLotOccupancyFees(
lotOccupancy.lotOccupancyId,
database
)
}
if (options.includeTransactions) {
lotOccupancy.lotOccupancyTransactions = await getLotOccupancyTransactions(
lotOccupancy.lotOccupancyId,
{ includeIntegrations: false },
database
)
}
if (options.includeOccupants) {
lotOccupancy.lotOccupancyOccupants = await getLotOccupancyOccupants(
lotOccupancy.lotOccupancyId,
database
)
}
return lotOccupancy
}
export async function getLotOccupancies(
filters: GetLotOccupanciesFilters,
options: GetLotOccupanciesOptions,
connectedDatabase?: PoolConnection
): Promise<{ count: number; lotOccupancies: LotOccupancy[] }> {
const database = connectedDatabase ?? (await acquireConnection())
database.function('userFn_dateIntegerToString', dateIntegerToString)
const { sqlWhereClause, sqlParameters } = buildWhereClause(filters)
let count = options.limit
const isLimited = options.limit !== -1
if (isLimited) {
count = (
database
.prepare(
`select count(*) as recordCount
from LotOccupancies o
left join Lots l on o.lotId = l.lotId
${sqlWhereClause}`
)
.get(sqlParameters) as { recordCount: number }
).recordCount
}
let lotOccupancies: LotOccupancy[] = []
if (count !== 0) {
lotOccupancies = database
.prepare(
`select o.lotOccupancyId,
o.occupancyTypeId, t.occupancyType,
o.lotId, lt.lotType, l.lotName,
l.mapId, m.mapName,
o.occupancyStartDate, userFn_dateIntegerToString(o.occupancyStartDate) as occupancyStartDateString,
o.occupancyEndDate, userFn_dateIntegerToString(o.occupancyEndDate) as occupancyEndDateString
from LotOccupancies o
left join OccupancyTypes t on o.occupancyTypeId = t.occupancyTypeId
left join Lots l on o.lotId = l.lotId
left join LotTypes lt on l.lotTypeId = lt.lotTypeId
left join Maps m on l.mapId = m.mapId
${sqlWhereClause}
order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId, o.lotOccupancyId desc` +
(isLimited ? ` limit ${options.limit} offset ${options.offset}` : '')
)
.all(sqlParameters) as LotOccupancy[]
if (!isLimited) {
count = lotOccupancies.length
}
for (const lotOccupancy of lotOccupancies) {
const occupancyType = await getOccupancyTypeById(
lotOccupancy.occupancyTypeId!
)
if (occupancyType !== undefined) {
lotOccupancy.printEJS = (
occupancyType.occupancyTypePrints ?? []
).includes('*')
? configFunctions.getConfigProperty('settings.lotOccupancy.prints')[0]
: occupancyType.occupancyTypePrints![0]
}
await addInclusions(lotOccupancy, options, database)
}
}
if (connectedDatabase === undefined) {
database.release()
}
return {
count,
lotOccupancies
}
}
export default getLotOccupancies