contract paging

pull/11/head
Dan Gowans 2025-04-23 10:31:04 -04:00
parent 9e6da86d80
commit 8e22ee1026
17 changed files with 273 additions and 66 deletions

View File

@ -0,0 +1 @@
export default function getNextContractId(contractId: number | string): Promise<number | undefined>;

View File

@ -0,0 +1,15 @@
import { acquireConnection } from './pool.js';
export default async function getNextContractId(contractId) {
const database = await acquireConnection();
const result = database
.prepare(`select contractId
from Contracts
where recordDelete_timeMillis is null
and contractId > ?
order by contractId
limit 1`)
.pluck()
.get(contractId);
database.release();
return result;
}

View File

@ -0,0 +1,23 @@
import { acquireConnection } from './pool.js'
export default async function getNextContractId(
contractId: number | string
): Promise<number | undefined> {
const database = await acquireConnection()
const result = database
.prepare(
`select contractId
from Contracts
where recordDelete_timeMillis is null
and contractId > ?
order by contractId
limit 1`
)
.pluck()
.get(contractId) as number | undefined
database.release()
return result
}

View File

@ -0,0 +1 @@
export default function getPreviousContractId(contractId: number | string): Promise<number | undefined>;

View File

@ -0,0 +1,15 @@
import { acquireConnection } from './pool.js';
export default async function getPreviousContractId(contractId) {
const database = await acquireConnection();
const result = database
.prepare(`select contractId
from Contracts
where recordDelete_timeMillis is null
and contractId < ?
order by contractId desc
limit 1`)
.pluck()
.get(contractId);
database.release();
return result;
}

View File

@ -0,0 +1,23 @@
import { acquireConnection } from './pool.js'
export default async function getPreviousContractId(
contractId: number | string
): Promise<number | undefined> {
const database = await acquireConnection()
const result = database
.prepare(
`select contractId
from Contracts
where recordDelete_timeMillis is null
and contractId < ?
order by contractId desc
limit 1`
)
.pluck()
.get(contractId) as number | undefined
database.release()
return result
}

View File

@ -1,2 +1,4 @@
import type { Request, Response } from 'express';
export default function handler(request: Request, response: Response): Promise<void>;
export default function handler(request: Request<{
cemeteryId: string;
}>, response: Response): Promise<void>;

View File

