From 8e110aa86f4584f6d6f262b93d8377eb536a5826 Mon Sep 17 00:00:00 2001 From: DyferHerioss Date: Tue, 11 Aug 2026 21:55:37 +0300 Subject: [PATCH] feat: reject credit payment --- doc/api.yml | 2 ++ doc/operations/paying-api.yml | 34 +++++++++++++++++++ .../rest/controller/PaymentController.java | 8 +++++ .../endpoint/rest/security/SecurityConf.java | 33 ++++++++++-------- .../haapi/integration/CreditControllerIT.java | 24 +++++++++++++ 5 files changed, 86 insertions(+), 15 deletions(-) diff --git a/doc/api.yml b/doc/api.yml index 3c220e7db..b25a45858 100644 --- a/doc/api.yml +++ b/doc/api.yml @@ -290,6 +290,8 @@ paths: $ref: './operations/paying-api.yml#/operations/getCreditPaymentsByStatus' '/students/payments/validate': $ref: './operations/paying-api.yml#/operations/validateCreditPayments' + '/students/payments/reject': + $ref: './operations/paying-api.yml#/operations/rejectCreditPayments' '/students/{student_id}/credit': $ref: './operations/paying-api.yml#/operations/getCreditByStudentId' '/students/{student_id}/credit-transactions': diff --git a/doc/operations/paying-api.yml b/doc/operations/paying-api.yml index b87fa4c03..b2a628a4c 100644 --- a/doc/operations/paying-api.yml +++ b/doc/operations/paying-api.yml @@ -1586,3 +1586,37 @@ operations: $ref: '../components.yml#/components/responses/429' '500': $ref: '../components.yml#/components/responses/500' + rejectCreditPayments: + patch: + tags: + - Paying + summary: Reject fee payments made using credit. + operationId: rejectCreditPayments + requestBody: + description: Students credit payments to reject + required: true + content: + application/json: + schema: + type: array + items: + type: string + responses: + '200': + description: List of fee credit payments rejected. + content: + application/json: + schema: + type: array + items: + $ref: '../components.yml#/components/schemas/Payment' + '400': + $ref: '../components.yml#/components/responses/400' + '403': + $ref: '../components.yml#/components/responses/403' + '404': + $ref: '../components.yml#/components/responses/404' + '429': + $ref: '../components.yml#/components/responses/429' + '500': + $ref: '../components.yml#/components/responses/500' diff --git a/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java b/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java index c907b7376..5faaadf90 100644 --- a/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java +++ b/src/main/java/school/hei/haapi/endpoint/rest/controller/PaymentController.java @@ -1,6 +1,7 @@ package school.hei.haapi.endpoint.rest.controller; import static java.util.stream.Collectors.toUnmodifiableList; +import static school.hei.haapi.model.PaymentStatus.INVALIDATE; import static school.hei.haapi.model.PaymentStatus.VALIDATE; import java.util.List; @@ -44,6 +45,13 @@ public List validatePayments(@RequestBody List paymentIds) { return paymentMapper.toRestPayment(paymentService.saveAll(payments)); } + @PatchMapping("/students/payments/reject") + public List rejectPayments(@RequestBody List paymentIds) { + var payments = paymentService.getByIds(paymentIds); + payments.forEach(payment -> payment.setStatus(INVALIDATE)); + return paymentMapper.toRestPayment(paymentService.saveAll(payments)); + } + @DeleteMapping("/students/{studentId}/fees/{feeId}/payments/{paymentId}") public Payment deleteStudentFeePaymentById( @PathVariable(name = "studentId") String studentId, diff --git a/src/main/java/school/hei/haapi/endpoint/rest/security/SecurityConf.java b/src/main/java/school/hei/haapi/endpoint/rest/security/SecurityConf.java index 93b5e40f5..0532e2877 100644 --- a/src/main/java/school/hei/haapi/endpoint/rest/security/SecurityConf.java +++ b/src/main/java/school/hei/haapi/endpoint/rest/security/SecurityConf.java @@ -1,5 +1,20 @@ package school.hei.haapi.endpoint.rest.security; +import static org.springframework.http.HttpMethod.DELETE; +import static org.springframework.http.HttpMethod.GET; +import static org.springframework.http.HttpMethod.OPTIONS; +import static org.springframework.http.HttpMethod.PATCH; +import static org.springframework.http.HttpMethod.POST; +import static org.springframework.http.HttpMethod.PUT; +import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; +import static school.hei.haapi.endpoint.rest.security.model.Role.ADMIN; +import static school.hei.haapi.endpoint.rest.security.model.Role.MANAGER; +import static school.hei.haapi.endpoint.rest.security.model.Role.MONITOR; +import static school.hei.haapi.endpoint.rest.security.model.Role.ORGANIZER; +import static school.hei.haapi.endpoint.rest.security.model.Role.STAFF_MEMBER; +import static school.hei.haapi.endpoint.rest.security.model.Role.STUDENT; +import static school.hei.haapi.endpoint.rest.security.model.Role.TEACHER; + import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Qualifier; @@ -22,21 +37,6 @@ import school.hei.haapi.service.CourseAssignmentService; import school.hei.haapi.service.MonitoringStudentService; -import static org.springframework.http.HttpMethod.DELETE; -import static org.springframework.http.HttpMethod.GET; -import static org.springframework.http.HttpMethod.OPTIONS; -import static org.springframework.http.HttpMethod.PATCH; -import static org.springframework.http.HttpMethod.POST; -import static org.springframework.http.HttpMethod.PUT; -import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; -import static school.hei.haapi.endpoint.rest.security.model.Role.ADMIN; -import static school.hei.haapi.endpoint.rest.security.model.Role.MANAGER; -import static school.hei.haapi.endpoint.rest.security.model.Role.MONITOR; -import static school.hei.haapi.endpoint.rest.security.model.Role.ORGANIZER; -import static school.hei.haapi.endpoint.rest.security.model.Role.STAFF_MEMBER; -import static school.hei.haapi.endpoint.rest.security.model.Role.STUDENT; -import static school.hei.haapi.endpoint.rest.security.model.Role.TEACHER; - @Configuration @Slf4j @EnableWebSecurity @@ -163,6 +163,7 @@ req, res, null, forbiddenWithRemoteInfo(req)))) antMatcher(POST, "/students/*/fees/*/payments"), antMatcher(DELETE, "/students/*/fees/*/payments/*"), antMatcher(PATCH, "/students/payments/validate"), + antMatcher(PATCH, "/students/payments/reject"), antMatcher(GET, "/students/credit-payments"), antMatcher(GET, "/students/{student_id}/credit"), antMatcher(GET, "/students/{student_id}/credit-transactions"), @@ -656,6 +657,8 @@ req, res, null, forbiddenWithRemoteInfo(req)))) .hasAnyRole(MANAGER.getRole(), ADMIN.getRole()) .requestMatchers(PATCH, "/students/payments/validate") .hasAnyRole(MANAGER.getRole(), ADMIN.getRole()) + .requestMatchers(PATCH, "/students/payments/reject") + .hasAnyRole(MANAGER.getRole(), ADMIN.getRole()) .requestMatchers(GET, "/students/credit-payments") .hasAnyRole(MANAGER.getRole(), ADMIN.getRole()) .requestMatchers(GET, "/students/{student_id}/credit") diff --git a/src/test/java/school/hei/haapi/integration/CreditControllerIT.java b/src/test/java/school/hei/haapi/integration/CreditControllerIT.java index f1086a9c7..fb10f5287 100644 --- a/src/test/java/school/hei/haapi/integration/CreditControllerIT.java +++ b/src/test/java/school/hei/haapi/integration/CreditControllerIT.java @@ -142,6 +142,30 @@ void manager_validate_credit_payments_OK() throws ApiException { assertEquals(150000, actualCredit.getAmount()); } + @Test + void manager_reject_credit_payments_OK() throws ApiException { + var studentApiClient = anApiClient(STUDENT1_TOKEN); + var managerApiClient = anApiClient(MANAGER1_TOKEN); + var studentPayingApi = new PayingApi(studentApiClient); + var managerPayingApi = new PayingApi(managerApiClient); + managerPayingApi.archiveStudentFee(student.getId(), feeToArchive.getId()); + var payments = + studentPayingApi.createStudentPayments( + student.getId(), currentFee.getId(), List.of(bankPayment(), creditPaymentCreated())); + var paymentsToReject = managerPayingApi.getCreditPaymentsByStatus(PaymentStatus.CREATED, 1, 10); + assertEquals(payments.getLast(), paymentsToReject.getFirst()); + var creditPaymentsRejected = + managerPayingApi.rejectCreditPayments(List.of(paymentsToReject.getFirst().getId())); + assertNotNull(creditPaymentsRejected); + assertEquals(PaymentStatus.INVALIDATE, creditPaymentsRejected.getFirst().getStatus()); + var feeNotPaid = managerPayingApi.getStudentFeeById(student.getId(), currentFee.getId()); + assertNotNull(feeNotPaid); + assertEquals(50000, feeNotPaid.getRemainingAmount()); + var actualCredit = managerPayingApi.getCreditByStudentId(student.getId()); + assertNotNull(actualCredit); + assertEquals(200000, actualCredit.getAmount()); + } + private static User student() { return User.builder() .ref("STD" + UUID.randomUUID())