diff --git a/app/client/src/features/inspections/ApiaryInspectionDetailsEdit.jsx b/app/client/src/features/inspections/ApiaryInspectionDetailsEdit.jsx
index 7f29b30..7600607 100644
--- a/app/client/src/features/inspections/ApiaryInspectionDetailsEdit.jsx
+++ b/app/client/src/features/inspections/ApiaryInspectionDetailsEdit.jsx
@@ -10,7 +10,6 @@ export default function ApiaryInspectionDetailsEdit({
initialValues,
site,
}) {
- console.log("ApiaryInspectionDetailsEdit");
const {
setValue,
register,
diff --git a/app/client/src/features/inspections/CreateInspectionPage.jsx b/app/client/src/features/inspections/CreateInspectionPage.jsx
index 6599821..68e6258 100644
--- a/app/client/src/features/inspections/CreateInspectionPage.jsx
+++ b/app/client/src/features/inspections/CreateInspectionPage.jsx
@@ -137,8 +137,6 @@ export default function CreateInspectionPage() {
const submissionLabel = submitting ? "Submitting..." : "Create";
- console.log(inspection.status);
-
if (inspection.status === REQUEST_STATUS.FULFILLED) {
return ;
}
diff --git a/app/client/src/features/inspections/InspectionDetailsViewEdit.jsx b/app/client/src/features/inspections/InspectionDetailsViewEdit.jsx
index b487fae..cbc0918 100644
--- a/app/client/src/features/inspections/InspectionDetailsViewEdit.jsx
+++ b/app/client/src/features/inspections/InspectionDetailsViewEdit.jsx
@@ -35,7 +35,6 @@ export default function InspectionDetailsViewEdit({
site,
licence,
}) {
- console.log("InspectionDetailsViewEdit");
const { status, error, mode } = inspection;
const dispatch = useDispatch();
diff --git a/app/client/src/features/reports/ReportLicenceComments.jsx b/app/client/src/features/reports/ReportLicenceComments.jsx
new file mode 100644
index 0000000..2837f6d
--- /dev/null
+++ b/app/client/src/features/reports/ReportLicenceComments.jsx
@@ -0,0 +1,83 @@
+import React, { useEffect } from "react";
+import { useForm } from "react-hook-form";
+import { useSelector, useDispatch } from "react-redux";
+import { Row, Col, Form, Button } from "react-bootstrap";
+
+import DocGenDownloadBar from "../../components/DocGenDownloadBar";
+
+import {
+ generateReport,
+ fetchReportJob,
+ selectReportsJob,
+ completeReportJob,
+ startLicenceCommentsJob,
+} from "./reportsSlice";
+
+import { REPORTS } from "../../utilities/constants";
+
+export default function ReportLicenceComments() {
+ const dispatch = useDispatch();
+
+ const job = useSelector(selectReportsJob);
+ const { pendingDocuments } = job;
+
+ const form = useForm({
+ reValidateMode: "onBlur",
+ });
+ const { register, watch } = form;
+
+ const watchLicenceNumber = watch("licenceNumber", null);
+
+ useEffect(() => {
+ if (job.id && job.type === REPORTS.LICENCE_COMMENTS) {
+ dispatch(fetchReportJob());
+
+ if (pendingDocuments?.length > 0) {
+ dispatch(generateReport(pendingDocuments[0].documentId));
+ } else {
+ dispatch(completeReportJob(job.id));
+ }
+ }
+ }, [pendingDocuments]); // eslint-disable-line react-hooks/exhaustive-deps
+
+ const onGenerateReport = () => {
+ dispatch(
+ startLicenceCommentsJob({
+ licenceNumber: watchLicenceNumber,
+ })
+ );
+ };
+
+ return (
+ <>
+
+
+ Licence Number
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
+
+ReportLicenceComments.propTypes = {};
diff --git a/app/client/src/features/reports/Reports.jsx b/app/client/src/features/reports/Reports.jsx
index e810b1b..75ae28d 100644
--- a/app/client/src/features/reports/Reports.jsx
+++ b/app/client/src/features/reports/Reports.jsx
@@ -23,6 +23,7 @@ import ReportLicenceExpiry from "./ReportLicenceExpiry";
import { clearReportsJob } from "./reportsSlice";
import RenderOnRole from "../../components/RenderOnRole";
import ReportDairyTrailerInspection from "./ReportDairyTrailerInspection";
+import ReportLicenceComments from "./ReportLicenceComments";
export default function Reports() {
const dispatch = useDispatch();
@@ -70,6 +71,9 @@ export default function Reports() {
case REPORTS.DAIRY_TEST_THRESHOLD:
control = ;
break;
+ case REPORTS.LICENCE_COMMENTS:
+ control = ;
+ break;
case REPORTS.LICENCE_LOCATION:
control = ;
break;
@@ -193,6 +197,18 @@ export default function Reports() {
+
+
+
+
{
+ try {
+ const response = await Api.post(
+ `documents/reports/startJob/licenceComments`,
+ payload
+ );
+ return response.data;
+ } catch (error) {
+ if (error instanceof ApiError) {
+ return thunkApi.rejectWithValue(error.serialize());
+ }
+ return thunkApi.rejectWithValue({ code: -1, description: error.message });
+ }
+ }
+);
+
export const startLicenceExpiryJob = createAsyncThunk(
"reports/startLicenceExpiryJob",
async (payload, thunkApi) => {
@@ -379,6 +397,9 @@ export const reportsSlice = createSlice({
[startLicenceExpiryJob.pending]: pendingStartJobReducer,
[startLicenceExpiryJob.fulfilled]: fulfilledStartJobReducer,
[startLicenceExpiryJob.rejected]: rejectionStartJobReducer,
+ [startLicenceCommentsJob.pending]: pendingStartJobReducer,
+ [startLicenceCommentsJob.fulfilled]: fulfilledStartJobReducer,
+ [startLicenceCommentsJob.rejected]: rejectionStartJobReducer,
[fetchReportJob.pending]: (state) => {
state.job.status = REQUEST_STATUS.PENDING;
diff --git a/app/client/src/features/trailerinspections/CreateTrailerInspectionPage.jsx b/app/client/src/features/trailerinspections/CreateTrailerInspectionPage.jsx
index 26880ae..12af31e 100644
--- a/app/client/src/features/trailerinspections/CreateTrailerInspectionPage.jsx
+++ b/app/client/src/features/trailerinspections/CreateTrailerInspectionPage.jsx
@@ -33,7 +33,6 @@ function submissionController(
clearErrors,
dispatch
) {
- console.log("CreateTrailerInspectionPage");
const onSubmit = async (data) => {
switch (licence.data.licenceTypeId) {
case LicenceTypeConstants.LICENCE_TYPE_ID_DAIRY_TANK_TRUCK: {
@@ -109,7 +108,6 @@ export default function CreateTrailerInspectionPage() {
const submissionLabel = submitting ? "Submitting..." : "Create";
- console.log(inspection);
if (inspection.status === REQUEST_STATUS.FULFILLED) {
return ;
}
diff --git a/app/client/src/features/trailerinspections/TrailerInspectionDetailsEdit.jsx b/app/client/src/features/trailerinspections/TrailerInspectionDetailsEdit.jsx
index ecc6712..0f8668a 100644
--- a/app/client/src/features/trailerinspections/TrailerInspectionDetailsEdit.jsx
+++ b/app/client/src/features/trailerinspections/TrailerInspectionDetailsEdit.jsx
@@ -10,7 +10,6 @@ export default function TrailerInspectionDetailsEdit({
initialValues,
trailer,
}) {
- console.log("TrailerInspectionDetailsEdit");
const {
setValue,
register,
diff --git a/app/client/src/utilities/constants.js b/app/client/src/utilities/constants.js
index 087078c..95cd2ea 100644
--- a/app/client/src/utilities/constants.js
+++ b/app/client/src/utilities/constants.js
@@ -150,6 +150,7 @@ export const REPORTS = {
DAIRY_FARM_QUALITY: "DAIRY_FARM_QUALITY",
DAIRY_FARM_TANK: "DAIRY_FARM_TANK",
DAIRY_TEST_THRESHOLD: "DAIRY_TEST_THRESHOLD",
+ LICENCE_COMMENTS: "LICENCE_COMMENTS",
LICENCE_LOCATION: "LICENCE_LOCATION",
LICENCE_EXPIRY: "LICENCE_EXPIRY",
DAIRY_TRAILER_INSPECTION: "TRAILER INSPECTION",
diff --git a/app/server/routes/v1/documents.js b/app/server/routes/v1/documents.js
index 84bb8ed..9c82240 100644
--- a/app/server/routes/v1/documents.js
+++ b/app/server/routes/v1/documents.js
@@ -955,6 +955,21 @@ async function startLicenceTypeLocationJob(licenceTypeId) {
return { jobId, documents };
}
+async function startLicenceCommentsJob(licenceNumber) {
+ const [procedureResult] = await prisma.$transaction([
+ prisma.$queryRawUnsafe(
+ `CALL mals_app.pr_generate_print_json_licence_comments('${licenceNumber}', NULL)`,
+ licenceNumber
+ ),
+ ]);
+
+ const jobId = procedureResult[0].iop_print_job_id;
+
+ const documents = await getPendingDocuments(jobId);
+
+ return { jobId, documents };
+}
+
async function startLicenceExpiryJob(startDate, endDate) {
const [procedureResult] = await prisma.$transaction([
prisma.$queryRawUnsafe(
@@ -1462,6 +1477,17 @@ router.post("/reports/startJob/licenceTypeLocation", async (req, res, next) => {
.finally(async () => prisma.$disconnect());
});
+router.post("/reports/startJob/licenceComments", async (req, res, next) => {
+ const licenceNumber = req.body.licenceNumber;
+
+ await startLicenceCommentsJob(licenceNumber)
+ .then(({ jobId, documents }) => {
+ return res.send({ jobId, documents, type: REPORTS.LICENCE_COMMENTS });
+ })
+ .catch(next)
+ .finally(async () => prisma.$disconnect());
+});
+
router.post("/reports/startJob/licenceExpiry", async (req, res, next) => {
const startDate = formatDate(new Date(req.body.startDate));
const endDate = formatDate(new Date(req.body.endDate));
@@ -1543,7 +1569,17 @@ router.post("/download/:jobId(\\d+)", async (req, res, next) => {
const zip = new AdmZip();
let fileName = null;
documents.forEach((document) => {
- if (job.printCategory === constants.DOCUMENT_TYPE_REPORT) {
+ if (
+ job.printCategory === constants.DOCUMENT_TYPE_REPORT &&
+ document.document_type === constants.REPORTS.LICENCE_COMMENTS
+ ) {
+ fileName = `${document.document_json.Licence_Number}-${document.document_type}.xlsx`;
+ } else if (
+ job.printCategory === constants.DOCUMENT_TYPE_REPORT &&
+ document.document_type === constants.REPORTS.DAIRY_TRAILER_INSPECTION
+ ) {
+ fileName = `${document.document_json.LicenceNumber}-${document.document_type}.xlsx`;
+ } else if (job.printCategory === constants.DOCUMENT_TYPE_REPORT) {
fileName = `${document.document_json.Licence_Type}-${document.document_type}.xlsx`;
} else if (
document.document_type === constants.DOCUMENT_TYPE_DAIRY_INFRACTION
@@ -1552,7 +1588,6 @@ router.post("/download/:jobId(\\d+)", async (req, res, next) => {
} else {
fileName = `${document.licence_number}-${document.document_type}.docx`;
}
-
zip.addFile(fileName, document.document_binary);
});
diff --git a/app/server/routes/v1/inspections.js b/app/server/routes/v1/inspections.js
index ea9967e..d636450 100644
--- a/app/server/routes/v1/inspections.js
+++ b/app/server/routes/v1/inspections.js
@@ -144,7 +144,6 @@ router.get("/trailer/:inspectionId(\\d+)", async (req, res, next) => {
});
router.post("/trailer", async (req, res, next) => {
- console.log("create trailer route");
const now = new Date();
const payload = inspection.convertTrailerInspectionToPhysicalModel(
diff --git a/app/server/static/templates/certificates/Dairy-Farm.docx b/app/server/static/templates/certificates/Dairy-Farm.docx
index 4883b6e..7146f16 100644
Binary files a/app/server/static/templates/certificates/Dairy-Farm.docx and b/app/server/static/templates/certificates/Dairy-Farm.docx differ
diff --git a/app/server/static/templates/reports/Dairy_Test_Threshold_Template.xlsx b/app/server/static/templates/reports/Dairy_Test_Threshold_Template.xlsx
index 96a92db..78ee28a 100644
Binary files a/app/server/static/templates/reports/Dairy_Test_Threshold_Template.xlsx and b/app/server/static/templates/reports/Dairy_Test_Threshold_Template.xlsx differ
diff --git a/app/server/static/templates/reports/Licence_Comments_Template.xlsx b/app/server/static/templates/reports/Licence_Comments_Template.xlsx
new file mode 100644
index 0000000..823dcb6
Binary files /dev/null and b/app/server/static/templates/reports/Licence_Comments_Template.xlsx differ
diff --git a/app/server/utilities/constants.js b/app/server/utilities/constants.js
index bac122b..bc0deab 100644
--- a/app/server/utilities/constants.js
+++ b/app/server/utilities/constants.js
@@ -102,5 +102,6 @@ module.exports = Object.freeze({
DAIRY_TRAILER_INSPECTION: "TRAILER INSPECTION",
LICENCE_LOCATION: "LICENCE_LOCATION",
LICENCE_EXPIRY: "LICENCE_EXPIRY",
+ LICENCE_COMMENTS: "LICENCE_COMMENTS",
},
});
diff --git a/app/server/utilities/documents.js b/app/server/utilities/documents.js
index df8d6e4..b09e3e8 100644
--- a/app/server/utilities/documents.js
+++ b/app/server/utilities/documents.js
@@ -196,6 +196,8 @@ function getReportsTemplateName(documentType) {
return "Licence_Expiry_Species_NoSpecies_Template";
case constants.REPORTS.DAIRY_TRAILER_INSPECTION:
return "Dairy_Trailer_Inspection_Template";
+ case constants.REPORTS.LICENCE_COMMENTS:
+ return "Licence_Comments_Template";
default:
return null;
}
diff --git a/spilo-db/db-scripts/releases/release_5.5_ddl.sql b/spilo-db/db-scripts/releases/release_5.5_ddl.sql
new file mode 100644
index 0000000..ab6fcf7
--- /dev/null
+++ b/spilo-db/db-scripts/releases/release_5.5_ddl.sql
@@ -0,0 +1,117 @@
+-- MALS-17 - New report - to show comments by license number and or IRMA number
+-- Create a view and procedure to support Comments reporting.
+
+DROP PROCEDURE IF EXISTS mals_app.pr_generate_print_json_licence_comments;
+DROP VIEW IF EXISTS mals_app.mal_licence_comment_vw;
+
+--
+-- VIEW: MAL_LICENCE_COMMENT_VW
+--
+
+CREATE OR REPLACE VIEW mals_app.mal_licence_comment_vw
+AS SELECT lic.id AS licence_id,
+ lic.licence_number,
+ lic.irma_number,
+ reg.last_name,
+ reg.first_name,
+ lic.company_name,
+ reg.email_address,
+ lictyp.licence_type,
+ com.create_timestamp,
+ com.licence_comment
+ FROM mals_app.mal_licence lic
+ JOIN mals_app.mal_licence_type_lu lictyp ON lic.licence_type_id = lictyp.id
+ LEFT JOIN mals_app.mal_registrant reg ON lic.primary_registrant_id = reg.id
+ LEFT JOIN mals_app.mal_licence_comment com ON lic.id = com.licence_id;
+
+-- Permissions
+
+ALTER TABLE mals_app.mal_licence_comment_vw OWNER TO mals;
+GRANT ALL ON TABLE mals_app.mal_licence_comment_vw TO mals;
+GRANT SELECT ON TABLE mals_app.mal_licence_comment_vw TO mals_app_role;
+
+--
+-- PROCEDURE: PR_GENERATE_PRINT_JSON_LICENCE_COMMENTS
+--
+
+CREATE OR REPLACE PROCEDURE mals_app.pr_generate_print_json_licence_comments(IN ip_licence_number character varying, INOUT iop_print_job_id integer)
+ LANGUAGE plpgsql
+AS $procedure$
+ declare
+ l_report_json_count integer default 0;
+ begin
+ --
+ -- Start a row in the mal_print_job table
+ call pr_start_print_job(
+ ip_print_category => 'REPORT',
+ iop_print_job_id => iop_print_job_id
+ );
+ --
+ -- Insert the JSON into the output table
+ with licence_comments as (
+ select
+ lic.licence_number,
+ lic.licence_type,
+ json_agg(json_build_object('LicenceNumber', lic.licence_number,
+ 'Lastname', lic.last_name,
+ 'Firstname', lic.first_name,
+ 'Company', lic.company_name,
+ 'Email', lic.email_address,
+ 'LicenceType', lic.licence_type,
+ 'CommentDate', lic.create_timestamp,
+ 'Comment', lic.licence_comment)
+ order by lic.create_timestamp) licence_json,
+ count(*) num_rows
+ from mal_licence_comment_vw lic
+ WHERE (lic.irma_number = ip_licence_number) OR (CAST(lic.licence_number AS varchar) = ip_licence_number)
+ group by lic.licence_number, lic.licence_type
+ )
+ --
+ -- MAIN QUERY
+ --
+ insert into mal_print_job_output(
+ print_job_id,
+ licence_type,
+ licence_number,
+ document_type,
+ document_json,
+ document_binary,
+ create_userid,
+ create_timestamp,
+ update_userid,
+ update_timestamp)
+ select
+ iop_print_job_id,
+ licence_type,
+ null,
+ 'LICENCE_COMMENTS',
+ json_build_object('DateTime', to_char(current_timestamp, 'fmyyyy-mm-dd hh24mi'),
+ 'Licence_Number', licence_number,
+ 'Licence', licence_json,
+ 'RowCount', num_rows) report_json,
+ null,
+ current_user,
+ current_timestamp,
+ current_user,
+ current_timestamp
+ from licence_comments;
+ --
+ GET DIAGNOSTICS l_report_json_count = ROW_COUNT;
+ --
+ -- Update the Print Job table.
+ update mal_print_job set
+ job_status = 'COMPLETE',
+ json_end_time = current_timestamp,
+ report_json_count = l_report_json_count,
+ update_userid = current_user,
+ update_timestamp = current_timestamp
+ where id = iop_print_job_id;
+end;
+$procedure$
+;
+
+-- Permissions
+
+ALTER PROCEDURE mals_app.pr_generate_print_json_licence_comments(in varchar, inout int4) OWNER TO mals;
+GRANT ALL ON PROCEDURE mals_app.pr_generate_print_json_licence_comments(in varchar, inout int4) TO mals;
+GRANT EXECUTE ON PROCEDURE mals_app.pr_generate_print_json_licence_comments(in varchar, inout int4) TO mals_app_role;
\ No newline at end of file