[TOB-192,168,140] feat: v0.3.0 Integrate contacts Commit contains all backend tasks for the third sprint. The focus of sprint 3 was to: - integrate the contact module into the statement public affairs backend module - add a role concept chapter to the architecture documentation - streamline sonarcube code quality configuration with the QS Details: [TOB-140, TOB-193] Documentation - Role concept - added role concept chapter in architecture documentation - increment module backend version [TOB-140, TOB-193] Documentation - Role concept - added role concept chapter in architecture documentation - added initial version of howtoBuild document - added initial version of howtoRun document - added initial version of the userGuide document [TOB-204] feat: ContactService - Fix some sonar bugs and code smell [TOB-204] test: testcases ContactService - add additional testcases for ContactService [TOB-204] test: testcases ContactService - add testcase for ContactService [TOB-204] add contactDatabaseApi - added contactdatabase api and response models - added ContactService and contact models - added debugController ContactsController [TOB-194] chor: Added application-dev.yml - added application config for devenvironment. [TOB-194] chor: logger config - added logger configuration [TOB-193] feat: Add process api documentation - Updated openapi.yaml. Added process REST interfaces to - list current tasks for statement - claim specific task - unclaim specific task - complete specific task [TOB-194] test: Fix Sonar code smells add tests - create additional testcases for StatementOverviewService - create additional testcases for StatementProcessService - reduce complexity of ServiceTypeProcess logic in StatenmebtProcessService [TOB-196] fix: Sonar code smells - fixed lambda code smells [TOB-196] fix: Sonar code smells - fixed private constructor - removed empyt Test class - fixed duplicates - fixed lambda code smells [TOB-196] fix: Sonar bugs and code smells - fixed sonar bugs - fixed lambda code smells [TOB-194] feat: test coverage WorkflowService - added test cases for WorkflowService methods. - read tenantId in WorkflowService from application.yml [TOB-204] feat: adapter contact api - added ContactDatabaseApi rest client adapter - added api response model classes [TOB-121] chor: Streamline testconfig with QS - setup sonar-project.properties - set correct sonar version in pom.xml - cleanup application.yml and add application-test.yml - set test profile in test classes Signed-off-by: Tobias Stummer <stummer@develop-group.de>
diff --git a/deploy/camunda/Stellungnahme.bpmn b/deploy/camunda/Stellungnahme.bpmn index 6e3c879..5df169c 100644 --- a/deploy/camunda/Stellungnahme.bpmn +++ b/deploy/camunda/Stellungnahme.bpmn
@@ -6,31 +6,26 @@ <bpmn:process id="statement_p" name="Statement" isExecutable="true"> <bpmn:laneSet id="LaneSet_0jxdwfn"> <bpmn:lane id="Lane_0spmnb6" name="Genehmiger"> - <bpmn:flowNodeRef>t_genehmigen_zust</bpmn:flowNodeRef> - <bpmn:flowNodeRef>Gateway_0lqi8ef</bpmn:flowNodeRef> + <bpmn:flowNodeRef>Gateway_1wxwe5e</bpmn:flowNodeRef> + <bpmn:flowNodeRef>approveStatement</bpmn:flowNodeRef> <bpmn:flowNodeRef>Gateway_0t8k8x7</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_genehmigung_stellungnahme</bpmn:flowNodeRef> </bpmn:lane> <bpmn:lane id="Lane_0gjug73" name="Sachbearbeiter"> <bpmn:flowNodeRef>Gateway_1qr83rr</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_ablehnung_durchfuehren</bpmn:flowNodeRef> - <bpmn:flowNodeRef>e_not_responsible</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_erstelluing_workflowdata</bpmn:flowNodeRef> - <bpmn:flowNodeRef>Gateway_127jq7b</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_ergaenzen_infodaten</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_erstellung_entwurf</bpmn:flowNodeRef> - <bpmn:flowNodeRef>Gateway_1doisb4</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_pruefung_vollstaendigkeit</bpmn:flowNodeRef> - <bpmn:flowNodeRef>Activity_1yuntdb</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_send_statement</bpmn:flowNodeRef> - <bpmn:flowNodeRef>Gateway_150w9po</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_anlegen</bpmn:flowNodeRef> - <bpmn:flowNodeRef>s_anlegen_manuell</bpmn:flowNodeRef> + <bpmn:flowNodeRef>addBasicInfoData</bpmn:flowNodeRef> + <bpmn:flowNodeRef>sendStatement</bpmn:flowNodeRef> <bpmn:flowNodeRef>e_erfolgreicher_abschluss</bpmn:flowNodeRef> + <bpmn:flowNodeRef>Gateway_0i8uj9a</bpmn:flowNodeRef> + <bpmn:flowNodeRef>addWorkflowData</bpmn:flowNodeRef> + <bpmn:flowNodeRef>createDraft</bpmn:flowNodeRef> + <bpmn:flowNodeRef>checkForCompleteness</bpmn:flowNodeRef> + <bpmn:flowNodeRef>Gateway_1doisb4</bpmn:flowNodeRef> + <bpmn:flowNodeRef>finalizeStatement</bpmn:flowNodeRef> + <bpmn:flowNodeRef>s_anlegen_manuell</bpmn:flowNodeRef> </bpmn:lane> - <bpmn:lane id="Lane_0hux5z5" name="SB und FB"> + <bpmn:lane id="Lane_078yf14" name="FB und SB"> <bpmn:flowNodeRef>Gateway_1vm0oko</bpmn:flowNodeRef> - <bpmn:flowNodeRef>t_anreichern_fb_results</bpmn:flowNodeRef> + <bpmn:flowNodeRef>enrichDraft</bpmn:flowNodeRef> </bpmn:lane> </bpmn:laneSet> <bpmn:exclusiveGateway id="Gateway_1qr83rr" name="Zuständig?"> @@ -38,40 +33,7 @@ <bpmn:outgoing>Flow_0nwawsv</bpmn:outgoing> <bpmn:outgoing>Flow_017kj0u</bpmn:outgoing> </bpmn:exclusiveGateway> - <bpmn:userTask id="t_genehmigen_zust" name="Genehmigen Ablehnung der Zuständigkeit" camunda:formKey="variables"> - <bpmn:extensionElements> - <camunda:formData> - <camunda:formField id="_rejectapproved" label="RejectApproved" type="boolean" /> - </camunda:formData> - <camunda:inputOutput> - <camunda:outputParameter name="rejectapproved">${rejectapproved}</camunda:outputParameter> - </camunda:inputOutput> - </bpmn:extensionElements> - <bpmn:incoming>Flow_017kj0u</bpmn:incoming> - <bpmn:outgoing>Flow_0wq62kf</bpmn:outgoing> - </bpmn:userTask> - <bpmn:userTask id="t_ablehnung_durchfuehren" name="Erstellen und Versenden der Negativmeldung"> - <bpmn:incoming>Flow_02s8ix9</bpmn:incoming> - <bpmn:outgoing>Flow_123dp6r</bpmn:outgoing> - </bpmn:userTask> - <bpmn:endEvent id="e_not_responsible" name="Ende nicht Zuständig"> - <bpmn:incoming>Flow_123dp6r</bpmn:incoming> - </bpmn:endEvent> - <bpmn:userTask id="t_erstelluing_workflowdata" name="Aufbereiten der Daten und Erstellen des Workflowdatensatz"> - <bpmn:incoming>Flow_0vg1k1c</bpmn:incoming> - <bpmn:outgoing>Flow_1hqe1j8</bpmn:outgoing> - </bpmn:userTask> - <bpmn:exclusiveGateway id="Gateway_0lqi8ef" name="Ablehnung genehmigt?"> - <bpmn:incoming>Flow_0wq62kf</bpmn:incoming> - <bpmn:outgoing>Flow_02s8ix9</bpmn:outgoing> - <bpmn:outgoing>Flow_1q09bdk</bpmn:outgoing> - </bpmn:exclusiveGateway> - <bpmn:exclusiveGateway id="Gateway_127jq7b"> - <bpmn:incoming>Flow_0nwawsv</bpmn:incoming> - <bpmn:incoming>Flow_1q09bdk</bpmn:incoming> - <bpmn:outgoing>Flow_0vg1k1c</bpmn:outgoing> - </bpmn:exclusiveGateway> - <bpmn:userTask id="t_ergaenzen_infodaten" name="Ergänzen Infodatensatz und Entscheiden Zuständigkeit" camunda:formKey="variables"> + <bpmn:userTask id="addBasicInfoData" name="Ergänzen Infodatensatz und Entscheiden Zuständigkeit" camunda:formKey="variables"> <bpmn:extensionElements> <camunda:formData> <camunda:formField id="_responsible" label="Responsible" type="boolean" /> @@ -80,58 +42,27 @@ <camunda:outputParameter name="responsible">${responsible}</camunda:outputParameter> </camunda:inputOutput> </bpmn:extensionElements> - <bpmn:incoming>Flow_1wkiruw</bpmn:incoming> + <bpmn:incoming>Flow_0oigd8l</bpmn:incoming> <bpmn:outgoing>Flow_167ttld</bpmn:outgoing> </bpmn:userTask> - <bpmn:userTask id="t_erstellung_entwurf" name="Erstellen Entwurf Stellungnahme"> - <bpmn:incoming>Flow_1hqe1j8</bpmn:incoming> - <bpmn:outgoing>Flow_0rrgglo</bpmn:outgoing> - </bpmn:userTask> - <bpmn:exclusiveGateway id="Gateway_1doisb4" name="Alle Informationen vollständig?"> - <bpmn:incoming>Flow_1tmr5qp</bpmn:incoming> - <bpmn:outgoing>Flow_10zb14i</bpmn:outgoing> - <bpmn:outgoing>Flow_12g2bxr</bpmn:outgoing> - </bpmn:exclusiveGateway> - <bpmn:exclusiveGateway id="Gateway_1vm0oko"> - <bpmn:incoming>Flow_0rrgglo</bpmn:incoming> - <bpmn:incoming>Flow_10zb14i</bpmn:incoming> - <bpmn:outgoing>Flow_1qahwu7</bpmn:outgoing> - </bpmn:exclusiveGateway> - <bpmn:userTask id="t_pruefung_vollstaendigkeit" name="Prüfen auf Vollständigkeit und Plausibilität" camunda:formKey="variables"> - <bpmn:extensionElements> - <camunda:formData> - <camunda:formField id="_data_complete" label="Data Complete" type="boolean" /> - </camunda:formData> - <camunda:inputOutput> - <camunda:outputParameter name="data_complete">${data_complete}</camunda:outputParameter> - </camunda:inputOutput> - </bpmn:extensionElements> - <bpmn:incoming>Flow_18v38ei</bpmn:incoming> - <bpmn:outgoing>Flow_1tmr5qp</bpmn:outgoing> - </bpmn:userTask> - <bpmn:userTask id="t_anreichern_fb_results" name="Anreichern durch die Fachbereiche"> - <bpmn:incoming>Flow_1qahwu7</bpmn:incoming> - <bpmn:outgoing>Flow_0r3c12h</bpmn:outgoing> - </bpmn:userTask> - <bpmn:userTask id="Activity_1yuntdb" name="Fertigstellen der Stellungnahme"> - <bpmn:incoming>Flow_12g2bxr</bpmn:incoming> - <bpmn:outgoing>Flow_006vhwy</bpmn:outgoing> - </bpmn:userTask> - <bpmn:exclusiveGateway id="Gateway_0t8k8x7" name="Genehmigung?"> - <bpmn:incoming>Flow_12c0wj3</bpmn:incoming> - <bpmn:outgoing>Flow_00qgmxu</bpmn:outgoing> - <bpmn:outgoing>Flow_1k89j3h</bpmn:outgoing> - </bpmn:exclusiveGateway> - <bpmn:userTask id="t_send_statement" name="Versenden der Stellungnahme"> + <bpmn:userTask id="sendStatement" name="Versenden der Antwort"> <bpmn:incoming>Flow_00qgmxu</bpmn:incoming> <bpmn:outgoing>Flow_0279yx1</bpmn:outgoing> </bpmn:userTask> - <bpmn:exclusiveGateway id="Gateway_150w9po"> + <bpmn:endEvent id="e_erfolgreicher_abschluss" name="Ende Stellungnahme"> + <bpmn:incoming>Flow_0279yx1</bpmn:incoming> + </bpmn:endEvent> + <bpmn:exclusiveGateway id="Gateway_0i8uj9a"> <bpmn:incoming>Flow_1k89j3h</bpmn:incoming> - <bpmn:incoming>Flow_0r3c12h</bpmn:incoming> - <bpmn:outgoing>Flow_18v38ei</bpmn:outgoing> + <bpmn:incoming>Flow_1uni785</bpmn:incoming> + <bpmn:outgoing>Flow_0oigd8l</bpmn:outgoing> </bpmn:exclusiveGateway> - <bpmn:userTask id="t_genehmigung_stellungnahme" name="Prüfen und Genehmigen der Stellungnahme" camunda:formKey="variables"> + <bpmn:exclusiveGateway id="Gateway_1wxwe5e"> + <bpmn:incoming>Flow_017kj0u</bpmn:incoming> + <bpmn:incoming>Flow_006vhwy</bpmn:incoming> + <bpmn:outgoing>Flow_13ba0uc</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:userTask id="approveStatement" name="Prüfen und Genehmigen der Antwort" camunda:formKey="variables"> <bpmn:extensionElements> <camunda:formData> <camunda:formField id="_approved_statement" label="Approved Statement" type="boolean" /> @@ -140,98 +71,85 @@ <camunda:outputParameter name="approved_statement">${approved_statement}</camunda:outputParameter> </camunda:inputOutput> </bpmn:extensionElements> - <bpmn:incoming>Flow_006vhwy</bpmn:incoming> + <bpmn:incoming>Flow_13ba0uc</bpmn:incoming> <bpmn:outgoing>Flow_12c0wj3</bpmn:outgoing> </bpmn:userTask> - <bpmn:userTask id="t_anlegen" name="Anlegen Stellungnahme" camunda:formKey="variables"> - <bpmn:extensionElements> - <camunda:inputOutput> - <camunda:outputParameter name="rejectrequest">${rejectrequest}</camunda:outputParameter> - </camunda:inputOutput> - <camunda:formData> - <camunda:formField id="_rejectrequest" label="RejectRequest" type="boolean" /> - </camunda:formData> - </bpmn:extensionElements> - <bpmn:incoming>Flow_1uni785</bpmn:incoming> - <bpmn:outgoing>Flow_1wkiruw</bpmn:outgoing> + <bpmn:exclusiveGateway id="Gateway_0t8k8x7" name="Genehmigung?"> + <bpmn:incoming>Flow_12c0wj3</bpmn:incoming> + <bpmn:outgoing>Flow_00qgmxu</bpmn:outgoing> + <bpmn:outgoing>Flow_1k89j3h</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:userTask id="addWorkflowData" name="Aufbereiten der Daten und Erstellen des Workflowdatensatz"> + <bpmn:incoming>Flow_0nwawsv</bpmn:incoming> + <bpmn:outgoing>Flow_1hqe1j8</bpmn:outgoing> </bpmn:userTask> - <bpmn:startEvent id="s_anlegen_manuell"> - <bpmn:outgoing>Flow_1uni785</bpmn:outgoing> - </bpmn:startEvent> - <bpmn:endEvent id="e_erfolgreicher_abschluss" name="Ende erfolgreiche Stellungnahme"> - <bpmn:incoming>Flow_0279yx1</bpmn:incoming> - </bpmn:endEvent> - <bpmn:sequenceFlow id="Flow_1q09bdk" name="nicht genehmigt" sourceRef="Gateway_0lqi8ef" targetRef="Gateway_127jq7b"> - <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${rejectapproved == false}</bpmn:conditionExpression> - </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_123dp6r" sourceRef="t_ablehnung_durchfuehren" targetRef="e_not_responsible" /> - <bpmn:sequenceFlow id="Flow_0wq62kf" sourceRef="t_genehmigen_zust" targetRef="Gateway_0lqi8ef" /> - <bpmn:sequenceFlow id="Flow_02s8ix9" name="genehmigt" sourceRef="Gateway_0lqi8ef" targetRef="t_ablehnung_durchfuehren"> - <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${rejectapproved == true}</bpmn:conditionExpression> - </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_017kj0u" name="nicht zuständig" sourceRef="Gateway_1qr83rr" targetRef="t_genehmigen_zust"> + <bpmn:userTask id="createDraft" name="Erstellen Entwurf Stellungnahme"> + <bpmn:incoming>Flow_1hqe1j8</bpmn:incoming> + <bpmn:outgoing>Flow_0rrgglo</bpmn:outgoing> + </bpmn:userTask> + <bpmn:exclusiveGateway id="Gateway_1vm0oko"> + <bpmn:incoming>Flow_0rrgglo</bpmn:incoming> + <bpmn:incoming>Flow_10zb14i</bpmn:incoming> + <bpmn:outgoing>Flow_0nt1wtg</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:userTask id="enrichDraft" name="Anreichern durch die Fachbereiche"> + <bpmn:incoming>Flow_0nt1wtg</bpmn:incoming> + <bpmn:outgoing>Flow_0r3c12h</bpmn:outgoing> + </bpmn:userTask> + <bpmn:userTask id="checkForCompleteness" name="Prüfen auf Vollständigkeit und Plausibilität" camunda:formKey="variables"> + <bpmn:extensionElements> + <camunda:formData> + <camunda:formField id="_data_complete" label="Data Complete" type="boolean" /> + </camunda:formData> + <camunda:inputOutput> + <camunda:outputParameter name="data_complete">${data_complete}</camunda:outputParameter> + </camunda:inputOutput> + </bpmn:extensionElements> + <bpmn:incoming>Flow_0r3c12h</bpmn:incoming> + <bpmn:outgoing>Flow_1tmr5qp</bpmn:outgoing> + </bpmn:userTask> + <bpmn:exclusiveGateway id="Gateway_1doisb4" name="Alle Informationen vollständig?"> + <bpmn:incoming>Flow_1tmr5qp</bpmn:incoming> + <bpmn:outgoing>Flow_10zb14i</bpmn:outgoing> + <bpmn:outgoing>Flow_12g2bxr</bpmn:outgoing> + </bpmn:exclusiveGateway> + <bpmn:userTask id="finalizeStatement" name="Fertigstellen der Stellungnahme"> + <bpmn:incoming>Flow_12g2bxr</bpmn:incoming> + <bpmn:outgoing>Flow_006vhwy</bpmn:outgoing> + </bpmn:userTask> + <bpmn:sequenceFlow id="Flow_017kj0u" name="nicht zuständig" sourceRef="Gateway_1qr83rr" targetRef="Gateway_1wxwe5e"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${responsible == false}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_0nwawsv" name="zuständig" sourceRef="Gateway_1qr83rr" targetRef="Gateway_127jq7b"> + <bpmn:sequenceFlow id="Flow_0nwawsv" name="zuständig" sourceRef="Gateway_1qr83rr" targetRef="addWorkflowData"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${responsible == true}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_1wkiruw" sourceRef="t_anlegen" targetRef="t_ergaenzen_infodaten" /> - <bpmn:sequenceFlow id="Flow_1uni785" sourceRef="s_anlegen_manuell" targetRef="t_anlegen" /> - <bpmn:sequenceFlow id="Flow_167ttld" sourceRef="t_ergaenzen_infodaten" targetRef="Gateway_1qr83rr" /> - <bpmn:sequenceFlow id="Flow_0vg1k1c" sourceRef="Gateway_127jq7b" targetRef="t_erstelluing_workflowdata" /> - <bpmn:sequenceFlow id="Flow_1hqe1j8" sourceRef="t_erstelluing_workflowdata" targetRef="t_erstellung_entwurf" /> - <bpmn:sequenceFlow id="Flow_0rrgglo" sourceRef="t_erstellung_entwurf" targetRef="Gateway_1vm0oko" /> - <bpmn:sequenceFlow id="Flow_0r3c12h" sourceRef="t_anreichern_fb_results" targetRef="Gateway_150w9po" /> - <bpmn:sequenceFlow id="Flow_1qahwu7" sourceRef="Gateway_1vm0oko" targetRef="t_anreichern_fb_results" /> - <bpmn:sequenceFlow id="Flow_1tmr5qp" sourceRef="t_pruefung_vollstaendigkeit" targetRef="Gateway_1doisb4" /> + <bpmn:sequenceFlow id="Flow_1uni785" sourceRef="s_anlegen_manuell" targetRef="Gateway_0i8uj9a" /> + <bpmn:sequenceFlow id="Flow_167ttld" sourceRef="addBasicInfoData" targetRef="Gateway_1qr83rr" /> + <bpmn:sequenceFlow id="Flow_1hqe1j8" sourceRef="addWorkflowData" targetRef="createDraft" /> + <bpmn:sequenceFlow id="Flow_0rrgglo" sourceRef="createDraft" targetRef="Gateway_1vm0oko" /> + <bpmn:sequenceFlow id="Flow_0r3c12h" sourceRef="enrichDraft" targetRef="checkForCompleteness" /> + <bpmn:sequenceFlow id="Flow_1tmr5qp" sourceRef="checkForCompleteness" targetRef="Gateway_1doisb4" /> <bpmn:sequenceFlow id="Flow_10zb14i" name="nicht vollständig" sourceRef="Gateway_1doisb4" targetRef="Gateway_1vm0oko"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${data_complete == false}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_12g2bxr" name="vollständig" sourceRef="Gateway_1doisb4" targetRef="Activity_1yuntdb"> + <bpmn:sequenceFlow id="Flow_12g2bxr" name="vollständig" sourceRef="Gateway_1doisb4" targetRef="finalizeStatement"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${data_complete == true}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_006vhwy" sourceRef="Activity_1yuntdb" targetRef="t_genehmigung_stellungnahme" /> - <bpmn:sequenceFlow id="Flow_12c0wj3" sourceRef="t_genehmigung_stellungnahme" targetRef="Gateway_0t8k8x7" /> - <bpmn:sequenceFlow id="Flow_00qgmxu" name="genehmigt" sourceRef="Gateway_0t8k8x7" targetRef="t_send_statement"> + <bpmn:sequenceFlow id="Flow_006vhwy" sourceRef="finalizeStatement" targetRef="Gateway_1wxwe5e" /> + <bpmn:sequenceFlow id="Flow_12c0wj3" sourceRef="approveStatement" targetRef="Gateway_0t8k8x7" /> + <bpmn:sequenceFlow id="Flow_00qgmxu" name="genehmigt" sourceRef="Gateway_0t8k8x7" targetRef="sendStatement"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approved_statement == true}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_1k89j3h" name="nicht genehmigt" sourceRef="Gateway_0t8k8x7" targetRef="Gateway_150w9po"> + <bpmn:sequenceFlow id="Flow_1k89j3h" name="nicht genehmigt" sourceRef="Gateway_0t8k8x7" targetRef="Gateway_0i8uj9a"> <bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approved_statement == false}</bpmn:conditionExpression> </bpmn:sequenceFlow> - <bpmn:sequenceFlow id="Flow_18v38ei" sourceRef="Gateway_150w9po" targetRef="t_pruefung_vollstaendigkeit" /> - <bpmn:sequenceFlow id="Flow_0279yx1" sourceRef="t_send_statement" targetRef="e_erfolgreicher_abschluss" /> - <bpmn:textAnnotation id="TextAnnotation_0o3acqz"> - <bpmn:text>BearbeitungS: - -outputP: -- ablehnung genehmigt?</bpmn:text> - </bpmn:textAnnotation> - <bpmn:textAnnotation id="TextAnnotation_1579k23"> - <bpmn:text>BearbeitungS: -Ausdruck</bpmn:text> - </bpmn:textAnnotation> - <bpmn:textAnnotation id="TextAnnotation_1cc5hqk"> - <bpmn:text>BearbeitungS: -- Fachbereichs Textbausteine -- Kommentare -- Anhänge</bpmn:text> - </bpmn:textAnnotation> - <bpmn:textAnnotation id="TextAnnotation_0bd2iv0"> - <bpmn:text>BearbeitungS: -- Kommentare -- Textbausteine - -outputP: -- vollständig?</bpmn:text> - </bpmn:textAnnotation> - <bpmn:textAnnotation id="TextAnnotation_0zhm9mr"> - <bpmn:text>BearbeitungS: -- Textbausteine</bpmn:text> - </bpmn:textAnnotation> - <bpmn:textAnnotation id="TextAnnotation_1b3dksb"> - <bpmn:text>BearbeitungS: -- Workflowdaten</bpmn:text> - </bpmn:textAnnotation> + <bpmn:sequenceFlow id="Flow_0279yx1" sourceRef="sendStatement" targetRef="e_erfolgreicher_abschluss" /> + <bpmn:sequenceFlow id="Flow_0oigd8l" sourceRef="Gateway_0i8uj9a" targetRef="addBasicInfoData" /> + <bpmn:sequenceFlow id="Flow_13ba0uc" sourceRef="Gateway_1wxwe5e" targetRef="approveStatement" /> + <bpmn:sequenceFlow id="Flow_0nt1wtg" sourceRef="Gateway_1vm0oko" targetRef="enrichDraft" /> + <bpmn:startEvent id="s_anlegen_manuell"> + <bpmn:outgoing>Flow_1uni785</bpmn:outgoing> + </bpmn:startEvent> <bpmn:textAnnotation id="TextAnnotation_0plj167"> <bpmn:text>BearbeitungS: - Titel @@ -244,346 +162,299 @@ - Negativmeldungstext outputP: -- zuständig?</bpmn:text> +- zuständig? + +id:addBasicInfoData</bpmn:text> </bpmn:textAnnotation> - <bpmn:textAnnotation id="TextAnnotation_1kjvfbn"> + <bpmn:textAnnotation id="TextAnnotation_1b3dksb"> <bpmn:text>BearbeitungS: -- Titel -- EingangsDatum -- Frist -- Ort, Art -- Anhänge -- Kontaktdaten</bpmn:text> +- Workflowdaten +id:addWorkflowData</bpmn:text> + </bpmn:textAnnotation> + <bpmn:textAnnotation id="TextAnnotation_0zhm9mr"> + <bpmn:text>BearbeitungS: +- Textbausteine +id:createDraft</bpmn:text> </bpmn:textAnnotation> <bpmn:textAnnotation id="TextAnnotation_0qa3dz1"> <bpmn:text>BearbeitungS: - Textbausteine - Kommentare -- Erstellen der PDF (implizit durch Taskabschluss)</bpmn:text> +- Erstellen der PDF (implizit durch Taskabschluss) + +ID:finalizeStatement</bpmn:text> </bpmn:textAnnotation> + <bpmn:textAnnotation id="TextAnnotation_0bd2iv0"> + <bpmn:text>BearbeitungS: +- Kommentare +- Textbausteine + +outputP: +- vollständig? +ID:checkForCompleteness</bpmn:text> + </bpmn:textAnnotation> + <bpmn:textAnnotation id="TextAnnotation_1eu0fdf"> + <bpmn:text>BearbeitungS: + Ausdruck + +Automatische persistieren + +ID:sendStatement</bpmn:text> + </bpmn:textAnnotation> + <bpmn:textAnnotation id="TextAnnotation_1cc5hqk"> + <bpmn:text>BearbeitungS: +- Fachbereichs Textbausteine +- Kommentare +- Anhänge +id: enrichDraft</bpmn:text> + </bpmn:textAnnotation> + <bpmn:association id="Association_1tkrwj3" sourceRef="addBasicInfoData" targetRef="TextAnnotation_0plj167" /> + <bpmn:association id="Association_14n2c6r" sourceRef="addWorkflowData" targetRef="TextAnnotation_1b3dksb" /> + <bpmn:association id="Association_1mp1cmg" sourceRef="createDraft" targetRef="TextAnnotation_0zhm9mr" /> + <bpmn:association id="Association_16bhqiy" sourceRef="finalizeStatement" targetRef="TextAnnotation_0qa3dz1" /> + <bpmn:association id="Association_0yk28uv" sourceRef="checkForCompleteness" targetRef="TextAnnotation_0bd2iv0" /> + <bpmn:association id="Association_1o329sx" sourceRef="sendStatement" targetRef="TextAnnotation_1eu0fdf" /> + <bpmn:association id="Association_16e69cr" sourceRef="enrichDraft" targetRef="TextAnnotation_1cc5hqk" /> <bpmn:textAnnotation id="TextAnnotation_0e6ka7i"> <bpmn:text>BearbeitungS: - Ablehnungsgrund outputP: -- genehmigt?</bpmn:text> +- genehmigt? +ID:approveStatement</bpmn:text> </bpmn:textAnnotation> - <bpmn:association id="Association_0ibyxtx" sourceRef="t_genehmigen_zust" targetRef="TextAnnotation_0o3acqz" /> - <bpmn:association id="Association_1wzmddm" sourceRef="t_ablehnung_durchfuehren" targetRef="TextAnnotation_1579k23" /> - <bpmn:association id="Association_16e69cr" sourceRef="t_anreichern_fb_results" targetRef="TextAnnotation_1cc5hqk" /> - <bpmn:association id="Association_0yk28uv" sourceRef="t_pruefung_vollstaendigkeit" targetRef="TextAnnotation_0bd2iv0" /> - <bpmn:association id="Association_1mp1cmg" sourceRef="t_erstellung_entwurf" targetRef="TextAnnotation_0zhm9mr" /> - <bpmn:association id="Association_14n2c6r" sourceRef="t_erstelluing_workflowdata" targetRef="TextAnnotation_1b3dksb" /> - <bpmn:association id="Association_1tkrwj3" sourceRef="t_ergaenzen_infodaten" targetRef="TextAnnotation_0plj167" /> - <bpmn:association id="Association_0nsvubu" sourceRef="t_anlegen" targetRef="TextAnnotation_1kjvfbn" /> - <bpmn:association id="Association_16bhqiy" sourceRef="Activity_1yuntdb" targetRef="TextAnnotation_0qa3dz1" /> - <bpmn:association id="Association_009oil7" sourceRef="t_genehmigung_stellungnahme" targetRef="TextAnnotation_0e6ka7i" /> - <bpmn:textAnnotation id="TextAnnotation_1eu0fdf"> - <bpmn:text>BearbeitungS: - Ausdruck - -Automatische persistieren</bpmn:text> - </bpmn:textAnnotation> - <bpmn:association id="Association_1o329sx" sourceRef="t_send_statement" targetRef="TextAnnotation_1eu0fdf" /> + <bpmn:association id="Association_009oil7" sourceRef="approveStatement" targetRef="TextAnnotation_0e6ka7i" /> </bpmn:process> <bpmn:message id="Message_1miquxl" name="m_create_from_mail" /> <bpmn:message id="Message_1fzsbnd" name="m_create_manual" /> <bpmndi:BPMNDiagram id="BPMNDiagram_1"> <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="statement_c"> <bpmndi:BPMNShape id="Participant_0pmtbog_di" bpmnElement="Participant_0pmtbog" isHorizontal="true"> - <dc:Bounds x="153" y="115" width="2357" height="1160" /> + <dc:Bounds x="153" y="80" width="2287" height="1030" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Lane_0spmnb6_di" bpmnElement="Lane_0spmnb6" isHorizontal="true"> - <dc:Bounds x="183" y="730" width="2327" height="315" /> + <dc:Bounds x="183" y="770" width="2257" height="340" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Lane_0gjug73_di" bpmnElement="Lane_0gjug73" isHorizontal="true"> - <dc:Bounds x="183" y="115" width="2327" height="615" /> + <dc:Bounds x="183" y="270" width="2257" height="500" /> </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Lane_0hux5z5_di" bpmnElement="Lane_0hux5z5" isHorizontal="true"> - <dc:Bounds x="183" y="1045" width="2327" height="230" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_0o3acqz_di" bpmnElement="TextAnnotation_0o3acqz"> - <dc:Bounds x="417" y="805" width="200.99379169755375" height="68.19866567828021" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_1579k23_di" bpmnElement="TextAnnotation_1579k23"> - <dc:Bounds x="1087" y="970" width="139.9995366938473" height="40.02965159377317" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_1cc5hqk_di" bpmnElement="TextAnnotation_1cc5hqk"> - <dc:Bounds x="1737" y="1065" width="99.99305040770942" height="82.28317272053373" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_0bd2iv0_di" bpmnElement="TextAnnotation_0bd2iv0"> - <dc:Bounds x="1637" y="155" width="99.99305040770942" height="96.36767976278725" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_0zhm9mr_di" bpmnElement="TextAnnotation_0zhm9mr"> - <dc:Bounds x="1327" y="165" width="99.99305040770942" height="40.02965159377317" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_1b3dksb_di" bpmnElement="TextAnnotation_1b3dksb"> - <dc:Bounds x="1007" y="165" width="99.99305040770942" height="40.02965159377317" /> + <bpmndi:BPMNShape id="Lane_078yf14_di" bpmnElement="Lane_078yf14" isHorizontal="true"> + <dc:Bounds x="183" y="80" width="2257" height="190" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="TextAnnotation_0plj167_di" bpmnElement="TextAnnotation_0plj167"> - <dc:Bounds x="607" y="255" width="164.99490363232024" height="180.87472201630837" /> + <dc:Bounds x="607" y="295" width="164.97894889663183" height="206.7363530778165" /> </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_1kjvfbn_di" bpmnElement="TextAnnotation_1kjvfbn"> - <dc:Bounds x="347" y="285" width="119.99629355077836" height="110.45218680504077" /> + <bpmndi:BPMNShape id="TextAnnotation_1b3dksb_di" bpmnElement="TextAnnotation_1b3dksb"> + <dc:Bounds x="960" y="408" width="120" height="81" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="TextAnnotation_0zhm9mr_di" bpmnElement="TextAnnotation_0zhm9mr"> + <dc:Bounds x="1140" y="408" width="99.99274099883856" height="53.426248548199766" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="TextAnnotation_0qa3dz1_di" bpmnElement="TextAnnotation_0qa3dz1"> - <dc:Bounds x="1837" y="155" width="190" height="110" /> + <dc:Bounds x="1820" y="373" width="189.98620789779326" height="123.11265969802555" /> </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="TextAnnotation_0e6ka7i_di" bpmnElement="TextAnnotation_0e6ka7i"> - <dc:Bounds x="1947" y="1075" width="203.77362861378802" height="82.28317272053373" /> + <bpmndi:BPMNShape id="TextAnnotation_0bd2iv0_di" bpmnElement="TextAnnotation_0bd2iv0"> + <dc:Bounds x="1580" y="387" width="170" height="123" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="TextAnnotation_1eu0fdf_di" bpmnElement="TextAnnotation_1eu0fdf"> - <dc:Bounds x="2170" y="163" width="99.98924268502581" height="80.89500860585198" /> + <dc:Bounds x="2110" y="373" width="117" height="123" /> </bpmndi:BPMNShape> - <bpmndi:BPMNEdge id="Flow_1q09bdk_di" bpmnElement="Flow_1q09bdk"> - <di:waypoint x="947" y="870" /> - <di:waypoint x="947" y="580" /> - <bpmndi:BPMNLabel> - <dc:Bounds x="958" y="778" width="78" height="14" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Flow_123dp6r_di" bpmnElement="Flow_123dp6r"> - <di:waypoint x="1197" y="665" /> - <di:waypoint x="1259" y="665" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Flow_0wq62kf_di" bpmnElement="Flow_0wq62kf"> - <di:waypoint x="847" y="895" /> - <di:waypoint x="922" y="895" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Flow_02s8ix9_di" bpmnElement="Flow_02s8ix9"> - <di:waypoint x="972" y="895" /> - <di:waypoint x="1147" y="895" /> - <di:waypoint x="1147" y="705" /> - <bpmndi:BPMNLabel> - <dc:Bounds x="1034" y="877" width="52" height="14" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNEdge> + <bpmndi:BPMNShape id="TextAnnotation_1cc5hqk_di" bpmnElement="TextAnnotation_1cc5hqk"> + <dc:Bounds x="1650" y="119" width="99.99274099883856" height="95.23809523809524" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="TextAnnotation_0e6ka7i_di" bpmnElement="TextAnnotation_0e6ka7i"> + <dc:Bounds x="1690" y="902" width="140" height="95" /> + </bpmndi:BPMNShape> <bpmndi:BPMNEdge id="Flow_017kj0u_di" bpmnElement="Flow_017kj0u"> - <di:waypoint x="797" y="580" /> - <di:waypoint x="797" y="855" /> + <di:waypoint x="797" y="620" /> + <di:waypoint x="797" y="840" /> + <di:waypoint x="1982" y="840" /> <bpmndi:BPMNLabel> - <dc:Bounds x="800" y="688" width="74" height="14" /> + <dc:Bounds x="813" y="648" width="74" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_0nwawsv_di" bpmnElement="Flow_0nwawsv"> - <di:waypoint x="822" y="555" /> - <di:waypoint x="922" y="555" /> + <di:waypoint x="822" y="595" /> + <di:waypoint x="960" y="595" /> <bpmndi:BPMNLabel> - <dc:Bounds x="848" y="537" width="48" height="14" /> + <dc:Bounds x="830" y="577" width="48" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Flow_1wkiruw_di" bpmnElement="Flow_1wkiruw"> - <di:waypoint x="447" y="555" /> - <di:waypoint x="607" y="555" /> - </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_1uni785_di" bpmnElement="Flow_1uni785"> - <di:waypoint x="285" y="555" /> - <di:waypoint x="347" y="555" /> + <di:waypoint x="388" y="595" /> + <di:waypoint x="525" y="595" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_167ttld_di" bpmnElement="Flow_167ttld"> - <di:waypoint x="707" y="555" /> - <di:waypoint x="772" y="555" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Flow_0vg1k1c_di" bpmnElement="Flow_0vg1k1c"> - <di:waypoint x="972" y="555" /> - <di:waypoint x="1097" y="555" /> + <di:waypoint x="707" y="595" /> + <di:waypoint x="772" y="595" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_1hqe1j8_di" bpmnElement="Flow_1hqe1j8"> - <di:waypoint x="1197" y="555" /> - <di:waypoint x="1327" y="555" /> + <di:waypoint x="1060" y="595" /> + <di:waypoint x="1140" y="595" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_0rrgglo_di" bpmnElement="Flow_0rrgglo"> - <di:waypoint x="1377" y="595" /> - <di:waypoint x="1377" y="1155" /> - <di:waypoint x="1452" y="1155" /> + <di:waypoint x="1240" y="595" /> + <di:waypoint x="1320" y="595" /> + <di:waypoint x="1320" y="160" /> + <di:waypoint x="1385" y="160" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_0r3c12h_di" bpmnElement="Flow_0r3c12h"> - <di:waypoint x="1647" y="1155" /> - <di:waypoint x="1687" y="1155" /> - <di:waypoint x="1687" y="700" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Flow_1qahwu7_di" bpmnElement="Flow_1qahwu7"> - <di:waypoint x="1502" y="1155" /> - <di:waypoint x="1547" y="1155" /> + <di:waypoint x="1530" y="200" /> + <di:waypoint x="1530" y="555" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_1tmr5qp_di" bpmnElement="Flow_1tmr5qp"> - <di:waypoint x="1737" y="555" /> - <di:waypoint x="1792" y="555" /> + <di:waypoint x="1580" y="595" /> + <di:waypoint x="1655" y="595" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_10zb14i_di" bpmnElement="Flow_10zb14i"> - <di:waypoint x="1817" y="530" /> - <di:waypoint x="1817" y="465" /> - <di:waypoint x="1477" y="465" /> - <di:waypoint x="1477" y="1130" /> + <di:waypoint x="1680" y="620" /> + <di:waypoint x="1680" y="690" /> + <di:waypoint x="1410" y="690" /> + <di:waypoint x="1410" y="185" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1608" y="447" width="79" height="14" /> + <dc:Bounds x="1591" y="707" width="79" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_12g2bxr_di" bpmnElement="Flow_12g2bxr"> - <di:waypoint x="1842" y="555" /> - <di:waypoint x="1957" y="555" /> + <di:waypoint x="1705" y="595" /> + <di:waypoint x="1830" y="595" /> <bpmndi:BPMNLabel> - <dc:Bounds x="1874" y="537" width="52" height="14" /> + <dc:Bounds x="1742" y="577" width="52" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_006vhwy_di" bpmnElement="Flow_006vhwy"> + <di:waypoint x="1930" y="595" /> <di:waypoint x="2007" y="595" /> - <di:waypoint x="2007" y="855" /> + <di:waypoint x="2007" y="815" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_12c0wj3_di" bpmnElement="Flow_12c0wj3"> - <di:waypoint x="2057" y="895" /> - <di:waypoint x="2152" y="895" /> + <di:waypoint x="2057" y="950" /> + <di:waypoint x="2152" y="950" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_00qgmxu_di" bpmnElement="Flow_00qgmxu"> - <di:waypoint x="2177" y="870" /> - <di:waypoint x="2177" y="595" /> + <di:waypoint x="2177" y="925" /> + <di:waypoint x="2177" y="635" /> <bpmndi:BPMNLabel> - <dc:Bounds x="2191" y="788" width="52" height="14" /> + <dc:Bounds x="2191" y="839" width="52" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_1k89j3h_di" bpmnElement="Flow_1k89j3h"> - <di:waypoint x="2177" y="920" /> - <di:waypoint x="2177" y="985" /> - <di:waypoint x="1817" y="985" /> - <di:waypoint x="1817" y="675" /> - <di:waypoint x="1712" y="675" /> + <di:waypoint x="2177" y="975" /> + <di:waypoint x="2177" y="1040" /> + <di:waypoint x="550" y="1040" /> + <di:waypoint x="550" y="620" /> <bpmndi:BPMNLabel> - <dc:Bounds x="2028" y="988" width="78" height="14" /> + <dc:Bounds x="1641" y="1043" width="78" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Flow_18v38ei_di" bpmnElement="Flow_18v38ei"> - <di:waypoint x="1687" y="650" /> - <di:waypoint x="1687" y="595" /> - </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Flow_0279yx1_di" bpmnElement="Flow_0279yx1"> - <di:waypoint x="2227" y="555" /> - <di:waypoint x="2329" y="555" /> + <di:waypoint x="2227" y="595" /> + <di:waypoint x="2329" y="595" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0oigd8l_di" bpmnElement="Flow_0oigd8l"> + <di:waypoint x="575" y="595" /> + <di:waypoint x="607" y="595" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_13ba0uc_di" bpmnElement="Flow_13ba0uc"> + <di:waypoint x="2007" y="865" /> + <di:waypoint x="2007" y="910" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Flow_0nt1wtg_di" bpmnElement="Flow_0nt1wtg"> + <di:waypoint x="1435" y="160" /> + <di:waypoint x="1480" y="160" /> </bpmndi:BPMNEdge> <bpmndi:BPMNShape id="Gateway_1qr83rr_di" bpmnElement="Gateway_1qr83rr" isMarkerVisible="true"> - <dc:Bounds x="772" y="530" width="50" height="50" /> + <dc:Bounds x="772" y="570" width="50" height="50" /> <bpmndi:BPMNLabel> - <dc:Bounds x="770" y="500" width="55" height="14" /> + <dc:Bounds x="770" y="540" width="55" height="14" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_1srttb4_di" bpmnElement="t_genehmigen_zust"> - <dc:Bounds x="747" y="855" width="100" height="80" /> + <bpmndi:BPMNShape id="Activity_0eqh4fs_di" bpmnElement="addBasicInfoData"> + <dc:Bounds x="607" y="555" width="100" height="80" /> </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_1ojw5pl_di" bpmnElement="t_ablehnung_durchfuehren"> - <dc:Bounds x="1097" y="625" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Event_08dad71_di" bpmnElement="e_not_responsible"> - <dc:Bounds x="1259" y="647" width="36" height="36" /> - <bpmndi:BPMNLabel> - <dc:Bounds x="1252" y="690" width="52" height="27" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_1oldmx6_di" bpmnElement="t_erstelluing_workflowdata"> - <dc:Bounds x="1097" y="515" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Gateway_0lqi8ef_di" bpmnElement="Gateway_0lqi8ef" isMarkerVisible="true"> - <dc:Bounds x="922" y="870" width="50" height="50" /> - <bpmndi:BPMNLabel> - <dc:Bounds x="919" y="927" width="58" height="27" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Gateway_127jq7b_di" bpmnElement="Gateway_127jq7b" isMarkerVisible="true"> - <dc:Bounds x="922" y="530" width="50" height="50" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_0eqh4fs_di" bpmnElement="t_ergaenzen_infodaten"> - <dc:Bounds x="607" y="515" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_1n1zr1f_di" bpmnElement="t_erstellung_entwurf"> - <dc:Bounds x="1327" y="515" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Gateway_1doisb4_di" bpmnElement="Gateway_1doisb4" isMarkerVisible="true"> - <dc:Bounds x="1792" y="530" width="50" height="50" /> - <bpmndi:BPMNLabel> - <dc:Bounds x="1773" y="590" width="89" height="27" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Gateway_1vm0oko_di" bpmnElement="Gateway_1vm0oko" isMarkerVisible="true"> - <dc:Bounds x="1452" y="1130" width="50" height="50" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_1tgzhpp_di" bpmnElement="t_pruefung_vollstaendigkeit"> - <dc:Bounds x="1637" y="515" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_18zc9wa_di" bpmnElement="t_anreichern_fb_results"> - <dc:Bounds x="1547" y="1115" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_0mabk8y_di" bpmnElement="Activity_1yuntdb"> - <dc:Bounds x="1957" y="515" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Gateway_0t8k8x7_di" bpmnElement="Gateway_0t8k8x7" isMarkerVisible="true"> - <dc:Bounds x="2152" y="870" width="50" height="50" /> - <bpmndi:BPMNLabel> - <dc:Bounds x="2212" y="888" width="76" height="14" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_1doaf0e_di" bpmnElement="t_send_statement"> - <dc:Bounds x="2127" y="515" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Gateway_150w9po_di" bpmnElement="Gateway_150w9po" isMarkerVisible="true"> - <dc:Bounds x="1662" y="650" width="50" height="50" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_0eyy22i_di" bpmnElement="t_genehmigung_stellungnahme"> - <dc:Bounds x="1957" y="855" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Activity_1ex6mn4_di" bpmnElement="t_anlegen"> - <dc:Bounds x="347" y="515" width="100" height="80" /> - </bpmndi:BPMNShape> - <bpmndi:BPMNShape id="Event_0fyjqwo_di" bpmnElement="s_anlegen_manuell"> - <dc:Bounds x="249" y="537" width="36" height="36" /> + <bpmndi:BPMNShape id="Activity_1doaf0e_di" bpmnElement="sendStatement"> + <dc:Bounds x="2127" y="555" width="100" height="80" /> </bpmndi:BPMNShape> <bpmndi:BPMNShape id="Event_1vaxrkr_di" bpmnElement="e_erfolgreicher_abschluss"> - <dc:Bounds x="2329" y="537" width="36" height="36" /> + <dc:Bounds x="2329" y="577" width="36" height="36" /> <bpmndi:BPMNLabel> - <dc:Bounds x="2305" y="580" width="87" height="27" /> + <dc:Bounds x="2312" y="620" width="74" height="27" /> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> - <bpmndi:BPMNEdge id="Association_0ibyxtx_di" bpmnElement="Association_0ibyxtx"> - <di:waypoint x="747" y="885" /> - <di:waypoint x="618" y="859" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Association_1wzmddm_di" bpmnElement="Association_1wzmddm"> - <di:waypoint x="1148" y="705" /> - <di:waypoint x="1156" y="970" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Association_16e69cr_di" bpmnElement="Association_16e69cr"> - <di:waypoint x="1647" y="1142" /> - <di:waypoint x="1737" y="1119" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Association_0yk28uv_di" bpmnElement="Association_0yk28uv"> - <di:waypoint x="1687" y="515" /> - <di:waypoint x="1687" y="251" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Association_1mp1cmg_di" bpmnElement="Association_1mp1cmg"> - <di:waypoint x="1377" y="515" /> - <di:waypoint x="1377" y="205" /> + <bpmndi:BPMNShape id="Gateway_0i8uj9a_di" bpmnElement="Gateway_0i8uj9a" isMarkerVisible="true"> + <dc:Bounds x="525" y="570" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_1wxwe5e_di" bpmnElement="Gateway_1wxwe5e" isMarkerVisible="true"> + <dc:Bounds x="1982" y="815" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0eyy22i_di" bpmnElement="approveStatement"> + <dc:Bounds x="1957" y="910" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_0t8k8x7_di" bpmnElement="Gateway_0t8k8x7" isMarkerVisible="true"> + <dc:Bounds x="2152" y="925" width="50" height="50" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="2212" y="943" width="76" height="14" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1oldmx6_di" bpmnElement="addWorkflowData"> + <dc:Bounds x="960" y="555" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1n1zr1f_di" bpmnElement="createDraft"> + <dc:Bounds x="1140" y="555" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_1vm0oko_di" bpmnElement="Gateway_1vm0oko" isMarkerVisible="true"> + <dc:Bounds x="1385" y="135" width="50" height="50" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_18zc9wa_di" bpmnElement="enrichDraft"> + <dc:Bounds x="1480" y="120" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_1tgzhpp_di" bpmnElement="checkForCompleteness"> + <dc:Bounds x="1480" y="555" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Gateway_1doisb4_di" bpmnElement="Gateway_1doisb4" isMarkerVisible="true"> + <dc:Bounds x="1655" y="570" width="50" height="50" /> + <bpmndi:BPMNLabel> + <dc:Bounds x="1635" y="532.5" width="89" height="27" /> + </bpmndi:BPMNLabel> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Activity_0mabk8y_di" bpmnElement="finalizeStatement"> + <dc:Bounds x="1830" y="555" width="100" height="80" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape id="Event_0fyjqwo_di" bpmnElement="s_anlegen_manuell"> + <dc:Bounds x="352" y="577" width="36" height="36" /> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge id="Association_1tkrwj3_di" bpmnElement="Association_1tkrwj3"> + <di:waypoint x="664" y="555" /> + <di:waypoint x="673" y="502" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Association_14n2c6r_di" bpmnElement="Association_14n2c6r"> - <di:waypoint x="1137" y="515" /> - <di:waypoint x="1062" y="205" /> + <di:waypoint x="1013" y="555" /> + <di:waypoint x="1017" y="489" /> </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Association_1tkrwj3_di" bpmnElement="Association_1tkrwj3"> - <di:waypoint x="663" y="515" /> - <di:waypoint x="676" y="436" /> - </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Association_0nsvubu_di" bpmnElement="Association_0nsvubu"> - <di:waypoint x="399" y="515" /> - <di:waypoint x="404" y="395" /> + <bpmndi:BPMNEdge id="Association_1mp1cmg_di" bpmnElement="Association_1mp1cmg"> + <di:waypoint x="1190" y="555" /> + <di:waypoint x="1190" y="461" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Association_16bhqiy_di" bpmnElement="Association_16bhqiy"> - <di:waypoint x="1998" y="515" /> - <di:waypoint x="1944" y="265" /> + <di:waypoint x="1889" y="555" /> + <di:waypoint x="1902" y="496" /> </bpmndi:BPMNEdge> - <bpmndi:BPMNEdge id="Association_009oil7_di" bpmnElement="Association_009oil7"> - <di:waypoint x="2015" y="935" /> - <di:waypoint x="2041" y="1075" /> + <bpmndi:BPMNEdge id="Association_0yk28uv_di" bpmnElement="Association_0yk28uv"> + <di:waypoint x="1566" y="555" /> + <di:waypoint x="1608" y="510" /> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge id="Association_1o329sx_di" bpmnElement="Association_1o329sx"> - <di:waypoint x="2182" y="515" /> - <di:waypoint x="2215" y="244" /> + <di:waypoint x="2175" y="555" /> + <di:waypoint x="2172" y="496" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Association_16e69cr_di" bpmnElement="Association_16e69cr"> + <di:waypoint x="1580" y="162" /> + <di:waypoint x="1650" y="164" /> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge id="Association_009oil7_di" bpmnElement="Association_009oil7"> + <di:waypoint x="1957" y="950" /> + <di:waypoint x="1830" y="949" /> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram>
diff --git a/pom.xml b/pom.xml index 64b6572..f1bc637 100644 --- a/pom.xml +++ b/pom.xml
@@ -19,7 +19,7 @@ </parent> <groupId>org.eclipse.openk</groupId> <artifactId>statement-public-affairs</artifactId> - <version>0.2.0</version> + <version>0.3.0</version> <name>statement-public-affairs</name> <description>StatementPublicAffairs project for openKONSEQUENZ</description> @@ -31,7 +31,7 @@ <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version> <springfox.version>2.9.2</springfox.version> <spring-security-test.version>5.2.1.RELEASE</spring-security-test.version> - <sonar-maven-plugin.version>3.2</sonar-maven-plugin.version> + <sonar-maven-plugin.version>3.6.0.1398</sonar-maven-plugin.version> <asciidoctor-maven-plugin-version>1.5.3</asciidoctor-maven-plugin-version> <asciidoctorj-pdf-version>1.5.0-alpha.11</asciidoctorj-pdf-version> <asciidoctorj-version>1.5.4</asciidoctorj-version>
diff --git a/sonar-project.properties b/sonar-project.properties index 757971d..d3c0161 100644 --- a/sonar-project.properties +++ b/sonar-project.properties
@@ -1,19 +1,14 @@ # must be unique in a given SonarQube instance -sonar.projectKey=openk.planeit.de:statement-public-affairs.backend +sonar.projectKey=openkdg:statement-public-affairs.backend # this is the name and version displayed in the SonarQube UI. Was mandatory prior to SonarQube 6.1. sonar.projectName=statement-public-affairs.BE sonar.projectVersion=0.0.1_Snapshot sonar.java.binaries=target/classes -# Language -sonar.language= - sonar.sourceEncoding=UTF-8 sonar.sources=src/main -sonar.exclusions=**/model/*.java,**/viewmodel/*.java +sonar.exclusions=**/model/**,**/viewmodel/** +sonar.coverage.exclusions=**/model/**,**/viewmodel/**,**/exceptions/** sonar.tests=src/test -#sonar.test.inclusions=**/*.spec.ts sonar.test.exclusions=**/model/**,**/viewmodel/** -#sonar.ts.tslintconfigpath=tslint.json -sonar.typescript.lcov.reportPaths=coverage/lcov.info
diff --git a/src/main/asciidoc/api/openapi.yaml b/src/main/asciidoc/api/openapi.yaml index 50e19b9..4954b94 100644 --- a/src/main/asciidoc/api/openapi.yaml +++ b/src/main/asciidoc/api/openapi.yaml
@@ -336,7 +336,158 @@ security: - JWT: - spa_access - + /process/statements/{statementId}/task: + get: + tags: + - "process" + summary: "Get all current workflow tasks for Statement with statementId" + description: "Get all current workflow tasks for Statement with statementId" + parameters: + - name: statementId + in: path + description: Statement ID + required: true + schema: + type: integer + format: int64 + responses: + 200: + description: "List of Current Statement Tasks" + content: + application/json: + schema: + $ref: '#/components/schemas/ListTaskModel' + 401: + description: "Not Authorized - Please provide a security token" + 403: + description: "Forbidden" + 404: + description: "Not Found - Task with given taskId of Statement with given statementId does not exist" + security: + - JWT: + - spa_access + + /process/statements/{statementId}/task/{taskId}/claim: + post: + tags: + - "process" + summary: "Claim task with taskId of Statement with statementId" + description: "Claim task with taskId of Statement with statementId" + parameters: + - name: statementId + in: path + description: Statement ID + required: true + schema: + type: integer + format: int64 + - name: taskId + in: path + description: Task ID + required: true + schema: + type: string + format: uuid + responses: + 200: + description: "Statement Task" + content: + application/json: + schema: + $ref: '#/components/schemas/TaskModel' + 400: + description: "Bad Request - Invalid parameters or already claimed" + 401: + description: "Not Authorized - Please provide a security token" + 403: + description: "Forbidden" + 404: + description: "Not Found - Statement with given statementId does not exist" + security: + - JWT: + - spa_access + + /process/statements/{statementId}/task/{taskId}/unclaim: + post: + tags: + - "process" + summary: "Unclaim task with taskId of Statement with statementId" + description: "Unclaim task with taskId of Statement with statementId" + parameters: + - name: statementId + in: path + description: Statement ID + required: true + schema: + type: integer + format: int64 + - name: taskId + in: path + description: Task ID + required: true + schema: + type: string + format: uuid + responses: + 200: + description: "Statement Task" + content: + application/json: + schema: + $ref: '#/components/schemas/TaskModel' + 400: + description: "Bad Request - Invalid parameters or not claimed" + 401: + description: "Not Authorized - Please provide a security token" + 403: + description: "Forbidden" + 404: + description: "Not Found - Statement with given statementId does not exist" + security: + - JWT: + - spa_access + + /process/statements/{statementId}/task/{taskId}/complete: + post: + tags: + - "process" + summary: "Complete task with taskId of Statement with statementId" + description: "Complete task with taskId of Statement with statementId" + parameters: + - name: statementId + in: path + description: Statement ID + required: true + schema: + type: integer + format: int64 + - name: taskId + in: path + description: Task ID + required: true + schema: + type: string + format: uuid + requestBody: + description: "Required variables to successfully complete the task." + content: + application/json: + schema: + $ref: '#/components/schemas/MapCompleteVariable' + responses: + 204: + description: "Complete sucessful" + 400: + description: "Bad Request - Invalid parameters or not claimed" + 401: + description: "Not Authorized - Please provide a security token" + 403: + description: "Forbidden" + 404: + description: "Not Found - Statement with given statementId does not exist" + security: + - JWT: + - spa_access components: securitySchemes: @@ -440,7 +591,62 @@ format: int64 name: type: "string" + + ListTaskModel: + type: "array" + items: + $ref: '#/components/schemas/TaskModel' + + TaskModel: + type: "object" + properties: + statementId: + type: integer + format: int64 + taskId: + type: string + example: "123e4567-e89b-12d3-a456-426655440000" + format: uuid + pattern: "xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx" + taskDefinitionKey: + type: string + processDefinitionKey: + type: string + assignee: + type: string + requiredVariables: + $ref: '#/components/schemas/TaskModelRequiredVariables' + + TaskModelRequiredVariables: + type: "object" + properties: + name: + type: string + enum: + - Boolean + MapCompleteVariable: + type: "object" + properties: + name: + $ref: '#/components/schemas/CompleteVariable' + + CompleteVariable: + type: "object" + properties: + type: + type: string + enum: + - Boolean + value: + type: boolean + + + + + + + externalDocs: description: "Find out more about OpenKONSEQUENZ" url: "https://www.openkonsequenz.de/"
diff --git a/src/main/asciidoc/arch/src/08_concepts.adoc b/src/main/asciidoc/arch/src/08_concepts.adoc index a62ef16..a542b33 100644 --- a/src/main/asciidoc/arch/src/08_concepts.adoc +++ b/src/main/asciidoc/arch/src/08_concepts.adoc
@@ -1,15 +1,66 @@ [[section-concepts]] == Cross-cutting Concepts +=== Role concept + +The creation of a new statement response requires the collaboration of multiple editors from different company domains. They enhance the statement details by adding domain specific information, comments that should support the final creation of the response document or verify the document for approval. The statement process is therefore divided up into multiple sequenced tasks each of which can be matched to one or more abstract user roles. A suitable role and rights concept must restrict general access to a previously defined group of editors as well as restricting the editing according to additional parameters like the current task and assigned user roles. This should be ensured by an adapted frontend visualization as well as a verification of the concrete edit type and parameters in the backend service. + +The authorization logic is therefore implemented in a multi-tier validation process. + +To identify an access user, the external core module AuthNAuth is used. Each user of the statement public affairs module is verified by a token generated by the AuthNAuth module. The assigned user roles managed by the AuthNAuth module can be used by the statement module to authorize the access interfaces. + +The overall access to the user interface as well as the backend api is authorized by a basic role SPA_ACCESS that has to be assigned to each user of the statement public affairs module. +This role grants you readable access to statment overview and details. Besides that, editing of statement details like attachments, comments or text-blocks is only allowed in certain statement process tasks and only granted for specific user roles. To prevent inconsistencies it shall be ensured, that only one user can edit a statment at the same time. This is ensured by a user to task assignment where only the currently assigned process task user is authorized to edit the statement. + +With that one can abstract the following basic rules: + +* General read access is granted by the basic SPA_ACCESS role +* Editing access is only granted for the currently assigned user +* The concrete edit authorization is specific to the statement process task and the user roles + +==== Roles + +[cols="2*", options="header"] +|=== +| Role | Description +| SPA_ACCESS | Basic role that provides module access +| SPA_ADMIN | Configures the statement module +| SPA_OIC | Official in charge that does the formal statment editing +| SPA_DIVISION_MEMBER | Member of a division that enhances the statement with domain specific information +| SPA_APPROVER | Approves finished statements or negative responses +| SPA_GUEST | Browses statements that are still in process or already finished +|=== + +==== Verification + +As shown in the authorization process diagramm the verification is a multi-tier process. + +image::authorization-process.png[] +The first tier is the only granted based on the SPA_ACCESS user role that every statement module user shares. +The next tiers differ in the concrete access types. Access types can be grouped into process task specific access and general access. General access is only verified by the user roles. Examples for these access types are reading statement details or starting a new statement process. The other access types are specified for each process task. To process a task, the user has to temporarily claim the task. This claim-user is matched with the access user. The last step of the task specific access authorization verifies the User Roles in combination with the task. -=== _<Concept 1>_ +==== Backend -_<explanation>_ +In the API backend, the three layer are implemented as follows. +The verificateion of the SPA_ACCESS role is implemented as a general precondition to access an endpoint. This reduces the attack surface of the service as only little code is executed before access is denied. +A central authorization service implements the other two verification layers. It has interfaces to verify the task specific access and the general access types and is requested in the beginning of each endpoint logic. +The central authorization service is configured by an authorization matrix that sets the role and task specific access rights. +==== Frontend +The basic strategy for the front end is to only render specific views or user controls if the user is authorized to read or use them. User roles as well as the information on tasks are stored centrally in the web application. On a change, all views are updated with the new data and display or hide certain parts of it. + +In the front end application, the first tier of access is verified right at the initialization when all roles for the user are loaded from the back end. If the user is not provided with general read access, only an error message is rendered. Otherwise, the user has access to the main views of the application. + +Certain sub pages, e.g. the settings page for configuring the module, can only be accessed with a specific user role. If a user is not provided with all necessary roles, links to the subpage are not rendered in the navigation bar. Route guards ensure that a user can not access restricted sub pages via an URL route and redirect to the main landing page in this case. + +The second tier of access is verified if a user wants to view or edits a specific user task. For example, user controls to claim a task are only rendered if the task is not claimed by another user and if the user is actually allowed to do so by its assigned roles. +Details of a statement can only be edited on a specific sub page, the edit page. When accessing the edit page for a specific task, first the relevant task information is loaded (or updated) and different kind of views are presented to the user based upon the task information and the user's roles. + +While visiting the web application, roles can be revoked from the user. If so and if the user is trying to access now restricted areas of the web application, the user is logged out automatically. This essentially forces the user to revisit the website. It is also possible that the user's claim on a statement task is revoked. If so, all currently displayed views are updated accordingly to the new task information. For example, the edit page is updated and displays now a simple message instead of a form to edit the statement's details. === _<Concept 2>_
diff --git a/src/main/asciidoc/howto/howtoBuild.adoc b/src/main/asciidoc/howto/howtoBuild.adoc new file mode 100644 index 0000000..88fe4f3 --- /dev/null +++ b/src/main/asciidoc/howto/howtoBuild.adoc
@@ -0,0 +1,84 @@ += openKonsequenz - How to build the module "Statement Public Affairs" +:Date: 2020-06-09 +:Revision: 0.3.0 +:icons: +:source-highlighter: highlightjs +:highlightjs-theme: solarized_dark + +<<< + +== Requirements +* Node.js 12.17.0 +* Angular-CLI +* Apache Maven 3.6.3 +* Openjdk 1.8.0_252 + +== Building the backend + +=== Environment + +Verify that your environment is set up correcytly. + +The java version of the jdk should match 1.8.0 + +[source,command] +---- + $ java -version +---- +The JAVA_HOME environment variable should point to the jdk home folder. + +The maven version should match 3.6.8 + +[source,command] +---- + $ mvn --version +---- + +=== Get backend sources + +Clone the backend sources with a git client. + +=== Configuration + +To include the configuration within the deployement artifact, the configuration file application.yml in src/main/resources can be replaced. +You can find a detailed description of the available configuration parameters in the howToRun document. + +=== Build + +To build the backend move to the project base folder + +The following command builds a new artifact, runs unittests to verify the implementation and stores the artifact and the test results within the target/ folder. + +[source, command] +---- + $ mvn clean install +---- + +To speed up the build you can skip testing. +[source, command] +---- + $ mvn clean install -DskipTests +---- + +The target/ folder should then contain a web application archive names statement-public-affairs.war + + +== Building the frontend + +=== Environment + +Verify that your environment is set up correctly. + +The node version should match 12.17.x +[source, command] +---- + $ node --version +---- + +TODO: add further details + +TIP: Next Step -> Read the *howToRun* documentation! + + + +
diff --git a/src/main/asciidoc/howto/howtoRun.adoc b/src/main/asciidoc/howto/howtoRun.adoc new file mode 100644 index 0000000..fe6a74c --- /dev/null +++ b/src/main/asciidoc/howto/howtoRun.adoc
@@ -0,0 +1,48 @@ += openKonsequenz - How to run the module "Statement Public Affairs" +:Date: 2020-06-09 +:Revision: 0.3.0 +:icons: +:source-highlighter: highlightjs +:highlightjs-theme: solarized_dark + +<<< + +IMPORTANT: Please be sure that you have installed and configured the following openKonsequenz modules! +* Portal (AuthNAuth) +* Contact Base Data + +== Requirements +* Browser (Chrome or Firefox) +* `statemtent-public-affairsBE.war` file after a successfully maven build located in `<backend project root>/target`. +* `statemtent-public-affairsFE.war` file after a successfully npm build located in `<frontend project root>/dist`. +See *howToBuild* documentation. + +== Prerequisites +* Portal Avaliable modules configuration - add statement module + +== Configure Keycloak +* AuthNAuth service users +* AuthNAuth SPA_Roles + +== Install and configure Apache Tomcat + +== Install and deploy the Database + +== Install and configure the Camunda workflow engine + +== Run the Backend + +=== Configuration of the Statement Public Affairs module Backend + +The backend service is configured with the `application.yml` file. + +==== Configuration Settings + +=== Deploy the Backend + +== Run the Frontend + +=== Configure your Webserver + +=== Deploy the Frontend +
diff --git a/src/main/asciidoc/images/authorization-process.png b/src/main/asciidoc/images/authorization-process.png new file mode 100644 index 0000000..db6b4ea --- /dev/null +++ b/src/main/asciidoc/images/authorization-process.png Binary files differ
diff --git a/src/main/asciidoc/userDocumentation/userDocumentation.adoc b/src/main/asciidoc/userDocumentation/userDocumentation.adoc new file mode 100644 index 0000000..1daa417 --- /dev/null +++ b/src/main/asciidoc/userDocumentation/userDocumentation.adoc
@@ -0,0 +1,57 @@ += User Guide: Statement Public Affairs + +<<< + +* Version: 0.3.0 +* Date: 2020-06-09 + +<<< + +:Author: Tobias Stummer +:Email: tobias.stummer@develop-group.de + +:Date: 2020-06-09 +:Revision: 0.3.0 + +:icons: + +:source-highlighter: highlightjs +:highlightjs-theme: solarized_dark + +:lang: de +:encoding: utf-8 + +:imagesdir: ../images +:iconsdir: ../images/icons + +:toc: +:toclevels: 4 +:toc-placement!: +:sectanchors: +:numbered: + +toc::[] + +<<< + +== Preface + +== Context: The statement process + +< process Overview image > +< Description of the basic User Roles > +< Description of the Tasks > + +== Basic navigation principles + +== Walk through common perspectives Dashboard and Details views + +== Walk through perspective OIC + +== Walk through perspective division member + +== Walk through perspective approver + +== Walk through Admin interfaces + +
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/Constants.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/Constants.java index 8887887..4f70d30 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/Constants.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/Constants.java
@@ -22,14 +22,21 @@ * */ public class Constants { - public static final String STATEMENT_WITH_ID_NOT_FOUND = "Statement with given id could not be found."; - public static final String ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND = "Attachment with given attachmentId and given statementId not found."; - public static final String NO_ATTACHMENT_FILE_SPECIFIED = "Request has no attachment file."; - public static final String MORE_THAN_ONE_ATTACHMENT_FILE = "Request contains more than one multipart attachment file."; - - public static final ResponseEntity<Object> RESPONSE_OK_NO_CONTENT = ResponseEntity.status(HttpStatus.NO_CONTENT).build(); - public static final ResponseEntity<Object> RESPONSE_OK = ResponseEntity.status(HttpStatus.OK).build(); - public static final ResponseEntity<Object> RESPONSE_NOT_IMPLEMENTED_YET = ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED).build(); - public static final ResponseEntity<Object> RESPONSE_SERVICE_NOT_AVAILABLE = ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE).build(); + + private Constants() { + } + + public static final String STATEMENT_WITH_ID_NOT_FOUND = "Statement with given id could not be found."; + public static final String ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND = "Attachment with given attachmentId and given statementId not found."; + public static final String NO_ATTACHMENT_FILE_SPECIFIED = "Request has no attachment file."; + public static final String MORE_THAN_ONE_ATTACHMENT_FILE = "Request contains more than one multipart attachment file."; + + public static final ResponseEntity<Object> RESPONSE_OK_NO_CONTENT = ResponseEntity.status(HttpStatus.NO_CONTENT) + .build(); + public static final ResponseEntity<Object> RESPONSE_OK = ResponseEntity.status(HttpStatus.OK).build(); + public static final ResponseEntity<Object> RESPONSE_NOT_IMPLEMENTED_YET = ResponseEntity + .status(HttpStatus.NOT_IMPLEMENTED).build(); + public static final ResponseEntity<Object> RESPONSE_SERVICE_NOT_AVAILABLE = ResponseEntity + .status(HttpStatus.SERVICE_UNAVAILABLE).build(); }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/api/CamundaApi.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/api/CamundaApi.java index 49850bc..a4f8a1c 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/api/CamundaApi.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/api/CamundaApi.java
@@ -39,8 +39,6 @@ import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; -import feign.Response; - /** * @author Tobias Stummer *
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/api/ContactDatabaseApi.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/api/ContactDatabaseApi.java new file mode 100644 index 0000000..739a7f3 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/api/ContactDatabaseApi.java
@@ -0,0 +1,65 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.api; + +import java.util.List; + +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiAddressModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiCompanyContactPersonModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiCompanyDetailsModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiContactDetailsModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiPagedCompanyContactPersonModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiPagedCompanyDetailsModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiPagedDetailedContact; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiPagedExternalPersonModel; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(name = "${services.contactdatabase.name}") +public interface ContactDatabaseApi { + + @GetMapping(value = "contacts") + public ContactApiPagedDetailedContact searchContacts(@RequestHeader("Authorization") String token, @RequestParam("contactType") String contactType, + @RequestParam("searchText") String searchText); + + @GetMapping(value = "contacts/{contact-uuid}") + public ContactApiContactDetailsModel getContact(@RequestHeader("Authorization") String token, + @RequestParam("contact-uuid") String contactuuid); + + @GetMapping(value = "contacts/{contact-uuid}/addresses") + public List<ContactApiAddressModel> getContactAddresses(@RequestHeader("Authorization") String token, + @RequestParam("contact-uuid") String contactuuid); + + @GetMapping(value = "companies") + public ContactApiPagedCompanyDetailsModel getCompanyList(@RequestHeader("Authorization") String token); + + @GetMapping(value = "companies/{company-uuid}") + public ContactApiCompanyDetailsModel getCompany(@RequestHeader("Authorization") String token, @RequestParam("company-uuid") String companyuuid); + + @GetMapping(value = "companies/{company-uuid}/contact-persons") + public ContactApiPagedCompanyContactPersonModel getCompanyContactPersons( + @RequestHeader("Authorization") String token, @RequestParam("company-uuid") String companyuuid); + + @GetMapping(value = "external-persons") + public ContactApiPagedExternalPersonModel getExternalPersonsList(@RequestHeader("Authorization") String token); + + @GetMapping(value="contact-persons/{contact-uuid}") + public ContactApiCompanyContactPersonModel getContactPerson( + @RequestHeader("Authorization") String token, @RequestParam("contact-uuid") String contactPersonUUID); + + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/JwtAuthenticationTokenFilter.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/JwtAuthenticationTokenFilter.java index 9dcdb79..375dc41 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/JwtAuthenticationTokenFilter.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/JwtAuthenticationTokenFilter.java
@@ -15,6 +15,7 @@ package org.eclipse.openk.statementpublicaffairs.config.auth; +import org.eclipse.openk.statementpublicaffairs.model.UserDetails; import org.keycloak.RSATokenVerifier; import org.keycloak.representations.AccessToken; import org.springframework.beans.factory.annotation.Value;
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserRoles.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserRoles.java index c2aaa9d..6d784f8 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserRoles.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserRoles.java
@@ -19,11 +19,15 @@ * */ public class UserRoles { - public static final String SPA_ACCESS = "ROLE_SPA_ACCESS"; - public static final String SPA_OFFICIAL_IN_CHARGE = "ROLE_SPA_OFFICIAL_IN_CHARGE"; - public static final String SPA_APPROVER = "ROLE_SPA_APPROVER"; - public static final String SPA_DIVISION_MEMBER = "ROLE_DIVISION_MEMBER"; - public static final String SPA_CUSTOMER = "ROLE_CUSTOMER"; - public static final String SPA_ADMIN = "ROLE_ADMIN"; + + private UserRoles() { + } + + public static final String SPA_ACCESS = "ROLE_SPA_ACCESS"; + public static final String SPA_OFFICIAL_IN_CHARGE = "ROLE_SPA_OFFICIAL_IN_CHARGE"; + public static final String SPA_APPROVER = "ROLE_SPA_APPROVER"; + public static final String SPA_DIVISION_MEMBER = "ROLE_DIVISION_MEMBER"; + public static final String SPA_CUSTOMER = "ROLE_CUSTOMER"; + public static final String SPA_ADMIN = "ROLE_ADMIN"; }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/ContactsController.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/ContactsController.java new file mode 100644 index 0000000..510672f --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/ContactsController.java
@@ -0,0 +1,55 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.controller; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalServerErrorException; +import org.eclipse.openk.statementpublicaffairs.model.CompanyModel; +import org.eclipse.openk.statementpublicaffairs.service.ContactService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class ContactsController { + + @Autowired + private ContactService contactService; + + + @GetMapping(value = "/contacts/") + public List<CompanyModel> searchContacts(@RequestParam("searchString") String searchString) { + try { + Optional<List<CompanyModel>> oCompanies = contactService.searchContacts(searchString); + if (oCompanies.isPresent()) { + return oCompanies.get(); + } else { + return new ArrayList<>(); + } + } catch (InternalErrorServiceException e) { + throw new InternalServerErrorException("Error occurred searching for contacts - " + e.getMessage(), e); + } + + } + + + + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementController.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementController.java index a928e06..8977670 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementController.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementController.java
@@ -25,10 +25,9 @@ import org.eclipse.openk.statementpublicaffairs.config.auth.UserRoles; import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestException; import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestServiceException; +import org.eclipse.openk.statementpublicaffairs.exceptions.ForbiddenException; import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; import org.eclipse.openk.statementpublicaffairs.exceptions.InternalServerErrorException; -import org.eclipse.openk.statementpublicaffairs.exceptions.ForbiddenException; -import org.eclipse.openk.statementpublicaffairs.exceptions.ForbiddenServiceException; import org.eclipse.openk.statementpublicaffairs.exceptions.NotFoundException; import org.eclipse.openk.statementpublicaffairs.model.AttachmentFile; import org.eclipse.openk.statementpublicaffairs.service.SessionService; @@ -64,216 +63,216 @@ @RestController public class StatementController { - @Autowired - private StatementService statementService; + @Autowired + private StatementService statementService; - @Autowired - private StatementProcessService statementProcessService; + @Autowired + private StatementProcessService statementProcessService; - @Autowired - private SessionService sessionService; + @Autowired + private SessionService sessionService; - /** - * Statement GET endpoint provides the Model of the requested Statement. - * - * @return StatementModel if exists. - * @throws NotFoundException if statement could not be found. - */ - @Secured({ UserRoles.SPA_ACCESS }) - @GetMapping(value = "/statements/{statementId}") - public StatementDetailsModel getStatementDetails(@PathVariable Long statementId) { - Optional<StatementDetailsModel> statementDetails; - try { - statementDetails = statementService.getStatement(statementId); - } catch (InternalErrorServiceException e) { - throw new InternalServerErrorException("Could not access statement ressource.", e); - } - if (statementDetails.isPresent()) { - return statementDetails.get(); - } - throw (new NotFoundException(Constants.STATEMENT_WITH_ID_NOT_FOUND)); - } - - /** - * Statement POST endpoint to create a new Statement. - * - * @param statement Statement model to create - * - * @return Statement model if successful. - * @throws BadRequestException if provided statement data is invalid - */ - @Secured({ UserRoles.SPA_ACCESS, UserRoles.SPA_OFFICIAL_IN_CHARGE }) - @PostMapping(value = "/statements") - public StatementDetailsModel createStatementDetails(@RequestBody StatementDetailsModel statement) { - try { - Optional<StatementDetailsModel> newstatement = statementProcessService.createStatement(statement); - if (newstatement.isPresent()) { - return newstatement.get(); - } else { - throw (new BadRequestException("Provided statement model is not correct.")); - } - } catch (BadRequestServiceException e) { - throw (new BadRequestException("Provided statement model is not correct.", e)); - } catch (InternalErrorServiceException e) { - throw new InternalServerErrorException("Error occurred creating the new statement" + e.getMessage() + e.getCause().getMessage(), e); + /** + * Statement GET endpoint provides the Model of the requested Statement. + * + * @return StatementModel if exists. + * @throws NotFoundException if statement could not be found. + */ + @Secured({ UserRoles.SPA_ACCESS }) + @GetMapping(value = "/statements/{statementId}") + public StatementDetailsModel getStatementDetails(@PathVariable Long statementId) { + Optional<StatementDetailsModel> statementDetails; + try { + statementDetails = statementService.getStatement(statementId); + } catch (InternalErrorServiceException e) { + throw new InternalServerErrorException("Could not access statement ressource.", e); } - } + if (statementDetails.isPresent()) { + return statementDetails.get(); + } + throw (new NotFoundException(Constants.STATEMENT_WITH_ID_NOT_FOUND)); + } - /** - * Statement PATCH endpoint allows to set a statement of given statementId to - * finished state. - * - * @param statementId Statement Identifier - * - * @return Ok_No_Content if successful. - * @throws NotFoundException if statement could not be found. - */ - @Secured({ UserRoles.SPA_ACCESS, UserRoles.SPA_OFFICIAL_IN_CHARGE }) - @PatchMapping(value = "/statements/{statementId}/finish") - public ResponseEntity<Object> finishAttachment(@PathVariable Long statementId) { - Optional<Boolean> successful = statementService.finishStatement(statementId); - if (successful.isPresent()) { - return Constants.RESPONSE_OK_NO_CONTENT; - } - throw new NotFoundException(Constants.STATEMENT_WITH_ID_NOT_FOUND); - } + /** + * Statement POST endpoint to create a new Statement. + * + * @param statement Statement model to create + * + * @return Statement model if successful. + * @throws BadRequestException if provided statement data is invalid + */ + @Secured({ UserRoles.SPA_ACCESS, UserRoles.SPA_OFFICIAL_IN_CHARGE }) + @PostMapping(value = "/statements") + public StatementDetailsModel createStatementDetails(@RequestBody StatementDetailsModel statement) { + try { + Optional<StatementDetailsModel> newstatement = statementProcessService.createStatement(statement); + if (newstatement.isPresent()) { + return newstatement.get(); + } else { + throw (new BadRequestException("Provided statement model is not correct.")); + } + } catch (BadRequestServiceException e) { + throw (new BadRequestException("Provided statement model is not correct.", e)); + } catch (InternalErrorServiceException e) { + throw new InternalServerErrorException( + "Error occurred creating the new statement" + e.getMessage() + e.getCause().getMessage(), e); + } + } - /** - * AllAttachments GET endpoint provides a list of all attachments of the - * statement with given statementId. - * - * @param statmentId Statement Identifier - * - * @throws NotFoundException if statement could not be found. - * @return List containing all Attachments as AttatchmentModel - */ - @Secured({ UserRoles.SPA_ACCESS }) - @GetMapping(value = "/statements/{statementId}/attachments") - public List<AttachmentModel> getAttachments(@PathVariable Long statementId) { - Optional<List<AttachmentModel>> attachments = statementService.getStatementAttachments(statementId); - if (attachments.isPresent()) { - return attachments.get(); - } + /** + * Statement PATCH endpoint allows to set a statement of given statementId to + * finished state. + * + * @param statementId Statement Identifier + * + * @return Ok_No_Content if successful. + * @throws NotFoundException if statement could not be found. + */ + @Secured({ UserRoles.SPA_ACCESS, UserRoles.SPA_OFFICIAL_IN_CHARGE }) + @PatchMapping(value = "/statements/{statementId}/finish") + public ResponseEntity<Object> finishAttachment(@PathVariable Long statementId) { + Optional<Boolean> successful = statementService.finishStatement(statementId); + if (successful.isPresent()) { + return Constants.RESPONSE_OK_NO_CONTENT; + } + throw new NotFoundException(Constants.STATEMENT_WITH_ID_NOT_FOUND); + } - throw (new NotFoundException(Constants.STATEMENT_WITH_ID_NOT_FOUND)); - } + /** + * AllAttachments GET endpoint provides a list of all attachments of the + * statement with given statementId. + * + * @param statmentId Statement Identifier + * + * @throws NotFoundException if statement could not be found. + * @return List containing all Attachments as AttatchmentModel + */ + @Secured({ UserRoles.SPA_ACCESS }) + @GetMapping(value = "/statements/{statementId}/attachments") + public List<AttachmentModel> getAttachments(@PathVariable Long statementId) { + Optional<List<AttachmentModel>> attachments = statementService.getStatementAttachments(statementId); + if (attachments.isPresent()) { + return attachments.get(); + } - /** - * Attachment GET endpoint provides the model of the requested Attachment by - * statementId and attachmentId. - * - * @param statmentId Statement Identifier - * @param attachmentId Attachment Identifier - * - * @return Requested AttachmentModel if successful. - * @throws NotFoundException if statement could not be found. - */ - @Secured({ UserRoles.SPA_ACCESS }) - @GetMapping(value = "/statements/{statementId}/attachments/{attachmentId}") - public AttachmentModel getAttachementDetails(@PathVariable Long statementId, @PathVariable Long attachmentId) { - Optional<AttachmentModel> attachment = statementService.getStatementAttachment(statementId, attachmentId); - if (attachment.isPresent()) { - return attachment.get(); - } - throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); - } + throw (new NotFoundException(Constants.STATEMENT_WITH_ID_NOT_FOUND)); + } - /** - * Attachment GET endpoint provides the file of the requested Attachment by - * statementId and attachmentId. - * - * @param statmentId Statement Identifier - * @param attachmentId Attachment Identifier - * - * @return Requested File Response if successful. - * @throws NotFoundException if statement could not be found. - * @throws ForbiddenException if provided token does not include fulfill - * access requirements. - */ - @GetMapping(value = "/statements/{statementId}/attachments/{attachmentId}/file") - public ResponseEntity<Object> getAttachementFile(@PathVariable Long statementId, @PathVariable Long attachmentId, - @RequestParam("accessToken") String token) { - if (!sessionService.hasRoles(Arrays.asList(UserRoles.SPA_ACCESS), token)) { - throw new ForbiddenException(); - } - Optional<AttachmentFile> attachmentFile = statementService.getStatementAttachmentFile(statementId, - attachmentId); - if (!attachmentFile.isPresent()) { - throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); - } - AttachmentFile file = attachmentFile.get(); - return ResponseEntity.ok().contentLength(file.getLength()).contentType(MediaType.valueOf(file.getType())) - .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"") - .body(new InputStreamResource(file.getRessource())); - } + /** + * Attachment GET endpoint provides the model of the requested Attachment by + * statementId and attachmentId. + * + * @param statmentId Statement Identifier + * @param attachmentId Attachment Identifier + * + * @return Requested AttachmentModel if successful. + * @throws NotFoundException if statement could not be found. + */ + @Secured({ UserRoles.SPA_ACCESS }) + @GetMapping(value = "/statements/{statementId}/attachments/{attachmentId}") + public AttachmentModel getAttachementDetails(@PathVariable Long statementId, @PathVariable Long attachmentId) { + Optional<AttachmentModel> attachment = statementService.getStatementAttachment(statementId, attachmentId); + if (attachment.isPresent()) { + return attachment.get(); + } + throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); + } - /** - * Attachment DELETE endpoint deletes the requested Attachment by statementId - * and attachmentId. - * - * @param statmentId Statement Identifier - * @param attachmentId Attachment Identifier - * - * @return OK_NO_CONTENT if successful. - * @throws NotFoundException if attachment could not be found. - */ - @Secured({ UserRoles.SPA_ACCESS }) - @DeleteMapping(value = "/statements/{statementId}/attachments/{attachmentId}") - public ResponseEntity<Object> deleteAttachement(@PathVariable Long statementId, @PathVariable Long attachmentId) { - Optional<Boolean> oDeleted = statementService.deleteStatementAttachments(statementId, attachmentId); - if (oDeleted.isPresent()) { - if (oDeleted.get()) { - return Constants.RESPONSE_OK_NO_CONTENT; - } else { - // TBD case, when request could not be processed. Maybe it is not allowed to - // delete after statement status > initial. - return Constants.RESPONSE_SERVICE_NOT_AVAILABLE; - } - } - throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); - } + /** + * Attachment GET endpoint provides the file of the requested Attachment by + * statementId and attachmentId. + * + * @param statmentId Statement Identifier + * @param attachmentId Attachment Identifier + * + * @return Requested File Response if successful. + * @throws NotFoundException if statement could not be found. + * @throws ForbiddenException if provided token does not include fulfill access + * requirements. + */ + @GetMapping(value = "/statements/{statementId}/attachments/{attachmentId}/file") + public ResponseEntity<Object> getAttachementFile(@PathVariable Long statementId, @PathVariable Long attachmentId, + @RequestParam("accessToken") String token) { + if (!sessionService.hasRoles(Arrays.asList(UserRoles.SPA_ACCESS), token)) { + throw new ForbiddenException(); + } + Optional<AttachmentFile> attachmentFile = statementService.getStatementAttachmentFile(statementId, + attachmentId); + if (!attachmentFile.isPresent()) { + throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); + } + AttachmentFile file = attachmentFile.get(); + return ResponseEntity.ok().contentLength(file.getLength()).contentType(MediaType.valueOf(file.getType())) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getName() + "\"") + .body(new InputStreamResource(file.getRessource())); + } - /** - * Attachment POST endpoint creates a new attachment for the specified Statement - * with the provided file content. - * - * @param statementId Statement Identifier - * @param files list of uploaded files - * - * @throws BadRequestException if provided attachment data is invalid - * @throws NotFoundException if statement could not be found. - * @return AttachmentModel of new created Attachment if successful. - */ - @Secured({ UserRoles.SPA_ACCESS }) - @PostMapping(value = "/statements/{statementId}/attachments") - public AttachmentModel createAttachement(@PathVariable Long statementId, - @RequestParam(value = "attachment", required = true) List<MultipartFile> files) { - if (files.isEmpty()) { - throw (new BadRequestException(Constants.NO_ATTACHMENT_FILE_SPECIFIED)); - } - if (files.size() > 1) { - throw (new BadRequestException(Constants.MORE_THAN_ONE_ATTACHMENT_FILE)); - } - MultipartFile file = files.get(0); - InputStream is; - try { - is = file.getInputStream(); - } catch (IOException e) { - log.log(Level.WARNING, "Attachment Upload - IOException: " + e.getMessage() + " - " + e.getStackTrace()); - throw (new BadRequestException(e.getMessage())); - } - long size = file.getSize(); - Optional<Long> attachmentId = statementService.createStatementAttachment(statementId, - file.getOriginalFilename(), file.getContentType(), is, file.getSize()); - if (attachmentId.isPresent()) { - Optional<AttachmentModel> oAttachment = statementService.getStatementAttachment(statementId, - attachmentId.get()); - if (oAttachment.isPresent()) { - return oAttachment.get(); - } - throw (new NotFoundException( - "Attachment successfully uploaded, but now not found in attachment repository.")); - } - throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); - } + /** + * Attachment DELETE endpoint deletes the requested Attachment by statementId + * and attachmentId. + * + * @param statmentId Statement Identifier + * @param attachmentId Attachment Identifier + * + * @return OK_NO_CONTENT if successful. + * @throws NotFoundException if attachment could not be found. + */ + @Secured({ UserRoles.SPA_ACCESS }) + @DeleteMapping(value = "/statements/{statementId}/attachments/{attachmentId}") + public ResponseEntity<Object> deleteAttachement(@PathVariable Long statementId, @PathVariable Long attachmentId) { + Optional<Boolean> oDeleted = statementService.deleteStatementAttachments(statementId, attachmentId); + if (oDeleted.isPresent()) { + if (Boolean.TRUE.equals(oDeleted.get())) { + return Constants.RESPONSE_OK_NO_CONTENT; + } else { + // TBD case, when request could not be processed. Maybe it is not allowed to + // delete after statement status > initial. + return Constants.RESPONSE_SERVICE_NOT_AVAILABLE; + } + } + throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); + } + + /** + * Attachment POST endpoint creates a new attachment for the specified Statement + * with the provided file content. + * + * @param statementId Statement Identifier + * @param files list of uploaded files + * + * @throws BadRequestException if provided attachment data is invalid + * @throws NotFoundException if statement could not be found. + * @return AttachmentModel of new created Attachment if successful. + */ + @Secured({ UserRoles.SPA_ACCESS }) + @PostMapping(value = "/statements/{statementId}/attachments") + public AttachmentModel createAttachement(@PathVariable Long statementId, + @RequestParam(value = "attachment", required = true) List<MultipartFile> files) { + if (files.isEmpty()) { + throw (new BadRequestException(Constants.NO_ATTACHMENT_FILE_SPECIFIED)); + } + if (files.size() > 1) { + throw (new BadRequestException(Constants.MORE_THAN_ONE_ATTACHMENT_FILE)); + } + MultipartFile file = files.get(0); + InputStream is; + try { + is = file.getInputStream(); + } catch (IOException e) { + log.log(Level.WARNING, "Attachment Upload - IOException: " + e.getMessage() + " - " + e.getStackTrace()); + throw (new BadRequestException(e.getMessage())); + } + Optional<Long> attachmentId = statementService.createStatementAttachment(statementId, + file.getOriginalFilename(), file.getContentType(), is, file.getSize()); + if (attachmentId.isPresent()) { + Optional<AttachmentModel> oAttachment = statementService.getStatementAttachment(statementId, + attachmentId.get()); + if (oAttachment.isPresent()) { + return oAttachment.get(); + } + throw (new NotFoundException( + "Attachment successfully uploaded, but now not found in attachment repository.")); + } + throw (new NotFoundException(Constants.ATTACHMENT_OF_STATEMENT_WITH_ID_NOT_FOUND)); + } } \ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessController.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessController.java index 79cfc77..3534836 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessController.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessController.java
@@ -47,7 +47,14 @@ @RestController public class StatementProcessController { - @Autowired + private static final String INVALID_REQUEST_PARAMETERS = "Invalid request parameters."; + private static final String STATEMENT_DOES_NOT_EXIST = "Statement does not exist or currently no open user task with taskId for this available."; + private static final String NOT_AUTHORIZED_TO_CLAIM_TASK = "Not authorized to claim task."; + private static final String NOT_AUTHORIZED_TO_GET_TASKS = "Not authorized to get tasks."; + private static final String NOT_AUTHORIZED_TO_GET_HISTORY = "Not authorized to get history."; + private static final String NOT_AUTHORIZED_TO_UNCLAIM_TASK = "Not authorized to unclaim task."; + private static final String NOT_AUTHORIZED_TO_COMPLETE_TASK = "Not authorized to complete task."; + @Autowired private StatementProcessService statementProcessService; /** @@ -74,7 +81,7 @@ throw new InternalServerErrorException("Error occurred processing the current statement task list request.", e); } catch (ForbiddenServiceException e) { - throw new ForbiddenException("Not authorized to claim task.", e); + throw new ForbiddenException(NOT_AUTHORIZED_TO_GET_TASKS, e); } } @@ -101,7 +108,7 @@ } catch (InternalErrorServiceException e) { throw new InternalServerErrorException("Error occurred processing the statement history list request.", e); } catch (ForbiddenServiceException e) { - throw new ForbiddenException("Not authorized to claim task.", e); + throw new ForbiddenException(NOT_AUTHORIZED_TO_GET_HISTORY, e); } } @@ -127,14 +134,14 @@ return task.get(); } else { throw new NotFoundException( - "Statement does not exist or currently no open user task with taskId for this available."); + STATEMENT_DOES_NOT_EXIST); } } catch (InternalErrorServiceException e) { throw new InternalServerErrorException("Error occurred processing the statement task claim request.", e); } catch (ForbiddenServiceException e) { - throw new ForbiddenException("Not authorized to claim task.", e); + throw new ForbiddenException(NOT_AUTHORIZED_TO_CLAIM_TASK, e); } catch (BadRequestServiceException e) { - throw new BadRequestException("Invalid request parameters.", e); + throw new BadRequestException(INVALID_REQUEST_PARAMETERS, e); } } @@ -160,14 +167,14 @@ return task.get(); } else { throw new NotFoundException( - "Statement does not exist or currently no open user task with taskId for this available."); + STATEMENT_DOES_NOT_EXIST); } } catch (InternalErrorServiceException e) { throw new InternalServerErrorException("Error occurred processing the statement task unclaim request.", e); } catch (ForbiddenServiceException e) { - throw new ForbiddenException("Not authorized to claim task.", e); + throw new ForbiddenException(NOT_AUTHORIZED_TO_UNCLAIM_TASK, e); } catch (BadRequestServiceException e) { - throw new BadRequestException("Invalid request parameters.", e); + throw new BadRequestException(INVALID_REQUEST_PARAMETERS, e); } } @@ -193,21 +200,21 @@ Optional<Boolean> task = statementProcessService.completeStatementTask(statementId, taskId, completeTaskVariables); if (task.isPresent()) { - if (task.get()) { + if (Boolean.TRUE.equals(task.get())) { return ResponseEntity.status(204).build(); } else { return ResponseEntity.status(400).build(); } } else { throw new NotFoundException( - "Statement does not exist or currently no open user task with taskId for this available."); + STATEMENT_DOES_NOT_EXIST); } } catch (BadRequestServiceException e) { - throw new BadRequestException("Invalid request parameters.", e); + throw new BadRequestException(INVALID_REQUEST_PARAMETERS, e); } catch (InternalErrorServiceException e) { throw new InternalServerErrorException("Error occurred processing the statement task complete request.", e); } catch (ForbiddenServiceException e) { - throw new ForbiddenException("Not authorized to claim task.", e); + throw new ForbiddenException(NOT_AUTHORIZED_TO_COMPLETE_TASK, e); } }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactAddressModel.java similarity index 66% copy from src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java copy to src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactAddressModel.java index d0b850b..1b446f8 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactAddressModel.java
@@ -12,25 +12,19 @@ * SPDX-License-Identifier: EPL-2.0 ******************************************************************************* */ -package org.eclipse.openk.statementpublicaffairs.config.auth; +package org.eclipse.openk.statementpublicaffairs.model; import lombok.Data; -/** - * User details. - * - * @author Tobias Stummer - * - */ @Data -public class UserDetails { - - private String firstName; - - private String lastName; - - private String name; - - private String userName; +public class CompanyContactAddressModel { + + private Boolean isMainAddress; + private String addressId; + private String houseNumber; + private String postCode; + private String street; + private String community; + private String communitySuffix; }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactBlockModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactBlockModel.java new file mode 100644 index 0000000..8cedf89 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactBlockModel.java
@@ -0,0 +1,22 @@ +package org.eclipse.openk.statementpublicaffairs.model; + +import lombok.Data; + +@Data +public class CompanyContactBlockModel { + + private String company; + private String department; + private String salution; + private String title; + private String firstName; + private String lastName; + + private String email; + private String street; + private String houseNumber; + private String postCode; + private String community; + private String communitySuffix; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactModel.java similarity index 62% copy from src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java copy to src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactModel.java index d0b850b..bd31c1b 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyContactModel.java
@@ -12,25 +12,21 @@ * SPDX-License-Identifier: EPL-2.0 ******************************************************************************* */ -package org.eclipse.openk.statementpublicaffairs.config.auth; +package org.eclipse.openk.statementpublicaffairs.model; + +import java.util.List; import lombok.Data; -/** - * User details. - * - * @author Tobias Stummer - * - */ @Data -public class UserDetails { - - private String firstName; - - private String lastName; - - private String name; - - private String userName; +public class CompanyContactModel { + private String contactType; + private String personType; + private String firstName; + private String lastName; + private String salutation; + private String title; + private String email; + private List<CompanyContactAddressModel> addresses; }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyModel.java new file mode 100644 index 0000000..22ebfc2 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/CompanyModel.java
@@ -0,0 +1,14 @@ +package org.eclipse.openk.statementpublicaffairs.model; + +import java.util.List; + +import lombok.Data; + +@Data +public class CompanyModel { + private String name; + private String type; + private String hrNumber; + private List<CompanyContactModel> contacts; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/UserDetails.java similarity index 92% rename from src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java rename to src/main/java/org/eclipse/openk/statementpublicaffairs/model/UserDetails.java index d0b850b..982c9a2 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/UserDetails.java
@@ -12,7 +12,7 @@ * SPDX-License-Identifier: EPL-2.0 ******************************************************************************* */ -package org.eclipse.openk.statementpublicaffairs.config.auth; +package org.eclipse.openk.statementpublicaffairs.model; import lombok.Data;
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiAddressModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiAddressModel.java new file mode 100644 index 0000000..f992eed --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiAddressModel.java
@@ -0,0 +1,25 @@ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import lombok.Data; + +@Data +public class ContactApiAddressModel { + + private String id; + private String contactId; + private Boolean isMainAddress; + private String postcode; + private String community; + private String communitySuffix; + private String street; + private String housenumber; + private String wgs84Zone; + private String latitude; + private String longitude; + private String urlMap; + private String note; + private String addressTypeId; + private String addressTypeType; + private String addressTypeDescription; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiCompanyContactPersonModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiCompanyContactPersonModel.java new file mode 100644 index 0000000..48da447 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiCompanyContactPersonModel.java
@@ -0,0 +1,38 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import lombok.Data; + +@Data +public class ContactApiCompanyContactPersonModel { + private String companyContactId; + private String companyHrNumber; + private String companyName; + private String companyType; + private Boolean contactAnonymized; + private String contactId; + private String contactNote; + private String contactType; + private String email; + private String firstName; + private String lastName; + private String personType; + private String personTypeId; + private String salutationId; + private String salutationType; + private String title; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiCompanyDetailsModel.java similarity index 64% copy from src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java copy to src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiCompanyDetailsModel.java index d0b850b..ff929f9 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiCompanyDetailsModel.java
@@ -12,25 +12,19 @@ * SPDX-License-Identifier: EPL-2.0 ******************************************************************************* */ -package org.eclipse.openk.statementpublicaffairs.config.auth; +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; import lombok.Data; -/** - * User details. - * - * @author Tobias Stummer - * - */ @Data -public class UserDetails { - - private String firstName; - - private String lastName; - - private String name; - - private String userName; +public class ContactApiCompanyDetailsModel { + + private String companyName; + private String companyType; + private Boolean contactAnonymized; + private String contactId; + private String contactNote; + private String contactType; + private String hrNumber; }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiContactDetailsModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiContactDetailsModel.java new file mode 100644 index 0000000..6156a75 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiContactDetailsModel.java
@@ -0,0 +1,42 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import lombok.Data; + +@Data +public class ContactApiContactDetailsModel { + + private Boolean anonymized; + private String companyId; + private String companyName; + private String companyType; + private String contactType; + private String department; + private String email; + private String firstName; + private Long fkContactId; + private Long id; + private String lastName; + private String mainAddress; + private String name; + private String note; + private String personType; + private String personTypeUuid; + private String salutationType; + private String salutationUuid; + private String searchfield; + private String uuid; +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiDetailedContact.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiDetailedContact.java new file mode 100644 index 0000000..e3505c2 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiDetailedContact.java
@@ -0,0 +1,31 @@ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import java.util.UUID; + +import lombok.Data; + +@Data +public class ContactApiDetailedContact { + + private Long fkContactId; + private Long id; + private String uuid; + private String name; + private String contactType; + private String companyName; + private String companyType; + private String companyId; + private String salutationUuid; + private String personTypeUuid; + private String firstName; + private String lastName; + private String department; + private String note; + private String salutationType; + private String personType; + private String mainAddress; + private String email; + private String searchfield; + private Boolean anonymized; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiExternalPersonModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiExternalPersonModel.java new file mode 100644 index 0000000..d471f85 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiExternalPersonModel.java
@@ -0,0 +1,34 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import lombok.Data; + +@Data +public class ContactApiExternalPersonModel { + + private Boolean contactAnonymized; + private String contactId; + private String contactNote; + private String contactType; + private String firstName; + private String lastName; + private String personType; + private String personTypeId; + private String salutationId; + private String salutationType; + private String title; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagableModel.java similarity index 68% copy from src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java copy to src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagableModel.java index d0b850b..b9760ad 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagableModel.java
@@ -12,25 +12,17 @@ * SPDX-License-Identifier: EPL-2.0 ******************************************************************************* */ -package org.eclipse.openk.statementpublicaffairs.config.auth; +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; import lombok.Data; -/** - * User details. - * - * @author Tobias Stummer - * - */ @Data -public class UserDetails { - - private String firstName; - - private String lastName; - - private String name; - - private String userName; +public class ContactApiPagableModel { + private Long offset; + private Long pageNumber; + private Long pageSize; + private Boolean paged; + private ContactApiSortModel sort; + private Boolean unpaged; }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedCompanyContactPersonModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedCompanyContactPersonModel.java new file mode 100644 index 0000000..70ccf83 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedCompanyContactPersonModel.java
@@ -0,0 +1,35 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import java.util.List; + +import lombok.Data; + +@Data +public class ContactApiPagedCompanyContactPersonModel { + private List<ContactApiCompanyContactPersonModel> content; + private Boolean empty; + private Boolean first; + private Boolean last; + private Long number; + private Long numberOfElements; + private ContactApiPagableModel pageable; + private Long size; + private ContactApiSortModel sort; + private Long totalElements; + private Long totalPages; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedCompanyDetailsModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedCompanyDetailsModel.java new file mode 100644 index 0000000..98215eb --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedCompanyDetailsModel.java
@@ -0,0 +1,36 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import java.util.List; + +import lombok.Data; + +@Data +public class ContactApiPagedCompanyDetailsModel { + + private List<ContactApiCompanyDetailsModel> content; + private Boolean empty; + private Boolean first; + private Boolean last; + private Long number; + private Long numberOfElements; + private ContactApiPagableModel pageable; + private Long size; + private ContactApiSortModel sort; + private Long totalElements; + private Long totalPages; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedDetailedContact.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedDetailedContact.java new file mode 100644 index 0000000..5c770e6 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedDetailedContact.java
@@ -0,0 +1,21 @@ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import java.util.List; + +import lombok.Data; + +@Data +public class ContactApiPagedDetailedContact { + private List<ContactApiDetailedContact> content; + private Boolean empty; + private Boolean first; + private Boolean last; + private Long number; + private Long numberOfElements; + private ContactApiPagableModel pageable; + private Long size; + private ContactApiSortModel sort; + private Long totalElements; + private Long totalPages; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedExternalPersonModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedExternalPersonModel.java new file mode 100644 index 0000000..a8f95f5 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiPagedExternalPersonModel.java
@@ -0,0 +1,36 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; + +import java.util.List; + +import lombok.Data; + +@Data +public class ContactApiPagedExternalPersonModel { + + private List<ContactApiExternalPersonModel> content; + private Boolean empty; + private Boolean first; + private Boolean last; + private Long number; + private Long numberOfElements; + private ContactApiPagableModel pageable; + private Long size; + private ContactApiSortModel sort; + private Long totalElements; + private Long totalPages; + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiSortModel.java similarity index 68% copy from src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java copy to src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiSortModel.java index d0b850b..94c272d 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/config/auth/UserDetails.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/model/contactdatabase/ContactApiSortModel.java
@@ -12,25 +12,15 @@ * SPDX-License-Identifier: EPL-2.0 ******************************************************************************* */ -package org.eclipse.openk.statementpublicaffairs.config.auth; +package org.eclipse.openk.statementpublicaffairs.model.contactdatabase; import lombok.Data; -/** - * User details. - * - * @author Tobias Stummer - * - */ @Data -public class UserDetails { - - private String firstName; - - private String lastName; - - private String name; - - private String userName; +public class ContactApiSortModel { + + private Boolean empty; + private Boolean sorted; + private Boolean unsorted; }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/ContactService.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/ContactService.java new file mode 100644 index 0000000..5647070 --- /dev/null +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/ContactService.java
@@ -0,0 +1,156 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.service; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.eclipse.openk.statementpublicaffairs.api.ContactDatabaseApi; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; +import org.eclipse.openk.statementpublicaffairs.model.CompanyContactAddressModel; +import org.eclipse.openk.statementpublicaffairs.model.CompanyContactModel; +import org.eclipse.openk.statementpublicaffairs.model.CompanyModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiAddressModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiCompanyContactPersonModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiCompanyDetailsModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiDetailedContact; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiPagedDetailedContact; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import feign.FeignException; + +@Service +public class ContactService { + + private static final String ERROR_OCCURED_ACCESSING_THE_CONTACT_DATABASE = "Error occured accessing the contactDatabase"; + + private static final String DEFAULT_NO_COMPANY_ID = "__default_company"; + + @Autowired + private ContactDatabaseApi contactDatabaseApi; + + @Autowired + private SessionService sessionService; + + @Value("${contactDatabase.technical-username}") + private String username; + + @Value("${contactDatabase.technical-userpassword}") + private String password; + + + /** + * Find company contacts with provided search string. + * + * @param searchString search string + * @return List of companies and their matching contacts if successful. + * @throws InternalErrorServiceException when ContactDatabase is not accessible + * or error occurred requesting the + * contacts data. + */ + public Optional<List<CompanyModel>> searchContacts(String searchString) throws InternalErrorServiceException { + String token = sessionService.getToken(username, password); + ContactApiPagedDetailedContact detailedContacts; + try { + detailedContacts = contactDatabaseApi.searchContacts(token, "1CP", searchString); + } catch (FeignException e) { + throw new InternalErrorServiceException(ERROR_OCCURED_ACCESSING_THE_CONTACT_DATABASE, e); + } + Map<String, CompanyModel> ccms = new HashMap<>(); + for (ContactApiDetailedContact detailedContact : detailedContacts.getContent()) { + String cId = detailedContact.getCompanyId(); + if (cId == null) { + cId = DEFAULT_NO_COMPANY_ID; + } + if (!ccms.containsKey(cId)) { + ccms.put(cId, createCompanyContactModel(token, cId)); + } + + CompanyModel company = ccms.get(cId); + + ContactApiCompanyContactPersonModel contact; + + try { + contact = contactDatabaseApi.getContactPerson(token, detailedContact.getUuid()); + } catch (FeignException e) { + throw new InternalErrorServiceException(ERROR_OCCURED_ACCESSING_THE_CONTACT_DATABASE, e); + } + + List<ContactApiAddressModel> addresses; + try { + addresses = contactDatabaseApi.getContactAddresses(token, contact.getContactId()); + } catch (FeignException e) { + throw new InternalErrorServiceException(ERROR_OCCURED_ACCESSING_THE_CONTACT_DATABASE, e); + } + + List<CompanyContactAddressModel> ccams = new ArrayList<>(); + + for (ContactApiAddressModel address : addresses) { + CompanyContactAddressModel cam = new CompanyContactAddressModel(); + cam.setAddressId(address.getId()); + cam.setHouseNumber(address.getHousenumber()); + cam.setCommunity(address.getCommunity()); + cam.setCommunitySuffix(address.getCommunitySuffix()); + cam.setStreet(address.getStreet()); + cam.setPostCode(address.getPostcode()); + cam.setIsMainAddress(address.getIsMainAddress()); + ccams.add(cam); + } + + CompanyContactModel ccm = new CompanyContactModel(); + ccm.setContactType(contact.getContactType()); + ccm.setPersonType(contact.getPersonType()); + ccm.setFirstName(contact.getFirstName()); + ccm.setLastName(contact.getLastName()); + ccm.setSalutation(contact.getSalutationType()); + ccm.setTitle(contact.getTitle()); + ccm.setEmail(contact.getEmail()); + ccm.setAddresses(ccams); + company.getContacts().add(ccm); + } + return Optional.of(new ArrayList<CompanyModel>(ccms.values())); + + } + + private CompanyModel createCompanyContactModel(String token, String cId) throws InternalErrorServiceException { + CompanyModel cm = new CompanyModel(); + if (DEFAULT_NO_COMPANY_ID.equals(cId)) { + cm.setName(""); + cm.setType(""); + cm.setHrNumber(""); + cm.setContacts(new ArrayList<>()); + } else { + ContactApiCompanyDetailsModel companyDetails; + try { + companyDetails = contactDatabaseApi.getCompany(token, cId); + } catch (FeignException e) { + throw new InternalErrorServiceException(ERROR_OCCURED_ACCESSING_THE_CONTACT_DATABASE, e); + } + cm.setName(companyDetails.getCompanyName()); + cm.setType(companyDetails.getCompanyType()); + cm.setHrNumber(companyDetails.getHrNumber()); + cm.setContacts(new ArrayList<>()); + } + return cm; + + } + + +}
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/SessionService.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/SessionService.java index 466c810..05c09a4 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/SessionService.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/SessionService.java
@@ -18,7 +18,11 @@ import java.util.List; import org.eclipse.openk.statementpublicaffairs.api.AuthNAuthApi; -import org.eclipse.openk.statementpublicaffairs.config.auth.UserDetails; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalServerErrorException; +import org.eclipse.openk.statementpublicaffairs.model.JwtToken; +import org.eclipse.openk.statementpublicaffairs.model.LoginCredentials; +import org.eclipse.openk.statementpublicaffairs.model.UserDetails; import org.keycloak.RSATokenVerifier; import org.keycloak.common.VerificationException; import org.keycloak.representations.AccessToken; @@ -31,6 +35,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import feign.FeignException; import feign.Response; import lombok.extern.java.Log; @@ -108,4 +113,13 @@ return roles.containsAll(requiredRoles); } + public String getToken(String username, String password) throws InternalErrorServiceException{ + JwtToken token; + try { + token = authNAuthApi.login(new LoginCredentials(username, password)); + } catch (FeignException e) { + throw new InternalErrorServiceException("Error occurred accessing the authNAuthApi login.", e); + } + return token.getAccessToken(); + } }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementOverviewService.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementOverviewService.java index 9366852..7c474ac 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementOverviewService.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementOverviewService.java
@@ -60,11 +60,10 @@ model.setFinished(statement.getFinished()); model.setId(statement.getId()); if (statement.getTaskId() != null) { - model.setTaskId(statement.getTaskId().toString()); + model.setBusinessKey(statement.getTaskId().toString()); } - TypeConversion.dateStringOfLocalDate(statement.getDueDate()).ifPresent(date -> model.setDueDate(date)); - TypeConversion.dateStringOfLocalDate(statement.getReceiptDate()) - .ifPresent(date -> model.setReceiptDate(date)); + TypeConversion.dateStringOfLocalDate(statement.getDueDate()).ifPresent(model::setDueDate); + TypeConversion.dateStringOfLocalDate(statement.getReceiptDate()).ifPresent(model::setReceiptDate); model.setTitle(statement.getTitle()); model.setCity(statement.getCity()); model.setDistrict(statement.getDistrict()); @@ -104,11 +103,10 @@ model.setFinished(statement.getFinished()); model.setId(statement.getId()); if (statement.getTaskId() != null) { - model.setTaskId(statement.getTaskId().toString()); + model.setBusinessKey(statement.getTaskId().toString()); } - TypeConversion.dateStringOfLocalDate(statement.getDueDate()).ifPresent(date -> model.setDueDate(date)); - TypeConversion.dateStringOfLocalDate(statement.getReceiptDate()) - .ifPresent(date -> model.setReceiptDate(date)); + TypeConversion.dateStringOfLocalDate(statement.getDueDate()).ifPresent(model::setDueDate); + TypeConversion.dateStringOfLocalDate(statement.getReceiptDate()).ifPresent(model::setReceiptDate); model.setTitle(statement.getTitle()); model.setDistrict(statement.getDistrict()); model.setCity(statement.getCity());
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessService.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessService.java index bb280ef..96a1d6c 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessService.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessService.java
@@ -30,15 +30,15 @@ import java.util.stream.Collectors; import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestServiceException; -import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; import org.eclipse.openk.statementpublicaffairs.exceptions.ForbiddenServiceException; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskModel; import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskResultModel; +import org.eclipse.openk.statementpublicaffairs.model.ProcessActivityHistoryModel; import org.eclipse.openk.statementpublicaffairs.model.ProcessDefinitionModel; import org.eclipse.openk.statementpublicaffairs.model.WorkflowTaskModel; import org.eclipse.openk.statementpublicaffairs.service.worker.IExternalTaskWorker; import org.eclipse.openk.statementpublicaffairs.util.TypeConversion; -import org.eclipse.openk.statementpublicaffairs.model.ProcessActivityHistoryModel; import org.eclipse.openk.statementpublicaffairs.viewmodel.ProcessActivityHistoryViewModel; import org.eclipse.openk.statementpublicaffairs.viewmodel.ProcessHistoryModel; import org.eclipse.openk.statementpublicaffairs.viewmodel.StatementDetailsModel; @@ -61,6 +61,8 @@ @Service public class StatementProcessService { + private static final String STATEMENT_IS_BOUND_NOT_EXISTENT_WORKFLOW = "Requested statement is bound to a not existent workflow process."; + @Autowired private WorkflowService workflowService; @@ -96,7 +98,7 @@ if (!statementModel.isPresent()) { return Optional.empty(); } - String businessKey = statementModel.get().getTaskId(); + String businessKey = statementModel.get().getBusinessKey(); if (businessKey == null) { throw new InternalErrorServiceException("Requested statement is not bound to a workflow process."); } @@ -104,7 +106,7 @@ Optional<List<WorkflowTaskModel>> workflowTaskModels = workflowService .getCurrentTasksOfProcessBusinessKey(businessKey); if (!workflowTaskModels.isPresent()) { - throw new InternalErrorServiceException("Requested statement is bound to a not existent workflow process."); + throw new InternalErrorServiceException(STATEMENT_IS_BOUND_NOT_EXISTENT_WORKFLOW); } for (WorkflowTaskModel workflowTaskModel : workflowTaskModels.get()) { authorizationService.authorize(workflowTaskModel.getTaskDefinitionKey(), "READ_WORKFLOW_TASK"); @@ -145,14 +147,14 @@ ProcessHistoryModel history = new ProcessHistoryModel(); - String businessKey = statementModel.get().getTaskId(); + String businessKey = statementModel.get().getBusinessKey(); if (businessKey == null) { throw new InternalErrorServiceException("Requested statement is not bound to a workflow process."); } Optional<ProcessDefinitionModel> oProcessDefinition = workflowService.getProcessDefinition(businessKey); if (!oProcessDefinition.isPresent()) { - throw new InternalErrorServiceException("Requested statement is bound to a not existent workflow process."); + throw new InternalErrorServiceException(STATEMENT_IS_BOUND_NOT_EXISTENT_WORKFLOW); } authorizationService.authorize("ANY", "READ_STATEMENT_PROCESS_HISTORY"); ProcessDefinitionModel pdm = oProcessDefinition.get(); @@ -162,7 +164,7 @@ Optional<List<ProcessActivityHistoryModel>> activityHistory = workflowService .getStatementProcessHistory(businessKey); if (!activityHistory.isPresent()) { - throw new InternalErrorServiceException("Requested statement is bound to a not existent workflow process."); + throw new InternalErrorServiceException(STATEMENT_IS_BOUND_NOT_EXISTENT_WORKFLOW); } List<ProcessActivityHistoryModel> finished = activityHistory.get().stream() .filter(activity -> activity.getStartTime() != null && activity.getEndTime() != null) @@ -191,18 +193,19 @@ viewmodel.setCompleteScope(model.getCompleteScope()); viewmodel.setDurationInMillis(model.getDurationInMillis()); if (model.getEndTime() != null) { - viewmodel.setEndTime(TypeConversion.camundaDateStringOfZDT(model.getEndTime()).get()); + TypeConversion.camundaDateStringOfZDT(model.getEndTime()).ifPresent(viewmodel::setEndTime); } viewmodel.setId(model.getId()); viewmodel.setProcessDefinitionId(model.getProcessDefinitionId()); viewmodel.setProcessDefinitionKey(model.getProcessDefinitionKey()); - viewmodel.setStartTime(TypeConversion.camundaDateStringOfZDT(model.getStartTime()).get()); + TypeConversion.camundaDateStringOfZDT(model.getStartTime()).ifPresent(viewmodel::setStartTime); viewmodel.setTenantId(model.getTenantId()); viewmodels.add(viewmodel); } return viewmodels; } + /** * Claim workflow process task with provided taskId of statement with provided * statementId. @@ -217,7 +220,7 @@ * statement task. * @throws ForbiddenServiceException if access is not authorised. * @throws BadRequestServiceException if workflow process task is already - * claimed + * claimed by another user */ public Optional<StatementTaskModel> claimStatementTask(Long statementId, String taskId) throws InternalErrorServiceException, ForbiddenServiceException, BadRequestServiceException { @@ -227,30 +230,43 @@ } for (StatementTaskModel task : currentTasks.get()) { if (task.getTaskId().contentEquals(taskId)) { - if (task.getAssignee() == null) { - authorizationService.authorize(task.getTaskDefinitionKey(), "CLAIM_WORKFLOW_TASK"); - Optional<WorkflowTaskModel> oWtm = workflowService.claimTask(taskId, userInfoService.getUserName()); - if (oWtm.isPresent()) { - WorkflowTaskModel workflowTaskModel = oWtm.get(); - StatementTaskModel statementTaskModel = new StatementTaskModel(); - statementTaskModel.setStatementId(statementId); - statementTaskModel.setProcessDefinitionKey(workflowTaskModel.getProcessDefinitionKey()); - statementTaskModel.setTaskDefinitionKey(workflowTaskModel.getTaskDefinitionKey()); - statementTaskModel.setTaskId(workflowTaskModel.getTaskId()); - statementTaskModel.setAssignee(workflowTaskModel.getAssignee()); - statementTaskModel.setRequiredVariables(workflowTaskModel.getRequiredVariables()); - return Optional.of(statementTaskModel); - } else { - throw new InternalErrorServiceException("Not able to get task after claim"); - } - } else { - throw new BadRequestServiceException("Tried to claim already claimed task"); - } + return claim(statementId, task); } } return Optional.empty(); } + private Optional<StatementTaskModel> claim(Long statementId, StatementTaskModel task) + throws ForbiddenServiceException, InternalErrorServiceException, BadRequestServiceException { + if (task.getAssignee() == null) { + authorizationService.authorize(task.getTaskDefinitionKey(), "CLAIM_WORKFLOW_TASK"); + Optional<WorkflowTaskModel> oWtm = workflowService.claimTask(task.getTaskId(), userInfoService.getUserName()); + if (oWtm.isPresent()) { + return Optional.of(statementTaskModelOfworkflowTaskModel(statementId, + oWtm.get())); + } else { + throw new InternalErrorServiceException("Not able to get task after claim"); + } + } else { + if (task.getAssignee().equals(userInfoService.getUserName())) { + return Optional.of(task); + } + throw new BadRequestServiceException("Tried to claim already claimed task"); + } + } + + private StatementTaskModel statementTaskModelOfworkflowTaskModel(Long statementId, + WorkflowTaskModel workflowTaskModel) { + StatementTaskModel statementTaskModel = new StatementTaskModel(); + statementTaskModel.setStatementId(statementId); + statementTaskModel.setProcessDefinitionKey(workflowTaskModel.getProcessDefinitionKey()); + statementTaskModel.setTaskDefinitionKey(workflowTaskModel.getTaskDefinitionKey()); + statementTaskModel.setTaskId(workflowTaskModel.getTaskId()); + statementTaskModel.setAssignee(workflowTaskModel.getAssignee()); + statementTaskModel.setRequiredVariables(workflowTaskModel.getRequiredVariables()); + return statementTaskModel; + } + /** * Unclaim workflow process task with provided taskId of statement with provided * statementId. @@ -278,15 +294,8 @@ authorizationService.authorize(task.getTaskDefinitionKey(), "UNCLAIM_WORKFLOW_TASK"); Optional<WorkflowTaskModel> oWtm = workflowService.unClaimTask(taskId); if (oWtm.isPresent()) { - WorkflowTaskModel workflowTaskModel = oWtm.get(); - StatementTaskModel statementTaskModel = new StatementTaskModel(); - statementTaskModel.setStatementId(statementId); - statementTaskModel.setProcessDefinitionKey(workflowTaskModel.getProcessDefinitionKey()); - statementTaskModel.setTaskDefinitionKey(workflowTaskModel.getTaskDefinitionKey()); - statementTaskModel.setTaskId(workflowTaskModel.getTaskId()); - statementTaskModel.setAssignee(workflowTaskModel.getAssignee()); - statementTaskModel.setRequiredVariables(workflowTaskModel.getRequiredVariables()); - return Optional.of(statementTaskModel); + return Optional.of(statementTaskModelOfworkflowTaskModel(statementId, + oWtm.get())); } else { throw new InternalErrorServiceException("Not able to get task after unclaim"); } @@ -330,8 +339,7 @@ if (task.getTaskId().contentEquals(taskId)) { if (task.getAssignee() != null) { authorizationService.authorize(task.getTaskDefinitionKey(), "COMPLETE_WORKFLOW_TASK"); - Optional<Boolean> completed = workflowService.completeTask(taskId, completeTaskVariables); - return completed; + return workflowService.completeTask(taskId, completeTaskVariables); } else { throw new BadRequestServiceException("Tried to complete not claimed task"); } @@ -351,7 +359,7 @@ */ public Optional<StatementDetailsModel> createStatement(StatementDetailsModel statement) throws InternalErrorServiceException, BadRequestServiceException { String businessKey = workflowService.startProcessLatestVersion(); - statement.setTaskId(businessKey); + statement.setBusinessKey(businessKey); try { return statementService.createStatement(statement); } catch (InternalErrorServiceException e) { @@ -361,6 +369,11 @@ } } + + + + + /** * Scheduled service task processing checks for current service tasks that can * be processed and completed by one of the workers that implement the @@ -378,8 +391,8 @@ public void checkAndHandleServiceTasks() throws InternalErrorServiceException, InterruptedException, ExecutionException { - String workerId = "myWorker"; - Set<String> topics = new HashSet<String>(); + String workerId = "workerId"; + Set<String> topics = new HashSet<>(); for (IExternalTaskWorker worker : workers) { topics.add(worker.getTopic()); } @@ -389,54 +402,10 @@ List<ExternalTaskModel> tasks = oTasks.get(); CountDownLatch cl = new CountDownLatch(tasks.size()); List<Future<Boolean>> taskResults = new ArrayList<>(); - ExecutorService executor = Executors.newFixedThreadPool(workers.size()); + for (ExternalTaskModel task : oTasks.get()) { - boolean found = false; - for (IExternalTaskWorker worker : workers) { - if (task.getTopicName().equals(worker.getTopic())) { - Future<Boolean> future = executor.submit(() -> { - try { - Optional<Boolean> res; - ExternalTaskResultModel result = worker.work(task); - // TODO handle exceptions for cases where you cannot tell the workflowService - // that you completed or failed. - // in these cases, the service should set a virual RedLight and maybe send a - // notification and retry the - // workflow messaging until stopped externally. - if (result.isSuccessful()) { - res = workflowService.completeExternalTask(task.getId(), task.getWorkerId(), - new HashMap<String, WorkflowTaskVariableModel>()); - } else { - res = workflowService.failureExternalTask(task.getId(), workerId, - result.getErrorMessage()); - } - if (res.isPresent()) { - cl.countDown(); - if (res.get()) { - return true; - } else { - return false; - } - } else { - cl.countDown(); - log.warning("finished task unsuccessful " + task.getTopicName()); - return false; - } - } catch (Exception e) { - cl.countDown(); - log.warning("exception task " + task.getTopicName() + " e - " + e.getMessage()); - return false; - } - }); - taskResults.add(future); - found = true; - break; - } - } - if (!found) { - cl.countDown(); - } + processServiceTask(workerId, cl, taskResults, executor, task); } cl.await(); for (Future<Boolean> task : taskResults) { @@ -445,4 +414,53 @@ } } + private void processServiceTask(String workerId, CountDownLatch cl, List<Future<Boolean>> taskResults, + ExecutorService executor, ExternalTaskModel task) { + boolean found = false; + for (IExternalTaskWorker worker : workers) { + if (task.getTopicName().equals(worker.getTopic())) { + processServiceTaskInstance(workerId, cl, taskResults, executor, task, worker); + found = true; + break; + } + } + if (!found) { + cl.countDown(); + } + } + + private void processServiceTaskInstance(String workerId, CountDownLatch cl, List<Future<Boolean>> taskResults, + ExecutorService executor, ExternalTaskModel task, IExternalTaskWorker worker) { + Future<Boolean> future = executor.submit(() -> { + try { + Optional<Boolean> res; + ExternalTaskResultModel result = worker.work(task); + // TODO handle exceptions for cases where you cannot tell the workflowService + // that you completed or failed. + // in these cases, the service should set a virual RedLight and maybe send a + // notification and retry the + // workflow messaging until stopped externally. + if (result.isSuccessful()) { + res = workflowService.completeExternalTask(task.getId(), task.getWorkerId(), + new HashMap<String, WorkflowTaskVariableModel>()); + } else { + res = workflowService.failureExternalTask(task.getId(), workerId, + result.getErrorMessage()); + } + cl.countDown(); + if (res.isPresent()) { + return Boolean.TRUE.equals(res.get()); + } else { + log.warning("finished task unsuccessful " + task.getTopicName()); + return false; + } + } catch (Exception e) { + cl.countDown(); + log.warning("exception task " + task.getTopicName() + " e - " + e.getMessage()); + return false; + } + }); + taskResults.add(future); + } + }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementService.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementService.java index 89bb9bd..b30fd5b 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementService.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/StatementService.java
@@ -79,12 +79,12 @@ if (statement.isPresent()) { TblStatement s = statement.get(); StatementDetailsModel model = new StatementDetailsModel(); - TypeConversion.dateStringOfLocalDate(s.getDueDate()).ifPresent(dueDate -> model.setDueDate(dueDate)); - TypeConversion.dateStringOfLocalDate(s.getReceiptDate()).ifPresent(date -> model.setReceiptDate(date)); + TypeConversion.dateStringOfLocalDate(s.getDueDate()).ifPresent(model::setDueDate); + TypeConversion.dateStringOfLocalDate(s.getReceiptDate()).ifPresent(model::setReceiptDate); model.setFinished(s.getFinished()); model.setId(s.getId()); model.setTitle(s.getTitle()); - TypeConversion.stringOfTaskId(s.getTaskId()).ifPresent(taskId -> model.setTaskId(taskId)); + TypeConversion.stringOfBusinessKey(s.getTaskId()).ifPresent(model::setBusinessKey); model.setCity(s.getCity()); model.setDistrict(s.getDistrict()); model.setTypeId(s.getStatementtype().getId()); @@ -115,7 +115,7 @@ Optional<TblStatement> statement = statementRepository.findById(statementId); if (statement.isPresent()) { TblStatement entity = statement.get(); - if (entity.getFinished() == true) { + if (Boolean.TRUE.equals(entity.getFinished())) { return Optional.of(false); } entity.setFinished(true); @@ -141,11 +141,10 @@ } TblStatement statement = new TblStatement(); statement.setTitle(newStatement.getTitle()); - TypeConversion.dateOfDateString(newStatement.getDueDate()).ifPresent(dueDate -> statement.setDueDate(dueDate)); - TypeConversion.dateOfDateString(newStatement.getReceiptDate()) - .ifPresent(date -> statement.setReceiptDate(date)); + TypeConversion.dateOfDateString(newStatement.getDueDate()).ifPresent(statement::setDueDate); + TypeConversion.dateOfDateString(newStatement.getReceiptDate()).ifPresent(statement::setReceiptDate); statement.setFinished(false); - TypeConversion.taskIdOfString(newStatement.getTaskId()).ifPresent(taskId -> statement.setTaskId(taskId)); + TypeConversion.businessKeyOfString(newStatement.getBusinessKey()).ifPresent(statement::setTaskId); statement.setCity(newStatement.getCity()); statement.setDistrict(newStatement.getDistrict()); @@ -167,13 +166,11 @@ throw new InternalErrorServiceException("Could not store new statement to the repository", e); } StatementDetailsModel createdModel = new StatementDetailsModel(); - TypeConversion.dateStringOfLocalDate(cStatement.getDueDate()) - .ifPresent(dueDate -> createdModel.setDueDate(dueDate)); - TypeConversion.dateStringOfLocalDate(cStatement.getReceiptDate()) - .ifPresent(date -> createdModel.setReceiptDate(date)); + TypeConversion.dateStringOfLocalDate(cStatement.getDueDate()).ifPresent(createdModel::setDueDate); + TypeConversion.dateStringOfLocalDate(cStatement.getReceiptDate()).ifPresent(createdModel::setReceiptDate); createdModel.setFinished(cStatement.getFinished()); createdModel.setId(cStatement.getId()); - TypeConversion.stringOfTaskId(cStatement.getTaskId()).ifPresent(taskId -> createdModel.setTaskId(taskId)); + TypeConversion.stringOfBusinessKey(cStatement.getTaskId()).ifPresent(createdModel::setBusinessKey); createdModel.setTitle(cStatement.getTitle()); createdModel.setCity(cStatement.getCity()); createdModel.setDistrict(cStatement.getDistrict()); @@ -235,6 +232,9 @@ byte[] data = new byte[(int) length]; try { int len = inputStream.read(data); + if (len != length) { + log.log(Level.WARNING, "Read input stream length differs from attachment meta data."); + } } catch (IOException e) { log.log(Level.WARNING, "Read input stream of attachment caused IOException: - " + e.getMessage() + " - " + e.getStackTrace()); @@ -294,12 +294,7 @@ for (TblAttachment attachment : oStatement.get().getAttachments()) { if (attachmentId == attachment.getId()) { attachmentRepository.deleteById(attachmentId); - // TODO: verify if really necessary. should be deleted. - if (attachmentRepository.existsById(attachmentId)) { - return Optional.of(true); - } else { - return Optional.of(false); - } + return Optional.of(attachmentRepository.existsById(attachmentId)); } } }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoService.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoService.java index 87c1378..93c125d 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoService.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoService.java
@@ -18,7 +18,7 @@ import java.util.Collection; import java.util.List; -import org.eclipse.openk.statementpublicaffairs.config.auth.UserDetails; +import org.eclipse.openk.statementpublicaffairs.model.UserDetails; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service;
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowService.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowService.java index dacd11e..9d1e5b9 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowService.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowService.java
@@ -28,6 +28,7 @@ import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestServiceException; import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskModel; +import org.eclipse.openk.statementpublicaffairs.model.ProcessActivityHistoryModel; import org.eclipse.openk.statementpublicaffairs.model.ProcessDefinitionModel; import org.eclipse.openk.statementpublicaffairs.model.WorkflowTaskModel; import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaClaimTaskRequestBody; @@ -45,7 +46,6 @@ import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaVariable; import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaVariablesRequestBody; import org.eclipse.openk.statementpublicaffairs.util.TypeConversion; -import org.eclipse.openk.statementpublicaffairs.model.ProcessActivityHistoryModel; import org.eclipse.openk.statementpublicaffairs.viewmodel.WorkflowTaskVariableModel; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -67,6 +67,10 @@ @Service public class WorkflowService { + private static final String COMPLETE_TASK = "Complete task "; + + private static final String RESPONSE_STATUS = " response status "; + private static final String REQUIRED_VARIABLE_PREFIX_INDICATOR = "_"; @Autowired @@ -80,6 +84,9 @@ @Value("${workflow.processDefinitionKey}") private String processDefinitionKey; + + @Value("${workflow.tenantId}") + private String tenantId; /** * Get basic auth header value. @@ -152,7 +159,7 @@ * instance from the workflow engine. */ public String startProcessLatestVersion() throws InternalErrorServiceException { - Optional<String> oBusinessKey = TypeConversion.stringOfTaskId(UUID.randomUUID()); + Optional<String> oBusinessKey = TypeConversion.stringOfBusinessKey(UUID.randomUUID()); if (!oBusinessKey.isPresent()) { throw new InternalErrorServiceException("Error when parsing businessKey"); } @@ -161,7 +168,7 @@ startReq.setBusinessKey(oBusinessKey.get()); CamundaProcessDefinitionStartRsp rsp; try { - rsp = camundaApi.startProcess(processDefinitionKey, "spa", getBasicAuth(), startReq); + rsp = camundaApi.startProcess(processDefinitionKey, tenantId, getBasicAuth(), startReq); } catch (FeignException e) { throw new InternalErrorServiceException( "Error accessing workflow engine api to start a new workflow process", e); @@ -202,26 +209,34 @@ } List<WorkflowTaskModel> tasks = new ArrayList<>(); for (CamundaTaskInstance cti : taskInstances) { - WorkflowTaskModel taskModel = new WorkflowTaskModel(); - requiredTaskVariables(cti.getId()).ifPresent(variables -> taskModel.setRequiredVariables(variables)); - taskModel.setTaskId(cti.getId()); - taskModel.setProcessInstanceId(cti.getProcessInstanceId()); - taskModel.setProcessDefinitionKey(processDefinitionKey); - taskModel.setAssignee(cti.getAssignee()); - taskModel.setTenantId(cti.getTenantId()); - taskModel.setTaskDefinitionKey(cti.getTaskDefinitionKey()); - taskModel.setSuspended(cti.getSuspended()); - taskModel.setOwner(cti.getOwner()); - taskModel.setName(cti.getName()); - taskModel.setDescription(cti.getDescription()); - TypeConversion.zDTOfCamundaDateString(cti.getDue()).ifPresent(date -> taskModel.setDue(date)); - TypeConversion.zDTOfCamundaDateString(cti.getCreated()).ifPresent(date -> taskModel.setCreated(date)); - taskModel.setFormKey(cti.getFormKey()); + String taskId = cti.getId(); + WorkflowTaskModel taskModel = workflowTaskModelOfCamundaTaskInstance(cti, taskId); tasks.add(taskModel); } return Optional.of(tasks); } + private WorkflowTaskModel workflowTaskModelOfCamundaTaskInstance(CamundaTaskInstance cti, String taskId) + throws InternalErrorServiceException { + WorkflowTaskModel taskModel = new WorkflowTaskModel(); + requiredTaskVariables(taskId).ifPresent(taskModel::setRequiredVariables); + taskModel.setTaskId(cti.getId()); + taskModel.setProcessInstanceId(cti.getProcessInstanceId()); + taskModel.setProcessDefinitionKey(processDefinitionKey); + taskModel.setAssignee(cti.getAssignee()); + taskModel.setTenantId(cti.getTenantId()); + taskModel.setTaskDefinitionKey(cti.getTaskDefinitionKey()); + taskModel.setSuspended(cti.getSuspended()); + taskModel.setOwner(cti.getOwner()); + taskModel.setName(cti.getName()); + taskModel.setDescription(cti.getDescription()); + TypeConversion.zDTOfCamundaDateString(cti.getDue()).ifPresent(taskModel::setDue); + TypeConversion.zDTOfCamundaDateString(cti.getCreated()).ifPresent(taskModel::setCreated); + taskModel.setFormKey(cti.getFormKey()); + return taskModel; + + } + /** * Get workflow task history of the workflow process identified by the provided * businessKey. @@ -266,8 +281,8 @@ model.setActivityType(step.getActivityType()); model.setActivityId(step.getActivityId()); model.setAssignee(step.getAssignee()); - TypeConversion.zDTOfCamundaDateString(step.getStartTime()).ifPresent(time -> model.setStartTime(time)); - TypeConversion.zDTOfCamundaDateString(step.getEndTime()).ifPresent(time -> model.setEndTime(time)); + TypeConversion.zDTOfCamundaDateString(step.getStartTime()).ifPresent(model::setStartTime); + TypeConversion.zDTOfCamundaDateString(step.getEndTime()).ifPresent(model::setEndTime); model.setDurationInMillis(step.getDurationInMillis()); model.setProcessDefinitionKey(step.getProcessDefinitionKey()); model.setProcessDefinitionId(step.getProcessDefinitionId()); @@ -290,7 +305,7 @@ * workflow engine */ private Optional<Map<String, String>> requiredTaskVariables(String taskId) throws InternalErrorServiceException { - Map<String, String> requiredVariables = new HashMap<String, String>(); + Map<String, String> requiredVariables = new HashMap<>(); Map<String, CamundaVariable> formVariables; try { formVariables = camundaApi.getTaskInstanceFormVariables(getBasicAuth(), taskId); @@ -333,36 +348,31 @@ "Error accessing workflow engine api to get claim task instance " + taskId, e); } if (HttpStatus.NO_CONTENT.value() == r.status()) { - CamundaTaskInstance cti; - try { - cti = camundaApi.getTaskInstance(getBasicAuth(), taskId); - } catch (FeignException e) { - throw new InternalErrorServiceException( - "Error accessing workflow engine api to get task instance " + taskId, e); - } - WorkflowTaskModel taskModel = new WorkflowTaskModel(); - requiredTaskVariables(taskId).ifPresent(variables -> taskModel.setRequiredVariables(variables)); - taskModel.setTaskId(cti.getId()); - taskModel.setProcessInstanceId(cti.getProcessInstanceId()); - taskModel.setProcessDefinitionKey(processDefinitionKey); - taskModel.setAssignee(cti.getAssignee()); - taskModel.setTenantId(cti.getTenantId()); - taskModel.setTaskDefinitionKey(cti.getTaskDefinitionKey()); - taskModel.setSuspended(cti.getSuspended()); - taskModel.setOwner(cti.getOwner()); - taskModel.setName(cti.getName()); - taskModel.setDescription(cti.getDescription()); - TypeConversion.zDTOfCamundaDateString(cti.getDue()).ifPresent(date -> taskModel.setDue(date)); - TypeConversion.zDTOfCamundaDateString(cti.getCreated()).ifPresent(date -> taskModel.setCreated(date)); - taskModel.setFormKey(cti.getFormKey()); - return Optional.of(taskModel); + return getTaskModel(taskId); } else if (HttpStatus.INTERNAL_SERVER_ERROR.value() == r.status()) { return Optional.empty(); } else { throw new InternalErrorServiceException("Error accessing workflow engine api to claim task instance " - + taskId + " response status " + r.status()); + + taskId + RESPONSE_STATUS + r.status()); } } + + /** + * Get TaskModel of task with provided taskId. + * @param taskId task identifier + * @return Workflow task details. + * @throws InternalErrorServiceException if error occurred accessing the workflow engine + */ + public Optional<WorkflowTaskModel> getTaskModel(String taskId) throws InternalErrorServiceException { + CamundaTaskInstance cti; + try { + cti = camundaApi.getTaskInstance(getBasicAuth(), taskId); + } catch (FeignException e) { + throw new InternalErrorServiceException( + "Error accessing workflow engine api to get task instance " + taskId, e); + } + return Optional.of(workflowTaskModelOfCamundaTaskInstance(cti, taskId)); + } /** * Unclaim workflow task identified by the provided taskId. @@ -381,34 +391,12 @@ "Error accessing workflow engine api to get unclaim task instance " + taskId, e); } if (HttpStatus.NO_CONTENT.value() == r.status()) { - CamundaTaskInstance cti; - try { - cti = camundaApi.getTaskInstance(getBasicAuth(), taskId); - } catch (FeignException e) { - throw new InternalErrorServiceException( - "Error accessing workflow engine api to get task instance " + taskId, e); - } - WorkflowTaskModel taskModel = new WorkflowTaskModel(); - requiredTaskVariables(taskId).ifPresent(variables -> taskModel.setRequiredVariables(variables)); - taskModel.setTaskId(cti.getId()); - taskModel.setProcessInstanceId(cti.getProcessInstanceId()); - taskModel.setProcessDefinitionKey(processDefinitionKey); - taskModel.setAssignee(cti.getAssignee()); - taskModel.setTenantId(cti.getTenantId()); - taskModel.setTaskDefinitionKey(cti.getTaskDefinitionKey()); - taskModel.setSuspended(cti.getSuspended()); - taskModel.setOwner(cti.getOwner()); - taskModel.setName(cti.getName()); - taskModel.setDescription(cti.getDescription()); - TypeConversion.zDTOfCamundaDateString(cti.getDue()).ifPresent(date -> taskModel.setDue(date)); - TypeConversion.zDTOfCamundaDateString(cti.getCreated()).ifPresent(date -> taskModel.setCreated(date)); - taskModel.setFormKey(cti.getFormKey()); - return Optional.of(taskModel); + return getTaskModel(taskId); } else if (HttpStatus.BAD_REQUEST.value() == r.status()) { return Optional.empty(); } else { throw new InternalErrorServiceException("Error accessing workflow engine api to unclaim task instance " - + taskId + " response status " + r.status()); + + taskId + RESPONSE_STATUS + r.status()); } } @@ -449,19 +437,19 @@ } else if (HttpStatus.BAD_REQUEST.value() == r.status()) { // TODO correctly parse the error json to verify if error of camunda, not enough // variables, ... - log.warning("Complete task " + taskId + " not successful: Bad Request - " + r.body().toString()); + log.warning(COMPLETE_TASK + taskId + " not successful: Bad Request - " + r.body().toString()); throw new BadRequestServiceException( - "Complete task " + taskId + " not successful: Bad Request - " + r.body().toString()); + COMPLETE_TASK + taskId + " not successful: Bad Request - " + r.body().toString()); } else if (HttpStatus.INTERNAL_SERVER_ERROR.value() == r.status()) { // TODO correctly parse the error json to verify if error of camunda, not enough // variables, ... - log.warning("Complete task " + taskId + " not successful: Internal Server Error -" + r.body().toString()); + log.warning(COMPLETE_TASK + taskId + " not successful: Internal Server Error -" + r.body().toString()); throw new InternalErrorServiceException("Error accessing workflow engine api to complete task instance " - + taskId + " response status " + r.status() + "; body " + r.body().toString()); + + taskId + RESPONSE_STATUS + r.status() + "; body " + r.body().toString()); } else { - log.severe("Complete task " + taskId + " not successful: " + r.status() + " - " + r.body().toString()); + log.severe(COMPLETE_TASK + taskId + " not successful: " + r.status() + " - " + r.body().toString()); throw new InternalErrorServiceException("Error accessing workflow engine api to complete task instance " - + taskId + " response status " + r.status() + "; body " + r.body().toString()); + + taskId + RESPONSE_STATUS + r.status() + "; body " + r.body().toString()); } }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/util/TypeConversion.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/util/TypeConversion.java index fda2686..ccd69ff 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/util/TypeConversion.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/util/TypeConversion.java
@@ -34,112 +34,115 @@ @Log public class TypeConversion { - private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); - private static DateTimeFormatter camundaDateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + private static DateTimeFormatter camundaDateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); - /** - * Convert LocalDate type to String representation format yyyy-MM-dd. - * - * @param date value to convert to String representation. - * @return Optional containing String representation if successful. Otherwise - * Optional.empty. - */ - public static Optional<String> dateStringOfLocalDate(LocalDate date) { - if (date == null) { - return Optional.empty(); - } - try { - String dateString = date.format(formatter); - return Optional.of(dateString); - } catch (DateTimeParseException e) { - log.log(Level.WARNING, "DateTime format failed from LocalDate: " + date.toString()); - return Optional.empty(); - } + private TypeConversion() { + } - } + /** + * Convert LocalDate type to String representation format yyyy-MM-dd. + * + * @param date value to convert to String representation. + * @return Optional containing String representation if successful. Otherwise + * Optional.empty. + */ + public static Optional<String> dateStringOfLocalDate(LocalDate date) { + if (date == null) { + return Optional.empty(); + } + try { + String dateString = date.format(formatter); + return Optional.of(dateString); + } catch (DateTimeParseException e) { + log.log(Level.WARNING, "DateTime format failed from LocalDate: " + date.toString()); + return Optional.empty(); + } - /** - * Convert String representation of LocalDate of format yyyy-MM-dd to LocalDate. - * - * @param dateString value to convert to LocalDate representation. - * @return Optional containing LocalDate representation if successful. Otherwise - * Optional.empty. - */ - public static Optional<LocalDate> dateOfDateString(String dateString) { - if (dateString == null) { - return Optional.empty(); - } - try { - LocalDate date = LocalDate.parse(dateString, formatter); - return Optional.of(date); - } catch (DateTimeParseException e) { - log.log(Level.WARNING, "DateTime parsing failed from dateString: " + dateString); - return Optional.empty(); - } - } + } - /** - * Convert TaskId UUID type to String representation. - * - * @param uuid value to convert to String representation. - * @return Optional containing String representation if successful. Otherwise - * Optional.empty. - */ - public static Optional<String> stringOfTaskId(UUID uuid) { - if (uuid == null) { - return Optional.empty(); - } - return Optional.of(uuid.toString()); - } + /** + * Convert String representation of LocalDate of format yyyy-MM-dd to LocalDate. + * + * @param dateString value to convert to LocalDate representation. + * @return Optional containing LocalDate representation if successful. Otherwise + * Optional.empty. + */ + public static Optional<LocalDate> dateOfDateString(String dateString) { + if (dateString == null) { + return Optional.empty(); + } + try { + LocalDate date = LocalDate.parse(dateString, formatter); + return Optional.of(date); + } catch (DateTimeParseException e) { + log.log(Level.WARNING, "DateTime parsing failed from dateString: " + dateString); + return Optional.empty(); + } + } - /** - * Convert String representation of TaskId UUID type to TaskId UUID. - * - * @param taskIdString value to convert to TaskId UUID representation. - * @return Optional containing TaskID UUID representation if successful. - * Otherwise Optional.empty. - */ - public static Optional<UUID> taskIdOfString(String taskIdString) { - if (taskIdString == null) { - return Optional.empty(); - } - try { - UUID uuid = UUID.fromString(taskIdString); - return Optional.of(uuid); - } catch (IllegalArgumentException e) { - log.log(Level.WARNING, "UUID parsing failed from taskIdString: " + taskIdString); - return Optional.empty(); - } - } + /** + * Convert BusinessKey UUID type to String representation. + * + * @param uuid value to convert to String representation. + * @return Optional containing String representation if successful. Otherwise + * Optional.empty. + */ + public static Optional<String> stringOfBusinessKey(UUID uuid) { + if (uuid == null) { + return Optional.empty(); + } + return Optional.of(uuid.toString()); + } - /** - * @param dueString - * @return - */ - public static Optional<ZonedDateTime> zDTOfCamundaDateString(String dateString) { - if (dateString == null) { - return Optional.empty(); - } - try { - ZonedDateTime date = ZonedDateTime.parse(dateString, camundaDateFormatter); - return Optional.of(date); - } catch (DateTimeParseException e) { - log.log(Level.WARNING, "ZonedDateTime parsing failed from dateString: " + dateString); - return Optional.empty(); - } - } - - public static Optional<String> camundaDateStringOfZDT(ZonedDateTime date) { - if (date == null) { - return Optional.empty(); - } - try { - String dateString = date.format(camundaDateFormatter); - return Optional.of(dateString); - } catch (DateTimeParseException e) { - log.log(Level.WARNING, "CamundaDateString format failed from ZonedDateTime: " + date.toString()); - return Optional.empty(); - } - } + /** + * Convert String representation of BusinessKey UUID type to BusinessKey UUID. + * + * @param businessKeyString value to convert to BusinessKey UUID representation. + * @return Optional containing TaskID UUID representation if successful. + * Otherwise Optional.empty. + */ + public static Optional<UUID> businessKeyOfString(String businessKeyString) { + if (businessKeyString == null) { + return Optional.empty(); + } + try { + UUID uuid = UUID.fromString(businessKeyString); + return Optional.of(uuid); + } catch (IllegalArgumentException e) { + log.log(Level.WARNING, "UUID parsing failed from businessKey: " + businessKeyString); + return Optional.empty(); + } + } + + /** + * @param dueString + * @return + */ + public static Optional<ZonedDateTime> zDTOfCamundaDateString(String dateString) { + if (dateString == null) { + return Optional.empty(); + } + try { + ZonedDateTime date = ZonedDateTime.parse(dateString, camundaDateFormatter); + return Optional.of(date); + } catch (DateTimeParseException e) { + log.log(Level.WARNING, "ZonedDateTime parsing failed from dateString: " + dateString); + return Optional.empty(); + } + } + + public static Optional<String> camundaDateStringOfZDT(ZonedDateTime date) { + if (date == null) { + return Optional.empty(); + } + try { + String dateString = date.format(camundaDateFormatter); + return Optional.of(dateString); + } catch (DateTimeParseException e) { + log.log(Level.WARNING, "CamundaDateString format failed from ZonedDateTime: " + date.toString()); + return Optional.empty(); + } + } }
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementDetailsModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementDetailsModel.java index eb1f748..3f74b94 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementDetailsModel.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementDetailsModel.java
@@ -27,7 +27,7 @@ private Boolean finished; private Long id; - private String taskId; + private String businessKey; private String dueDate; private String receiptDate; private String title;
diff --git a/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementModel.java b/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementModel.java index 8937b1d..005091e 100644 --- a/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementModel.java +++ b/src/main/java/org/eclipse/openk/statementpublicaffairs/viewmodel/StatementModel.java
@@ -27,7 +27,7 @@ private Boolean finished; private Long id; - private String taskId; + private String businessKey; private String dueDate; private String receiptDate; private String title;
diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml new file mode 100644 index 0000000..e9240ba --- /dev/null +++ b/src/main/resources/application-test.yml
@@ -0,0 +1,85 @@ +# ******************************************************************************* +# Copyright (c) 2019 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License v. 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0. +# +# SPDX-License-Identifier: EPL-2.0 +# ******************************************************************************* +spring: + flyway: + enabled: false + + datasource: + url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 + + jpa: + generate-ddl: true + hibernate: + ddl-auto: create + + +application: + name: ^project.artifactId^ +build: + version: ^project.version^ + +server: + port: 9156 + +jwt: + tokenHeader: Authorization + useStaticJwt: true + staticJwt: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJHN0MtQ1E4ckdYUGpzSlY0R0xEWHI2dTFiOUwzV1pYVkxEa1VJOWV1d1FnIn0.eyJqdGkiOiI5MDM1MDI4ZC0zODllLTQ3YjYtODM5NS1hNmE2OTdjMTY5Y2UiLCJleHAiOjE1ODYzNDU1ODIsIm5iZiI6MCwiaWF0IjoxNTg2MzQ1MjgyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgzODAvYXV0aC9yZWFsbXMvT3BlbktSZWFsbSIsImF1ZCI6ImVsb2dib29rLWJhY2tlbmQiLCJzdWIiOiI2MDI0YjZiOS1kYWY4LTRjNjEtOGJjMy1jZDYxMGMxYmI3MTMiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJlbG9nYm9vay1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiYTRmY2EzNTAtOTRiNi00NTExLWJkZTgtOGQ2OTYxNGRkNjg4IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJzcGFfZGl2aXNpb25fbWVtYmVyIiwic3BhX2FjY2VzcyIsInNwYV9hcHByb3ZlciIsInNwYV9vZmZpY2lhbF9pbl9jaGFyZ2UiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInJvbGVzIjoiW3NwYV9kaXZpc2lvbl9tZW1iZXIsIG9mZmxpbmVfYWNjZXNzLCB1bWFfYXV0aG9yaXphdGlvbiwgc3BhX2FjY2Vzcywgc3BhX29mZmljaWFsX2luX2NoYXJnZSwgc3BhX2FwcHJvdmVyXSIsIm5hbWUiOiJUZXN0IE1pdGFyYmVpdGVyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic3BhX211bHRpIiwiZ2l2ZW5fbmFtZSI6IlRlc3QiLCJmYW1pbHlfbmFtZSI6Ik1pdGFyYmVpdGVyIn0.emFfQHg9ID2qSfUhXkzSi3JZAEnNRuFGuY60bELnsgRtM22HfpnzjU9u0NIg5YGj8ePRNTz-1cqxDRHLvL76c3cayriTRMLifORyhC3NLIusmnnaYF4R7AsVBiGJOgXvWwhcQfmjoiNjqXAADw1EiCbAKypjBQDcJpq0trq-yz98TRdlbJUHQmHv-PPgMOagyQq5q4fRdgWkzxXz32rKn7BSklWw9_Plv2tbRztcNgL8xxpOnypSy3aY2y1iLM1Dki-9BSqm7sYd28l4tQfnhAMBnox-BlFG8e3rZuYyiFBr0uDBdwdDEJvyvRVvYAI5HL5R6j9sL1aLHJNboWhO3w + +services: + authNAuth: + name: authNAuthService + camunda: + name: camundaService + contactdatabase: + name: contactDatabaseService + +authNAuthService: + ribbon: + listOfServers: http://localhost:8080 + +camunda: + user: spa_service + pw: spa_service + + +workflow: + processDefinitionKey: statement_p + tenantId: spa + +camundaService: + ribbon: + listOfServers: http://localhost:8480 + +contactDatabaseService: + ribbon: + listOfServers: http://localhost:8080 + +authnauth: + technical-username: spa_service + technical-userpassword: spa_service + + +contactDatabase: + technical-username: spa_service + technical-userpassword: spa_service + +feign: + client: + config: + default: + connectTimeout: 60000 + readTimeout: 60000 +cors: + corsEnabled: false +
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 218c26c..f274487 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml
@@ -14,25 +14,14 @@ flyway: enabled: false - #datasource: - # url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1 - - #jpa: - # hibernate: - # ddl-auto: create - datasource: hikari: connectionTimeout: 20000 maximumPoolSize: 5 - url: "jdbc:postgresql://spadb:5432/spa_service" + url: "jdbc:postgresql://localhost:5432/spa_service" username: "spa_service" password: "spa_service" - #jpa: - #generate-ddl: true - #hibernate: - # ddl-auto: create application: @@ -43,21 +32,18 @@ server: port: 9156 -#jwt: -# tokenHeader: Authorization -# useStaticJwt: false -# staticJwt: x - jwt: tokenHeader: Authorization - useStaticJwt: true - staticJwt: eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJHN0MtQ1E4ckdYUGpzSlY0R0xEWHI2dTFiOUwzV1pYVkxEa1VJOWV1d1FnIn0.eyJqdGkiOiI5MDM1MDI4ZC0zODllLTQ3YjYtODM5NS1hNmE2OTdjMTY5Y2UiLCJleHAiOjE1ODYzNDU1ODIsIm5iZiI6MCwiaWF0IjoxNTg2MzQ1MjgyLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgzODAvYXV0aC9yZWFsbXMvT3BlbktSZWFsbSIsImF1ZCI6ImVsb2dib29rLWJhY2tlbmQiLCJzdWIiOiI2MDI0YjZiOS1kYWY4LTRjNjEtOGJjMy1jZDYxMGMxYmI3MTMiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJlbG9nYm9vay1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiYTRmY2EzNTAtOTRiNi00NTExLWJkZTgtOGQ2OTYxNGRkNjg4IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJzcGFfZGl2aXNpb25fbWVtYmVyIiwic3BhX2FjY2VzcyIsInNwYV9hcHByb3ZlciIsInNwYV9vZmZpY2lhbF9pbl9jaGFyZ2UiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInJvbGVzIjoiW3NwYV9kaXZpc2lvbl9tZW1iZXIsIG9mZmxpbmVfYWNjZXNzLCB1bWFfYXV0aG9yaXphdGlvbiwgc3BhX2FjY2Vzcywgc3BhX29mZmljaWFsX2luX2NoYXJnZSwgc3BhX2FwcHJvdmVyXSIsIm5hbWUiOiJUZXN0IE1pdGFyYmVpdGVyIiwicHJlZmVycmVkX3VzZXJuYW1lIjoic3BhX211bHRpIiwiZ2l2ZW5fbmFtZSI6IlRlc3QiLCJmYW1pbHlfbmFtZSI6Ik1pdGFyYmVpdGVyIn0.emFfQHg9ID2qSfUhXkzSi3JZAEnNRuFGuY60bELnsgRtM22HfpnzjU9u0NIg5YGj8ePRNTz-1cqxDRHLvL76c3cayriTRMLifORyhC3NLIusmnnaYF4R7AsVBiGJOgXvWwhcQfmjoiNjqXAADw1EiCbAKypjBQDcJpq0trq-yz98TRdlbJUHQmHv-PPgMOagyQq5q4fRdgWkzxXz32rKn7BSklWw9_Plv2tbRztcNgL8xxpOnypSy3aY2y1iLM1Dki-9BSqm7sYd28l4tQfnhAMBnox-BlFG8e3rZuYyiFBr0uDBdwdDEJvyvRVvYAI5HL5R6j9sL1aLHJNboWhO3w + useStaticJwt: false + staticJwt: x services: authNAuth: name: authNAuthService camunda: name: camundaService + contactdatabase: + name: contactDatabaseService authNAuthService: ribbon: @@ -69,18 +55,24 @@ workflow: processDefinitionKey: statement_p + tenantId: spa camundaService: ribbon: - listOfServers: http://localhost:8480 + listOfServers: http://localhost:8280 -contactModule: - name: "name value" +contactDatabaseService: + ribbon: + listOfServers: http://localhost:9155 authnauth: technical-username: spa_service technical-userpassword: spa_service +contactDatabase: + technical-username: spa_service + technical-userpassword: spa_service + feign: client: config:
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml new file mode 100644 index 0000000..f359cf7 --- /dev/null +++ b/src/main/resources/logback-spring.xml
@@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configuration> + + <property name="LOGS" value="${catalina.base}/logs"/> + + <appender name="Console" class="ch.qos.logback.core.ConsoleAppender"> + <layout class="ch.qos.logback.classic.PatternLayout"> + <Pattern> + %black(%d{ISO8601}) %highlight(%-5level) [%blue(%t)] %yellow(%c{60}): %msg%n%throwable + </Pattern> + </layout> + </appender> + + <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${LOGS}/statement-public-affairs.log</file> + <encoder + class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> + <Pattern>%d %p %c{60} [%t] %m%n</Pattern> + </encoder> + + <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> + <fileNamePattern>${LOGS}/archived/statement-public-affairs-%d{yyyy-MM-dd}.gz</fileNamePattern> + <MaxHistory>30</MaxHistory> + <cleanHistoryOnStart>true</cleanHistoryOnStart> + </rollingPolicy> + </appender> + + <!-- LOG everything at INFO level --> + <root level="info"> + <appender-ref ref="RollingFile"/> + <appender-ref ref="Console"/> + </root> + + <logger name="org.eclipse.openk.statementpublicaffairs" level="trace" additivity="false"> + <appender-ref ref="RollingFile"/> + <appender-ref ref="Console"/> + </logger> + +</configuration> \ No newline at end of file
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/StatementPublicAffairsApplicationTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/StatementPublicAffairsApplicationTest.java deleted file mode 100644 index 23e4a57..0000000 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/StatementPublicAffairsApplicationTest.java +++ /dev/null
@@ -1,31 +0,0 @@ -/* - ******************************************************************************* - * Copyright (c) 2020 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License v. 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * SPDX-License-Identifier: EPL-2.0 - ******************************************************************************* -*/ -package org.eclipse.openk.statementpublicaffairs; - -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -class StatementPublicAffairsApplicationTest { - - @SpringBootTest - class ContactBaseDataApplicationTests { - - @Test - void contextLoads() { - } - - } - -}
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfiguration.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfiguration.java index 9c026ff..1d58441 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfiguration.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfiguration.java
@@ -39,7 +39,7 @@ */ @EntityScan(basePackageClasses = StatementPublicAffairsApplication.class) @ContextConfiguration(initializers = { ConfigFileApplicationContextInitializer.class }) -@TestPropertySource("spring.config.location=classpath:application.yml") +@TestPropertySource("spring.config.location=classpath:application-test.yml") public class TestConfiguration {
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationContactService.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationContactService.java new file mode 100644 index 0000000..f39c712 --- /dev/null +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationContactService.java
@@ -0,0 +1,50 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.config; + +import org.eclipse.openk.statementpublicaffairs.StatementPublicAffairsApplication; +import org.eclipse.openk.statementpublicaffairs.api.ContactDatabaseApi; +import org.eclipse.openk.statementpublicaffairs.service.ContactService; +import org.eclipse.openk.statementpublicaffairs.service.SessionService; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; + +/** + * Test configuration environment. + * + * @author Tobias Stummer + * + */ +@EntityScan(basePackageClasses = StatementPublicAffairsApplication.class) +@ContextConfiguration(initializers = { ConfigFileApplicationContextInitializer.class }) +@TestPropertySource("spring.config.location=classpath:application-test.yml") +public class TestConfigurationContactService { + + @MockBean + private ContactDatabaseApi contactDatabaseApi; + + + @MockBean + private SessionService sessionService; + + @Bean + public ContactService myContactService() { + return new ContactService(); + } +} \ No newline at end of file
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationStatementOverviewService.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationStatementOverviewService.java new file mode 100644 index 0000000..df8e1e7 --- /dev/null +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationStatementOverviewService.java
@@ -0,0 +1,50 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.config; + +import org.eclipse.openk.statementpublicaffairs.StatementPublicAffairsApplication; +import org.eclipse.openk.statementpublicaffairs.repository.StatementRepository; +import org.eclipse.openk.statementpublicaffairs.repository.StatementtypeRepository; +import org.eclipse.openk.statementpublicaffairs.service.StatementOverviewService; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.TestPropertySource; + +/** + * Test configuration environment. + * + * @author Tobias Stummer + * + */ +@EntityScan(basePackageClasses = StatementPublicAffairsApplication.class) +@ContextConfiguration(initializers = { ConfigFileApplicationContextInitializer.class }) +@TestPropertySource("spring.config.location=classpath:application-test.yml") +public class TestConfigurationStatementOverviewService { + + @MockBean + private StatementRepository statementRepository; + + @MockBean + private StatementtypeRepository statementtypeRepository; + + @Bean + public StatementOverviewService myStatementOverviewService() { + return new StatementOverviewService(); + } + +} \ No newline at end of file
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationStatementProcessService.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationStatementProcessService.java index b45c58e..8ab6b6d 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationStatementProcessService.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/config/TestConfigurationStatementProcessService.java
@@ -14,6 +14,7 @@ */ package org.eclipse.openk.statementpublicaffairs.config; +import java.util.ArrayList; import java.util.List; import org.eclipse.openk.statementpublicaffairs.StatementPublicAffairsApplication; @@ -38,7 +39,7 @@ */ @EntityScan(basePackageClasses = StatementPublicAffairsApplication.class) @ContextConfiguration(initializers = { ConfigFileApplicationContextInitializer.class }) -@TestPropertySource("spring.config.location=classpath:application.yml") +@TestPropertySource("spring.config.location=classpath:application-test.yml") public class TestConfigurationStatementProcessService { @MockBean @@ -49,14 +50,14 @@ @MockBean private UserInfoService userInfoService; - + @MockBean private StatementAuthorizationService authorizationService; - - - @MockBean - private List<IExternalTaskWorker> workers; + @Bean + public List<IExternalTaskWorker> workers() { + return new ArrayList<>(); + } @Bean public StatementProcessService myStatementProcessService() {
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/SessionControllerTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/SessionControllerTest.java index b1d1191..e4714d7 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/SessionControllerTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/SessionControllerTest.java
@@ -25,6 +25,7 @@ import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; /** @@ -35,6 +36,7 @@ */ @SpringBootTest(classes = StatementPublicAffairsApplication.class) @AutoConfigureMockMvc +@ActiveProfiles("test") class SessionControllerTest { @MockBean
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementControllerTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementControllerTest.java index 683e7a3..a495ada 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementControllerTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementControllerTest.java
@@ -32,6 +32,7 @@ import org.eclipse.openk.statementpublicaffairs.StatementPublicAffairsApplication; import org.eclipse.openk.statementpublicaffairs.model.AttachmentFile; import org.eclipse.openk.statementpublicaffairs.service.SessionService; +import org.eclipse.openk.statementpublicaffairs.service.StatementProcessService; import org.eclipse.openk.statementpublicaffairs.service.StatementService; import org.eclipse.openk.statementpublicaffairs.viewmodel.AttachmentModel; import org.eclipse.openk.statementpublicaffairs.viewmodel.StatementDetailsModel; @@ -45,6 +46,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; @@ -56,12 +58,16 @@ */ @SpringBootTest(classes = StatementPublicAffairsApplication.class) @AutoConfigureMockMvc +@ActiveProfiles("test") class StatementControllerTest { @MockBean private StatementService statementService; @MockBean + private StatementProcessService statementProcessService; + + @MockBean private SessionService sessionService; @Autowired @@ -78,7 +84,7 @@ Long id = 4711L; String dueDate = "2020-04-30"; String receiptDate = "2020-04-10"; - String taskId = "taskId"; + String businessKey = "businessKey"; String title = "title"; String city = "City"; String district = "District"; @@ -87,7 +93,7 @@ model.setDueDate(dueDate); model.setReceiptDate(receiptDate); model.setTitle(title); - model.setTaskId(taskId); + model.setBusinessKey(businessKey); model.setDistrict(district); model.setCity(city); model.setTypeId(1L); @@ -97,7 +103,7 @@ .andExpect(jsonPath("finished", is(false))).andExpect(jsonPath("dueDate", is(dueDate))) .andExpect(jsonPath("receiptDate", is(receiptDate))).andExpect(jsonPath("title", is(title))) .andExpect(jsonPath("city", is(city))).andExpect(jsonPath("district", is(district))) - .andExpect(jsonPath("typeId", is(1))).andExpect(jsonPath("taskId", is(taskId))); + .andExpect(jsonPath("typeId", is(1))).andExpect(jsonPath("businessKey", is(businessKey))); } /** @@ -158,7 +164,7 @@ + "\", \"title\":\"" + title + "\", \"city\":\"" + city + "\" , \"district\":\"" + district + "\" , \"typeId\":\"" + statementTypeId + "\" }"; - Mockito.when(statementService.createStatement(Mockito.any(StatementDetailsModel.class))) + Mockito.when(statementProcessService.createStatement(Mockito.any(StatementDetailsModel.class))) .thenAnswer(new Answer<Optional<StatementDetailsModel>>() { @Override public Optional<StatementDetailsModel> answer(InvocationOnMock invocation) throws Throwable {
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementOverviewControllerTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementOverviewControllerTest.java index 6b77834..5b304c6 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementOverviewControllerTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementOverviewControllerTest.java
@@ -34,6 +34,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; @@ -45,6 +46,8 @@ */ @SpringBootTest(classes = StatementPublicAffairsApplication.class) @AutoConfigureMockMvc +@ActiveProfiles("test") + class StatementOverviewControllerTest { @MockBean @@ -116,22 +119,22 @@ StatementModel statementModelA = new StatementModel(); statementModelA.setId(1L); statementModelA.setFinished(true); - statementModelA.setTaskId("taskId1"); + statementModelA.setBusinessKey("businessKey1"); testStatementsFtHTt.add(statementModelA); StatementModel statementModelB = new StatementModel(); statementModelB.setId(2L); statementModelB.setFinished(true); - statementModelB.setTaskId(null); + statementModelB.setBusinessKey(null); testStatementsFtHTf.add(statementModelB); StatementModel statementModelC = new StatementModel(); statementModelC.setId(3L); statementModelC.setFinished(true); - statementModelC.setTaskId("taskId1"); + statementModelC.setBusinessKey("businessKey1"); testStatementsFfHTt.add(statementModelC); StatementModel statementModelD = new StatementModel(); statementModelD.setId(4L); statementModelD.setFinished(true); - statementModelD.setTaskId(null); + statementModelD.setBusinessKey(null); testStatementsFfHTf.add(statementModelD); Mockito.when(statementOverviewService.getStatementModels(true, true)).thenReturn(testStatementsFtHTt); Mockito.when(statementOverviewService.getStatementModels(true, false)).thenReturn(testStatementsFtHTf);
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessControllerTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessControllerTest.java index 778a60b..823136b 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessControllerTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/StatementProcessControllerTest.java
@@ -31,10 +31,13 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; @SpringBootTest(classes = StatementPublicAffairsApplication.class) @AutoConfigureMockMvc +@ActiveProfiles("test") + class StatementProcessControllerTest { @MockBean
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/UserInfoControllerTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/UserInfoControllerTest.java index a98e495..9934bfa 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/UserInfoControllerTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/UserInfoControllerTest.java
@@ -28,6 +28,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; /** @@ -38,6 +39,8 @@ */ @SpringBootTest(classes = StatementPublicAffairsApplication.class) @AutoConfigureMockMvc +@ActiveProfiles("test") + class UserInfoControllerTest {
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/VersionControllerTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/VersionControllerTest.java index 8c67184..26094a7 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/VersionControllerTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/controller/VersionControllerTest.java
@@ -29,6 +29,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; /** @@ -39,6 +40,8 @@ */ @SpringBootTest(classes = StatementPublicAffairsApplication.class) @AutoConfigureMockMvc +@ActiveProfiles("test") + class VersionControllerTest { @MockBean
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/ContactServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/ContactServiceTest.java new file mode 100644 index 0000000..8834085 --- /dev/null +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/ContactServiceTest.java
@@ -0,0 +1,322 @@ +package org.eclipse.openk.statementpublicaffairs.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; + +import org.eclipse.openk.statementpublicaffairs.api.ContactDatabaseApi; +import org.eclipse.openk.statementpublicaffairs.config.TestConfigurationContactService; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; +import org.eclipse.openk.statementpublicaffairs.model.CompanyContactAddressModel; +import org.eclipse.openk.statementpublicaffairs.model.CompanyContactModel; +import org.eclipse.openk.statementpublicaffairs.model.CompanyModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiAddressModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiCompanyContactPersonModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiCompanyDetailsModel; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiDetailedContact; +import org.eclipse.openk.statementpublicaffairs.model.contactdatabase.ContactApiPagedDetailedContact; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import feign.FeignException; +import feign.Request; +import feign.Response; +import feign.Request.Body; + +@SpringBootTest(classes = TestConfigurationContactService.class) +@ActiveProfiles("test") +class ContactServiceTest { + + @Autowired + ContactService contactService; + + @Autowired + SessionService sessionService; + + @Autowired + ContactDatabaseApi contactDatabaseApi; + + @Test + void testSearchContactsValidSearchStringShouldRespondWithListOfContacts() throws InternalErrorServiceException { + + String token = "token"; + String searchString = "searchString"; + Mockito.when(sessionService.getToken(Mockito.anyString(), Mockito.anyString())).thenReturn(token); + + String companyId = "companyId"; + String contactId = "contactId"; + ContactApiPagedDetailedContact pDetailedcontact = new ContactApiPagedDetailedContact(); + + List<ContactApiDetailedContact> content = new ArrayList<>(); + ContactApiDetailedContact detailedContact = new ContactApiDetailedContact(); + detailedContact.setCompanyId(companyId); + detailedContact.setUuid(contactId); + content.add(detailedContact); + pDetailedcontact.setContent(content); + Mockito.when(contactDatabaseApi.searchContacts(Mockito.eq(token), Mockito.eq("1CP"), Mockito.eq(searchString))) + .thenReturn(pDetailedcontact); + + String companyName = "companyName"; + String companyType = "companyType"; + String hrNumber = "hrNumber"; + ContactApiCompanyDetailsModel companyDetails = new ContactApiCompanyDetailsModel(); + companyDetails.setCompanyName(companyName); + companyDetails.setCompanyType(companyType); + companyDetails.setHrNumber(hrNumber); + Mockito.when(contactDatabaseApi.getCompany(Mockito.eq(token), Mockito.eq(companyId))) + .thenReturn(companyDetails); + + String contactType = "contactType"; + String personType = "personType"; + String firstName = "firstName"; + String lastName = "lastName"; + String salutationType = "salutationType"; + String title = "title"; + String email = "email"; + + ContactApiCompanyContactPersonModel contactPerson = new ContactApiCompanyContactPersonModel(); + contactPerson.setContactType(contactType); + contactPerson.setPersonType(personType); + contactPerson.setFirstName(firstName); + contactPerson.setLastName(lastName); + contactPerson.setSalutationType(salutationType); + contactPerson.setTitle(title); + contactPerson.setEmail(email); + contactPerson.setContactId(contactId); + Mockito.when(contactDatabaseApi.getContactPerson(Mockito.eq(token), Mockito.eq(contactId))) + .thenReturn(contactPerson); + + String addressId = "addressId"; + String housenumber = "housenumber"; + String community = "community"; + String communitySuffix = "communitySuffix"; + String street = "street"; + String postcode = "postcode"; + List<ContactApiAddressModel> contactAddresses = new ArrayList<>(); + ContactApiAddressModel contactAddress = new ContactApiAddressModel(); + contactAddress.setId(addressId); + contactAddress.setHousenumber(housenumber); + contactAddress.setCommunity(community); + contactAddress.setCommunitySuffix(communitySuffix); + contactAddress.setStreet(street); + contactAddress.setPostcode(postcode); + contactAddress.setIsMainAddress(true); + contactAddresses.add(contactAddress); + Mockito.when(contactDatabaseApi.getContactAddresses(Mockito.eq(token), Mockito.eq(contactId))) + .thenReturn(contactAddresses); + + Optional<List<CompanyModel>> contacts = contactService.searchContacts(searchString); + assertTrue(contacts.isPresent()); + CompanyModel cm = contacts.get().get(0); + assertEquals(companyName, cm.getName()); + assertEquals(companyType, cm.getType()); + assertEquals(hrNumber, cm.getHrNumber()); + + assertFalse(cm.getContacts().isEmpty()); + CompanyContactModel cc = cm.getContacts().get(0); + assertEquals(contactType, cc.getContactType()); + assertEquals(personType, cc.getPersonType()); + assertEquals(firstName, cc.getFirstName()); + assertEquals(lastName, cc.getLastName()); + assertEquals(salutationType, cc.getSalutation()); + assertEquals(title, cc.getTitle()); + assertEquals(email, cc.getEmail()); + + assertFalse(cc.getAddresses().isEmpty()); + CompanyContactAddressModel ca = cc.getAddresses().get(0); + assertEquals(addressId, ca.getAddressId()); + assertEquals(housenumber, ca.getHouseNumber()); + assertEquals(community, ca.getCommunity()); + assertEquals(communitySuffix, ca.getCommunitySuffix()); + assertEquals(street, ca.getStreet()); + assertEquals(postcode, ca.getPostCode()); + assertTrue(ca.getIsMainAddress()); + } + + @Test + void testSearchContactsValidSearchStringApiExceptiongetCompanyShouldThrowInternalErrorServiceException() + throws InternalErrorServiceException { + + String token = "token"; + String searchString = "searchString"; + Mockito.when(sessionService.getToken(Mockito.anyString(), Mockito.anyString())).thenReturn(token); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(contactDatabaseApi) + .searchContacts(Mockito.eq(token), Mockito.eq("1CP"), Mockito.eq(searchString)); + + try { + contactService.searchContacts(searchString); + fail("Should have thrown an InternalErrorServiceException"); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + void testSearchContactsValidSearchStringApiExceptionSearchingContactShouldThrowInternalErrorServiceException() + throws InternalErrorServiceException { + + String token = "token"; + String searchString = "searchString"; + Mockito.when(sessionService.getToken(Mockito.anyString(), Mockito.anyString())).thenReturn(token); + + String companyId = "companyId"; + String contactId = "contactId"; + ContactApiPagedDetailedContact pDetailedcontact = new ContactApiPagedDetailedContact(); + + List<ContactApiDetailedContact> content = new ArrayList<>(); + ContactApiDetailedContact detailedContact = new ContactApiDetailedContact(); + detailedContact.setCompanyId(companyId); + detailedContact.setUuid(contactId); + content.add(detailedContact); + pDetailedcontact.setContent(content); + Mockito.when(contactDatabaseApi.searchContacts(Mockito.eq(token), Mockito.eq("1CP"), Mockito.eq(searchString))) + .thenReturn(pDetailedcontact); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(contactDatabaseApi).getCompany(Mockito.eq(token), Mockito.eq(companyId)); + + try { + contactService.searchContacts(searchString); + fail("Should have thrown an InternalErrorServiceException"); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + void testSearchContactsValidSearchStringApiExceptionGetContactPersonShouldThrowInternalErrorServiceException() + throws InternalErrorServiceException { + + String token = "token"; + String searchString = "searchString"; + Mockito.when(sessionService.getToken(Mockito.anyString(), Mockito.anyString())).thenReturn(token); + + String companyId = "companyId"; + String contactId = "contactId"; + ContactApiPagedDetailedContact pDetailedcontact = new ContactApiPagedDetailedContact(); + + List<ContactApiDetailedContact> content = new ArrayList<>(); + ContactApiDetailedContact detailedContact = new ContactApiDetailedContact(); + detailedContact.setCompanyId(companyId); + detailedContact.setUuid(contactId); + content.add(detailedContact); + pDetailedcontact.setContent(content); + Mockito.when(contactDatabaseApi.searchContacts(Mockito.eq(token), Mockito.eq("1CP"), Mockito.eq(searchString))) + .thenReturn(pDetailedcontact); + + String companyName = "companyName"; + String companyType = "companyType"; + String hrNumber = "hrNumber"; + ContactApiCompanyDetailsModel companyDetails = new ContactApiCompanyDetailsModel(); + companyDetails.setCompanyName(companyName); + companyDetails.setCompanyType(companyType); + companyDetails.setHrNumber(hrNumber); + Mockito.when(contactDatabaseApi.getCompany(Mockito.eq(token), Mockito.eq(companyId))) + .thenReturn(companyDetails); + ; + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(contactDatabaseApi).getContactPerson(Mockito.eq(token), Mockito.eq(contactId)); + + try { + contactService.searchContacts(searchString); + fail("Should have thrown an InternalErrorServiceException"); + } catch (InternalErrorServiceException e) { + // pass + } + } + + @Test + void testSearchContactsValidSearchStringApiExceptionGetContactAddressesShouldThrowInternalErrorServiceException() + throws InternalErrorServiceException { + + String token = "token"; + String searchString = "searchString"; + Mockito.when(sessionService.getToken(Mockito.anyString(), Mockito.anyString())).thenReturn(token); + + String companyId = "companyId"; + String contactId = "contactId"; + ContactApiPagedDetailedContact pDetailedcontact = new ContactApiPagedDetailedContact(); + + List<ContactApiDetailedContact> content = new ArrayList<>(); + ContactApiDetailedContact detailedContact = new ContactApiDetailedContact(); + detailedContact.setCompanyId(companyId); + detailedContact.setUuid(contactId); + content.add(detailedContact); + pDetailedcontact.setContent(content); + Mockito.when(contactDatabaseApi.searchContacts(Mockito.eq(token), Mockito.eq("1CP"), Mockito.eq(searchString))) + .thenReturn(pDetailedcontact); + + String companyName = "companyName"; + String companyType = "companyType"; + String hrNumber = "hrNumber"; + ContactApiCompanyDetailsModel companyDetails = new ContactApiCompanyDetailsModel(); + companyDetails.setCompanyName(companyName); + companyDetails.setCompanyType(companyType); + companyDetails.setHrNumber(hrNumber); + Mockito.when(contactDatabaseApi.getCompany(Mockito.eq(token), Mockito.eq(companyId))) + .thenReturn(companyDetails); + + String contactType = "contactType"; + String personType = "personType"; + String firstName = "firstName"; + String lastName = "lastName"; + String salutationType = "salutationType"; + String title = "title"; + String email = "email"; + + ContactApiCompanyContactPersonModel contactPerson = new ContactApiCompanyContactPersonModel(); + contactPerson.setContactType(contactType); + contactPerson.setPersonType(personType); + contactPerson.setFirstName(firstName); + contactPerson.setLastName(lastName); + contactPerson.setSalutationType(salutationType); + contactPerson.setTitle(title); + contactPerson.setEmail(email); + contactPerson.setContactId(contactId); + Mockito.when(contactDatabaseApi.getContactPerson(Mockito.eq(token), Mockito.eq(contactId))) + .thenReturn(contactPerson); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(contactDatabaseApi).getContactAddresses(Mockito.eq(token), Mockito.eq(contactId)); + + try { + contactService.searchContacts(searchString); + fail("Should have thrown an InternalErrorServiceException"); + } catch (InternalErrorServiceException e) { + // pass + } + + } +}
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/SessionServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/SessionServiceTest.java index f272a33..6c54eca 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/SessionServiceTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/SessionServiceTest.java
@@ -30,6 +30,7 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.test.context.ActiveProfiles; import feign.Request.HttpMethod; @@ -41,6 +42,8 @@ * */ @SpringBootTest(classes = TestConfiguration.class) +@ActiveProfiles("test") + class SessionServiceTest { @Autowired
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementOverviewServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementOverviewServiceTest.java new file mode 100644 index 0000000..f96b1ec --- /dev/null +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementOverviewServiceTest.java
@@ -0,0 +1,258 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.service; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.fail; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import javax.persistence.PersistenceException; + +import org.eclipse.openk.statementpublicaffairs.config.TestConfigurationStatementOverviewService; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; +import org.eclipse.openk.statementpublicaffairs.model.TblStatement; +import org.eclipse.openk.statementpublicaffairs.model.TblStatementtype; +import org.eclipse.openk.statementpublicaffairs.repository.StatementRepository; +import org.eclipse.openk.statementpublicaffairs.repository.StatementtypeRepository; +import org.eclipse.openk.statementpublicaffairs.util.TypeConversion; +import org.eclipse.openk.statementpublicaffairs.viewmodel.StatementModel; +import org.eclipse.openk.statementpublicaffairs.viewmodel.StatementTypeModel; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@SpringBootTest(classes = TestConfigurationStatementOverviewService.class) +@ActiveProfiles("test") + +class StatementOverviewServiceTest { + + @Autowired + private StatementOverviewService statementOverviewService; + + @Autowired + private StatementRepository statementRepository; + + @Autowired + private StatementtypeRepository statementtypeRepository; + + @Test + void testGetAllStatementModelsShouldRespondListWithAllStatements() throws InternalErrorServiceException { + + Boolean finished = true; + Long id = 123L; + String dueDate = TypeConversion.dateStringOfLocalDate(LocalDate.now()).get(); + String receiptDate = TypeConversion.dateStringOfLocalDate(LocalDate.now()).get(); + String title = "title"; + String city = "city"; + String district = "district"; + Long statementypeId = 1L; + TblStatementtype statementtype = new TblStatementtype(); + statementtype.setId(statementypeId); + + List<TblStatement> statements = new ArrayList<>(); + TblStatement tblstatement = new TblStatement(); + tblstatement.setFinished(finished); + tblstatement.setId(id); + tblstatement.setDueDate(TypeConversion.dateOfDateString(dueDate).get()); + tblstatement.setReceiptDate(TypeConversion.dateOfDateString(receiptDate).get()); + tblstatement.setTitle(title); + tblstatement.setCity(city); + tblstatement.setDistrict(district); + tblstatement.setStatementtype(statementtype); + statements.add(tblstatement); + + Mockito.when(statementRepository.findAll()).thenReturn(statements); + + List<StatementModel> all = statementOverviewService.getAllStatementModels(); + assertFalse(all.isEmpty()); + StatementModel s = all.get(0); + + assertEquals(finished, s.getFinished()); + assertEquals(id, s.getId()); + assertEquals(dueDate, s.getDueDate()); + assertEquals(receiptDate, s.getReceiptDate()); + assertEquals(title, s.getTitle()); + assertEquals(city, s.getCity()); + assertEquals(district, s.getDistrict()); + assertEquals(statementypeId, s.getTypeId()); + + } + + @Test + void testGetAllStatementModelsIllegalArgumentExceptionOnRepositoryAccessShouldThrowInternalErrorServiceException() { + Mockito.doThrow(new IllegalArgumentException()).when(statementRepository).findAll(); + + try { + statementOverviewService.getAllStatementModels(); + fail("Should have thrown an InternalServiceErrorException"); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + void testGetAllStatementModelsPersistenceExceptionOnRepositoryAccessShouldThrowInternalErrorServiceException() { + Mockito.doThrow(new PersistenceException()).when(statementRepository).findAll(); + + try { + statementOverviewService.getAllStatementModels(); + fail("Should have thrown an InternalServiceErrorException"); + } catch (InternalErrorServiceException e) { + // pass + } + } + + @Test + void testGetStatementModelsFilterFinishedShouldRespondWithListOfStatemens() throws InternalErrorServiceException { + + Boolean finished = true; + Long id = 123L; + String dueDate = TypeConversion.dateStringOfLocalDate(LocalDate.now()).get(); + String receiptDate = TypeConversion.dateStringOfLocalDate(LocalDate.now()).get(); + String title = "title"; + String city = "city"; + String district = "district"; + String businessKey = TypeConversion.stringOfBusinessKey(UUID.randomUUID()).get(); + Long statementypeId = 1L; + TblStatementtype statementtype = new TblStatementtype(); + statementtype.setId(statementypeId); + + List<TblStatement> hasBusinessKeyStatements= new ArrayList<>(); + TblStatement hs = new TblStatement(); + hs.setFinished(finished); + hs.setId(id); + hs.setTaskId(TypeConversion.businessKeyOfString(businessKey).get()); + hs.setDueDate(TypeConversion.dateOfDateString(dueDate).get()); + hs.setReceiptDate(TypeConversion.dateOfDateString(receiptDate).get()); + hs.setTitle(title); + hs.setDistrict(district); + hs.setCity(city); + hs.setStatementtype(statementtype); + hasBusinessKeyStatements.add(hs); + + List<TblStatement> noBusinessKeyStatements = new ArrayList<>(); + + Mockito.when(statementRepository.findByFinishedAndFilterHasTaskId(Mockito.eq(true))) + .thenReturn(hasBusinessKeyStatements); + Mockito.when(statementRepository.findByFinishedAndFilterNoTaskId(Mockito.eq(true))) + .thenReturn(noBusinessKeyStatements); + + List<StatementModel> filtered = statementOverviewService.getStatementModels(true); + assertFalse(filtered.isEmpty()); + + StatementModel s = filtered.get(0); + assertEquals(finished, s.getFinished()); + assertEquals(id, s.getId()); + assertEquals(dueDate, s.getDueDate()); + assertEquals(receiptDate, s.getReceiptDate()); + assertEquals(title, s.getTitle()); + assertEquals(city, s.getCity()); + assertEquals(district, s.getDistrict()); + assertEquals(statementypeId, s.getTypeId()); + assertEquals(businessKey, s.getBusinessKey()); + + } + + @Test + void ttestGetStatementModelsFilterFinishedIllegalArgumentExceptionOnRepositoryAccessShouldThrowInternalErrorServiceException() { + Mockito.doThrow(new IllegalArgumentException()).when(statementRepository) + .findByFinishedAndFilterHasTaskId(Mockito.anyBoolean()); + Mockito.doThrow(new IllegalArgumentException()).when(statementRepository) + .findByFinishedAndFilterNoTaskId(Mockito.anyBoolean()); + + try { + statementOverviewService.getStatementModels(true); + ; + fail("Should have thrown an InternalServiceErrorException"); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + void testGetStatementModelsFilterFinishedPersistenceExceptionOnRepositoryAccessShouldThrowInternalErrorServiceException() { + Mockito.doThrow(new PersistenceException()).when(statementRepository) + .findByFinishedAndFilterHasTaskId(Mockito.anyBoolean()); + Mockito.doThrow(new PersistenceException()).when(statementRepository) + .findByFinishedAndFilterNoTaskId(Mockito.anyBoolean()); + + try { + statementOverviewService.getStatementModels(true); + ; + fail("Should have thrown an InternalServiceErrorException"); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + void testGetStatementTypeModelsShouldRespondListOfStatementTypeModels() throws InternalErrorServiceException { + + Long id = 123L; + String name = "name"; + List<TblStatementtype> types = new ArrayList<>(); + TblStatementtype type = new TblStatementtype(); + type.setId(id); + type.setName(name); + types.add(type); + + Mockito.when(statementtypeRepository.findAll()).thenReturn(types); + + List<StatementTypeModel> all = statementOverviewService.getStatementTypeModels(); + assertFalse(all.isEmpty()); + + StatementTypeModel s = all.get(0); + assertEquals(id, s.getId()); + assertEquals(name, s.getName()); + + } + + @Test + void testGetStatementTypeModelsIllegalArgumentExceptionOnRepositoryAccessShouldThrowInternalErrorServiceException() { + + Mockito.doThrow(new IllegalArgumentException()).when(statementtypeRepository).findAll(); + + try { + statementOverviewService.getStatementTypeModels(); + fail("Should have thrown an InternalServiceErrorException"); + } catch (InternalErrorServiceException e) { + // pass + } + } + + @Test + void testGetStatementTypeModelsPersistenceExceptionOnRepositoryAccessShouldThrowInternalErrorServiceException() { + + Mockito.doThrow(new PersistenceException()).when(statementtypeRepository).findAll(); + + try { + statementOverviewService.getStatementTypeModels(); + fail("Should have thrown an InternalServiceErrorException"); + } catch (InternalErrorServiceException e) { + // pass + } + } + +}
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessServiceTest.java index 8ebb7e6..8f205d9 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessServiceTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementProcessServiceTest.java
@@ -22,17 +22,24 @@ import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ExecutionException; import org.eclipse.openk.statementpublicaffairs.config.TestConfigurationStatementProcessService; import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestServiceException; import org.eclipse.openk.statementpublicaffairs.exceptions.ForbiddenServiceException; import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; +import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskModel; import org.eclipse.openk.statementpublicaffairs.model.ProcessActivityHistoryModel; import org.eclipse.openk.statementpublicaffairs.model.ProcessDefinitionModel; import org.eclipse.openk.statementpublicaffairs.model.WorkflowTaskModel; +import org.eclipse.openk.statementpublicaffairs.service.worker.IExternalTaskWorker; +import org.eclipse.openk.statementpublicaffairs.service.worker.TestWorkerFalse; +import org.eclipse.openk.statementpublicaffairs.service.worker.TestWorkerTrue; import org.eclipse.openk.statementpublicaffairs.util.TypeConversion; import org.eclipse.openk.statementpublicaffairs.viewmodel.ProcessActivityHistoryViewModel; import org.eclipse.openk.statementpublicaffairs.viewmodel.ProcessHistoryModel; @@ -43,8 +50,11 @@ import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; @SpringBootTest(classes = TestConfigurationStatementProcessService.class) +@ActiveProfiles("test") + class StatementProcessServiceTest { @Autowired @@ -61,6 +71,9 @@ @Autowired private StatementProcessService statementProcessService; + + @Autowired + private List<IExternalTaskWorker> workers; @Test void testGetCurrentStatementTasksWithValidStatementIdShouldReturnListOfWorkflowProcessTasks() throws InternalErrorServiceException, ForbiddenServiceException { @@ -111,7 +124,7 @@ StatementDetailsModel sdm = new StatementDetailsModel(); sdm.setId(statementId); - sdm.setTaskId(businessKey); + sdm.setBusinessKey(businessKey); Mockito.when(statementService.getStatement(statementId)).thenReturn(Optional.of(sdm)); @@ -150,7 +163,7 @@ String businessKey = "businessKey"; StatementDetailsModel sdm = new StatementDetailsModel(); sdm.setId(statementId); - sdm.setTaskId(businessKey); + sdm.setBusinessKey(businessKey); Mockito.when(statementService.getStatement(statementId)).thenReturn(Optional.of(sdm)); @@ -167,7 +180,7 @@ Long statementId = 1234L; StatementDetailsModel sdm = new StatementDetailsModel(); sdm.setId(statementId); - sdm.setTaskId(null); + sdm.setBusinessKey(null); Mockito.when(statementService.getStatement(statementId)).thenReturn(Optional.of(sdm)); @@ -186,7 +199,7 @@ String businessKey = "businessKey"; StatementDetailsModel sdm = new StatementDetailsModel(); sdm.setId(statementId); - sdm.setTaskId(null); + sdm.setBusinessKey(null); Mockito.when(statementService.getStatement(statementId)).thenReturn(Optional.of(sdm)); @@ -249,7 +262,7 @@ StatementDetailsModel sdm = new StatementDetailsModel(); sdm.setId(statementId); - sdm.setTaskId(businessKey); + sdm.setBusinessKey(businessKey); Mockito.when(statementService.getStatement(statementId)).thenReturn(Optional.of(sdm)); @@ -275,7 +288,7 @@ String businessKey = "businessKey"; StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); String processName = "processName"; Long processVersion = 12L; @@ -393,7 +406,7 @@ Long statementId = 1234L; StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(null); + statementDetails.setBusinessKey(null); Mockito.when(statementService.getStatement(statementId)).thenReturn(Optional.of(statementDetails)); try { @@ -410,7 +423,7 @@ String businessKey = "businessKey"; StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); Mockito.when(statementService.getStatement(statementId)).thenReturn(Optional.of(statementDetails)); Mockito.when(workflowService.getProcessDefinition(businessKey)).thenReturn(Optional.empty()); @@ -430,7 +443,7 @@ Long processVersion = 12L; StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); ProcessDefinitionModel processDefinition = new ProcessDefinitionModel(); processDefinition.setVersion(processVersion); @@ -456,7 +469,7 @@ Long processVersion = 12L; StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); ProcessDefinitionModel processDefinition = new ProcessDefinitionModel(); processDefinition.setVersion(processVersion); @@ -487,7 +500,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -551,7 +564,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -595,7 +608,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -634,7 +647,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -676,7 +689,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -740,7 +753,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -780,7 +793,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -818,7 +831,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); List<WorkflowTaskModel> currentTasks = new ArrayList<>(); @@ -860,7 +873,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); Map<String, WorkflowTaskVariableModel> completeTaskVariables = new HashMap<>(); WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); @@ -913,7 +926,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); Map<String, WorkflowTaskVariableModel> completeTaskVariables = new HashMap<>(); WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); @@ -958,7 +971,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); Map<String, WorkflowTaskVariableModel> completeTaskVariables = new HashMap<>(); WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); @@ -1002,7 +1015,7 @@ requiredVariables.put("var", "Boolean"); StatementDetailsModel statementDetails = new StatementDetailsModel(); - statementDetails.setTaskId(businessKey); + statementDetails.setBusinessKey(businessKey); Map<String, WorkflowTaskVariableModel> completeTaskVariables = new HashMap<>(); @@ -1040,11 +1053,11 @@ StatementDetailsModel statementModel = new StatementDetailsModel(); statementModel.setId(statementId); - statementModel.setTaskId(fakeTaskId); + statementModel.setBusinessKey(fakeTaskId); StatementDetailsModel createdModel = new StatementDetailsModel(); createdModel.setId(statementId); - createdModel.setTaskId(businessKey); + createdModel.setBusinessKey(businessKey); Mockito.when(workflowService.startProcessLatestVersion()).thenReturn(businessKey); @@ -1065,11 +1078,11 @@ StatementDetailsModel statementModel = new StatementDetailsModel(); statementModel.setId(statementId); - statementModel.setTaskId(fakeTaskId); + statementModel.setBusinessKey(fakeTaskId); StatementDetailsModel createdModel = new StatementDetailsModel(); createdModel.setId(statementId); - createdModel.setTaskId(businessKey); + createdModel.setBusinessKey(businessKey); Mockito.when(workflowService.startProcessLatestVersion()).thenReturn(businessKey); @@ -1087,11 +1100,11 @@ StatementDetailsModel statementModel = new StatementDetailsModel(); statementModel.setId(statementId); - statementModel.setTaskId(fakeTaskId); + statementModel.setBusinessKey(fakeTaskId); StatementDetailsModel createdModel = new StatementDetailsModel(); createdModel.setId(statementId); - createdModel.setTaskId(businessKey); + createdModel.setBusinessKey(businessKey); Mockito.when(workflowService.startProcessLatestVersion()).thenReturn(businessKey); Mockito.doThrow(new InternalErrorServiceException()).when(statementService).createStatement(Mockito.any()); @@ -1103,5 +1116,57 @@ // pass } } + + @Test + void testCheAndHandleServiceTasksSuccessfulProcessingTask() throws InternalErrorServiceException, InterruptedException, ExecutionException, BadRequestServiceException { + String workerId = "workerId"; + String taskId = "taskId"; + String testTopic = "testTopicTrue"; + + List<ExternalTaskModel> externalTasks = new ArrayList<>(); + ExternalTaskModel externalTask = new ExternalTaskModel(); + externalTask.setTopicName(testTopic); + externalTask.setWorkerId(workerId); + externalTask.setId(taskId); + externalTasks.add(externalTask); + + workers.clear(); + workers.add(new TestWorkerTrue()); + Set<String> testTopics = new HashSet<>(); + testTopics.add(testTopic); + Mockito.when(workflowService.fetchAndLockExternalTasks(Mockito.eq(testTopics), Mockito.eq(workerId))).thenReturn(Optional.of(externalTasks)); + + Mockito.when(workflowService.completeExternalTask(Mockito.eq(taskId), Mockito.eq(workerId), Mockito.anyMap())).thenReturn(Optional.of(true)); + + statementProcessService.checkAndHandleServiceTasks(); + + + } + + @Test + void testCheAndHandleServiceTasksErrorProcessingTask() throws InternalErrorServiceException, BadRequestServiceException, InterruptedException, ExecutionException { + String workerId = "workerId"; + String taskId = "taskId"; + String testTopic = "testTopicFalse"; + + workers.clear(); + workers.add(new TestWorkerFalse()); + + List<ExternalTaskModel> externalTasks = new ArrayList<>(); + ExternalTaskModel externalTask = new ExternalTaskModel(); + externalTask.setTopicName(testTopic); + externalTask.setWorkerId(workerId); + externalTask.setId(taskId); + externalTasks.add(externalTask); + + Set<String> testTopics = new HashSet<>(); + testTopics.add(testTopic); + Mockito.when(workflowService.fetchAndLockExternalTasks(Mockito.eq(testTopics), Mockito.eq(workerId))).thenReturn(Optional.of(externalTasks)); + + Mockito.when(workflowService.failureExternalTask(Mockito.eq(taskId), Mockito.eq(workerId), Mockito.eq(TestWorkerFalse.ERROR_MESSAGE))).thenReturn(Optional.of(true)); + + statementProcessService.checkAndHandleServiceTasks(); + + } }
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementServiceTest.java index d636213..851799f 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementServiceTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/StatementServiceTest.java
@@ -44,6 +44,7 @@ import org.mockito.stubbing.Answer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; /** * Test verifies SessionService interfaces. @@ -52,6 +53,8 @@ * */ @SpringBootTest(classes = TestConfiguration.class) +@ActiveProfiles("test") + class StatementServiceTest { @Autowired @@ -71,7 +74,7 @@ TblStatement tblstatement = Mockito.mock(TblStatement.class); String sDueDate = "2020-04-22"; String SReceiptDate = "2020-04-22"; - String sTaskId = "123e4567-e89b-12d3-a456-426655440000"; + String sBusinessKey = "123e4567-e89b-12d3-a456-426655440000"; String city = "City"; String district = "District"; String title = "title"; @@ -82,7 +85,7 @@ Mockito.when(tblstatement.getReceiptDate()).thenReturn(TypeConversion.dateOfDateString(SReceiptDate).get()); Mockito.when(tblstatement.getFinished()).thenReturn(false); Mockito.when(tblstatement.getId()).thenReturn(12L); - Mockito.when(tblstatement.getTaskId()).thenReturn(TypeConversion.taskIdOfString(sTaskId).get()); + Mockito.when(tblstatement.getTaskId()).thenReturn(TypeConversion.businessKeyOfString(sBusinessKey).get()); Mockito.when(tblstatement.getDistrict()).thenReturn(district); Mockito.when(tblstatement.getCity()).thenReturn(city); Mockito.when(tblstatement.getTitle()).thenReturn(title); @@ -93,7 +96,7 @@ assertEquals(12L, oStatementDetails.get().getId()); assertEquals(sDueDate, oStatementDetails.get().getDueDate()); assertEquals(SReceiptDate, oStatementDetails.get().getReceiptDate()); - assertEquals(sTaskId, oStatementDetails.get().getTaskId()); + assertEquals(sBusinessKey, oStatementDetails.get().getBusinessKey()); assertEquals(false, oStatementDetails.get().getFinished()); assertEquals(1L, oStatementDetails.get().getTypeId()); assertEquals(city, oStatementDetails.get().getCity()); @@ -115,12 +118,12 @@ void finishStatementWithValidStatementIdStatementNotFinishedYetRespondsWithOptionalTrue() { TblStatement tblstatementorig = Mockito.mock(TblStatement.class); String sDueDate = "2020-04-22"; - String sTaskId = "123e4567-e89b-12d3-a456-426655440000"; + String sBusinessKey = "123e4567-e89b-12d3-a456-426655440000"; String title = "title"; Mockito.when(tblstatementorig.getDueDate()).thenReturn(TypeConversion.dateOfDateString(sDueDate).get()); Mockito.when(tblstatementorig.getFinished()).thenReturn(false); Mockito.when(tblstatementorig.getId()).thenReturn(12L); - Mockito.when(tblstatementorig.getTaskId()).thenReturn(TypeConversion.taskIdOfString(sTaskId).get()); + Mockito.when(tblstatementorig.getTaskId()).thenReturn(TypeConversion.businessKeyOfString(sBusinessKey).get()); Mockito.when(tblstatementorig.getTitle()).thenReturn(title); Mockito.when(statementRepository.findById(12L)).thenReturn(Optional.of(tblstatementorig)); @@ -128,7 +131,7 @@ Mockito.when(tblstatementchanged.getDueDate()).thenReturn(TypeConversion.dateOfDateString(sDueDate).get()); Mockito.when(tblstatementchanged.getFinished()).thenReturn(true); Mockito.when(tblstatementchanged.getId()).thenReturn(12L); - Mockito.when(tblstatementchanged.getTaskId()).thenReturn(TypeConversion.taskIdOfString(sTaskId).get()); + Mockito.when(tblstatementchanged.getTaskId()).thenReturn(TypeConversion.businessKeyOfString(sBusinessKey).get()); Mockito.when(tblstatementchanged.getTitle()).thenReturn(title); Mockito.when(statementRepository.save(tblstatementchanged)).thenReturn(tblstatementchanged); @@ -156,14 +159,14 @@ void createStatementWithValidStatementDetailsModelRespondsWithOptionalStatementDetailsModel() throws InternalErrorServiceException, BadRequestServiceException { String sDueDate = "2020-04-22"; String sReceiptDate = "2020-04-22"; - String sTaskId = "123e4567-e89b-12d3-a456-426655440000"; + String sBusinessKey = "123e4567-e89b-12d3-a456-426655440000"; String title = "Title"; String city = "City"; String district = "District"; StatementDetailsModel model = new StatementDetailsModel(); model.setFinished(true); model.setDueDate(sDueDate); - model.setTaskId(sTaskId); + model.setBusinessKey(sBusinessKey); model.setTitle(title); model.setReceiptDate(sReceiptDate); model.setCity(city); @@ -182,7 +185,7 @@ .thenReturn(TypeConversion.dateOfDateString(sReceiptDate).get()); Mockito.when(tblstatementchanged.getFinished()).thenReturn(true); Mockito.when(tblstatementchanged.getId()).thenReturn(12L); - Mockito.when(tblstatementchanged.getTaskId()).thenReturn(TypeConversion.taskIdOfString(sTaskId).get()); + Mockito.when(tblstatementchanged.getTaskId()).thenReturn(TypeConversion.businessKeyOfString(sBusinessKey).get()); Mockito.when(tblstatementchanged.getTitle()).thenReturn(title); Mockito.when(tblstatementchanged.getCity()).thenReturn(city); Mockito.when(tblstatementchanged.getDistrict()).thenReturn(district); @@ -196,7 +199,7 @@ TblStatement statement = (TblStatement) args[0]; // Replaced by the service if set. assertNull(statement.getId()); - assertEquals(model.getTaskId(), TypeConversion.stringOfTaskId(statement.getTaskId()).get()); + assertEquals(model.getBusinessKey(),TypeConversion.stringOfBusinessKey(statement.getTaskId()).get()); assertEquals(false, statement.getFinished()); // Should match the model. assertEquals(model.getDueDate(), @@ -220,7 +223,7 @@ assertEquals(model.getFinished(), response.getFinished()); assertEquals(model.getDueDate(), response.getDueDate()); assertEquals(model.getReceiptDate(), response.getReceiptDate()); - assertEquals(model.getTaskId(), response.getTaskId()); + assertEquals(model.getBusinessKey(), response.getBusinessKey()); assertEquals(model.getTitle(), response.getTitle()); assertEquals(model.getCity(), response.getCity()); assertEquals(model.getDistrict(), response.getDistrict());
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoServiceTest.java index bf148a6..63b369c 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoServiceTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/UserInfoServiceTest.java
@@ -25,7 +25,7 @@ import java.util.Set; import org.eclipse.openk.statementpublicaffairs.StatementPublicAffairsApplication; -import org.eclipse.openk.statementpublicaffairs.config.auth.UserDetails; +import org.eclipse.openk.statementpublicaffairs.model.UserDetails; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -35,6 +35,7 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.test.context.ActiveProfiles; /** * Verify UserInfoService interfaces. @@ -42,6 +43,8 @@ * */ @SpringBootTest(classes = StatementPublicAffairsApplication.class) +@ActiveProfiles("test") + class UserInfoServiceTest { @Autowired
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/VersionServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/VersionServiceTest.java index ff2004d..ce3002a 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/VersionServiceTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/VersionServiceTest.java
@@ -20,6 +20,7 @@ import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.util.ReflectionTestUtils; /** @@ -29,6 +30,8 @@ * */ @SpringBootTest(classes = StatementPublicAffairsApplication.class) +@ActiveProfiles("test") + class VersionServiceTest { @Autowired
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowServiceTest.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowServiceTest.java index f4d3766..ca1fe41 100644 --- a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowServiceTest.java +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/WorkflowServiceTest.java
@@ -14,322 +14,1535 @@ */ package org.eclipse.openk.statementpublicaffairs.service; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import java.time.ZonedDateTime; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; +import java.util.Set; + +import org.eclipse.openk.statementpublicaffairs.api.CamundaApi; import org.eclipse.openk.statementpublicaffairs.config.TestConfigurationWorkflowService; +import org.eclipse.openk.statementpublicaffairs.exceptions.BadRequestServiceException; +import org.eclipse.openk.statementpublicaffairs.exceptions.InternalErrorServiceException; +import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskModel; +import org.eclipse.openk.statementpublicaffairs.model.ProcessActivityHistoryModel; +import org.eclipse.openk.statementpublicaffairs.model.ProcessDefinitionModel; +import org.eclipse.openk.statementpublicaffairs.model.WorkflowTaskModel; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaClaimTaskRequestBody; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaCompleteExternalTaskRequestBody; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaExternalTaskFetchAndLockRsp; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaFailureExternalTaskRequestBody; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaFetchAndLockExtTaskRequestBody; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaProcessDefinition; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaProcessDefinitionStartReq; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaProcessDefinitionStartRsp; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaProcessHistoryStep; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaProcessInstance; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaTaskInstance; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaVariable; +import org.eclipse.openk.statementpublicaffairs.model.camunda.CamundaVariablesRequestBody; +import org.eclipse.openk.statementpublicaffairs.util.TypeConversion; +import org.eclipse.openk.statementpublicaffairs.viewmodel.WorkflowTaskVariableModel; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import feign.FeignException; +import feign.Request; +import feign.Request.Body; +import feign.Response; @SpringBootTest(classes = TestConfigurationWorkflowService.class) +@ActiveProfiles("test") + class WorkflowServiceTest { -// -// @Test -// public void getProcessDefinitionWithValidBusinessKeyShouldRespondWithProcessDefinition() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getProcessDefinitionWithInvalidBusinessKeyShouldRespondWithOptionalEmpty() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getProcessDefinitionWithValidBusinessKeyExceptionGettingProcessInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getProcessDefinitionWithValidBusinessKeyExceptionGettingProcessDefinitionFromWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void startProcessLatestVersionShouldRespondWithUUIDBasedBusinessKeyString() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void startProcessLatestVersionExceptionStartingProcessInstanceWithWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getCurrentTaskOfProcessBusinessKeyWithValidBusinessKeyShouldRespondWithListOfCurrentWorkflowTaskModels() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getCurrentTaskOfProcessBusinessKeyWithInvalidBusinessKeyShouldRespondWithOptionalEmpty() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getCurrentTaskOfProcessBusinessKeyWithValidBusinessKeyExceptionGettingProcessInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getCurrentTaskOfProcessBusinessKeyWithValidBusinessKeyExceptionGettingCurrentTaskInstancesFromWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getStatementProcessHistoryWithValidBusinessKeyShouldRespondWithListOfTaskHistoryEntries() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getStatementProcessHistoryWithInvalidBusinessKeyShouldRespondOptionalEmpty() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getStatementProcessHistoryWithValidBusinessKeyMoreThanOneProcessInstancesWithSameBusinessKeyShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getStatementProcessHistoryWithValidBusinessKeyExceptionGettingProcessInstanceFromWorkflowEngineShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void getStatementProcessHistoryWithValidBusinessKeyExceptionGettingProcessHistoryFromWorkflowEngineShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void claimTaskWithValidTaskIdAndAssigneeShouldRespondWorkflowDetails() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void claimTaskWithInvalidTaskIdShouldRespondOptionalEmpty() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void claimTaskWithValidTaskIdExceptionClaimingTaskInstanceInWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void claimTaskWithValidTaskIdExceptionGettingTaskInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void claimTaskWithValidTaskIdInvalidResponseCLaimingTaskInWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void unClaimTaskWithValidTaskIdShouldRespondWorkflowDetails() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void unClaimTaskWithInvalidTaskIdShouldRespondOptionalEmpty() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void unClaimTaskWithValidTaskIdExceptionUnclaimingTaskInstanceInWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void unClaimTaskWithValidTaskIdExceptionGettingTaskInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void unClaimTaskWithValidTaskIdInvalidResponseUnclaimingTaskInWorkflowEngineThrowsInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeTaskWithValidTaskIdAndCompleteVariablesShouldRespondWithTrue() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeTaskWithInvalidTaskIdShouldRespondWithOptionalEmpty() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completetTaskWithValidTaskIdAndExceptionCompleteTaskInWorkflowEngineShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeTaskWithValidTaskIdAndBadRequestResponseCompleteTaskInWorkflowEngineShouldThrowBadRequestServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeTaskWithValidTaskIdAndInternalServerErrorResponseCompleteTaskInWorkflowEngineShouldInternalServerErrorException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeTaskWithValidTaskIdAndInvalidResponseCompleteTaskInWorkflowEngineShouldInternalServerErrorException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void fetchAndLockExternalTasksWithValidSetOfTopicsAndValidWorkerIdShouldRespondWithListOfExternalTasks() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void fetchAndLockExternalTasksWithValidSetOfTopicsAndValidWorkerIdExceptionAccessingTheWorkflowEnfineShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeExternalTaskWithValidTaskIdAndValidWorkerIdAndCompleteVariablesShouldRespondTrue() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeExternalTasksWithValidTaskIdAndValidWorkerIdExceptionAccessingTheWorkflowEngineShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeExternalTaskWithInValidTaskIdOfShouldThrowBadRequestServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeExternalTaskWithValidTaskIdAndInvalidWorkerIdShouldThrowBadRequestServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeExternalTaskWithValidTaskIdAndValidWorkerIdInternalServerErrorResponseFromWorkflowEngineShouldRespondWithFalse() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void completeExternalTaskWithValidTaskIdAndValidWorkerIdInvalidResponseFromWorkflowEngineShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void failureExternalTaskWithValidTaskIdAndValidWorkerIdShouldRespondWithTrue() { -// fail("Not implemented Yet."); -// -// } -// -// @Test -// public void failureExternalTaskWithInvalidTaskIdShouldThrowBadRequestServiceException() { -// fail("Not implemented Yet."); -// -// } -// -// @Test -// public void failureExternalTaskWithValidTaskIdAndInvalidWorkerIdShouldThrowBadRequestServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void failureExternalTaskWithValidTaskIdAndValidWorkerIdExceptionAccessingWorkflowengineShouldThrowInternalErrorServiceException() { -// fail("Not implemented Yet."); -// -// } -// -// @Test -// public void failureExternalTaskWithValidTaskIdAndValidWorkerIdInternalServerErrorResponseFromWorkflowShouldRespondWithFalse() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void failureExternalTaskWithValidTaskIdAndValidWorkerIdInvalidResponseFromWorkflowShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void deleteProcessInstanceWithValidBusinessKeyShouldRespondTrue() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void deleteProcessInstanceWithInvalidBusinessKeyShouldThrowBadRequestServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void deleteProcessInstanceWithValidBusinessKeyExceptionGettingProceessInstanceShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void deleteProcessInstanceWithValidBusinessKeyMoreThanOneProcessInstanceWithSameBusinessKeyShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void deleteProcessInstanceWithValidBusinessKeyExceptionDeleteProcessInstanceInWorkflowEngineShouldThrowInternalErrorServiceException() { -// fail("Not implemented Yet."); -// -// } -// -// @Test -// public void deleteProcessInstanceWithValidBusinessKeyNotFoundResponseDeleteProcessInstanceInWorkflowEngineShouldThrowBadRequestServiceException() { -// -// fail("Not implemented Yet."); -// } -// -// @Test -// public void deleteProcessInstanceWithValidBusinessKeyInvalidResponseDeleteProcessInstanceInWorkflowEngineShouldThrowInternalErrorServiceException() { -// -// fail("Not implemented Yet."); -// } + + @Autowired + private WorkflowService workflowService; + + @Autowired + private CamundaApi camundaApi; + + @Value("${workflow.processDefinitionKey}") + private String processDefinitionKey; + + @Value("${workflow.tenantId}") + private String tenantId; + + @Test + public void getProcessDefinitionWithValidBusinessKeyShouldRespondWithProcessDefinition() + throws InternalErrorServiceException { + String businessKey = "businessKey"; + String definitionId = "definitionId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + processInstances.add(pi); + + String id = "id"; + String key = "key"; + String category = "category"; + String description = "description"; + String name = "name"; + Long version = 1L; + String resource = "resource"; + String tenantId = "tenantId"; + String versionTag = "versionTag"; + + CamundaProcessDefinition processDefinition = new CamundaProcessDefinition(); + processDefinition.setId(id); + processDefinition.setKey(key); + processDefinition.setCategory(category); + processDefinition.setDescription(description); + processDefinition.setName(name); + processDefinition.setVersion(version); + processDefinition.setResource(resource); + processDefinition.setTenantId(tenantId); + processDefinition.setVersionTag(versionTag); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + Mockito.when(camundaApi.getProcessDefinitionForId(Mockito.anyString(), Mockito.eq(definitionId))) + .thenReturn(processDefinition); + + Optional<ProcessDefinitionModel> oPD = workflowService.getProcessDefinition(businessKey); + + assertTrue(oPD.isPresent()); + + ProcessDefinitionModel pd = oPD.get(); + + assertEquals(id, pd.getId()); + assertEquals(key, pd.getKey()); + assertEquals(category, pd.getCategory()); + assertEquals(description, pd.getDescription()); + assertEquals(name, pd.getName()); + assertEquals(version, pd.getVersion()); + assertEquals(resource, pd.getResource()); + assertEquals(tenantId, pd.getTenantId()); + assertEquals(versionTag, pd.getVersionTag()); + } + + @Test + public void getProcessDefinitionWithInvalidBusinessKeyShouldRespondWithOptionalEmpty() + throws InternalErrorServiceException { + String businessKey = "404"; + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(new ArrayList<CamundaProcessInstance>()); + + assertFalse(workflowService.getProcessDefinition(businessKey).isPresent()); + } + + @Test + public void getProcessDefinitionWithValidBusinessKeyExceptionGettingProcessInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { + + String businessKey = "businessKey"; + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), Mockito.eq(businessKey)); + + try { + workflowService.getProcessDefinition(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void getProcessDefinitionWithValidBusinessKeyExceptionGettingProcessDefinitionFromWorkflowEngineThrowsInternalErrorServiceException() { + + String businessKey = "businessKey"; + String definitionId = "definitionId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + processInstances.add(pi); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).getProcessDefinitionForId(Mockito.anyString(), Mockito.eq(definitionId)); + + try { + workflowService.getProcessDefinition(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + } + + @Test + public void startProcessLatestVersionShouldRespondWithUUIDBasedBusinessKeyString() + throws InternalErrorServiceException { + + String businessKey = "businessKey"; + CamundaProcessDefinitionStartRsp resp = new CamundaProcessDefinitionStartRsp(); + resp.setBusinessKey(businessKey); + Mockito.when(camundaApi.startProcess(Mockito.eq(processDefinitionKey), Mockito.eq(tenantId), + Mockito.anyString(), Mockito.any(CamundaProcessDefinitionStartReq.class))).thenReturn(resp); + + assertEquals(businessKey, workflowService.startProcessLatestVersion()); + } + + @Test + public void startProcessLatestVersionExceptionStartingProcessInstanceWithWorkflowEngineThrowsInternalErrorServiceException() { + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).startProcess(Mockito.eq(processDefinitionKey), Mockito.eq(tenantId), + Mockito.anyString(), Mockito.any(CamundaProcessDefinitionStartReq.class)); + + try { + workflowService.startProcessLatestVersion(); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + } + + @Test + public void getCurrentTaskOfProcessBusinessKeyWithValidBusinessKeyShouldRespondWithListOfCurrentWorkflowTaskModels() + throws InternalErrorServiceException { + + String businessKey = "businessKey"; + String definitionId = "definitionId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + processInstances.add(pi); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + List<CamundaTaskInstance> cTasks = new ArrayList<>(); + CamundaTaskInstance task = new CamundaTaskInstance(); + + String taskId = "taskId"; + String processInstanceId = "processInstanceId"; + String assignee = "assignee"; + String taskDefinitionKey = "taskDefinitionKey"; + Boolean suspended = false; + String owner = "owner"; + String name = "name"; + String description = "description"; + String due = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + String created = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + String formKey = "formKey"; + task.setId(taskId); + task.setProcessInstanceId(processInstanceId); + task.setAssignee(assignee); + task.setTenantId(tenantId); + task.setTaskDefinitionKey(taskDefinitionKey); + task.setSuspended(suspended); + task.setOwner(owner); + task.setName(name); + task.setDescription(description); + task.setDue(due); + task.setCreated(created); + task.setFormKey(formKey); + cTasks.add(task); + + Map<String, CamundaVariable> rVariables = new HashMap<>(); + CamundaVariable var = new CamundaVariable(); + var.setLocal(false); + var.setType("Boolean"); + rVariables.put("_var", var); + + Mockito.when(camundaApi.getCurrentTaskInstancesWithProcessInstanceBusinessKey(Mockito.anyString(), + Mockito.eq(processDefinitionKey), Mockito.eq(businessKey))).thenReturn(cTasks); + + Mockito.when(camundaApi.getTaskInstanceFormVariables(Mockito.anyString(), Mockito.eq(taskId))) + .thenReturn(rVariables); + + Optional<List<WorkflowTaskModel>> oTasks = workflowService.getCurrentTasksOfProcessBusinessKey(businessKey); + + assertTrue(oTasks.isPresent()); + List<WorkflowTaskModel> tasks = oTasks.get(); + WorkflowTaskModel wTask = tasks.get(0); + assertEquals(taskId, wTask.getTaskId()); + assertEquals(processInstanceId, wTask.getProcessInstanceId()); + assertEquals(assignee, wTask.getAssignee()); + assertEquals(taskDefinitionKey, wTask.getTaskDefinitionKey()); + assertEquals(suspended, wTask.getSuspended()); + assertEquals(owner, wTask.getOwner()); + assertEquals(name, wTask.getName()); + assertEquals(description, wTask.getDescription()); + assertEquals(due, TypeConversion.camundaDateStringOfZDT(wTask.getDue()).get()); + assertEquals(created, TypeConversion.camundaDateStringOfZDT(wTask.getCreated()).get()); + assertEquals(formKey, wTask.getFormKey()); + assertEquals(processDefinitionKey, wTask.getProcessDefinitionKey()); + assertEquals(var.getType(), wTask.getRequiredVariables().get("var")); + } + + @Test + public void getCurrentTaskOfProcessBusinessKeyWithInvalidBusinessKeyShouldRespondWithOptionalEmpty() + throws InternalErrorServiceException { + String businessKey = "businessKey"; + + assertFalse(workflowService.getCurrentTasksOfProcessBusinessKey(businessKey).isPresent()); + } + + @Test + public void getCurrentTaskOfProcessBusinessKeyWithValidBusinessKeyExceptionGettingProcessInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { + + String businessKey = "businessKey"; + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), Mockito.eq(businessKey)); + + try { + workflowService.getCurrentTasksOfProcessBusinessKey(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void getCurrentTaskOfProcessBusinessKeyWithValidBusinessKeyExceptionGettingCurrentTaskInstancesFromWorkflowEngineThrowsInternalErrorServiceException() { + + String businessKey = "businessKey"; + String definitionId = "definitionId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + processInstances.add(pi); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).getCurrentTaskInstancesWithProcessInstanceBusinessKey(Mockito.anyString(), + Mockito.eq(processDefinitionKey), Mockito.eq(businessKey)); + + try { + workflowService.getCurrentTasksOfProcessBusinessKey(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void getStatementProcessHistoryWithValidBusinessKeyShouldRespondWithListOfTaskHistoryEntries() + throws InternalErrorServiceException { + String businessKey = "businessKey"; + String definitionId = "definitionId"; + String processInstanceId = "processInstanceId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processInstanceId); + processInstances.add(pi); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + List<CamundaProcessHistoryStep> historySteps = new ArrayList<>(); + + CamundaProcessHistoryStep step = new CamundaProcessHistoryStep(); + + String id = "id"; + String activityName = "activityName"; + String activityType = "activityType"; + String activityId = "activityId"; + String assignee = "assignee"; + String startTime = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + String endTime = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + Long durationInMillis = 1000L; + String processDefinitionKey = "processDefinitionKey"; + String processDefinitionId = "processDefinitionId"; + Boolean canceled = false; + Boolean completeScope = true; + String tenantId = "tenantId"; + step.setId(id); + step.setActivityName(activityName); + step.setActivityType(activityType); + step.setActivityId(activityId); + step.setAssignee(assignee); + step.setStartTime(startTime); + step.setEndTime(endTime); + step.setDurationInMillis(durationInMillis); + step.setProcessDefinitionKey(processDefinitionKey); + step.setProcessDefinitionId(processDefinitionId); + step.setCanceled(canceled); + step.setCompleteScope(completeScope); + step.setTenantId(tenantId); + historySteps.add(step); + + Mockito.when(camundaApi.getProcessHistory(Mockito.anyString(), Mockito.eq(processInstanceId))) + .thenReturn(historySteps); + + Optional<List<ProcessActivityHistoryModel>> oHistory = workflowService.getStatementProcessHistory(businessKey); + assertTrue(oHistory.isPresent()); + + List<ProcessActivityHistoryModel> history = oHistory.get(); + + ProcessActivityHistoryModel hstep = history.get(0); + + assertEquals(id, hstep.getId()); + assertEquals(activityName, hstep.getActivityName()); + assertEquals(activityId, hstep.getActivityId()); + assertEquals(assignee, hstep.getAssignee()); + assertEquals(startTime, TypeConversion.camundaDateStringOfZDT(hstep.getStartTime()).get()); + assertEquals(endTime, TypeConversion.camundaDateStringOfZDT(hstep.getEndTime()).get()); + assertEquals(durationInMillis, hstep.getDurationInMillis()); + assertEquals(processDefinitionKey, hstep.getProcessDefinitionKey()); + assertEquals(processDefinitionId, hstep.getProcessDefinitionId()); + assertEquals(canceled, hstep.getCanceled()); + assertEquals(completeScope, hstep.getCompleteScope()); + assertEquals(tenantId, hstep.getTenantId()); + } + + @Test + public void getStatementProcessHistoryWithInvalidBusinessKeyShouldRespondOptionalEmpty() + throws InternalErrorServiceException { + + String businessKey = "404"; + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(new ArrayList<CamundaProcessInstance>()); + assertFalse(workflowService.getStatementProcessHistory(businessKey).isPresent()); + + } + + @Test + public void getStatementProcessHistoryWithValidBusinessKeyMoreThanOneProcessInstancesWithSameBusinessKeyShouldThrowInternalErrorServiceException() { + + String businessKey = "businessKey"; + String definitionId = "definitionId"; + String processInstanceId = "processInstanceId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processInstanceId); + processInstances.add(pi); + processInstances.add(pi); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + try { + workflowService.getStatementProcessHistory(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void getStatementProcessHistoryWithValidBusinessKeyExceptionGettingProcessInstanceFromWorkflowEngineShouldThrowInternalErrorServiceException() { + + String businessKey = "404"; + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), Mockito.eq(businessKey)); + + try { + workflowService.getStatementProcessHistory(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void getStatementProcessHistoryWithValidBusinessKeyExceptionGettingProcessHistoryFromWorkflowEngineShouldThrowInternalErrorServiceException() { + + String businessKey = "businessKey"; + String definitionId = "definitionId"; + String processInstanceId = "processInstanceId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processInstanceId); + processInstances.add(pi); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).getProcessHistory(Mockito.anyString(), Mockito.eq(processInstanceId)); + + try { + workflowService.getStatementProcessHistory(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void claimTaskWithValidTaskIdAndAssigneeShouldRespondWorkflowDetails() throws InternalErrorServiceException { + + String assignee = "assignee"; + String taskId = "taskId"; + + Response response = Response.builder().headers(Collections.emptyMap()).status(204).request( + Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.claimTaskInstance(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaClaimTaskRequestBody.class))).thenReturn(response); + + String processInstanceId = "processInstanceId"; + String taskDefinitionKey = "taskDefinitionKey"; + Boolean suspended = false; + String owner = "owner"; + String name = "name"; + String description = "description"; + String due = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + String created = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + String formKey = "formKey"; + + CamundaTaskInstance cTask = new CamundaTaskInstance(); + cTask.setId(taskId); + cTask.setProcessInstanceId(processInstanceId); + cTask.setAssignee(assignee); + cTask.setTenantId(tenantId); + cTask.setTaskDefinitionKey(taskDefinitionKey); + cTask.setSuspended(suspended); + cTask.setOwner(owner); + cTask.setName(name); + cTask.setDescription(description); + cTask.setDue(due); + cTask.setCreated(created); + cTask.setFormKey(formKey); + + Mockito.when(camundaApi.getTaskInstance(Mockito.anyString(), Mockito.eq(taskId))).thenReturn(cTask); + + Map<String, CamundaVariable> rVariables = new HashMap<>(); + CamundaVariable var = new CamundaVariable(); + var.setLocal(false); + var.setType("Boolean"); + rVariables.put("_var", var); + + Mockito.when(camundaApi.getTaskInstanceFormVariables(Mockito.anyString(), Mockito.eq(taskId))) + .thenReturn(rVariables); + + Optional<WorkflowTaskModel> oTask = workflowService.claimTask(taskId, assignee); + assertTrue(oTask.isPresent()); + WorkflowTaskModel wTask = oTask.get(); + + assertEquals(taskId, wTask.getTaskId()); + assertEquals(processInstanceId, wTask.getProcessInstanceId()); + assertEquals(processDefinitionKey, wTask.getProcessDefinitionKey()); + assertEquals(assignee, wTask.getAssignee()); + assertEquals(tenantId, wTask.getTenantId()); + assertEquals(taskDefinitionKey, wTask.getTaskDefinitionKey()); + assertEquals(suspended, wTask.getSuspended()); + assertEquals(owner, wTask.getOwner()); + assertEquals(name, wTask.getName()); + assertEquals(description, wTask.getDescription()); + assertEquals(due, TypeConversion.camundaDateStringOfZDT(wTask.getDue()).get()); + assertEquals(created, TypeConversion.camundaDateStringOfZDT(wTask.getCreated()).get()); + assertEquals(formKey, wTask.getFormKey()); + + assertEquals(var.getType(), wTask.getRequiredVariables().get("var")); + + } + + @Test + public void claimTaskWithInvalidTaskIdShouldRespondOptionalEmpty() throws InternalErrorServiceException { + + String assignee = "assignee"; + String taskId = "taskId"; + + Response response = Response.builder().headers(Collections.emptyMap()).status(500).request( + Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.claimTaskInstance(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaClaimTaskRequestBody.class))).thenReturn(response); + + assertFalse(workflowService.claimTask(taskId, assignee).isPresent()); + + } + + @Test + public void claimTaskWithValidTaskIdExceptionClaimingTaskInstanceInWorkflowEngineThrowsInternalErrorServiceException() { + + String assignee = "assignee"; + String taskId = "taskId"; + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).claimTaskInstance(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaClaimTaskRequestBody.class)); + + try { + workflowService.claimTask(taskId, assignee); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void claimTaskWithValidTaskIdExceptionGettingTaskInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { + + String assignee = "assignee"; + String taskId = "taskId"; + + Response response = Response.builder().headers(Collections.emptyMap()).status(204).request( + Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.claimTaskInstance(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaClaimTaskRequestBody.class))).thenReturn(response); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).getTaskInstance(Mockito.anyString(), Mockito.eq(taskId)); + + try { + workflowService.claimTask(taskId, assignee); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void unClaimTaskWithValidTaskIdShouldRespondWorkflowDetails() throws InternalErrorServiceException { + + String taskId = "taskId"; + + Response response = Response.builder().headers(Collections.emptyMap()).status(204).request( + Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.unclaimTaskInstance(Mockito.anyString(), Mockito.eq(taskId))).thenReturn(response); + + String processInstanceId = "processInstanceId"; + String taskDefinitionKey = "taskDefinitionKey"; + Boolean suspended = false; + String owner = "owner"; + String name = "name"; + String description = "description"; + String due = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + String created = TypeConversion.camundaDateStringOfZDT(ZonedDateTime.now()).get(); + String formKey = "formKey"; + + CamundaTaskInstance cTask = new CamundaTaskInstance(); + cTask.setId(taskId); + cTask.setProcessInstanceId(processInstanceId); + cTask.setAssignee(null); + cTask.setTenantId(tenantId); + cTask.setTaskDefinitionKey(taskDefinitionKey); + cTask.setSuspended(suspended); + cTask.setOwner(owner); + cTask.setName(name); + cTask.setDescription(description); + cTask.setDue(due); + cTask.setCreated(created); + cTask.setFormKey(formKey); + + Mockito.when(camundaApi.getTaskInstance(Mockito.anyString(), Mockito.eq(taskId))).thenReturn(cTask); + + Map<String, CamundaVariable> rVariables = new HashMap<>(); + CamundaVariable var = new CamundaVariable(); + var.setLocal(false); + var.setType("Boolean"); + rVariables.put("_var", var); + + Mockito.when(camundaApi.getTaskInstanceFormVariables(Mockito.anyString(), Mockito.eq(taskId))) + .thenReturn(rVariables); + + Optional<WorkflowTaskModel> oTask = workflowService.unClaimTask(taskId); + assertTrue(oTask.isPresent()); + WorkflowTaskModel wTask = oTask.get(); + + assertEquals(taskId, wTask.getTaskId()); + assertEquals(processInstanceId, wTask.getProcessInstanceId()); + assertEquals(processDefinitionKey, wTask.getProcessDefinitionKey()); + assertNull(wTask.getAssignee()); + assertEquals(tenantId, wTask.getTenantId()); + assertEquals(taskDefinitionKey, wTask.getTaskDefinitionKey()); + assertEquals(suspended, wTask.getSuspended()); + assertEquals(owner, wTask.getOwner()); + assertEquals(name, wTask.getName()); + assertEquals(description, wTask.getDescription()); + assertEquals(due, TypeConversion.camundaDateStringOfZDT(wTask.getDue()).get()); + assertEquals(created, TypeConversion.camundaDateStringOfZDT(wTask.getCreated()).get()); + assertEquals(formKey, wTask.getFormKey()); + + assertEquals(var.getType(), wTask.getRequiredVariables().get("var")); + + } + + @Test + public void unClaimTaskWithInvalidTaskIdShouldRespondOptionalEmpty() throws InternalErrorServiceException { + + String taskId = "taskId"; + + Response response = Response.builder().headers(Collections.emptyMap()).status(400).request( + Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.unclaimTaskInstance(Mockito.anyString(), Mockito.eq(taskId))).thenReturn(response); + + assertFalse(workflowService.unClaimTask(taskId).isPresent()); + + } + + @Test + public void unClaimTaskWithValidTaskIdExceptionUnclaimingTaskInstanceInWorkflowEngineThrowsInternalErrorServiceException() { + + String taskId = "taskId"; + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).unclaimTaskInstance(Mockito.anyString(), Mockito.eq(taskId)); + + try { + workflowService.unClaimTask(taskId); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void unClaimTaskWithValidTaskIdExceptionGettingTaskInstanceFromWorkflowEngineThrowsInternalErrorServiceException() { + + String taskId = "taskId"; + + Response response = Response.builder().headers(Collections.emptyMap()).status(204).request( + Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.unclaimTaskInstance(Mockito.anyString(), Mockito.eq(taskId))).thenReturn(response); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi).getTaskInstance(Mockito.anyString(), Mockito.eq(taskId)); + + try { + workflowService.unClaimTask(taskId); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void completeTaskWithValidTaskIdAndCompleteVariablesShouldRespondWithTrue() + throws InternalErrorServiceException, BadRequestServiceException { + String taskId = "taskId"; + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); + var.setType("Boolean"); + var.setValue(true); + variables.put("var", var); + + Response response = Response.builder().headers(Collections.emptyMap()).status(204).request( + Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeTask(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaVariablesRequestBody.class))).thenReturn(response); + + Optional<Boolean> oCompleted = workflowService.completeTask(taskId, variables); + assertTrue(oCompleted.isPresent()); + assertTrue(oCompleted.get()); + + } + + @Test + public void completetTaskWithValidTaskIdAndExceptionCompleteTaskInWorkflowEngineShouldThrowInternalErrorServiceException() + throws BadRequestServiceException { + String taskId = "taskId"; + + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); + var.setType("Boolean"); + var.setValue(true); + variables.put("var", var); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .completeTask(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaVariablesRequestBody.class)); + + try { + workflowService.completeTask(taskId, variables); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void completeTaskWithValidTaskIdAndBadRequestResponseCompleteTaskInWorkflowEngineShouldThrowBadRequestServiceException() + throws InternalErrorServiceException { + String taskId = "taskId"; + + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); + var.setType("Boolean"); + var.setValue(true); + variables.put("var", var); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(400).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeTask(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaVariablesRequestBody.class))).thenReturn(response); + + try { + workflowService.completeTask(taskId, variables); + fail("Should have thrown an InternalErrorServiceException."); + } catch (BadRequestServiceException e) { + // pass + } + + } + + @Test + public void completeTaskWithValidTaskIdAndInternalServerErrorResponseCompleteTaskInWorkflowEngineShouldInternalServerErrorException() + throws BadRequestServiceException { + String taskId = "taskId"; + + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); + var.setType("Boolean"); + var.setValue(true); + variables.put("var", var); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(500).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeTask(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaVariablesRequestBody.class))).thenReturn(response); + + try { + workflowService.completeTask(taskId, variables); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void completeTaskWithValidTaskIdAndInvalidResponseCompleteTaskInWorkflowEngineShouldInternalServerErrorException() + throws BadRequestServiceException { + String taskId = "taskId"; + + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + WorkflowTaskVariableModel var = new WorkflowTaskVariableModel(); + var.setType("Boolean"); + var.setValue(true); + variables.put("var", var); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(404).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeTask(Mockito.anyString(), Mockito.eq(taskId), + Mockito.any(CamundaVariablesRequestBody.class))).thenReturn(response); + + try { + workflowService.completeTask(taskId, variables); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void fetchAndLockExternalTasksWithValidSetOfTopicsAndValidWorkerIdShouldRespondWithListOfExternalTasks() throws InternalErrorServiceException { + Set<String> topics = new HashSet<>(); + String topicName = "topic"; + topics.add(topicName); + String workerId = "workerId"; + + String activityId = "acrivityId"; + String activityInstanceId = "activityInstanceId"; + String errorDetails = "errorDetails"; + String errorMessage = "errorMessage"; + String executionId = "executionId"; + String id = "id"; + String lockExpirationTime = "lockExpirationTime"; + Long priority = 1L; + String processDefinitionId = "processDefinitionId"; + String processInstanceId = "processInstanceId"; + Long retries = 2L; + + Map<String, CamundaVariable> variables = new HashMap<>(); + CamundaVariable var = new CamundaVariable(); + var.setType("Boolean"); + var.setValue(true); + variables.put("var", var); + List<CamundaExternalTaskFetchAndLockRsp> extTasks = new ArrayList<>(); + CamundaExternalTaskFetchAndLockRsp extTask = new CamundaExternalTaskFetchAndLockRsp(); + extTask.setActivityId(activityId); + extTask.setActivityInstanceId(activityInstanceId); + extTask.setErrorDetails(errorDetails); + extTask.setErrorMessage(errorMessage); + extTask.setExecutionId(executionId); + extTask.setId(id); + extTask.setLockExpirationTime(lockExpirationTime); + extTask.setPriority(priority); + extTask.setProcessDefinitionId(processDefinitionId); + extTask.setProcessDefinitionKey(processDefinitionKey); + extTask.setProcessInstanceId(processInstanceId); + extTask.setRetries(retries); + extTask.setTenantId(tenantId); + extTask.setTopicName(topicName); + extTask.setWorkerId(workerId); + extTask.setVariables(variables); + + extTasks.add(extTask); + + Mockito.when(camundaApi.fetchAndLockExternalTaskInstances(Mockito.anyString(), + Mockito.any(CamundaFetchAndLockExtTaskRequestBody.class))).thenReturn(extTasks); + + Optional<List<ExternalTaskModel>> oTasks = workflowService.fetchAndLockExternalTasks(topics, workerId); + assertTrue(oTasks.isPresent()); + ExternalTaskModel task = oTasks.get().get(0); + assertEquals(activityId, task.getActivityId()); + assertEquals(activityInstanceId, task.getActivityInstanceId()); + assertEquals(errorDetails, task.getErrorDetails()); + assertEquals(errorMessage, task.getErrorMessage()); + assertEquals(executionId, task.getExecutionId()); + assertEquals(id, task.getId()); + assertEquals(lockExpirationTime, task.getLockExpirationTime()); + assertEquals(priority, task.getPriority()); + assertEquals(processDefinitionId, task.getProcessDefinitionId()); + assertEquals(processDefinitionKey, task.getProcessDefinitionKey()); + assertEquals(processInstanceId, task.getProcessInstanceId()); + assertEquals(retries, task.getRetries()); + assertEquals(tenantId, task.getTenantId()); + assertEquals(topicName, task.getTopicName()); + assertEquals(workerId, task.getWorkerId()); + WorkflowTaskVariableModel wvar = task.getVariables().get("var"); + assertEquals(var.getType(), wvar.getType()); + assertEquals(var.getValue(), wvar.getValue()); + + } + + @Test + public void fetchAndLockExternalTasksWithValidSetOfTopicsAndValidWorkerIdExceptionAccessingTheWorkflowEnfineShouldThrowInternalErrorServiceException() { + Set<String> topics = new HashSet<>(); + String topicName = "topic"; + topics.add(topicName); + String workerId = "workerId"; + + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .fetchAndLockExternalTaskInstances(Mockito.anyString(), + Mockito.any(CamundaFetchAndLockExtTaskRequestBody.class)); + + try { + workflowService.fetchAndLockExternalTasks(topics, workerId); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void completeExternalTaskWithValidTaskIdAndValidWorkerIdAndCompleteVariablesShouldRespondTrue() throws InternalErrorServiceException, BadRequestServiceException { + + String taskId = "taskId"; + String workerId = "workerId"; + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + + Response response = Response + .builder().headers(Collections.emptyMap()).status(204).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaCompleteExternalTaskRequestBody.class))).thenReturn(response); + + Optional<Boolean> oResponse = workflowService.completeExternalTask(taskId, workerId, variables); + assertTrue(oResponse.isPresent()); + assertTrue(oResponse.get()); + + } + + @Test + public void completeExternalTasksWithValidTaskIdAndValidWorkerIdExceptionAccessingTheWorkflowEngineShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + String taskId = "taskId"; + String workerId = "workerId"; + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .completeExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaCompleteExternalTaskRequestBody.class)); + + try { + workflowService.completeExternalTask(taskId, workerId, variables); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void completeExternalTaskWithInValidTaskIdOfShouldThrowBadRequestServiceException() throws InternalErrorServiceException { + + String taskId = "taskId"; + String workerId = "workerId"; + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + CamundaCompleteExternalTaskRequestBody reqBody = new CamundaCompleteExternalTaskRequestBody(); + reqBody.setWorkerId(workerId); + Map<String, CamundaVariable> camundaVariables = new HashMap<>(); + for (Entry<String, WorkflowTaskVariableModel> entry : variables.entrySet()) { + WorkflowTaskVariableModel var = entry.getValue(); + CamundaVariable cv = new CamundaVariable(); + cv.setLocal(true); + cv.setType(var.getType()); + cv.setValue(var.getValue()); + } + reqBody.setVariables(camundaVariables); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(404).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaCompleteExternalTaskRequestBody.class))).thenReturn(response); + + try { + workflowService.completeExternalTask(taskId, workerId, variables); + fail("Should have thrown an BadRequestServiceException."); + } catch (BadRequestServiceException e) { + // pass + } + } + + @Test + public void completeExternalTaskWithValidTaskIdAndInvalidWorkerIdShouldThrowBadRequestServiceException() throws InternalErrorServiceException { + + String taskId = "taskId"; + String workerId = "workerId"; + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + CamundaCompleteExternalTaskRequestBody reqBody = new CamundaCompleteExternalTaskRequestBody(); + reqBody.setWorkerId(workerId); + Map<String, CamundaVariable> camundaVariables = new HashMap<>(); + for (Entry<String, WorkflowTaskVariableModel> entry : variables.entrySet()) { + WorkflowTaskVariableModel var = entry.getValue(); + CamundaVariable cv = new CamundaVariable(); + cv.setLocal(true); + cv.setType(var.getType()); + cv.setValue(var.getValue()); + } + reqBody.setVariables(camundaVariables); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(400).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaCompleteExternalTaskRequestBody.class))).thenReturn(response); + + try { + workflowService.completeExternalTask(taskId, workerId, variables); + fail("Should have thrown an BadRequestServiceException."); + } catch (BadRequestServiceException e) { + // pass + } + + } + + @Test + public void completeExternalTaskWithValidTaskIdAndValidWorkerIdInternalServerErrorResponseFromWorkflowEngineShouldRespondWithFalse() throws InternalErrorServiceException, BadRequestServiceException { + String taskId = "taskId"; + String workerId = "workerId"; + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + CamundaCompleteExternalTaskRequestBody reqBody = new CamundaCompleteExternalTaskRequestBody(); + reqBody.setWorkerId(workerId); + Map<String, CamundaVariable> camundaVariables = new HashMap<>(); + for (Entry<String, WorkflowTaskVariableModel> entry : variables.entrySet()) { + WorkflowTaskVariableModel var = entry.getValue(); + CamundaVariable cv = new CamundaVariable(); + cv.setLocal(true); + cv.setType(var.getType()); + cv.setValue(var.getValue()); + } + reqBody.setVariables(camundaVariables); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(500).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaCompleteExternalTaskRequestBody.class))).thenReturn(response); + + Optional<Boolean> oResponse = workflowService.completeExternalTask(taskId, workerId, variables); + assertTrue(oResponse.isPresent()); + assertFalse(oResponse.get()); + + } + + @Test + public void completeExternalTaskWithValidTaskIdAndValidWorkerIdInvalidResponseFromWorkflowEngineShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + + + String taskId = "taskId"; + String workerId = "workerId"; + Map<String, WorkflowTaskVariableModel> variables = new HashMap<>(); + + CamundaCompleteExternalTaskRequestBody reqBody = new CamundaCompleteExternalTaskRequestBody(); + reqBody.setWorkerId(workerId); + Map<String, CamundaVariable> camundaVariables = new HashMap<>(); + for (Entry<String, WorkflowTaskVariableModel> entry : variables.entrySet()) { + WorkflowTaskVariableModel var = entry.getValue(); + CamundaVariable cv = new CamundaVariable(); + cv.setLocal(true); + cv.setType(var.getType()); + cv.setValue(var.getValue()); + } + reqBody.setVariables(camundaVariables); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(406).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.completeExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaCompleteExternalTaskRequestBody.class))).thenReturn(response); + + try { + workflowService.completeExternalTask(taskId, workerId, variables); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void failureExternalTaskWithValidTaskIdAndValidWorkerIdShouldRespondWithTrue() throws InternalErrorServiceException, BadRequestServiceException { + + String taskId = "taskId"; + String workerId = "workerId"; + String errorMessage = "errorMessage"; + + Response response = Response + .builder().headers(Collections.emptyMap()).status(204).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + + Mockito.when(camundaApi.failureExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaFailureExternalTaskRequestBody.class))).thenReturn(response); + Optional<Boolean> oResponse = workflowService.failureExternalTask(taskId, workerId, errorMessage); + assertTrue(oResponse.isPresent()); + assertTrue(oResponse.get()); + + } + + @Test + public void failureExternalTaskWithInvalidTaskIdShouldThrowBadRequestServiceException() throws InternalErrorServiceException { + String taskId = "taskId"; + String workerId = "workerId"; + String errorMessage = "errorMessage"; + + Response response = Response + .builder().headers(Collections.emptyMap()).status(404).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + + Mockito.when(camundaApi.failureExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaFailureExternalTaskRequestBody.class))).thenReturn(response); + + try { + workflowService.failureExternalTask(taskId, workerId, errorMessage); + fail("Should have thrown an BadRequestServiceException."); + } catch (BadRequestServiceException e) { + // pass + } + + } + + @Test + public void failureExternalTaskWithValidTaskIdAndInvalidWorkerIdShouldThrowBadRequestServiceException() throws InternalErrorServiceException { + + String taskId = "taskId"; + String workerId = "workerId"; + String errorMessage = "errorMessage"; + + Response response = Response + .builder().headers(Collections.emptyMap()).status(400).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + + Mockito.when(camundaApi.failureExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaFailureExternalTaskRequestBody.class))).thenReturn(response); + + try { + workflowService.failureExternalTask(taskId, workerId, errorMessage); + fail("Should have thrown an BadRequestServiceException."); + } catch (BadRequestServiceException e) { + // pass + } + + } + + @Test + public void failureExternalTaskWithValidTaskIdAndValidWorkerIdExceptionAccessingWorkflowengineShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + + String taskId = "taskId"; + String workerId = "workerId"; + String errorMessage = "errorMessage"; + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .failureExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaFailureExternalTaskRequestBody.class)); + + try { + workflowService.failureExternalTask(taskId, workerId, errorMessage); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void failureExternalTaskWithValidTaskIdAndValidWorkerIdInternalServerErrorResponseFromWorkflowShouldRespondWithFalse() throws InternalErrorServiceException, BadRequestServiceException { + String taskId = "taskId"; + String workerId = "workerId"; + String errorMessage = "errorMessage"; + + Response response = Response + .builder().headers(Collections.emptyMap()).status(500).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + + Mockito.when(camundaApi.failureExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaFailureExternalTaskRequestBody.class))).thenReturn(response); + Optional<Boolean> oResponse = workflowService.failureExternalTask(taskId, workerId, errorMessage); + assertTrue(oResponse.isPresent()); + assertFalse(oResponse.get()); + + } + + @Test + public void failureExternalTaskWithValidTaskIdAndValidWorkerIdInvalidResponseFromWorkflowShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + + String taskId = "taskId"; + String workerId = "workerId"; + String errorMessage = "errorMessage"; + + Response response = Response + .builder().headers(Collections.emptyMap()).status(406).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + + Mockito.when(camundaApi.failureExternalTaskInstance(Mockito.anyString(), Mockito.eq(taskId), Mockito.any(CamundaFailureExternalTaskRequestBody.class))).thenReturn(response); + + try { + workflowService.failureExternalTask(taskId, workerId, errorMessage); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void deleteProcessInstanceWithValidBusinessKeyShouldRespondTrue() throws InternalErrorServiceException, BadRequestServiceException { + String businessKey = "businessKey"; + + String definitionId = "definitionId"; + String processId = "processId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processId); + processInstances.add(pi); + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(204).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.deleteProcessInstanceWithProcessId(Mockito.anyString(), Mockito.eq(processId))).thenReturn(response); + + Optional<Boolean> oResp = workflowService.deleteProcessInstance(businessKey); + assertTrue(oResp.isPresent()); + assertTrue(oResp.get()); + + } + + @Test + public void deleteProcessInstanceWithInvalidBusinessKeyShouldThrowBadRequestServiceException() throws InternalErrorServiceException { + String businessKey = "businessKey"; + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(new ArrayList<CamundaProcessInstance>()); + + try { + workflowService.deleteProcessInstance(businessKey); + fail("Should have thrown an BadRequestServiceException."); + } catch (BadRequestServiceException e) { + // pass + } + + } + + @Test + public void deleteProcessInstanceWithValidBusinessKeyExceptionGettingProceessInstanceShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + String businessKey = "businessKey"; + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), Mockito.eq(businessKey)); + + try { + workflowService.deleteProcessInstance(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + } + + @Test + public void deleteProcessInstanceWithValidBusinessKeyMoreThanOneProcessInstanceWithSameBusinessKeyShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + String businessKey = "businessKey"; + + String definitionId = "definitionId"; + String processId = "processId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processId); + processInstances.add(pi); + processInstances.add(pi); + + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + try { + workflowService.deleteProcessInstance(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + } + + @Test + public void deleteProcessInstanceWithValidBusinessKeyExceptionDeleteProcessInstanceInWorkflowEngineShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + + String businessKey = "businessKey"; + + String definitionId = "definitionId"; + String processId = "processId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processId); + processInstances.add(pi); + + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + Mockito.doThrow(FeignException.errorStatus("", + Response.builder().headers(Collections.emptyMap()).status(400) + .request(Request.create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), + Body.empty())) + .build())) + .when(camundaApi) + .deleteProcessInstanceWithProcessId(Mockito.anyString(), Mockito.eq(processId)); + + try { + workflowService.deleteProcessInstance(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } + + @Test + public void deleteProcessInstanceWithValidBusinessKeyNotFoundResponseDeleteProcessInstanceInWorkflowEngineShouldThrowBadRequestServiceException() throws InternalErrorServiceException { + + String businessKey = "businessKey"; + + String definitionId = "definitionId"; + String processId = "processId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processId); + processInstances.add(pi); + + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(404).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.deleteProcessInstanceWithProcessId(Mockito.anyString(), Mockito.eq(processId))).thenReturn(response); + + try { + workflowService.deleteProcessInstance(businessKey); + fail("Should have thrown an BadRequestServiceException."); + } catch (BadRequestServiceException e) { + // pass + } + } + + @Test + public void deleteProcessInstanceWithValidBusinessKeyInvalidResponseDeleteProcessInstanceInWorkflowEngineShouldThrowInternalErrorServiceException() throws BadRequestServiceException { + + String businessKey = "businessKey"; + + String definitionId = "definitionId"; + String processId = "processId"; + List<CamundaProcessInstance> processInstances = new ArrayList<>(); + CamundaProcessInstance pi = new CamundaProcessInstance(); + pi.setBusinessKey(businessKey); + pi.setDefinitionId(definitionId); + pi.setId(processId); + processInstances.add(pi); + + + Mockito.when(camundaApi.getProcessInstancesWithBusinessKey(Mockito.anyString(), Mockito.anyString(), + Mockito.eq(businessKey))).thenReturn(processInstances); + + Response response = Response + .builder().headers(Collections.emptyMap()).status(406).body("Body".getBytes()).request(Request + .create(Request.HttpMethod.GET, "", new HashMap<String, Collection<String>>(), Body.empty())) + .build(); + + Mockito.when(camundaApi.deleteProcessInstanceWithProcessId(Mockito.anyString(), Mockito.eq(processId))).thenReturn(response); + + try { + workflowService.deleteProcessInstance(businessKey); + fail("Should have thrown an InternalErrorServiceException."); + } catch (InternalErrorServiceException e) { + // pass + } + + } }
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/worker/TestWorkerFalse.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/worker/TestWorkerFalse.java new file mode 100644 index 0000000..376cf5f --- /dev/null +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/worker/TestWorkerFalse.java
@@ -0,0 +1,47 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.service.worker; + +import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskModel; +import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskResultModel; +import org.springframework.stereotype.Component; + +import lombok.extern.java.Log; + +/** + * @author Tobias Stummer + * + */ +@Component +@Log +public class TestWorkerFalse implements IExternalTaskWorker{ + + public static final String ERROR_MESSAGE = "Test Error Message"; + + @Override + public String getTopic() { + return "testTopicFalse"; + } + + @Override + public ExternalTaskResultModel work(ExternalTaskModel task) { + log.warning("Work on TopicBA"); + ExternalTaskResultModel result = new ExternalTaskResultModel(); + result.setSuccessful(false); + result.setErrorMessage(ERROR_MESSAGE); + return result; + } + +}
diff --git a/src/test/java/org/eclipse/openk/statementpublicaffairs/service/worker/TestWorkerTrue.java b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/worker/TestWorkerTrue.java new file mode 100644 index 0000000..4f158d6 --- /dev/null +++ b/src/test/java/org/eclipse/openk/statementpublicaffairs/service/worker/TestWorkerTrue.java
@@ -0,0 +1,44 @@ +/* + ******************************************************************************* + * Copyright (c) 2020 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************* +*/ +package org.eclipse.openk.statementpublicaffairs.service.worker; + +import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskModel; +import org.eclipse.openk.statementpublicaffairs.model.ExternalTaskResultModel; +import org.springframework.stereotype.Component; + +import lombok.extern.java.Log; + +/** + * @author Tobias Stummer + * + */ +@Component +@Log +public class TestWorkerTrue implements IExternalTaskWorker{ + + @Override + public String getTopic() { + return "testTopicTrue"; + } + + @Override + public ExternalTaskResultModel work(ExternalTaskModel task) { + log.warning("Work on TopicBA"); + ExternalTaskResultModel result = new ExternalTaskResultModel(); + result.setSuccessful(true); + return result; + } + +}