reduce work order milestone queries

deepsource-autofix-76c6eb20
Dan Gowans 2022-09-27 14:08:36 -04:00
parent 62a4506a49
commit d9666c3e2a
15 changed files with 276 additions and 279 deletions

View File

@ -14,23 +14,24 @@ export const handler = (request, response) => {
configFunctions.getProperty("reverseProxy.urlPrefix"); configFunctions.getProperty("reverseProxy.urlPrefix");
const workOrderMilestoneFilters = { const workOrderMilestoneFilters = {
workOrderTypeIds: request.query.workOrderTypeIds, workOrderTypeIds: request.query.workOrderTypeIds,
workOrderMilestoneTypeIds: request.query workOrderMilestoneTypeIds: request.query.workOrderMilestoneTypeIds
.workOrderMilestoneTypeIds
}; };
if (request.query.workOrderId) { if (request.query.workOrderId) {
workOrderMilestoneFilters.workOrderId = request.query workOrderMilestoneFilters.workOrderId = request.query.workOrderId;
.workOrderId;
} }
else { else {
workOrderMilestoneFilters.workOrderMilestoneDateFilter = "recent"; workOrderMilestoneFilters.workOrderMilestoneDateFilter = "recent";
} }
const workOrderMilestones = getWorkOrderMilestones(workOrderMilestoneFilters, { includeWorkOrders: true, orderBy: "date" }); const workOrderMilestones = getWorkOrderMilestones(workOrderMilestoneFilters, {
includeWorkOrders: true,
orderBy: "date"
});
const calendar = ical({ const calendar = ical({
name: "Work Order Milestone Calendar", name: "Work Order Milestone Calendar",
url: urlRoot + "/workOrders" url: urlRoot + "/workOrders"
}); });
if (request.query.workOrderId && workOrderMilestones.length > 0) { if (request.query.workOrderId && workOrderMilestones.length > 0) {
calendar.name("Work Order #" + workOrderMilestones[0].workOrder.workOrderNumber); calendar.name("Work Order #" + workOrderMilestones[0].workOrderNumber);
calendar.url(urlRoot + "/workOrders/" + workOrderMilestones[0].workOrderId); calendar.url(urlRoot + "/workOrders/" + workOrderMilestones[0].workOrderId);
} }
calendar.prodId({ calendar.prodId({
@ -42,13 +43,14 @@ export const handler = (request, response) => {
" " + " " +
milestone.workOrderMilestoneTimeString).split(timeStringSplitRegex); milestone.workOrderMilestoneTimeString).split(timeStringSplitRegex);
const milestoneDate = new Date(Number.parseInt(milestoneTimePieces[0], 10), Number.parseInt(milestoneTimePieces[1], 10) - 1, Number.parseInt(milestoneTimePieces[2], 10), Number.parseInt(milestoneTimePieces[3], 10), Number.parseInt(milestoneTimePieces[4], 10)); const milestoneDate = new Date(Number.parseInt(milestoneTimePieces[0], 10), Number.parseInt(milestoneTimePieces[1], 10) - 1, Number.parseInt(milestoneTimePieces[2], 10), Number.parseInt(milestoneTimePieces[3], 10), Number.parseInt(milestoneTimePieces[4], 10));
const milestoneEndDate = new Date(milestoneDate.getTime());
milestoneEndDate.setHours(milestoneEndDate.getHours() + 1);
let summary = (milestone.workOrderMilestoneTypeId let summary = (milestone.workOrderMilestoneTypeId
? milestone.workOrderMilestoneType ? milestone.workOrderMilestoneType
: milestone.workOrderMilestoneDescription).trim(); : milestone.workOrderMilestoneDescription).trim();
if (milestone.workOrder.workOrderLotOccupancies.length > 0) { if (milestone.workOrderLotOccupancies.length > 0) {
let occupantCount = 0; let occupantCount = 0;
for (const lotOccupancy of milestone.workOrder for (const lotOccupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
for (const occupant of lotOccupancy.lotOccupancyOccupants) { for (const occupant of lotOccupancy.lotOccupancyOccupants) {
occupantCount += 1; occupantCount += 1;
if (occupantCount === 1) { if (occupantCount === 1) {
@ -68,24 +70,25 @@ export const handler = (request, response) => {
start: milestoneDate, start: milestoneDate,
created: new Date(milestone.recordCreate_timeMillis), created: new Date(milestone.recordCreate_timeMillis),
stamp: new Date(milestone.recordCreate_timeMillis), stamp: new Date(milestone.recordCreate_timeMillis),
lastModified: new Date(Math.max(milestone.recordUpdate_timeMillis, milestone.workOrder.recordUpdate_timeMillis)), lastModified: new Date(Math.max(milestone.recordUpdate_timeMillis, milestone.workOrderRecordUpdate_timeMillis)),
allDay: !milestone.workOrderMilestoneTime, allDay: !milestone.workOrderMilestoneTime,
summary, summary,
url: workOrderURL url: workOrderURL
}; };
if (!eventData.allDay) {
eventData.end = milestoneEndDate;
}
const calendarEvent = calendar.createEvent(eventData); const calendarEvent = calendar.createEvent(eventData);
let descriptionHTML = "<h1>Milestone Description</h1>" + let descriptionHTML = "<h1>Milestone Description</h1>" +
"<p>" + "<p>" +
escapeHTML(milestone.workOrderMilestoneDescription) + escapeHTML(milestone.workOrderMilestoneDescription) +
"</p>" + "</p>" +
"<h2>Work Order #" + "<h2>Work Order #" +
milestone.workOrder.workOrderNumber + milestone.workOrderNumber +
"</h2>" + "</h2>" +
("<p>" + ("<p>" + escapeHTML(milestone.workOrderDescription) + "</p>") +
escapeHTML(milestone.workOrder.workOrderDescription) +
"</p>") +
('<p><a href="' + workOrderURL + '">' + workOrderURL + "</a></p>"); ('<p><a href="' + workOrderURL + '">' + workOrderURL + "</a></p>");
if (milestone.workOrder.workOrderLotOccupancies.length > 0) { if (milestone.workOrderLotOccupancies.length > 0) {
descriptionHTML += descriptionHTML +=
"<h2>Related " + "<h2>Related " +
escapeHTML(configFunctions.getProperty("aliases.occupancies")) + escapeHTML(configFunctions.getProperty("aliases.occupancies")) +
@ -94,18 +97,13 @@ export const handler = (request, response) => {
("<th>" + ("<th>" +
escapeHTML(configFunctions.getProperty("aliases.occupancy")) + escapeHTML(configFunctions.getProperty("aliases.occupancy")) +
" Type</th>") + " Type</th>") +
("<th>" + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.lot")) + "</th>") +
escapeHTML(configFunctions.getProperty("aliases.lot")) +
"</th>") +
"<th>Start Date</th>" + "<th>Start Date</th>" +
"<th>End Date</th>" + "<th>End Date</th>" +
("<th>" + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.occupants")) + "</th>") +
escapeHTML(configFunctions.getProperty("aliases.occupants")) +
"</th>") +
"</tr></thead>" + "</tr></thead>" +
"<tbody>"; "<tbody>";
for (const occupancy of milestone.workOrder for (const occupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
descriptionHTML += descriptionHTML +=
"<tr>" + "<tr>" +
("<td>" + ("<td>" +
@ -117,9 +115,7 @@ export const handler = (request, response) => {
escapeHTML(occupancy.occupancyType) + escapeHTML(occupancy.occupancyType) +
"</a></td>") + "</a></td>") +
("<td>" + ("<td>" +
(occupancy.lotName (occupancy.lotName ? escapeHTML(occupancy.lotName) : "(Not Set)") +
? escapeHTML(occupancy.lotName)
: "(Not Set)") +
"</td>") + "</td>") +
("<td>" + occupancy.occupancyStartDateString + "</td>") + ("<td>" + occupancy.occupancyStartDateString + "</td>") +
"<td>" + "<td>" +
@ -129,25 +125,20 @@ export const handler = (request, response) => {
"</td>" + "</td>" +
"<td>"; "<td>";
for (const occupant of occupancy.lotOccupancyOccupants) { for (const occupant of occupancy.lotOccupancyOccupants) {
descriptionHTML += descriptionHTML += escapeHTML(occupant.occupantName) + "<br />";
escapeHTML(occupant.occupantName) + "<br />";
} }
descriptionHTML += "</td>" + "</tr>"; descriptionHTML += "</td>" + "</tr>";
} }
descriptionHTML += "</tbody></table>"; descriptionHTML += "</tbody></table>";
} }
if (milestone.workOrder.workOrderLots.length > 0) { if (milestone.workOrderLots.length > 0) {
descriptionHTML += descriptionHTML +=
"<h2>Related " + "<h2>Related " +
escapeHTML(configFunctions.getProperty("aliases.lots")) + escapeHTML(configFunctions.getProperty("aliases.lots")) +
"</h2>" + "</h2>" +
'<table border="1"><thead><tr>' + '<table border="1"><thead><tr>' +
("<th>" + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type</th>") +
escapeHTML(configFunctions.getProperty("aliases.lot")) + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.map")) + "</th>") +
" Type</th>") +
("<th>" +
escapeHTML(configFunctions.getProperty("aliases.map")) +
"</th>") +
("<th>" + ("<th>" +
escapeHTML(configFunctions.getProperty("aliases.lot")) + escapeHTML(configFunctions.getProperty("aliases.lot")) +
" Type" + " Type" +
@ -155,7 +146,7 @@ export const handler = (request, response) => {
"<th>Status</th>" + "<th>Status</th>" +
"</tr></thead>" + "</tr></thead>" +
"<tbody>"; "<tbody>";
for (const lot of milestone.workOrder.workOrderLots) { for (const lot of milestone.workOrderLots) {
descriptionHTML += descriptionHTML +=
"<tr>" + "<tr>" +
("<td>" + ("<td>" +
@ -185,20 +176,19 @@ export const handler = (request, response) => {
name: milestone.workOrderMilestoneType name: milestone.workOrderMilestoneType
}); });
calendarEvent.createCategory({ calendarEvent.createCategory({
name: milestone.workOrder.workOrderType name: milestone.workOrderType
}); });
} }
if (milestone.workOrder.workOrderLots.length > 0) { if (milestone.workOrderLots.length > 0) {
const lotNames = []; const lotNames = [];
for (const lot of milestone.workOrder.workOrderLots) { for (const lot of milestone.workOrderLots) {
lotNames.push(lot.mapName + ": " + lot.lotName); lotNames.push(lot.mapName + ": " + lot.lotName);
} }
calendarEvent.location(lotNames.join(", ")); calendarEvent.location(lotNames.join(", "));
} }
if (milestone.workOrder.workOrderLotOccupancies.length > 0) { if (milestone.workOrderLotOccupancies.length > 0) {
let organizerSet = false; let organizerSet = false;
for (const lotOccupancy of milestone.workOrder for (const lotOccupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
for (const occupant of lotOccupancy.lotOccupancyOccupants) { for (const occupant of lotOccupancy.lotOccupancyOccupants) {
if (organizerSet) { if (organizerSet) {
calendarEvent.createAttendee({ calendarEvent.createAttendee({

View File

@ -14,10 +14,7 @@ import * as configFunctions from "../../helpers/functions.config.js";
const timeStringSplitRegex = /[ :-]/; const timeStringSplitRegex = /[ :-]/;
function escapeHTML(stringToEscape: string) { function escapeHTML(stringToEscape: string) {
return stringToEscape.replace( return stringToEscape.replace(/[^\d A-Za-z]/g, (c) => "&#" + c.codePointAt(0) + ";");
/[^\d A-Za-z]/g,
(c) => "&#" + c.codePointAt(0) + ";"
);
} }
export const handler: RequestHandler = (request, response) => { export const handler: RequestHandler = (request, response) => {
@ -31,21 +28,19 @@ export const handler: RequestHandler = (request, response) => {
const workOrderMilestoneFilters: WorkOrderMilestoneFilters = { const workOrderMilestoneFilters: WorkOrderMilestoneFilters = {
workOrderTypeIds: request.query.workOrderTypeIds as string, workOrderTypeIds: request.query.workOrderTypeIds as string,
workOrderMilestoneTypeIds: request.query workOrderMilestoneTypeIds: request.query.workOrderMilestoneTypeIds as string
.workOrderMilestoneTypeIds as string
}; };
if (request.query.workOrderId) { if (request.query.workOrderId) {
workOrderMilestoneFilters.workOrderId = request.query workOrderMilestoneFilters.workOrderId = request.query.workOrderId as string;
.workOrderId as string;
} else { } else {
workOrderMilestoneFilters.workOrderMilestoneDateFilter = "recent"; workOrderMilestoneFilters.workOrderMilestoneDateFilter = "recent";
} }
const workOrderMilestones = getWorkOrderMilestones( const workOrderMilestones = getWorkOrderMilestones(workOrderMilestoneFilters, {
workOrderMilestoneFilters, includeWorkOrders: true,
{ includeWorkOrders: true, orderBy: "date" } orderBy: "date"
); });
const calendar = ical({ const calendar = ical({
name: "Work Order Milestone Calendar", name: "Work Order Milestone Calendar",
@ -53,7 +48,7 @@ export const handler: RequestHandler = (request, response) => {
}); });
if (request.query.workOrderId && workOrderMilestones.length > 0) { if (request.query.workOrderId && workOrderMilestones.length > 0) {
calendar.name("Work Order #" + workOrderMilestones[0].workOrder.workOrderNumber); calendar.name("Work Order #" + workOrderMilestones[0].workOrderNumber);
calendar.url(urlRoot + "/workOrders/" + workOrderMilestones[0].workOrderId); calendar.url(urlRoot + "/workOrders/" + workOrderMilestones[0].workOrderId);
} }
@ -77,6 +72,9 @@ export const handler: RequestHandler = (request, response) => {
Number.parseInt(milestoneTimePieces[4], 10) Number.parseInt(milestoneTimePieces[4], 10)
); );
const milestoneEndDate = new Date(milestoneDate.getTime());
milestoneEndDate.setHours(milestoneEndDate.getHours() + 1);
// Build summary (title in Outlook) // Build summary (title in Outlook)
let summary = ( let summary = (
@ -85,11 +83,10 @@ export const handler: RequestHandler = (request, response) => {
: milestone.workOrderMilestoneDescription : milestone.workOrderMilestoneDescription
).trim(); ).trim();
if (milestone.workOrder.workOrderLotOccupancies.length > 0) { if (milestone.workOrderLotOccupancies.length > 0) {
let occupantCount = 0; let occupantCount = 0;
for (const lotOccupancy of milestone.workOrder for (const lotOccupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
for (const occupant of lotOccupancy.lotOccupancyOccupants) { for (const occupant of lotOccupancy.lotOccupancyOccupants) {
occupantCount += 1; occupantCount += 1;
@ -121,7 +118,7 @@ export const handler: RequestHandler = (request, response) => {
lastModified: new Date( lastModified: new Date(
Math.max( Math.max(
milestone.recordUpdate_timeMillis, milestone.recordUpdate_timeMillis,
milestone.workOrder.recordUpdate_timeMillis milestone.workOrderRecordUpdate_timeMillis
) )
), ),
allDay: !milestone.workOrderMilestoneTime, allDay: !milestone.workOrderMilestoneTime,
@ -129,6 +126,10 @@ export const handler: RequestHandler = (request, response) => {
url: workOrderURL url: workOrderURL
}; };
if (!eventData.allDay) {
eventData.end = milestoneEndDate;
}
const calendarEvent = calendar.createEvent(eventData); const calendarEvent = calendar.createEvent(eventData);
// Build description // Build description
@ -139,39 +140,28 @@ export const handler: RequestHandler = (request, response) => {
escapeHTML(milestone.workOrderMilestoneDescription) + escapeHTML(milestone.workOrderMilestoneDescription) +
"</p>" + "</p>" +
"<h2>Work Order #" + "<h2>Work Order #" +
milestone.workOrder.workOrderNumber + milestone.workOrderNumber +
"</h2>" + "</h2>" +
("<p>" + ("<p>" + escapeHTML(milestone.workOrderDescription) + "</p>") +
escapeHTML(milestone.workOrder.workOrderDescription) +
"</p>") +
('<p><a href="' + workOrderURL + '">' + workOrderURL + "</a></p>"); ('<p><a href="' + workOrderURL + '">' + workOrderURL + "</a></p>");
if (milestone.workOrder.workOrderLotOccupancies.length > 0) { if (milestone.workOrderLotOccupancies.length > 0) {
descriptionHTML += descriptionHTML +=
"<h2>Related " + "<h2>Related " +
escapeHTML(configFunctions.getProperty("aliases.occupancies")) + escapeHTML(configFunctions.getProperty("aliases.occupancies")) +
"</h2>" + "</h2>" +
'<table border="1"><thead><tr>' + '<table border="1"><thead><tr>' +
("<th>" + ("<th>" +
escapeHTML( escapeHTML(configFunctions.getProperty("aliases.occupancy")) +
configFunctions.getProperty("aliases.occupancy")
) +
" Type</th>") + " Type</th>") +
("<th>" + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.lot")) + "</th>") +
escapeHTML(configFunctions.getProperty("aliases.lot")) +
"</th>") +
"<th>Start Date</th>" + "<th>Start Date</th>" +
"<th>End Date</th>" + "<th>End Date</th>" +
("<th>" + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.occupants")) + "</th>") +
escapeHTML(
configFunctions.getProperty("aliases.occupants")
) +
"</th>") +
"</tr></thead>" + "</tr></thead>" +
"<tbody>"; "<tbody>";
for (const occupancy of milestone.workOrder for (const occupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
descriptionHTML += descriptionHTML +=
"<tr>" + "<tr>" +
("<td>" + ("<td>" +
@ -183,9 +173,7 @@ export const handler: RequestHandler = (request, response) => {
escapeHTML(occupancy.occupancyType) + escapeHTML(occupancy.occupancyType) +
"</a></td>") + "</a></td>") +
("<td>" + ("<td>" +
(occupancy.lotName (occupancy.lotName ? escapeHTML(occupancy.lotName) : "(Not Set)") +
? escapeHTML(occupancy.lotName)
: "(Not Set)") +
"</td>") + "</td>") +
("<td>" + occupancy.occupancyStartDateString + "</td>") + ("<td>" + occupancy.occupancyStartDateString + "</td>") +
"<td>" + "<td>" +
@ -196,8 +184,7 @@ export const handler: RequestHandler = (request, response) => {
"<td>"; "<td>";
for (const occupant of occupancy.lotOccupancyOccupants) { for (const occupant of occupancy.lotOccupancyOccupants) {
descriptionHTML += descriptionHTML += escapeHTML(occupant.occupantName) + "<br />";
escapeHTML(occupant.occupantName) + "<br />";
} }
descriptionHTML += "</td>" + "</tr>"; descriptionHTML += "</td>" + "</tr>";
@ -206,18 +193,14 @@ export const handler: RequestHandler = (request, response) => {
descriptionHTML += "</tbody></table>"; descriptionHTML += "</tbody></table>";
} }
if (milestone.workOrder.workOrderLots.length > 0) { if (milestone.workOrderLots.length > 0) {
descriptionHTML += descriptionHTML +=
"<h2>Related " + "<h2>Related " +
escapeHTML(configFunctions.getProperty("aliases.lots")) + escapeHTML(configFunctions.getProperty("aliases.lots")) +
"</h2>" + "</h2>" +
'<table border="1"><thead><tr>' + '<table border="1"><thead><tr>' +
("<th>" + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.lot")) + " Type</th>") +
escapeHTML(configFunctions.getProperty("aliases.lot")) + ("<th>" + escapeHTML(configFunctions.getProperty("aliases.map")) + "</th>") +
" Type</th>") +
("<th>" +
escapeHTML(configFunctions.getProperty("aliases.map")) +
"</th>") +
("<th>" + ("<th>" +
escapeHTML(configFunctions.getProperty("aliases.lot")) + escapeHTML(configFunctions.getProperty("aliases.lot")) +
" Type" + " Type" +
@ -226,7 +209,7 @@ export const handler: RequestHandler = (request, response) => {
"</tr></thead>" + "</tr></thead>" +
"<tbody>"; "<tbody>";
for (const lot of milestone.workOrder.workOrderLots) { for (const lot of milestone.workOrderLots) {
descriptionHTML += descriptionHTML +=
"<tr>" + "<tr>" +
("<td>" + ("<td>" +
@ -265,16 +248,16 @@ export const handler: RequestHandler = (request, response) => {
}); });
calendarEvent.createCategory({ calendarEvent.createCategory({
name: milestone.workOrder.workOrderType name: milestone.workOrderType
}); });
} }
// Set location // Set location
if (milestone.workOrder.workOrderLots.length > 0) { if (milestone.workOrderLots.length > 0) {
const lotNames = []; const lotNames = [];
for (const lot of milestone.workOrder.workOrderLots) { for (const lot of milestone.workOrderLots) {
lotNames.push(lot.mapName + ": " + lot.lotName); lotNames.push(lot.mapName + ": " + lot.lotName);
} }
@ -283,20 +266,23 @@ export const handler: RequestHandler = (request, response) => {
// Set organizer / attendees // Set organizer / attendees
if (milestone.workOrder.workOrderLotOccupancies.length > 0) { if (milestone.workOrderLotOccupancies.length > 0) {
let organizerSet = false; let organizerSet = false;
for (const lotOccupancy of milestone.workOrder for (const lotOccupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
for (const occupant of lotOccupancy.lotOccupancyOccupants) { for (const occupant of lotOccupancy.lotOccupancyOccupants) {
if (organizerSet) { if (organizerSet) {
calendarEvent.createAttendee({ calendarEvent.createAttendee({
name: occupant.occupantName, name: occupant.occupantName,
email: configFunctions.getProperty("settings.workOrders.calendarEmailAddress") email: configFunctions.getProperty(
"settings.workOrders.calendarEmailAddress"
)
}); });
} else { } else {
calendarEvent.organizer({ calendarEvent.organizer({
name: occupant.occupantName, name: occupant.occupantName,
email: configFunctions.getProperty("settings.workOrders.calendarEmailAddress") email: configFunctions.getProperty(
"settings.workOrders.calendarEmailAddress"
)
}); });
organizerSet = true; organizerSet = true;
} }

View File

@ -22,9 +22,7 @@ export const getLotOccupancies = (filters, options, connectedDatabase) => {
} }
} }
if (filters.occupantName) { if (filters.occupantName) {
const occupantNamePieces = filters.occupantName const occupantNamePieces = filters.occupantName.toLowerCase().split(" ");
.toLowerCase()
.split(" ");
for (const occupantNamePiece of occupantNamePieces) { for (const occupantNamePiece of occupantNamePieces) {
sqlWhereClause += sqlWhereClause +=
" and o.lotOccupancyId in (select oo.lotOccupancyId from LotOccupancyOccupants oo where oo.recordDelete_timeMillis is null and instr(lower(oo.occupantName), ?))"; " and o.lotOccupancyId in (select oo.lotOccupancyId from LotOccupancyOccupants oo where oo.recordDelete_timeMillis is null and instr(lower(oo.occupantName), ?))";
@ -80,14 +78,17 @@ export const getLotOccupancies = (filters, options, connectedDatabase) => {
" and o.lotOccupancyId not in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)"; " and o.lotOccupancyId not in (select lotOccupancyId from WorkOrderLotOccupancies where recordDelete_timeMillis is null and workOrderId = ?)";
sqlParameters.push(filters.notWorkOrderId); sqlParameters.push(filters.notWorkOrderId);
} }
const count = database let count;
.prepare("select count(*) as recordCount" + if (options.limit !== -1) {
" from LotOccupancies o" + count = database
" left join Lots l on o.lotId = l.lotId" + .prepare("select count(*) as recordCount" +
sqlWhereClause) " from LotOccupancies o" +
.get(sqlParameters).recordCount; " left join Lots l on o.lotId = l.lotId" +
sqlWhereClause)
.get(sqlParameters).recordCount;
}
let lotOccupancies = []; let lotOccupancies = [];
if (count > 0) { if (options.limit === -1 || count > 0) {
lotOccupancies = database lotOccupancies = database
.prepare("select o.lotOccupancyId," + .prepare("select o.lotOccupancyId," +
" o.occupancyTypeId, t.occupancyType," + " o.occupancyTypeId, t.occupancyType," +
@ -102,12 +103,12 @@ export const getLotOccupancies = (filters, options, connectedDatabase) => {
sqlWhereClause + sqlWhereClause +
" order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" + " order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" +
(options.limit !== -1 (options.limit !== -1
? " limit " + ? " limit " + options.limit + " offset " + options.offset
options.limit +
" offset " +
options.offset
: "")) : ""))
.all(sqlParameters); .all(sqlParameters);
if (options.limit === -1) {
count = lotOccupancies.length;
}
if (options.includeOccupants) { if (options.includeOccupants) {
for (const lotOccupancy of lotOccupancies) { for (const lotOccupancy of lotOccupancies) {
lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(lotOccupancy.lotOccupancyId, database); lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(lotOccupancy.lotOccupancyId, database);

View File

@ -65,9 +65,7 @@ export const getLotOccupancies = (
} }
if (filters.occupantName) { if (filters.occupantName) {
const occupantNamePieces = filters.occupantName const occupantNamePieces = filters.occupantName.toLowerCase().split(" ");
.toLowerCase()
.split(" ");
for (const occupantNamePiece of occupantNamePieces) { for (const occupantNamePiece of occupantNamePieces) {
sqlWhereClause += sqlWhereClause +=
" and o.lotOccupancyId in (select oo.lotOccupancyId from LotOccupancyOccupants oo where oo.recordDelete_timeMillis is null and instr(lower(oo.occupantName), ?))"; " and o.lotOccupancyId in (select oo.lotOccupancyId from LotOccupancyOccupants oo where oo.recordDelete_timeMillis is null and instr(lower(oo.occupantName), ?))";
@ -104,9 +102,7 @@ export const getLotOccupancies = (
if (filters.occupancyStartDateString) { if (filters.occupancyStartDateString) {
sqlWhereClause += " and o.occupancyStartDate = ?"; sqlWhereClause += " and o.occupancyStartDate = ?";
sqlParameters.push( sqlParameters.push(dateStringToInteger(filters.occupancyStartDateString));
dateStringToInteger(filters.occupancyStartDateString)
);
} }
if (filters.occupancyEffectiveDateString) { if (filters.occupancyEffectiveDateString) {
@ -140,18 +136,22 @@ export const getLotOccupancies = (
sqlParameters.push(filters.notWorkOrderId); sqlParameters.push(filters.notWorkOrderId);
} }
const count: number = database let count: number;
.prepare(
"select count(*) as recordCount" + if (options.limit !== -1) {
" from LotOccupancies o" + count = database
" left join Lots l on o.lotId = l.lotId" + .prepare(
sqlWhereClause "select count(*) as recordCount" +
) " from LotOccupancies o" +
.get(sqlParameters).recordCount; " left join Lots l on o.lotId = l.lotId" +
sqlWhereClause
)
.get(sqlParameters).recordCount;
}
let lotOccupancies: recordTypes.LotOccupancy[] = []; let lotOccupancies: recordTypes.LotOccupancy[] = [];
if (count > 0) { if (options.limit === -1 || count > 0) {
lotOccupancies = database lotOccupancies = database
.prepare( .prepare(
"select o.lotOccupancyId," + "select o.lotOccupancyId," +
@ -167,14 +167,15 @@ export const getLotOccupancies = (
sqlWhereClause + sqlWhereClause +
" order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" + " order by o.occupancyStartDate desc, ifnull(o.occupancyEndDate, 99999999) desc, l.lotName, o.lotId" +
(options.limit !== -1 (options.limit !== -1
? " limit " + ? " limit " + options.limit + " offset " + options.offset
options.limit +
" offset " +
options.offset
: "") : "")
) )
.all(sqlParameters); .all(sqlParameters);
if (options.limit === -1) {
count = lotOccupancies.length;
}
if (options.includeOccupants) { if (options.includeOccupants) {
for (const lotOccupancy of lotOccupancies) { for (const lotOccupancy of lotOccupancies) {
lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants( lotOccupancy.lotOccupancyOccupants = getLotOccupancyOccupants(

View File

@ -9,7 +9,7 @@ interface GetLotsFilters {
workOrderId?: number | string; workOrderId?: number | string;
} }
interface GetLotsOptions { interface GetLotsOptions {
limit: number; limit: -1 | number;
offset: number; offset: number;
} }
export declare const getLots: (filters: GetLotsFilters, options: GetLotsOptions, connectedDatabase?: sqlite.Database) => { export declare const getLots: (filters: GetLotsFilters, options: GetLotsOptions, connectedDatabase?: sqlite.Database) => {

View File

@ -43,24 +43,27 @@ export const getLots = (filters, options, connectedDatabase) => {
sqlParameters.push(filters.workOrderId); sqlParameters.push(filters.workOrderId);
} }
const currentDate = dateToInteger(new Date()); const currentDate = dateToInteger(new Date());
const count = database let count;
.prepare("select count(*) as recordCount" + if (options.limit !== -1) {
" from Lots l" + count = database
(" left join (" + .prepare("select count(*) as recordCount" +
"select lotId, count(lotOccupancyId) as lotOccupancyCount" + " from Lots l" +
" from LotOccupancies" + (" left join (" +
" where recordDelete_timeMillis is null" + "select lotId, count(lotOccupancyId) as lotOccupancyCount" +
" and occupancyStartDate <= " + " from LotOccupancies" +
currentDate + " where recordDelete_timeMillis is null" +
" and (occupancyEndDate is null or occupancyEndDate >= " + " and occupancyStartDate <= " +
currentDate + currentDate +
")" + " and (occupancyEndDate is null or occupancyEndDate >= " +
" group by lotId" + currentDate +
") o on l.lotId = o.lotId") + ")" +
sqlWhereClause) " group by lotId" +
.get(sqlParameters).recordCount; ") o on l.lotId = o.lotId") +
sqlWhereClause)
.get(sqlParameters).recordCount;
}
let lots = []; let lots = [];
if (count > 0) { if (options.limit === -1 || count > 0) {
database.function("userFn_lotNameSortName", configFunctions.getProperty("settings.lot.lotNameSortNameFunction")); database.function("userFn_lotNameSortName", configFunctions.getProperty("settings.lot.lotNameSortNameFunction"));
lots = database lots = database
.prepare("select l.lotId, l.lotName," + .prepare("select l.lotId, l.lotName," +
@ -92,6 +95,9 @@ export const getLots = (filters, options, connectedDatabase) => {
options.offset options.offset
: "")) : ""))
.all(sqlParameters); .all(sqlParameters);
if (options.limit === -1) {
count = lots.length;
}
} }
if (!connectedDatabase) { if (!connectedDatabase) {
database.close(); database.close();

View File

@ -18,7 +18,7 @@ interface GetLotsFilters {
} }
interface GetLotsOptions { interface GetLotsOptions {
limit: number; limit: -1 | number;
offset: number; offset: number;
} }
@ -79,7 +79,10 @@ export const getLots = (
const currentDate = dateToInteger(new Date()); const currentDate = dateToInteger(new Date());
const count: number = database let count: number;
if (options.limit !== -1) {
count = database
.prepare( .prepare(
"select count(*) as recordCount" + "select count(*) as recordCount" +
" from Lots l" + " from Lots l" +
@ -97,10 +100,11 @@ export const getLots = (
sqlWhereClause sqlWhereClause
) )
.get(sqlParameters).recordCount; .get(sqlParameters).recordCount;
}
let lots: recordTypes.Lot[] = []; let lots: recordTypes.Lot[] = [];
if (count > 0) { if (options.limit === -1 || count > 0) {
database.function( database.function(
"userFn_lotNameSortName", "userFn_lotNameSortName",
configFunctions.getProperty("settings.lot.lotNameSortNameFunction") configFunctions.getProperty("settings.lot.lotNameSortNameFunction")
@ -138,6 +142,10 @@ export const getLots = (
: "") : "")
) )
.all(sqlParameters); .all(sqlParameters);
if (options.limit === -1) {
count = lots.length;
}
} }
if (!connectedDatabase) { if (!connectedDatabase) {

View File

@ -1,8 +1,9 @@
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 { getWorkOrder } from "./getWorkOrder.js";
import { dateIntegerToString, dateStringToInteger, dateToInteger, timeIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js"; import { dateIntegerToString, dateStringToInteger, dateToInteger, timeIntegerToString } from "@cityssm/expressjs-server-js/dateTimeFns.js";
import * as configFunctions from "../functions.config.js"; import * as configFunctions from "../functions.config.js";
import { getLots } from "./getLots.js";
import { getLotOccupancies } from "./getLotOccupancies.js";
const commaSeparatedNumbersRegex = /^\d+(,\d+)*$/; const commaSeparatedNumbersRegex = /^\d+(,\d+)*$/;
export const getWorkOrderMilestones = (filters, options, connectedDatabase) => { export const getWorkOrderMilestones = (filters, options, connectedDatabase) => {
const database = connectedDatabase || const database = connectedDatabase ||
@ -42,17 +43,13 @@ export const getWorkOrderMilestones = (filters, options, connectedDatabase) => {
sqlWhereClause += " and m.workOrderMilestoneDate = ?"; sqlWhereClause += " and m.workOrderMilestoneDate = ?";
sqlParameters.push(dateStringToInteger(filters.workOrderMilestoneDateString)); sqlParameters.push(dateStringToInteger(filters.workOrderMilestoneDateString));
} }
if (filters.workOrderTypeIds && if (filters.workOrderTypeIds && commaSeparatedNumbersRegex.test(filters.workOrderTypeIds)) {
commaSeparatedNumbersRegex.test(filters.workOrderTypeIds)) { sqlWhereClause += " and w.workOrderTypeId in (" + filters.workOrderTypeIds + ")";
sqlWhereClause +=
" and w.workOrderTypeId in (" + filters.workOrderTypeIds + ")";
} }
if (filters.workOrderMilestoneTypeIds && if (filters.workOrderMilestoneTypeIds &&
commaSeparatedNumbersRegex.test(filters.workOrderMilestoneTypeIds)) { commaSeparatedNumbersRegex.test(filters.workOrderMilestoneTypeIds)) {
sqlWhereClause += sqlWhereClause +=
" and m.workOrderMilestoneTypeId in (" + " and m.workOrderMilestoneTypeId in (" + filters.workOrderMilestoneTypeIds + ")";
filters.workOrderMilestoneTypeIds +
")";
} }
let orderByClause = ""; let orderByClause = "";
switch (options.orderBy) { switch (options.orderBy) {
@ -68,29 +65,45 @@ export const getWorkOrderMilestones = (filters, options, connectedDatabase) => {
" order by m.workOrderMilestoneDate, case when m.workOrderMilestoneTime = 0 then 9999 else m.workOrderMilestoneTime end," + " order by m.workOrderMilestoneDate, case when m.workOrderMilestoneTime = 0 then 9999 else m.workOrderMilestoneTime end," +
" t.orderNumber, m.workOrderId, m.workOrderMilestoneId"; " t.orderNumber, m.workOrderId, m.workOrderMilestoneId";
} }
const workOrderMilestones = database const sql = "select m.workOrderMilestoneId," +
.prepare("select m.workOrderId, m.workOrderMilestoneId," +
" m.workOrderMilestoneTypeId, t.workOrderMilestoneType," + " m.workOrderMilestoneTypeId, t.workOrderMilestoneType," +
" m.workOrderMilestoneDate, userFn_dateIntegerToString(m.workOrderMilestoneDate) as workOrderMilestoneDateString," + " m.workOrderMilestoneDate, userFn_dateIntegerToString(m.workOrderMilestoneDate) as workOrderMilestoneDateString," +
" m.workOrderMilestoneTime, userFn_timeIntegerToString(m.workOrderMilestoneTime) as workOrderMilestoneTimeString," + " m.workOrderMilestoneTime, userFn_timeIntegerToString(m.workOrderMilestoneTime) as workOrderMilestoneTimeString," +
" m.workOrderMilestoneDescription," + " m.workOrderMilestoneDescription," +
" m.workOrderMilestoneCompletionDate, userFn_dateIntegerToString(m.workOrderMilestoneCompletionDate) as workOrderMilestoneCompletionDateString," + " m.workOrderMilestoneCompletionDate, userFn_dateIntegerToString(m.workOrderMilestoneCompletionDate) as workOrderMilestoneCompletionDateString," +
" m.workOrderMilestoneCompletionTime, userFn_timeIntegerToString(m.workOrderMilestoneCompletionTime) as workOrderMilestoneCompletionTimeString," + " m.workOrderMilestoneCompletionTime, userFn_timeIntegerToString(m.workOrderMilestoneCompletionTime) as workOrderMilestoneCompletionTimeString," +
(options.includeWorkOrders
? " m.workOrderId, w.workOrderNumber, wt.workOrderType, w.workOrderDescription," +
" w.workOrderOpenDate, userFn_dateIntegerToString(w.workOrderOpenDate) as workOrderOpenDateString," +
" w.workOrderCloseDate, userFn_dateIntegerToString(w.workOrderCloseDate) as workOrderCloseDateString," +
" w.recordUpdate_timeMillis as workOrderRecordUpdate_timeMillis,"
: "") +
" m.recordCreate_userName, m.recordCreate_timeMillis," + " m.recordCreate_userName, m.recordCreate_timeMillis," +
" m.recordUpdate_userName, m.recordUpdate_timeMillis" + " m.recordUpdate_userName, m.recordUpdate_timeMillis" +
" from WorkOrderMilestones m" + " from WorkOrderMilestones m" +
" left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId" + " left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId" +
" left join WorkOrders w on m.workOrderId = w.workOrderId" + " left join WorkOrders w on m.workOrderId = w.workOrderId" +
" left join WorkOrderTypes wt on w.workOrderTypeId = wt.workOrderTypeId" +
sqlWhereClause + sqlWhereClause +
orderByClause) orderByClause;
const workOrderMilestones = database
.prepare(sql)
.all(sqlParameters); .all(sqlParameters);
if (options.includeWorkOrders) { if (options.includeWorkOrders) {
for (const workOrderMilestone of workOrderMilestones) { for (const workOrderMilestone of workOrderMilestones) {
workOrderMilestone.workOrder = getWorkOrder(workOrderMilestone.workOrderId, { workOrderMilestone.workOrderLots = getLots({
includeLotsAndLotOccupancies: true, workOrderId: workOrderMilestone.workOrderId
includeComments: false, }, {
includeMilestones: false limit: -1,
}, database); offset: 0
}, database).lots;
workOrderMilestone.workOrderLotOccupancies = getLotOccupancies({
workOrderId: workOrderMilestone.workOrderId
}, {
limit: -1,
offset: 0,
includeOccupants: true
}, database).lotOccupancies;
} }
} }
if (!connectedDatabase) { if (!connectedDatabase) {

View File

@ -2,8 +2,6 @@ import sqlite from "better-sqlite3";
import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js"; import { lotOccupancyDB as databasePath } from "../../data/databasePaths.js";
import { getWorkOrder } from "./getWorkOrder.js";
import { import {
dateIntegerToString, dateIntegerToString,
dateStringToInteger, dateStringToInteger,
@ -13,6 +11,9 @@ import {
import * as configFunctions from "../functions.config.js"; import * as configFunctions from "../functions.config.js";
import { getLots } from "./getLots.js";
import { getLotOccupancies } from "./getLotOccupancies.js";
import type * as recordTypes from "../../types/recordTypes"; import type * as recordTypes from "../../types/recordTypes";
export interface WorkOrderMilestoneFilters { export interface WorkOrderMilestoneFilters {
@ -46,7 +47,8 @@ export const getWorkOrderMilestones = (
// Filters // Filters
let sqlWhereClause = " where m.recordDelete_timeMillis is null and w.recordDelete_timeMillis is null"; let sqlWhereClause =
" where m.recordDelete_timeMillis is null and w.recordDelete_timeMillis is null";
const sqlParameters = []; const sqlParameters = [];
if (filters.workOrderId) { if (filters.workOrderId) {
@ -71,9 +73,7 @@ export const getWorkOrderMilestones = (
configFunctions.getProperty( configFunctions.getProperty(
"settings.workOrders.workOrderMilestoneDateRecentBeforeDays" "settings.workOrders.workOrderMilestoneDateRecentBeforeDays"
) + ) +
configFunctions.getProperty( configFunctions.getProperty("settings.workOrders.workOrderMilestoneDateRecentAfterDays")
"settings.workOrders.workOrderMilestoneDateRecentAfterDays"
)
); );
const recentAfterDateNumber = dateToInteger(date); const recentAfterDateNumber = dateToInteger(date);
@ -94,17 +94,11 @@ export const getWorkOrderMilestones = (
if (filters.workOrderMilestoneDateString) { if (filters.workOrderMilestoneDateString) {
sqlWhereClause += " and m.workOrderMilestoneDate = ?"; sqlWhereClause += " and m.workOrderMilestoneDate = ?";
sqlParameters.push( sqlParameters.push(dateStringToInteger(filters.workOrderMilestoneDateString));
dateStringToInteger(filters.workOrderMilestoneDateString)
);
} }
if ( if (filters.workOrderTypeIds && commaSeparatedNumbersRegex.test(filters.workOrderTypeIds)) {
filters.workOrderTypeIds && sqlWhereClause += " and w.workOrderTypeId in (" + filters.workOrderTypeIds + ")";
commaSeparatedNumbersRegex.test(filters.workOrderTypeIds)
) {
sqlWhereClause +=
" and w.workOrderTypeId in (" + filters.workOrderTypeIds + ")";
} }
if ( if (
@ -112,9 +106,7 @@ export const getWorkOrderMilestones = (
commaSeparatedNumbersRegex.test(filters.workOrderMilestoneTypeIds) commaSeparatedNumbersRegex.test(filters.workOrderMilestoneTypeIds)
) { ) {
sqlWhereClause += sqlWhereClause +=
" and m.workOrderMilestoneTypeId in (" + " and m.workOrderMilestoneTypeId in (" + filters.workOrderMilestoneTypeIds + ")";
filters.workOrderMilestoneTypeIds +
")";
} }
// Order By // Order By
@ -138,36 +130,57 @@ export const getWorkOrderMilestones = (
// Query // Query
const sql =
"select m.workOrderMilestoneId," +
" m.workOrderMilestoneTypeId, t.workOrderMilestoneType," +
" m.workOrderMilestoneDate, userFn_dateIntegerToString(m.workOrderMilestoneDate) as workOrderMilestoneDateString," +
" m.workOrderMilestoneTime, userFn_timeIntegerToString(m.workOrderMilestoneTime) as workOrderMilestoneTimeString," +
" m.workOrderMilestoneDescription," +
" m.workOrderMilestoneCompletionDate, userFn_dateIntegerToString(m.workOrderMilestoneCompletionDate) as workOrderMilestoneCompletionDateString," +
" m.workOrderMilestoneCompletionTime, userFn_timeIntegerToString(m.workOrderMilestoneCompletionTime) as workOrderMilestoneCompletionTimeString," +
(options.includeWorkOrders
? " m.workOrderId, w.workOrderNumber, wt.workOrderType, w.workOrderDescription," +
" w.workOrderOpenDate, userFn_dateIntegerToString(w.workOrderOpenDate) as workOrderOpenDateString," +
" w.workOrderCloseDate, userFn_dateIntegerToString(w.workOrderCloseDate) as workOrderCloseDateString," +
" w.recordUpdate_timeMillis as workOrderRecordUpdate_timeMillis,"
: "") +
" m.recordCreate_userName, m.recordCreate_timeMillis," +
" m.recordUpdate_userName, m.recordUpdate_timeMillis" +
" from WorkOrderMilestones m" +
" left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId" +
" left join WorkOrders w on m.workOrderId = w.workOrderId" +
" left join WorkOrderTypes wt on w.workOrderTypeId = wt.workOrderTypeId" +
sqlWhereClause +
orderByClause;
const workOrderMilestones: recordTypes.WorkOrderMilestone[] = database const workOrderMilestones: recordTypes.WorkOrderMilestone[] = database
.prepare( .prepare(sql)
"select m.workOrderId, m.workOrderMilestoneId," +
" m.workOrderMilestoneTypeId, t.workOrderMilestoneType," +
" m.workOrderMilestoneDate, userFn_dateIntegerToString(m.workOrderMilestoneDate) as workOrderMilestoneDateString," +
" m.workOrderMilestoneTime, userFn_timeIntegerToString(m.workOrderMilestoneTime) as workOrderMilestoneTimeString," +
" m.workOrderMilestoneDescription," +
" m.workOrderMilestoneCompletionDate, userFn_dateIntegerToString(m.workOrderMilestoneCompletionDate) as workOrderMilestoneCompletionDateString," +
" m.workOrderMilestoneCompletionTime, userFn_timeIntegerToString(m.workOrderMilestoneCompletionTime) as workOrderMilestoneCompletionTimeString," +
" m.recordCreate_userName, m.recordCreate_timeMillis," +
" m.recordUpdate_userName, m.recordUpdate_timeMillis" +
" from WorkOrderMilestones m" +
" left join WorkOrderMilestoneTypes t on m.workOrderMilestoneTypeId = t.workOrderMilestoneTypeId" +
" left join WorkOrders w on m.workOrderId = w.workOrderId" +
sqlWhereClause +
orderByClause
)
.all(sqlParameters); .all(sqlParameters);
if (options.includeWorkOrders) { if (options.includeWorkOrders) {
for (const workOrderMilestone of workOrderMilestones) { for (const workOrderMilestone of workOrderMilestones) {
workOrderMilestone.workOrder = getWorkOrder( workOrderMilestone.workOrderLots = getLots(
workOrderMilestone.workOrderId,
{ {
includeLotsAndLotOccupancies: true, workOrderId: workOrderMilestone.workOrderId
includeComments: false, },
includeMilestones: false {
limit: -1,
offset: 0
}, },
database database
); ).lots;
workOrderMilestone.workOrderLotOccupancies = getLotOccupancies(
{
workOrderId: workOrderMilestone.workOrderId
},
{
limit: -1,
offset: 0,
includeOccupants: true
},
database
).lotOccupancies;
} }
} }

View File

@ -16,7 +16,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
return; return;
} }
milestoneCalendarContainerElement.innerHTML = ""; milestoneCalendarContainerElement.innerHTML = "";
let currentDate = cityssm.dateToString(new Date()); const currentDate = cityssm.dateToString(new Date());
let currentPanelElement; let currentPanelElement;
let currentPanelDateString = ""; let currentPanelDateString = "";
for (const milestone of workOrderMilestones) { for (const milestone of workOrderMilestones) {
@ -27,18 +27,17 @@ Object.defineProperty(exports, "__esModule", { value: true });
currentPanelElement = document.createElement("div"); currentPanelElement = document.createElement("div");
currentPanelElement.className = "panel"; currentPanelElement.className = "panel";
currentPanelElement.innerHTML = currentPanelElement.innerHTML =
'<h2 class="panel-heading">' + '<h2 class="panel-heading">' + milestone.workOrderMilestoneDateString + "</h2>";
milestone.workOrderMilestoneDateString +
"</h2>";
currentPanelDateString = milestone.workOrderMilestoneDateString; currentPanelDateString = milestone.workOrderMilestoneDateString;
} }
const panelBlockElement = document.createElement("div"); const panelBlockElement = document.createElement("div");
panelBlockElement.className = "panel-block is-block"; panelBlockElement.className = "panel-block is-block";
if (!milestone.workOrderMilestoneCompletionDate && milestone.workOrderMilestoneDateString < currentDate) { if (!milestone.workOrderMilestoneCompletionDate &&
milestone.workOrderMilestoneDateString < currentDate) {
panelBlockElement.classList.add("has-background-warning-light"); panelBlockElement.classList.add("has-background-warning-light");
} }
let lotOccupancyHTML = ""; let lotOccupancyHTML = "";
for (const lot of milestone.workOrder.workOrderLots) { for (const lot of milestone.workOrderLots) {
lotOccupancyHTML += lotOccupancyHTML +=
'<i class="fas fa-vector-square" aria-label="' + '<i class="fas fa-vector-square" aria-label="' +
cityssm.escapeHTML(exports.aliases.lot) + cityssm.escapeHTML(exports.aliases.lot) +
@ -46,8 +45,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
cityssm.escapeHTML(lot.lotName) + cityssm.escapeHTML(lot.lotName) +
"<br />"; "<br />";
} }
for (const lotOccupancy of milestone.workOrder for (const lotOccupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
if (lotOccupancy.lotOccupancyOccupants.length > 0) { if (lotOccupancy.lotOccupancyOccupants.length > 0) {
lotOccupancyHTML += lotOccupancyHTML +=
'<i class="fas fa-user" aria-label="' + '<i class="fas fa-user" aria-label="' +
@ -80,21 +78,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
"</span>" + "</span>" +
"</div>") + "</div>") +
('<div class="column">' + ('<div class="column">' +
"<i class=\"fas fa-circle\" style=\"color:" + los.getRandomColor(milestone.workOrder.workOrderNumber) + "\" aria-hidden=\"true\"></i>" + '<i class="fas fa-circle" style="color:' +
los.getRandomColor(milestone.workOrderNumber) +
'" aria-hidden="true"></i>' +
' <a class="has-text-weight-bold" href="' + ' <a class="has-text-weight-bold" href="' +
urlPrefix + urlPrefix +
"/workOrders/" + "/workOrders/" +
milestone.workOrderId + milestone.workOrderId +
'">' + '">' +
cityssm.escapeHTML(milestone.workOrder.workOrderNumber) + cityssm.escapeHTML(milestone.workOrderNumber) +
"</a><br />" + "</a><br />" +
'<span class="is-size-7">' + '<span class="is-size-7">' +
cityssm.escapeHTML(milestone.workOrder.workOrderDescription) + cityssm.escapeHTML(milestone.workOrderDescription) +
"</span>" + "</span>" +
"</div>") + "</div>") +
('<div class="column is-size-7">' + ('<div class="column is-size-7">' + lotOccupancyHTML + "</div>") +
lotOccupancyHTML +
"</div>") +
"</div>"; "</div>";
currentPanelElement.append(panelBlockElement); currentPanelElement.append(panelBlockElement);
} }

View File

@ -15,23 +15,19 @@ declare const cityssm: cityssmGlobal;
"#form--searchFilters" "#form--searchFilters"
) as HTMLFormElement; ) as HTMLFormElement;
const workOrderMilestoneDateFilterElement = const workOrderMilestoneDateFilterElement = workOrderSearchFiltersFormElement.querySelector(
workOrderSearchFiltersFormElement.querySelector( "#searchFilter--workOrderMilestoneDateFilter"
"#searchFilter--workOrderMilestoneDateFilter" ) as HTMLSelectElement;
) as HTMLSelectElement;
const workOrderMilestoneDateStringElement = const workOrderMilestoneDateStringElement = workOrderSearchFiltersFormElement.querySelector(
workOrderSearchFiltersFormElement.querySelector( "#searchFilter--workOrderMilestoneDateString"
"#searchFilter--workOrderMilestoneDateString" ) as HTMLInputElement;
) as HTMLInputElement;
const milestoneCalendarContainerElement = document.querySelector( const milestoneCalendarContainerElement = document.querySelector(
"#container--milestoneCalendar" "#container--milestoneCalendar"
) as HTMLElement; ) as HTMLElement;
const renderMilestones = ( const renderMilestones = (workOrderMilestones: recordTypes.WorkOrderMilestone[]) => {
workOrderMilestones: recordTypes.WorkOrderMilestone[]
) => {
if (workOrderMilestones.length === 0) { if (workOrderMilestones.length === 0) {
milestoneCalendarContainerElement.innerHTML = milestoneCalendarContainerElement.innerHTML =
'<div class="message is-info">' + '<div class="message is-info">' +
@ -42,7 +38,7 @@ declare const cityssm: cityssmGlobal;
milestoneCalendarContainerElement.innerHTML = ""; milestoneCalendarContainerElement.innerHTML = "";
let currentDate = cityssm.dateToString(new Date()); const currentDate = cityssm.dateToString(new Date());
let currentPanelElement: HTMLElement; let currentPanelElement: HTMLElement;
let currentPanelDateString = ""; let currentPanelDateString = "";
@ -50,33 +46,32 @@ declare const cityssm: cityssmGlobal;
for (const milestone of workOrderMilestones) { for (const milestone of workOrderMilestones) {
if (currentPanelDateString !== milestone.workOrderMilestoneDateString) { if (currentPanelDateString !== milestone.workOrderMilestoneDateString) {
if (currentPanelElement) { if (currentPanelElement) {
milestoneCalendarContainerElement.append( milestoneCalendarContainerElement.append(currentPanelElement);
currentPanelElement
);
} }
currentPanelElement = document.createElement("div"); currentPanelElement = document.createElement("div");
currentPanelElement.className = "panel"; currentPanelElement.className = "panel";
currentPanelElement.innerHTML = currentPanelElement.innerHTML =
'<h2 class="panel-heading">' + '<h2 class="panel-heading">' + milestone.workOrderMilestoneDateString + "</h2>";
milestone.workOrderMilestoneDateString +
"</h2>";
currentPanelDateString = milestone.workOrderMilestoneDateString; currentPanelDateString = milestone.workOrderMilestoneDateString;
} }
const panelBlockElement = document.createElement("div"); const panelBlockElement = document.createElement("div");
panelBlockElement.className = "panel-block is-block"; panelBlockElement.className = "panel-block is-block";
if (!milestone.workOrderMilestoneCompletionDate && milestone.workOrderMilestoneDateString < currentDate) { if (
!milestone.workOrderMilestoneCompletionDate &&
milestone.workOrderMilestoneDateString < currentDate
) {
panelBlockElement.classList.add("has-background-warning-light"); panelBlockElement.classList.add("has-background-warning-light");
} }
let lotOccupancyHTML = ""; let lotOccupancyHTML = "";
for (const lot of milestone.workOrder.workOrderLots) { for (const lot of milestone.workOrderLots) {
lotOccupancyHTML += lotOccupancyHTML +=
'<i class="fas fa-vector-square" aria-label="' + '<i class="fas fa-vector-square" aria-label="' +
cityssm.escapeHTML(exports.aliases.lot) + cityssm.escapeHTML(exports.aliases.lot) +
@ -85,16 +80,13 @@ declare const cityssm: cityssmGlobal;
"<br />"; "<br />";
} }
for (const lotOccupancy of milestone.workOrder for (const lotOccupancy of milestone.workOrderLotOccupancies) {
.workOrderLotOccupancies) {
if (lotOccupancy.lotOccupancyOccupants.length > 0) { if (lotOccupancy.lotOccupancyOccupants.length > 0) {
lotOccupancyHTML += lotOccupancyHTML +=
'<i class="fas fa-user" aria-label="' + '<i class="fas fa-user" aria-label="' +
cityssm.escapeHTML(exports.aliases.lotOccupancy) + cityssm.escapeHTML(exports.aliases.lotOccupancy) +
'"></i> ' + '"></i> ' +
cityssm.escapeHTML( cityssm.escapeHTML(lotOccupancy.lotOccupancyOccupants[0].occupantName) +
lotOccupancy.lotOccupancyOccupants[0].occupantName
) +
"<br />"; "<br />";
} }
} }
@ -118,29 +110,25 @@ declare const cityssm: cityssmGlobal;
"</strong><br />" "</strong><br />"
: "") + : "") +
'<span class="is-size-7">' + '<span class="is-size-7">' +
cityssm.escapeHTML( cityssm.escapeHTML(milestone.workOrderMilestoneDescription) +
milestone.workOrderMilestoneDescription
) +
"</span>" + "</span>" +
"</div>") + "</div>") +
('<div class="column">' + ('<div class="column">' +
"<i class=\"fas fa-circle\" style=\"color:" + los.getRandomColor(milestone.workOrder.workOrderNumber) + "\" aria-hidden=\"true\"></i>" + '<i class="fas fa-circle" style="color:' +
los.getRandomColor(milestone.workOrderNumber) +
'" aria-hidden="true"></i>' +
' <a class="has-text-weight-bold" href="' + ' <a class="has-text-weight-bold" href="' +
urlPrefix + urlPrefix +
"/workOrders/" + "/workOrders/" +
milestone.workOrderId + milestone.workOrderId +
'">' + '">' +
cityssm.escapeHTML(milestone.workOrder.workOrderNumber) + cityssm.escapeHTML(milestone.workOrderNumber) +
"</a><br />" + "</a><br />" +
'<span class="is-size-7">' + '<span class="is-size-7">' +
cityssm.escapeHTML( cityssm.escapeHTML(milestone.workOrderDescription) +
milestone.workOrder.workOrderDescription
) +
"</span>" + "</span>" +
"</div>") + "</div>") +
('<div class="column is-size-7">' + ('<div class="column is-size-7">' + lotOccupancyHTML + "</div>") +
lotOccupancyHTML +
"</div>") +
"</div>"; "</div>";
currentPanelElement.append(panelBlockElement); currentPanelElement.append(panelBlockElement);
@ -163,9 +151,7 @@ declare const cityssm: cityssmGlobal;
cityssm.postJSON( cityssm.postJSON(
urlPrefix + "/workOrders/doGetWorkOrderMilestones", urlPrefix + "/workOrders/doGetWorkOrderMilestones",
workOrderSearchFiltersFormElement, workOrderSearchFiltersFormElement,
(responseJSON: { (responseJSON: { workOrderMilestones: recordTypes.WorkOrderMilestone[] }) => {
workOrderMilestones: recordTypes.WorkOrderMilestone[];
}) => {
renderMilestones(responseJSON.workOrderMilestones); renderMilestones(responseJSON.workOrderMilestones);
} }
); );
@ -177,10 +163,7 @@ declare const cityssm: cityssmGlobal;
getMilestones(); getMilestones();
}); });
workOrderMilestoneDateStringElement.addEventListener( workOrderMilestoneDateStringElement.addEventListener("change", getMilestones);
"change",
getMilestones
);
workOrderSearchFiltersFormElement.addEventListener("submit", getMilestones); workOrderSearchFiltersFormElement.addEventListener("submit", getMilestones);
getMilestones(); getMilestones();

View File

@ -1 +1 @@
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,r=document.querySelector("main").dataset.urlPrefix,s=document.querySelector("#form--searchFilters"),a=s.querySelector("#searchFilter--workOrderMilestoneDateFilter"),t=s.querySelector("#searchFilter--workOrderMilestoneDateString"),i=document.querySelector("#container--milestoneCalendar"),o=a=>{a&&a.preventDefault(),i.innerHTML='<div class="has-text-grey has-text-centered"><i class="fas fa-5x fa-circle-notch fa-spin" aria-hidden="true"></i><br />Loading Milestones...</div>',cityssm.postJSON(r+"/workOrders/doGetWorkOrderMilestones",s,s=>{(s=>{if(0===s.length)return void(i.innerHTML='<div class="message is-info"><p class="message-body">There are no milestones that meet the search criteria.</p></div>');i.innerHTML="";let a,t=cityssm.dateToString(new Date),o="";for(const n of s){o!==n.workOrderMilestoneDateString&&(a&&i.append(a),(a=document.createElement("div")).className="panel",a.innerHTML='<h2 class="panel-heading">'+n.workOrderMilestoneDateString+"</h2>",o=n.workOrderMilestoneDateString);const s=document.createElement("div");s.className="panel-block is-block",!n.workOrderMilestoneCompletionDate&&n.workOrderMilestoneDateString<t&&s.classList.add("has-background-warning-light");let c="";for(const e of n.workOrder.workOrderLots)c+='<i class="fas fa-vector-square" aria-label="'+cityssm.escapeHTML(exports.aliases.lot)+'"></i> '+cityssm.escapeHTML(e.lotName)+"<br />";for(const e of n.workOrder.workOrderLotOccupancies)e.lotOccupancyOccupants.length>0&&(c+='<i class="fas fa-user" aria-label="'+cityssm.escapeHTML(exports.aliases.lotOccupancy)+'"></i> '+cityssm.escapeHTML(e.lotOccupancyOccupants[0].occupantName)+"<br />");s.innerHTML='<div class="columns"><div class="column is-narrow"><span class="icon is-small">'+(n.workOrderMilestoneCompletionDate?'<i class="fas fa-check" aria-label="Completed"></i>':'<i class="far fa-square has-text-grey" aria-label="Incomplete"></i>')+'</span></div><div class="column">'+(0===n.workOrderMilestoneTime?"":n.workOrderMilestoneTimeString+"<br />")+(n.workOrderMilestoneTypeId?"<strong>"+cityssm.escapeHTML(n.workOrderMilestoneType)+"</strong><br />":"")+'<span class="is-size-7">'+cityssm.escapeHTML(n.workOrderMilestoneDescription)+'</span></div><div class="column"><i class="fas fa-circle" style="color:'+e.getRandomColor(n.workOrder.workOrderNumber)+'" aria-hidden="true"></i> <a class="has-text-weight-bold" href="'+r+"/workOrders/"+n.workOrderId+'">'+cityssm.escapeHTML(n.workOrder.workOrderNumber)+'</a><br /><span class="is-size-7">'+cityssm.escapeHTML(n.workOrder.workOrderDescription)+'</span></div><div class="column is-size-7">'+c+"</div></div>",a.append(s)}i.append(a)})(s.workOrderMilestones)})};a.addEventListener("change",()=>{t.disabled="date"!==a.value,o()}),t.addEventListener("change",o),s.addEventListener("submit",o),o()})(); "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),(()=>{const e=exports.los,s=document.querySelector("main").dataset.urlPrefix,r=document.querySelector("#form--searchFilters"),a=r.querySelector("#searchFilter--workOrderMilestoneDateFilter"),t=r.querySelector("#searchFilter--workOrderMilestoneDateString"),i=document.querySelector("#container--milestoneCalendar"),o=a=>{a&&a.preventDefault(),i.innerHTML='<div class="has-text-grey has-text-centered"><i class="fas fa-5x fa-circle-notch fa-spin" aria-hidden="true"></i><br />Loading Milestones...</div>',cityssm.postJSON(s+"/workOrders/doGetWorkOrderMilestones",r,r=>{(r=>{if(0===r.length)return void(i.innerHTML='<div class="message is-info"><p class="message-body">There are no milestones that meet the search criteria.</p></div>');i.innerHTML="";const a=cityssm.dateToString(new Date);let t,o="";for(const n of r){o!==n.workOrderMilestoneDateString&&(t&&i.append(t),(t=document.createElement("div")).className="panel",t.innerHTML='<h2 class="panel-heading">'+n.workOrderMilestoneDateString+"</h2>",o=n.workOrderMilestoneDateString);const r=document.createElement("div");r.className="panel-block is-block",!n.workOrderMilestoneCompletionDate&&n.workOrderMilestoneDateString<a&&r.classList.add("has-background-warning-light");let c="";for(const e of n.workOrderLots)c+='<i class="fas fa-vector-square" aria-label="'+cityssm.escapeHTML(exports.aliases.lot)+'"></i> '+cityssm.escapeHTML(e.lotName)+"<br />";for(const e of n.workOrderLotOccupancies)e.lotOccupancyOccupants.length>0&&(c+='<i class="fas fa-user" aria-label="'+cityssm.escapeHTML(exports.aliases.lotOccupancy)+'"></i> '+cityssm.escapeHTML(e.lotOccupancyOccupants[0].occupantName)+"<br />");r.innerHTML='<div class="columns"><div class="column is-narrow"><span class="icon is-small">'+(n.workOrderMilestoneCompletionDate?'<i class="fas fa-check" aria-label="Completed"></i>':'<i class="far fa-square has-text-grey" aria-label="Incomplete"></i>')+'</span></div><div class="column">'+(0===n.workOrderMilestoneTime?"":n.workOrderMilestoneTimeString+"<br />")+(n.workOrderMilestoneTypeId?"<strong>"+cityssm.escapeHTML(n.workOrderMilestoneType)+"</strong><br />":"")+'<span class="is-size-7">'+cityssm.escapeHTML(n.workOrderMilestoneDescription)+'</span></div><div class="column"><i class="fas fa-circle" style="color:'+e.getRandomColor(n.workOrderNumber)+'" aria-hidden="true"></i> <a class="has-text-weight-bold" href="'+s+"/workOrders/"+n.workOrderId+'">'+cityssm.escapeHTML(n.workOrderNumber)+'</a><br /><span class="is-size-7">'+cityssm.escapeHTML(n.workOrderDescription)+'</span></div><div class="column is-size-7">'+c+"</div></div>",t.append(r)}i.append(t)})(r.workOrderMilestones)})};a.addEventListener("change",()=>{t.disabled="date"!==a.value,o()}),t.addEventListener("change",o),r.addEventListener("submit",o),o()})();

View File

@ -206,10 +206,8 @@ export interface WorkOrderComment extends Record {
workOrderCommentTimeString?: string; workOrderCommentTimeString?: string;
workOrderComment?: string; workOrderComment?: string;
} }
export interface WorkOrderMilestone extends Record { export interface WorkOrderMilestone extends Record, WorkOrder {
workOrderMilestoneId?: number; workOrderMilestoneId?: number;
workOrderId?: number;
workOrder?: WorkOrder;
workOrderMilestoneTypeId?: number; workOrderMilestoneTypeId?: number;
workOrderMilestoneType?: string; workOrderMilestoneType?: string;
workOrderMilestoneDate?: number; workOrderMilestoneDate?: number;
@ -221,6 +219,7 @@ export interface WorkOrderMilestone extends Record {
workOrderMilestoneCompletionDateString?: string; workOrderMilestoneCompletionDateString?: string;
workOrderMilestoneCompletionTime?: number; workOrderMilestoneCompletionTime?: number;
workOrderMilestoneCompletionTimeString?: string; workOrderMilestoneCompletionTimeString?: string;
workOrderRecordUpdate_timeMillis?: number;
} }
export interface WorkOrder extends Record { export interface WorkOrder extends Record {
workOrderId?: number; workOrderId?: number;

View File

@ -277,12 +277,9 @@ export interface WorkOrderComment extends Record {
workOrderComment?: string; workOrderComment?: string;
} }
export interface WorkOrderMilestone extends Record { export interface WorkOrderMilestone extends Record, WorkOrder {
workOrderMilestoneId?: number; workOrderMilestoneId?: number;
workOrderId?: number;
workOrder?: WorkOrder;
workOrderMilestoneTypeId?: number; workOrderMilestoneTypeId?: number;
workOrderMilestoneType?: string; workOrderMilestoneType?: string;
@ -299,6 +296,8 @@ export interface WorkOrderMilestone extends Record {
workOrderMilestoneCompletionTime?: number; workOrderMilestoneCompletionTime?: number;
workOrderMilestoneCompletionTimeString?: string; workOrderMilestoneCompletionTimeString?: string;
workOrderRecordUpdate_timeMillis?: number;
} }
export interface WorkOrder extends Record { export interface WorkOrder extends Record {

View File

@ -29,18 +29,18 @@
<strong><%= milestone.workOrderMilestoneType %></strong><br /> <strong><%= milestone.workOrderMilestoneType %></strong><br />
<% } %> <% } %>
<span class="is-size-7"> <span class="is-size-7">
<i class="fas fa-hard-hat" aria-label="Work Order"></i> <%= milestone.workOrder.workOrderNumber %><br /> <i class="fas fa-hard-hat" aria-label="Work Order"></i> <%= milestone.workOrderNumber %><br />
<% <%
if (milestone.workOrder.workOrderLots.length > 0) { if (milestone.workOrderLots.length > 0) {
for (const lot of milestone.workOrder.workOrderLots) { for (const lot of milestone.workOrderLots) {
%> %>
<i class="fas fa-vector-square" aria-label="<%= configFunctions.getProperty("aliases.lot") %>"></i> <%= lot.lotName %><br /> <i class="fas fa-vector-square" aria-label="<%= configFunctions.getProperty("aliases.lot") %>"></i> <%= lot.lotName %><br />
<% <%
} }
} }
if (milestone.workOrder.workOrderLotOccupancies.length > 0) { if (milestone.workOrderLotOccupancies.length > 0) {
for (const occupancy of milestone.workOrder.workOrderLotOccupancies) { for (const occupancy of milestone.workOrderLotOccupancies) {
for (const occupant of occupancy.lotOccupancyOccupants) { for (const occupant of occupancy.lotOccupancyOccupants) {
%> %>
<i class="fas fa-user" aria-label="<%= configFunctions.getProperty("aliases.occupancy") %>"></i> <%= occupant.occupantName %><br /> <i class="fas fa-user" aria-label="<%= configFunctions.getProperty("aliases.occupancy") %>"></i> <%= occupant.occupantName %><br />