Reference: {{submissionId}}
diff --git a/package-lock.json b/package-lock.json index 894591a..8a5552f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.2", "handlebars": "^4.7.8", + "node-cache": "^5.1.2", "pg": "^8.16.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", @@ -9440,6 +9441,25 @@ "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/node-cache/node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/node-emoji": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", diff --git a/package.json b/package.json index fd3f78a..b152295 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.2", "handlebars": "^4.7.8", + "node-cache": "^5.1.2", "pg": "^8.16.3", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", diff --git a/schemas/community-sports-programme.json b/schemas/community-sports-programme.json index 271bb56..f1baa36 100644 --- a/schemas/community-sports-programme.json +++ b/schemas/community-sports-programme.json @@ -4,219 +4,290 @@ "description": "Register for our community sports programme", "fields": [ { - "name": "firstName", - "type": "string", - "label": "First Name", - "required": true, - "validations": { - "min": 2, - "max": 50 - } - }, - { - "name": "lastName", - "type": "string", - "label": "Last Name", + "name": "applicant", + "type": "object", "required": true, - "validations": { - "min": 2, - "max": 50 - } + "fields": [ + { + "name": "firstName", + "type": "string", + "label": "First name", + "required": true, + "validations": { + "min": 1, + "max": 100, + "message": "First name is required" + } + }, + { + "name": "lastName", + "type": "string", + "label": "Last name", + "required": true, + "validations": { + "min": 1, + "max": 100, + "message": "Last name is required" + } + }, + { + "name": "dateOfBirth", + "type": "date", + "label": "Date of birth", + "required": false, + "validations": { + "regex": "^\\d{4}-\\d{2}-\\d{2}$", + "message": "Date of birth is required and must be in YYYY-MM-DD format" + } + }, + { + "name": "sex", + "type": "string", + "label": "Sex", + "required": true, + "validations": { + "regex": "^(male|female)$", + "message": "Must select a valid sex" + } + } + ] }, { - "name": "dateOfBirth", - "type": "date", - "label": "Date of Birth", + "name": "discipline", + "type": "object", "required": true, - "validations": { - "regex": "^\\d{4}-\\d{2}-\\d{2}$", - "message": "Date must be in YYYY-MM-DD format" - } - }, - { - "name": "gender", - "type": "string", - "label": "Gender", - "required": true - }, - { - "name": "disciplineOfInterest", - "type": "string", - "label": "Discipline of Interest", - "required": true - }, - { - "name": "disciplineExperience", - "type": "string", - "label": "Do you have experience in this discipline?", - "required": true - }, - { - "name": "experienceLevel", - "type": "string", - "label": "Experience Level", - "required": false - }, - { - "name": "otherExperienceLevel", - "type": "string", - "label": "Other Experience Level", - "required": false - }, - { - "name": "yearsOfExperience", - "type": "number", - "label": "Years of Experience", - "required": false, - "validations": { - "min": 0, - "max": 50 - } - }, - { - "name": "employmentStatus", - "type": "string", - "label": "Employment Status", - "required": true + "fields": [ + { + "name": "areaOfInterest", + "type": "string", + "label": "Discipline of Interest", + "required": true + }, + { + "name": "hasExperience", + "type": "string", + "label": "Do you have experience in this discipline?", + "required": true, + "validations": { + "regex": "^(yes|no)$", + "message": "Must select a valid option" + } + } + ] }, { - "name": "institutionName", - "type": "string", - "label": "Institution Name", - "required": false, - "validations": { - "max": 100 - } + "name": "experience", + "type": "object", + "fields": [ + { + "name": "levelOfExperience", + "type": "string", + "label": "Experience Level", + "required": false + }, + { + "name": "otherExperience", + "type": "string", + "label": "Other Experience Level", + "required": false + }, + { + "name": "yearsOfExperience", + "type": "number", + "label": "Years of Experience", + "required": false, + "validations": { + "min": 0, + "max": 50 + } + } + ] }, { - "name": "employerName", - "type": "string", - "label": "Employer Name", - "required": false, - "validations": { - "max": 100 - } + "name": "employment", + "type": "object", + "fields": [ + { + "name": "status", + "type": "string", + "label": "Employment Status", + "required": true + }, + { + "name": "institutionName", + "type": "string", + "label": "Institution Name", + "required": false, + "validations": { + "max": 100 + } + }, + { + "name": "companyName", + "type": "string", + "label": "Company or organisation name is require", + "required": false, + "validations": { + "max": 100 + } + }, + { + "name": "otherDetails", + "type": "string", + "label": "Other Employment Details", + "required": false, + "validations": { + "max": 200 + } + } + ] }, { - "name": "otherEmploymentDetails", + "name": "belongsToOrganisations", "type": "string", - "label": "Other Employment Details", - "required": false, + "label": "Do you belong to any organisations?", + "required": true, "validations": { - "max": 200 + "regex": "^(yes|no)$", + "message": "Must select an option" } }, { - "name": "belongsToOrganizations", - "type": "string", - "label": "Do you belong to any sports organizations?", - "required": true - }, - { - "name": "organizationNames", + "name": "organizationDetails", "type": "array", - "label": "Organization Names", + "label": "Organization Details", "required": false, "items": { "type": "object", "properties": { - "value": { + "organizationName": { + "type": "string" + }, + "hasSignificantPosition": { "type": "string" } } } }, { - "name": "addressLine1", - "type": "string", - "label": "Address Line 1", + "name": "contact", + "type": "object", + "label": "Contact Information", "required": true, - "validations": { - "max": 100 - } - }, - { - "name": "addressLine2", - "type": "string", - "label": "Address Line 2", - "required": false, - "validations": { - "max": 100 - } - }, - { - "name": "email", - "type": "string", - "label": "Email address", - "required": true - }, - { - "name": "parish", - "type": "string", - "label": "Parish", - "required": true - }, - { - "name": "telephoneNumber", - "type": "string", - "label": "Telephone Number", - "required": true - }, - { - "name": "emergencyFirstName", - "type": "string", - "label": "Emergency Contact First Name", - "required": true, - "validations": { - "min": 2, - "max": 50 - } - }, - { - "name": "emergencyLastName", - "type": "string", - "label": "Emergency Contact Last Name", - "required": true, - "validations": { - "min": 2, - "max": 50 - } - }, - { - "name": "emergencyRelationship", - "type": "string", - "label": "Relationship to Emergency Contact", - "required": true + "fields": [ + { + "name": "addressLine1", + "type": "string", + "label": "Address Line 1", + "required": true, + "validations": { + "max": 100 + } + }, + { + "name": "addressLine2", + "type": "string", + "label": "Address Line 2", + "required": false, + "validations": { + "max": 100 + } + }, + { + "name": "parish", + "type": "string", + "label": "Parish", + "required": true + }, + { + "name": "email", + "type": "email", + "label": "Email Address", + "required": true + }, + { + "name": "telephoneNumber", + "type": "string", + "label": "Telephone Number", + "required": true + } + ] }, { - "name": "emergencyAddressLine1", - "type": "string", - "label": "Emergency Contact Address Line 1", + "name": "emergency", + "type": "object", + "label": "Contact Information", "required": true, - "validations": { - "max": 100 - } - }, - { - "name": "emergencyAddressLine2", - "type": "string", - "label": "Emergency Contact Address Line 2", - "required": false, - "validations": { - "max": 100 - } - }, - { - "name": "emergencyParish", - "type": "string", - "label": "Emergency Contact Parish", - "required": true - }, - { - "name": "emergencyTelephoneNumber", - "type": "string", - "label": "Emergency Contact Telephone Number", - "required": true + "fields": [ + { + "name": "firstName", + "type": "string", + "label": "First name", + "required": true, + "validations": { + "min": 1, + "max": 100, + "message": "First name is required" + } + }, + { + "name": "lastName", + "type": "string", + "label": "Last name", + "required": true, + "validations": { + "min": 1, + "max": 100, + "message": "Last name is required" + } + }, + { + "name": "relationship", + "type": "string", + "label": "Relationship", + "required": false, + "validations": { + "max": 100, + "message": "Relationship is required" + } + }, + { + "name": "addressLine1", + "type": "string", + "label": "Address line 1", + "required": true, + "validations": { + "max": 100 + } + }, + { + "name": "addressLine2", + "type": "string", + "label": "Address line 2", + "required": false, + "validations": { + "max": 100 + } + }, + { + "name": "parish", + "type": "string", + "label": "Parish", + "required": true + }, + { + "name": "email", + "type": "email", + "label": "Email Address", + "required": true + }, + { + "name": "telephoneNumber", + "type": "string", + "label": "Telephone Number", + "required": true + } + ] } ], "processors": [ @@ -224,9 +295,17 @@ "type": "email", "config": { "to": "{{db:community-sports-registration:admin_email}}", - "subject": "New Community Sports Programme Registration - {{formData.firstName}} {{formData.lastName}}", + "subject": "New Community Sports Programme Registration - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "community-sports-registration" } + }, + { + "type": "email", + "config": { + "to": "{{formData.email}}", + "subject": "Community Sports Programme Registration - Submission Received", + "template": "community-sports-programme-receipt" + } } ] } diff --git a/schemas/conductor-licence.json b/schemas/conductor-licence.json index 89e447b..fe9452c 100644 --- a/schemas/conductor-licence.json +++ b/schemas/conductor-licence.json @@ -244,6 +244,14 @@ "subject": "Apply for conductor licence - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "apply-for-conductor-licence" } + }, + { + "type": "email", + "config": { + "to": "{{formData.contactDetails.email}}", + "subject": "Conductor Licence Application - Submission Received", + "template": "conductor-licence-receipt" + } } ] } diff --git a/schemas/fire-service-inspection.json b/schemas/fire-service-inspection.json index d74cfb0..f50b2e2 100644 --- a/schemas/fire-service-inspection.json +++ b/schemas/fire-service-inspection.json @@ -118,9 +118,17 @@ "type": "email", "config": { "to": "{{db:request-a-fire-service-inspection:admin_email}}", - "subject": "New Birth Certificate Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", + "subject": "New Fire Service Inspection Request - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "request-a-fire-service-inspection" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Fire Service Inspection Request - Submission Received", + "template": "fire-service-inspection-receipt" + } } ] } diff --git a/schemas/get-birth-certificate.json b/schemas/get-birth-certificate.json index 5ef54fc..c5c2562 100644 --- a/schemas/get-birth-certificate.json +++ b/schemas/get-birth-certificate.json @@ -482,39 +482,39 @@ ] } ], - "processors": [ - { - "type": "payment", - "config": { - "provider": "ezpay", - "department": "oag_registration", - "paymentCode": "{{db:get-birth-certificate:payment_code}}", - "amount": "{{formData.order.numberOfCopies * db:get-birth-certificate:payment_amount}}", - "description": "Birth Certificate Processing Fee (per copy)", - "required": true, - "timing": "after_validation", - "responseData": { - "include": ["order.numberOfCopies"] - } - } - }, - { - "type": "email", - "config": { - "to": "{{db:get-birth-certificate:admin_email}}", - "subject": "New Birth Certificate Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", - "template": "birth-certificate", - "recipientType": "admin" - } - }, - { - "type": "email", - "config": { - "to": "{{formData.applicant.email}}", - "subject": "Birth Certificate - Submission Received", - "template": "birth-certificate-receipt", - "recipientType": "user" - } - } - ] + "processors": [ + { + "type": "payment", + "config": { + "provider": "ezpay", + "department": "oag_registration", + "paymentCode": "{{db:get-birth-certificate:payment_code}}", + "amount": "{{formData.order.numberOfCopies * db:get-birth-certificate:payment_amount}}", + "description": "Birth Certificate Processing Fee (per copy)", + "required": true, + "timing": "after_validation", + "responseData": { + "include": ["order.numberOfCopies"] + } + } + }, + { + "type": "email", + "config": { + "to": "{{db:get-birth-certificate:admin_email}}", + "subject": "New Birth Certificate Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", + "template": "birth-certificate", + "recipientType": "admin" + } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Birth Certificate - Submission Received", + "template": "birth-certificate-receipt", + "recipientType": "user" + } + } + ] } diff --git a/schemas/get-death-certificate.json b/schemas/get-death-certificate.json index 75cc4c1..aa9e150 100644 --- a/schemas/get-death-certificate.json +++ b/schemas/get-death-certificate.json @@ -288,6 +288,14 @@ "template": "death-certificate-receipt", "recipientType": "user" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Death Certificate Application - Submission Received", + "template": "death-certificate-receipt" + } } ] } diff --git a/schemas/jobstart-plus-programme.json b/schemas/jobstart-plus-programme.json index ef71ed6..aeda711 100644 --- a/schemas/jobstart-plus-programme.json +++ b/schemas/jobstart-plus-programme.json @@ -480,7 +480,7 @@ "name": "willingToWorkAtNight", "type": "string", "label": "Are you willing to work at night?", - "required": true, + "required": false, "validations": { "regex": "^(yes|no)$", "message": "Must select an option" @@ -508,6 +508,14 @@ "subject": "New JobStart Plus Programme Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "jobstart-plus-programme" } + }, + { + "type": "email", + "config": { + "to": "{{formData.contactDetails.email}}", + "subject": "JobStart Plus Programme Application - Submission Received", + "template": "jobstart-plus-programme-receipt" + } } ] } diff --git a/schemas/permission-to-remove-tree.json b/schemas/permission-to-remove-tree.json index c889fd0..ce54949 100644 --- a/schemas/permission-to-remove-tree.json +++ b/schemas/permission-to-remove-tree.json @@ -145,6 +145,14 @@ "subject": "New Request to remove protected tree - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "permission-to-remove-tree" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Permission to Remove Tree - Submission Received", + "template": "permission-to-remove-tree-receipt" + } } ] } diff --git a/schemas/post-office-redirection-business.json b/schemas/post-office-redirection-business.json index bc81c82..bae3713 100644 --- a/schemas/post-office-redirection-business.json +++ b/schemas/post-office-redirection-business.json @@ -107,6 +107,23 @@ "message": "Last name is required" } }, + { + "name": "idNumber", + "type": "string", + "required": false, + "validations": { + "regex": "^\\d{6}[-]?\\d{4}$", + "message": "Must be in format XXXXXX-XXXX" + } + }, + { + "name": "passportNumber", + "type": "string", + "required": false, + "validations": { + "max": 50 + } + }, { "name": "email", "type": "email", @@ -122,12 +139,12 @@ ] }, { - "name": "permissionDetails", + "name": "positionDetails", "type": "string", - "label": "Tell us what permission you have to act for this business", + "label": "Tell us what position you hold in the business.", "required": true, "validations": { - "message": "Permission details required" + "message": "Position is required" } }, { @@ -175,38 +192,19 @@ "message": "Enter a valid postal code (e.g., BB17004)" } }, - { - "name": "isMovingPermanent", - "type": "string", - "label": "Are you moving permanently?", - "required": true, - "validations": { - "regex": "^(yes|no)$", - "message": "Must select an option" - } - }, { "name": "redirectionStartDate", "type": "date", "label": "Redirection Start Date", - "required": false + "required": true }, { "name": "redirectionEndDate", "type": "date", "label": "Redirection End Date", - "required": false + "required": true } ] - }, - { - "name": "uploadDocumentUrls", - "type": "array", - "label": "Uploaded Documents", - "required": true, - "items": { - "type": "string" - } } ], "processors": [ @@ -217,6 +215,14 @@ "subject": "New Request to Redirect my business mail - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "post-office-redirection-notice" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Business Mail Redirection - Submission Received", + "template": "post-office-redirection-business-receipt" + } } ] } diff --git a/schemas/post-office-redirection-deceased.json b/schemas/post-office-redirection-deceased.json index bf28cc4..e84320b 100644 --- a/schemas/post-office-redirection-deceased.json +++ b/schemas/post-office-redirection-deceased.json @@ -132,14 +132,13 @@ } }, { - "name": "relationshipToDeceased", + "name": "middleName", "type": "string", - "label": "What is your relationship to the person?", - "required": true, + "label": "Middle name", + "required": false, "validations": { - "min": 1, "max": 100, - "message": "Relationship to deceased is required" + "message": "Middle name must be between 1 and 100 characters" } }, { @@ -153,6 +152,17 @@ "message": "Last name is required" } }, + { + "name": "relationshipToDeceased", + "type": "string", + "label": "What is your relationship to the person?", + "required": true, + "validations": { + "min": 1, + "max": 100, + "message": "Relationship to deceased is required" + } + }, { "name": "email", "type": "email", @@ -221,16 +231,6 @@ "message": "Enter a valid postal code (e.g., BB17004)" } }, - { - "name": "isRedirectPermanent", - "type": "string", - "label": "Are you redirecting their mail permanently?", - "required": true, - "validations": { - "regex": "^(yes|no)$", - "message": "Must select an option" - } - }, { "name": "redirectionStartDate", "type": "string", @@ -244,15 +244,6 @@ "required": false } ] - }, - { - "name": "uploadDocumentUrls", - "type": "array", - "label": "Uploaded Documents", - "required": true, - "items": { - "type": "string" - } } ], "processors": [ @@ -263,6 +254,14 @@ "subject": "New Request to redirect mail for a Deceased Person - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "post-office-redirection-notice" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Deceased Mail Redirection - Submission Received", + "template": "post-office-redirection-deceased-receipt" + } } ] } diff --git a/schemas/post-office-redirection-individual.json b/schemas/post-office-redirection-individual.json index f440c7c..0072e96 100644 --- a/schemas/post-office-redirection-individual.json +++ b/schemas/post-office-redirection-individual.json @@ -29,6 +29,15 @@ "message": "First name is required" } }, + { + "name": "middleName", + "type": "string", + "label": "Middle name", + "required": false, + "validations": { + "max": 100 + } + }, { "name": "lastName", "type": "string", @@ -175,16 +184,6 @@ "message": "Enter a valid postal code (e.g., BB17004)" } }, - { - "name": "isMovingPermanent", - "type": "string", - "label": "Are you moving permanently?", - "required": true, - "validations": { - "regex": "^(yes|no)$", - "message": "Must select an option" - } - }, { "name": "redirectionStartDate", "type": "date", @@ -208,14 +207,21 @@ ] }, { - "name": "anyMinorDependents", - "type": "string", - "label": "Are there any minor dependents?", + "name": "dependents", + "type": "object", "required": true, - "validations": { - "regex": "^(yes|no)$", - "message": "Must select an option" - } + "fields": [ + { + "name": "anyMinorDependents", + "type": "string", + "label": "Are there any minor dependents?", + "required": true, + "validations": { + "regex": "^(yes|no)$", + "message": "Must select an option" + } + } + ] }, { "name": "minorDetails", @@ -228,8 +234,60 @@ "firstName": { "type": "string" }, + "middleName": { + "type": "string" + }, + "lastName": { + "type": "string" + }, + "idNumber": { + "type": "string", + "validations": { + "regex": "^\\d{6}-\\d{4}$" + } + } + } + } + }, + { + "name": "adult", + "type": "object", + "required": true, + "fields": [ + { + "name": "anyAdults", + "type": "string", + "label": "Are there any adults?", + "required": true, + "validations": { + "regex": "^(yes|no)$", + "message": "Must select an option" + } + } + ] + }, + { + "name": "adultDetails", + "type": "array", + "label": "Tell us about the adults that needs their email sent to the new address", + "required": false, + "items": { + "type": "object", + "properties": { + "firstName": { + "type": "string" + }, + "middleName": { + "type": "string" + }, "lastName": { "type": "string" + }, + "idNumber": { + "type": "string", + "validations": { + "regex": "^\\d{6}-\\d{4}$" + } } } } @@ -243,6 +301,14 @@ "subject": "New Request to redirect mail for an individual - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "post-office-redirection-notice" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Mail Redirection - Submission Received", + "template": "post-office-redirection-individual-receipt" + } } ] } diff --git a/schemas/primary-school-textbook-grant.json b/schemas/primary-school-textbook-grant.json index b1e1a52..bd1026b 100644 --- a/schemas/primary-school-textbook-grant.json +++ b/schemas/primary-school-textbook-grant.json @@ -193,9 +193,17 @@ "type": "email", "config": { "to": "{{db:primary-school-textbook-grant:admin_email}}", - "subject": "New Textbook Grant Application - {{formData.beneficiaries.firstName}} {{formData.beneficiaries.lastName}}", + "subject": "New Textbook Grant Application - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "primary-school-textbook-grant" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Primary School Textbook Grant - Submission Received", + "template": "primary-school-textbook-grant-receipt" + } } ] } diff --git a/schemas/project-protege-mentor.json b/schemas/project-protege-mentor.json index 770a665..99ab5f0 100644 --- a/schemas/project-protege-mentor.json +++ b/schemas/project-protege-mentor.json @@ -4,9 +4,9 @@ "description": "Register as a mentor for the Project Protege mentorship program", "fields": [ { - "name": "personal", + "name": "applicant", "type": "object", - "label": "Personal Information", + "label": "Applicant Information", "required": true, "fields": [ { diff --git a/schemas/register-birth-form.json b/schemas/register-birth-form.json index 7b563dd..ed7e245 100644 --- a/schemas/register-birth-form.json +++ b/schemas/register-birth-form.json @@ -53,28 +53,25 @@ } }, { - "name": "hadOtherSurname", + "name": "parish", "type": "string", - "required": false, + "required": true, "validations": { - "regex": "^(yes|no)$" + "min": 2, + "max": 500 } }, { - "name": "otherSurname", + "name": "streetAddress", "type": "string", - "required": false, + "required": true, "validations": { - "max": 100 + "min": 2, + "max": 500 } }, { - "name": "dateOfBirth", - "type": "date", - "required": false - }, - { - "name": "address", + "name": "addressLine2", "type": "string", "required": false, "validations": { @@ -82,11 +79,11 @@ } }, { - "name": "nationalRegistrationNumber", + "name": "idNumber", "type": "string", "required": false, "validations": { - "regex": "^\\d{6}-\\d{4}$", + "regex": "^\\d{6}[-]?\\d{4}$", "message": "Must be in format XXXXXX-XXXX" } }, @@ -99,20 +96,79 @@ } }, { - "name": "passportPlaceOfIssue", + "name": "occupation", "type": "string", "required": false, "validations": { "max": 100 } + } + ] + }, + { + "name": "birth", + "type": "object", + "required": true, + "fields": [ + { + "name": "placeOfBirth", + "type": "string", + "label": "Where did the birth take place?", + "required": true, + "validations": { + "regex": "^(health-facility|residential|other)$", + "message": "Must select an option" + } }, { - "name": "occupation", + "name": "parish", "type": "string", - "required": false, + "label": "Parish", + "required": false + }, + { + "name": "streetAddress", + "type": "string", + "label": "Street Address", + "required": false + }, + { + "name": "numberOfBirths", + "type": "string", + "label": "How many births do you need to register?", + "required": true, "validations": { - "max": 100 + "regex": "^(single|twins|triplets|more-than-triplets)$", + "message": "Must select an option" + } + }, + { + "name": "attendantAtBirth", + "type": "string", + "label": "Attendant at birth", + "required": true, + "validations": { + "regex": "^(doctor|midwife|nurse|relative|none)$", + "message": "Must select an option" } + }, + { + "name": "liveBorn", + "type": "string", + "label": "Live born", + "required": false + }, + { + "name": "stillBorn", + "type": "string", + "label": "Still born", + "required": false + }, + { + "name": "totalStillAlive", + "type": "string", + "label": "Total still alive", + "required": false } ] }, @@ -148,58 +204,54 @@ } }, { - "name": "hadOtherSurname", + "name": "maidenSurname", "type": "string", "required": false, "validations": { - "regex": "^(yes|no)$" + "max": 100 } }, { - "name": "otherSurname", + "name": "parish", "type": "string", - "required": false, + "required": true, "validations": { - "max": 100 + "min": 2, + "max": 500 } }, { - "name": "dateOfBirth", - "type": "date", - "required": true - }, - { - "name": "address", + "name": "streetAddress", "type": "string", "required": true, "validations": { - "min": 5, + "min": 2, "max": 500 } }, { - "name": "nationalRegistrationNumber", + "name": "addressLine2", "type": "string", "required": false, "validations": { - "regex": "^\\d{6}-\\d{4}$", - "message": "Must be in format XXXXXX-XXXX" + "max": 500 } }, { - "name": "passportNumber", + "name": "idNumber", "type": "string", "required": false, "validations": { - "max": 50 + "regex": "^\\d{6}[-]?\\d{4}$", + "message": "Must be in format XXXXXX-XXXX" } }, { - "name": "passportPlaceOfIssue", + "name": "passportNumber", "type": "string", "required": false, "validations": { - "max": 100 + "max": 50 } }, { @@ -219,7 +271,7 @@ "required": true, "fields": [ { - "name": "firstNames", + "name": "firstName", "type": "string", "required": true, "validations": { @@ -228,7 +280,7 @@ } }, { - "name": "middleNames", + "name": "middleName", "type": "string", "required": false, "validations": { @@ -254,51 +306,44 @@ "type": "string", "required": true, "validations": { - "regex": "^(Male|Female)$", - "message": "Must be 'Male' or 'Female'" + "regex": "^(male|female)$", + "message": "Must be 'male' or 'female'" } - }, + } + ] + }, + { + "name": "order", + "type": "object", + "required": true, + "fields": [ { - "name": "parishOfBirth", - "type": "string", + "name": "numberOfCopies", + "type": "number", + "label": "Number of copies", "required": true, "validations": { "min": 1, - "max": 100 + "max": 10, + "message": "You must order at least 1 copy and maximum 10 copies" } } ] - }, - { - "name": "numberOfCertificates", - "type": "number", - "required": true, - "validations": { - "min": 0, - "max": 20 - } - }, - { - "name": "email", - "type": "email", - "required": true - }, - { - "name": "phoneNumber", - "type": "string", - "required": true, - "validations": { - "min": 7, - "max": 20 - } } ], "processors": [ + { + "type": "opencrvs", + "config": { + "eventType": "birth", + "officeName": "Registration District A" + } + }, { "type": "email", "config": { "to": "{{db:register-birth-form:admin_email}}", - "subject": "New Birth Registration - {{formData.child.firstNames}} {{formData.child.lastName}}", + "subject": "New Birth Registration - {{formData.child.firstName}} {{formData.child.lastName}}", "template": "birth-registration" } }, diff --git a/schemas/reserve-company-name.json b/schemas/reserve-company-name.json index 73f80f8..2c3f87f 100644 --- a/schemas/reserve-company-name.json +++ b/schemas/reserve-company-name.json @@ -173,9 +173,17 @@ "type": "email", "config": { "to": "{{db:reserve-company-name:admin_email}}", - "subject": "New Request to Reserve Society Name - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", + "subject": "New Request to Reserve Company Name - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "reserve-company-name" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Reserve Company Name - Submission Received", + "template": "reserve-company-name-receipt" + } } ] } diff --git a/schemas/reserve-society-name.json b/schemas/reserve-society-name.json index 8a24435..6d47f6f 100644 --- a/schemas/reserve-society-name.json +++ b/schemas/reserve-society-name.json @@ -151,6 +151,14 @@ "subject": "New Request to Reserve Society Name - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "reserve-society-name" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Reserve Society Name - Submission Received", + "template": "reserve-society-name-receipt" + } } ] } diff --git a/schemas/sell-goods-services-beach-park.json b/schemas/sell-goods-services-beach-park.json index 5caa9c6..95f52e2 100644 --- a/schemas/sell-goods-services-beach-park.json +++ b/schemas/sell-goods-services-beach-park.json @@ -146,46 +146,102 @@ { "name": "goodsOrServices", "type": "string", + "label": "Selling goods or services", "required": true, "validations": { "regex": "^(goods|services)$", "message": "Must be 'goods' or 'services'" } + } + ] + }, + { + "name": "goods", + "type": "object", + "required": false, + "conditionalOn": { + "field": "selling.goodsOrServices", + "value": "goods" + }, + "fields": [ + { + "name": "from", + "type": "string", + "label": "Where are the goods from?", + "required": true, + "validations": { + "regex": "^(barbados|imported)$", + "message": "Must be 'barbados' or 'imported'" + } }, { "name": "manufacturingLocation", "type": "string", + "label": "Which country are the goods from?", "required": false, + "conditionalOn": { + "field": "goods.from", + "value": "imported" + }, "validations": { + "min": 2, "max": 100, - "message": "Location is required" + "message": "Location must be at least 2 characters" + } + }, + { + "name": "description", + "type": "string", + "label": "Describe the goods you would like to sell", + "required": true, + "validations": { + "min": 2, + "max": 500, + "message": "Description of goods must be at least 2 characters" + } + }, + { + "name": "intendedLocation", + "type": "string", + "label": "Where do you intend to sell your goods?", + "required": true, + "validations": { + "min": 2, + "max": 200, + "message": "Place of doing business must be at least 2 characters" } } ] }, { - "name": "business", + "name": "services", "type": "object", - "required": true, + "required": false, + "conditionalOn": { + "field": "selling.goodsOrServices", + "value": "services" + }, "fields": [ { - "name": "descriptionOfGoodsOrServices", + "name": "description", "type": "string", + "label": "Describe the services you would like to offer", "required": true, "validations": { "min": 2, - "max": 100, - "message": "Description is required" + "max": 500, + "message": "Description of services must be at least 2 characters" } }, { - "name": "intendedPlaceOfDoingBusiness", + "name": "intendedLocation", "type": "string", + "label": "Where do you intend to offer this service?", "required": true, "validations": { "min": 2, - "max": 100, - "message": "Place of doing business is required" + "max": 200, + "message": "Place of doing business must be at least 2 characters" } } ] @@ -373,6 +429,26 @@ } } ] + }, + { + "name": "documents", + "type": "object", + "required": true, + "fields": [ + { + "name": "policeCertificate", + "type": "file", + "label": "Police Certificate of Character", + "required": true + }, + { + "name": "passportPhotos", + "type": "file", + "label": "2 passport-sized photos", + "required": true, + "multiple": true + } + ] } ], "processors": [ @@ -383,6 +459,14 @@ "subject": "New Request to sell good or services at a beach or park - {{formData.applicant.firstName}} {{formData.applicant.lastName}}", "template": "sell-goods-services-beach-park-notice" } + }, + { + "type": "email", + "config": { + "to": "{{formData.applicant.email}}", + "subject": "Sell Goods/Services at Beach or Park - Submission Received", + "template": "sell-goods-services-beach-park-receipt" + } } ] } diff --git a/src/config/configuration.ts b/src/config/configuration.ts index 30e21a0..9991e80 100644 --- a/src/config/configuration.ts +++ b/src/config/configuration.ts @@ -53,7 +53,30 @@ export default () => ({ ministry_of_agriculture: process.env.EZPAY_MINISTRY_OF_AGRICULTURE_API_KEY, oag_registration: process.env.EZPAY_OAG_REGISTRATION_API_KEY, + post_office: process.env.EZPAY_OAG_REGISTRATION_API_KEY, //TODO: Update when we get the correct API key default: process.env.EZPAY_API_KEY || 'HWqgTn5EXIHLAzVjXtGpB2mIjgQgj0Ql', }, }, + opencrvs: { + // Use localhost URLs when running locally against OpenCRVS dev environment + localhost: process.env.OPENCRVS_LOCALHOST === 'true', + // Production/QA URLs + authBaseUrl: + process.env.OPENCRVS_AUTH_URL || 'https://auth.barbados-qa.opencrvs.org', + eventsBaseUrl: + process.env.OPENCRVS_EVENTS_URL || + 'https://register.barbados-qa.opencrvs.org', + locationsBaseUrl: + process.env.OPENCRVS_LOCATIONS_URL || + 'https://gateway.barbados-qa.opencrvs.org', + // Authentication credentials + clientId: process.env.OPENCRVS_CLIENT_ID, + clientSecret: process.env.OPENCRVS_CLIENT_SECRET, + // Default location names (resolved to IDs at runtime) + defaultOfficeName: + process.env.OPENCRVS_DEFAULT_OFFICE || + 'Registration Department Records Branch', + defaultHealthFacilityName: process.env.OPENCRVS_DEFAULT_HEALTH_FACILITY, + defaultParishName: process.env.OPENCRVS_DEFAULT_PARISH || 'Christ Church', + }, }); diff --git a/src/email/email.service.ts b/src/email/email.service.ts index 1bdcbbc..22b52ef 100644 --- a/src/email/email.service.ts +++ b/src/email/email.service.ts @@ -57,49 +57,65 @@ export class EmailService { private registerHandlebarsHelpers(): void { // Equality helper - Handlebars.registerHelper('eq', function (a, b) { + Handlebars.registerHelper('eq', function(a, b) { return a === b; }); // Not equal helper - Handlebars.registerHelper('ne', function (a, b) { + Handlebars.registerHelper('ne', function(a, b) { return a !== b; }); // Greater than helper - Handlebars.registerHelper('gt', function (a, b) { + Handlebars.registerHelper('gt', function(a, b) { return a > b; }); // Less than helper - Handlebars.registerHelper('lt', function (a, b) { + Handlebars.registerHelper('lt', function(a, b) { return a < b; }); // Greater than or equal helper - Handlebars.registerHelper('gte', function (a, b) { + Handlebars.registerHelper('gte', function(a, b) { return a >= b; }); // Less than or equal helper - Handlebars.registerHelper('lte', function (a, b) { + Handlebars.registerHelper('lte', function(a, b) { return a <= b; }); // Logical AND helper - Handlebars.registerHelper('and', function (...args) { + Handlebars.registerHelper('and', function(...args) { // Remove the last argument which is the options object const values = args.slice(0, -1); return values.every((val) => !!val); }); // Logical OR helper - Handlebars.registerHelper('or', function (...args) { + Handlebars.registerHelper('or', function(...args) { // Remove the last argument which is the options object const values = args.slice(0, -1); return values.some((val) => !!val); }); + Handlebars.registerHelper('today', function(...args) { + const currentDate = new Date(); + return currentDate.toDateString(); + }); + + Handlebars.registerHelper('titleCase', function(...args) { + const values = args.slice(0, -1); + const titled = values + .filter(v => typeof v === 'string') + .map(str => str.toLowerCase() + .replace(/\b\w/g, (char: string) => char.toUpperCase())) + .join(" "); + + return Handlebars.escapeExpression(titled); + }); + this.logger.log('Handlebars helpers registered'); } diff --git a/src/email/templates/apply-for-conductor-licence.hbs b/src/email/templates/apply-for-conductor-licence.hbs index 0dff27a..94fb2ed 100644 --- a/src/email/templates/apply-for-conductor-licence.hbs +++ b/src/email/templates/apply-for-conductor-licence.hbs @@ -12,18 +12,17 @@ .section-title { color: #2c5282; font-size: 18px; font-weight: bold; margin-bottom: 15px; border-bottom: 2px solid #2c5282; padding-bottom: 5px; } .field { margin-bottom: 12px; } .field-label { font-weight: bold; - color: #4a5568; display: inline-block; width: 200px; } .field-value { - color: #1a202c; } .address-comparison { display: flex; gap: 20px; } - .address-box { flex: 1; border: 1px solid #e2e8f0; padding: 15px; - border-radius: 5px; } .old-address { background-color: #fed7d7; } - .new-address { background-color: #c6f6d5; } .footer { margin-top: 30px; - padding: 20px; background-color: #edf2f7; border-radius: 5px; text-align: - center; font-size: 14px; color: #718096; } + color: #4a5568; display: inline-block; width: 250px; } .field-value { + color: #1a202c; } .footer { margin-top: 30px; padding: 20px; + background-color: #edf2f7; border-radius: 5px; text-align: center; + font-size: 14px; color: #718096; } .endorsement-item { background-color: + #f7fafc; padding: 15px; margin: 10px 0; border-left: 3px solid #2c5282; + border-radius: 3px; }
Reference: {{submissionId}}