@ -4,7 +4,7 @@ import getNextCemeteryId from '../../database/getNextCemeteryId.js'
import { getConfigProperty } from '../../helpers/config.helpers.js'
export default async function handler(
request: Request,
request: Request<{ cemeteryId: string }>,
response: Response
): Promise<void> {
const cemeteryId = Number.parseInt(request.params.cemeteryId, 10)

View File

@ -0,0 +1,4 @@
import type { Request, Response } from 'express';
export default function handler(request: Request<{
contractId: string;
}>, response: Response): Promise<void>;

View File

@ -0,0 +1,11 @@
import getNextContractId from '../../database/getNextContractId.js';
import { getConfigProperty } from '../../helpers/config.helpers.js';
export default async function handler(request, response) {
const contractId = Number.parseInt(request.params.contractId, 10);
const nextContractId = await getNextContractId(contractId);
if (nextContractId === undefined) {
response.redirect(`${getConfigProperty('reverseProxy.urlPrefix')}/contracts/?error=noNextContractIdFound`);
return;
}
response.redirect(`${getConfigProperty('reverseProxy.urlPrefix')}/contracts/${nextContractId.toString()}`);
}

View File

@ -0,0 +1,28 @@
import type { Request, Response } from 'express'
import getNextContractId from '../../database/getNextContractId.js'
import { getConfigProperty } from '../../helpers/config.helpers.js'
export default async function handler(
request: Request<{ contractId: string }>,
response: Response
): Promise<void> {
const contractId = Number.parseInt(request.params.contractId, 10)
const nextContractId = await getNextContractId(contractId)
if (nextContractId === undefined) {
response.redirect(
`${getConfigProperty(
'reverseProxy.urlPrefix'
)}/contracts/?error=noNextContractIdFound`
)
return
}
response.redirect(
`${getConfigProperty(
'reverseProxy.urlPrefix'
)}/contracts/${nextContractId.toString()}`
)
}

View File

@ -0,0 +1,4 @@
import type { Request, Response } from 'express';
export default function handler(request: Request<{
contractId: string;
}>, response: Response): Promise<void>;

View File

@ -0,0 +1,11 @@
import getPreviousContractId from '../../database/getPreviousContractId.js';
import { getConfigProperty } from '../../helpers/config.helpers.js';
export default async function handler(request, response) {
const contractId = Number.parseInt(request.params.contractId, 10);
const previousContractId = await getPreviousContractId(contractId);
if (previousContractId === undefined) {
response.redirect(`${getConfigProperty('reverseProxy.urlPrefix')}/contracts/?error=noPreviousContractIdFound`);
return;
}
response.redirect(`${getConfigProperty('reverseProxy.urlPrefix')}/contracts/${previousContractId.toString()}`);
}

View File

@ -0,0 +1,28 @@
import type { Request, Response } from 'express'
import getPreviousContractId from '../../database/getPreviousContractId.js'
import { getConfigProperty } from '../../helpers/config.helpers.js'
export default async function handler(
request: Request<{ contractId: string }>,
response: Response
): Promise<void> {
const contractId = Number.parseInt(request.params.contractId, 10)
const previousContractId = await getPreviousContractId(contractId)
if (previousContractId === undefined) {
response.redirect(
`${getConfigProperty(
'reverseProxy.urlPrefix'
)}/contracts/?error=noPreviousContractIdFound`
)
return
}
response.redirect(
`${getConfigProperty(
'reverseProxy.urlPrefix'
)}/contracts/${previousContractId.toString()}`
)
}

View File

@ -1,6 +1,8 @@
import { Router } from 'express';
import handler_edit from '../handlers/contracts-get/edit.js';
import handler_new from '../handlers/contracts-get/new.js';
import handler_next from '../handlers/contracts-get/next.js';
import handler_previous from '../handlers/contracts-get/previous.js';
import handler_search from '../handlers/contracts-get/search.js';
import handler_view from '../handlers/contracts-get/view.js';
import handler_doAddContractComment from '../handlers/contracts-post/doAddContractComment.js';
@ -36,6 +38,8 @@ router.post('/doGetContractTypeFields', updatePostHandler, handler_doGetContract
router.post('/doCreateContract', updatePostHandler, handler_doCreateContract);
// View
router.get('/:contractId', handler_view);
router.get('/:contractId/next', handler_next);
router.get('/:contractId/previous', handler_previous);
// Edit
router.get('/:contractId/edit', updateGetHandler, handler_edit);
router.post('/doUpdateContract', updatePostHandler, handler_doUpdateContract);

View File

@ -2,6 +2,8 @@ import { Router } from 'express'
import handler_edit from '../handlers/contracts-get/edit.js'
import handler_new from '../handlers/contracts-get/new.js'
import handler_next from '../handlers/contracts-get/next.js'
import handler_previous from '../handlers/contracts-get/previous.js'
import handler_search from '../handlers/contracts-get/search.js'
import handler_view from '../handlers/contracts-get/view.js'
import handler_doAddContractComment from '../handlers/contracts-post/doAddContractComment.js'
@ -52,6 +54,10 @@ router.post('/doCreateContract', updatePostHandler, handler_doCreateContract)
router.get('/:contractId', handler_view)
router.get('/:contractId/next', handler_next)
router.get('/:contractId/previous', handler_previous)
// Edit
router.get('/:contractId/edit', updateGetHandler, handler_edit)

View File

@ -34,6 +34,20 @@
</div>
<div class="column is-narrow has-text-right">
<div class="buttons is-right">
<a class="button is-link is-outlined has-tooltip-left"
data-tooltip="Previous Contract"
href="<%= urlPrefix %>/contracts/<%= contract.contractId %>/previous"
accesskey=",">
<span class="icon m-0"><i class="fas fa-arrow-left" aria-hidden="true"></i></span>
<span class="sr-only">Previous Contract</span>
</a>
<a class="button is-link has-tooltip-left"
data-tooltip="Next Contract"
href="<%= urlPrefix %>/contracts/<%= contract.contractId %>/next"
accesskey=".">
<span>Next</span>
<span class="icon"><i class="fas fa-arrow-right" aria-hidden="true"></i></span>
</a>
<% if (contractTypePrints.length > 0) { %>
<% if (contractTypePrints.length === 1) { %>
<a href="<%= urlPrefix %>/print/<%= contractTypePrints[0] %>/?contractId=<%= contract.contractId %>" target="_blank" aria-label="Print">
@ -244,7 +258,11 @@
<div class="columns">
<div class="column">
<p>
<%= contract.purchaserName %><br />
<% if (contract.purchaserName === '') { %>
<span class="has-text-grey">(No Purchaser Set)</span>
<% } else { %>
<%= contract.purchaserName %>
<% } %><br />
<span class="is-size-7">
<% if (contract.purchaserAddress1) { %>
<%= contract.purchaserAddress1 %><br />
@ -398,70 +416,70 @@
<div class="columns">
<div class="column">
<div class="panel">
<h2 class="panel-heading">Fees</h2>
<div class="panel-block is-block">
<% if (contract.contractFees.length === 0) { %>
<div class="message is-info">
<p class="message-body">
There are no fees applied to this contract.
</p>
</div>
<% } else { %>
<%
let feeAmountTotal = 0;
let taxAmountTotal = 0;
%>
<table class="table is-fullwidth is-striped is-hoverable">
<thead>
<tr>
<th>Fee</th>
<th class="has-text-right"><span class="is-sr-only">Unit Cost</span></th>
<th class="has-width-1"><span class="is-sr-only">&times;</span></th>
<th class="has-width-1 has-text-right"><span class="is-sr-only">Quantity</span></th>
<th class="has-width-1"><span class="is-sr-only">=</span></th>
<th class="has-width-1 has-text-right">Total</th>
</tr>
</thead>
<tbody>
<% for (const contractFee of contract.contractFees) { %>
<%
feeAmountTotal += (contractFee.feeAmount * contractFee.quantity);
taxAmountTotal += (contractFee.taxAmount * contractFee.quantity);
%>
<tr>
<td colspan="<%= (contractFee.quantity === 1 ? "5" : "1") %>">
<%= contractFee.feeName %><br />
<span class="tag"><%= contractFee.feeCategory %></span>
</td>
<% if (contractFee.quantity !== 1) { %>
<td class="has-text-right">$<%= contractFee.feeAmount.toFixed(2) %></td>
<td>&times;</td>
<td class="has-text-right"><%= contractFee.quantity %></td>
<td>=</td>
<% } %>
<td class="has-text-right">$<%= (contractFee.feeAmount * contractFee.quantity).toFixed(2) %></td>
</tr>
<% } %>
</tbody>
<tfoot>
<tr>
<th colspan="5">Subtotal</th>
<td class="has-text-right has-text-weight-bold">$<%= feeAmountTotal.toFixed(2) %></td>
</tr>
<tr>
<th colspan="5">Tax</th>
<td class="has-text-right">$<%= taxAmountTotal.toFixed(2) %></td>
</tr>
<tr>
<th colspan="5">Grand Total</th>
<td class="has-text-right has-text-weight-bold">$<%= (feeAmountTotal + taxAmountTotal).toFixed(2) %></td>
</tr>
</tfoot>
</table>
<% } %>
<div class="panel">
<h2 class="panel-heading">Fees</h2>
<div class="panel-block is-block">
<% if (contract.contractFees.length === 0) { %>
<div class="message is-info">
<p class="message-body">
There are no fees applied to this contract.
</p>
</div>
<% } else { %>
<%
let feeAmountTotal = 0;
let taxAmountTotal = 0;
%>
<table class="table is-fullwidth is-striped is-hoverable">
<thead>
<tr>
<th>Fee</th>
<th class="has-text-right"><span class="is-sr-only">Unit Cost</span></th>
<th class="has-width-1"><span class="is-sr-only">&times;</span></th>
<th class="has-width-1 has-text-right"><span class="is-sr-only">Quantity</span></th>
<th class="has-width-1"><span class="is-sr-only">=</span></th>
<th class="has-width-1 has-text-right">Total</th>
</tr>
</thead>
<tbody>
<% for (const contractFee of contract.contractFees) { %>
<%
feeAmountTotal += (contractFee.feeAmount * contractFee.quantity);
taxAmountTotal += (contractFee.taxAmount * contractFee.quantity);
%>
<tr>
<td colspan="<%= (contractFee.quantity === 1 ? "5" : "1") %>">
<%= contractFee.feeName %><br />
<span class="tag"><%= contractFee.feeCategory %></span>
</td>
<% if (contractFee.quantity !== 1) { %>
<td class="has-text-right">$<%= contractFee.feeAmount.toFixed(2) %></td>
<td>&times;</td>
<td class="has-text-right"><%= contractFee.quantity %></td>
<td>=</td>
<% } %>
<td class="has-text-right">$<%= (contractFee.feeAmount * contractFee.quantity).toFixed(2) %></td>
</tr>
<% } %>
</tbody>
<tfoot>
<tr>
<th colspan="5">Subtotal</th>
<td class="has-text-right has-text-weight-bold">$<%= feeAmountTotal.toFixed(2) %></td>
</tr>
<tr>
<th colspan="5">Tax</th>
<td class="has-text-right">$<%= taxAmountTotal.toFixed(2) %></td>
</tr>
<tr>
<th colspan="5">Grand Total</th>
<td class="has-text-right has-text-weight-bold">$<%= (feeAmountTotal + taxAmountTotal).toFixed(2) %></td>
</tr>
</tfoot>
</table>
<% } %>
</div>
</div>
</div>
<div class="column">
<div class="panel">
@ -537,7 +555,20 @@
const workOrderCloseDateAlias = configFunctions.getConfigProperty("aliases.workOrderCloseDate");
%>
<div class="panel">
<h2 class="panel-heading">Work Orders</h2>
<div class="panel-heading">
<div class="level is-mobile">
<div class="level-left">
<div class="level-item">
<h2 class="has-text-weight-bold">Work Orders</h2>
</div>
</div>
<div class="level-right">
<div class="level-item">
<i class="fas fa-hard-hat" aria-hidden="true"></i>
</div>
</div>
</div>
</div>
<div class="panel-block is-block">
<table class="table is-fullwidth is-striped is-hoverable">
<thead>