Compare commits

..

192 Commits

Author SHA1 Message Date
Dan Gowans 118fc1959b fix undefined transaction time 2025-05-02 08:52:35 -04:00
Dan Gowans 9830bede34 linting 2025-05-01 14:53:07 -04:00
Dan Gowans 302a9a4c48 include "cms" in title 2025-05-01 12:45:59 -04:00
Dan Gowans fe9188d1fb version bump 2025-05-01 12:36:08 -04:00
Dan Gowans 4664366e12 linting 2025-05-01 12:32:36 -04:00
Dan Gowans afcdca959b use built in database backup function 2025-05-01 12:19:48 -04:00
Dan Gowans 434e15ba1d highlight today's funerals 2025-05-01 11:34:47 -04:00
Dan Gowans 39dc10369f show funeral home upcoming contracts 2025-05-01 11:20:33 -04:00
Dan Gowans 7371be711a restore deleted burial sites 2025-05-01 10:38:13 -04:00
Dan Gowans 9048235ef2 more deleted item loading 2025-05-01 09:26:40 -04:00
Dan Gowans 59b0fb7e5f ensure deleted items are loaded for import 2025-05-01 09:16:02 -04:00
Dan Gowans 57b6dbf35e use common "cremation" cemetery list 2025-05-01 08:55:34 -04:00
Dan Gowans c460d073e7 linting 2025-04-30 15:14:56 -04:00
Dan Gowans a7ce5a99cb add default city to interment modals 2025-04-30 15:11:12 -04:00
Dan Gowans db05999c72 track burial site capacities
alter table BurialSiteTypes
add bodyCapacityMax smallint

alter table BurialSiteTypes
add crematedCapacityMax smallint

alter table BurialSites
add bodyCapacity smallint

alter table BurialSites
add crematedCapacity smallint
2025-04-30 14:40:47 -04:00
Dan Gowans 9c47b48abc linting 2025-04-30 10:42:16 -04:00
Dan Gowans 2ed7902320 rename "switch to edit mode" buttons 2025-04-30 10:19:16 -04:00
Dan Gowans 7887230c86 linting 2025-04-30 10:00:59 -04:00
Dan Gowans 18edc57f70 update linter 2025-04-30 10:00:27 -04:00
Dan Gowans 656f1b052e linting 2025-04-30 08:45:39 -04:00
Dan Gowans 3c1d023ccd linting 2025-04-29 15:22:01 -04:00
Dan Gowans 2c506711fb add id to pdf file name 2025-04-29 14:57:07 -04:00
Dan Gowans 0dcdfaaa8a fix small screen alignment 2025-04-29 13:44:33 -04:00
Dan Gowans ba0c9f3287 version bump 2025-04-29 13:23:22 -04:00
Dan Gowans ab61a3e340 fix initializing database 2025-04-29 13:17:31 -04:00
Dan Gowans 111663a274 interment container type maint
closes #8
2025-04-29 13:14:43 -04:00
Dan Gowans 1c7bc96392 committal type table maint #8 2025-04-29 11:54:17 -04:00
Dan Gowans b26e8b17b2 restructure config table management
preparing for #8
- switch tabs for collapsed panels
- split the javascript into a file per table
2025-04-29 11:01:50 -04:00
Dan Gowans c9b10f3696 fix toggle panel-block 2025-04-29 10:03:30 -04:00
Dan Gowans 34c00b856b fix viewing work orders 2025-04-29 09:25:57 -04:00
Dan Gowans 0474631bf5 fix create cemeteries 2025-04-29 09:25:46 -04:00
Dan Gowans 927334d954 allow testUpdate user to update work orders 2025-04-28 15:46:54 -04:00
Dan Gowans 50551582c1 identify 'HO' funeral home 2025-04-28 15:40:39 -04:00
Dan Gowans 19a7c81766 linting 2025-04-28 15:30:48 -04:00
Dan Gowans f96d975aa0 avoid order number updates
when deleted records are loaded
2025-04-28 15:10:19 -04:00
Dan Gowans 3c4c85df19 import cleanup 2025-04-28 14:50:34 -04:00
Dan Gowans 0d2f6f78ce missed include deleted 2025-04-28 14:16:08 -04:00
Dan Gowans 007b47a1f0 linting 2025-04-28 14:08:46 -04:00
Dan Gowans 62efb70542 include deleted list items
for import purposes
2025-04-28 14:05:45 -04:00
Dan Gowans f440a35df7 linting 2025-04-28 14:05:18 -04:00
Dan Gowans 78cae2f964 disable map scroll wheel zoom 2025-04-28 13:11:39 -04:00
Dan Gowans afa0286a2a show funeral details on work order view 2025-04-28 13:08:31 -04:00
Dan Gowans 556a6a71b6 add "direction of arrival"
database update:

create table if not exists CemeteryDirectionsOfArrival (
cemeteryId integer not null,
directionOfArrival varchar(2) not null,
directionOfArrivalDescription varchar(100) not null,
primary key (cemeteryId, directionOfArrival),
foreign key (cemeteryId) references Cemeteries (cemeteryId)) without rowid

alter table Contracts
add directionOfArrival varchar(2)
2025-04-28 11:59:09 -04:00
Dan Gowans 96a41862bf heading icons on contract view 2025-04-25 15:36:45 -04:00
Dan Gowans f35946d0a5 readd missing is-nowrap class 2025-04-25 15:28:19 -04:00
Dan Gowans d4670603b7 clean up awaits 2025-04-25 15:23:38 -04:00
Dan Gowans 09b3de1086 required indicators 2025-04-25 14:27:35 -04:00
Dan Gowans c7640f6dfd death age calculator
closes #9
2025-04-25 14:18:24 -04:00
Dan Gowans 14bd8e0ea4 internal data lists
move deathAgePeriods and purchaserRelationships out of config
2025-04-25 13:41:31 -04:00
Dan Gowans b356d771ab rename config files 2025-04-25 13:27:24 -04:00
Dan Gowans b359aaf564 type issue 2025-04-25 13:26:39 -04:00
Dan Gowans c330dff849 adjustable results limit 2025-04-25 13:03:05 -04:00
Dan Gowans a4522ec4d0 updated selling points 2025-04-25 12:38:28 -04:00
Dan Gowans 3babad95c4 version bump 2025-04-25 11:53:42 -04:00
Dan Gowans 5767b14f76 try removing legacy puppeteer in testing 2025-04-25 11:50:46 -04:00
Dan Gowans eada41aaaa linting 2025-04-25 11:42:02 -04:00
Dan Gowans e09d1ddb5d debug logging alignment 2025-04-25 11:19:19 -04:00
Dan Gowans f6eb3bf550 create burial site from contract
closes #7
2025-04-25 10:52:55 -04:00
Dan Gowans dc9a9b2bcc show "no cemetery" when none selected 2025-04-25 10:12:50 -04:00
Dan Gowans e7f79cbc4f fix burial site images 2025-04-25 10:03:38 -04:00
Dan Gowans 9bfed5aa4d date field restrictions 2025-04-24 14:48:13 -04:00
Dan Gowans 9a153bb238 linting 2025-04-24 14:15:25 -04:00
Dan Gowans 41761dcc8c remove node 18 testing 2025-04-24 13:49:32 -04:00
Dan Gowans 36e2b0f9cc linting 2025-04-24 13:48:19 -04:00
Dan Gowans d4087caa74 switch work order create button permission 2025-04-24 13:07:52 -04:00
Dan Gowans 9c9b94199b highlight overpayment 2025-04-24 13:00:43 -04:00
Dan Gowans 96eb7f36dc gp connection error catch 2025-04-24 12:55:40 -04:00
Dan Gowans 4f6fc87e05 remove better-sqlite-pool 2025-04-24 11:59:27 -04:00
Dan Gowans 38c1288856 separate `canUpdateWorkOrders` permission 2025-04-24 09:36:44 -04:00
Dan Gowans a167ef4a16 rename types files 2025-04-24 09:24:25 -04:00
Dan Gowans 3da2aad21b fix add grouped fee 2025-04-24 09:15:20 -04:00
Dan Gowans dcbaad753b linting 2025-04-23 14:13:45 -04:00
Dan Gowans d46a94db07 link funeral home name 2025-04-23 14:13:36 -04:00
Dan Gowans bb3100c0b0 version bump 2025-04-23 13:03:14 -04:00
Dan Gowans 3f28571dc2 fix contract status filter 2025-04-23 12:55:55 -04:00
Dan Gowans 8f201e05b3 linting 2025-04-23 12:06:29 -04:00
Dan Gowans d5915db9bd contract finalized indicator 2025-04-23 11:58:28 -04:00
Dan Gowans 8e22ee1026 contract paging 2025-04-23 10:31:04 -04:00
Dan Gowans 9e6da86d80 linting import 2025-04-23 10:30:44 -04:00
Dan Gowans 31837d4370 dev dependencies 2025-04-23 10:30:27 -04:00
Dan Gowans 880a6fd23a add import latitude and longitude 2025-04-22 15:38:55 -04:00
Dan Gowans 125f1e0949 version bump 2025-04-22 15:22:51 -04:00
Dan Gowans d4280a3796 import updates 2025-04-22 15:21:21 -04:00
Dan Gowans b3e5d8e5ad fix missing labels 2025-04-22 15:21:10 -04:00
Dan Gowans df3f7725d3 linting and development 2025-04-22 13:51:02 -04:00
Dan Gowans b8c9fd723d darken domain label
trying to fix cypress accessibility issue
2025-04-22 11:39:27 -04:00
Dan Gowans 3b98ac6f15 menu titles 2025-04-22 10:57:28 -04:00
Dan Gowans 6d964eb93a link together sections 2025-04-22 10:44:14 -04:00
Dan Gowans 688e55857d cypress update 2025-04-22 10:43:48 -04:00
Dan Gowans 59ab59bb1f enforce light theme 2025-04-17 14:20:12 -04:00
Dan Gowans f7ae72d40a linting and polish 2025-04-16 15:43:35 -04:00
Dan Gowans 43d70d8967 restrict parent cemeteries
when the cemetery has child cemeteries
2025-04-16 15:33:15 -04:00
Dan Gowans cd47832247 show child cemeteries 2025-04-16 15:14:33 -04:00
Dan Gowans 966a2fc869 polish 2025-04-16 14:20:26 -04:00
Dan Gowans 0b767d6b88 documentation 2025-04-16 14:06:56 -04:00
Dan Gowans 5e2b90f2a2 version bump 2025-04-16 13:01:28 -04:00
Dan Gowans fb5c960bc7 linting 2025-04-16 12:51:12 -04:00
Dan Gowans 4a17f0ecfa fix broken cemetery create 2025-04-16 12:50:51 -04:00
Dan Gowans 86cc71d235 ssm cemetery details 2025-04-16 11:21:02 -04:00
Dan Gowans a4e4a11a59 polish 2025-04-16 11:20:44 -04:00
Dan Gowans 20702c598a increase max process cutoff 2025-04-15 14:48:42 -04:00
Dan Gowans 6cb36c4548 linting 2025-04-15 14:48:26 -04:00
Dan Gowans 2176158847 fix url 2025-04-15 13:57:07 -04:00
Dan Gowans ebc74816c2 polish 2025-04-15 13:56:50 -04:00
Dan Gowans 9f661f478f fix urls 2025-04-15 13:56:39 -04:00
Dan Gowans f652f27c5e documentation 2025-04-15 13:36:18 -04:00
Dan Gowans 3312f70967 framing up documentation 2025-04-15 13:20:26 -04:00
Dan Gowans ab6ee7a9e2 linting 2025-04-15 13:20:06 -04:00
Dan Gowans cc79209eb9 update contract icon 2025-04-15 11:52:03 -04:00
Dan Gowans 9a69c2e6dd version bump 2025-04-15 11:15:36 -04:00
Dan Gowans 1e59a368a4 test not watching changes 2025-04-15 11:13:02 -04:00
Dan Gowans d41117a44a development
- combine functions.database and database.helpers
- monitor image folders for changes
- warning message for config table update
- properly track replacement workers
- show cemetery maps on burial sites
- show parent cemetery maps on child cemetery sites
- linting and polish
2025-04-15 11:05:41 -04:00
Dan Gowans 190d17cabd consistent admin heading sizes 2025-04-14 09:44:47 -04:00
Dan Gowans 9501f30b23 add missing config table reports 2025-04-14 09:14:48 -04:00
Dan Gowans 8efea8d739 add menard funeral home 2025-04-11 14:50:10 -04:00
Dan Gowans 9bc85e6a8b parent cemeteries, linting 2025-04-11 14:50:00 -04:00
Dan Gowans ed87174c19 dev dependencies 2025-04-09 13:13:38 -04:00
Dan Gowans 04a4e6473b speed improvement
3.5min to 0.1sec
2025-04-09 13:13:26 -04:00
Dan Gowans a5a1c9f793 linting 2025-04-03 15:30:06 -04:00
Dan Gowans 7f32d0a14a linting 2025-04-03 15:08:35 -04:00
Dan Gowans 70c796bb41 use default public-internal for testing 2025-04-03 14:21:47 -04:00
Dan Gowans a17257a9c8 version bump 2025-04-03 14:10:15 -04:00
Dan Gowans 0c378970ae move all sault ste marie assets to separate repo
https://github.com/cityssm/sunrise-cms-saultstemarie
2025-04-03 13:40:15 -04:00
Dan Gowans 495231afd6 linting and polish 2025-04-03 11:40:04 -04:00
Dan Gowans 6125ef0030 include key in results 2025-04-03 10:09:42 -04:00
Dan Gowans 58d6cc76b5 add basic test 2025-04-03 10:09:24 -04:00
Dan Gowans 4bc7d0a844 polishing 2025-04-02 15:12:51 -04:00
Dan Gowans 4d3ba54d50 rebuild burial site names on cemetery key change 2025-04-02 14:02:58 -04:00
Dan Gowans 1f19359195 linting and polish 2025-04-02 14:02:48 -04:00
Dan Gowans 01f44f0727 fix comment print 2025-04-02 12:59:32 -04:00
Dan Gowans 1dd8024e35 fix work order delete 2025-04-02 11:58:32 -04:00
Dan Gowans 5a1d47dd17 version bump 2025-04-02 11:43:03 -04:00
Dan Gowans 19178a025f version bump 2025-04-02 11:35:37 -04:00
Dan Gowans 11a78a9bc5 polish 2025-04-02 11:34:17 -04:00
Dan Gowans ed96a35c94 fix toolbars on mobile 2025-04-01 15:20:01 -04:00
Dan Gowans 54867f1cbc mobile updates 2025-04-01 12:32:20 -04:00
Dan Gowans 452565943e mapping fixes, select by map 2025-04-01 10:25:42 -04:00
Dan Gowans b2da12dac1 linting 2025-03-31 14:59:31 -04:00
Dan Gowans 4a1f6b42b0 update express to v5 2025-03-31 10:31:29 -04:00
Dan Gowans bd23675b04 use social image 2025-03-28 15:34:56 -04:00
Dan Gowans ebd9f01491 Create socialPreview.png 2025-03-28 15:33:57 -04:00
Dan Gowans 09f87ed3da freeze optional puppeteer version 2025-03-28 15:15:02 -04:00
Dan Gowans b060cbcd78 version bump 2025-03-28 15:04:31 -04:00
Dan Gowans 9bf4a2cfee linting
- login page overflow
- make sure funeral home icons use fa-place-of-worship
2025-03-28 15:03:42 -04:00
Dan Gowans ee0e79b60a print out polish 2025-03-28 14:23:04 -04:00
Dan Gowans ac4ae20f78 linting 2025-03-28 12:43:33 -04:00
Dan Gowans 922603a1f2 development and linting 2025-03-28 12:36:56 -04:00
Dan Gowans 66a697e097 burial site images
- make cemetery svgs and burial site images only available to logged in users
2025-03-28 10:47:21 -04:00
Dan Gowans 906f8c41e5 update pdf-puppeteer 2025-03-27 12:52:13 -04:00
Dan Gowans 91d94b6a49 use cypress 14 2025-03-26 13:43:18 -04:00
Dan Gowans 542e3ceabb update heading tags 2025-03-26 13:43:10 -04:00
Dan Gowans 8fa012be75 linting and polish 2025-03-26 13:21:28 -04:00
Dan Gowans 061c1fa43a linting 2025-03-25 14:40:22 -04:00
Dan Gowans beb57e70ab delete burial site and cemetery protection 2025-03-25 14:03:22 -04:00
Dan Gowans 7ccc56d5e0 linting 2025-03-25 12:22:21 -04:00
Dan Gowans 5f4aa595f2 rename field 2025-03-25 12:22:16 -04:00
Dan Gowans 4900895f5e show funeral home and purchaser 2025-03-25 12:21:59 -04:00
Dan Gowans 261f1ba354 include funeralHomeName 2025-03-25 12:21:34 -04:00
Dan Gowans 16db467481 toggle past contracts 2025-03-25 12:21:07 -04:00
Dan Gowans 2d3b8042a0 linting 2025-03-25 12:20:42 -04:00
Dan Gowans b48bc3b677 add screenshot 2025-03-24 12:22:32 -04:00
Dan Gowans 461a790b70 fix burial site highlighting 2025-03-24 12:22:21 -04:00
Dan Gowans 92056cf6b7 filter search by funeral home 2025-03-24 12:21:55 -04:00
Dan Gowans df44ab95f7 add some ids, for screenshot 2025-03-24 12:21:01 -04:00
Dan Gowans 4af21f4261 linting 2025-03-24 10:52:36 -04:00
Dan Gowans 669d942c0d dev dependencies 2025-03-24 10:52:27 -04:00
Dan Gowans 27097dc1ca fix funeral field update 2025-03-24 10:52:06 -04:00
Dan Gowans b16f96c74b development
- fix close work order button contrast
- fix work order menu alignment
2025-03-21 11:07:59 -04:00
Dan Gowans fa3e40253f development
- admin menu alignment
- fix svg display
- fix print buttons
2025-03-21 10:25:48 -04:00
Dan Gowans 80fa36853d ensure burial site names remain distinct 2025-03-21 09:12:31 -04:00
Dan Gowans d7f4cb4d3b set node-windows as optional dependency 2025-03-20 15:34:42 -04:00
Dan Gowans 2b481c32df bring back login page help link 2025-03-20 15:30:27 -04:00
Dan Gowans a71c11c5e4 fix hard to read button 2025-03-20 15:28:19 -04:00
Dan Gowans 3644bc6170 fix server start 2025-03-20 14:44:48 -04:00
Dan Gowans f36302d492 version bump 2025-03-20 14:40:13 -04:00
Dan Gowans 17595d6f2f default port update 2025-03-20 14:40:08 -04:00
Dan Gowans 18b1ffa0cc link typo 2025-03-20 11:55:53 -04:00
Dan Gowans 0dbbd3f750 development
- add latitude and longitude bounds
- add purchaser relationship suggestions
- clean up dashboard
- switch to native node testing
- linting
2025-03-20 11:53:56 -04:00
Dan Gowans 28fe138fb5 svg logo 2025-03-19 13:36:00 -04:00
Dan Gowans b30c02d9c4 update bulma to current 2025-03-19 11:58:25 -04:00
Dan Gowans 856abc9fcf update font awesome to current 2025-03-19 09:00:44 -04:00
Dan Gowans 478fe4518b restore full import 2025-03-18 15:33:49 -04:00
Dan Gowans 22ba4f367d cleanup 2025-03-18 15:18:38 -04:00
Dan Gowans cf52a3daea fix for github pages 2025-03-18 14:57:18 -04:00
Dan Gowans 9bc27dafe8 linting 2025-03-18 14:52:24 -04:00
Dan Gowans 0aa050dbae fix more test errors 2025-03-18 14:23:41 -04:00
Dan Gowans dce2f75a52 update tested node versions 2025-03-18 13:59:02 -04:00
Dan Gowans 022de4c764 add badges 2025-03-18 13:50:18 -04:00
Dan Gowans c16b8f0294 fix cypress issue 2025-03-18 13:50:13 -04:00
Dan Gowans d4aa83fd7a legacy import 2025-03-18 13:40:03 -04:00
Dan Gowans 545941e69e fix cypress test 2025-03-17 12:40:59 -04:00
Dan Gowans cbdda9e602
Merge pull request #2 from cityssm/deepsource-autofix-76c6eb20
refactor: replace template strings with regular string literals
2025-03-17 12:34:17 -04:00
1226 changed files with 29214 additions and 303127 deletions

View File

@ -10,7 +10,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
node: [ 18, 20, 21 ] node: [ 20, 22, 23 ]
env: env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
@ -25,11 +25,12 @@ jobs:
- name: Install Application - name: Install Application
run: | run: |
npm uninstall puppeteer
npm ci npm ci
npm install -g mocha c8 cypress@13 npm install -g mocha c8 cypress@14
- name: Copy Test Config - name: Copy Test Config
run: cp ./data/config.testing.js ./data/config.js run: cp ./data/testing.config.js ./data/config.js
- name: Test Application Startup - name: Test Application Startup
run: npm run test:startup run: npm run test:startup
@ -43,14 +44,14 @@ jobs:
run: c8 --reporter=lcov --reporter=text --reporter=text-summary mocha --timeout 10000 --exit run: c8 --reporter=lcov --reporter=text --reporter=text-summary mocha --timeout 10000 --exit
- name: Codecov - name: Codecov
if: ${{ github.event_name != 'pull_request' && env.CODECOV_TOKEN != '' && matrix.node == 20 }} if: ${{ github.event_name != 'pull_request' && env.CODECOV_TOKEN != '' && matrix.node == 22 }}
run: | run: |
curl -Os https://uploader.codecov.io/latest/linux/codecov curl -Os https://uploader.codecov.io/latest/linux/codecov
chmod +x codecov chmod +x codecov
./codecov -t ${CODECOV_TOKEN} ./codecov -t ${CODECOV_TOKEN}
- name: DeepSource - name: DeepSource
if: ${{ github.event_name != 'pull_request' && env.DEEPSOURCE_DSN != '' && matrix.node == 20 }} if: ${{ github.event_name != 'pull_request' && env.DEEPSOURCE_DSN != '' && matrix.node == 22 }}
run: | run: |
# Install deepsource CLI # Install deepsource CLI
curl https://deepsource.io/cli | sh curl https://deepsource.io/cli | sh

View File

@ -1,8 +1,3 @@
{ {
"reject": [ "reject": ["puppeteer"]
"@cityssm/bulma-sticky-table",
"@fortawesome/fontawesome-free",
"bulma",
"bulma-calendar"
]
} }

View File

