development
parent
fad2578773
commit
31d11de8d4
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js";
|
||||||
|
import { getFeeCategories } from "../../helpers/lotOccupancyDB/getFeeCategories.js";
|
||||||
|
export const handler = (_request, response) => {
|
||||||
|
const feeCategories = getFeeCategories({}, {
|
||||||
|
includeFees: true
|
||||||
|
});
|
||||||
|
const occupancyTypes = getOccupancyTypes();
|
||||||
|
const lotTypes = getLotTypes();
|
||||||
|
response.render("admin-fees", {
|
||||||
|
headTitle: "Fee Management",
|
||||||
|
feeCategories,
|
||||||
|
occupancyTypes,
|
||||||
|
lotTypes
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import type {
|
||||||
|
RequestHandler
|
||||||
|
} from "express";
|
||||||
|
|
||||||
|
import { getLotTypes, getOccupancyTypes } from "../../helpers/functions.cache.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getFeeCategories
|
||||||
|
} from "../../helpers/lotOccupancyDB/getFeeCategories.js";
|
||||||
|
|
||||||
|
|
||||||
|
export const handler: RequestHandler = (_request, response) => {
|
||||||
|
|
||||||
|
const feeCategories = getFeeCategories({}, {
|
||||||
|
includeFees: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const occupancyTypes = getOccupancyTypes();
|
||||||
|
const lotTypes = getLotTypes();
|
||||||
|
|
||||||
|
response.render("admin-fees", {
|
||||||
|
headTitle: "Fee Management",
|
||||||
|
feeCategories,
|
||||||
|
occupancyTypes,
|
||||||
|
lotTypes
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
export const handler = (_request, response) => {
|
|
||||||
response.render("admin-licenceCategories", {
|
|
||||||
headTitle: "Licence Categories"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
export default handler;
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
import type { RequestHandler } from "express";
|
|
||||||
|
|
||||||
|
|
||||||
export const handler: RequestHandler = (_request, response) => {
|
|
||||||
|
|
||||||
response.render("admin-licenceCategories", {
|
|
||||||
headTitle: "Licence Categories"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default handler;
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
export declare const handler: RequestHandler;
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { addFeeCategory } from "../../helpers/lotOccupancyDB/addFeeCategory.js";
|
||||||
|
import { getFeeCategories } from "../../helpers/lotOccupancyDB/getFeeCategories.js";
|
||||||
|
export const handler = async (request, response) => {
|
||||||
|
const feeCategoryId = addFeeCategory(request.body, request.session);
|
||||||
|
const feeCategories = getFeeCategories({}, {
|
||||||
|
includeFees: true
|
||||||
|
});
|
||||||
|
response.json({
|
||||||
|
success: true,
|
||||||
|
feeCategoryId,
|
||||||
|
feeCategories
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import type {
|
||||||
|
RequestHandler
|
||||||
|
} from "express";
|
||||||
|
|
||||||
|
import {
|
||||||
|
addFeeCategory
|
||||||
|
} from "../../helpers/lotOccupancyDB/addFeeCategory.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getFeeCategories
|
||||||
|
} from "../../helpers/lotOccupancyDB/getFeeCategories.js";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const handler: RequestHandler = async (request, response) => {
|
||||||
|
|
||||||
|
const feeCategoryId = addFeeCategory(request.body, request.session);
|
||||||
|
|
||||||
|
const feeCategories = getFeeCategories({}, {
|
||||||
|
includeFees: true
|
||||||
|
});
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
success: true,
|
||||||
|
feeCategoryId,
|
||||||
|
feeCategories
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import type { RequestHandler } from "express";
|
||||||
|
export declare const handler: RequestHandler;
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { updateFeeCategory } from "../../helpers/lotOccupancyDB/updateFeeCategory.js";
|
||||||
|
import { getFeeCategories } from "../../helpers/lotOccupancyDB/getFeeCategories.js";
|
||||||
|
export const handler = async (request, response) => {
|
||||||
|
const success = updateFeeCategory(request.body, request.session);
|
||||||
|
const feeCategories = getFeeCategories({}, {
|
||||||
|
includeFees: true
|
||||||
|
});
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
feeCategories
|
||||||
|
});
|
||||||
|
};
|
||||||
|
export default handler;
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import type {
|
||||||
|
RequestHandler
|
||||||
|
} from "express";
|
||||||
|
|
||||||
|
import {
|
||||||
|
updateFeeCategory
|
||||||
|
} from "../../helpers/lotOccupancyDB/updateFeeCategory.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getFeeCategories
|
||||||
|
} from "../../helpers/lotOccupancyDB/getFeeCategories.js";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const handler: RequestHandler = async (request, response) => {
|
||||||
|
|
||||||
|
const success = updateFeeCategory(request.body, request.session);
|
||||||
|
|
||||||
|
const feeCategories = getFeeCategories({}, {
|
||||||
|
includeFees: true
|
||||||
|
});
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
success,
|
||||||
|
feeCategories
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default handler;
|
||||||
|
|
@ -2,12 +2,16 @@ import type * as recordTypes from "../types/recordTypes";
|
||||||
export declare function getLotOccupantTypes(): recordTypes.LotOccupantType[];
|
export declare function getLotOccupantTypes(): recordTypes.LotOccupantType[];
|
||||||
export declare function getLotOccupantTypeById(lotOccupantTypeId: number): recordTypes.LotOccupantType;
|
export declare function getLotOccupantTypeById(lotOccupantTypeId: number): recordTypes.LotOccupantType;
|
||||||
export declare function getLotOccupantTypesByLotOccupantType(lotOccupantType: string): recordTypes.LotOccupantType;
|
export declare function getLotOccupantTypesByLotOccupantType(lotOccupantType: string): recordTypes.LotOccupantType;
|
||||||
|
export declare function clearLotOccupantTypesCache(): void;
|
||||||
export declare function getLotStatuses(): recordTypes.LotStatus[];
|
export declare function getLotStatuses(): recordTypes.LotStatus[];
|
||||||
export declare function getLotStatusById(lotStatusId: number): recordTypes.LotStatus;
|
export declare function getLotStatusById(lotStatusId: number): recordTypes.LotStatus;
|
||||||
export declare function getLotStatusByLotStatus(lotStatus: string): recordTypes.LotStatus;
|
export declare function getLotStatusByLotStatus(lotStatus: string): recordTypes.LotStatus;
|
||||||
|
export declare function clearLotStatusesCache(): void;
|
||||||
export declare function getLotTypes(): recordTypes.LotType[];
|
export declare function getLotTypes(): recordTypes.LotType[];
|
||||||
export declare function getLotTypeById(lotTypeId: number): recordTypes.LotType;
|
export declare function getLotTypeById(lotTypeId: number): recordTypes.LotType;
|
||||||
export declare function getLotTypesByLotType(lotType: string): recordTypes.LotType;
|
export declare function getLotTypesByLotType(lotType: string): recordTypes.LotType;
|
||||||
|
export declare function clearLotTypesCache(): void;
|
||||||
export declare function getOccupancyTypes(): recordTypes.OccupancyType[];
|
export declare function getOccupancyTypes(): recordTypes.OccupancyType[];
|
||||||
export declare function getOccupancyTypeById(occupancyTypeId: number): recordTypes.OccupancyType;
|
export declare function getOccupancyTypeById(occupancyTypeId: number): recordTypes.OccupancyType;
|
||||||
export declare function getOccupancyTypeByOccupancyType(occupancyTypeString: string): recordTypes.OccupancyType;
|
export declare function getOccupancyTypeByOccupancyType(occupancyTypeString: string): recordTypes.OccupancyType;
|
||||||
|
export declare function clearOccupancyTypesCache(): void;
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ export function getLotOccupantTypesByLotOccupantType(lotOccupantType) {
|
||||||
return currentLotOccupantType.lotOccupantType.toLowerCase() === lotOccupantTypeLowerCase;
|
return currentLotOccupantType.lotOccupantType.toLowerCase() === lotOccupantTypeLowerCase;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
export function clearLotOccupantTypesCache() {
|
||||||
|
lotOccupantTypes = undefined;
|
||||||
|
}
|
||||||
let lotStatuses;
|
let lotStatuses;
|
||||||
export function getLotStatuses() {
|
export function getLotStatuses() {
|
||||||
if (!lotStatuses) {
|
if (!lotStatuses) {
|
||||||
|
|
@ -43,6 +46,9 @@ export function getLotStatusByLotStatus(lotStatus) {
|
||||||
return currentLotStatus.lotStatus.toLowerCase() === lotStatusLowerCase;
|
return currentLotStatus.lotStatus.toLowerCase() === lotStatusLowerCase;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
export function clearLotStatusesCache() {
|
||||||
|
lotStatuses = undefined;
|
||||||
|
}
|
||||||
let lotTypes;
|
let lotTypes;
|
||||||
export function getLotTypes() {
|
export function getLotTypes() {
|
||||||
if (!lotTypes) {
|
if (!lotTypes) {
|
||||||
|
|
@ -63,6 +69,9 @@ export function getLotTypesByLotType(lotType) {
|
||||||
return currentLotType.lotType.toLowerCase() === lotTypeLowerCase;
|
return currentLotType.lotType.toLowerCase() === lotTypeLowerCase;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
export function clearLotTypesCache() {
|
||||||
|
lotTypes = undefined;
|
||||||
|
}
|
||||||
let occupancyTypes;
|
let occupancyTypes;
|
||||||
const occupancyTypeMap = new Map();
|
const occupancyTypeMap = new Map();
|
||||||
export function getOccupancyTypes() {
|
export function getOccupancyTypes() {
|
||||||
|
|
@ -89,3 +98,7 @@ export function getOccupancyTypeByOccupancyType(occupancyTypeString) {
|
||||||
}
|
}
|
||||||
return occupancyType;
|
return occupancyType;
|
||||||
}
|
}
|
||||||
|
export function clearOccupancyTypesCache() {
|
||||||
|
occupancyTypes = undefined;
|
||||||
|
occupancyTypeMap.clear();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,24 @@
|
||||||
import { getLotOccupantTypes as getLotOccupantTypesFromDatabase } from "./lotOccupancyDB/getLotOccupantTypes.js";
|
import {
|
||||||
import { getLotStatuses as getLotStatusesFromDatabase } from "./lotOccupancyDB/getLotStatuses.js";
|
getLotOccupantTypes as getLotOccupantTypesFromDatabase
|
||||||
import { getLotTypes as getLotTypesFromDatabase } from "./lotOccupancyDB/getLotTypes.js";
|
} from "./lotOccupancyDB/getLotOccupantTypes.js";
|
||||||
import { getOccupancyTypes as getOccupancyTypesFromDatabase } from "./lotOccupancyDB/getOccupancyTypes.js";
|
|
||||||
|
import {
|
||||||
|
getLotStatuses as getLotStatusesFromDatabase
|
||||||
|
} from "./lotOccupancyDB/getLotStatuses.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getLotTypes as getLotTypesFromDatabase
|
||||||
|
} from "./lotOccupancyDB/getLotTypes.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getOccupancyTypes as getOccupancyTypesFromDatabase
|
||||||
|
} from "./lotOccupancyDB/getOccupancyTypes.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getOccupancyType
|
||||||
|
} from "./lotOccupancyDB/getOccupancyType.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../types/recordTypes";
|
import type * as recordTypes from "../types/recordTypes";
|
||||||
import { getOccupancyType } from "./lotOccupancyDB/getOccupancyType.js";
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lot Occupant Types
|
* Lot Occupant Types
|
||||||
|
|
@ -41,42 +55,50 @@ export function getLotOccupantTypesByLotOccupantType(lotOccupantType: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearLotOccupantTypesCache() {
|
||||||
|
lotOccupantTypes = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lot Statuses
|
* Lot Statuses
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let lotStatuses: recordTypes.LotStatus[];
|
let lotStatuses: recordTypes.LotStatus[];
|
||||||
|
|
||||||
export function getLotStatuses () {
|
export function getLotStatuses() {
|
||||||
|
|
||||||
if (!lotStatuses) {
|
if (!lotStatuses) {
|
||||||
lotStatuses = getLotStatusesFromDatabase();
|
lotStatuses = getLotStatusesFromDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
return lotStatuses;
|
return lotStatuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLotStatusById (lotStatusId: number) {
|
export function getLotStatusById(lotStatusId: number) {
|
||||||
|
|
||||||
const cachedLotStatuses = getLotStatuses();
|
const cachedLotStatuses = getLotStatuses();
|
||||||
|
|
||||||
return cachedLotStatuses.find((currentLotStatus) => {
|
return cachedLotStatuses.find((currentLotStatus) => {
|
||||||
return currentLotStatus.lotStatusId === lotStatusId;
|
return currentLotStatus.lotStatusId === lotStatusId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getLotStatusByLotStatus (lotStatus: string) {
|
export function getLotStatusByLotStatus(lotStatus: string) {
|
||||||
|
|
||||||
const cachedLotStatuses = getLotStatuses();
|
const cachedLotStatuses = getLotStatuses();
|
||||||
|
|
||||||
const lotStatusLowerCase = lotStatus.toLowerCase();
|
const lotStatusLowerCase = lotStatus.toLowerCase();
|
||||||
|
|
||||||
return cachedLotStatuses.find((currentLotStatus) => {
|
return cachedLotStatuses.find((currentLotStatus) => {
|
||||||
return currentLotStatus.lotStatus.toLowerCase() === lotStatusLowerCase;
|
return currentLotStatus.lotStatus.toLowerCase() === lotStatusLowerCase;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearLotStatusesCache() {
|
||||||
|
lotStatuses = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lot Types
|
* Lot Types
|
||||||
*/
|
*/
|
||||||
|
|
@ -112,14 +134,19 @@ export function getLotTypesByLotType(lotType: string) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function clearLotTypesCache() {
|
||||||
|
lotTypes = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Occupancy Types
|
* Occupancy Types
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let occupancyTypes: recordTypes.OccupancyType[];
|
let occupancyTypes: recordTypes.OccupancyType[];
|
||||||
const occupancyTypeMap = new Map<number, recordTypes.OccupancyType>();
|
const occupancyTypeMap = new Map < number,
|
||||||
|
recordTypes.OccupancyType > ();
|
||||||
|
|
||||||
export function getOccupancyTypes () {
|
export function getOccupancyTypes() {
|
||||||
|
|
||||||
if (!occupancyTypes) {
|
if (!occupancyTypes) {
|
||||||
occupancyTypes = getOccupancyTypesFromDatabase();
|
occupancyTypes = getOccupancyTypesFromDatabase();
|
||||||
|
|
@ -128,7 +155,7 @@ export function getOccupancyTypes () {
|
||||||
return occupancyTypes;
|
return occupancyTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOccupancyTypeById (occupancyTypeId: number) {
|
export function getOccupancyTypeById(occupancyTypeId: number) {
|
||||||
|
|
||||||
if (!occupancyTypeMap.has(occupancyTypeId)) {
|
if (!occupancyTypeMap.has(occupancyTypeId)) {
|
||||||
|
|
||||||
|
|
@ -139,8 +166,8 @@ export function getOccupancyTypeById (occupancyTypeId: number) {
|
||||||
return occupancyTypeMap.get(occupancyTypeId);
|
return occupancyTypeMap.get(occupancyTypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getOccupancyTypeByOccupancyType (occupancyTypeString: string) {
|
export function getOccupancyTypeByOccupancyType(occupancyTypeString: string) {
|
||||||
|
|
||||||
const cachedOccupancyTypes = getOccupancyTypes();
|
const cachedOccupancyTypes = getOccupancyTypes();
|
||||||
|
|
||||||
const occupancyTypeLowerCase = occupancyTypeString.toLowerCase();
|
const occupancyTypeLowerCase = occupancyTypeString.toLowerCase();
|
||||||
|
|
@ -155,4 +182,9 @@ export function getOccupancyTypeByOccupancyType (occupancyTypeString: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return occupancyType;
|
return occupancyType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearOccupancyTypesCache() {
|
||||||
|
occupancyTypes = undefined;
|
||||||
|
occupancyTypeMap.clear();
|
||||||
}
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import { addOccupancyTypeField } from "./lotOccupancyDB/addOccupancyTypeField.js
|
||||||
import { addLotStatus } from "./lotOccupancyDB/addLotStatus.js";
|
import { addLotStatus } from "./lotOccupancyDB/addLotStatus.js";
|
||||||
import { addLotOccupantType } from "./lotOccupancyDB/addLotOccupantType.js";
|
import { addLotOccupantType } from "./lotOccupancyDB/addLotOccupantType.js";
|
||||||
import Debug from "debug";
|
import Debug from "debug";
|
||||||
|
import addFeeCategory from "./lotOccupancyDB/addFeeCategory.js";
|
||||||
const debug = Debug("lot-occupancy-system:initialize");
|
const debug = Debug("lot-occupancy-system:initialize");
|
||||||
const session = {
|
const session = {
|
||||||
user: {
|
user: {
|
||||||
|
|
@ -147,5 +148,25 @@ const initializeCemeteryDatabase = () => {
|
||||||
maximumLength: 100,
|
maximumLength: 100,
|
||||||
orderNumber: 21
|
orderNumber: 21
|
||||||
}, session);
|
}, session);
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Interment Rights",
|
||||||
|
orderNumber: 1
|
||||||
|
}, session);
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Cremation Services",
|
||||||
|
orderNumber: 2
|
||||||
|
}, session);
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Burial Charges",
|
||||||
|
orderNumber: 3
|
||||||
|
}, session);
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Disinterment of Human Remains",
|
||||||
|
orderNumber: 4
|
||||||
|
}, session);
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Additional Services",
|
||||||
|
orderNumber: 5
|
||||||
|
}, session);
|
||||||
};
|
};
|
||||||
initializeCemeteryDatabase();
|
initializeCemeteryDatabase();
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import type {
|
||||||
} from "../types/recordTypes.js";
|
} from "../types/recordTypes.js";
|
||||||
|
|
||||||
import Debug from "debug";
|
import Debug from "debug";
|
||||||
|
import addFeeCategory from "./lotOccupancyDB/addFeeCategory.js";
|
||||||
const debug = Debug("lot-occupancy-system:initialize");
|
const debug = Debug("lot-occupancy-system:initialize");
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -220,6 +221,35 @@ const initializeCemeteryDatabase = () => {
|
||||||
maximumLength: 100,
|
maximumLength: 100,
|
||||||
orderNumber: 21
|
orderNumber: 21
|
||||||
}, session);
|
}, session);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fee Categories
|
||||||
|
*/
|
||||||
|
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Interment Rights",
|
||||||
|
orderNumber: 1
|
||||||
|
}, session);
|
||||||
|
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Cremation Services",
|
||||||
|
orderNumber: 2
|
||||||
|
}, session);
|
||||||
|
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Burial Charges",
|
||||||
|
orderNumber: 3
|
||||||
|
}, session);
|
||||||
|
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Disinterment of Human Remains",
|
||||||
|
orderNumber: 4
|
||||||
|
}, session);
|
||||||
|
|
||||||
|
addFeeCategory({
|
||||||
|
feeCategory: "Additional Services",
|
||||||
|
orderNumber: 5
|
||||||
|
}, session);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -172,16 +172,29 @@ export const initializeDatabase = () => {
|
||||||
")").run();
|
")").run();
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lotoccupancycomments_datetime" +
|
lotOccupancyDB.prepare("create index if not exists idx_lotoccupancycomments_datetime" +
|
||||||
" on LotOccupancyComments (lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime)").run();
|
" on LotOccupancyComments (lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime)").run();
|
||||||
|
lotOccupancyDB.prepare("create table if not exists FeeCategories (" +
|
||||||
|
"feeCategoryId integer not null primary key autoincrement," +
|
||||||
|
" feeCategory varchar(100) not null," +
|
||||||
|
" orderNumber smallint not null default 0," +
|
||||||
|
recordColumns +
|
||||||
|
")").run();
|
||||||
lotOccupancyDB.prepare("create table if not exists Fees (" +
|
lotOccupancyDB.prepare("create table if not exists Fees (" +
|
||||||
"feeId integer not null primary key autoincrement," +
|
"feeId integer not null primary key autoincrement," +
|
||||||
|
" feeCategoryId integer not null," +
|
||||||
" feeName varchar(100) not null," +
|
" feeName varchar(100) not null," +
|
||||||
|
" feeDescription text," +
|
||||||
" occupancyTypeId integer," +
|
" occupancyTypeId integer," +
|
||||||
" lotTypeId integer," +
|
" lotTypeId integer," +
|
||||||
|
" includeQuantity boolean not null default 0," +
|
||||||
|
" quantityUnit varchar(30)," +
|
||||||
" feeAmount decimal(6, 2)," +
|
" feeAmount decimal(6, 2)," +
|
||||||
" feeFunction varchar(100)," +
|
" feeFunction varchar(100)," +
|
||||||
|
" taxAmount decimal(6, 2)," +
|
||||||
|
" taxPercentage decimal(5, 2)," +
|
||||||
" isRequired bit not null default 0," +
|
" isRequired bit not null default 0," +
|
||||||
" orderNumber smallint not null default 0," +
|
" orderNumber smallint not null default 0," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
|
" foreign key (feeCategoryId) references FeeCategories (feeCategoryId)," +
|
||||||
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)," +
|
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)," +
|
||||||
" foreign key (lotTypeId) references LotTypes (lotTypeId)" +
|
" foreign key (lotTypeId) references LotTypes (lotTypeId)" +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
@ -190,7 +203,9 @@ export const initializeDatabase = () => {
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupancyFees (" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupancyFees (" +
|
||||||
"lotOccupancyId integer not null," +
|
"lotOccupancyId integer not null," +
|
||||||
" feeId integer not null," +
|
" feeId integer not null," +
|
||||||
|
" quantity decimal(4, 1) not null default 1," +
|
||||||
" feeAmount decimal(6, 2) not null," +
|
" feeAmount decimal(6, 2) not null," +
|
||||||
|
" taxAmount decmial(6, 2) not null," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" primary key (lotOccupancyId, feeId)," +
|
" primary key (lotOccupancyId, feeId)," +
|
||||||
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
lotOccupancyDB as databasePath
|
lotOccupancyDB as databasePath
|
||||||
} from "../data/databasePaths.js";
|
} from "../data/databasePaths.js";
|
||||||
|
|
||||||
import debug from "debug";
|
import debug from "debug";
|
||||||
|
|
@ -9,311 +9,327 @@ const debugSQL = debug("lot-occupancy-system:databaseInitializer");
|
||||||
|
|
||||||
|
|
||||||
const recordColumns = " recordCreate_userName varchar(30) not null," +
|
const recordColumns = " recordCreate_userName varchar(30) not null," +
|
||||||
" recordCreate_timeMillis integer not null," +
|
" recordCreate_timeMillis integer not null," +
|
||||||
" recordUpdate_userName varchar(30) not null," +
|
" recordUpdate_userName varchar(30) not null," +
|
||||||
" recordUpdate_timeMillis integer not null," +
|
" recordUpdate_timeMillis integer not null," +
|
||||||
" recordDelete_userName varchar(30)," +
|
" recordDelete_userName varchar(30)," +
|
||||||
" recordDelete_timeMillis integer";
|
" recordDelete_timeMillis integer";
|
||||||
|
|
||||||
|
|
||||||
export const initializeDatabase = (): boolean => {
|
export const initializeDatabase = (): boolean => {
|
||||||
|
|
||||||
const lotOccupancyDB = sqlite(databasePath);
|
const lotOccupancyDB = sqlite(databasePath);
|
||||||
|
|
||||||
const row = lotOccupancyDB
|
const row = lotOccupancyDB
|
||||||
.prepare("select name from sqlite_master where type = 'table' and name = 'Fees'")
|
.prepare("select name from sqlite_master where type = 'table' and name = 'Fees'")
|
||||||
.get();
|
.get();
|
||||||
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
|
|
||||||
debugSQL("Creating " + databasePath);
|
debugSQL("Creating " + databasePath);
|
||||||
|
|
||||||
// Lot Types
|
// Lot Types
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotTypes (" +
|
lotOccupancyDB.prepare("create table if not exists LotTypes (" +
|
||||||
"lotTypeId integer not null primary key autoincrement," +
|
"lotTypeId integer not null primary key autoincrement," +
|
||||||
" lotType varchar(100) not null," +
|
" lotType varchar(100) not null," +
|
||||||
" orderNumber smallint not null default 0," +
|
" orderNumber smallint not null default 0," +
|
||||||
recordColumns +
|
recordColumns +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lottypes_ordernumber" +
|
lotOccupancyDB.prepare("create index if not exists idx_lottypes_ordernumber" +
|
||||||
" on LotTypes (orderNumber, lotType)").run();
|
" on LotTypes (orderNumber, lotType)").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotTypeFields (" +
|
lotOccupancyDB.prepare("create table if not exists LotTypeFields (" +
|
||||||
"lotTypeFieldId integer not null primary key autoincrement," +
|
"lotTypeFieldId integer not null primary key autoincrement," +
|
||||||
" lotTypeId integer not null," +
|
" lotTypeId integer not null," +
|
||||||
" lotTypeField varchar(100) not null," +
|
" lotTypeField varchar(100) not null," +
|
||||||
" lotTypeFieldValues text," +
|
" lotTypeFieldValues text," +
|
||||||
" isRequired bit not null default 0," +
|
" isRequired bit not null default 0," +
|
||||||
" pattern varchar(100)," +
|
" pattern varchar(100)," +
|
||||||
" minimumLength smallint not null default 1 check (minimumLength >= 0)," +
|
" minimumLength smallint not null default 1 check (minimumLength >= 0)," +
|
||||||
" maximumLength smallint not null default 100 check (maximumLength >= 0)," +
|
" maximumLength smallint not null default 100 check (maximumLength >= 0)," +
|
||||||
" orderNumber smallint not null default 0," +
|
" orderNumber smallint not null default 0," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" foreign key (lotTypeId) references LotTypes (lotTypeId)" +
|
" foreign key (lotTypeId) references LotTypes (lotTypeId)" +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lottypefields_ordernumber" +
|
lotOccupancyDB.prepare("create index if not exists idx_lottypefields_ordernumber" +
|
||||||
" on LotTypeFields (lotTypeId, orderNumber, lotTypeField)").run();
|
" on LotTypeFields (lotTypeId, orderNumber, lotTypeField)").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotStatuses (" +
|
lotOccupancyDB.prepare("create table if not exists LotStatuses (" +
|
||||||
"lotStatusId integer not null primary key autoincrement," +
|
"lotStatusId integer not null primary key autoincrement," +
|
||||||
" lotStatus varchar(100) not null," +
|
" lotStatus varchar(100) not null," +
|
||||||
" orderNumber smallint not null default 0," +
|
" orderNumber smallint not null default 0," +
|
||||||
recordColumns +
|
recordColumns +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lotstatuses_ordernumber" +
|
lotOccupancyDB.prepare("create index if not exists idx_lotstatuses_ordernumber" +
|
||||||
" on LotStatuses (orderNumber, lotStatus)").run();
|
" on LotStatuses (orderNumber, lotStatus)").run();
|
||||||
|
|
||||||
// Maps and Lots
|
// Maps and Lots
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists Maps (" +
|
lotOccupancyDB.prepare("create table if not exists Maps (" +
|
||||||
"mapId integer not null primary key autoincrement," +
|
"mapId integer not null primary key autoincrement," +
|
||||||
" mapName varchar(200) not null," +
|
" mapName varchar(200) not null," +
|
||||||
" mapDescription text," +
|
" mapDescription text," +
|
||||||
|
|
||||||
" mapLatitude decimal(10, 8) check (mapLatitude between -90 and 90)," +
|
" mapLatitude decimal(10, 8) check (mapLatitude between -90 and 90)," +
|
||||||
" mapLongitude decimal(11, 8) check (mapLongitude between -180 and 180)," +
|
" mapLongitude decimal(11, 8) check (mapLongitude between -180 and 180)," +
|
||||||
|
|
||||||
" mapSVG varchar(50)," +
|
" mapSVG varchar(50)," +
|
||||||
|
|
||||||
" mapAddress1 varchar(50)," +
|
" mapAddress1 varchar(50)," +
|
||||||
" mapAddress2 varchar(50)," +
|
" mapAddress2 varchar(50)," +
|
||||||
" mapCity varchar(20)," +
|
" mapCity varchar(20)," +
|
||||||
" mapProvince varchar(2)," +
|
" mapProvince varchar(2)," +
|
||||||
" mapPostalCode varchar(7)," +
|
" mapPostalCode varchar(7)," +
|
||||||
" mapPhoneNumber varchar(30)," +
|
" mapPhoneNumber varchar(30)," +
|
||||||
|
|
||||||
recordColumns +
|
recordColumns +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists Lots (" +
|
lotOccupancyDB.prepare("create table if not exists Lots (" +
|
||||||
"lotId integer not null primary key autoincrement," +
|
"lotId integer not null primary key autoincrement," +
|
||||||
" lotTypeId integer not null," +
|
" lotTypeId integer not null," +
|
||||||
" lotName varchar(100)," +
|
" lotName varchar(100)," +
|
||||||
" mapId integer," +
|
" mapId integer," +
|
||||||
" mapKey varchar(100)," +
|
" mapKey varchar(100)," +
|
||||||
|
|
||||||
" lotLatitude decimal(10, 8) check (lotLatitude between -90 and 90)," +
|
" lotLatitude decimal(10, 8) check (lotLatitude between -90 and 90)," +
|
||||||
" lotLongitude decimal(11, 8) check (lotLongitude between -180 and 180)," +
|
" lotLongitude decimal(11, 8) check (lotLongitude between -180 and 180)," +
|
||||||
|
|
||||||
" lotStatusId integer," +
|
" lotStatusId integer," +
|
||||||
|
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" foreign key (lotTypeId) references LotTypes (lotTypeId)," +
|
" foreign key (lotTypeId) references LotTypes (lotTypeId)," +
|
||||||
" foreign key (mapId) references Maps (mapId)," +
|
" foreign key (mapId) references Maps (mapId)," +
|
||||||
" foreign key (lotStatusId) references LotStatuses (lotStatusId)" +
|
" foreign key (lotStatusId) references LotStatuses (lotStatusId)" +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotFields (" +
|
lotOccupancyDB.prepare("create table if not exists LotFields (" +
|
||||||
"lotId integer not null," +
|
"lotId integer not null," +
|
||||||
" lotTypeFieldId integer not null," +
|
" lotTypeFieldId integer not null," +
|
||||||
" lotFieldValue text not null," +
|
" lotFieldValue text not null," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" primary key (lotId, lotTypeFieldId)," +
|
" primary key (lotId, lotTypeFieldId)," +
|
||||||
" foreign key (lotId) references Lots (lotId)," +
|
" foreign key (lotId) references Lots (lotId)," +
|
||||||
" foreign key (lotTypeFieldId) references LotTypeFields (lotTypeFieldId)" +
|
" foreign key (lotTypeFieldId) references LotTypeFields (lotTypeFieldId)" +
|
||||||
") without rowid").run();
|
") without rowid").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotComments (" +
|
lotOccupancyDB.prepare("create table if not exists LotComments (" +
|
||||||
"lotCommentId integer not null primary key autoincrement," +
|
"lotCommentId integer not null primary key autoincrement," +
|
||||||
" lotId integer not null," +
|
" lotId integer not null," +
|
||||||
" lotCommentDate integer not null check (lotCommentDate > 0)," +
|
" lotCommentDate integer not null check (lotCommentDate > 0)," +
|
||||||
" lotCommentTime integer not null check (lotCommentTime >= 0)," +
|
" lotCommentTime integer not null check (lotCommentTime >= 0)," +
|
||||||
" lotComment text not null," +
|
" lotComment text not null," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" foreign key (lotId) references Lots (lotId)" +
|
" foreign key (lotId) references Lots (lotId)" +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lotcomments_datetime" +
|
lotOccupancyDB.prepare("create index if not exists idx_lotcomments_datetime" +
|
||||||
" on LotComments (lotId, lotCommentDate, lotCommentTime)").run();
|
" on LotComments (lotId, lotCommentDate, lotCommentTime)").run();
|
||||||
|
|
||||||
// Occupancies
|
// Occupancies
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists OccupancyTypes (" +
|
lotOccupancyDB.prepare("create table if not exists OccupancyTypes (" +
|
||||||
"occupancyTypeId integer not null primary key autoincrement," +
|
"occupancyTypeId integer not null primary key autoincrement," +
|
||||||
" occupancyType varchar(100) not null," +
|
" occupancyType varchar(100) not null," +
|
||||||
" orderNumber smallint not null default 0," +
|
" orderNumber smallint not null default 0," +
|
||||||
recordColumns +
|
recordColumns +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_occupancytypes_ordernumber" +
|
lotOccupancyDB.prepare("create index if not exists idx_occupancytypes_ordernumber" +
|
||||||
" on OccupancyTypes (orderNumber, occupancyType)").run();
|
" on OccupancyTypes (orderNumber, occupancyType)").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists OccupancyTypeFields (" +
|
lotOccupancyDB.prepare("create table if not exists OccupancyTypeFields (" +
|
||||||
"occupancyTypeFieldId integer not null primary key autoincrement," +
|
"occupancyTypeFieldId integer not null primary key autoincrement," +
|
||||||
" occupancyTypeId integer not null," +
|
" occupancyTypeId integer not null," +
|
||||||
" occupancyTypeField varchar(100) not null," +
|
" occupancyTypeField varchar(100) not null," +
|
||||||
" occupancyTypeFieldValues text," +
|
" occupancyTypeFieldValues text," +
|
||||||
" isRequired bit not null default 0," +
|
" isRequired bit not null default 0," +
|
||||||
" pattern varchar(100)," +
|
" pattern varchar(100)," +
|
||||||
" minimumLength smallint not null default 1 check (minimumLength >= 0)," +
|
" minimumLength smallint not null default 1 check (minimumLength >= 0)," +
|
||||||
" maximumLength smallint not null default 100 check (maximumLength >= 0)," +
|
" maximumLength smallint not null default 100 check (maximumLength >= 0)," +
|
||||||
" orderNumber smallint not null default 0," +
|
" orderNumber smallint not null default 0," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)" +
|
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)" +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_occupancytypefields_ordernumber" +
|
lotOccupancyDB.prepare("create index if not exists idx_occupancytypefields_ordernumber" +
|
||||||
" on OccupancyTypeFields (occupancyTypeId, orderNumber, occupancyTypeField)").run();
|
" on OccupancyTypeFields (occupancyTypeId, orderNumber, occupancyTypeField)").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupantTypes (" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupantTypes (" +
|
||||||
"lotOccupantTypeId integer not null primary key autoincrement," +
|
"lotOccupantTypeId integer not null primary key autoincrement," +
|
||||||
" lotOccupantType varchar(100) not null," +
|
" lotOccupantType varchar(100) not null," +
|
||||||
" orderNumber smallint not null default 0," +
|
" orderNumber smallint not null default 0," +
|
||||||
recordColumns +
|
recordColumns +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lotoccupanttypes_ordernumber" +
|
lotOccupancyDB.prepare("create index if not exists idx_lotoccupanttypes_ordernumber" +
|
||||||
" on LotOccupantTypes (orderNumber, lotOccupantType)").run();
|
" on LotOccupantTypes (orderNumber, lotOccupantType)").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupancies (" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupancies (" +
|
||||||
"lotOccupancyId integer not null primary key autoincrement," +
|
"lotOccupancyId integer not null primary key autoincrement," +
|
||||||
" occupancyTypeId integer not null," +
|
" occupancyTypeId integer not null," +
|
||||||
" lotId integer," +
|
" lotId integer," +
|
||||||
" occupancyStartDate integer not null check (occupancyStartDate > 0)," +
|
" occupancyStartDate integer not null check (occupancyStartDate > 0)," +
|
||||||
" occupancyEndDate integer check (occupancyEndDate > 0)," +
|
" occupancyEndDate integer check (occupancyEndDate > 0)," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" foreign key (lotId) references Lots (lotId)," +
|
" foreign key (lotId) references Lots (lotId)," +
|
||||||
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)" +
|
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)" +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupancyOccupants (" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupancyOccupants (" +
|
||||||
"lotOccupancyId integer not null," +
|
"lotOccupancyId integer not null," +
|
||||||
" lotOccupantIndex integer not null," +
|
" lotOccupantIndex integer not null," +
|
||||||
" occupantName varchar(200) not null," +
|
" occupantName varchar(200) not null," +
|
||||||
" occupantAddress1 varchar(50)," +
|
" occupantAddress1 varchar(50)," +
|
||||||
" occupantAddress2 varchar(50)," +
|
" occupantAddress2 varchar(50)," +
|
||||||
" occupantCity varchar(20)," +
|
" occupantCity varchar(20)," +
|
||||||
" occupantProvince varchar(2)," +
|
" occupantProvince varchar(2)," +
|
||||||
" occupantPostalCode varchar(7)," +
|
" occupantPostalCode varchar(7)," +
|
||||||
" occupantPhoneNumber varchar(30)," +
|
" occupantPhoneNumber varchar(30)," +
|
||||||
" lotOccupantTypeId integer not null," +
|
" lotOccupantTypeId integer not null," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" primary key (lotOccupancyId, lotOccupantIndex)," +
|
" primary key (lotOccupancyId, lotOccupantIndex)," +
|
||||||
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
||||||
" foreign key (lotOccupantTypeId) references LotOccupantTypes (lotOccupantTypeId)" +
|
" foreign key (lotOccupantTypeId) references LotOccupantTypes (lotOccupantTypeId)" +
|
||||||
") without rowid").run();
|
") without rowid").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupancyFields (" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupancyFields (" +
|
||||||
"lotOccupancyId integer not null," +
|
"lotOccupancyId integer not null," +
|
||||||
" occupancyTypeFieldId integer not null," +
|
" occupancyTypeFieldId integer not null," +
|
||||||
" lotOccupancyFieldValue text not null," +
|
" lotOccupancyFieldValue text not null," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" primary key (lotOccupancyId, occupancyTypeFieldId)," +
|
" primary key (lotOccupancyId, occupancyTypeFieldId)," +
|
||||||
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
||||||
" foreign key (occupancyTypeFieldId) references OccupancyTypeFields (occupancyTypeFieldId)" +
|
" foreign key (occupancyTypeFieldId) references OccupancyTypeFields (occupancyTypeFieldId)" +
|
||||||
") without rowid").run();
|
") without rowid").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupancyComments (" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupancyComments (" +
|
||||||
"lotOccupancyCommentId integer not null primary key autoincrement," +
|
"lotOccupancyCommentId integer not null primary key autoincrement," +
|
||||||
" lotOccupancyId integer not null," +
|
" lotOccupancyId integer not null," +
|
||||||
" lotOccupancyCommentDate integer not null check (lotOccupancyCommentDate > 0)," +
|
" lotOccupancyCommentDate integer not null check (lotOccupancyCommentDate > 0)," +
|
||||||
" lotOccupancyCommentTime integer not null check (lotOccupancyCommentTime >= 0)," +
|
" lotOccupancyCommentTime integer not null check (lotOccupancyCommentTime >= 0)," +
|
||||||
" lotOccupancyComment text not null," +
|
" lotOccupancyComment text not null," +
|
||||||
recordColumns + "," +
|
recordColumns + "," +
|
||||||
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)" +
|
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)" +
|
||||||
")").run();
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lotoccupancycomments_datetime" +
|
lotOccupancyDB.prepare("create index if not exists idx_lotoccupancycomments_datetime" +
|
||||||
" on LotOccupancyComments (lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime)").run();
|
" on LotOccupancyComments (lotOccupancyId, lotOccupancyCommentDate, lotOccupancyCommentTime)").run();
|
||||||
|
|
||||||
// Occupancy Fees and Transactions
|
// Occupancy Fees and Transactions
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists Fees (" +
|
lotOccupancyDB.prepare("create table if not exists FeeCategories (" +
|
||||||
"feeId integer not null primary key autoincrement," +
|
"feeCategoryId integer not null primary key autoincrement," +
|
||||||
" feeName varchar(100) not null," +
|
" feeCategory varchar(100) not null," +
|
||||||
" occupancyTypeId integer," +
|
" orderNumber smallint not null default 0," +
|
||||||
" lotTypeId integer," +
|
recordColumns +
|
||||||
" feeAmount decimal(6, 2)," +
|
")").run();
|
||||||
" feeFunction varchar(100)," +
|
|
||||||
" isRequired bit not null default 0," +
|
|
||||||
" orderNumber smallint not null default 0," +
|
|
||||||
recordColumns + "," +
|
|
||||||
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)," +
|
|
||||||
" foreign key (lotTypeId) references LotTypes (lotTypeId)" +
|
|
||||||
")").run();
|
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_fees_ordernumber" +
|
lotOccupancyDB.prepare("create table if not exists Fees (" +
|
||||||
" on Fees (orderNumber, feeName)").run();
|
"feeId integer not null primary key autoincrement," +
|
||||||
|
" feeCategoryId integer not null," +
|
||||||
|
" feeName varchar(100) not null," +
|
||||||
|
" feeDescription text," +
|
||||||
|
" occupancyTypeId integer," +
|
||||||
|
" lotTypeId integer," +
|
||||||
|
" includeQuantity boolean not null default 0," +
|
||||||
|
" quantityUnit varchar(30)," +
|
||||||
|
" feeAmount decimal(6, 2)," +
|
||||||
|
" feeFunction varchar(100)," +
|
||||||
|
" taxAmount decimal(6, 2)," +
|
||||||
|
" taxPercentage decimal(5, 2)," +
|
||||||
|
" isRequired bit not null default 0," +
|
||||||
|
" orderNumber smallint not null default 0," +
|
||||||
|
recordColumns + "," +
|
||||||
|
" foreign key (feeCategoryId) references FeeCategories (feeCategoryId)," +
|
||||||
|
" foreign key (occupancyTypeId) references OccupancyTypes (occupancyTypeId)," +
|
||||||
|
" foreign key (lotTypeId) references LotTypes (lotTypeId)" +
|
||||||
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupancyFees (" +
|
lotOccupancyDB.prepare("create index if not exists idx_fees_ordernumber" +
|
||||||
"lotOccupancyId integer not null," +
|
" on Fees (orderNumber, feeName)").run();
|
||||||
" feeId integer not null," +
|
|
||||||
" feeAmount decimal(6, 2) not null," +
|
|
||||||
recordColumns + "," +
|
|
||||||
" primary key (lotOccupancyId, feeId)," +
|
|
||||||
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
|
||||||
" foreign key (feeId) references Fees (feeId)" +
|
|
||||||
") without rowid").run();
|
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists LotOccupancyTransactions (" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupancyFees (" +
|
||||||
"lotOccupancyId integer not null," +
|
"lotOccupancyId integer not null," +
|
||||||
" transactionIndex integer not null," +
|
" feeId integer not null," +
|
||||||
" transactionDate integer not null check (transactionDate > 0)," +
|
" quantity decimal(4, 1) not null default 1," +
|
||||||
" transactionTime integer not null check (transactionTime >= 0)," +
|
" feeAmount decimal(6, 2) not null," +
|
||||||
" transactionAmount decimal(6, 2) not null," +
|
" taxAmount decmial(6, 2) not null," +
|
||||||
" externalReceiptNumber varchar(100)," +
|
recordColumns + "," +
|
||||||
" transactionNote text," +
|
" primary key (lotOccupancyId, feeId)," +
|
||||||
recordColumns + "," +
|
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)," +
|
||||||
" primary key (lotOccupancyId, transactionIndex)," +
|
" foreign key (feeId) references Fees (feeId)" +
|
||||||
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)" +
|
") without rowid").run();
|
||||||
") without rowid").run();
|
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_lotoccupancytransactions_ordernumber" +
|
lotOccupancyDB.prepare("create table if not exists LotOccupancyTransactions (" +
|
||||||
" on LotOccupancyTransactions (lotOccupancyId, transactionDate, transactionTime)").run();
|
"lotOccupancyId integer not null," +
|
||||||
|
" transactionIndex integer not null," +
|
||||||
|
" transactionDate integer not null check (transactionDate > 0)," +
|
||||||
|
" transactionTime integer not null check (transactionTime >= 0)," +
|
||||||
|
" transactionAmount decimal(6, 2) not null," +
|
||||||
|
" externalReceiptNumber varchar(100)," +
|
||||||
|
" transactionNote text," +
|
||||||
|
recordColumns + "," +
|
||||||
|
" primary key (lotOccupancyId, transactionIndex)," +
|
||||||
|
" foreign key (lotOccupancyId) references LotOccupancies (lotOccupancyId)" +
|
||||||
|
") without rowid").run();
|
||||||
|
|
||||||
// Work Orders
|
lotOccupancyDB.prepare("create index if not exists idx_lotoccupancytransactions_ordernumber" +
|
||||||
|
" on LotOccupancyTransactions (lotOccupancyId, transactionDate, transactionTime)").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists WorkOrderTypes (" +
|
// Work Orders
|
||||||
"workOrderTypeId integer not null primary key autoincrement," +
|
|
||||||
" workOrderType varchar(100) not null," +
|
|
||||||
" orderNumber smallint not null default 0," +
|
|
||||||
recordColumns +
|
|
||||||
")").run();
|
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_workordertypes_ordernumber" +
|
lotOccupancyDB.prepare("create table if not exists WorkOrderTypes (" +
|
||||||
" on WorkOrderTypes (orderNumber, workOrderType)").run();
|
"workOrderTypeId integer not null primary key autoincrement," +
|
||||||
|
" workOrderType varchar(100) not null," +
|
||||||
|
" orderNumber smallint not null default 0," +
|
||||||
|
recordColumns +
|
||||||
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists WorkOrders (" +
|
lotOccupancyDB.prepare("create index if not exists idx_workordertypes_ordernumber" +
|
||||||
"workOrderId integer not null primary key autoincrement," +
|
" on WorkOrderTypes (orderNumber, workOrderType)").run();
|
||||||
" workOrderTypeId integer not null," +
|
|
||||||
" workOrderNumber varchar(50) not null," +
|
|
||||||
" workOrderDescription text," +
|
|
||||||
" workOrderOpenDate integer check (workOrderOpenDate > 0)," +
|
|
||||||
" workOrderCloseDate integer check (workOrderCloseDate > 0)," +
|
|
||||||
recordColumns + "," +
|
|
||||||
" foreign key (workOrderTypeId) references WorkOrderTypes (workOrderTypeId)" +
|
|
||||||
")").run();
|
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists WorkOrderLots (" +
|
lotOccupancyDB.prepare("create table if not exists WorkOrders (" +
|
||||||
"workOrderId integer not null," +
|
"workOrderId integer not null primary key autoincrement," +
|
||||||
" lotId integer not null," +
|
" workOrderTypeId integer not null," +
|
||||||
recordColumns + "," +
|
" workOrderNumber varchar(50) not null," +
|
||||||
" primary key (workOrderId, lotId)," +
|
" workOrderDescription text," +
|
||||||
" foreign key (workOrderId) references WorkOrders (workOrderId)," +
|
" workOrderOpenDate integer check (workOrderOpenDate > 0)," +
|
||||||
" foreign key (lotId) references Lots (lotId)" +
|
" workOrderCloseDate integer check (workOrderCloseDate > 0)," +
|
||||||
") without rowid").run();
|
recordColumns + "," +
|
||||||
|
" foreign key (workOrderTypeId) references WorkOrderTypes (workOrderTypeId)" +
|
||||||
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create table if not exists WorkOrderComments (" +
|
lotOccupancyDB.prepare("create table if not exists WorkOrderLots (" +
|
||||||
"workOrderCommentId integer not null primary key autoincrement," +
|
"workOrderId integer not null," +
|
||||||
" workOrderId integer not null," +
|
" lotId integer not null," +
|
||||||
" workOrderCommentDate integer not null check (workOrderCommentDate > 0)," +
|
recordColumns + "," +
|
||||||
" workOrderCommentTime integer not null check (workOrderCommentTime >= 0)," +
|
" primary key (workOrderId, lotId)," +
|
||||||
" workOrderComment text not null," +
|
" foreign key (workOrderId) references WorkOrders (workOrderId)," +
|
||||||
recordColumns + "," +
|
" foreign key (lotId) references Lots (lotId)" +
|
||||||
" foreign key (workOrderId) references WorkOrders (workOrderId)" +
|
") without rowid").run();
|
||||||
")").run();
|
|
||||||
|
|
||||||
lotOccupancyDB.prepare("create index if not exists idx_workordercomments_datetime" +
|
lotOccupancyDB.prepare("create table if not exists WorkOrderComments (" +
|
||||||
" on WorkOrderComments (workOrderId, workOrderCommentDate, workOrderCommentTime)").run();
|
"workOrderCommentId integer not null primary key autoincrement," +
|
||||||
|
" workOrderId integer not null," +
|
||||||
|
" workOrderCommentDate integer not null check (workOrderCommentDate > 0)," +
|
||||||
|
" workOrderCommentTime integer not null check (workOrderCommentTime >= 0)," +
|
||||||
|
" workOrderComment text not null," +
|
||||||
|
recordColumns + "," +
|
||||||
|
" foreign key (workOrderId) references WorkOrders (workOrderId)" +
|
||||||
|
")").run();
|
||||||
|
|
||||||
lotOccupancyDB.close();
|
lotOccupancyDB.prepare("create index if not exists idx_workordercomments_datetime" +
|
||||||
|
" on WorkOrderComments (workOrderId, workOrderCommentDate, workOrderCommentTime)").run();
|
||||||
|
|
||||||
return true;
|
lotOccupancyDB.close();
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return true;
|
||||||
};
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
interface AddFeeCategoryForm {
|
||||||
|
feeCategory: string;
|
||||||
|
orderNumber?: number;
|
||||||
|
}
|
||||||
|
export declare const addFeeCategory: (feeCategoryForm: AddFeeCategoryForm, requestSession: recordTypes.PartialSession) => number;
|
||||||
|
export default addFeeCategory;
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
export const addFeeCategory = (feeCategoryForm, requestSession) => {
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
const result = database
|
||||||
|
.prepare("insert into FeeCategories (" +
|
||||||
|
"feeCategory, orderNumber," +
|
||||||
|
" recordCreate_userName, recordCreate_timeMillis," +
|
||||||
|
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
||||||
|
" values (?, ?, ?, ?, ?, ?)")
|
||||||
|
.run(feeCategoryForm.feeCategory, (feeCategoryForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
|
database.close();
|
||||||
|
return result.lastInsertRowid;
|
||||||
|
};
|
||||||
|
export default addFeeCategory;
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
|
||||||
|
interface AddFeeCategoryForm {
|
||||||
|
feeCategory: string;
|
||||||
|
orderNumber?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const addFeeCategory =
|
||||||
|
(feeCategoryForm: AddFeeCategoryForm, requestSession: recordTypes.PartialSession): number => {
|
||||||
|
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
|
||||||
|
const result = database
|
||||||
|
.prepare("insert into FeeCategories (" +
|
||||||
|
"feeCategory, orderNumber," +
|
||||||
|
" recordCreate_userName, recordCreate_timeMillis," +
|
||||||
|
" recordUpdate_userName, recordUpdate_timeMillis)" +
|
||||||
|
" values (?, ?, ?, ?, ?, ?)")
|
||||||
|
.run(feeCategoryForm.feeCategory,
|
||||||
|
(feeCategoryForm.orderNumber || 0),
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis,
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis);
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
|
||||||
|
return result.lastInsertRowid as number;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default addFeeCategory;
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
import { clearLotOccupantTypesCache } from "../functions.cache.js";
|
||||||
export const addLotOccupantType = (lotOccupantTypeForm, requestSession) => {
|
export const addLotOccupantType = (lotOccupantTypeForm, requestSession) => {
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -11,6 +12,7 @@ export const addLotOccupantType = (lotOccupantTypeForm, requestSession) => {
|
||||||
" values (?, ?, ?, ?, ?, ?)")
|
" values (?, ?, ?, ?, ?, ?)")
|
||||||
.run(lotOccupantTypeForm.lotOccupantType, (lotOccupantTypeForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
.run(lotOccupantTypeForm.lotOccupantType, (lotOccupantTypeForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
database.close();
|
database.close();
|
||||||
|
clearLotOccupantTypesCache();
|
||||||
return result.lastInsertRowid;
|
return result.lastInsertRowid;
|
||||||
};
|
};
|
||||||
export default addLotOccupantType;
|
export default addLotOccupantType;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
} from "../../data/databasePaths.js";
|
} from "../../data/databasePaths.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../../types/recordTypes";
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
import { clearLotOccupantTypesCache } from "../functions.cache.js";
|
||||||
|
|
||||||
|
|
||||||
interface AddLotOccupantTypeForm {
|
interface AddLotOccupantTypeForm {
|
||||||
|
|
@ -35,6 +36,8 @@ export const addLotOccupantType =
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
|
clearLotOccupantTypesCache();
|
||||||
|
|
||||||
return result.lastInsertRowid as number;
|
return result.lastInsertRowid as number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
import { clearLotStatusesCache } from "../functions.cache.js";
|
||||||
export const addLotStatus = (lotStatusForm, requestSession) => {
|
export const addLotStatus = (lotStatusForm, requestSession) => {
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -11,6 +12,7 @@ export const addLotStatus = (lotStatusForm, requestSession) => {
|
||||||
" values (?, ?, ?, ?, ?, ?)")
|
" values (?, ?, ?, ?, ?, ?)")
|
||||||
.run(lotStatusForm.lotStatus, (lotStatusForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
.run(lotStatusForm.lotStatus, (lotStatusForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
database.close();
|
database.close();
|
||||||
|
clearLotStatusesCache();
|
||||||
return result.lastInsertRowid;
|
return result.lastInsertRowid;
|
||||||
};
|
};
|
||||||
export default addLotStatus;
|
export default addLotStatus;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
} from "../../data/databasePaths.js";
|
} from "../../data/databasePaths.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../../types/recordTypes";
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
import { clearLotStatusesCache } from "../functions.cache.js";
|
||||||
|
|
||||||
|
|
||||||
interface AddLotStatusForm {
|
interface AddLotStatusForm {
|
||||||
|
|
@ -35,6 +36,8 @@ export const addLotStatus =
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
|
clearLotStatusesCache();
|
||||||
|
|
||||||
return result.lastInsertRowid as number;
|
return result.lastInsertRowid as number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
import { clearLotTypesCache } from "../functions.cache.js";
|
||||||
export const addLotType = (lotTypeForm, requestSession) => {
|
export const addLotType = (lotTypeForm, requestSession) => {
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -11,6 +12,7 @@ export const addLotType = (lotTypeForm, requestSession) => {
|
||||||
" values (?, ?, ?, ?, ?, ?)")
|
" values (?, ?, ?, ?, ?, ?)")
|
||||||
.run(lotTypeForm.lotType, (lotTypeForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
.run(lotTypeForm.lotType, (lotTypeForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
database.close();
|
database.close();
|
||||||
|
clearLotTypesCache();
|
||||||
return result.lastInsertRowid;
|
return result.lastInsertRowid;
|
||||||
};
|
};
|
||||||
export default addLotType;
|
export default addLotType;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
} from "../../data/databasePaths.js";
|
} from "../../data/databasePaths.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../../types/recordTypes";
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
import { clearLotTypesCache } from "../functions.cache.js";
|
||||||
|
|
||||||
|
|
||||||
interface AddLotTypeForm {
|
interface AddLotTypeForm {
|
||||||
|
|
@ -35,6 +36,8 @@ export const addLotType =
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
|
clearLotTypesCache();
|
||||||
|
|
||||||
return result.lastInsertRowid as number;
|
return result.lastInsertRowid as number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
import { clearOccupancyTypesCache } from "../functions.cache.js";
|
||||||
export const addOccupancyType = (occupancyTypeForm, requestSession) => {
|
export const addOccupancyType = (occupancyTypeForm, requestSession) => {
|
||||||
const database = sqlite(databasePath);
|
const database = sqlite(databasePath);
|
||||||
const rightNowMillis = Date.now();
|
const rightNowMillis = Date.now();
|
||||||
|
|
@ -11,6 +12,7 @@ export const addOccupancyType = (occupancyTypeForm, requestSession) => {
|
||||||
" values (?, ?, ?, ?, ?, ?)")
|
" values (?, ?, ?, ?, ?, ?)")
|
||||||
.run(occupancyTypeForm.occupancyType, (occupancyTypeForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
.run(occupancyTypeForm.occupancyType, (occupancyTypeForm.orderNumber || 0), requestSession.user.userName, rightNowMillis, requestSession.user.userName, rightNowMillis);
|
||||||
database.close();
|
database.close();
|
||||||
|
clearOccupancyTypesCache();
|
||||||
return result.lastInsertRowid;
|
return result.lastInsertRowid;
|
||||||
};
|
};
|
||||||
export default addOccupancyType;
|
export default addOccupancyType;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import {
|
||||||
} from "../../data/databasePaths.js";
|
} from "../../data/databasePaths.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../../types/recordTypes";
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
import { clearOccupancyTypesCache } from "../functions.cache.js";
|
||||||
|
|
||||||
|
|
||||||
interface AddOccupancyTypeForm {
|
interface AddOccupancyTypeForm {
|
||||||
|
|
@ -35,6 +36,8 @@ export const addOccupancyType =
|
||||||
|
|
||||||
database.close();
|
database.close();
|
||||||
|
|
||||||
|
clearOccupancyTypesCache();
|
||||||
|
|
||||||
return result.lastInsertRowid as number;
|
return result.lastInsertRowid as number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
interface GetFeeCategoriesFilters {
|
||||||
|
occupancyTypeId?: number | string;
|
||||||
|
lotTypeId?: number | string;
|
||||||
|
}
|
||||||
|
interface GetFeeCategoriesOptions {
|
||||||
|
includeFees?: boolean;
|
||||||
|
}
|
||||||
|
export declare const getFeeCategories: (filters?: GetFeeCategoriesFilters, options?: GetFeeCategoriesOptions) => recordTypes.FeeCategory[];
|
||||||
|
export default getFeeCategories;
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
export const getFeeCategories = (filters, options) => {
|
||||||
|
const database = sqlite(databasePath, {
|
||||||
|
readonly: true
|
||||||
|
});
|
||||||
|
let sql = "select feeCategoryId, feeCategory" +
|
||||||
|
" from FeeCategories" +
|
||||||
|
" where recordDelete_timeMillis is null";
|
||||||
|
let sqlParameters = [];
|
||||||
|
if (filters.occupancyTypeId) {
|
||||||
|
sql += " and feeCategoryId in (" +
|
||||||
|
"select feeCategoryId from Fees" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and (occupancyTypeId is null or occupancyTypeId = ?))";
|
||||||
|
sqlParameters.push(filters.occupancyTypeId);
|
||||||
|
}
|
||||||
|
if (filters.lotTypeId) {
|
||||||
|
sql += " and feeCategoryId in (" +
|
||||||
|
"select feeCategoryId from Fees" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and (lotTypeId is null or lotTypeId = ?))";
|
||||||
|
sqlParameters.push(filters.lotTypeId);
|
||||||
|
}
|
||||||
|
const feeCategories = database.prepare(sql +
|
||||||
|
" order by orderNumber, feeCategory")
|
||||||
|
.all(sqlParameters);
|
||||||
|
if (options.includeFees) {
|
||||||
|
sql = "select feeId, feeName, feeDescription," +
|
||||||
|
" occupancyTypeId, lotTypeId," +
|
||||||
|
" feeAmount, feeFunction, taxAmount, taxPercentage," +
|
||||||
|
" isRequired" +
|
||||||
|
" from Fees" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and feeCategoryId = ?";
|
||||||
|
sqlParameters = [];
|
||||||
|
for (const feeCategory of feeCategories) {
|
||||||
|
sqlParameters.push(feeCategory.feeCategoryId);
|
||||||
|
if (filters.occupancyTypeId) {
|
||||||
|
sql += " and (occupancyTypeId is null or occupancyTypeId = ?)";
|
||||||
|
sqlParameters.push(filters.occupancyTypeId);
|
||||||
|
}
|
||||||
|
if (filters.lotTypeId) {
|
||||||
|
sql += " and (lotTypeId is null or lotTypeId = ?)";
|
||||||
|
sqlParameters.push(filters.lotTypeId);
|
||||||
|
}
|
||||||
|
feeCategory.fees = database.prepare(sql +
|
||||||
|
" order by orderNumber, feeName")
|
||||||
|
.all(sqlParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
database.close();
|
||||||
|
return feeCategories;
|
||||||
|
};
|
||||||
|
export default getFeeCategories;
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
|
import {
|
||||||
|
lotOccupancyDB as databasePath
|
||||||
|
} from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
|
||||||
|
interface GetFeeCategoriesFilters {
|
||||||
|
occupancyTypeId ? : number | string;
|
||||||
|
lotTypeId ? : number | string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GetFeeCategoriesOptions {
|
||||||
|
includeFees ? : boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const getFeeCategories = (filters ? : GetFeeCategoriesFilters, options ? : GetFeeCategoriesOptions): recordTypes.FeeCategory[] => {
|
||||||
|
|
||||||
|
const database = sqlite(databasePath, {
|
||||||
|
readonly: true
|
||||||
|
});
|
||||||
|
|
||||||
|
let sql = "select feeCategoryId, feeCategory" +
|
||||||
|
" from FeeCategories" +
|
||||||
|
" where recordDelete_timeMillis is null";
|
||||||
|
|
||||||
|
let sqlParameters = [];
|
||||||
|
|
||||||
|
if (filters.occupancyTypeId) {
|
||||||
|
sql += " and feeCategoryId in (" +
|
||||||
|
"select feeCategoryId from Fees" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and (occupancyTypeId is null or occupancyTypeId = ?))";
|
||||||
|
|
||||||
|
sqlParameters.push(filters.occupancyTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.lotTypeId) {
|
||||||
|
sql += " and feeCategoryId in (" +
|
||||||
|
"select feeCategoryId from Fees" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and (lotTypeId is null or lotTypeId = ?))";
|
||||||
|
|
||||||
|
sqlParameters.push(filters.lotTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const feeCategories: recordTypes.FeeCategory[] = database.prepare(sql +
|
||||||
|
" order by orderNumber, feeCategory")
|
||||||
|
.all(sqlParameters);
|
||||||
|
|
||||||
|
if (options.includeFees) {
|
||||||
|
|
||||||
|
sql = "select feeId, feeName, feeDescription," +
|
||||||
|
" occupancyTypeId, lotTypeId," +
|
||||||
|
" feeAmount, feeFunction, taxAmount, taxPercentage," +
|
||||||
|
" isRequired" +
|
||||||
|
" from Fees" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and feeCategoryId = ?";
|
||||||
|
|
||||||
|
sqlParameters = [];
|
||||||
|
|
||||||
|
for (const feeCategory of feeCategories) {
|
||||||
|
|
||||||
|
sqlParameters.push(feeCategory.feeCategoryId);
|
||||||
|
|
||||||
|
if (filters.occupancyTypeId) {
|
||||||
|
sql += " and (occupancyTypeId is null or occupancyTypeId = ?)";
|
||||||
|
|
||||||
|
sqlParameters.push(filters.occupancyTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filters.lotTypeId) {
|
||||||
|
sql += " and (lotTypeId is null or lotTypeId = ?)";
|
||||||
|
|
||||||
|
sqlParameters.push(filters.lotTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
feeCategory.fees = database.prepare(sql +
|
||||||
|
" order by orderNumber, feeName")
|
||||||
|
.all(sqlParameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
|
||||||
|
return feeCategories;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default getFeeCategories;
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { dateToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js";
|
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
import { dateToInteger } from "@cityssm/expressjs-server-js/dateTimeFns.js";
|
||||||
export const getLots = (filters, options) => {
|
export const getLots = (filters, options) => {
|
||||||
const database = sqlite(databasePath, {
|
const database = sqlite(databasePath, {
|
||||||
readonly: true
|
readonly: true
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,13 @@
|
||||||
import {
|
|
||||||
dateToInteger
|
|
||||||
} from "@cityssm/expressjs-server-js/dateTimeFns.js";
|
|
||||||
import sqlite from "better-sqlite3";
|
import sqlite from "better-sqlite3";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
lotOccupancyDB as databasePath
|
lotOccupancyDB as databasePath
|
||||||
} from "../../data/databasePaths.js";
|
} from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import {
|
||||||
|
dateToInteger
|
||||||
|
} from "@cityssm/expressjs-server-js/dateTimeFns.js";
|
||||||
|
|
||||||
import type * as recordTypes from "../../types/recordTypes";
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
interface UpdateFeeCategoryForm {
|
||||||
|
feeCategoryId: number | string;
|
||||||
|
feeCategory: string;
|
||||||
|
}
|
||||||
|
export declare const updateFeeCategory: (feeCategoryForm: UpdateFeeCategoryForm, requestSession: recordTypes.PartialSession) => boolean;
|
||||||
|
export default updateFeeCategory;
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
export const updateFeeCategory = (feeCategoryForm, requestSession) => {
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
const result = database
|
||||||
|
.prepare("update FeeCategories" +
|
||||||
|
" set feeCategory = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and feeCategoryId = ?")
|
||||||
|
.run(feeCategoryForm.feeCategory, requestSession.user.userName, rightNowMillis, feeCategoryForm.feeCategoryId);
|
||||||
|
database.close();
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
export default updateFeeCategory;
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import sqlite from "better-sqlite3";
|
||||||
|
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
|
||||||
|
|
||||||
|
import type * as recordTypes from "../../types/recordTypes";
|
||||||
|
|
||||||
|
|
||||||
|
interface UpdateFeeCategoryForm {
|
||||||
|
feeCategoryId: number | string;
|
||||||
|
feeCategory: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export const updateFeeCategory =
|
||||||
|
(feeCategoryForm: UpdateFeeCategoryForm, requestSession: recordTypes.PartialSession): boolean => {
|
||||||
|
|
||||||
|
const database = sqlite(databasePath);
|
||||||
|
|
||||||
|
const rightNowMillis = Date.now();
|
||||||
|
|
||||||
|
const result = database
|
||||||
|
.prepare("update FeeCategories" +
|
||||||
|
" set feeCategory = ?," +
|
||||||
|
" recordUpdate_userName = ?," +
|
||||||
|
" recordUpdate_timeMillis = ?" +
|
||||||
|
" where recordDelete_timeMillis is null" +
|
||||||
|
" and feeCategoryId = ?")
|
||||||
|
.run(feeCategoryForm.feeCategory,
|
||||||
|
requestSession.user.userName,
|
||||||
|
rightNowMillis,
|
||||||
|
feeCategoryForm.feeCategoryId);
|
||||||
|
|
||||||
|
database.close();
|
||||||
|
|
||||||
|
return result.changes > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
export default updateFeeCategory;
|
||||||
|
|
@ -53,8 +53,8 @@
|
||||||
"@types/node-windows": "^0.1.2",
|
"@types/node-windows": "^0.1.2",
|
||||||
"@types/papaparse": "^5.3.3",
|
"@types/papaparse": "^5.3.3",
|
||||||
"@types/session-file-store": "^1.2.2",
|
"@types/session-file-store": "^1.2.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
"@typescript-eslint/eslint-plugin": "^5.33.1",
|
||||||
"@typescript-eslint/parser": "^5.33.0",
|
"@typescript-eslint/parser": "^5.33.1",
|
||||||
"bulma": "^0.9.4",
|
"bulma": "^0.9.4",
|
||||||
"eslint": "^8.22.0",
|
"eslint": "^8.22.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
|
|
@ -1147,14 +1147,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz",
|
||||||
"integrity": "sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==",
|
"integrity": "sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "5.33.0",
|
"@typescript-eslint/scope-manager": "5.33.1",
|
||||||
"@typescript-eslint/type-utils": "5.33.0",
|
"@typescript-eslint/type-utils": "5.33.1",
|
||||||
"@typescript-eslint/utils": "5.33.0",
|
"@typescript-eslint/utils": "5.33.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
|
|
@ -1180,14 +1180,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/parser": {
|
"node_modules/@typescript-eslint/parser": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.1.tgz",
|
||||||
"integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==",
|
"integrity": "sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/scope-manager": "5.33.0",
|
"@typescript-eslint/scope-manager": "5.33.1",
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/typescript-estree": "5.33.0",
|
"@typescript-eslint/typescript-estree": "5.33.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -1207,13 +1207,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/scope-manager": {
|
"node_modules/@typescript-eslint/scope-manager": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz",
|
||||||
"integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==",
|
"integrity": "sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/visitor-keys": "5.33.0"
|
"@typescript-eslint/visitor-keys": "5.33.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
|
|
@ -1224,12 +1224,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/type-utils": {
|
"node_modules/@typescript-eslint/type-utils": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz",
|
||||||
"integrity": "sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==",
|
"integrity": "sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/utils": "5.33.0",
|
"@typescript-eslint/utils": "5.33.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"tsutils": "^3.21.0"
|
"tsutils": "^3.21.0"
|
||||||
},
|
},
|
||||||
|
|
@ -1250,9 +1250,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/types": {
|
"node_modules/@typescript-eslint/types": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.1.tgz",
|
||||||
"integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==",
|
"integrity": "sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
|
|
@ -1263,13 +1263,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/typescript-estree": {
|
"node_modules/@typescript-eslint/typescript-estree": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz",
|
||||||
"integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==",
|
"integrity": "sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/visitor-keys": "5.33.0",
|
"@typescript-eslint/visitor-keys": "5.33.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"globby": "^11.1.0",
|
"globby": "^11.1.0",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
|
|
@ -1290,15 +1290,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/utils": {
|
"node_modules/@typescript-eslint/utils": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.1.tgz",
|
||||||
"integrity": "sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==",
|
"integrity": "sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/json-schema": "^7.0.9",
|
"@types/json-schema": "^7.0.9",
|
||||||
"@typescript-eslint/scope-manager": "5.33.0",
|
"@typescript-eslint/scope-manager": "5.33.1",
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/typescript-estree": "5.33.0",
|
"@typescript-eslint/typescript-estree": "5.33.1",
|
||||||
"eslint-scope": "^5.1.1",
|
"eslint-scope": "^5.1.1",
|
||||||
"eslint-utils": "^3.0.0"
|
"eslint-utils": "^3.0.0"
|
||||||
},
|
},
|
||||||
|
|
@ -1314,12 +1314,12 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@typescript-eslint/visitor-keys": {
|
"node_modules/@typescript-eslint/visitor-keys": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz",
|
||||||
"integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==",
|
"integrity": "sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"eslint-visitor-keys": "^3.3.0"
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -11632,14 +11632,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/eslint-plugin": {
|
"@typescript-eslint/eslint-plugin": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz",
|
||||||
"integrity": "sha512-jHvZNSW2WZ31OPJ3enhLrEKvAZNyAFWZ6rx9tUwaessTc4sx9KmgMNhVcqVAl1ETnT5rU5fpXTLmY9YvC1DCNg==",
|
"integrity": "sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/scope-manager": "5.33.0",
|
"@typescript-eslint/scope-manager": "5.33.1",
|
||||||
"@typescript-eslint/type-utils": "5.33.0",
|
"@typescript-eslint/type-utils": "5.33.1",
|
||||||
"@typescript-eslint/utils": "5.33.0",
|
"@typescript-eslint/utils": "5.33.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"functional-red-black-tree": "^1.0.1",
|
"functional-red-black-tree": "^1.0.1",
|
||||||
"ignore": "^5.2.0",
|
"ignore": "^5.2.0",
|
||||||
|
|
@ -11649,52 +11649,52 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/parser": {
|
"@typescript-eslint/parser": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.1.tgz",
|
||||||
"integrity": "sha512-cgM5cJrWmrDV2KpvlcSkelTBASAs1mgqq+IUGKJvFxWrapHpaRy5EXPQz9YaKF3nZ8KY18ILTiVpUtbIac86/w==",
|
"integrity": "sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/scope-manager": "5.33.0",
|
"@typescript-eslint/scope-manager": "5.33.1",
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/typescript-estree": "5.33.0",
|
"@typescript-eslint/typescript-estree": "5.33.1",
|
||||||
"debug": "^4.3.4"
|
"debug": "^4.3.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/scope-manager": {
|
"@typescript-eslint/scope-manager": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz",
|
||||||
"integrity": "sha512-/Jta8yMNpXYpRDl8EwF/M8It2A9sFJTubDo0ATZefGXmOqlaBffEw0ZbkbQ7TNDK6q55NPHFshGBPAZvZkE8Pw==",
|
"integrity": "sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/visitor-keys": "5.33.0"
|
"@typescript-eslint/visitor-keys": "5.33.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/type-utils": {
|
"@typescript-eslint/type-utils": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz",
|
||||||
"integrity": "sha512-2zB8uEn7hEH2pBeyk3NpzX1p3lF9dKrEbnXq1F7YkpZ6hlyqb2yZujqgRGqXgRBTHWIUG3NGx/WeZk224UKlIA==",
|
"integrity": "sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/utils": "5.33.0",
|
"@typescript-eslint/utils": "5.33.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"tsutils": "^3.21.0"
|
"tsutils": "^3.21.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/types": {
|
"@typescript-eslint/types": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.1.tgz",
|
||||||
"integrity": "sha512-nIMt96JngB4MYFYXpZ/3ZNU4GWPNdBbcB5w2rDOCpXOVUkhtNlG2mmm8uXhubhidRZdwMaMBap7Uk8SZMU/ppw==",
|
"integrity": "sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@typescript-eslint/typescript-estree": {
|
"@typescript-eslint/typescript-estree": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz",
|
||||||
"integrity": "sha512-tqq3MRLlggkJKJUrzM6wltk8NckKyyorCSGMq4eVkyL5sDYzJJcMgZATqmF8fLdsWrW7OjjIZ1m9v81vKcaqwQ==",
|
"integrity": "sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/visitor-keys": "5.33.0",
|
"@typescript-eslint/visitor-keys": "5.33.1",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"globby": "^11.1.0",
|
"globby": "^11.1.0",
|
||||||
"is-glob": "^4.0.3",
|
"is-glob": "^4.0.3",
|
||||||
|
|
@ -11703,26 +11703,26 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/utils": {
|
"@typescript-eslint/utils": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.1.tgz",
|
||||||
"integrity": "sha512-JxOAnXt9oZjXLIiXb5ZIcZXiwVHCkqZgof0O8KPgz7C7y0HS42gi75PdPlqh1Tf109M0fyUw45Ao6JLo7S5AHw==",
|
"integrity": "sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/json-schema": "^7.0.9",
|
"@types/json-schema": "^7.0.9",
|
||||||
"@typescript-eslint/scope-manager": "5.33.0",
|
"@typescript-eslint/scope-manager": "5.33.1",
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"@typescript-eslint/typescript-estree": "5.33.0",
|
"@typescript-eslint/typescript-estree": "5.33.1",
|
||||||
"eslint-scope": "^5.1.1",
|
"eslint-scope": "^5.1.1",
|
||||||
"eslint-utils": "^3.0.0"
|
"eslint-utils": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@typescript-eslint/visitor-keys": {
|
"@typescript-eslint/visitor-keys": {
|
||||||
"version": "5.33.0",
|
"version": "5.33.1",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz",
|
||||||
"integrity": "sha512-/XsqCzD4t+Y9p5wd9HZiptuGKBlaZO5showwqODii5C0nZawxWLF+Q6k5wYHBrQv96h6GYKyqqMHCSTqta8Kiw==",
|
"integrity": "sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@typescript-eslint/types": "5.33.0",
|
"@typescript-eslint/types": "5.33.1",
|
||||||
"eslint-visitor-keys": "^3.3.0"
|
"eslint-visitor-keys": "^3.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -74,8 +74,8 @@
|
||||||
"@types/node-windows": "^0.1.2",
|
"@types/node-windows": "^0.1.2",
|
||||||
"@types/papaparse": "^5.3.3",
|
"@types/papaparse": "^5.3.3",
|
||||||
"@types/session-file-store": "^1.2.2",
|
"@types/session-file-store": "^1.2.2",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.33.0",
|
"@typescript-eslint/eslint-plugin": "^5.33.1",
|
||||||
"@typescript-eslint/parser": "^5.33.0",
|
"@typescript-eslint/parser": "^5.33.1",
|
||||||
"bulma": "^0.9.4",
|
"bulma": "^0.9.4",
|
||||||
"eslint": "^8.22.0",
|
"eslint": "^8.22.0",
|
||||||
"eslint-plugin-import": "^2.26.0",
|
"eslint-plugin-import": "^2.26.0",
|
||||||
|
|
|
||||||
|
|
@ -125,4 +125,14 @@ fieldset:enabled .is-hidden-enabled {
|
||||||
|
|
||||||
.select option:disabled {
|
.select option:disabled {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modal Size Fix
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
.modal-card {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export {};
|
||||||
|
|
@ -0,0 +1,176 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
(() => {
|
||||||
|
const los = exports.los;
|
||||||
|
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
|
||||||
|
const feeCategoriesContainerElement = document.querySelector("#container--feeCategories");
|
||||||
|
let feeCategories = exports.feeCategories;
|
||||||
|
const openEditFeeCategory = (clickEvent) => {
|
||||||
|
const feeCategoryId = Number.parseInt(clickEvent.currentTarget.closest(".container--feeCategory").dataset.feeCategoryId, 10);
|
||||||
|
const feeCategory = feeCategories.find((currentFeeCategory) => {
|
||||||
|
return currentFeeCategory.feeCategoryId === feeCategoryId;
|
||||||
|
});
|
||||||
|
let editCloseModalFunction;
|
||||||
|
const doUpdateFeeCategory = (submitEvent) => {
|
||||||
|
submitEvent.preventDefault();
|
||||||
|
cityssm.postJSON(urlPrefix + "/admin/doUpdateFeeCategory", submitEvent.currentTarget, (responseJSON) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
feeCategories = responseJSON.feeCategories;
|
||||||
|
editCloseModalFunction();
|
||||||
|
renderFeeCategories();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Updating Fee Category",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
cityssm.openHtmlModal("adminFees-editFeeCategory", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
modalElement.querySelector("#feeCategoryEdit--feeCategoryId").value = feeCategory.feeCategoryId.toString();
|
||||||
|
modalElement.querySelector("#feeCategoryEdit--feeCategory").value = feeCategory.feeCategory;
|
||||||
|
},
|
||||||
|
onshown: (modalElement, closeModalFunction) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
editCloseModalFunction = closeModalFunction;
|
||||||
|
modalElement.querySelector("form").addEventListener("submit", doUpdateFeeCategory);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const openAddFee = (clickEvent) => {
|
||||||
|
const feeCategoryId = Number.parseInt(clickEvent.currentTarget.closest(".container--feeCategory").dataset.feeCategoryId, 10);
|
||||||
|
let addCloseModalFunction;
|
||||||
|
const doAddFee = (submitEvent) => {
|
||||||
|
submitEvent.preventDefault();
|
||||||
|
};
|
||||||
|
cityssm.openHtmlModal("adminFees-addFee", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
const feeCategoryElement = modalElement.querySelector("#feeAdd--feeCategoryId");
|
||||||
|
for (const feeCategory of feeCategories) {
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = feeCategory.feeCategoryId.toString();
|
||||||
|
optionElement.textContent = feeCategory.feeCategory;
|
||||||
|
if (feeCategory.feeCategoryId === feeCategoryId) {
|
||||||
|
optionElement.selected = true;
|
||||||
|
}
|
||||||
|
feeCategoryElement.append(optionElement);
|
||||||
|
}
|
||||||
|
const occupancyTypeElement = modalElement.querySelector("#feeAdd--occupancyTypeId");
|
||||||
|
for (const occupancyType of exports.occupancyTypes) {
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = occupancyType.occupancyTypeId.toString();
|
||||||
|
optionElement.textContent = occupancyType.occupancyType;
|
||||||
|
occupancyTypeElement.append(optionElement);
|
||||||
|
}
|
||||||
|
const lotTypeElement = modalElement.querySelector("#feeAdd--lotTypeId");
|
||||||
|
for (const lotType of exports.lotTypes) {
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = lotType.lotTypeId.toString();
|
||||||
|
optionElement.textContent = lotType.lotType;
|
||||||
|
lotTypeElement.append(optionElement);
|
||||||
|
}
|
||||||
|
los.populateAliases(modalElement);
|
||||||
|
},
|
||||||
|
onshown: (modalElement, closeModalFunction) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
addCloseModalFunction = closeModalFunction;
|
||||||
|
modalElement.querySelector("form").addEventListener("submit", doAddFee);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const renderFeeCategories = () => {
|
||||||
|
if (feeCategories.length === 0) {
|
||||||
|
feeCategoriesContainerElement.innerHTML = "<div class=\"message is-warning\">" +
|
||||||
|
"<p class=\"message-body\">There are no available fees.</p>" +
|
||||||
|
"</div>";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
feeCategoriesContainerElement.innerHTML = "";
|
||||||
|
for (const feeCategory of feeCategories) {
|
||||||
|
const feeCategoryContainerElement = document.createElement("section");
|
||||||
|
feeCategoryContainerElement.className = "container--feeCategory";
|
||||||
|
feeCategoryContainerElement.dataset.feeCategoryId = feeCategory.feeCategoryId.toString();
|
||||||
|
feeCategoryContainerElement.insertAdjacentHTML("beforeend", "<div class=\"level is-mobile\">" +
|
||||||
|
("<div class=\"level-left\">" +
|
||||||
|
"<div class=\"level-item\">" +
|
||||||
|
"<h2 class=\"title is-4\">" + cityssm.escapeHTML(feeCategory.feeCategory) + "</h2>" +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
("<div class=\"level-right\">" +
|
||||||
|
"<div class=\"level-item\">" +
|
||||||
|
"<button class=\"button is-small is-primary button--editFeeCategory\" type=\"button\">" +
|
||||||
|
"<span class=\"icon is-small\"><i class=\"fas fa-pencil-alt\" aria-hidden=\"true\"></i></span>" +
|
||||||
|
"<span>Edit Category</span>" +
|
||||||
|
"</button>" +
|
||||||
|
"</div>" +
|
||||||
|
"<div class=\"level-item\">" +
|
||||||
|
"<button class=\"button is-small is-success button--addFee\" type=\"button\">" +
|
||||||
|
"<span class=\"icon is-small\"><i class=\"fas fa-plus\" aria-hidden=\"true\"></i></span>" +
|
||||||
|
"<span>Add Fee</span>" +
|
||||||
|
"</button>" +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
"</div>");
|
||||||
|
if (feeCategory.fees.length === 0) {
|
||||||
|
feeCategoryContainerElement.insertAdjacentHTML("beforeend", "<div class=\"message is-info\">" +
|
||||||
|
"<p class=\"message-body\">There are no fees in the \"" + cityssm.escapeHTML(feeCategory.feeCategory) + "\" category.</p>" +
|
||||||
|
"</div>");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const panelElement = document.createElement("div");
|
||||||
|
panelElement.className = "panel";
|
||||||
|
feeCategoryContainerElement.append(panelElement);
|
||||||
|
}
|
||||||
|
feeCategoriesContainerElement.append(feeCategoryContainerElement);
|
||||||
|
}
|
||||||
|
const editCategoryButtonElements = feeCategoriesContainerElement.querySelectorAll(".button--editFeeCategory");
|
||||||
|
for (const editCategoryButtonElement of editCategoryButtonElements) {
|
||||||
|
editCategoryButtonElement.addEventListener("click", openEditFeeCategory);
|
||||||
|
}
|
||||||
|
const addFeeButtonElements = feeCategoriesContainerElement.querySelectorAll(".button--addFee");
|
||||||
|
for (const addFeeButtonElement of addFeeButtonElements) {
|
||||||
|
addFeeButtonElement.addEventListener("click", openAddFee);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
renderFeeCategories();
|
||||||
|
document.querySelector("#button--addFeeCategory").addEventListener("click", () => {
|
||||||
|
let addCloseModalFunction;
|
||||||
|
const doAddFeeCategory = (submitEvent) => {
|
||||||
|
submitEvent.preventDefault();
|
||||||
|
cityssm.postJSON(urlPrefix + "/admin/doAddFeeCategory", submitEvent.currentTarget, (responseJSON) => {
|
||||||
|
if (responseJSON.success) {
|
||||||
|
feeCategories = responseJSON.feeCategories;
|
||||||
|
addCloseModalFunction();
|
||||||
|
renderFeeCategories();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Creating Fee Category",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
cityssm.openHtmlModal("adminFees-addFeeCategory", {
|
||||||
|
onshown: (modalElement, closeModalFunction) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
modalElement.querySelector("#feeCategoryAdd--feeCategory").focus();
|
||||||
|
addCloseModalFunction = closeModalFunction;
|
||||||
|
modalElement.querySelector("form").addEventListener("submit", doAddFeeCategory);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
@ -0,0 +1,260 @@
|
||||||
|
/* eslint-disable unicorn/prefer-module */
|
||||||
|
|
||||||
|
import type * as globalTypes from "../types/globalTypes";
|
||||||
|
import type * as recordTypes from "../types/recordTypes";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
cityssmGlobal
|
||||||
|
} from "@cityssm/bulma-webapp-js/src/types";
|
||||||
|
|
||||||
|
import type {
|
||||||
|
BulmaJS
|
||||||
|
} from "@cityssm/bulma-js/types";
|
||||||
|
|
||||||
|
declare const cityssm: cityssmGlobal;
|
||||||
|
declare const bulmaJS: BulmaJS;
|
||||||
|
|
||||||
|
|
||||||
|
(() => {
|
||||||
|
const los = (exports.los as globalTypes.LOS);
|
||||||
|
|
||||||
|
const urlPrefix = document.querySelector("main").dataset.urlPrefix;
|
||||||
|
|
||||||
|
const feeCategoriesContainerElement = document.querySelector("#container--feeCategories") as HTMLElement;
|
||||||
|
|
||||||
|
let feeCategories: recordTypes.FeeCategory[] = exports.feeCategories;
|
||||||
|
|
||||||
|
const openEditFeeCategory = (clickEvent: Event) => {
|
||||||
|
|
||||||
|
const feeCategoryId = Number.parseInt(((clickEvent.currentTarget as HTMLElement).closest(".container--feeCategory") as HTMLElement).dataset.feeCategoryId, 10);
|
||||||
|
|
||||||
|
const feeCategory = feeCategories.find((currentFeeCategory) => {
|
||||||
|
return currentFeeCategory.feeCategoryId === feeCategoryId;
|
||||||
|
});
|
||||||
|
|
||||||
|
let editCloseModalFunction: () => void;
|
||||||
|
|
||||||
|
const doUpdateFeeCategory = (submitEvent: SubmitEvent) => {
|
||||||
|
submitEvent.preventDefault();
|
||||||
|
|
||||||
|
cityssm.postJSON(urlPrefix + "/admin/doUpdateFeeCategory",
|
||||||
|
submitEvent.currentTarget,
|
||||||
|
(responseJSON: {
|
||||||
|
success: boolean;
|
||||||
|
errorMessage ? : string;
|
||||||
|
feeCategories: recordTypes.FeeCategory[];
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
if (responseJSON.success) {
|
||||||
|
feeCategories = responseJSON.feeCategories;
|
||||||
|
editCloseModalFunction();
|
||||||
|
renderFeeCategories();
|
||||||
|
} else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Updating Fee Category",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cityssm.openHtmlModal("adminFees-editFeeCategory", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
(modalElement.querySelector("#feeCategoryEdit--feeCategoryId") as HTMLInputElement).value = feeCategory.feeCategoryId.toString();
|
||||||
|
(modalElement.querySelector("#feeCategoryEdit--feeCategory") as HTMLInputElement).value = feeCategory.feeCategory;
|
||||||
|
},
|
||||||
|
onshown: (modalElement, closeModalFunction) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
|
||||||
|
editCloseModalFunction = closeModalFunction;
|
||||||
|
|
||||||
|
modalElement.querySelector("form").addEventListener("submit", doUpdateFeeCategory);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const openAddFee = (clickEvent: Event) => {
|
||||||
|
|
||||||
|
const feeCategoryId = Number.parseInt(((clickEvent.currentTarget as HTMLElement).closest(".container--feeCategory") as HTMLElement).dataset.feeCategoryId, 10);
|
||||||
|
|
||||||
|
let addCloseModalFunction: () => void;
|
||||||
|
|
||||||
|
const doAddFee = (submitEvent: SubmitEvent) => {
|
||||||
|
submitEvent.preventDefault();
|
||||||
|
};
|
||||||
|
|
||||||
|
cityssm.openHtmlModal("adminFees-addFee", {
|
||||||
|
onshow: (modalElement) => {
|
||||||
|
|
||||||
|
const feeCategoryElement = modalElement.querySelector("#feeAdd--feeCategoryId") as HTMLSelectElement;
|
||||||
|
|
||||||
|
for (const feeCategory of feeCategories) {
|
||||||
|
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = feeCategory.feeCategoryId.toString();
|
||||||
|
optionElement.textContent = feeCategory.feeCategory;
|
||||||
|
|
||||||
|
if (feeCategory.feeCategoryId === feeCategoryId) {
|
||||||
|
optionElement.selected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
feeCategoryElement.append(optionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
const occupancyTypeElement = modalElement.querySelector("#feeAdd--occupancyTypeId") as HTMLSelectElement;
|
||||||
|
|
||||||
|
for (const occupancyType of exports.occupancyTypes as recordTypes.OccupancyType[]) {
|
||||||
|
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = occupancyType.occupancyTypeId.toString();
|
||||||
|
optionElement.textContent = occupancyType.occupancyType;
|
||||||
|
occupancyTypeElement.append(optionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
const lotTypeElement = modalElement.querySelector("#feeAdd--lotTypeId") as HTMLSelectElement;
|
||||||
|
|
||||||
|
for (const lotType of exports.lotTypes as recordTypes.LotType[]) {
|
||||||
|
|
||||||
|
const optionElement = document.createElement("option");
|
||||||
|
optionElement.value = lotType.lotTypeId.toString();
|
||||||
|
optionElement.textContent = lotType.lotType;
|
||||||
|
lotTypeElement.append(optionElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
los.populateAliases(modalElement);
|
||||||
|
},
|
||||||
|
onshown: (modalElement, closeModalFunction) => {
|
||||||
|
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
addCloseModalFunction = closeModalFunction;
|
||||||
|
|
||||||
|
modalElement.querySelector("form").addEventListener("submit", doAddFee);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderFeeCategories = () => {
|
||||||
|
|
||||||
|
if (feeCategories.length === 0) {
|
||||||
|
feeCategoriesContainerElement.innerHTML = "<div class=\"message is-warning\">" +
|
||||||
|
"<p class=\"message-body\">There are no available fees.</p>" +
|
||||||
|
"</div>";
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
feeCategoriesContainerElement.innerHTML = "";
|
||||||
|
|
||||||
|
for (const feeCategory of feeCategories) {
|
||||||
|
|
||||||
|
const feeCategoryContainerElement = document.createElement("section");
|
||||||
|
feeCategoryContainerElement.className = "container--feeCategory";
|
||||||
|
feeCategoryContainerElement.dataset.feeCategoryId = feeCategory.feeCategoryId.toString();
|
||||||
|
|
||||||
|
feeCategoryContainerElement.insertAdjacentHTML("beforeend",
|
||||||
|
"<div class=\"level is-mobile\">" +
|
||||||
|
("<div class=\"level-left\">" +
|
||||||
|
"<div class=\"level-item\">" +
|
||||||
|
"<h2 class=\"title is-4\">" + cityssm.escapeHTML(feeCategory.feeCategory) + "</h2>" +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
("<div class=\"level-right\">" +
|
||||||
|
"<div class=\"level-item\">" +
|
||||||
|
"<button class=\"button is-small is-primary button--editFeeCategory\" type=\"button\">" +
|
||||||
|
"<span class=\"icon is-small\"><i class=\"fas fa-pencil-alt\" aria-hidden=\"true\"></i></span>" +
|
||||||
|
"<span>Edit Category</span>" +
|
||||||
|
"</button>" +
|
||||||
|
"</div>" +
|
||||||
|
"<div class=\"level-item\">" +
|
||||||
|
"<button class=\"button is-small is-success button--addFee\" type=\"button\">" +
|
||||||
|
"<span class=\"icon is-small\"><i class=\"fas fa-plus\" aria-hidden=\"true\"></i></span>" +
|
||||||
|
"<span>Add Fee</span>" +
|
||||||
|
"</button>" +
|
||||||
|
"</div>" +
|
||||||
|
"</div>") +
|
||||||
|
"</div>");
|
||||||
|
|
||||||
|
if (feeCategory.fees.length === 0) {
|
||||||
|
feeCategoryContainerElement.insertAdjacentHTML("beforeend",
|
||||||
|
"<div class=\"message is-info\">" +
|
||||||
|
"<p class=\"message-body\">There are no fees in the \"" + cityssm.escapeHTML(feeCategory.feeCategory) + "\" category.</p>" +
|
||||||
|
"</div>");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
const panelElement = document.createElement("div");
|
||||||
|
panelElement.className = "panel";
|
||||||
|
|
||||||
|
feeCategoryContainerElement.append(panelElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
feeCategoriesContainerElement.append(feeCategoryContainerElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
const editCategoryButtonElements = feeCategoriesContainerElement.querySelectorAll(".button--editFeeCategory");
|
||||||
|
|
||||||
|
for (const editCategoryButtonElement of editCategoryButtonElements) {
|
||||||
|
editCategoryButtonElement.addEventListener("click", openEditFeeCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
const addFeeButtonElements = feeCategoriesContainerElement.querySelectorAll(".button--addFee");
|
||||||
|
|
||||||
|
for (const addFeeButtonElement of addFeeButtonElements) {
|
||||||
|
addFeeButtonElement.addEventListener("click", openAddFee);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
renderFeeCategories();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fee Categories
|
||||||
|
*/
|
||||||
|
|
||||||
|
document.querySelector("#button--addFeeCategory").addEventListener("click", () => {
|
||||||
|
|
||||||
|
let addCloseModalFunction: () => void;
|
||||||
|
|
||||||
|
const doAddFeeCategory = (submitEvent: SubmitEvent) => {
|
||||||
|
submitEvent.preventDefault();
|
||||||
|
|
||||||
|
cityssm.postJSON(urlPrefix + "/admin/doAddFeeCategory",
|
||||||
|
submitEvent.currentTarget,
|
||||||
|
(responseJSON: {
|
||||||
|
success: boolean;errorMessage ? : string;feeCategories: recordTypes.FeeCategory[];
|
||||||
|
}) => {
|
||||||
|
|
||||||
|
if (responseJSON.success) {
|
||||||
|
feeCategories = responseJSON.feeCategories;
|
||||||
|
addCloseModalFunction();
|
||||||
|
renderFeeCategories();
|
||||||
|
} else {
|
||||||
|
bulmaJS.alert({
|
||||||
|
title: "Error Creating Fee Category",
|
||||||
|
message: responseJSON.errorMessage,
|
||||||
|
contextualColorName: "danger"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
cityssm.openHtmlModal("adminFees-addFeeCategory", {
|
||||||
|
|
||||||
|
onshown: (modalElement, closeModalFunction) => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
(modalElement.querySelector("#feeCategoryAdd--feeCategory") as HTMLInputElement).focus();
|
||||||
|
|
||||||
|
addCloseModalFunction = closeModalFunction;
|
||||||
|
modalElement.querySelector("form").addEventListener("submit", doAddFeeCategory);
|
||||||
|
},
|
||||||
|
onremoved: () => {
|
||||||
|
bulmaJS.toggleHtmlClipped();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
|
@ -51,11 +51,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
case "lot":
|
case "lot":
|
||||||
aliasElement.textContent = exports.aliases.lot.toLowerCase();
|
aliasElement.textContent = exports.aliases.lot.toLowerCase();
|
||||||
break;
|
break;
|
||||||
|
case "Occupancy":
|
||||||
|
aliasElement.textContent = exports.aliases.occupancy;
|
||||||
|
break;
|
||||||
|
case "occupancy":
|
||||||
|
aliasElement.textContent = exports.aliases.occupancy.toLowerCase();
|
||||||
|
break;
|
||||||
case "Occupant":
|
case "Occupant":
|
||||||
aliasElement.textContent = exports.aliases.occupant;
|
aliasElement.textContent = exports.aliases.occupant;
|
||||||
break;
|
break;
|
||||||
case "occupant":
|
case "occupant":
|
||||||
aliasElement.textContent = exports.aliases.lot.toLowerCase();
|
aliasElement.textContent = exports.aliases.occupant.toLowerCase();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,12 +84,20 @@ import type * as globalTypes from "../types/globalTypes";
|
||||||
aliasElement.textContent = exports.aliases.lot.toLowerCase();
|
aliasElement.textContent = exports.aliases.lot.toLowerCase();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "Occupancy":
|
||||||
|
aliasElement.textContent = exports.aliases.occupancy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "occupancy":
|
||||||
|
aliasElement.textContent = exports.aliases.occupancy.toLowerCase();
|
||||||
|
break;
|
||||||
|
|
||||||
case "Occupant":
|
case "Occupant":
|
||||||
aliasElement.textContent = exports.aliases.occupant;
|
aliasElement.textContent = exports.aliases.occupant;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "occupant":
|
case "occupant":
|
||||||
aliasElement.textContent = exports.aliases.lot.toLowerCase();
|
aliasElement.textContent = exports.aliases.occupant.toLowerCase();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
<div class="modal">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-card" style="width:900px">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<h3 class="modal-card-title">
|
||||||
|
Add Fee
|
||||||
|
</h3>
|
||||||
|
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<form id="form--feeAdd">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--feeCategoryId">Fee Category</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select is-fullwidth">
|
||||||
|
<select id="feeAdd--feeCategoryId" name="feeCategoryId" required></select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--feeName">Fee</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" id="feeAdd--feeName" name="feeName" maxlength="100" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--feeDescription">Fee Description</label>
|
||||||
|
<div class="control">
|
||||||
|
<textarea class="textarea" id="feeAdd--feeDescription" name="feeDescription"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--occupancyTypeId"><span class="alias" data-alias="Occupancy"></span> Type Filter</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select is-fullwidth">
|
||||||
|
<select id="feeAdd--occupancyTypeId" name="occupancyTypeId">
|
||||||
|
<option value="">(All Types)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--lotTypeId"><span class="alias" data-alias="Lot"></span> Type Filter</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select is-fullwidth">
|
||||||
|
<select id="feeAdd--lotTypeId" name="lotTypeId">
|
||||||
|
<option value="">(All Types)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--feeAmount">Fee Amount</label>
|
||||||
|
<div class="control has-icons-left">
|
||||||
|
<input class="input has-text-right" id="feeAdd--feeAmount" name="feeAmount" type="number" step="0.01" min="0" max="9999.99" value="0" onwheel="return false" />
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-dollar-sign" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--feeFunction">Fee Function</label>
|
||||||
|
<div class="control">
|
||||||
|
<div class="select is-fullwidth">
|
||||||
|
<select id="feeAdd--feeFunction" name="feeFunction"></select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--taxAmount">Tax Amount</label>
|
||||||
|
<div class="control has-icons-left">
|
||||||
|
<input class="input has-text-right" id="feeAdd--taxAmount" name="taxAmount" type="number" step="0.01" min="0" max="9999.99" onwheel="return false" />
|
||||||
|
<span class="icon is-small is-left">
|
||||||
|
<i class="fas fa-dollar-sign" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeAdd--taxPercentage">Tax Percentage</label>
|
||||||
|
<div class="control has-icons-right">
|
||||||
|
<input class="input has-text-right" id="feeAdd--taxPercentage" name="taxPercentage" type="number" step="0.01" min="0" max="100" value="0" onwheel="return false" />
|
||||||
|
<span class="icon is-small is-right">
|
||||||
|
<i class="fas fa-percent" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot justify-right">
|
||||||
|
<button class="button is-success" type="submit" form="form--feeAdd">
|
||||||
|
<span class="icon"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
||||||
|
<span>Add Fee</span>
|
||||||
|
</button>
|
||||||
|
<button class="button is-close-modal-button" type="button">Cancel</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<div class="modal">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-card">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<h3 class="modal-card-title">
|
||||||
|
Add Fee Category
|
||||||
|
</h3>
|
||||||
|
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<form id="form--feeCategoryAdd">
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeCategoryAdd--feeCategory">New Fee Category</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" id="feeCategoryAdd--feeCategory" name="feeCategory" maxlength="100" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot justify-right">
|
||||||
|
<button class="button is-success" type="submit" form="form--feeCategoryAdd">
|
||||||
|
<span class="icon"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
||||||
|
<span>Add Fee Category</span>
|
||||||
|
</button>
|
||||||
|
<button class="button is-close-modal-button" type="button">Cancel</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
<div class="modal">
|
||||||
|
<div class="modal-background"></div>
|
||||||
|
<div class="modal-card">
|
||||||
|
<header class="modal-card-head">
|
||||||
|
<h3 class="modal-card-title">
|
||||||
|
Update Fee Category
|
||||||
|
</h3>
|
||||||
|
<button class="delete is-close-modal-button" aria-label="close" type="button"></button>
|
||||||
|
</header>
|
||||||
|
<section class="modal-card-body">
|
||||||
|
<form id="form--feeCategoryEdit">
|
||||||
|
<input id="feeCategoryEdit--feeCategoryId" name="feeCategoryId" type="hidden" />
|
||||||
|
<div class="field">
|
||||||
|
<label class="label" for="feeCategoryEdit--feeCategory">Fee Category</label>
|
||||||
|
<div class="control">
|
||||||
|
<input class="input" id="feeCategoryEdit--feeCategory" name="feeCategory" maxlength="100" required />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
<footer class="modal-card-foot justify-right">
|
||||||
|
<button class="button is-success" type="submit" form="form--feeCategoryEdit">
|
||||||
|
<span class="icon"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
||||||
|
<span>Update Fee Category</span>
|
||||||
|
</button>
|
||||||
|
<button class="button is-close-modal-button" type="button">Cancel</button>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,t=document.querySelector("main").dataset.urlPrefix,o=document.querySelector("#container--feeCategories");let s=exports.feeCategories;const a=e=>{const o=Number.parseInt(e.currentTarget.closest(".container--feeCategory").dataset.feeCategoryId,10),a=s.find(e=>e.feeCategoryId===o);let r;const l=e=>{e.preventDefault(),cityssm.postJSON(t+"/admin/doUpdateFeeCategory",e.currentTarget,e=>{e.success?(s=e.feeCategories,r(),n()):bulmaJS.alert({title:"Error Updating Fee Category",message:e.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("adminFees-editFeeCategory",{onshow:e=>{e.querySelector("#feeCategoryEdit--feeCategoryId").value=a.feeCategoryId.toString(),e.querySelector("#feeCategoryEdit--feeCategory").value=a.feeCategory},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),r=t,e.querySelector("form").addEventListener("submit",l)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},r=t=>{const o=Number.parseInt(t.currentTarget.closest(".container--feeCategory").dataset.feeCategoryId,10);let a;const r=e=>{e.preventDefault()};cityssm.openHtmlModal("adminFees-addFee",{onshow:t=>{const a=t.querySelector("#feeAdd--feeCategoryId");for(const e of s){const t=document.createElement("option");t.value=e.feeCategoryId.toString(),t.textContent=e.feeCategory,e.feeCategoryId===o&&(t.selected=!0),a.append(t)}const r=t.querySelector("#feeAdd--occupancyTypeId");for(const e of exports.occupancyTypes){const t=document.createElement("option");t.value=e.occupancyTypeId.toString(),t.textContent=e.occupancyType,r.append(t)}const n=t.querySelector("#feeAdd--lotTypeId");for(const e of exports.lotTypes){const t=document.createElement("option");t.value=e.lotTypeId.toString(),t.textContent=e.lotType,n.append(t)}e.populateAliases(t)},onshown:(e,t)=>{bulmaJS.toggleHtmlClipped(),a=t,e.querySelector("form").addEventListener("submit",r)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})},n=()=>{if(0===s.length)return void(o.innerHTML='<div class="message is-warning"><p class="message-body">There are no available fees.</p></div>');o.innerHTML="";for(const e of s){const t=document.createElement("section");if(t.className="container--feeCategory",t.dataset.feeCategoryId=e.feeCategoryId.toString(),t.insertAdjacentHTML("beforeend",'<div class="level is-mobile"><div class="level-left"><div class="level-item"><h2 class="title is-4">'+cityssm.escapeHTML(e.feeCategory)+'</h2></div></div><div class="level-right"><div class="level-item"><button class="button is-small is-primary button--editFeeCategory" type="button"><span class="icon is-small"><i class="fas fa-pencil-alt" aria-hidden="true"></i></span><span>Edit Category</span></button></div><div class="level-item"><button class="button is-small is-success button--addFee" type="button"><span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span><span>Add Fee</span></button></div></div></div>'),0===e.fees.length)t.insertAdjacentHTML("beforeend",'<div class="message is-info"><p class="message-body">There are no fees in the "'+cityssm.escapeHTML(e.feeCategory)+'" category.</p></div>');else{const e=document.createElement("div");e.className="panel",t.append(e)}o.append(t)}const e=o.querySelectorAll(".button--editFeeCategory");for(const t of e)t.addEventListener("click",a);const t=o.querySelectorAll(".button--addFee");for(const e of t)e.addEventListener("click",r)};n(),document.querySelector("#button--addFeeCategory").addEventListener("click",()=>{let e;const o=o=>{o.preventDefault(),cityssm.postJSON(t+"/admin/doAddFeeCategory",o.currentTarget,t=>{t.success?(s=t.feeCategories,e(),n()):bulmaJS.alert({title:"Error Creating Fee Category",message:t.errorMessage,contextualColorName:"danger"})})};cityssm.openHtmlModal("adminFees-addFeeCategory",{onshown:(t,s)=>{bulmaJS.toggleHtmlClipped(),t.querySelector("#feeCategoryAdd--feeCategory").focus(),e=s,t.querySelector("form").addEventListener("submit",o)},onremoved:()=>{bulmaJS.toggleHtmlClipped()}})})})();
|
||||||
|
|
@ -1 +1 @@
|
||||||
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=e=>{const t=e.currentTarget.closest(".field").querySelector("input, select");if("INPUT"===t.tagName)t.disabled=!1;else{const e=t.querySelectorAll("option");for(const t of e)t.disabled=!1}t.focus()},t={highlightMap:(e,t,o)=>{let l,s=t;for(;!(l=e.querySelector("#"+s))&&s.includes("-");)s=s.slice(0,Math.max(0,s.lastIndexOf("-"))),console.log(s);if(l){l.style.fill=null,l.classList.add("highlight","is-"+o);const e=l.querySelectorAll("path");for(const t of e)t.style.fill=null}},initializeUnlockFieldButtons:t=>{const o=t.querySelectorAll(".is-unlock-field-button");for(const t of o)t.addEventListener("click",e)},populateAliases:e=>{const t=e.querySelectorAll(".alias");for(const e of t)switch(e.dataset.alias){case"Lot":e.textContent=exports.aliases.lot;break;case"lot":e.textContent=exports.aliases.lot.toLowerCase();break;case"Occupant":e.textContent=exports.aliases.occupant;break;case"occupant":e.textContent=exports.aliases.lot.toLowerCase()}}};exports.los=t})();
|
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=e=>{const t=e.currentTarget.closest(".field").querySelector("input, select");if("INPUT"===t.tagName)t.disabled=!1;else{const e=t.querySelectorAll("option");for(const t of e)t.disabled=!1}t.focus()},t={highlightMap:(e,t,o)=>{let s,l=t;for(;!(s=e.querySelector("#"+l))&&l.includes("-");)l=l.slice(0,Math.max(0,l.lastIndexOf("-"))),console.log(l);if(s){s.style.fill=null,s.classList.add("highlight","is-"+o);const e=s.querySelectorAll("path");for(const t of e)t.style.fill=null}},initializeUnlockFieldButtons:t=>{const o=t.querySelectorAll(".is-unlock-field-button");for(const t of o)t.addEventListener("click",e)},populateAliases:e=>{const t=e.querySelectorAll(".alias");for(const e of t)switch(e.dataset.alias){case"Lot":e.textContent=exports.aliases.lot;break;case"lot":e.textContent=exports.aliases.lot.toLowerCase();break;case"Occupancy":e.textContent=exports.aliases.occupancy;break;case"occupancy":e.textContent=exports.aliases.occupancy.toLowerCase();break;case"Occupant":e.textContent=exports.aliases.occupant;break;case"occupant":e.textContent=exports.aliases.occupant.toLowerCase()}}};exports.los=t})();
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,10 @@
|
||||||
import { Router } from "express";
|
import { Router } from "express";
|
||||||
import * as permissionHandlers from "../handlers/permissions.js";
|
import * as permissionHandlers from "../handlers/permissions.js";
|
||||||
import handler_licenceCategories from "../handlers/admin-get/licenceCategories.js";
|
import handler_fees from "../handlers/admin-get/fees.js";
|
||||||
|
import handler_doAddFeeCategory from "../handlers/admin-post/doAddFeeCategory.js";
|
||||||
|
import handler_doUpdateFeeCategory from "../handlers/admin-post/doUpdateFeeCategory.js";
|
||||||
export const router = Router();
|
export const router = Router();
|
||||||
router.get("/licenceCategories", permissionHandlers.adminGetHandler, handler_licenceCategories);
|
router.get("/fees", permissionHandlers.adminGetHandler, handler_fees);
|
||||||
|
router.post("/doAddFeeCategory", permissionHandlers.adminPostHandler, handler_doAddFeeCategory);
|
||||||
|
router.post("/doUpdateFeeCategory", permissionHandlers.adminPostHandler, handler_doUpdateFeeCategory);
|
||||||
export default router;
|
export default router;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,30 @@
|
||||||
import { Router } from "express";
|
import {
|
||||||
|
Router
|
||||||
|
} from "express";
|
||||||
|
|
||||||
import * as permissionHandlers from "../handlers/permissions.js";
|
import * as permissionHandlers from "../handlers/permissions.js";
|
||||||
|
|
||||||
import handler_licenceCategories from "../handlers/admin-get/licenceCategories.js";
|
import handler_fees from "../handlers/admin-get/fees.js";
|
||||||
|
import handler_doAddFeeCategory from "../handlers/admin-post/doAddFeeCategory.js";
|
||||||
|
import handler_doUpdateFeeCategory from "../handlers/admin-post/doUpdateFeeCategory.js";
|
||||||
|
|
||||||
|
|
||||||
export const router = Router();
|
export const router = Router();
|
||||||
|
|
||||||
|
|
||||||
// Licence Categories
|
// Fees
|
||||||
|
|
||||||
router.get("/licenceCategories",
|
router.get("/fees",
|
||||||
permissionHandlers.adminGetHandler,
|
permissionHandlers.adminGetHandler,
|
||||||
handler_licenceCategories);
|
handler_fees);
|
||||||
|
|
||||||
|
router.post("/doAddFeeCategory",
|
||||||
|
permissionHandlers.adminPostHandler,
|
||||||
|
handler_doAddFeeCategory);
|
||||||
|
|
||||||
|
router.post("/doUpdateFeeCategory",
|
||||||
|
permissionHandlers.adminPostHandler,
|
||||||
|
handler_doUpdateFeeCategory);
|
||||||
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
@ -4,10 +4,11 @@ import * as authenticationFunctions from "../helpers/functions.authentication.js
|
||||||
export const router = Router();
|
export const router = Router();
|
||||||
const getSafeRedirectURL = (possibleRedirectURL = "") => {
|
const getSafeRedirectURL = (possibleRedirectURL = "") => {
|
||||||
const urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");
|
const urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");
|
||||||
const urlToCheck = (possibleRedirectURL.startsWith(urlPrefix)
|
const urlToCheck = (possibleRedirectURL.startsWith(urlPrefix) ?
|
||||||
? possibleRedirectURL.slice(urlPrefix.length)
|
possibleRedirectURL.slice(urlPrefix.length) :
|
||||||
: possibleRedirectURL).toLowerCase();
|
possibleRedirectURL).toLowerCase();
|
||||||
switch (urlToCheck) {
|
switch (urlToCheck) {
|
||||||
|
case "/admin/fees":
|
||||||
case "/lotOccupancies":
|
case "/lotOccupancies":
|
||||||
case "/lots":
|
case "/lots":
|
||||||
case "/maps":
|
case "/maps":
|
||||||
|
|
|
||||||
141
routes/login.ts
141
routes/login.ts
|
|
@ -1,4 +1,6 @@
|
||||||
import { Router } from "express";
|
import {
|
||||||
|
Router
|
||||||
|
} from "express";
|
||||||
|
|
||||||
import * as configFunctions from "../helpers/functions.config.js";
|
import * as configFunctions from "../helpers/functions.config.js";
|
||||||
|
|
||||||
|
|
@ -11,102 +13,103 @@ export const router = Router();
|
||||||
|
|
||||||
const getSafeRedirectURL = (possibleRedirectURL = "") => {
|
const getSafeRedirectURL = (possibleRedirectURL = "") => {
|
||||||
|
|
||||||
const urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");
|
const urlPrefix = configFunctions.getProperty("reverseProxy.urlPrefix");
|
||||||
|
|
||||||
const urlToCheck = (possibleRedirectURL.startsWith(urlPrefix)
|
const urlToCheck = (possibleRedirectURL.startsWith(urlPrefix) ?
|
||||||
? possibleRedirectURL.slice(urlPrefix.length)
|
possibleRedirectURL.slice(urlPrefix.length) :
|
||||||
: possibleRedirectURL).toLowerCase();
|
possibleRedirectURL).toLowerCase();
|
||||||
|
|
||||||
switch (urlToCheck) {
|
switch (urlToCheck) {
|
||||||
case "/lotOccupancies":
|
case "/admin/fees":
|
||||||
case "/lots":
|
case "/lotOccupancies":
|
||||||
case "/maps":
|
case "/lots":
|
||||||
case "/workOrders":
|
case "/maps":
|
||||||
case "/reports":
|
case "/workOrders":
|
||||||
|
case "/reports":
|
||||||
|
|
||||||
return urlPrefix + urlToCheck;
|
return urlPrefix + urlToCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
return urlPrefix + "/dashboard";
|
return urlPrefix + "/dashboard";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
router.route("/")
|
router.route("/")
|
||||||
.get((request, response) => {
|
.get((request, response) => {
|
||||||
|
|
||||||
const sessionCookieName = configFunctions.getProperty("session.cookieName");
|
const sessionCookieName = configFunctions.getProperty("session.cookieName");
|
||||||
|
|
||||||
if (request.session.user && request.cookies[sessionCookieName]) {
|
if (request.session.user && request.cookies[sessionCookieName]) {
|
||||||
|
|
||||||
const redirectURL = getSafeRedirectURL((request.query.redirect || "") as string);
|
const redirectURL = getSafeRedirectURL((request.query.redirect || "") as string);
|
||||||
|
|
||||||
response.redirect(redirectURL);
|
response.redirect(redirectURL);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
response.render("login", {
|
response.render("login", {
|
||||||
userName: "",
|
userName: "",
|
||||||
message: "",
|
message: "",
|
||||||
redirect: request.query.redirect
|
redirect: request.query.redirect
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.post(async (request, response) => {
|
.post(async (request, response) => {
|
||||||
|
|
||||||
const userName = request.body.userName as string;
|
const userName = request.body.userName as string;
|
||||||
const passwordPlain = request.body.password as string;
|
const passwordPlain = request.body.password as string;
|
||||||
|
|
||||||
const redirectURL = getSafeRedirectURL(request.body.redirect);
|
const redirectURL = getSafeRedirectURL(request.body.redirect);
|
||||||
|
|
||||||
const isAuthenticated = await authenticationFunctions.authenticate(userName, passwordPlain)
|
const isAuthenticated = await authenticationFunctions.authenticate(userName, passwordPlain)
|
||||||
let userObject: recordTypes.User;
|
let userObject: recordTypes.User;
|
||||||
|
|
||||||
if (isAuthenticated) {
|
if (isAuthenticated) {
|
||||||
|
|
||||||
const userNameLowerCase = userName.toLowerCase();
|
const userNameLowerCase = userName.toLowerCase();
|
||||||
|
|
||||||
const canLogin = configFunctions.getProperty("users.canLogin")
|
const canLogin = configFunctions.getProperty("users.canLogin")
|
||||||
.some((currentUserName) => {
|
.some((currentUserName) => {
|
||||||
return userNameLowerCase === currentUserName.toLowerCase();
|
return userNameLowerCase === currentUserName.toLowerCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (canLogin) {
|
if (canLogin) {
|
||||||
|
|
||||||
const canUpdate = configFunctions.getProperty("users.canUpdate")
|
const canUpdate = configFunctions.getProperty("users.canUpdate")
|
||||||
.some((currentUserName) => {
|
.some((currentUserName) => {
|
||||||
return userNameLowerCase === currentUserName.toLowerCase();
|
return userNameLowerCase === currentUserName.toLowerCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
const isAdmin = configFunctions.getProperty("users.isAdmin")
|
const isAdmin = configFunctions.getProperty("users.isAdmin")
|
||||||
.some((currentUserName) => {
|
.some((currentUserName) => {
|
||||||
return userNameLowerCase === currentUserName.toLowerCase();
|
return userNameLowerCase === currentUserName.toLowerCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
userObject = {
|
userObject = {
|
||||||
userName: userNameLowerCase,
|
userName: userNameLowerCase,
|
||||||
userProperties: {
|
userProperties: {
|
||||||
canUpdate,
|
canUpdate,
|
||||||
isAdmin
|
isAdmin
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAuthenticated && userObject) {
|
if (isAuthenticated && userObject) {
|
||||||
|
|
||||||
request.session.user = userObject;
|
request.session.user = userObject;
|
||||||
|
|
||||||
response.redirect(redirectURL);
|
response.redirect(redirectURL);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
response.render("login", {
|
response.render("login", {
|
||||||
userName,
|
userName,
|
||||||
message: "Login Failed",
|
message: "Login Failed",
|
||||||
redirect: redirectURL
|
redirect: redirectURL
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
@ -27,14 +27,15 @@ import * as permissionHandlers from "../handlers/permissions.js";
|
||||||
|
|
||||||
export const router = Router();
|
export const router = Router();
|
||||||
|
|
||||||
|
// Search
|
||||||
|
|
||||||
router.get("/",
|
router.get("/",
|
||||||
handler_search);
|
handler_search);
|
||||||
|
|
||||||
|
|
||||||
router.post("/doSearchLotOccupancies",
|
router.post("/doSearchLotOccupancies",
|
||||||
handler_doSearchLotOccupancies);
|
handler_doSearchLotOccupancies);
|
||||||
|
|
||||||
|
// Create
|
||||||
|
|
||||||
router.get("/new",
|
router.get("/new",
|
||||||
permissionHandlers.updateGetHandler,
|
permissionHandlers.updateGetHandler,
|
||||||
|
|
@ -48,10 +49,12 @@ router.post("/doCreateLotOccupancy",
|
||||||
permissionHandlers.updatePostHandler,
|
permissionHandlers.updatePostHandler,
|
||||||
handler_doCreateLotOccupancy);
|
handler_doCreateLotOccupancy);
|
||||||
|
|
||||||
|
// View
|
||||||
|
|
||||||
router.get("/:lotOccupancyId",
|
router.get("/:lotOccupancyId",
|
||||||
handler_view);
|
handler_view);
|
||||||
|
|
||||||
|
// Edit
|
||||||
|
|
||||||
router.get("/:lotOccupancyId/edit",
|
router.get("/:lotOccupancyId/edit",
|
||||||
permissionHandlers.updateGetHandler,
|
permissionHandlers.updateGetHandler,
|
||||||
|
|
@ -61,6 +64,8 @@ router.post("/doUpdateLotOccupancy",
|
||||||
permissionHandlers.updatePostHandler,
|
permissionHandlers.updatePostHandler,
|
||||||
handler_doUpdateLotOccupancy);
|
handler_doUpdateLotOccupancy);
|
||||||
|
|
||||||
|
// Occupants
|
||||||
|
|
||||||
router.post("/doAddLotOccupancyOccupant",
|
router.post("/doAddLotOccupancyOccupant",
|
||||||
permissionHandlers.updatePostHandler,
|
permissionHandlers.updatePostHandler,
|
||||||
handler_doAddLotOccupancyOccupant);
|
handler_doAddLotOccupancyOccupant);
|
||||||
|
|
@ -73,6 +78,8 @@ router.post("/doDeleteLotOccupancyOccupant",
|
||||||
permissionHandlers.updatePostHandler,
|
permissionHandlers.updatePostHandler,
|
||||||
handler_doDeleteLotOccupancyOccupant);
|
handler_doDeleteLotOccupancyOccupant);
|
||||||
|
|
||||||
|
// Comments
|
||||||
|
|
||||||
router.post("/doAddLotOccupancyComment",
|
router.post("/doAddLotOccupancyComment",
|
||||||
permissionHandlers.updatePostHandler,
|
permissionHandlers.updatePostHandler,
|
||||||
handler_doAddLotOccupancyComment);
|
handler_doAddLotOccupancyComment);
|
||||||
|
|
|
||||||
|
|
@ -97,18 +97,34 @@ export interface LotOccupantType extends Record {
|
||||||
lotOccupantType?: string;
|
lotOccupantType?: string;
|
||||||
orderNumber?: number;
|
orderNumber?: number;
|
||||||
}
|
}
|
||||||
|
export interface FeeCategory extends Record {
|
||||||
|
feeCategoryId?: number;
|
||||||
|
feeCategory?: string;
|
||||||
|
fees?: Fee[];
|
||||||
|
}
|
||||||
export interface Fee extends Record {
|
export interface Fee extends Record {
|
||||||
feeId?: number;
|
feeId?: number;
|
||||||
|
feeCategoryId?: number;
|
||||||
|
feeCategory?: string;
|
||||||
feeName?: string;
|
feeName?: string;
|
||||||
|
feeDescription?: string;
|
||||||
occupancyTypeId?: number;
|
occupancyTypeId?: number;
|
||||||
lotTypeId?: number;
|
lotTypeId?: number;
|
||||||
|
includeQuantity?: boolean;
|
||||||
|
quantityUnit?: string;
|
||||||
feeAmount?: number;
|
feeAmount?: number;
|
||||||
feeFunction?: string;
|
feeFunction?: string;
|
||||||
|
taxAmount?: number;
|
||||||
|
taxPercentage?: number;
|
||||||
isRequired?: boolean;
|
isRequired?: boolean;
|
||||||
}
|
}
|
||||||
export interface LotOccupancyFee extends Fee, Record {
|
export interface LotOccupancyFee extends Fee, Record {
|
||||||
lotOccupancyId?: number;
|
lotOccupancyId?: number;
|
||||||
|
feeId?: number;
|
||||||
|
feeName?: string;
|
||||||
|
quantity?: number;
|
||||||
feeAmount?: number;
|
feeAmount?: number;
|
||||||
|
taxAmount?: number;
|
||||||
}
|
}
|
||||||
export interface LotOccupancyTransaction extends Record {
|
export interface LotOccupancyTransaction extends Record {
|
||||||
lotOccupancyId?: number;
|
lotOccupancyId?: number;
|
||||||
|
|
|
||||||
|
|
@ -139,36 +139,60 @@ export interface LotOccupantType extends Record {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface FeeCategory extends Record {
|
||||||
|
feeCategoryId ? : number;
|
||||||
|
feeCategory ? : string;
|
||||||
|
fees ? : Fee[];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface Fee extends Record {
|
export interface Fee extends Record {
|
||||||
feeId?: number;
|
feeId ? : number;
|
||||||
feeName?: string;
|
|
||||||
|
|
||||||
occupancyTypeId?: number;
|
feeCategoryId ? : number;
|
||||||
lotTypeId?: number;
|
feeCategory ? : string;
|
||||||
|
|
||||||
feeAmount?: number;
|
feeName ? : string;
|
||||||
feeFunction?: string;
|
feeDescription ? : string;
|
||||||
|
|
||||||
isRequired?: boolean;
|
occupancyTypeId ? : number;
|
||||||
|
lotTypeId ? : number;
|
||||||
|
|
||||||
|
includeQuantity ? : boolean;
|
||||||
|
quantityUnit ? : string;
|
||||||
|
|
||||||
|
feeAmount ? : number;
|
||||||
|
feeFunction ? : string;
|
||||||
|
|
||||||
|
taxAmount ? : number;
|
||||||
|
taxPercentage ? : number;
|
||||||
|
|
||||||
|
isRequired ? : boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface LotOccupancyFee extends Fee, Record {
|
export interface LotOccupancyFee extends Fee, Record {
|
||||||
lotOccupancyId?: number;
|
lotOccupancyId ? : number;
|
||||||
feeAmount?: number;
|
|
||||||
|
feeId ? : number;
|
||||||
|
feeName ? : string;
|
||||||
|
|
||||||
|
quantity ? : number;
|
||||||
|
feeAmount ? : number;
|
||||||
|
taxAmount ? : number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface LotOccupancyTransaction extends Record {
|
export interface LotOccupancyTransaction extends Record {
|
||||||
lotOccupancyId?: number;
|
lotOccupancyId ? : number;
|
||||||
transactionIndex?: number;
|
transactionIndex ? : number;
|
||||||
transactionDate?: number;
|
transactionDate ? : number;
|
||||||
transactionDateString?: string;
|
transactionDateString ? : string;
|
||||||
transactionTime?: number;
|
transactionTime ? : number;
|
||||||
transactionTimeString?: string;
|
transactionTimeString ? : string;
|
||||||
tranactionAmount?: number;
|
tranactionAmount ? : number;
|
||||||
externalReceiptNumber?: string;
|
externalReceiptNumber ? : string;
|
||||||
transactionNote?: string;
|
transactionNote ? : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -204,9 +228,9 @@ export interface LotOccupancyComment extends Record {
|
||||||
|
|
||||||
|
|
||||||
export interface LotOccupancyField extends OccupancyTypeField, Record {
|
export interface LotOccupancyField extends OccupancyTypeField, Record {
|
||||||
lotOccupancyId?: number;
|
lotOccupancyId ? : number;
|
||||||
occupancyTypeFieldId?: number;
|
occupancyTypeFieldId ? : number;
|
||||||
lotOccupancyFieldValue?: string;
|
lotOccupancyFieldValue ? : string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -224,15 +248,15 @@ export interface LotOccupancy extends Record {
|
||||||
|
|
||||||
occupancyStartDate ? : number;
|
occupancyStartDate ? : number;
|
||||||
occupancyStartDateString ? : string;
|
occupancyStartDateString ? : string;
|
||||||
|
|
||||||
occupancyEndDate ? : number;
|
occupancyEndDate ? : number;
|
||||||
occupancyEndDateString ? : string;
|
occupancyEndDateString ? : string;
|
||||||
|
|
||||||
lotOccupancyFields? : LotOccupancyField[];
|
lotOccupancyFields ? : LotOccupancyField[];
|
||||||
lotOccupancyComments ? : LotOccupancyComment[];
|
lotOccupancyComments ? : LotOccupancyComment[];
|
||||||
lotOccupancyOccupants ? : LotOccupancyOccupant[];
|
lotOccupancyOccupants ? : LotOccupancyOccupant[];
|
||||||
lotOccupancyFees?: LotOccupancyFee[];
|
lotOccupancyFees ? : LotOccupancyFee[];
|
||||||
lotOccupancyTransactions?: LotOccupancyTransaction[];
|
lotOccupancyTransactions ? : LotOccupancyTransaction[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
<%- include('_header'); -%>
|
||||||
|
|
||||||
|
<nav class="breadcrumb">
|
||||||
|
<ul>
|
||||||
|
<li><a href="<%= urlPrefix %>/dashboard">Home</a></li>
|
||||||
|
<li>
|
||||||
|
<a href="#">
|
||||||
|
|
||||||
|
<span class="icon is-small"><i class="fas fa-cog" aria-hidden="true"></i></span>
|
||||||
|
<span>Administrator Tools</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="is-active">
|
||||||
|
<a href="#" aria-current="page">
|
||||||
|
Fee Management
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="level is-mobile">
|
||||||
|
<div class="level-left">
|
||||||
|
<div class="level-item">
|
||||||
|
<h1 class="title is-1">
|
||||||
|
Fee Management
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="level-right">
|
||||||
|
<div class="level-item">
|
||||||
|
<button class="button is-success" id="button--addFeeCategory" type="button">
|
||||||
|
<span class="icon is-small"><i class="fas fa-plus" aria-hidden="true"></i></span>
|
||||||
|
<span>Add Fee Category</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="container--feeCategories"></div>
|
||||||
|
|
||||||
|
<%- include('_footerA'); -%>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
exports.feeCategories = <%- JSON.stringify(feeCategories) %>;
|
||||||
|
exports.occupancyTypes = <%- JSON.stringify(occupancyTypes) %>;
|
||||||
|
exports.lotTypes = <%- JSON.stringify(lotTypes) %>;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script src="<%= urlPrefix %>/javascripts/adminFees.min.js"></script>
|
||||||
|
|
||||||
|
<%- include('_footerB'); -%>
|
||||||
|
|
@ -1,146 +1,154 @@
|
||||||
<%- include('_header'); -%>
|
<%- include('_header'); -%>
|
||||||
|
|
||||||
<div class="level">
|
<h1 class="title is-1">
|
||||||
<div class="level-left has-flex-shrink-1">
|
<%= configFunctions.getProperty("application.applicationName") %>
|
||||||
<h1 class="title is-1">
|
</h1>
|
||||||
<%= configFunctions.getProperty("application.applicationName") %>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<span class="fa-layers fa-3x fa-fw" aria-hidden="true">
|
|
||||||
<i class="fas fa-vector-square"></i>
|
|
||||||
<i class="fas fa-user" data-fa-transform="shrink-10"></i>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div class="media-content has-text-black">
|
|
||||||
<h2 class="title is-4 is-marginless">
|
|
||||||
<a href="<%= urlPrefix %>/lotOccupancies"><%= configFunctions.getProperty("aliases.lot") %> <%= configFunctions.getProperty("aliases.occupancies") %></a>
|
|
||||||
</h2>
|
|
||||||
<p>View and maintain current and past <%= configFunctions.getProperty("aliases.lot").toLowerCase() %> <%= configFunctions.getProperty("aliases.occupancies").toLowerCase() %>.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<i class="fas fa-3x fa-fw fa-hard-hat" aria-hidden="true"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-content has-text-black">
|
|
||||||
<h2 class="title is-4 is-marginless">
|
|
||||||
<a href="<%= urlPrefix %>/workOrders">Work Orders</a>
|
|
||||||
</h2>
|
|
||||||
<p>View and maintain work orders.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="column">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<i class="fas fa-3x fa-fw fa-vector-square" aria-hidden="true"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-content has-text-black">
|
|
||||||
<h2 class="title is-4 is-marginless">
|
|
||||||
<a href="<%= urlPrefix %>/lots"><%= configFunctions.getProperty("aliases.lots") %></a>
|
|
||||||
</h2>
|
|
||||||
<p>View and maintain <%= configFunctions.getProperty("aliases.lots").toLowerCase() %> within a <%= configFunctions.getProperty("aliases.map").toLowerCase() %>.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<i class="far fa-3x fa-fw fa-map" aria-hidden="true"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-content has-text-black">
|
|
||||||
<h2 class="title is-4 is-marginless">
|
|
||||||
<a href="<%= urlPrefix %>/maps"><%= configFunctions.getProperty("aliases.maps") %></a>
|
|
||||||
</h2>
|
|
||||||
<p>View and maintain <%= configFunctions.getProperty("aliases.maps").toLowerCase() %>.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="columns">
|
|
||||||
<div class="column">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<i class="fas fa-3x fa-fw fa-file" aria-hidden="true"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-content has-text-black">
|
|
||||||
<h2 class="title is-4 is-marginless">
|
|
||||||
<a href="<%= urlPrefix %>/reports">Report Library</a>
|
|
||||||
</h2>
|
|
||||||
<p>Produce reports and export data.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="column">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-content">
|
|
||||||
<div class="media">
|
|
||||||
<div class="media-left">
|
|
||||||
<i class="fas fa-3x fa-fw fa-question-circle" aria-hidden="true"></i>
|
|
||||||
</div>
|
|
||||||
<div class="media-content has-text-black">
|
|
||||||
<h2 class="title is-4 is-marginless">
|
|
||||||
<a href="https://cityssm.github.io/lot-occupancy-system/" target="_blank" rel="noopener noreferrer">Help Documentation</a>
|
|
||||||
</h2>
|
|
||||||
<p>Instructions on how to use this application.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a class="card-footer-item has-tooltip-bottom" data-tooltip="Latest Updates, Issue Tracker, Say Hello" href="https://github.com/cityssm/lot-occupancy-system" target="_blank" rel="noreferrer">
|
|
||||||
<span class="icon">
|
|
||||||
<i class="fab fa-github" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
GitHub
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<% if (false && user.userProperties.isAdmin) { %>
|
|
||||||
<h2 class="title is-3">Administrator Tools</h2>
|
|
||||||
|
|
||||||
<div class="columns">
|
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<div class="media">
|
<div class="media">
|
||||||
<div class="media-left">
|
<div class="media-left">
|
||||||
<i class="fas fa-3x fa-fw fa-cogs" aria-hidden="true"></i>
|
<span class="fa-layers fa-3x fa-fw" aria-hidden="true">
|
||||||
|
<i class="fas fa-vector-square"></i>
|
||||||
|
<i class="fas fa-user" data-fa-transform="shrink-10"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="media-content has-text-black">
|
||||||
|
<h2 class="title is-4 is-marginless">
|
||||||
|
<a href="<%= urlPrefix %>/lotOccupancies"><%= configFunctions.getProperty("aliases.lot") %>
|
||||||
|
<%= configFunctions.getProperty("aliases.occupancies") %></a>
|
||||||
|
</h2>
|
||||||
|
<p>View and maintain current and past
|
||||||
|
<%= configFunctions.getProperty("aliases.lot").toLowerCase() %>
|
||||||
|
<%= configFunctions.getProperty("aliases.occupancies").toLowerCase() %>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="media-content has-text-black">
|
<div class="card-content">
|
||||||
<h2 class="title is-4 is-marginless">
|
<div class="media">
|
||||||
<a href="<%= urlPrefix %>/admin/licenceCategories">Licence Categories</a>
|
<div class="media-left">
|
||||||
</h2>
|
<i class="fas fa-3x fa-fw fa-hard-hat" aria-hidden="true"></i>
|
||||||
<p>Add new licence types. Maintain existing licence types.</p>
|
</div>
|
||||||
|
<div class="media-content has-text-black">
|
||||||
|
<h2 class="title is-4 is-marginless">
|
||||||
|
<a href="<%= urlPrefix %>/workOrders">Work Orders</a>
|
||||||
|
</h2>
|
||||||
|
<p>View and maintain work orders.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<i class="fas fa-3x fa-fw fa-vector-square" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
<div class="media-content has-text-black">
|
||||||
|
<h2 class="title is-4 is-marginless">
|
||||||
|
<a href="<%= urlPrefix %>/lots"><%= configFunctions.getProperty("aliases.lots") %></a>
|
||||||
|
</h2>
|
||||||
|
<p>View and maintain <%= configFunctions.getProperty("aliases.lots").toLowerCase() %> within a
|
||||||
|
<%= configFunctions.getProperty("aliases.map").toLowerCase() %>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<i class="far fa-3x fa-fw fa-map" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
<div class="media-content has-text-black">
|
||||||
|
<h2 class="title is-4 is-marginless">
|
||||||
|
<a href="<%= urlPrefix %>/maps"><%= configFunctions.getProperty("aliases.maps") %></a>
|
||||||
|
</h2>
|
||||||
|
<p>View and maintain <%= configFunctions.getProperty("aliases.maps").toLowerCase() %>.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<i class="fas fa-3x fa-fw fa-file" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
<div class="media-content has-text-black">
|
||||||
|
<h2 class="title is-4 is-marginless">
|
||||||
|
<a href="<%= urlPrefix %>/reports">Report Library</a>
|
||||||
|
</h2>
|
||||||
|
<p>Produce reports and export data.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<i class="fas fa-3x fa-fw fa-question-circle" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
<div class="media-content has-text-black">
|
||||||
|
<h2 class="title is-4 is-marginless">
|
||||||
|
<a href="https://cityssm.github.io/lot-occupancy-system/" target="_blank"
|
||||||
|
rel="noopener noreferrer">Help Documentation</a>
|
||||||
|
</h2>
|
||||||
|
<p>Instructions on how to use this application.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<a class="card-footer-item has-tooltip-bottom" data-tooltip="Latest Updates, Issue Tracker, Say Hello"
|
||||||
|
href="https://github.com/cityssm/lot-occupancy-system" target="_blank" rel="noreferrer">
|
||||||
|
<span class="icon">
|
||||||
|
<i class="fab fa-github" aria-hidden="true"></i>
|
||||||
|
</span>
|
||||||
|
GitHub
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if (user.userProperties.isAdmin) { %>
|
||||||
|
<h2 class="title is-3">Administrator Tools</h2>
|
||||||
|
|
||||||
|
<div class="columns">
|
||||||
|
<div class="column">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-content">
|
||||||
|
<div class="media">
|
||||||
|
<div class="media-left">
|
||||||
|
<i class="fas fa-3x fa-fw fa-dollar-sign" aria-hidden="true"></i>
|
||||||
|
</div>
|
||||||
|
<div class="media-content has-text-black">
|
||||||
|
<h2 class="title is-4 is-marginless">
|
||||||
|
<a href="<%= urlPrefix %>/admin/fees">Fee Management</a>
|
||||||
|
</h2>
|
||||||
|
<p>
|
||||||
|
Manage fees for
|
||||||
|
<%= configFunctions.getProperty("aliases.lot").toLowerCase() %>
|
||||||
|
<%= configFunctions.getProperty("aliases.occupancy").toLowerCase() %>
|
||||||
|
and specific
|
||||||
|
<%= configFunctions.getProperty("aliases.lot").toLowerCase() %> types.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<%- include('_footerA'); -%>
|
<%- include('_footerA'); -%>
|
||||||
<%- include('_footerB'); -%>
|
<%- include('_footerB'); -%>
|
||||||
Loading…
Reference in New Issue