@ -1,4 +1,4 @@
# Thank you for your interest in making the Lot Occupancy System better # Thank you for your interest in making Sunrise CMS better
Together, we can build high quality software that meets the needs of municipalities, Together, we can build high quality software that meets the needs of municipalities,
while remaining open and budget conscious. while remaining open and budget conscious.

View File

@ -1,27 +1,70 @@
<div align=center>
# Sunrise Cemetery Management System (CMS) # Sunrise Cemetery Management System (CMS)
![Sunrise CMS Logo](./public/images/sunrise-cms.png) [![DeepSource](https://app.deepsource.com/gh/cityssm/sunrise-cms.svg/?label=active+issues&show_trend=true&token=AhEAYh9dbdDAe7cgW95_SVqP)](https://app.deepsource.com/gh/cityssm/sunrise-cms/)
[![codecov](https://codecov.io/gh/cityssm/sunrise-cms/graph/badge.svg?token=OY7SWY1PLC)](https://codecov.io/gh/cityssm/sunrise-cms)
[![sunrise-cms](https://img.shields.io/endpoint?url=https://cloud.cypress.io/badge/simple/26a4bi&style=flat&logo=cypress)](https://cloud.cypress.io/projects/26a4bi/runs)
[![Coverage Testing](https://github.com/cityssm/sunrise-cms/actions/workflows/coverage.yml/badge.svg)](https://github.com/cityssm/sunrise-cms/actions/workflows/coverage.yml)
![Sunrise CMS](./docs/images/socialPreview.png)
🚧 **In development** 🚧 🚧 **In development** 🚧
**A web-based application to assist cemetery managers with managing their cemetery records** **A web-based application to assist cemetery managers with managing their cemetery records.**
</div> ![Burial Site View](./docs/images/burialSite-view.png)
This is a major refactoring of the This is a major refactoring of the now archived
[Lot Occupancy System](https://github.com/cityssm/lot-occupancy-system), [Lot Occupancy System](https://github.com/cityssm/lot-occupancy-system),
originally built with multiple focuses. This fork reworks the project to focus exculsively originally built with multiple focuses in mind. This fork completely reworks the project
on cemetery management. to focus exculsively on cemetery management.
[**User Documentation (In the Works)**](./docs/README.md)
## Why Sunrise CMS?
### ✔️ Cemetery Maps are NOT Required
Many cemetery applications rely on maps to drill down into burial sites.
In Sunrise CMS, maps are completely optional, greatly reducing the effort needed to get started,
and reducing the maintenance work when new blocks of burial sites are introduced.
### ✔️ The System Requirements are Very Low
Sunrise CMS does not need an expensive server to run.
No separate database server is required either.
The whole application could run on a current, modest workstation.
### ✔️ Track Unlimited Cemeteries, Unlimited Burial Sites, Unlimited Contracts...
There are no limits to the number of records that can be tracked in Sunrise CMS.
### ✔️ Includes a Simple Built-In Work Order System
In addition to tracking data related to cemetery plots,
Sunrise CMS can also track work order activities, like interments and grave maintenance.
### ✔️ Sunrise CMS is Free and Open Source
There's no cost to use it.
## About this Project ## About this Project
- [Code of Conduct](CODE_OF_CONDUCT.md) - 📘 [Documentation](./docs/README.md)
- [Contributing Guidelines](CONTRIBUTING.md) - 🤗 [Code of Conduct](CODE_OF_CONDUCT.md)
- [Security Policy](SECURITY.md) - 🥰 [Contributing Guidelines](CONTRIBUTING.md)
- [MIT Licence](LICENSE.md) - 🛡️ [Security Policy](SECURITY.md)
- 📃 [MIT Licence](LICENSE.md)
Although the system is quite niche, it's being released in an open source environment in hopes to pool developer resources from other municipalities looking to move away from older, legacy systems. Although the system is quite niche, it's being released in an open source environment in hopes to pool developer resources from other municipalities looking to move away from older, legacy systems.
It is being shared to start the dialog among other municipalities and present an option to those who may be looking to refresh their own cemetery systems. It is being shared to start the dialog among other municipalities and present an option to those who may be looking to refresh their own cemetery systems.
## More City Management Applications from the City of Sault Ste. Marie
[**General Licence Manager**](https://cityssm.github.io/general-licence-manager/)<br />
An application built to manage the general licences issued by municipalities.
[**Attendance Tracking**](https://cityssm.github.io/attendance-tracking/)<br />
Track employee absences, call outs, and more.
💡 Discover even more on [the City of Sault Ste. Marie's GitHub page](https://cityssm.github.io/).

View File

@ -1,2 +1,2 @@
theme: jekyll-theme-cayman theme: jekyll-theme-cayman
title: Sunrise Cemetery Management System title: Sunrise Cemetery Management System (CMS)

88
app.js
View File

@ -1,5 +1,6 @@
import path from 'node:path'; import path from 'node:path';
import * as dateTimeFns from '@cityssm/utils-datetime'; import { secondsToMillis } from '@cityssm/to-millis';
import * as dateTimeFunctions from '@cityssm/utils-datetime';
import compression from 'compression'; import compression from 'compression';
import cookieParser from 'cookie-parser'; import cookieParser from 'cookie-parser';
import csurf from 'csurf'; import csurf from 'csurf';
@ -9,12 +10,12 @@ import rateLimit from 'express-rate-limit';
import session from 'express-session'; import session from 'express-session';
import createError from 'http-errors'; import createError from 'http-errors';
import FileStore from 'session-file-store'; import FileStore from 'session-file-store';
import { initializeDatabase } from './database/initializeDatabase.js'; import dataLists from './data/dataLists.js';
import { DEBUG_NAMESPACE } from './debug.config.js'; import { DEBUG_NAMESPACE } from './debug.config.js';
import * as permissionHandlers from './handlers/permissions.js'; import * as permissionHandlers from './handlers/permissions.js';
import { getSafeRedirectURL } from './helpers/authentication.helpers.js';
import * as configFunctions from './helpers/config.helpers.js'; import * as configFunctions from './helpers/config.helpers.js';
import { useTestDatabases } from './helpers/database.helpers.js'; import { useTestDatabases } from './helpers/database.helpers.js';
import { getSafeRedirectURL } from './helpers/functions.authentication.js';
import * as printFunctions from './helpers/functions.print.js'; import * as printFunctions from './helpers/functions.print.js';
import routerAdmin from './routes/admin.js'; import routerAdmin from './routes/admin.js';
import routerApi from './routes/api.js'; import routerApi from './routes/api.js';
@ -28,11 +29,7 @@ import routerPrint from './routes/print.js';
import routerReports from './routes/reports.js'; import routerReports from './routes/reports.js';
import routerWorkOrders from './routes/workOrders.js'; import routerWorkOrders from './routes/workOrders.js';
import { version } from './version.js'; import { version } from './version.js';
const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`); const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid.toString().padEnd(5)}`);
/*
* INITIALIZE THE DATABASE
*/
await initializeDatabase();
/* /*
* INITIALIZE APP * INITIALIZE APP
*/ */
@ -57,29 +54,18 @@ app.use(express.urlencoded({
extended: false extended: false
})); }));
app.use(cookieParser()); app.use(cookieParser());
app.use(csurf({ app.use(
// eslint-disable-next-line sonarjs/insecure-cookie, sonarjs/cookie-no-httponly
csurf({
cookie: true cookie: true
})); }));
/* /*
* Rate Limiter * Rate Limiter
*/ */
app.use(rateLimit({ app.use(rateLimit({
windowMs: 10_000, max: useTestDatabases ? 1_000_000 : 200,
max: useTestDatabases ? 1_000_000 : 200 windowMs: secondsToMillis(10)
})); }));
/*
* STATIC ROUTES
*/
const urlPrefix = configFunctions.getConfigProperty('reverseProxy.urlPrefix');
if (urlPrefix !== '') {
debug(`urlPrefix = ${urlPrefix}`);
}
app.use(urlPrefix, express.static(path.join('public')));
app.use(`${urlPrefix}/lib/cityssm-bulma-js/bulma-js.js`, express.static(path.join('node_modules', '@cityssm', 'bulma-js', 'dist', 'bulma-js.js')));
app.use(`${urlPrefix}/lib/cityssm-bulma-webapp-js`, express.static(path.join('node_modules', '@cityssm', 'bulma-webapp-js', 'dist')));
app.use(`${urlPrefix}/lib/fa`, express.static(path.join('node_modules', '@fortawesome', 'fontawesome-free')));
app.use(`${urlPrefix}/lib/leaflet`, express.static(path.join('node_modules', 'leaflet', 'dist')));
app.use(`${urlPrefix}/lib/randomcolor/randomColor.js`, express.static(path.join('node_modules', 'randomcolor', 'randomColor.js')));
/* /*
* SESSION MANAGEMENT * SESSION MANAGEMENT
*/ */
@ -87,20 +73,20 @@ const sessionCookieName = configFunctions.getConfigProperty('session.cookieName'
const FileStoreSession = FileStore(session); const FileStoreSession = FileStore(session);
// Initialize session // Initialize session
app.use(session({ app.use(session({
store: new FileStoreSession({
path: './data/sessions',
logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`),
retries: 20
}),
name: sessionCookieName, name: sessionCookieName,
secret: configFunctions.getConfigProperty('session.secret'),
resave: true,
saveUninitialized: false,
rolling: true,
cookie: { cookie: {
maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'), maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'),
sameSite: 'strict' sameSite: 'strict'
} },
secret: configFunctions.getConfigProperty('session.secret'),
store: new FileStoreSession({
logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid.toString().padEnd(5)}`),
path: './data/sessions',
retries: 20
}),
resave: true,
rolling: true,
saveUninitialized: false
})); }));
// Clear cookie if no corresponding session // Clear cookie if no corresponding session
app.use((request, response, next) => { app.use((request, response, next) => {
@ -110,6 +96,34 @@ app.use((request, response, next) => {
} }
next(); next();
}); });
/*
* STATIC ROUTES
*/
const urlPrefix = configFunctions.getConfigProperty('reverseProxy.urlPrefix');
if (urlPrefix !== '') {
debug(`urlPrefix = ${urlPrefix}`);
}
app.use(`${urlPrefix}/internal`, (request, response, next) => {
if (Object.hasOwn(request.session, 'user') &&
Object.hasOwn(request.cookies, sessionCookieName)) {
next();
return;
}
response.sendStatus(403);
}, express.static(configFunctions.getConfigProperty('settings.publicInternalPath')));
app.use(urlPrefix, express.static(path.join('public')));
app.use(`${urlPrefix}/lib/bulma`, express.static(path.join('node_modules', 'bulma', 'css')));
app.use(`${urlPrefix}/lib/bulma-tooltip`, express.static(path.join('node_modules', 'bulma-tooltip', 'dist', 'css')));
app.use(`${urlPrefix}/lib/cityssm-bulma-js/bulma-js.js`, express.static(path.join('node_modules', '@cityssm', 'bulma-js', 'dist', 'bulma-js.js')));
app.use(`${urlPrefix}/lib/cityssm-fa-glow`, express.static(path.join('node_modules', '@cityssm', 'fa-glow')));
app.use(`${urlPrefix}/lib/cityssm-bulma-sticky-table`, express.static(path.join('node_modules', '@cityssm', 'bulma-sticky-table')));
app.use(`${urlPrefix}/lib/cityssm-bulma-webapp-js`, express.static(path.join('node_modules', '@cityssm', 'bulma-webapp-js', 'dist')));
app.use(`${urlPrefix}/lib/fa`, express.static(path.join('node_modules', '@fortawesome', 'fontawesome-free')));
app.use(`${urlPrefix}/lib/leaflet`, express.static(path.join('node_modules', 'leaflet', 'dist')));
app.use(`${urlPrefix}/lib/randomcolor/randomColor.js`, express.static(path.join('node_modules', 'randomcolor', 'randomColor.js')));
/*
* ROUTES
*/
// Redirect logged in users // Redirect logged in users
const sessionChecker = (request, response, next) => { const sessionChecker = (request, response, next) => {
if (Object.hasOwn(request.session, 'user') && if (Object.hasOwn(request.session, 'user') &&
@ -120,9 +134,6 @@ const sessionChecker = (request, response, next) => {
const redirectUrl = getSafeRedirectURL(request.originalUrl); const redirectUrl = getSafeRedirectURL(request.originalUrl);
response.redirect(`${urlPrefix}/login?redirect=${encodeURIComponent(redirectUrl)}`); response.redirect(`${urlPrefix}/login?redirect=${encodeURIComponent(redirectUrl)}`);
}; };
/*
* ROUTES
*/
// Make the user and config objects available to the templates // Make the user and config objects available to the templates
app.use((request, response, next) => { app.use((request, response, next) => {
response.locals.buildNumber = version; response.locals.buildNumber = version;
@ -130,7 +141,8 @@ app.use((request, response, next) => {
response.locals.csrfToken = request.csrfToken(); response.locals.csrfToken = request.csrfToken();
response.locals.configFunctions = configFunctions; response.locals.configFunctions = configFunctions;
response.locals.printFunctions = printFunctions; response.locals.printFunctions = printFunctions;
response.locals.dateTimeFunctions = dateTimeFns; response.locals.dateTimeFunctions = dateTimeFunctions;
response.locals.dataLists = dataLists;
response.locals.urlPrefix = configFunctions.getConfigProperty('reverseProxy.urlPrefix'); response.locals.urlPrefix = configFunctions.getConfigProperty('reverseProxy.urlPrefix');
next(); next();
}); });

146
app.ts
View File

@ -1,6 +1,7 @@
import path from 'node:path' import path from 'node:path'
import * as dateTimeFns from '@cityssm/utils-datetime' import { secondsToMillis } from '@cityssm/to-millis'
import * as dateTimeFunctions from '@cityssm/utils-datetime'
import compression from 'compression' import compression from 'compression'
import cookieParser from 'cookie-parser' import cookieParser from 'cookie-parser'
import csurf from 'csurf' import csurf from 'csurf'
@ -11,12 +12,12 @@ import session from 'express-session'
import createError from 'http-errors' import createError from 'http-errors'
import FileStore from 'session-file-store' import FileStore from 'session-file-store'
import { initializeDatabase } from './database/initializeDatabase.js' import dataLists from './data/dataLists.js'
import { DEBUG_NAMESPACE } from './debug.config.js' import { DEBUG_NAMESPACE } from './debug.config.js'
import * as permissionHandlers from './handlers/permissions.js' import * as permissionHandlers from './handlers/permissions.js'
import { getSafeRedirectURL } from './helpers/authentication.helpers.js'
import * as configFunctions from './helpers/config.helpers.js' import * as configFunctions from './helpers/config.helpers.js'
import { useTestDatabases } from './helpers/database.helpers.js' import { useTestDatabases } from './helpers/database.helpers.js'
import { getSafeRedirectURL } from './helpers/functions.authentication.js'
import * as printFunctions from './helpers/functions.print.js' import * as printFunctions from './helpers/functions.print.js'
import routerAdmin from './routes/admin.js' import routerAdmin from './routes/admin.js'
import routerApi from './routes/api.js' import routerApi from './routes/api.js'
@ -31,13 +32,7 @@ import routerReports from './routes/reports.js'
import routerWorkOrders from './routes/workOrders.js' import routerWorkOrders from './routes/workOrders.js'
import { version } from './version.js' import { version } from './version.js'
const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid}`) const debug = Debug(`${DEBUG_NAMESPACE}:app:${process.pid.toString().padEnd(5)}`)
/*
* INITIALIZE THE DATABASE
*/
await initializeDatabase()
/* /*
* INITIALIZE APP * INITIALIZE APP
@ -76,6 +71,7 @@ app.use(
app.use(cookieParser()) app.use(cookieParser())
app.use( app.use(
// eslint-disable-next-line sonarjs/insecure-cookie, sonarjs/cookie-no-httponly
csurf({ csurf({
cookie: true cookie: true
}) })
@ -87,11 +83,54 @@ app.use(
app.use( app.use(
rateLimit({ rateLimit({
windowMs: 10_000, max: useTestDatabases ? 1_000_000 : 200,
max: useTestDatabases ? 1_000_000 : 200 windowMs: secondsToMillis(10)
}) })
) )
/*
* SESSION MANAGEMENT
*/
const sessionCookieName: string =
configFunctions.getConfigProperty('session.cookieName')
const FileStoreSession = FileStore(session)
// Initialize session
app.use(
session({
name: sessionCookieName,
cookie: {
maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'),
sameSite: 'strict'
},
secret: configFunctions.getConfigProperty('session.secret'),
store: new FileStoreSession({
logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid.toString().padEnd(5)}`),
path: './data/sessions',
retries: 20
}),
resave: true,
rolling: true,
saveUninitialized: false
})
)
// Clear cookie if no corresponding session
app.use((request, response, next) => {
if (
Object.hasOwn(request.cookies, sessionCookieName) &&
!Object.hasOwn(request.session, 'user')
) {
response.clearCookie(sessionCookieName)
}
next()
})
/* /*
* STATIC ROUTES * STATIC ROUTES
*/ */
@ -102,8 +141,34 @@ if (urlPrefix !== '') {
debug(`urlPrefix = ${urlPrefix}`) debug(`urlPrefix = ${urlPrefix}`)
} }
app.use(
`${urlPrefix}/internal`,
(request, response, next) => {
if (
Object.hasOwn(request.session, 'user') &&
Object.hasOwn(request.cookies, sessionCookieName)
) {
next()
return
}
response.sendStatus(403)
},
express.static(configFunctions.getConfigProperty('settings.publicInternalPath'))
)
app.use(urlPrefix, express.static(path.join('public'))) app.use(urlPrefix, express.static(path.join('public')))
app.use(
`${urlPrefix}/lib/bulma`,
express.static(path.join('node_modules', 'bulma', 'css'))
)
app.use(
`${urlPrefix}/lib/bulma-tooltip`,
express.static(path.join('node_modules', 'bulma-tooltip', 'dist', 'css'))
)
app.use( app.use(
`${urlPrefix}/lib/cityssm-bulma-js/bulma-js.js`, `${urlPrefix}/lib/cityssm-bulma-js/bulma-js.js`,
express.static( express.static(
@ -111,6 +176,16 @@ app.use(
) )
) )
app.use(
`${urlPrefix}/lib/cityssm-fa-glow`,
express.static(path.join('node_modules', '@cityssm', 'fa-glow'))
)
app.use(
`${urlPrefix}/lib/cityssm-bulma-sticky-table`,
express.static(path.join('node_modules', '@cityssm', 'bulma-sticky-table'))
)
app.use( app.use(
`${urlPrefix}/lib/cityssm-bulma-webapp-js`, `${urlPrefix}/lib/cityssm-bulma-webapp-js`,
express.static( express.static(
@ -134,46 +209,9 @@ app.use(
) )
/* /*
* SESSION MANAGEMENT * ROUTES
*/ */
const sessionCookieName: string =
configFunctions.getConfigProperty('session.cookieName')
const FileStoreSession = FileStore(session)
// Initialize session
app.use(
session({
store: new FileStoreSession({
path: './data/sessions',
logFn: Debug(`${DEBUG_NAMESPACE}:session:${process.pid}`),
retries: 20
}),
name: sessionCookieName,
secret: configFunctions.getConfigProperty('session.secret'),
resave: true,
saveUninitialized: false,
rolling: true,
cookie: {
maxAge: configFunctions.getConfigProperty('session.maxAgeMillis'),
sameSite: 'strict'
}
})
)
// Clear cookie if no corresponding session
app.use((request, response, next) => {
if (
Object.hasOwn(request.cookies, sessionCookieName) &&
!Object.hasOwn(request.session, 'user')
) {
response.clearCookie(sessionCookieName)
}
next()
})
// Redirect logged in users // Redirect logged in users
const sessionChecker = ( const sessionChecker = (
request: express.Request, request: express.Request,
@ -195,10 +233,6 @@ const sessionChecker = (
) )
} }
/*
* ROUTES
*/
// Make the user and config objects available to the templates // Make the user and config objects available to the templates
app.use((request, response, next) => { app.use((request, response, next) => {
@ -209,7 +243,9 @@ app.use((request, response, next) => {
response.locals.configFunctions = configFunctions response.locals.configFunctions = configFunctions
response.locals.printFunctions = printFunctions response.locals.printFunctions = printFunctions
response.locals.dateTimeFunctions = dateTimeFns response.locals.dateTimeFunctions = dateTimeFunctions
response.locals.dataLists = dataLists
response.locals.urlPrefix = configFunctions.getConfigProperty( response.locals.urlPrefix = configFunctions.getConfigProperty(
'reverseProxy.urlPrefix' 'reverseProxy.urlPrefix'

View File

@ -6,19 +6,26 @@ import ntfyPublish from '@cityssm/ntfy-publish';
import { secondsToMillis } from '@cityssm/to-millis'; import { secondsToMillis } from '@cityssm/to-millis';
import Debug from 'debug'; import Debug from 'debug';
import exitHook from 'exit-hook'; import exitHook from 'exit-hook';
import { initializeDatabase } from '../database/initializeDatabase.js';
import { DEBUG_NAMESPACE } from '../debug.config.js'; import { DEBUG_NAMESPACE } from '../debug.config.js';
import { getConfigProperty } from '../helpers/config.helpers.js'; import { getConfigProperty } from '../helpers/config.helpers.js';
import version from '../version.js';
const debug = Debug(`${DEBUG_NAMESPACE}:www:${process.pid}`); const debug = Debug(`${DEBUG_NAMESPACE}:www:${process.pid}`);
// INITIALIZE THE DATABASE
initializeDatabase();
const directoryName = path.dirname(fileURLToPath(import.meta.url)); const directoryName = path.dirname(fileURLToPath(import.meta.url));
const processCount = Math.min(getConfigProperty('application.maximumProcesses'), os.cpus().length); const processCount = Math.min(getConfigProperty('application.maximumProcesses'), os.cpus().length * 2);
process.title = `${getConfigProperty('application.applicationName')} (Primary)`; const applicationName = getConfigProperty('application.applicationName');
process.title = `${applicationName} (Primary)`;
debug(`Primary pid: ${process.pid}`); debug(`Primary pid: ${process.pid}`);
debug(`Primary title: ${process.title}`); debug(`Primary title: ${process.title}`);
debug(`Version: ${version}`);
debug(`Launching ${processCount} processes`); debug(`Launching ${processCount} processes`);
const clusterSettings = { const clusterSettings = {
exec: `${directoryName}/wwwProcess.js` exec: `${directoryName}/wwwProcess.js`
}; };
cluster.setupPrimary(clusterSettings); cluster.setupPrimary(clusterSettings);
let doShutdown = false;
const activeWorkers = new Map(); const activeWorkers = new Map();
for (let index = 0; index < processCount; index += 1) { for (let index = 0; index < processCount; index += 1) {
const worker = cluster.fork(); const worker = cluster.fork();
@ -26,6 +33,7 @@ for (let index = 0; index < processCount; index += 1) {
} }
cluster.on('message', (worker, message) => { cluster.on('message', (worker, message) => {
for (const [pid, activeWorker] of activeWorkers.entries()) { for (const [pid, activeWorker] of activeWorkers.entries()) {
// eslint-disable-next-line sonarjs/different-types-comparison, @typescript-eslint/no-unnecessary-condition
if (activeWorker === undefined || pid === message.pid) { if (activeWorker === undefined || pid === message.pid) {
continue; continue;
} }
@ -36,24 +44,27 @@ cluster.on('message', (worker, message) => {
cluster.on('exit', (worker) => { cluster.on('exit', (worker) => {
debug(`Worker ${(worker.process.pid ?? 0).toString()} has been killed`); debug(`Worker ${(worker.process.pid ?? 0).toString()} has been killed`);
activeWorkers.delete(worker.process.pid ?? 0); activeWorkers.delete(worker.process.pid ?? 0);
debug('Starting another worker'); if (!doShutdown) {
cluster.fork(); debug('Starting another worker');
const newWorker = cluster.fork();
activeWorkers.set(newWorker.process.pid ?? 0, newWorker);
}
}); });
const ntfyStartupConfig = getConfigProperty('application.ntfyStartup'); const ntfyStartupConfig = getConfigProperty('application.ntfyStartup');
if (ntfyStartupConfig !== undefined) { if (ntfyStartupConfig !== undefined) {
const topic = ntfyStartupConfig.topic; const topic = ntfyStartupConfig.topic;
const server = ntfyStartupConfig.server; const server = ntfyStartupConfig.server;
const ntfyStartupMessage = { const ntfyStartupMessage = {
topic,
title: getConfigProperty('application.applicationName'),
message: 'Application Started', message: 'Application Started',
tags: ['arrow_up'] tags: ['arrow_up'],
title: applicationName,
topic
}; };
const ntfyShutdownMessage = { const ntfyShutdownMessage = {
topic,
title: getConfigProperty('application.applicationName'),
message: 'Application Shut Down', message: 'Application Shut Down',
tags: ['arrow_down'] tags: ['arrow_down'],
title: applicationName,
topic
}; };
if (server !== undefined) { if (server !== undefined) {
ntfyStartupMessage.server = server; ntfyStartupMessage.server = server;
@ -70,7 +81,16 @@ if (process.env.STARTUP_TEST === 'true') {
debug(`Killing processes in ${killSeconds} seconds...`); debug(`Killing processes in ${killSeconds} seconds...`);
setTimeout(() => { setTimeout(() => {
debug('Killing processes'); debug('Killing processes');
doShutdown = true;
// eslint-disable-next-line unicorn/no-process-exit // eslint-disable-next-line unicorn/no-process-exit
process.exit(0); process.exit(0);
}, secondsToMillis(killSeconds)); }, secondsToMillis(killSeconds));
} }
exitHook(() => {
doShutdown = true;
debug('Shutting down...');
for (const worker of activeWorkers.values()) {
debug(`Killing worker ${worker.process.pid}`);
worker.kill();
}
});

View File

@ -8,23 +8,31 @@ import { secondsToMillis } from '@cityssm/to-millis'
import Debug from 'debug' import Debug from 'debug'
import exitHook from 'exit-hook' import exitHook from 'exit-hook'
import { initializeDatabase } from '../database/initializeDatabase.js'
import { DEBUG_NAMESPACE } from '../debug.config.js' import { DEBUG_NAMESPACE } from '../debug.config.js'
import { getConfigProperty } from '../helpers/config.helpers.js' import { getConfigProperty } from '../helpers/config.helpers.js'
import type { WorkerMessage } from '../types/applicationTypes.js' import type { WorkerMessage } from '../types/application.types.js'
import version from '../version.js'
const debug = Debug(`${DEBUG_NAMESPACE}:www:${process.pid}`) const debug = Debug(`${DEBUG_NAMESPACE}:www:${process.pid}`)
// INITIALIZE THE DATABASE
initializeDatabase()
const directoryName = path.dirname(fileURLToPath(import.meta.url)) const directoryName = path.dirname(fileURLToPath(import.meta.url))
const processCount = Math.min( const processCount = Math.min(
getConfigProperty('application.maximumProcesses'), getConfigProperty('application.maximumProcesses'),
os.cpus().length os.cpus().length * 2
) )
process.title = `${getConfigProperty('application.applicationName')} (Primary)` const applicationName = getConfigProperty('application.applicationName')
process.title = `${applicationName} (Primary)`
debug(`Primary pid: ${process.pid}`) debug(`Primary pid: ${process.pid}`)
debug(`Primary title: ${process.title}`) debug(`Primary title: ${process.title}`)
debug(`Version: ${version}`)
debug(`Launching ${processCount} processes`) debug(`Launching ${processCount} processes`)
const clusterSettings = { const clusterSettings = {
@ -33,6 +41,7 @@ const clusterSettings = {
cluster.setupPrimary(clusterSettings) cluster.setupPrimary(clusterSettings)
let doShutdown = false
const activeWorkers = new Map<number, Worker>() const activeWorkers = new Map<number, Worker>()
for (let index = 0; index < processCount; index += 1) { for (let index = 0; index < processCount; index += 1) {
@ -42,6 +51,7 @@ for (let index = 0; index < processCount; index += 1) {
cluster.on('message', (worker, message: WorkerMessage) => { cluster.on('message', (worker, message: WorkerMessage) => {
for (const [pid, activeWorker] of activeWorkers.entries()) { for (const [pid, activeWorker] of activeWorkers.entries()) {
// eslint-disable-next-line sonarjs/different-types-comparison, @typescript-eslint/no-unnecessary-condition
if (activeWorker === undefined || pid === message.pid) { if (activeWorker === undefined || pid === message.pid) {
continue continue
} }
@ -55,8 +65,12 @@ cluster.on('exit', (worker) => {
debug(`Worker ${(worker.process.pid ?? 0).toString()} has been killed`) debug(`Worker ${(worker.process.pid ?? 0).toString()} has been killed`)
activeWorkers.delete(worker.process.pid ?? 0) activeWorkers.delete(worker.process.pid ?? 0)
debug('Starting another worker') if (!doShutdown) {
cluster.fork() debug('Starting another worker')
const newWorker = cluster.fork()
activeWorkers.set(newWorker.process.pid ?? 0, newWorker)
}
}) })
const ntfyStartupConfig = getConfigProperty('application.ntfyStartup') const ntfyStartupConfig = getConfigProperty('application.ntfyStartup')
@ -66,17 +80,17 @@ if (ntfyStartupConfig !== undefined) {
const server = ntfyStartupConfig.server const server = ntfyStartupConfig.server
const ntfyStartupMessage: NtfyMessageOptions = { const ntfyStartupMessage: NtfyMessageOptions = {
topic,
title: getConfigProperty('application.applicationName'),
message: 'Application Started', message: 'Application Started',
tags: ['arrow_up'] tags: ['arrow_up'],
title: applicationName,
topic
} }
const ntfyShutdownMessage: NtfyMessageOptions = { const ntfyShutdownMessage: NtfyMessageOptions = {
topic,
title: getConfigProperty('application.applicationName'),
message: 'Application Shut Down', message: 'Application Shut Down',
tags: ['arrow_down'] tags: ['arrow_down'],
title: applicationName,
topic
} }
if (server !== undefined) { if (server !== undefined) {
@ -100,7 +114,19 @@ if (process.env.STARTUP_TEST === 'true') {
setTimeout(() => { setTimeout(() => {
debug('Killing processes') debug('Killing processes')
doShutdown = true
// eslint-disable-next-line unicorn/no-process-exit // eslint-disable-next-line unicorn/no-process-exit
process.exit(0) process.exit(0)
}, secondsToMillis(killSeconds)) }, secondsToMillis(killSeconds))
} }
exitHook(() => {
doShutdown = true
debug('Shutting down...')
for (const worker of activeWorkers.values()) {
debug(`Killing worker ${worker.process.pid}`)
worker.kill()
}
})

View File

@ -4,9 +4,14 @@ import http from 'node:http';
import Debug from 'debug'; import Debug from 'debug';
import exitHook from 'exit-hook'; import exitHook from 'exit-hook';
import { app } from '../app.js'; import { app } from '../app.js';
import { initializeDatabase } from '../database/initializeDatabase.js';
import { DEBUG_NAMESPACE } from '../debug.config.js'; import { DEBUG_NAMESPACE } from '../debug.config.js';
import { getConfigProperty } from '../helpers/config.helpers.js'; import { getConfigProperty } from '../helpers/config.helpers.js';
const debug = Debug(`${DEBUG_NAMESPACE}:wwwProcess:${process.pid}`); const debug = Debug(`${DEBUG_NAMESPACE}:wwwProcess:${process.pid.toString().padEnd(5)}`);
if (process.send === undefined) {
// INITIALIZE THE DATABASE
initializeDatabase();
}
function onError(error) { function onError(error) {
if (error.syscall !== 'listen') { if (error.syscall !== 'listen') {
throw error; throw error;

View File

@ -7,14 +7,20 @@ import Debug from 'debug'
import exitHook from 'exit-hook' import exitHook from 'exit-hook'
import { app } from '../app.js' import { app } from '../app.js'
import { initializeDatabase } from '../database/initializeDatabase.js'
import { DEBUG_NAMESPACE } from '../debug.config.js' import { DEBUG_NAMESPACE } from '../debug.config.js'
import { getConfigProperty } from '../helpers/config.helpers.js' import { getConfigProperty } from '../helpers/config.helpers.js'
const debug = Debug(`${DEBUG_NAMESPACE}:wwwProcess:${process.pid}`) const debug = Debug(`${DEBUG_NAMESPACE}:wwwProcess:${process.pid.toString().padEnd(5)}`)
if (process.send === undefined) {
// INITIALIZE THE DATABASE
initializeDatabase()
}
interface ServerError extends Error { interface ServerError extends Error {
syscall: string
code: string code: string
syscall: string
} }
function onError(error: ServerError): void { function onError(error: ServerError): void {

View File

@ -1,9 +1,9 @@
import { defineConfig } from 'cypress'; import { defineConfig } from 'cypress';
export default defineConfig({ export default defineConfig({
e2e: { e2e: {
baseUrl: 'http://localhost:7000', baseUrl: 'http://localhost:9000',
projectId: '26a4bi',
specPattern: 'cypress/e2e/**/*.cy.js', specPattern: 'cypress/e2e/**/*.cy.js',
supportFile: false, supportFile: false
projectId: '26a4bi'
} }
}); });

View File

@ -2,9 +2,9 @@ import { defineConfig } from 'cypress'
export default defineConfig({ export default defineConfig({
e2e: { e2e: {
baseUrl: 'http://localhost:7000', baseUrl: 'http://localhost:9000',
projectId: '26a4bi',
specPattern: 'cypress/e2e/**/*.cy.js', specPattern: 'cypress/e2e/**/*.cy.js',
supportFile: false, supportFile: false
projectId: '26a4bi'
} }
}) })

View File

@ -1,6 +1,6 @@
import { getConfigProperty } from '../../../helpers/config.helpers.js' import { getConfigProperty } from '../../../helpers/config.helpers.js'
import { testAdmin } from '../../../test/_globals.js' import { testAdmin } from '../../../test/_globals.js'
import type { Fee } from '../../../types/recordTypes.js' import type { Fee } from '../../../types/record.types.js'
import { ajaxDelayMillis, login, logout } from '../../support/index.js' import { ajaxDelayMillis, login, logout } from '../../support/index.js'
describe('Admin - Fee Management', () => { describe('Admin - Fee Management', () => {

View File

@ -1,6 +1,6 @@
import { getConfigProperty } from '../../../helpers/config.helpers.js' import { getConfigProperty } from '../../../helpers/config.helpers.js'
import { testUpdate } from '../../../test/_globals.js' import { testUpdate } from '../../../test/_globals.js'
import type { Cemetery } from '../../../types/recordTypes.js' import type { Cemetery } from '../../../types/record.types.js'
import { login, logout } from '../../support/index.js' import { login, logout } from '../../support/index.js'
describe('Update - Cemeteries', () => { describe('Update - Cemeteries', () => {

View File

@ -0,0 +1,21 @@
import { testUpdate } from '../../../test/_globals.js';
import { login, logout } from '../../support/index.js';
describe('Update - Funeral Homes', () => {
beforeEach('Loads page', () => {
logout();
login(testUpdate);
});
afterEach(logout);
it('Has a "Create" link on the Funeral Home Search', () => {
cy.visit('/funeralHomes');
cy.location('pathname').should('equal', '/funeralHomes');
cy.get("a[href$='/funeralHomes/new']").should('exist');
});
describe('Creates a New Funeral Home', () => {
it('Has no detectable accessibility issues', () => {
cy.visit('/funeralHomes/new');
cy.injectAxe();
cy.checkA11y();
});
});
});

View File

@ -0,0 +1,25 @@
import { testUpdate } from '../../../test/_globals.js'
import { login, logout } from '../../support/index.js'
describe('Update - Funeral Homes', () => {
beforeEach('Loads page', () => {
logout()
login(testUpdate)
})
afterEach(logout)
it('Has a "Create" link on the Funeral Home Search', () => {
cy.visit('/funeralHomes')
cy.location('pathname').should('equal', '/funeralHomes')
cy.get("a[href$='/funeralHomes/new']").should('exist')
})
describe('Creates a New Funeral Home', () => {
it('Has no detectable accessibility issues', () => {
cy.visit('/funeralHomes/new')
cy.injectAxe()
cy.checkA11y()
})
})
})

View File

@ -1,3 +1,3 @@
import type { Config } from '../types/configTypes.js'; import type { Config } from '../types/config.types.js';
export declare const config: Config; export declare const config: Config;
export default config; export default config;

View File

@ -1,19 +1,21 @@
export const config = { export const config = {
application: {},
session: {},
reverseProxy: {},
users: {},
aliases: {}, aliases: {},
application: {},
reverseProxy: {},
session: {},
settings: { settings: {
fees: {},
burialSites: {},
contracts: {},
workOrders: {},
adminCleanup: {}, adminCleanup: {},
printPdf: {}, burialSites: {},
burialSiteTypes: {},
cemeteries: {},
contracts: {},
dynamicsGP: { dynamicsGP: {
integrationIsEnabled: false integrationIsEnabled: false
} },
} fees: {},
printPdf: {},
workOrders: {}
},
users: {}
}; };
export default config; export default config;

View File

@ -1,22 +1,24 @@
import type { Config } from '../types/configTypes.js' import type { Config } from '../types/config.types.js'
export const config: Config = { export const config: Config = {
application: {},
session: {},
reverseProxy: {},
users: {},
aliases: {}, aliases: {},
application: {},
reverseProxy: {},
session: {},
settings: { settings: {
fees: {},
burialSites: {},
contracts: {},
workOrders: {},
adminCleanup: {}, adminCleanup: {},
printPdf: {}, burialSites: {},
burialSiteTypes: {},
cemeteries: {},
contracts: {},
dynamicsGP: { dynamicsGP: {
integrationIsEnabled: false integrationIsEnabled: false
} },
} fees: {},
printPdf: {},
workOrders: {}
},
users: {}
} }
export default config export default config

View File

@ -1,2 +0,0 @@
export declare const config: import("../types/configTypes.js").Config;
export default config;

View File

@ -1,5 +0,0 @@
import { config as baseConfig } from './config.base.js';
export const config = Object.assign({}, baseConfig);
config.settings.provinceDefault = 'ON';
config.settings.fees.taxPercentageDefault = 13;
export default config;

View File

@ -1,9 +0,0 @@
import { config as baseConfig } from './config.base.js'
export const config = Object.assign({}, baseConfig)
config.settings.provinceDefault = 'ON'
config.settings.fees.taxPercentageDefault = 13
export default config

View File

@ -1,41 +1,54 @@
import type { config as MSSQLConfig } from 'mssql'; import type { config as MSSQLConfig } from 'mssql';
import type { ConfigActiveDirectory, ConfigBurialSiteNameSegments, ConfigNtfyStartup, DynamicsGPLookup } from '../types/configTypes.js'; import type { ConfigActiveDirectory, ConfigBurialSiteNameSegments, ConfigNtfyStartup, DynamicsGPLookup } from '../types/config.types.js';
export declare const configDefaultValues: { export declare const configDefaultValues: {
activeDirectory: ConfigActiveDirectory; activeDirectory: ConfigActiveDirectory;
'application.applicationName': string; 'application.applicationName': string;
'application.backgroundURL': string; 'application.backgroundURL': string;
'application.logoURL': string;
'application.httpPort': number; 'application.httpPort': number;
'application.userDomain': string; 'application.logoURL': string;
'application.useTestDatabases': boolean;
'application.maximumProcesses': number; 'application.maximumProcesses': number;
'application.ntfyStartup': ConfigNtfyStartup | undefined; 'application.ntfyStartup': ConfigNtfyStartup | undefined;
'application.userDomain': string;
'application.useTestDatabases': boolean;
'reverseProxy.disableCompression': boolean; 'reverseProxy.disableCompression': boolean;
'reverseProxy.disableEtag': boolean; 'reverseProxy.disableEtag': boolean;
'reverseProxy.urlPrefix': string; 'reverseProxy.urlPrefix': string;
'session.cookieName': string; 'session.cookieName': string;
'session.secret': string;
'session.maxAgeMillis': number;
'session.doKeepAlive': boolean; 'session.doKeepAlive': boolean;
'users.testing': string[]; 'session.maxAgeMillis': number;
'session.secret': string;
'users.canLogin': string[]; 'users.canLogin': string[];
'users.canUpdate': string[]; 'users.canUpdate': string[];
'users.canUpdateWorkOrders': string[];
'users.isAdmin': string[]; 'users.isAdmin': string[];
'users.testing': string[];
'aliases.externalReceiptNumber': string; 'aliases.externalReceiptNumber': string;
'aliases.workOrderOpenDate': string;
'aliases.workOrderCloseDate': string; 'aliases.workOrderCloseDate': string;
'aliases.workOrderOpenDate': string;
'settings.cityDefault': string; 'settings.cityDefault': string;
'settings.provinceDefault': string; 'settings.provinceDefault': string;
'settings.publicInternalPath': string;
'settings.latitudeMax': number;
'settings.latitudeMin': number;
'settings.longitudeMax': number;
'settings.longitudeMin': number;
'settings.cemeteries.refreshImageChanges': boolean;
'settings.burialSiteTypes.bodyCapacityMaxDefault': number;
'settings.burialSiteTypes.crematedCapacityMaxDefault': number;
'settings.burialSites.burialSiteNameSegments': ConfigBurialSiteNameSegments; 'settings.burialSites.burialSiteNameSegments': ConfigBurialSiteNameSegments;
'settings.burialSites.burialSiteNameSegments.includeCemeteryKey': boolean;
'settings.burialSites.refreshImageChanges': boolean;
'settings.contracts.burialSiteIdIsRequired': boolean; 'settings.contracts.burialSiteIdIsRequired': boolean;
'settings.contracts.contractEndDateIsRequired': boolean;
'settings.contracts.prints': string[]; 'settings.contracts.prints': string[];
'settings.fees.taxPercentageDefault': number; 'settings.fees.taxPercentageDefault': number;
'settings.workOrders.workOrderNumberLength': number; 'settings.workOrders.workOrderNumberLength': number;
'settings.workOrders.workOrderMilestoneDateRecentBeforeDays': number;
'settings.workOrders.workOrderMilestoneDateRecentAfterDays': number;
'settings.workOrders.calendarEmailAddress': string; 'settings.workOrders.calendarEmailAddress': string;
'settings.workOrders.prints': string[]; 'settings.workOrders.prints': string[];
'settings.workOrders.workOrderMilestoneDateRecentAfterDays': number;
'settings.workOrders.workOrderMilestoneDateRecentBeforeDays': number;
'settings.adminCleanup.recordDeleteAgeDays': number; 'settings.adminCleanup.recordDeleteAgeDays': number;
'settings.printPdf.browser': "chrome" | "firefox";
'settings.printPdf.contentDisposition': "attachment" | "inline"; 'settings.printPdf.contentDisposition': "attachment" | "inline";
'settings.dynamicsGP.integrationIsEnabled': boolean; 'settings.dynamicsGP.integrationIsEnabled': boolean;
'settings.dynamicsGP.mssqlConfig': MSSQLConfig; 'settings.dynamicsGP.mssqlConfig': MSSQLConfig;
@ -44,3 +57,4 @@ export declare const configDefaultValues: {
'settings.dynamicsGP.itemNumbers': string[]; 'settings.dynamicsGP.itemNumbers': string[];
'settings.dynamicsGP.trialBalanceCodes': string[]; 'settings.dynamicsGP.trialBalanceCodes': string[];
}; };
export default configDefaultValues;

View File

@ -3,49 +3,65 @@ export const configDefaultValues = {
activeDirectory: undefined, activeDirectory: undefined,
'application.applicationName': 'Sunrise CMS', 'application.applicationName': 'Sunrise CMS',
'application.backgroundURL': '/images/cemetery-background.jpg', 'application.backgroundURL': '/images/cemetery-background.jpg',
'application.logoURL': '/images/sunrise-cms.png', 'application.httpPort': 9000,
'application.httpPort': 7000, 'application.logoURL': '/images/sunrise-cms.svg',
'application.userDomain': '',
'application.useTestDatabases': false,
'application.maximumProcesses': 4, 'application.maximumProcesses': 4,
'application.ntfyStartup': undefined, 'application.ntfyStartup': undefined,
'application.userDomain': '',
'application.useTestDatabases': false,
'reverseProxy.disableCompression': false, 'reverseProxy.disableCompression': false,
'reverseProxy.disableEtag': false, 'reverseProxy.disableEtag': false,
'reverseProxy.urlPrefix': '', 'reverseProxy.urlPrefix': '',
'session.cookieName': 'sunrise-user-sid', 'session.cookieName': 'sunrise-user-sid',
'session.secret': 'cityssm/sunrise',
'session.maxAgeMillis': hoursToMillis(1),
'session.doKeepAlive': false, 'session.doKeepAlive': false,
'users.testing': [], 'session.maxAgeMillis': hoursToMillis(1),
'session.secret': 'cityssm/sunrise',
'users.canLogin': ['administrator'], 'users.canLogin': ['administrator'],
'users.canUpdate': [], 'users.canUpdate': [],
'users.canUpdateWorkOrders': [],
'users.isAdmin': ['administrator'], 'users.isAdmin': ['administrator'],
'users.testing': [],
'aliases.externalReceiptNumber': 'External Receipt Number', 'aliases.externalReceiptNumber': 'External Receipt Number',
'aliases.workOrderOpenDate': 'Order Date',
'aliases.workOrderCloseDate': 'Completion Date', 'aliases.workOrderCloseDate': 'Completion Date',
'aliases.workOrderOpenDate': 'Order Date',
'settings.cityDefault': '', 'settings.cityDefault': '',
'settings.provinceDefault': '', 'settings.provinceDefault': '',
'settings.publicInternalPath': 'public-internal',
'settings.latitudeMax': 90,
'settings.latitudeMin': -90,
'settings.longitudeMax': 180,
'settings.longitudeMin': -180,
'settings.cemeteries.refreshImageChanges': false,
// eslint-disable-next-line no-secrets/no-secrets
'settings.burialSiteTypes.bodyCapacityMaxDefault': 2,
// eslint-disable-next-line no-secrets/no-secrets
'settings.burialSiteTypes.crematedCapacityMaxDefault': 6,
'settings.burialSites.burialSiteNameSegments': { 'settings.burialSites.burialSiteNameSegments': {
includeCemeteryKey: false,
separator: '-', separator: '-',
segments: { segments: {
1: { 1: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: true,
label: 'Plot Number', label: 'Plot Number',
minLength: 1, maxLength: 20,
maxLength: 20 minLength: 1
} }
} }
}, },
'settings.burialSites.burialSiteNameSegments.includeCemeteryKey': false,
'settings.burialSites.refreshImageChanges': false,
'settings.contracts.burialSiteIdIsRequired': true, 'settings.contracts.burialSiteIdIsRequired': true,
'settings.contracts.contractEndDateIsRequired': false,
'settings.contracts.prints': ['screen/contract'], 'settings.contracts.prints': ['screen/contract'],
'settings.fees.taxPercentageDefault': 0, 'settings.fees.taxPercentageDefault': 0,
'settings.workOrders.workOrderNumberLength': 6, 'settings.workOrders.workOrderNumberLength': 6,
'settings.workOrders.workOrderMilestoneDateRecentBeforeDays': 5,
'settings.workOrders.workOrderMilestoneDateRecentAfterDays': 60,
'settings.workOrders.calendarEmailAddress': 'no-reply@127.0.0.1', 'settings.workOrders.calendarEmailAddress': 'no-reply@127.0.0.1',
'settings.workOrders.prints': ['pdf/workOrder', 'pdf/workOrder-commentLog'], 'settings.workOrders.prints': ['pdf/workOrder', 'pdf/workOrder-commentLog'],
'settings.workOrders.workOrderMilestoneDateRecentAfterDays': 60,
'settings.workOrders.workOrderMilestoneDateRecentBeforeDays': 5,
'settings.adminCleanup.recordDeleteAgeDays': 60, 'settings.adminCleanup.recordDeleteAgeDays': 60,
'settings.printPdf.browser': 'chrome',
'settings.printPdf.contentDisposition': 'attachment', 'settings.printPdf.contentDisposition': 'attachment',
'settings.dynamicsGP.integrationIsEnabled': false, 'settings.dynamicsGP.integrationIsEnabled': false,
'settings.dynamicsGP.mssqlConfig': undefined, 'settings.dynamicsGP.mssqlConfig': undefined,
@ -55,3 +71,4 @@ export const configDefaultValues = {
'settings.dynamicsGP.itemNumbers': [], 'settings.dynamicsGP.itemNumbers': [],
'settings.dynamicsGP.trialBalanceCodes': [] 'settings.dynamicsGP.trialBalanceCodes': []
}; };
export default configDefaultValues;

View File

@ -6,70 +6,93 @@ import type {
ConfigBurialSiteNameSegments, ConfigBurialSiteNameSegments,
ConfigNtfyStartup, ConfigNtfyStartup,
DynamicsGPLookup DynamicsGPLookup
} from '../types/configTypes.js' } from '../types/config.types.js'
export const configDefaultValues = { export const configDefaultValues = {
activeDirectory: undefined as unknown as ConfigActiveDirectory, activeDirectory: undefined as unknown as ConfigActiveDirectory,
'application.applicationName': 'Sunrise CMS', 'application.applicationName': 'Sunrise CMS',
'application.backgroundURL': '/images/cemetery-background.jpg', 'application.backgroundURL': '/images/cemetery-background.jpg',
'application.logoURL': '/images/sunrise-cms.png', 'application.httpPort': 9000,
'application.httpPort': 7000, 'application.logoURL': '/images/sunrise-cms.svg',
'application.maximumProcesses': 4,
'application.ntfyStartup': undefined as ConfigNtfyStartup | undefined,
'application.userDomain': '', 'application.userDomain': '',
'application.useTestDatabases': false, 'application.useTestDatabases': false,
'application.maximumProcesses': 4,
'application.ntfyStartup': undefined as ConfigNtfyStartup | undefined,
'reverseProxy.disableCompression': false, 'reverseProxy.disableCompression': false,
'reverseProxy.disableEtag': false, 'reverseProxy.disableEtag': false,
'reverseProxy.urlPrefix': '', 'reverseProxy.urlPrefix': '',
'session.cookieName': 'sunrise-user-sid', 'session.cookieName': 'sunrise-user-sid',
'session.secret': 'cityssm/sunrise',
'session.maxAgeMillis': hoursToMillis(1),
'session.doKeepAlive': false, 'session.doKeepAlive': false,
'session.maxAgeMillis': hoursToMillis(1),
'session.secret': 'cityssm/sunrise',
'users.testing': [] as string[],
'users.canLogin': ['administrator'], 'users.canLogin': ['administrator'],
'users.canUpdate': [] as string[], 'users.canUpdate': [] as string[],
'users.canUpdateWorkOrders': [] as string[],
'users.isAdmin': ['administrator'], 'users.isAdmin': ['administrator'],
'users.testing': [] as string[],
'aliases.externalReceiptNumber': 'External Receipt Number', 'aliases.externalReceiptNumber': 'External Receipt Number',
'aliases.workOrderOpenDate': 'Order Date',
'aliases.workOrderCloseDate': 'Completion Date', 'aliases.workOrderCloseDate': 'Completion Date',
'aliases.workOrderOpenDate': 'Order Date',
'settings.cityDefault': '', 'settings.cityDefault': '',
'settings.provinceDefault': '', 'settings.provinceDefault': '',
'settings.publicInternalPath': 'public-internal',
'settings.latitudeMax': 90,
'settings.latitudeMin': -90,
'settings.longitudeMax': 180,
'settings.longitudeMin': -180,
'settings.cemeteries.refreshImageChanges': false,
// eslint-disable-next-line no-secrets/no-secrets
'settings.burialSiteTypes.bodyCapacityMaxDefault': 2,
// eslint-disable-next-line no-secrets/no-secrets
'settings.burialSiteTypes.crematedCapacityMaxDefault': 6,
'settings.burialSites.burialSiteNameSegments': { 'settings.burialSites.burialSiteNameSegments': {
includeCemeteryKey: false,
separator: '-', separator: '-',
segments: { segments: {
1: { 1: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: true,
label: 'Plot Number', label: 'Plot Number',
minLength: 1, maxLength: 20,
maxLength: 20 minLength: 1
} }
} }
} as unknown as ConfigBurialSiteNameSegments, } as unknown as ConfigBurialSiteNameSegments,
'settings.burialSites.burialSiteNameSegments.includeCemeteryKey': false,
'settings.burialSites.refreshImageChanges': false,
'settings.contracts.burialSiteIdIsRequired': true, 'settings.contracts.burialSiteIdIsRequired': true,
'settings.contracts.contractEndDateIsRequired': false,
'settings.contracts.prints': ['screen/contract'], 'settings.contracts.prints': ['screen/contract'],
'settings.fees.taxPercentageDefault': 0, 'settings.fees.taxPercentageDefault': 0,
'settings.workOrders.workOrderNumberLength': 6, 'settings.workOrders.workOrderNumberLength': 6,
'settings.workOrders.workOrderMilestoneDateRecentBeforeDays': 5,
'settings.workOrders.workOrderMilestoneDateRecentAfterDays': 60,
'settings.workOrders.calendarEmailAddress': 'no-reply@127.0.0.1', 'settings.workOrders.calendarEmailAddress': 'no-reply@127.0.0.1',
'settings.workOrders.prints': ['pdf/workOrder', 'pdf/workOrder-commentLog'], 'settings.workOrders.prints': ['pdf/workOrder', 'pdf/workOrder-commentLog'],
'settings.workOrders.workOrderMilestoneDateRecentAfterDays': 60,
'settings.workOrders.workOrderMilestoneDateRecentBeforeDays': 5,
'settings.adminCleanup.recordDeleteAgeDays': 60, 'settings.adminCleanup.recordDeleteAgeDays': 60,
'settings.printPdf.browser': 'chrome' as 'chrome' | 'firefox',
'settings.printPdf.contentDisposition': 'attachment' as 'settings.printPdf.contentDisposition': 'attachment' as
| 'attachment' | 'attachment'
| 'inline', | 'inline',
@ -84,3 +107,5 @@ export const configDefaultValues = {
'settings.dynamicsGP.itemNumbers': [] as string[], 'settings.dynamicsGP.itemNumbers': [] as string[],
'settings.dynamicsGP.trialBalanceCodes': [] as string[] 'settings.dynamicsGP.trialBalanceCodes': [] as string[]
} }
export default configDefaultValues

9
data/dataLists.d.ts vendored 100644
View File

@ -0,0 +1,9 @@
export declare const deathAgePeriods: readonly ["Years", "Months", "Days", "Stillborn"];
export declare const purchaserRelationships: readonly ["Spouse", "Husband", "Wife", "Child", "Parent", "Sibling", "Friend", "Self"];
export declare const directionsOfArrival: readonly ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];
declare const _default: {
deathAgePeriods: readonly ["Years", "Months", "Days", "Stillborn"];
directionsOfArrival: readonly ["N", "NE", "E", "SE", "S", "SW", "W", "NW"];
purchaserRelationships: readonly ["Spouse", "Husband", "Wife", "Child", "Parent", "Sibling", "Friend", "Self"];
};
export default _default;

26
data/dataLists.js 100644
View File

@ -0,0 +1,26 @@
export const deathAgePeriods = ['Years', 'Months', 'Days', 'Stillborn'];
export const purchaserRelationships = [
'Spouse',
'Husband',
'Wife',
'Child',
'Parent',
'Sibling',
'Friend',
'Self'
];
export const directionsOfArrival = [
'N',
'NE',
'E',
'SE',
'S',
'SW',
'W',
'NW'
];
export default {
deathAgePeriods,
directionsOfArrival,
purchaserRelationships
};

29
data/dataLists.ts 100644
View File

@ -0,0 +1,29 @@
export const deathAgePeriods = ['Years', 'Months', 'Days', 'Stillborn'] as const
export const purchaserRelationships = [
'Spouse',
'Husband',
'Wife',
'Child',
'Parent',
'Sibling',
'Friend',
'Self'
] as const
export const directionsOfArrival = [
'N',
'NE',
'E',
'SE',
'S',
'SW',
'W',
'NW'
] as const
export default {
deathAgePeriods,
directionsOfArrival,
purchaserRelationships
}

2
data/ontario.config.d.ts vendored 100644
View File

@ -0,0 +1,2 @@
export declare const config: import("../types/config.types.js").Config;
export default config;

View File

@ -0,0 +1,9 @@
import { config as baseConfig } from './base.config.js';
export const config = Object.assign({}, baseConfig);
config.settings.provinceDefault = 'ON';
config.settings.latitudeMax = 56.85;
config.settings.latitudeMin = 41.68;
config.settings.longitudeMax = -74;
config.settings.longitudeMin = -95.15;
config.settings.fees.taxPercentageDefault = 13;
export default config;

View File

@ -0,0 +1,15 @@
import { config as baseConfig } from './base.config.js'
export const config = Object.assign({}, baseConfig)
config.settings.provinceDefault = 'ON'
config.settings.latitudeMax = 56.85
config.settings.latitudeMin = 41.68
config.settings.longitudeMax = -74
config.settings.longitudeMin = -95.15
config.settings.fees.taxPercentageDefault = 13
export default config

View File

@ -1,3 +1,3 @@
import type { Config } from '../types/configTypes.js'; import type { Config } from '../types/config.types.js';
export declare const config: Config; export declare const config: Config;
export default config; export default config;

View File

@ -1,45 +1,52 @@
import { config as cemeteryConfig } from './config.baseOntario.js'; import { config as cemeteryConfig } from './ontario.config.js';
export const config = { ...cemeteryConfig }; export const config = { ...cemeteryConfig };
config.aliases.externalReceiptNumber = 'GP Receipt Number'; config.aliases.externalReceiptNumber = 'GP Receipt Number';
config.settings.publicInternalPath =
'../sunrise-cms-saultstemarie/public-internal';
config.settings.burialSites.burialSiteNameSegments = { config.settings.burialSites.burialSiteNameSegments = {
separator: '-',
includeCemeteryKey: true, includeCemeteryKey: true,
separator: '-',
segments: { segments: {
1: { 1: {
isRequired: false,
isAvailable: true, isAvailable: true,
isRequired: false,
label: 'Block', label: 'Block',
minLength: 1, maxLength: 1,
maxLength: 1 minLength: 1
}, },
2: { 2: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: false,
label: 'Range', label: 'Range',
minLength: 1, maxLength: 3,
maxLength: 3 minLength: 1
}, },
3: { 3: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: true,
label: 'Lot', label: 'Lot',
minLength: 1, maxLength: 4,
maxLength: 4 minLength: 1
}, },
4: { 4: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: true,
label: 'Grave', label: 'Grave',
minLength: 1, maxLength: 2,
maxLength: 2 minLength: 1
} }
} }
}; };
config.settings.cityDefault = 'Sault Ste. Marie'; config.settings.cityDefault = 'Sault Ste. Marie';
config.settings.latitudeMax = 46.75;
config.settings.latitudeMin = 46.4;
config.settings.longitudeMax = -84.2;
config.settings.longitudeMin = -84.5;
config.settings.contracts.prints = [ config.settings.contracts.prints = [
'pdf/ssm.cemetery.burialPermit', 'pdf/ssm.cemetery.burialPermit',
'pdf/ssm.cemetery.contract' 'pdf/ssm.cemetery.contract'
]; ];
config.settings.printPdf.browser = 'firefox';
config.settings.workOrders.workOrderNumberLength = 6; config.settings.workOrders.workOrderNumberLength = 6;
config.settings.workOrders.workOrderMilestoneDateRecentBeforeDays = 7; config.settings.workOrders.workOrderMilestoneDateRecentBeforeDays = 7;
config.settings.workOrders.workOrderMilestoneDateRecentAfterDays = 30; config.settings.workOrders.workOrderMilestoneDateRecentAfterDays = 30;

View File

@ -1,53 +1,64 @@
import type { Config } from '../types/configTypes.js' import type { Config } from '../types/config.types.js'
import { config as cemeteryConfig } from './config.baseOntario.js' import { config as cemeteryConfig } from './ontario.config.js'
export const config: Config = { ...cemeteryConfig } export const config: Config = { ...cemeteryConfig }
config.aliases.externalReceiptNumber = 'GP Receipt Number' config.aliases.externalReceiptNumber = 'GP Receipt Number'
config.settings.publicInternalPath =
'../sunrise-cms-saultstemarie/public-internal'
config.settings.burialSites.burialSiteNameSegments = { config.settings.burialSites.burialSiteNameSegments = {
separator: '-',
includeCemeteryKey: true, includeCemeteryKey: true,
separator: '-',
segments: { segments: {
1: { 1: {
isRequired: false,
isAvailable: true, isAvailable: true,
isRequired: false,
label: 'Block', label: 'Block',
minLength: 1, maxLength: 1,
maxLength: 1 minLength: 1
}, },
2: { 2: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: false,
label: 'Range', label: 'Range',
minLength: 1, maxLength: 3,
maxLength: 3 minLength: 1
}, },
3: { 3: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: true,
label: 'Lot', label: 'Lot',
minLength: 1, maxLength: 4,
maxLength: 4 minLength: 1
}, },
4: { 4: {
isRequired: true,
isAvailable: true, isAvailable: true,
isRequired: true,
label: 'Grave', label: 'Grave',
minLength: 1, maxLength: 2,
maxLength: 2 minLength: 1
} }
} }
} }
config.settings.cityDefault = 'Sault Ste. Marie' config.settings.cityDefault = 'Sault Ste. Marie'
config.settings.latitudeMax = 46.75
config.settings.latitudeMin = 46.4
config.settings.longitudeMax = -84.2
config.settings.longitudeMin = -84.5
config.settings.contracts.prints = [ config.settings.contracts.prints = [
'pdf/ssm.cemetery.burialPermit', 'pdf/ssm.cemetery.burialPermit',
'pdf/ssm.cemetery.contract' 'pdf/ssm.cemetery.contract'
] ]
config.settings.printPdf.browser = 'firefox'
config.settings.workOrders.workOrderNumberLength = 6 config.settings.workOrders.workOrderNumberLength = 6
config.settings.workOrders.workOrderMilestoneDateRecentBeforeDays = 7 config.settings.workOrders.workOrderMilestoneDateRecentBeforeDays = 7
config.settings.workOrders.workOrderMilestoneDateRecentAfterDays = 30 config.settings.workOrders.workOrderMilestoneDateRecentAfterDays = 30

View File

@ -1,3 +1,3 @@
import type { Config } from '../types/configTypes.js'; import type { Config } from '../types/config.types.js';
export declare const config: Config; export declare const config: Config;
export default config; export default config;

View File

@ -1,12 +1,14 @@
import { config as cemeteryConfig } from './config.baseSsm.js'; import { config as cemeteryConfig } from './ssm.ontario.config.js';
export const config = { ...cemeteryConfig }; export const config = { ...cemeteryConfig };
config.application.useTestDatabases = true; config.application.useTestDatabases = true;
config.session.doKeepAlive = true; config.session.doKeepAlive = true;
config.users = { config.users = {
testing: ['*testView', '*testUpdate', '*testAdmin'],
canLogin: ['*testView', '*testUpdate', '*testAdmin'], canLogin: ['*testView', '*testUpdate', '*testAdmin'],
canUpdate: ['*testUpdate'], canUpdate: ['*testUpdate'],
isAdmin: ['*testAdmin'] canUpdateWorkOrders: ['*testUpdate'],
isAdmin: ['*testAdmin'],
testing: ['*testView', '*testUpdate', '*testAdmin']
}; };
config.settings.publicInternalPath = 'public-internal';
config.settings.dynamicsGP.integrationIsEnabled = false; config.settings.dynamicsGP.integrationIsEnabled = false;
export default config; export default config;

View File

@ -1,6 +1,6 @@
import type { Config } from '../types/configTypes.js' import type { Config } from '../types/config.types.js'
import { config as cemeteryConfig } from './config.baseSsm.js' import { config as cemeteryConfig } from './ssm.ontario.config.js'
export const config: Config = { ...cemeteryConfig } export const config: Config = { ...cemeteryConfig }
@ -9,12 +9,15 @@ config.application.useTestDatabases = true
config.session.doKeepAlive = true config.session.doKeepAlive = true
config.users = { config.users = {
testing: ['*testView', '*testUpdate', '*testAdmin'],
canLogin: ['*testView', '*testUpdate', '*testAdmin'], canLogin: ['*testView', '*testUpdate', '*testAdmin'],
canUpdate: ['*testUpdate'], canUpdate: ['*testUpdate'],
isAdmin: ['*testAdmin'] canUpdateWorkOrders: ['*testUpdate'],
isAdmin: ['*testAdmin'],
testing: ['*testView', '*testUpdate', '*testAdmin']
} }
config.settings.publicInternalPath = 'public-internal'
config.settings.dynamicsGP!.integrationIsEnabled = false config.settings.dynamicsGP!.integrationIsEnabled = false
export default config export default config

View File

@ -1,16 +1,29 @@
export interface AddBurialSiteForm { export interface AddBurialSiteForm {
burialSiteNameSegment1: string; burialSiteNameSegment1?: string;
burialSiteNameSegment2?: string; burialSiteNameSegment2?: string;
burialSiteNameSegment3?: string; burialSiteNameSegment3?: string;
burialSiteNameSegment4?: string; burialSiteNameSegment4?: string;
burialSiteNameSegment5?: string; burialSiteNameSegment5?: string;
burialSiteTypeId: string | number; burialSiteStatusId: number | string;
burialSiteStatusId: string | number; burialSiteTypeId: number | string;
cemeteryId: string | number; bodyCapacity?: number | string;
cemeterySvgId: string; crematedCapacity?: number | string;
burialSiteLatitude: string; burialSiteImage?: string;
burialSiteLongitude: string; cemeteryId: number | string;
cemeterySvgId?: string;
burialSiteLatitude?: string;
burialSiteLongitude?: string;
burialSiteTypeFieldIds?: string; burialSiteTypeFieldIds?: string;
[fieldValue_burialSiteTypeFieldId: string]: unknown; [fieldValue_burialSiteTypeFieldId: string]: unknown;
} }
export default function addBurialSite(burialSiteForm: AddBurialSiteForm, user: User): Promise<number>; /**
* Creates a new burial site.
* @param burialSiteForm - The new burial site's information
* @param user - The user making the request
* @returns The new burial site's id.
* @throws If an active burial site with the same name already exists.
*/
export default function addBurialSite(burialSiteForm: AddBurialSiteForm, user: User): {
burialSiteId: number;
burialSiteName: string;
};

View File

@ -1,12 +1,35 @@
import sqlite from 'better-sqlite3';
import { buildBurialSiteName } from '../helpers/burialSites.helpers.js'; import { buildBurialSiteName } from '../helpers/burialSites.helpers.js';
import { sunriseDB } from '../helpers/database.helpers.js';
import addOrUpdateBurialSiteField from './addOrUpdateBurialSiteField.js'; import addOrUpdateBurialSiteField from './addOrUpdateBurialSiteField.js';
import getCemetery from './getCemetery.js'; import getCemetery from './getCemetery.js';
import { acquireConnection } from './pool.js'; /**
export default async function addBurialSite(burialSiteForm, user) { * Creates a new burial site.
const database = await acquireConnection(); * @param burialSiteForm - The new burial site's information
* @param user - The user making the request
* @returns The new burial site's id.
* @throws If an active burial site with the same name already exists.
*/
// eslint-disable-next-line complexity
export default function addBurialSite(burialSiteForm, user) {
const database = sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const cemetery = burialSiteForm.cemeteryId === '' ? undefined : await getCemetery(burialSiteForm.cemeteryId, database); const cemetery = burialSiteForm.cemeteryId === ''
? undefined
: getCemetery(burialSiteForm.cemeteryId, database);
const burialSiteName = buildBurialSiteName(cemetery?.cemeteryKey, burialSiteForm); const burialSiteName = buildBurialSiteName(cemetery?.cemeteryKey, burialSiteForm);
// Ensure no active burial sites share the same name
const existingBurialSite = database
.prepare(`select burialSiteId
from BurialSites
where burialSiteName = ?
and recordDelete_timeMillis is null`)
.pluck()
.get(burialSiteName);
if (existingBurialSite !== undefined) {
database.close();
throw new Error('An active burial site with that name already exists.');
}
const result = database const result = database
.prepare(`insert into BurialSites ( .prepare(`insert into BurialSites (
burialSiteNameSegment1, burialSiteNameSegment1,
@ -16,27 +39,41 @@ export default async function addBurialSite(burialSiteForm, user) {
burialSiteNameSegment5, burialSiteNameSegment5,
burialSiteName, burialSiteName,
burialSiteTypeId, burialSiteStatusId, burialSiteTypeId, burialSiteStatusId,
cemeteryId, cemeterySvgId, bodyCapacity, crematedCapacity,
cemeteryId, cemeterySvgId, burialSiteImage,
burialSiteLatitude, burialSiteLongitude, burialSiteLatitude, burialSiteLongitude,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, values (?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?)`) ?, ?, ?, ?)`)
.run(burialSiteForm.burialSiteNameSegment1, burialSiteForm.burialSiteNameSegment2 ?? '', burialSiteForm.burialSiteNameSegment3 ?? '', burialSiteForm.burialSiteNameSegment4 ?? '', burialSiteForm.burialSiteNameSegment5 ?? '', burialSiteName, burialSiteForm.burialSiteTypeId, burialSiteForm.burialSiteStatusId === '' ? undefined : burialSiteForm.burialSiteStatusId, burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId, burialSiteForm.cemeterySvgId, burialSiteForm.burialSiteLatitude === '' ? undefined : burialSiteForm.burialSiteLatitude, burialSiteForm.burialSiteLongitude === '' ? undefined : burialSiteForm.burialSiteLongitude, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(burialSiteForm.burialSiteNameSegment1 ?? '', burialSiteForm.burialSiteNameSegment2 ?? '', burialSiteForm.burialSiteNameSegment3 ?? '', burialSiteForm.burialSiteNameSegment4 ?? '', burialSiteForm.burialSiteNameSegment5 ?? '', burialSiteName, burialSiteForm.burialSiteTypeId, burialSiteForm.burialSiteStatusId === ''
? undefined
: burialSiteForm.burialSiteStatusId, burialSiteForm.bodyCapacity === ''
? undefined
: burialSiteForm.bodyCapacity, burialSiteForm.crematedCapacity === ''
? undefined
: burialSiteForm.crematedCapacity, burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId, burialSiteForm.cemeterySvgId, burialSiteForm.burialSiteImage ?? '', burialSiteForm.burialSiteLatitude === ''
? undefined
: burialSiteForm.burialSiteLatitude, burialSiteForm.burialSiteLongitude === ''
? undefined
: burialSiteForm.burialSiteLongitude, user.userName, rightNowMillis, user.userName, rightNowMillis);
const burialSiteId = result.lastInsertRowid; const burialSiteId = result.lastInsertRowid;
const burialSiteTypeFieldIds = (burialSiteForm.burialSiteTypeFieldIds ?? '').split(','); const burialSiteTypeFieldIds = (burialSiteForm.burialSiteTypeFieldIds ?? '').split(',');
for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) { for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) {
const fieldValue = burialSiteForm[`burialSiteFieldValue_${burialSiteTypeFieldId}`]; const fieldValue = burialSiteForm[`burialSiteFieldValue_${burialSiteTypeFieldId}`];
if ((fieldValue ?? '') !== '') { if ((fieldValue ?? '') !== '') {
await addOrUpdateBurialSiteField({ addOrUpdateBurialSiteField({
burialSiteId, burialSiteId,
burialSiteTypeFieldId, burialSiteTypeFieldId,
fieldValue: fieldValue ?? '' fieldValue: fieldValue ?? ''
}, user, database); }, user, database);
} }
} }
database.release(); database.close();
return burialSiteId; return {
burialSiteId,
burialSiteName
};
} }

View File

@ -1,42 +1,78 @@
import sqlite from 'better-sqlite3'
import { buildBurialSiteName } from '../helpers/burialSites.helpers.js' import { buildBurialSiteName } from '../helpers/burialSites.helpers.js'
import { sunriseDB } from '../helpers/database.helpers.js'
import addOrUpdateBurialSiteField from './addOrUpdateBurialSiteField.js' import addOrUpdateBurialSiteField from './addOrUpdateBurialSiteField.js'
import getCemetery from './getCemetery.js' import getCemetery from './getCemetery.js'
import { acquireConnection } from './pool.js'
export interface AddBurialSiteForm { export interface AddBurialSiteForm {
burialSiteNameSegment1: string burialSiteNameSegment1?: string
burialSiteNameSegment2?: string burialSiteNameSegment2?: string
burialSiteNameSegment3?: string burialSiteNameSegment3?: string
burialSiteNameSegment4?: string burialSiteNameSegment4?: string
burialSiteNameSegment5?: string burialSiteNameSegment5?: string
burialSiteTypeId: string | number burialSiteStatusId: number | string
burialSiteStatusId: string | number burialSiteTypeId: number | string
cemeteryId: string | number bodyCapacity?: number | string
cemeterySvgId: string crematedCapacity?: number | string
burialSiteLatitude: string burialSiteImage?: string
burialSiteLongitude: string cemeteryId: number | string
cemeterySvgId?: string
burialSiteLatitude?: string
burialSiteLongitude?: string
burialSiteTypeFieldIds?: string burialSiteTypeFieldIds?: string
[fieldValue_burialSiteTypeFieldId: string]: unknown [fieldValue_burialSiteTypeFieldId: string]: unknown
} }
export default async function addBurialSite( /**
* Creates a new burial site.
* @param burialSiteForm - The new burial site's information
* @param user - The user making the request
* @returns The new burial site's id.
* @throws If an active burial site with the same name already exists.
*/
// eslint-disable-next-line complexity
export default function addBurialSite(
burialSiteForm: AddBurialSiteForm, burialSiteForm: AddBurialSiteForm,
user: User user: User
): Promise<number> { ): { burialSiteId: number; burialSiteName: string } {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
const cemetery = burialSiteForm.cemeteryId === '' ? undefined : await getCemetery(burialSiteForm.cemeteryId, database) const cemetery =
burialSiteForm.cemeteryId === ''
? undefined
: getCemetery(burialSiteForm.cemeteryId, database)
const burialSiteName = buildBurialSiteName( const burialSiteName = buildBurialSiteName(
cemetery?.cemeteryKey, cemetery?.cemeteryKey,
burialSiteForm) burialSiteForm
)
// Ensure no active burial sites share the same name
const existingBurialSite = database
.prepare(
`select burialSiteId
from BurialSites
where burialSiteName = ?
and recordDelete_timeMillis is null`
)
.pluck()
.get(burialSiteName) as number | undefined
if (existingBurialSite !== undefined) {
database.close()
throw new Error('An active burial site with that name already exists.')
}
const result = database const result = database
.prepare( .prepare(
@ -48,28 +84,45 @@ export default async function addBurialSite(
burialSiteNameSegment5, burialSiteNameSegment5,
burialSiteName, burialSiteName,
burialSiteTypeId, burialSiteStatusId, burialSiteTypeId, burialSiteStatusId,
cemeteryId, cemeterySvgId, bodyCapacity, crematedCapacity,
cemeteryId, cemeterySvgId, burialSiteImage,
burialSiteLatitude, burialSiteLongitude, burialSiteLatitude, burialSiteLongitude,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, values (?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?)` ?, ?, ?, ?)`
) )
.run( .run(
burialSiteForm.burialSiteNameSegment1, burialSiteForm.burialSiteNameSegment1 ?? '',
burialSiteForm.burialSiteNameSegment2 ?? '', burialSiteForm.burialSiteNameSegment2 ?? '',
burialSiteForm.burialSiteNameSegment3 ?? '', burialSiteForm.burialSiteNameSegment3 ?? '',
burialSiteForm.burialSiteNameSegment4 ?? '', burialSiteForm.burialSiteNameSegment4 ?? '',
burialSiteForm.burialSiteNameSegment5 ?? '', burialSiteForm.burialSiteNameSegment5 ?? '',
burialSiteName, burialSiteName,
burialSiteForm.burialSiteTypeId, burialSiteForm.burialSiteTypeId,
burialSiteForm.burialSiteStatusId === '' ? undefined : burialSiteForm.burialSiteStatusId, burialSiteForm.burialSiteStatusId === ''
? undefined
: burialSiteForm.burialSiteStatusId,
burialSiteForm.bodyCapacity === ''
? undefined
: burialSiteForm.bodyCapacity,
burialSiteForm.crematedCapacity === ''
? undefined
: burialSiteForm.crematedCapacity,
burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId, burialSiteForm.cemeteryId === '' ? undefined : burialSiteForm.cemeteryId,
burialSiteForm.cemeterySvgId, burialSiteForm.cemeterySvgId,
burialSiteForm.burialSiteLatitude === '' ? undefined : burialSiteForm.burialSiteLatitude, burialSiteForm.burialSiteImage ?? '',
burialSiteForm.burialSiteLongitude === '' ? undefined : burialSiteForm.burialSiteLongitude, burialSiteForm.burialSiteLatitude === ''
? undefined
: burialSiteForm.burialSiteLatitude,
burialSiteForm.burialSiteLongitude === ''
? undefined
: burialSiteForm.burialSiteLongitude,
user.userName, user.userName,
rightNowMillis, rightNowMillis,
user.userName, user.userName,
@ -78,13 +131,17 @@ export default async function addBurialSite(
const burialSiteId = result.lastInsertRowid as number const burialSiteId = result.lastInsertRowid as number
const burialSiteTypeFieldIds = (burialSiteForm.burialSiteTypeFieldIds ?? '').split(',') const burialSiteTypeFieldIds = (
burialSiteForm.burialSiteTypeFieldIds ?? ''
).split(',')
for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) { for (const burialSiteTypeFieldId of burialSiteTypeFieldIds) {
const fieldValue = burialSiteForm[`burialSiteFieldValue_${burialSiteTypeFieldId}`] as string | undefined const fieldValue = burialSiteForm[
`burialSiteFieldValue_${burialSiteTypeFieldId}`
] as string | undefined
if ((fieldValue ?? '') !== '') { if ((fieldValue ?? '') !== '') {
await addOrUpdateBurialSiteField( addOrUpdateBurialSiteField(
{ {
burialSiteId, burialSiteId,
burialSiteTypeFieldId, burialSiteTypeFieldId,
@ -96,7 +153,10 @@ export default async function addBurialSite(
} }
} }
database.release() database.close()
return burialSiteId return {
burialSiteId,
burialSiteName
}
} }

View File

@ -2,4 +2,4 @@ export interface AddBurialSiteCommentForm {
burialSiteId: string; burialSiteId: string;
comment: string; comment: string;
} }
export default function addBurialSiteComment(commentForm: AddBurialSiteCommentForm, user: User): Promise<number>; export default function addBurialSiteComment(commentForm: AddBurialSiteCommentForm, user: User): number;

View File

@ -1,7 +1,8 @@
import { dateToInteger, dateToTimeInteger } from '@cityssm/utils-datetime'; import { dateToInteger, dateToTimeInteger } from '@cityssm/utils-datetime';
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addBurialSiteComment(commentForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = await acquireConnection(); export default function addBurialSiteComment(commentForm, user) {
const database = sqlite(sunriseDB);
const rightNow = new Date(); const rightNow = new Date();
const result = database const result = database
.prepare(`insert into BurialSiteComments ( .prepare(`insert into BurialSiteComments (
@ -11,6 +12,6 @@ export default async function addBurialSiteComment(commentForm, user) {
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?)`)
.run(commentForm.burialSiteId, dateToInteger(rightNow), dateToTimeInteger(rightNow), commentForm.comment, user.userName, rightNow.getTime(), user.userName, rightNow.getTime()); .run(commentForm.burialSiteId, dateToInteger(rightNow), dateToTimeInteger(rightNow), commentForm.comment, user.userName, rightNow.getTime(), user.userName, rightNow.getTime());
database.release(); database.close();
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,17 +1,18 @@
import { dateToInteger, dateToTimeInteger } from '@cityssm/utils-datetime' import { dateToInteger, dateToTimeInteger } from '@cityssm/utils-datetime'
import sqlite from 'better-sqlite3'
import { acquireConnection } from './pool.js' import { sunriseDB } from '../helpers/database.helpers.js'
export interface AddBurialSiteCommentForm { export interface AddBurialSiteCommentForm {
burialSiteId: string burialSiteId: string
comment: string comment: string
} }
export default async function addBurialSiteComment( export default function addBurialSiteComment(
commentForm: AddBurialSiteCommentForm, commentForm: AddBurialSiteCommentForm,
user: User user: User
): Promise<number> { ): number {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNow = new Date() const rightNow = new Date()
@ -35,7 +36,7 @@ export default async function addBurialSiteComment(
rightNow.getTime() rightNow.getTime()
) )
database.release() database.close()
return result.lastInsertRowid as number return result.lastInsertRowid as number
} }

View File

@ -0,0 +1,7 @@
export interface AddBurialSiteTypeForm {
burialSiteType: string;
bodyCapacityMax: number | string;
crematedCapacityMax: number | string;
orderNumber?: number | string;
}
export default function addBurialSiteType(addForm: AddBurialSiteTypeForm, user: User): number;

View File

@ -0,0 +1,20 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { clearCacheByTableName } from '../helpers/functions.cache.js';
export default function addBurialSiteType(addForm, user) {
const database = sqlite(sunriseDB);
const rightNowMillis = Date.now();
const result = database
.prepare(`insert into BurialSiteTypes (
burialSiteType, bodyCapacityMax, crematedCapacityMax,
orderNumber,
recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.burialSiteType, addForm.bodyCapacityMax === '' ? undefined : addForm.bodyCapacityMax, addForm.crematedCapacityMax === ''
? undefined
: addForm.crematedCapacityMax, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.close();
clearCacheByTableName('BurialSiteTypes');
return result.lastInsertRowid;
}

View File

@ -0,0 +1,50 @@
import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import { clearCacheByTableName } from '../helpers/functions.cache.js'
export interface AddBurialSiteTypeForm {
burialSiteType: string
bodyCapacityMax: number | string
crematedCapacityMax: number | string
orderNumber?: number | string
}
export default function addBurialSiteType(
addForm: AddBurialSiteTypeForm,
user: User
): number {
const database = sqlite(sunriseDB)
const rightNowMillis = Date.now()
const result = database
.prepare(
`insert into BurialSiteTypes (
burialSiteType, bodyCapacityMax, crematedCapacityMax,
orderNumber,
recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?)`
)
.run(
addForm.burialSiteType,
addForm.bodyCapacityMax === '' ? undefined : addForm.bodyCapacityMax,
addForm.crematedCapacityMax === ''
? undefined
: addForm.crematedCapacityMax,
addForm.orderNumber ?? -1,
user.userName,
rightNowMillis,
user.userName,
rightNowMillis
)
database.close()
clearCacheByTableName('BurialSiteTypes')
return result.lastInsertRowid as number
}

View File

@ -1,12 +1,12 @@
export interface AddBurialSiteTypeFieldForm { export interface AddBurialSiteTypeFieldForm {
burialSiteTypeId: string | number; burialSiteTypeId: number | string;
burialSiteTypeField: string; burialSiteTypeField: string;
fieldType?: string; fieldType?: string;
fieldValues?: string; fieldValues?: string;
isRequired?: string; isRequired?: string;
maxLength?: number | string;
minLength?: number | string;
pattern?: string; pattern?: string;
minLength?: string | number;
maxLength?: string | number;
orderNumber?: number; orderNumber?: number;
} }
export default function addBurialSiteTypeField(addForm: AddBurialSiteTypeFieldForm, user: User): Promise<number>; export default function addBurialSiteTypeField(addForm: AddBurialSiteTypeFieldForm, user: User): number;

View File

@ -1,7 +1,8 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; export default function addBurialSiteTypeField(addForm, user) {
export default async function addBurialSiteTypeField(addForm, user) { const database = sqlite(sunriseDB);
const database = await acquireConnection();
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into BurialSiteTypeFields ( .prepare(`insert into BurialSiteTypeFields (
@ -13,8 +14,10 @@ export default async function addBurialSiteTypeField(addForm, user) {
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.burialSiteTypeId, addForm.burialSiteTypeField, addForm.fieldType ?? 'text', addForm.fieldValues ?? '', addForm.isRequired === '' ? 0 : 1, addForm.pattern ?? '', addForm.minLength ?? 0, addForm.maxLength ?? 100, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(addForm.burialSiteTypeId, addForm.burialSiteTypeField, addForm.fieldType ?? 'text', addForm.fieldValues ?? '', addForm.isRequired === '' ? 0 : 1, addForm.pattern ?? '', addForm.minLength ?? 0,
database.release(); // eslint-disable-next-line @typescript-eslint/no-magic-numbers
addForm.maxLength ?? 100, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.close();
clearCacheByTableName('BurialSiteTypeFields'); clearCacheByTableName('BurialSiteTypeFields');
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,24 +1,29 @@
import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import { clearCacheByTableName } from '../helpers/functions.cache.js' import { clearCacheByTableName } from '../helpers/functions.cache.js'
import { acquireConnection } from './pool.js'
export interface AddBurialSiteTypeFieldForm { export interface AddBurialSiteTypeFieldForm {
burialSiteTypeId: string | number burialSiteTypeId: number | string
burialSiteTypeField: string burialSiteTypeField: string
fieldType?: string fieldType?: string
fieldValues?: string fieldValues?: string
isRequired?: string isRequired?: string
maxLength?: number | string
minLength?: number | string
pattern?: string pattern?: string
minLength?: string | number
maxLength?: string | number
orderNumber?: number orderNumber?: number
} }
export default async function addBurialSiteTypeField( export default function addBurialSiteTypeField(
addForm: AddBurialSiteTypeFieldForm, addForm: AddBurialSiteTypeFieldForm,
user: User user: User
): Promise<number> { ): number {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -42,6 +47,7 @@ export default async function addBurialSiteTypeField(
addForm.isRequired === '' ? 0 : 1, addForm.isRequired === '' ? 0 : 1,
addForm.pattern ?? '', addForm.pattern ?? '',
addForm.minLength ?? 0, addForm.minLength ?? 0,
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
addForm.maxLength ?? 100, addForm.maxLength ?? 100,
addForm.orderNumber ?? -1, addForm.orderNumber ?? -1,
user.userName, user.userName,
@ -50,7 +56,7 @@ export default async function addBurialSiteTypeField(
rightNowMillis rightNowMillis
) )
database.release() database.close()
clearCacheByTableName('BurialSiteTypeFields') clearCacheByTableName('BurialSiteTypeFields')

View File

@ -1,15 +1,17 @@
export interface AddCemeteryForm { import { type UpdateCemeteryDirectionsOfArrivalForm } from './updateCemeteryDirectionsOfArrival.js';
cemeteryName: string; export type AddCemeteryForm = UpdateCemeteryDirectionsOfArrivalForm & {
cemeteryKey: string;
cemeteryDescription: string; cemeteryDescription: string;
cemeterySvg: string; cemeteryKey: string;
cemeteryName: string;
parentCemeteryId: string;
cemeteryLatitude: string; cemeteryLatitude: string;
cemeteryLongitude: string; cemeteryLongitude: string;
cemeterySvg: string;
cemeteryAddress1: string; cemeteryAddress1: string;
cemeteryAddress2: string; cemeteryAddress2: string;
cemeteryCity: string; cemeteryCity: string;
cemeteryProvince: string;
cemeteryPostalCode: string; cemeteryPostalCode: string;
cemeteryProvince: string;
cemeteryPhoneNumber: string; cemeteryPhoneNumber: string;
} };
export default function addCemetery(addForm: AddCemeteryForm, user: User): Promise<number>; export default function addCemetery(addForm: AddCemeteryForm, user: User): number;

View File

@ -1,6 +1,8 @@
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addCemetery(addForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = await acquireConnection(); import updateCemeteryDirectionsOfArrival from './updateCemeteryDirectionsOfArrival.js';
export default function addCemetery(addForm, user) {
const database = sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into Cemeteries ( .prepare(`insert into Cemeteries (
@ -9,10 +11,13 @@ export default async function addCemetery(addForm, user) {
cemeteryAddress1, cemeteryAddress2, cemeteryAddress1, cemeteryAddress2,
cemeteryCity, cemeteryProvince, cemeteryPostalCode, cemeteryCity, cemeteryProvince, cemeteryPostalCode,
cemeteryPhoneNumber, cemeteryPhoneNumber,
parentCemeteryId,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.cemeteryName, addForm.cemeteryKey, addForm.cemeteryDescription, addForm.cemeterySvg, addForm.cemeteryLatitude === '' ? undefined : addForm.cemeteryLatitude, addForm.cemeteryLongitude === '' ? undefined : addForm.cemeteryLongitude, addForm.cemeteryAddress1, addForm.cemeteryAddress2, addForm.cemeteryCity, addForm.cemeteryProvince, addForm.cemeteryPostalCode, addForm.cemeteryPhoneNumber, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(addForm.cemeteryName, addForm.cemeteryKey, addForm.cemeteryDescription, addForm.cemeterySvg, addForm.cemeteryLatitude === '' ? undefined : addForm.cemeteryLatitude, addForm.cemeteryLongitude === '' ? undefined : addForm.cemeteryLongitude, addForm.cemeteryAddress1, addForm.cemeteryAddress2, addForm.cemeteryCity, addForm.cemeteryProvince, addForm.cemeteryPostalCode, addForm.cemeteryPhoneNumber, addForm.parentCemeteryId === '' ? undefined : addForm.parentCemeteryId, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.release(); const cemeteryId = result.lastInsertRowid;
return result.lastInsertRowid; updateCemeteryDirectionsOfArrival(cemeteryId, addForm, database);
database.close();
return cemeteryId;
} }

View File

@ -1,27 +1,35 @@
import { acquireConnection } from './pool.js' import sqlite from 'better-sqlite3'
export interface AddCemeteryForm { import { sunriseDB } from '../helpers/database.helpers.js'
cemeteryName: string
cemeteryKey: string import updateCemeteryDirectionsOfArrival, {
type UpdateCemeteryDirectionsOfArrivalForm
} from './updateCemeteryDirectionsOfArrival.js'
export type AddCemeteryForm = UpdateCemeteryDirectionsOfArrivalForm & {
cemeteryDescription: string cemeteryDescription: string
cemeteryKey: string
cemeteryName: string
parentCemeteryId: string
cemeterySvg: string
cemeteryLatitude: string cemeteryLatitude: string
cemeteryLongitude: string cemeteryLongitude: string
cemeterySvg: string
cemeteryAddress1: string cemeteryAddress1: string
cemeteryAddress2: string cemeteryAddress2: string
cemeteryCity: string cemeteryCity: string
cemeteryProvince: string
cemeteryPostalCode: string cemeteryPostalCode: string
cemeteryProvince: string
cemeteryPhoneNumber: string cemeteryPhoneNumber: string
} }
export default async function addCemetery( export default function addCemetery(
addForm: AddCemeteryForm, addForm: AddCemeteryForm,
user: User user: User
): Promise<number> { ): number {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -33,9 +41,10 @@ export default async function addCemetery(
cemeteryAddress1, cemeteryAddress2, cemeteryAddress1, cemeteryAddress2,
cemeteryCity, cemeteryProvince, cemeteryPostalCode, cemeteryCity, cemeteryProvince, cemeteryPostalCode,
cemeteryPhoneNumber, cemeteryPhoneNumber,
parentCemeteryId,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
) )
.run( .run(
addForm.cemeteryName, addForm.cemeteryName,
@ -50,13 +59,18 @@ export default async function addCemetery(
addForm.cemeteryProvince, addForm.cemeteryProvince,
addForm.cemeteryPostalCode, addForm.cemeteryPostalCode,
addForm.cemeteryPhoneNumber, addForm.cemeteryPhoneNumber,
addForm.parentCemeteryId === '' ? undefined : addForm.parentCemeteryId,
user.userName, user.userName,
rightNowMillis, rightNowMillis,
user.userName, user.userName,
rightNowMillis rightNowMillis
) )
database.release() const cemeteryId = result.lastInsertRowid as number
return result.lastInsertRowid as number updateCemeteryDirectionsOfArrival(cemeteryId, addForm, database)
database.close()
return cemeteryId
} }

6
database/addCommittalType.d.ts vendored 100644
View File

@ -0,0 +1,6 @@
export interface AddForm {
committalType: string;
committalTypeKey?: string;
orderNumber?: number | string;
}
export default function addCommittalType(addForm: AddForm, user: User): number;

View File

@ -0,0 +1,17 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { clearCacheByTableName } from '../helpers/functions.cache.js';
export default function addCommittalType(addForm, user) {
const database = sqlite(sunriseDB);
const rightNowMillis = Date.now();
const result = database
.prepare(`insert into CommittalTypes (
committalType, committalTypeKey, orderNumber,
recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.committalType, addForm.committalTypeKey ?? '', addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.close();
clearCacheByTableName('CommittalTypes');
return result.lastInsertRowid;
}

View File

@ -0,0 +1,40 @@
import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import { clearCacheByTableName } from '../helpers/functions.cache.js'
export interface AddForm {
committalType: string
committalTypeKey?: string
orderNumber?: number | string
}
export default function addCommittalType(addForm: AddForm, user: User): number {
const database = sqlite(sunriseDB)
const rightNowMillis = Date.now()
const result = database
.prepare(
`insert into CommittalTypes (
committalType, committalTypeKey, orderNumber,
recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?)`
)
.run(
addForm.committalType,
addForm.committalTypeKey ?? '',
addForm.orderNumber ?? -1,
user.userName,
rightNowMillis,
user.userName,
rightNowMillis
)
database.close()
clearCacheByTableName('CommittalTypes')
return result.lastInsertRowid as number
}

View File

@ -1,36 +1,39 @@
import { type DateString, type TimeString } from '@cityssm/utils-datetime'; import { type DateString, type TimeString } from '@cityssm/utils-datetime';
import type { PoolConnection } from 'better-sqlite-pool'; import sqlite from 'better-sqlite3';
export interface AddContractForm { export interface AddContractForm {
contractTypeId: string | number; burialSiteId: number | string;
burialSiteId: string | number; contractEndDateString: '' | DateString;
contractStartDateString: DateString | ''; contractStartDateString: '' | DateString;
contractEndDateString: DateString | ''; contractTypeId: number | string;
contractTypeFieldIds?: string;
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown; [fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown;
purchaserName?: string; contractTypeFieldIds?: string;
committalTypeId?: number | string;
directionOfArrival?: string;
funeralDateString?: '' | DateString;
funeralDirectorName?: string;
funeralHomeId?: number | string;
funeralTimeString?: '' | TimeString;
purchaserAddress1?: string; purchaserAddress1?: string;
purchaserAddress2?: string; purchaserAddress2?: string;
purchaserCity?: string; purchaserCity?: string;
purchaserProvince?: string;
purchaserPostalCode?: string;
purchaserPhoneNumber?: string;
purchaserEmail?: string; purchaserEmail?: string;
purchaserName?: string;
purchaserPhoneNumber?: string;
purchaserPostalCode?: string;
purchaserProvince?: string;
purchaserRelationship?: string; purchaserRelationship?: string;
funeralHomeId?: string | number; birthDateString?: '' | DateString;
funeralDirectorName?: string; birthPlace?: string;
funeralDateString?: DateString | ''; deathAge?: string;
funeralTimeString?: TimeString | ''; deathAgePeriod?: string;
committalTypeId?: string | number; deathDateString?: '' | DateString;
deceasedName?: string; deathPlace?: string;
deceasedAddress1?: string; deceasedAddress1?: string;
deceasedAddress2?: string; deceasedAddress2?: string;
deceasedCity?: string; deceasedCity?: string;
deceasedProvince?: string; deceasedName?: string;
deceasedPostalCode?: string; deceasedPostalCode?: string;
birthDateString?: DateString | ''; deceasedProvince?: string;
birthPlace?: string; intermentContainerTypeId?: number | string;
deathDateString?: DateString | '';
deathPlace?: string;
intermentContainerTypeId?: string | number;
} }
export default function addContract(addForm: AddContractForm, user: User, connectedDatabase?: PoolConnection): Promise<number>; export default function addContract(addForm: AddContractForm, user: User, connectedDatabase?: sqlite.Database): number;

View File

@ -1,9 +1,10 @@
import { dateStringToInteger, timeStringToInteger } from '@cityssm/utils-datetime'; import { dateStringToInteger, timeStringToInteger } from '@cityssm/utils-datetime';
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import addOrUpdateContractField from './addOrUpdateContractField.js'; import addOrUpdateContractField from './addOrUpdateContractField.js';
import { acquireConnection } from './pool.js';
// eslint-disable-next-line complexity // eslint-disable-next-line complexity
export default async function addContract(addForm, user, connectedDatabase) { export default function addContract(addForm, user, connectedDatabase) {
const database = connectedDatabase ?? (await acquireConnection()); const database = connectedDatabase ?? sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const contractStartDate = dateStringToInteger(addForm.contractStartDateString); const contractStartDate = dateStringToInteger(addForm.contractStartDateString);
const result = database const result = database
@ -15,17 +16,17 @@ export default async function addContract(addForm, user, connectedDatabase) {
purchaserPhoneNumber, purchaserEmail, purchaserRelationship, purchaserPhoneNumber, purchaserEmail, purchaserRelationship,
funeralHomeId, funeralDirectorName, funeralHomeId, funeralDirectorName,
funeralDate, funeralTime, funeralDate, funeralTime,
committalTypeId, directionOfArrival, committalTypeId,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.contractTypeId, addForm.burialSiteId === '' ? undefined : addForm.burialSiteId, contractStartDate, addForm.contractEndDateString === '' .run(addForm.contractTypeId, addForm.burialSiteId === '' ? undefined : addForm.burialSiteId, contractStartDate, addForm.contractEndDateString === ''
? undefined ? undefined
: dateStringToInteger(addForm.contractEndDateString), addForm.purchaserName ?? '', addForm.purchaserAddress1 ?? '', addForm.purchaserAddress2 ?? '', addForm.purchaserCity ?? '', addForm.purchaserProvince ?? '', addForm.purchaserPostalCode ?? '', addForm.purchaserPhoneNumber ?? '', addForm.purchaserEmail ?? '', addForm.purchaserRelationship ?? '', addForm.funeralHomeId === '' ? undefined : addForm.funeralHomeId, addForm.funeralDirectorName ?? '', addForm.funeralDateString === '' : dateStringToInteger(addForm.contractEndDateString), addForm.purchaserName ?? '', addForm.purchaserAddress1 ?? '', addForm.purchaserAddress2 ?? '', addForm.purchaserCity ?? '', addForm.purchaserProvince ?? '', addForm.purchaserPostalCode ?? '', addForm.purchaserPhoneNumber ?? '', addForm.purchaserEmail ?? '', addForm.purchaserRelationship ?? '', addForm.funeralHomeId === '' ? undefined : addForm.funeralHomeId, addForm.funeralDirectorName ?? '', addForm.funeralDateString === ''
? undefined ? undefined
: dateStringToInteger(addForm.funeralDateString), addForm.funeralTimeString === '' : dateStringToInteger(addForm.funeralDateString), addForm.funeralTimeString === ''
? undefined ? undefined
: timeStringToInteger(addForm.funeralTimeString), addForm.committalTypeId === '' ? undefined : addForm.committalTypeId, user.userName, rightNowMillis, user.userName, rightNowMillis); : timeStringToInteger(addForm.funeralTimeString), addForm.directionOfArrival ?? '', addForm.committalTypeId === '' ? undefined : addForm.committalTypeId, user.userName, rightNowMillis, user.userName, rightNowMillis);
const contractId = result.lastInsertRowid; const contractId = result.lastInsertRowid;
/* /*
* Add contract fields * Add contract fields
@ -34,7 +35,7 @@ export default async function addContract(addForm, user, connectedDatabase) {
for (const contractTypeFieldId of contractTypeFieldIds) { for (const contractTypeFieldId of contractTypeFieldIds) {
const fieldValue = addForm[`fieldValue_${contractTypeFieldId}`]; const fieldValue = addForm[`fieldValue_${contractTypeFieldId}`];
if ((fieldValue ?? '') !== '') { if ((fieldValue ?? '') !== '') {
await addOrUpdateContractField({ addOrUpdateContractField({
contractId, contractId,
contractTypeFieldId, contractTypeFieldId,
fieldValue: fieldValue ?? '' fieldValue: fieldValue ?? ''
@ -52,20 +53,21 @@ export default async function addContract(addForm, user, connectedDatabase) {
deceasedCity, deceasedProvince, deceasedPostalCode, deceasedCity, deceasedProvince, deceasedPostalCode,
birthDate, deathDate, birthDate, deathDate,
birthPlace, deathPlace, birthPlace, deathPlace,
deathAge, deathAgePeriod,
intermentContainerTypeId, intermentContainerTypeId,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(contractId, 1, addForm.deceasedName ?? '', addForm.deceasedAddress1 ?? '', addForm.deceasedAddress2 ?? '', addForm.deceasedCity ?? '', addForm.deceasedProvince ?? '', addForm.deceasedPostalCode ?? '', addForm.birthDateString === '' .run(contractId, 1, addForm.deceasedName ?? '', addForm.deceasedAddress1 ?? '', addForm.deceasedAddress2 ?? '', addForm.deceasedCity ?? '', addForm.deceasedProvince ?? '', addForm.deceasedPostalCode ?? '', addForm.birthDateString === ''
? undefined ? undefined
: dateStringToInteger(addForm.birthDateString), addForm.deathDateString === '' : dateStringToInteger(addForm.birthDateString), addForm.deathDateString === ''
? undefined ? undefined
: dateStringToInteger(addForm.deathDateString), addForm.birthPlace ?? '', addForm.deathPlace ?? '', addForm.intermentContainerTypeId === '' : dateStringToInteger(addForm.deathDateString), addForm.birthPlace ?? '', addForm.deathPlace ?? '', addForm.deathAge ?? undefined, addForm.deathAgePeriod ?? '', addForm.intermentContainerTypeId === ''
? undefined ? undefined
: addForm.intermentContainerTypeId, user.userName, rightNowMillis, user.userName, rightNowMillis); : addForm.intermentContainerTypeId, user.userName, rightNowMillis, user.userName, rightNowMillis);
} }
if (connectedDatabase === undefined) { if (connectedDatabase === undefined) {
database.release(); database.close();
} }
return contractId; return contractId;
} }

View File

@ -4,58 +4,60 @@ import {
dateStringToInteger, dateStringToInteger,
timeStringToInteger timeStringToInteger
} from '@cityssm/utils-datetime' } from '@cityssm/utils-datetime'
import type { PoolConnection } from 'better-sqlite-pool' import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import addOrUpdateContractField from './addOrUpdateContractField.js' import addOrUpdateContractField from './addOrUpdateContractField.js'
import { acquireConnection } from './pool.js'
export interface AddContractForm { export interface AddContractForm {
contractTypeId: string | number burialSiteId: number | string
burialSiteId: string | number contractEndDateString: '' | DateString
contractStartDateString: '' | DateString
contractTypeId: number | string
contractStartDateString: DateString | ''
contractEndDateString: DateString | ''
contractTypeFieldIds?: string
[fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown [fieldValue_contractTypeFieldId: `fieldValue_${string}`]: unknown
contractTypeFieldIds?: string
committalTypeId?: number | string
directionOfArrival?: string
funeralDateString?: '' | DateString
funeralDirectorName?: string
funeralHomeId?: number | string
funeralTimeString?: '' | TimeString
purchaserName?: string
purchaserAddress1?: string purchaserAddress1?: string
purchaserAddress2?: string purchaserAddress2?: string
purchaserCity?: string purchaserCity?: string
purchaserProvince?: string
purchaserPostalCode?: string
purchaserPhoneNumber?: string
purchaserEmail?: string purchaserEmail?: string
purchaserName?: string
purchaserPhoneNumber?: string
purchaserPostalCode?: string
purchaserProvince?: string
purchaserRelationship?: string purchaserRelationship?: string
funeralHomeId?: string | number birthDateString?: '' | DateString
funeralDirectorName?: string birthPlace?: string
funeralDateString?: DateString | '' deathAge?: string
funeralTimeString?: TimeString | '' deathAgePeriod?: string
committalTypeId?: string | number deathDateString?: '' | DateString
deathPlace?: string
deceasedName?: string
deceasedAddress1?: string deceasedAddress1?: string
deceasedAddress2?: string deceasedAddress2?: string
deceasedCity?: string deceasedCity?: string
deceasedProvince?: string deceasedName?: string
deceasedPostalCode?: string deceasedPostalCode?: string
deceasedProvince?: string
birthDateString?: DateString | '' intermentContainerTypeId?: number | string
birthPlace?: string
deathDateString?: DateString | ''
deathPlace?: string
intermentContainerTypeId?: string | number
} }
// eslint-disable-next-line complexity // eslint-disable-next-line complexity
export default async function addContract( export default function addContract(
addForm: AddContractForm, addForm: AddContractForm,
user: User, user: User,
connectedDatabase?: PoolConnection connectedDatabase?: sqlite.Database
): Promise<number> { ): number {
const database = connectedDatabase ?? (await acquireConnection()) const database = connectedDatabase ?? sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -73,10 +75,10 @@ export default async function addContract(
purchaserPhoneNumber, purchaserEmail, purchaserRelationship, purchaserPhoneNumber, purchaserEmail, purchaserRelationship,
funeralHomeId, funeralDirectorName, funeralHomeId, funeralDirectorName,
funeralDate, funeralTime, funeralDate, funeralTime,
committalTypeId, directionOfArrival, committalTypeId,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
) )
.run( .run(
addForm.contractTypeId, addForm.contractTypeId,
@ -102,6 +104,7 @@ export default async function addContract(
addForm.funeralTimeString === '' addForm.funeralTimeString === ''
? undefined ? undefined
: timeStringToInteger(addForm.funeralTimeString as TimeString), : timeStringToInteger(addForm.funeralTimeString as TimeString),
addForm.directionOfArrival ?? '',
addForm.committalTypeId === '' ? undefined : addForm.committalTypeId, addForm.committalTypeId === '' ? undefined : addForm.committalTypeId,
user.userName, user.userName,
rightNowMillis, rightNowMillis,
@ -123,7 +126,7 @@ export default async function addContract(
| undefined | undefined
if ((fieldValue ?? '') !== '') { if ((fieldValue ?? '') !== '') {
await addOrUpdateContractField( addOrUpdateContractField(
{ {
contractId, contractId,
contractTypeFieldId, contractTypeFieldId,
@ -148,10 +151,11 @@ export default async function addContract(
deceasedCity, deceasedProvince, deceasedPostalCode, deceasedCity, deceasedProvince, deceasedPostalCode,
birthDate, deathDate, birthDate, deathDate,
birthPlace, deathPlace, birthPlace, deathPlace,
deathAge, deathAgePeriod,
intermentContainerTypeId, intermentContainerTypeId,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
) )
.run( .run(
@ -171,6 +175,8 @@ export default async function addContract(
: dateStringToInteger(addForm.deathDateString as DateString), : dateStringToInteger(addForm.deathDateString as DateString),
addForm.birthPlace ?? '', addForm.birthPlace ?? '',
addForm.deathPlace ?? '', addForm.deathPlace ?? '',
addForm.deathAge ?? undefined,
addForm.deathAgePeriod ?? '',
addForm.intermentContainerTypeId === '' addForm.intermentContainerTypeId === ''
? undefined ? undefined
: addForm.intermentContainerTypeId, : addForm.intermentContainerTypeId,
@ -182,7 +188,7 @@ export default async function addContract(
} }
if (connectedDatabase === undefined) { if (connectedDatabase === undefined) {
database.release() database.close()
} }
return contractId return contractId

View File

@ -1,8 +1,8 @@
import { type DateString, type TimeString } from '@cityssm/utils-datetime'; import { type DateString, type TimeString } from '@cityssm/utils-datetime';
export interface AddContractCommentForm { export interface AddContractCommentForm {
contractId: string | number; contractId: number | string;
comment: string;
commentDateString?: DateString; commentDateString?: DateString;
commentTimeString?: TimeString; commentTimeString?: TimeString;
comment: string;
} }
export default function addContractComment(commentForm: AddContractCommentForm, user: User): Promise<number>; export default function addContractComment(commentForm: AddContractCommentForm, user: User): number;

View File

@ -1,6 +1,7 @@
import { dateStringToInteger, dateToInteger, dateToTimeInteger, timeStringToInteger } from '@cityssm/utils-datetime'; import { dateStringToInteger, dateToInteger, dateToTimeInteger, timeStringToInteger } from '@cityssm/utils-datetime';
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addContractComment(commentForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
export default function addContractComment(commentForm, user) {
const rightNow = new Date(); const rightNow = new Date();
let commentDate = 0; let commentDate = 0;
let commentTime = 0; let commentTime = 0;
@ -12,7 +13,7 @@ export default async function addContractComment(commentForm, user) {
commentDate = dateStringToInteger(commentForm.commentDateString); commentDate = dateStringToInteger(commentForm.commentDateString);
commentTime = timeStringToInteger(commentForm.commentTimeString); commentTime = timeStringToInteger(commentForm.commentTimeString);
} }
const database = await acquireConnection(); const database = sqlite(sunriseDB);
const result = database const result = database
.prepare(`insert into ContractComments ( .prepare(`insert into ContractComments (
contractId, contractId,
@ -22,6 +23,6 @@ export default async function addContractComment(commentForm, user) {
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?)`)
.run(commentForm.contractId, commentDate, commentTime ?? 0, commentForm.comment, user.userName, rightNow.getTime(), user.userName, rightNow.getTime()); .run(commentForm.contractId, commentDate, commentTime ?? 0, commentForm.comment, user.userName, rightNow.getTime(), user.userName, rightNow.getTime());
database.release(); database.close();
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -6,20 +6,22 @@ import {
dateToTimeInteger, dateToTimeInteger,
timeStringToInteger timeStringToInteger
} from '@cityssm/utils-datetime' } from '@cityssm/utils-datetime'
import sqlite from 'better-sqlite3'
import { acquireConnection } from './pool.js' import { sunriseDB } from '../helpers/database.helpers.js'
export interface AddContractCommentForm { export interface AddContractCommentForm {
contractId: string | number contractId: number | string
comment: string
commentDateString?: DateString commentDateString?: DateString
commentTimeString?: TimeString commentTimeString?: TimeString
comment: string
} }
export default async function addContractComment( export default function addContractComment(
commentForm: AddContractCommentForm, commentForm: AddContractCommentForm,
user: User user: User
): Promise<number> { ): number {
const rightNow = new Date() const rightNow = new Date()
let commentDate = 0 let commentDate = 0
@ -37,7 +39,7 @@ export default async function addContractComment(
) )
} }
const database = await acquireConnection() const database = sqlite(sunriseDB)
const result = database const result = database
.prepare( .prepare(
@ -60,7 +62,7 @@ export default async function addContractComment(
rightNow.getTime() rightNow.getTime()
) )
database.release() database.close()
return result.lastInsertRowid as number return result.lastInsertRowid as number
} }

View File

@ -1,9 +1,9 @@
import type { PoolConnection } from 'better-sqlite-pool'; import sqlite from 'better-sqlite3';
export interface AddContractFeeForm { export interface AddContractFeeForm {
contractId: number | string; contractId: number | string;
feeId: number | string; feeId: number | string;
quantity: number | string;
feeAmount?: number | string; feeAmount?: number | string;
quantity: number | string;
taxAmount?: number | string; taxAmount?: number | string;
} }
export default function addContractFee(addFeeForm: AddContractFeeForm, user: User, connectedDatabase?: PoolConnection): Promise<boolean>; export default function addContractFee(addFeeForm: AddContractFeeForm, user: User, connectedDatabase?: sqlite.Database): Promise<boolean>;

View File

@ -1,16 +1,17 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { calculateFeeAmount, calculateTaxAmount } from '../helpers/functions.fee.js'; import { calculateFeeAmount, calculateTaxAmount } from '../helpers/functions.fee.js';
import getContract from './getContract.js'; import getContract from './getContract.js';
import getFee from './getFee.js'; import getFee from './getFee.js';
import { acquireConnection } from './pool.js';
export default async function addContractFee(addFeeForm, user, connectedDatabase) { export default async function addContractFee(addFeeForm, user, connectedDatabase) {
const database = connectedDatabase ?? (await acquireConnection()); const database = connectedDatabase ?? sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
// Calculate fee and tax (if not set) // Calculate fee and tax (if not set)
let feeAmount; let feeAmount;
let taxAmount; let taxAmount;
if ((addFeeForm.feeAmount ?? '') === '') { if ((addFeeForm.feeAmount ?? '') === '') {
const contract = (await getContract(addFeeForm.contractId)); const contract = (await getContract(addFeeForm.contractId));
const fee = (await getFee(addFeeForm.feeId)); const fee = getFee(addFeeForm.feeId);
feeAmount = calculateFeeAmount(fee, contract); feeAmount = calculateFeeAmount(fee, contract);
taxAmount = calculateTaxAmount(fee, feeAmount); taxAmount = calculateTaxAmount(fee, feeAmount);
} }
@ -83,7 +84,7 @@ export default async function addContractFee(addFeeForm, user, connectedDatabase
} }
finally { finally {
if (connectedDatabase === undefined) { if (connectedDatabase === undefined) {
database.release(); database.close();
} }
} }
} }

View File

@ -1,29 +1,30 @@
import type { PoolConnection } from 'better-sqlite-pool' import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import { import {
calculateFeeAmount, calculateFeeAmount,
calculateTaxAmount calculateTaxAmount
} from '../helpers/functions.fee.js' } from '../helpers/functions.fee.js'
import type { Contract, Fee } from '../types/recordTypes.js' import type { Contract, Fee } from '../types/record.types.js'
import getContract from './getContract.js' import getContract from './getContract.js'
import getFee from './getFee.js' import getFee from './getFee.js'
import { acquireConnection } from './pool.js'
export interface AddContractFeeForm { export interface AddContractFeeForm {
contractId: number | string contractId: number | string
feeId: number | string feeId: number | string
quantity: number | string
feeAmount?: number | string feeAmount?: number | string
quantity: number | string
taxAmount?: number | string taxAmount?: number | string
} }
export default async function addContractFee( export default async function addContractFee(
addFeeForm: AddContractFeeForm, addFeeForm: AddContractFeeForm,
user: User, user: User,
connectedDatabase?: PoolConnection connectedDatabase?: sqlite.Database
): Promise<boolean> { ): Promise<boolean> {
const database = connectedDatabase ?? (await acquireConnection()) const database = connectedDatabase ?? sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -32,11 +33,9 @@ export default async function addContractFee(
let taxAmount: number let taxAmount: number
if ((addFeeForm.feeAmount ?? '') === '') { if ((addFeeForm.feeAmount ?? '') === '') {
const contract = (await getContract( const contract = (await getContract(addFeeForm.contractId)) as Contract
addFeeForm.contractId
)) as Contract
const fee = (await getFee(addFeeForm.feeId)) as Fee const fee = getFee(addFeeForm.feeId) as Fee
feeAmount = calculateFeeAmount(fee, contract) feeAmount = calculateFeeAmount(fee, contract)
taxAmount = calculateTaxAmount(fee, feeAmount) taxAmount = calculateTaxAmount(fee, feeAmount)
@ -64,6 +63,7 @@ export default async function addContractFee(
| { | {
feeAmount: number | null feeAmount: number | null
taxAmount: number | null taxAmount: number | null
recordDelete_timeMillis: number | null recordDelete_timeMillis: number | null
} }
| undefined | undefined
@ -155,7 +155,7 @@ export default async function addContractFee(
return result.changes > 0 return result.changes > 0
} finally { } finally {
if (connectedDatabase === undefined) { if (connectedDatabase === undefined) {
database.release() database.close()
} }
} }
} }

View File

@ -1,9 +1,10 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import addContractFee from './addContractFee.js'; import addContractFee from './addContractFee.js';
import { getFeeCategory } from './getFeeCategories.js'; import { getFeeCategory } from './getFeeCategories.js';
import { acquireConnection } from './pool.js';
export default async function addContractFeeCategory(addFeeCategoryForm, user) { export default async function addContractFeeCategory(addFeeCategoryForm, user) {
const database = await acquireConnection(); const database = sqlite(sunriseDB);
const feeCategory = await getFeeCategory(addFeeCategoryForm.feeCategoryId, database); const feeCategory = getFeeCategory(addFeeCategoryForm.feeCategoryId, database);
let addedFeeCount = 0; let addedFeeCount = 0;
for (const fee of feeCategory?.fees ?? []) { for (const fee of feeCategory?.fees ?? []) {
const success = await addContractFee({ const success = await addContractFee({
@ -15,6 +16,6 @@ export default async function addContractFeeCategory(addFeeCategoryForm, user) {
addedFeeCount += 1; addedFeeCount += 1;
} }
} }
database.release(); database.close();
return addedFeeCount; return addedFeeCount;
} }

View File

@ -1,6 +1,9 @@
import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import addContractFee from './addContractFee.js' import addContractFee from './addContractFee.js'
import { getFeeCategory } from './getFeeCategories.js' import { getFeeCategory } from './getFeeCategories.js'
import { acquireConnection } from './pool.js'
export interface AddContractCategoryForm { export interface AddContractCategoryForm {
contractId: number | string contractId: number | string
@ -11,12 +14,9 @@ export default async function addContractFeeCategory(
addFeeCategoryForm: AddContractCategoryForm, addFeeCategoryForm: AddContractCategoryForm,
user: User user: User
): Promise<number> { ): Promise<number> {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const feeCategory = await getFeeCategory( const feeCategory = getFeeCategory(addFeeCategoryForm.feeCategoryId, database)
addFeeCategoryForm.feeCategoryId,
database
)
let addedFeeCount = 0 let addedFeeCount = 0
@ -36,7 +36,7 @@ export default async function addContractFeeCategory(
} }
} }
database.release() database.close()
return addedFeeCount return addedFeeCount
} }

View File

@ -1,16 +1,19 @@
import { type DateString } from '@cityssm/utils-datetime'; import { type DateString } from '@cityssm/utils-datetime';
import sqlite from 'better-sqlite3';
export interface AddForm { export interface AddForm {
contractId: string | number; contractId: number | string;
deceasedName: string; deceasedName: string;
deceasedAddress1: string; deceasedAddress1: string;
deceasedAddress2: string; deceasedAddress2: string;
deceasedCity: string; deceasedCity: string;
deceasedProvince: string;
deceasedPostalCode: string; deceasedPostalCode: string;
birthDateString: DateString | ''; deceasedProvince: string;
birthDateString: '' | DateString;
birthPlace: string; birthPlace: string;
deathDateString: DateString | ''; deathDateString: '' | DateString;
deathPlace: string; deathPlace: string;
intermentContainerTypeId: string | number; deathAge: number | string;
deathAgePeriod: string;
intermentContainerTypeId: number | string;
} }
export default function addContractInterment(contractForm: AddForm, user: User): Promise<number>; export default function addContractInterment(contractForm: AddForm, user: User, connectedDatabase?: sqlite.Database): number;

View File

@ -1,11 +1,12 @@
import { dateStringToInteger } from '@cityssm/utils-datetime'; import { dateStringToInteger } from '@cityssm/utils-datetime';
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addContractInterment(contractForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = await acquireConnection(); export default function addContractInterment(contractForm, user, connectedDatabase) {
const database = connectedDatabase ?? sqlite(sunriseDB);
const maxIntermentNumber = (database const maxIntermentNumber = (database
.prepare(`select max(intermentNumber) as maxIntermentNumber .prepare(`select max(intermentNumber) as maxIntermentNumber
from ContractInterments from ContractInterments
where contractId = ?`) where contractId = ?`)
.pluck() .pluck()
.get(contractForm.contractId) ?? 0); .get(contractForm.contractId) ?? 0);
const newIntermentNumber = maxIntermentNumber + 1; const newIntermentNumber = maxIntermentNumber + 1;
@ -25,6 +26,8 @@ export default async function addContractInterment(contractForm, user) {
: dateStringToInteger(contractForm.deathDateString), contractForm.deathPlace, contractForm.intermentContainerTypeId === '' : dateStringToInteger(contractForm.deathDateString), contractForm.deathPlace, contractForm.intermentContainerTypeId === ''
? undefined ? undefined
: contractForm.intermentContainerTypeId, user.userName, rightNowMillis, user.userName, rightNowMillis); : contractForm.intermentContainerTypeId, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.release(); if (connectedDatabase === undefined) {
database.close();
}
return newIntermentNumber; return newIntermentNumber;
} }

View File

@ -1,33 +1,42 @@
import { type DateString, dateStringToInteger } from '@cityssm/utils-datetime' import { type DateString, dateStringToInteger } from '@cityssm/utils-datetime'
import sqlite from 'better-sqlite3'
import { acquireConnection } from './pool.js' import { sunriseDB } from '../helpers/database.helpers.js'
export interface AddForm { export interface AddForm {
contractId: string | number contractId: number | string
deceasedName: string deceasedName: string
deceasedAddress1: string deceasedAddress1: string
deceasedAddress2: string deceasedAddress2: string
deceasedCity: string deceasedCity: string
deceasedProvince: string
deceasedPostalCode: string deceasedPostalCode: string
birthDateString: DateString | '' deceasedProvince: string
birthDateString: '' | DateString
birthPlace: string birthPlace: string
deathDateString: DateString | '' deathDateString: '' | DateString
deathPlace: string deathPlace: string
intermentContainerTypeId: string | number
deathAge: number | string
deathAgePeriod: string
intermentContainerTypeId: number | string
} }
export default async function addContractInterment( export default function addContractInterment(
contractForm: AddForm, contractForm: AddForm,
user: User user: User,
): Promise<number> { connectedDatabase?: sqlite.Database
const database = await acquireConnection() ): number {
const database = connectedDatabase ?? sqlite(sunriseDB)
const maxIntermentNumber = (database const maxIntermentNumber = (database
.prepare( .prepare(
`select max(intermentNumber) as maxIntermentNumber `select max(intermentNumber) as maxIntermentNumber
from ContractInterments from ContractInterments
where contractId = ?` where contractId = ?`
) )
.pluck() .pluck()
.get(contractForm.contractId) ?? 0) as number .get(contractForm.contractId) ?? 0) as number
@ -71,7 +80,9 @@ export default async function addContractInterment(
rightNowMillis rightNowMillis
) )
database.release() if (connectedDatabase === undefined) {
database.close()
}
return newIntermentNumber return newIntermentNumber
} }

View File

@ -1,9 +1,10 @@
import { type DateString, type TimeString } from '@cityssm/utils-datetime';
export interface AddTransactionForm { export interface AddTransactionForm {
contractId: string | number; contractId: number | string;
transactionDateString?: string; transactionDateString?: '' | DateString;
transactionTimeString?: string; transactionTimeString?: '' | TimeString;
transactionAmount: string | number;
externalReceiptNumber: string; externalReceiptNumber: string;
transactionAmount: number | string;
transactionNote: string; transactionNote: string;
} }
export default function addContractTransaction(contractTransactionForm: AddTransactionForm, user: User): Promise<number>; export default function addContractTransaction(contractTransactionForm: AddTransactionForm, user: User): number;

View File

@ -1,7 +1,8 @@
import { dateStringToInteger, dateToInteger, dateToTimeInteger, timeStringToInteger } from '@cityssm/utils-datetime'; import { dateStringToInteger, dateToInteger, dateToTimeInteger, timeStringToInteger } from '@cityssm/utils-datetime';
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addContractTransaction(contractTransactionForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = await acquireConnection(); export default function addContractTransaction(contractTransactionForm, user) {
const database = sqlite(sunriseDB);
let transactionIndex = 0; let transactionIndex = 0;
const maxIndexResult = database const maxIndexResult = database
.prepare(`select transactionIndex .prepare(`select transactionIndex
@ -14,12 +15,12 @@ export default async function addContractTransaction(contractTransactionForm, us
transactionIndex = maxIndexResult.transactionIndex + 1; transactionIndex = maxIndexResult.transactionIndex + 1;
} }
const rightNow = new Date(); const rightNow = new Date();
const transactionDate = contractTransactionForm.transactionDateString const transactionDate = (contractTransactionForm.transactionDateString ?? '') === ''
? dateStringToInteger(contractTransactionForm.transactionDateString) ? dateToInteger(rightNow)
: dateToInteger(rightNow); : dateStringToInteger(contractTransactionForm.transactionDateString);
const transactionTime = contractTransactionForm.transactionTimeString const transactionTime = (contractTransactionForm.transactionTimeString ?? '') === ''
? timeStringToInteger(contractTransactionForm.transactionTimeString) ? dateToTimeInteger(rightNow)
: dateToTimeInteger(rightNow); : timeStringToInteger(contractTransactionForm.transactionTimeString);
database database
.prepare(`insert into ContractTransactions ( .prepare(`insert into ContractTransactions (
contractId, transactionIndex, contractId, transactionIndex,
@ -29,6 +30,6 @@ export default async function addContractTransaction(contractTransactionForm, us
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(contractTransactionForm.contractId, transactionIndex, transactionDate, transactionTime, contractTransactionForm.transactionAmount, contractTransactionForm.externalReceiptNumber, contractTransactionForm.transactionNote, user.userName, rightNow.getTime(), user.userName, rightNow.getTime()); .run(contractTransactionForm.contractId, transactionIndex, transactionDate, transactionTime, contractTransactionForm.transactionAmount, contractTransactionForm.externalReceiptNumber, contractTransactionForm.transactionNote, user.userName, rightNow.getTime(), user.userName, rightNow.getTime());
database.release(); database.close();
return transactionIndex; return transactionIndex;
} }

View File

@ -1,26 +1,31 @@
import { import {
type DateString,
type TimeString,
dateStringToInteger, dateStringToInteger,
dateToInteger, dateToInteger,
dateToTimeInteger, dateToTimeInteger,
timeStringToInteger timeStringToInteger
} from '@cityssm/utils-datetime' } from '@cityssm/utils-datetime'
import sqlite from 'better-sqlite3'
import { acquireConnection } from './pool.js' import { sunriseDB } from '../helpers/database.helpers.js'
export interface AddTransactionForm { export interface AddTransactionForm {
contractId: string | number contractId: number | string
transactionDateString?: string
transactionTimeString?: string transactionDateString?: '' | DateString
transactionAmount: string | number transactionTimeString?: '' | TimeString
externalReceiptNumber: string externalReceiptNumber: string
transactionAmount: number | string
transactionNote: string transactionNote: string
} }
export default async function addContractTransaction( export default function addContractTransaction(
contractTransactionForm: AddTransactionForm, contractTransactionForm: AddTransactionForm,
user: User user: User
): Promise<number> { ): number {
const database = await acquireConnection() const database = sqlite(sunriseDB)
let transactionIndex = 0 let transactionIndex = 0
@ -42,13 +47,19 @@ export default async function addContractTransaction(
const rightNow = new Date() const rightNow = new Date()
const transactionDate = contractTransactionForm.transactionDateString const transactionDate =
? dateStringToInteger(contractTransactionForm.transactionDateString) (contractTransactionForm.transactionDateString ?? '') === ''
: dateToInteger(rightNow) ? dateToInteger(rightNow)
: dateStringToInteger(
contractTransactionForm.transactionDateString as DateString
)
const transactionTime = contractTransactionForm.transactionTimeString const transactionTime =
? timeStringToInteger(contractTransactionForm.transactionTimeString) (contractTransactionForm.transactionTimeString ?? '') === ''
: dateToTimeInteger(rightNow) ? dateToTimeInteger(rightNow)
: timeStringToInteger(
contractTransactionForm.transactionTimeString as TimeString
)
database database
.prepare( .prepare(
@ -74,7 +85,7 @@ export default async function addContractTransaction(
rightNow.getTime() rightNow.getTime()
) )
database.release() database.close()
return transactionIndex return transactionIndex
} }

View File

@ -3,4 +3,4 @@ export interface AddForm {
isPreneed?: string; isPreneed?: string;
orderNumber?: number; orderNumber?: number;
} }
export default function addContractType(addForm: AddForm, user: User): Promise<number>; export default function addContractType(addForm: AddForm, user: User): number;

View File

@ -1,7 +1,8 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; export default function addContractType(addForm, user) {
export default async function addContractType(addForm, user) { const database = sqlite(sunriseDB);
const database = await acquireConnection();
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into ContractTypes ( .prepare(`insert into ContractTypes (
@ -10,7 +11,7 @@ export default async function addContractType(addForm, user) {
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.contractType, addForm.isPreneed === undefined ? 0 : 1, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(addForm.contractType, addForm.isPreneed === undefined ? 0 : 1, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.release(); database.close();
clearCacheByTableName('ContractTypes'); clearCacheByTableName('ContractTypes');
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,6 +1,7 @@
import { clearCacheByTableName } from '../helpers/functions.cache.js' import sqlite from 'better-sqlite3'
import { acquireConnection } from './pool.js' import { sunriseDB } from '../helpers/database.helpers.js'
import { clearCacheByTableName } from '../helpers/functions.cache.js'
export interface AddForm { export interface AddForm {
contractType: string contractType: string
@ -8,11 +9,8 @@ export interface AddForm {
orderNumber?: number orderNumber?: number
} }
export default async function addContractType( export default function addContractType(addForm: AddForm, user: User): number {
addForm: AddForm, const database = sqlite(sunriseDB)
user: User
): Promise<number> {
const database = await acquireConnection()
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -34,7 +32,7 @@ export default async function addContractType(
rightNowMillis rightNowMillis
) )
database.release() database.close()
clearCacheByTableName('ContractTypes') clearCacheByTableName('ContractTypes')

View File

@ -1,12 +1,12 @@
export interface AddContractTypeFieldForm { export interface AddContractTypeFieldForm {
contractTypeId?: string | number; contractTypeId?: number | string;
contractTypeField: string; contractTypeField: string;
fieldValues?: string;
fieldType?: string; fieldType?: string;
fieldValues?: string;
isRequired?: string; isRequired?: string;
maxLength?: number | string;
minLength?: number | string;
pattern?: string; pattern?: string;
minLength?: string | number;
maxLength?: string | number;
orderNumber?: number; orderNumber?: number;
} }
export default function addContractTypeField(addForm: AddContractTypeFieldForm, user: User): Promise<number>; export default function addContractTypeField(addForm: AddContractTypeFieldForm, user: User): number;

View File

@ -1,7 +1,8 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; export default function addContractTypeField(addForm, user) {
export default async function addContractTypeField(addForm, user) { const database = sqlite(sunriseDB);
const database = await acquireConnection();
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into ContractTypeFields ( .prepare(`insert into ContractTypeFields (
@ -12,8 +13,10 @@ export default async function addContractTypeField(addForm, user) {
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.contractTypeId ?? undefined, addForm.contractTypeField, addForm.fieldType ?? 'text', addForm.fieldValues ?? '', addForm.isRequired === '' ? 0 : 1, addForm.pattern ?? '', addForm.minLength ?? 0, addForm.maxLength ?? 100, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(addForm.contractTypeId ?? undefined, addForm.contractTypeField, addForm.fieldType ?? 'text', addForm.fieldValues ?? '', addForm.isRequired === '' ? 0 : 1, addForm.pattern ?? '', addForm.minLength ?? 0,
database.release(); // eslint-disable-next-line @typescript-eslint/no-magic-numbers
addForm.maxLength ?? 100, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.close();
clearCacheByTableName('ContractTypeFields'); clearCacheByTableName('ContractTypeFields');
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,24 +1,28 @@
import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import { clearCacheByTableName } from '../helpers/functions.cache.js' import { clearCacheByTableName } from '../helpers/functions.cache.js'
import { acquireConnection } from './pool.js'
export interface AddContractTypeFieldForm { export interface AddContractTypeFieldForm {
contractTypeId?: string | number contractTypeId?: number | string
contractTypeField: string contractTypeField: string
fieldValues?: string
fieldType?: string fieldType?: string
fieldValues?: string
isRequired?: string isRequired?: string
maxLength?: number | string
minLength?: number | string
pattern?: string pattern?: string
minLength?: string | number
maxLength?: string | number
orderNumber?: number orderNumber?: number
} }
export default async function addContractTypeField( export default function addContractTypeField(
addForm: AddContractTypeFieldForm, addForm: AddContractTypeFieldForm,
user: User user: User
): Promise<number> { ): number {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -41,6 +45,7 @@ export default async function addContractTypeField(
addForm.isRequired === '' ? 0 : 1, addForm.isRequired === '' ? 0 : 1,
addForm.pattern ?? '', addForm.pattern ?? '',
addForm.minLength ?? 0, addForm.minLength ?? 0,
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
addForm.maxLength ?? 100, addForm.maxLength ?? 100,
addForm.orderNumber ?? -1, addForm.orderNumber ?? -1,
user.userName, user.userName,
@ -49,7 +54,7 @@ export default async function addContractTypeField(
rightNowMillis rightNowMillis
) )
database.release() database.close()
clearCacheByTableName('ContractTypeFields') clearCacheByTableName('ContractTypeFields')

View File

@ -1,6 +1,6 @@
export interface AddContractTypePrintForm { export interface AddContractTypePrintForm {
contractTypeId: string | number; contractTypeId: number | string;
printEJS: string; printEJS: string;
orderNumber?: number; orderNumber?: number;
} }
export default function addContractTypePrint(addForm: AddContractTypePrintForm, user: User): Promise<boolean>; export default function addContractTypePrint(addForm: AddContractTypePrintForm, user: User): boolean;

View File

@ -1,16 +1,17 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; export default function addContractTypePrint(addForm, user) {
export default async function addContractTypePrint(addForm, user) { const database = sqlite(sunriseDB);
const database = await acquireConnection();
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
let result = database let result = database
.prepare(`update ContractTypePrints .prepare(`update ContractTypePrints
set recordUpdate_userName = ?, set recordUpdate_userName = ?,
recordUpdate_timeMillis = ?, recordUpdate_timeMillis = ?,
recordDelete_userName = null, recordDelete_userName = null,
recordDelete_timeMillis = null recordDelete_timeMillis = null
where contractTypeId = ? where contractTypeId = ?
and printEJS = ?`) and printEJS = ?`)
.run(user.userName, rightNowMillis, addForm.contractTypeId, addForm.printEJS); .run(user.userName, rightNowMillis, addForm.contractTypeId, addForm.printEJS);
if (result.changes === 0) { if (result.changes === 0) {
result = database result = database
@ -21,7 +22,7 @@ export default async function addContractTypePrint(addForm, user) {
values (?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.contractTypeId, addForm.printEJS, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(addForm.contractTypeId, addForm.printEJS, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
} }
database.release(); database.close();
clearCacheByTableName('ContractTypePrints'); clearCacheByTableName('ContractTypePrints');
return result.changes > 0; return result.changes > 0;
} }

View File

@ -1,18 +1,20 @@
import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import { clearCacheByTableName } from '../helpers/functions.cache.js' import { clearCacheByTableName } from '../helpers/functions.cache.js'
import { acquireConnection } from './pool.js'
export interface AddContractTypePrintForm { export interface AddContractTypePrintForm {
contractTypeId: string | number contractTypeId: number | string
printEJS: string printEJS: string
orderNumber?: number orderNumber?: number
} }
export default async function addContractTypePrint( export default function addContractTypePrint(
addForm: AddContractTypePrintForm, addForm: AddContractTypePrintForm,
user: User user: User
): Promise<boolean> { ): boolean {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -20,11 +22,11 @@ export default async function addContractTypePrint(
.prepare( .prepare(
`update ContractTypePrints `update ContractTypePrints
set recordUpdate_userName = ?, set recordUpdate_userName = ?,
recordUpdate_timeMillis = ?, recordUpdate_timeMillis = ?,
recordDelete_userName = null, recordDelete_userName = null,
recordDelete_timeMillis = null recordDelete_timeMillis = null
where contractTypeId = ? where contractTypeId = ?
and printEJS = ?` and printEJS = ?`
) )
.run( .run(
user.userName, user.userName,
@ -53,7 +55,7 @@ export default async function addContractTypePrint(
) )
} }
database.release() database.close()
clearCacheByTableName('ContractTypePrints') clearCacheByTableName('ContractTypePrints')

View File

@ -1,10 +1,10 @@
export interface AddFeeForm { export interface AddFeeForm {
feeCategoryId: string; feeCategoryId: number | string;
feeName: string; feeName: string;
feeDescription: string; feeDescription: string;
feeAccount: string; feeAccount: string;
contractTypeId: string; contractTypeId: number | string;
burialSiteTypeId: string; burialSiteTypeId: number | string;
feeAmount?: string; feeAmount?: string;
feeFunction?: string; feeFunction?: string;
taxAmount?: string; taxAmount?: string;
@ -14,4 +14,4 @@ export interface AddFeeForm {
isRequired?: '' | '1'; isRequired?: '' | '1';
orderNumber?: number; orderNumber?: number;
} }
export default function addFee(feeForm: AddFeeForm, user: User): Promise<number>; export default function addFee(feeForm: AddFeeForm, user: User): number;

View File

@ -1,6 +1,7 @@
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addFee(feeForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = await acquireConnection(); export default function addFee(feeForm, user) {
const database = sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into Fees ( .prepare(`insert into Fees (
@ -14,7 +15,7 @@ export default async function addFee(feeForm, user) {
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(feeForm.feeCategoryId, feeForm.feeName, feeForm.feeDescription, feeForm.feeAccount, feeForm.contractTypeId === '' ? undefined : feeForm.contractTypeId, feeForm.burialSiteTypeId === '' ? undefined : feeForm.burialSiteTypeId, feeForm.feeAmount ?? undefined, feeForm.feeFunction ?? undefined, feeForm.taxAmount ?? undefined, feeForm.taxPercentage ?? undefined, (feeForm.includeQuantity ?? '') === '' ? 0 : 1, feeForm.quantityUnit, (feeForm.isRequired ?? '') === '' ? 0 : 1, feeForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(feeForm.feeCategoryId, feeForm.feeName, feeForm.feeDescription, feeForm.feeAccount, feeForm.contractTypeId === '' ? undefined : feeForm.contractTypeId, feeForm.burialSiteTypeId === '' ? undefined : feeForm.burialSiteTypeId, feeForm.feeAmount === '' ? undefined : feeForm.feeAmount, feeForm.feeFunction ?? undefined, feeForm.taxAmount === '' ? undefined : feeForm.taxAmount, feeForm.taxPercentage === '' ? undefined : feeForm.taxPercentage, (feeForm.includeQuantity ?? '') === '' ? 0 : 1, feeForm.quantityUnit, (feeForm.isRequired ?? '') === '' ? 0 : 1, feeForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.release(); database.close();
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,12 +1,14 @@
import { acquireConnection } from './pool.js' import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
export interface AddFeeForm { export interface AddFeeForm {
feeCategoryId: string feeCategoryId: number | string
feeName: string feeName: string
feeDescription: string feeDescription: string
feeAccount: string feeAccount: string
contractTypeId: string contractTypeId: number | string
burialSiteTypeId: string burialSiteTypeId: number | string
feeAmount?: string feeAmount?: string
feeFunction?: string feeFunction?: string
taxAmount?: string taxAmount?: string
@ -17,11 +19,8 @@ export interface AddFeeForm {
orderNumber?: number orderNumber?: number
} }
export default async function addFee( export default function addFee(feeForm: AddFeeForm, user: User): number {
feeForm: AddFeeForm, const database = sqlite(sunriseDB)
user: User
): Promise<number> {
const database = await acquireConnection()
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -46,10 +45,10 @@ export default async function addFee(
feeForm.feeAccount, feeForm.feeAccount,
feeForm.contractTypeId === '' ? undefined : feeForm.contractTypeId, feeForm.contractTypeId === '' ? undefined : feeForm.contractTypeId,
feeForm.burialSiteTypeId === '' ? undefined : feeForm.burialSiteTypeId, feeForm.burialSiteTypeId === '' ? undefined : feeForm.burialSiteTypeId,
feeForm.feeAmount ?? undefined, feeForm.feeAmount === '' ? undefined : feeForm.feeAmount,
feeForm.feeFunction ?? undefined, feeForm.feeFunction ?? undefined,
feeForm.taxAmount ?? undefined, feeForm.taxAmount === '' ? undefined : feeForm.taxAmount,
feeForm.taxPercentage ?? undefined, feeForm.taxPercentage === '' ? undefined : feeForm.taxPercentage,
(feeForm.includeQuantity ?? '') === '' ? 0 : 1, (feeForm.includeQuantity ?? '') === '' ? 0 : 1,
feeForm.quantityUnit, feeForm.quantityUnit,
(feeForm.isRequired ?? '') === '' ? 0 : 1, (feeForm.isRequired ?? '') === '' ? 0 : 1,
@ -60,7 +59,7 @@ export default async function addFee(
rightNowMillis rightNowMillis
) )
database.release() database.close()
return result.lastInsertRowid as number return result.lastInsertRowid as number
} }

View File

@ -3,4 +3,4 @@ export interface AddFeeCategoryForm {
isGroupedFee?: '1'; isGroupedFee?: '1';
orderNumber?: number; orderNumber?: number;
} }
export default function addFeeCategory(feeCategoryForm: AddFeeCategoryForm, user: User): Promise<number>; export default function addFeeCategory(feeCategoryForm: AddFeeCategoryForm, user: User): number;

View File

@ -1,6 +1,7 @@
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addFeeCategory(feeCategoryForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = await acquireConnection(); export default function addFeeCategory(feeCategoryForm, user) {
const database = sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into FeeCategories ( .prepare(`insert into FeeCategories (
@ -10,6 +11,6 @@ export default async function addFeeCategory(feeCategoryForm, user) {
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?)`)
.run(feeCategoryForm.feeCategory, (feeCategoryForm.isGroupedFee ?? '') === '1' ? 1 : 0, feeCategoryForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(feeCategoryForm.feeCategory, (feeCategoryForm.isGroupedFee ?? '') === '1' ? 1 : 0, feeCategoryForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.release(); database.close();
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,4 +1,6 @@
import { acquireConnection } from './pool.js' import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
export interface AddFeeCategoryForm { export interface AddFeeCategoryForm {
feeCategory: string feeCategory: string
@ -6,11 +8,11 @@ export interface AddFeeCategoryForm {
orderNumber?: number orderNumber?: number
} }
export default async function addFeeCategory( export default function addFeeCategory(
feeCategoryForm: AddFeeCategoryForm, feeCategoryForm: AddFeeCategoryForm,
user: User user: User
): Promise<number> { ): number {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -33,7 +35,7 @@ export default async function addFeeCategory(
rightNowMillis rightNowMillis
) )
database.release() database.close()
return result.lastInsertRowid as number return result.lastInsertRowid as number
} }

View File

@ -1,10 +1,11 @@
export interface AddForm { export interface AddForm {
funeralHomeKey: string;
funeralHomeName: string; funeralHomeName: string;
funeralHomeAddress1: string; funeralHomeAddress1: string;
funeralHomeAddress2: string; funeralHomeAddress2: string;
funeralHomeCity: string; funeralHomeCity: string;
funeralHomeProvince: string;
funeralHomePostalCode: string; funeralHomePostalCode: string;
funeralHomeProvince: string;
funeralHomePhoneNumber: string; funeralHomePhoneNumber: string;
} }
export default function addFuneralHome(addForm: AddForm, user: User): Promise<number>; export default function addFuneralHome(addForm: AddForm, user: User): number;

View File

@ -1,15 +1,16 @@
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addFuneralHome(addForm, user) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = await acquireConnection(); export default function addFuneralHome(addForm, user) {
const database = sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into FuneralHomes ( .prepare(`insert into FuneralHomes (
funeralHomeName, funeralHomeAddress1, funeralHomeAddress2, funeralHomeName, funeralHomeKey, funeralHomeAddress1, funeralHomeAddress2,
funeralHomeCity, funeralHomeProvince, funeralHomePostalCode, funeralHomePhoneNumber, funeralHomeCity, funeralHomeProvince, funeralHomePostalCode, funeralHomePhoneNumber,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.funeralHomeName, addForm.funeralHomeAddress1, addForm.funeralHomeAddress2, addForm.funeralHomeCity, addForm.funeralHomeProvince, addForm.funeralHomePostalCode, addForm.funeralHomePhoneNumber, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(addForm.funeralHomeName, addForm.funeralHomeKey, addForm.funeralHomeAddress1, addForm.funeralHomeAddress2, addForm.funeralHomeCity, addForm.funeralHomeProvince, addForm.funeralHomePostalCode, addForm.funeralHomePhoneNumber, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.release(); database.close();
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,34 +1,37 @@
import { acquireConnection } from './pool.js' import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
export interface AddForm { export interface AddForm {
funeralHomeKey: string
funeralHomeName: string funeralHomeName: string
funeralHomeAddress1: string funeralHomeAddress1: string
funeralHomeAddress2: string funeralHomeAddress2: string
funeralHomeCity: string funeralHomeCity: string
funeralHomeProvince: string
funeralHomePostalCode: string funeralHomePostalCode: string
funeralHomeProvince: string
funeralHomePhoneNumber: string funeralHomePhoneNumber: string
} }
export default async function addFuneralHome( export default function addFuneralHome(addForm: AddForm, user: User): number {
addForm: AddForm, const database = sqlite(sunriseDB)
user: User
): Promise<number> {
const database = await acquireConnection()
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
const result = database const result = database
.prepare( .prepare(
`insert into FuneralHomes ( `insert into FuneralHomes (
funeralHomeName, funeralHomeAddress1, funeralHomeAddress2, funeralHomeName, funeralHomeKey, funeralHomeAddress1, funeralHomeAddress2,
funeralHomeCity, funeralHomeProvince, funeralHomePostalCode, funeralHomePhoneNumber, funeralHomeCity, funeralHomeProvince, funeralHomePostalCode, funeralHomePhoneNumber,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
) )
.run( .run(
addForm.funeralHomeName, addForm.funeralHomeName,
addForm.funeralHomeKey,
addForm.funeralHomeAddress1, addForm.funeralHomeAddress1,
addForm.funeralHomeAddress2, addForm.funeralHomeAddress2,
addForm.funeralHomeCity, addForm.funeralHomeCity,
@ -41,7 +44,7 @@ export default async function addFuneralHome(
rightNowMillis rightNowMillis
) )
database.release() database.close()
return result.lastInsertRowid as number return result.lastInsertRowid as number
} }

View File

@ -1,6 +1,7 @@
export interface AddForm { export interface AddIntermentContainerTypeForm {
intermentContainerType: string; intermentContainerType: string;
isCremationType?: string; intermentContainerTypeKey?: string;
orderNumber?: number; isCremationType?: '0' | '1';
orderNumber?: number | string;
} }
export default function addIntermentContainerType(addForm: AddForm, user: User): Promise<number>; export default function addIntermentContainerType(addForm: AddIntermentContainerTypeForm, user: User): number;

View File

@ -1,16 +1,17 @@
import sqlite from 'better-sqlite3';
import { sunriseDB } from '../helpers/database.helpers.js';
import { clearCacheByTableName } from '../helpers/functions.cache.js'; import { clearCacheByTableName } from '../helpers/functions.cache.js';
import { acquireConnection } from './pool.js'; export default function addIntermentContainerType(addForm, user) {
export default async function addIntermentContainerType(addForm, user) { const database = sqlite(sunriseDB);
const database = await acquireConnection();
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
const result = database const result = database
.prepare(`insert into IntermentContainerTypes ( .prepare(`insert into IntermentContainerTypes (
intermentContainerType, isCremationType, orderNumber, intermentContainerType, intermentContainerTypeKey, isCremationType, orderNumber,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?)`) values (?, ?, ?, ?, ?, ?, ?, ?)`)
.run(addForm.intermentContainerType, addForm.isCremationType === undefined ? 0 : 1, addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(addForm.intermentContainerType, addForm.intermentContainerTypeKey ?? '', addForm.isCremationType ?? '0', addForm.orderNumber ?? -1, user.userName, rightNowMillis, user.userName, rightNowMillis);
database.release(); database.close();
clearCacheByTableName('IntermentContainerTypes'); clearCacheByTableName('IntermentContainerTypes');
return result.lastInsertRowid; return result.lastInsertRowid;
} }

View File

@ -1,32 +1,35 @@
import sqlite from 'better-sqlite3'
import { sunriseDB } from '../helpers/database.helpers.js'
import { clearCacheByTableName } from '../helpers/functions.cache.js' import { clearCacheByTableName } from '../helpers/functions.cache.js'
import { acquireConnection } from './pool.js' export interface AddIntermentContainerTypeForm {
export interface AddForm {
intermentContainerType: string intermentContainerType: string
isCremationType?: string intermentContainerTypeKey?: string
orderNumber?: number isCremationType?: '0' | '1'
orderNumber?: number | string
} }
export default async function addIntermentContainerType( export default function addIntermentContainerType(
addForm: AddForm, addForm: AddIntermentContainerTypeForm,
user: User user: User
): Promise<number> { ): number {
const database = await acquireConnection() const database = sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
const result = database const result = database
.prepare( .prepare(
`insert into IntermentContainerTypes ( `insert into IntermentContainerTypes (
intermentContainerType, isCremationType, orderNumber, intermentContainerType, intermentContainerTypeKey, isCremationType, orderNumber,
recordCreate_userName, recordCreate_timeMillis, recordCreate_userName, recordCreate_timeMillis,
recordUpdate_userName, recordUpdate_timeMillis) recordUpdate_userName, recordUpdate_timeMillis)
values (?, ?, ?, ?, ?, ?, ?)` values (?, ?, ?, ?, ?, ?, ?, ?)`
) )
.run( .run(
addForm.intermentContainerType, addForm.intermentContainerType,
addForm.isCremationType === undefined ? 0 : 1, addForm.intermentContainerTypeKey ?? '',
addForm.isCremationType ?? '0',
addForm.orderNumber ?? -1, addForm.orderNumber ?? -1,
user.userName, user.userName,
rightNowMillis, rightNowMillis,
@ -34,7 +37,7 @@ export default async function addIntermentContainerType(
rightNowMillis rightNowMillis
) )
database.release() database.close()
clearCacheByTableName('IntermentContainerTypes') clearCacheByTableName('IntermentContainerTypes')

View File

@ -1,7 +1,7 @@
import type { PoolConnection } from 'better-sqlite-pool'; import sqlite from 'better-sqlite3';
export interface BurialSiteFieldForm { export interface BurialSiteFieldForm {
burialSiteId: string | number; burialSiteId: number | string;
burialSiteTypeFieldId: string | number; burialSiteTypeFieldId: number | string;
fieldValue: string; fieldValue: string;
} }
export default function addOrUpdateBurialSiteField(fieldForm: BurialSiteFieldForm, user: User, connectedDatabase?: PoolConnection): Promise<boolean>; export default function addOrUpdateBurialSiteField(fieldForm: BurialSiteFieldForm, user: User, connectedDatabase?: sqlite.Database): boolean;

View File

@ -1,16 +1,17 @@
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addOrUpdateBurialSiteField(fieldForm, user, connectedDatabase) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = connectedDatabase ?? (await acquireConnection()); export default function addOrUpdateBurialSiteField(fieldForm, user, connectedDatabase) {
const database = connectedDatabase ?? sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
let result = database let result = database
.prepare(`update BurialSiteFields .prepare(`update BurialSiteFields
set fieldValue = ?, set fieldValue = ?,
recordUpdate_userName = ?, recordUpdate_userName = ?,
recordUpdate_timeMillis = ?, recordUpdate_timeMillis = ?,
recordDelete_userName = null, recordDelete_userName = null,
recordDelete_timeMillis = null recordDelete_timeMillis = null
where burialSiteId = ? where burialSiteId = ?
and burialSiteTypeFieldId = ?`) and burialSiteTypeFieldId = ?`)
.run(fieldForm.fieldValue, user.userName, rightNowMillis, fieldForm.burialSiteId, fieldForm.burialSiteTypeFieldId); .run(fieldForm.fieldValue, user.userName, rightNowMillis, fieldForm.burialSiteId, fieldForm.burialSiteTypeFieldId);
if (result.changes === 0) { if (result.changes === 0) {
result = database result = database
@ -22,7 +23,7 @@ export default async function addOrUpdateBurialSiteField(fieldForm, user, connec
.run(fieldForm.burialSiteId, fieldForm.burialSiteTypeFieldId, fieldForm.fieldValue, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(fieldForm.burialSiteId, fieldForm.burialSiteTypeFieldId, fieldForm.fieldValue, user.userName, rightNowMillis, user.userName, rightNowMillis);
} }
if (connectedDatabase === undefined) { if (connectedDatabase === undefined) {
database.release(); database.close();
} }
return result.changes > 0; return result.changes > 0;
} }

View File

@ -1,19 +1,19 @@
import type { PoolConnection } from 'better-sqlite-pool' import sqlite from 'better-sqlite3'
import { acquireConnection } from './pool.js' import { sunriseDB } from '../helpers/database.helpers.js'
export interface BurialSiteFieldForm { export interface BurialSiteFieldForm {
burialSiteId: string | number burialSiteId: number | string
burialSiteTypeFieldId: string | number burialSiteTypeFieldId: number | string
fieldValue: string fieldValue: string
} }
export default async function addOrUpdateBurialSiteField( export default function addOrUpdateBurialSiteField(
fieldForm: BurialSiteFieldForm, fieldForm: BurialSiteFieldForm,
user: User, user: User,
connectedDatabase?: PoolConnection connectedDatabase?: sqlite.Database
): Promise<boolean> { ): boolean {
const database = connectedDatabase ?? (await acquireConnection()) const database = connectedDatabase ?? sqlite(sunriseDB)
const rightNowMillis = Date.now() const rightNowMillis = Date.now()
@ -21,12 +21,12 @@ export default async function addOrUpdateBurialSiteField(
.prepare( .prepare(
`update BurialSiteFields `update BurialSiteFields
set fieldValue = ?, set fieldValue = ?,
recordUpdate_userName = ?, recordUpdate_userName = ?,
recordUpdate_timeMillis = ?, recordUpdate_timeMillis = ?,
recordDelete_userName = null, recordDelete_userName = null,
recordDelete_timeMillis = null recordDelete_timeMillis = null
where burialSiteId = ? where burialSiteId = ?
and burialSiteTypeFieldId = ?` and burialSiteTypeFieldId = ?`
) )
.run( .run(
fieldForm.fieldValue, fieldForm.fieldValue,
@ -57,7 +57,7 @@ export default async function addOrUpdateBurialSiteField(
} }
if (connectedDatabase === undefined) { if (connectedDatabase === undefined) {
database.release() database.close()
} }
return result.changes > 0 return result.changes > 0

View File

@ -1,7 +1,7 @@
import type { PoolConnection } from 'better-sqlite-pool'; import sqlite from 'better-sqlite3';
export interface ContractFieldForm { export interface ContractFieldForm {
contractId: string | number; contractId: number | string;
contractTypeFieldId: string | number; contractTypeFieldId: number | string;
fieldValue: string; fieldValue: string;
} }
export default function addOrUpdateContractField(fieldForm: ContractFieldForm, user: User, connectedDatabase?: PoolConnection): Promise<boolean>; export default function addOrUpdateContractField(fieldForm: ContractFieldForm, user: User, connectedDatabase?: sqlite.Database): boolean;

View File

@ -1,16 +1,17 @@
import { acquireConnection } from './pool.js'; import sqlite from 'better-sqlite3';
export default async function addOrUpdateContractField(fieldForm, user, connectedDatabase) { import { sunriseDB } from '../helpers/database.helpers.js';
const database = connectedDatabase ?? (await acquireConnection()); export default function addOrUpdateContractField(fieldForm, user, connectedDatabase) {
const database = connectedDatabase ?? sqlite(sunriseDB);
const rightNowMillis = Date.now(); const rightNowMillis = Date.now();
let result = database let result = database
.prepare(`update ContractFields .prepare(`update ContractFields
set fieldValue = ?, set fieldValue = ?,
recordUpdate_userName = ?, recordUpdate_userName = ?,
recordUpdate_timeMillis = ?, recordUpdate_timeMillis = ?,
recordDelete_userName = null, recordDelete_userName = null,
recordDelete_timeMillis = null recordDelete_timeMillis = null
where contractId = ? where contractId = ?
and contractTypeFieldId = ?`) and contractTypeFieldId = ?`)
.run(fieldForm.fieldValue, user.userName, rightNowMillis, fieldForm.contractId, fieldForm.contractTypeFieldId); .run(fieldForm.fieldValue, user.userName, rightNowMillis, fieldForm.contractId, fieldForm.contractTypeFieldId);
if (result.changes === 0) { if (result.changes === 0) {
result = database result = database
@ -22,7 +23,7 @@ export default async function addOrUpdateContractField(fieldForm, user, connecte
.run(fieldForm.contractId, fieldForm.contractTypeFieldId, fieldForm.fieldValue, user.userName, rightNowMillis, user.userName, rightNowMillis); .run(fieldForm.contractId, fieldForm.contractTypeFieldId, fieldForm.fieldValue, user.userName, rightNowMillis, user.userName, rightNowMillis);
} }
if (connectedDatabase === undefined) { if (connectedDatabase === undefined) {
database.release(); database.close();
} }
return result.changes > 0; return result.changes > 0;
} }

Some files were not shown because too many files have changed in this diff Show More