diff --git a/api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/v2/BillController.java b/api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/v2/BillController.java new file mode 100644 index 0000000000..df6e5e2b46 --- /dev/null +++ b/api-gateway/src/main/java/com/petclinic/bffapigateway/presentationlayer/v2/BillController.java @@ -0,0 +1,29 @@ +package com.petclinic.bffapigateway.presentationlayer.v2; + +import com.petclinic.bffapigateway.domainclientlayer.BillServiceClient; +import com.petclinic.bffapigateway.dtos.Bills.BillResponseDTO; +import com.petclinic.bffapigateway.utils.Security.Annotations.IsUserSpecific; +import com.petclinic.bffapigateway.utils.Security.Variables.Roles; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import reactor.core.publisher.Flux; + +@RestController +@RequiredArgsConstructor +@Slf4j +@RequestMapping("/api/v2/gateway/bills") +@Validated +@CrossOrigin(origins = "http://localhost:3000, http://localhost:80") +public class BillController { + private final BillServiceClient billService; + + @IsUserSpecific(idToMatch = {"customerId"}, bypassRoles = {Roles.ADMIN}) + @GetMapping(value = "/customer/{customerId}", produces= MediaType.TEXT_EVENT_STREAM_VALUE) + public Flux getBillsByOwnerId(final @PathVariable String customerId) + { + return billService.getBillsByOwnerId(customerId); + } +} diff --git a/api-gateway/src/test/java/com/petclinic/bffapigateway/presentationlayer/v2/BillControllerUnitTest.java b/api-gateway/src/test/java/com/petclinic/bffapigateway/presentationlayer/v2/BillControllerUnitTest.java new file mode 100644 index 0000000000..17770b9ca4 --- /dev/null +++ b/api-gateway/src/test/java/com/petclinic/bffapigateway/presentationlayer/v2/BillControllerUnitTest.java @@ -0,0 +1,76 @@ +package com.petclinic.bffapigateway.presentationlayer.v2; + +import com.petclinic.bffapigateway.domainclientlayer.BillServiceClient; +import com.petclinic.bffapigateway.dtos.Bills.BillResponseDTO; +import com.petclinic.bffapigateway.dtos.Bills.BillStatus; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; +import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; + +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.reactive.server.WebTestClient; +import reactor.core.publisher.Flux; + +import java.time.LocalDate; + +import static org.mockito.Mockito.when; + +@RunWith(SpringRunner.class) +@ContextConfiguration(classes = { + BillController.class, + BillServiceClient.class +}) +@WebFluxTest(controllers = BillController.class) +@AutoConfigureWebTestClient +public class BillControllerUnitTest { + + @Autowired + private WebTestClient webTestClient; + @MockBean + private BillServiceClient billServiceClient; + +private final String baseBillURL = "/api/v2/gateway/bills"; + + private BillResponseDTO billresponse = BillResponseDTO.builder() + .billId("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a") + .customerId("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a") + .visitType("general") + .vetId("3") + .date(LocalDate.parse("2024-10-11")) + .amount(100.0) + .taxedAmount(0.0) + .billStatus(BillStatus.UNPAID) + .dueDate(LocalDate.parse("2024-10-13")) + .build(); + + private BillResponseDTO billresponse2 = BillResponseDTO.builder() + .billId("e6c7398e-8ac4-4e10-9ee0-03ef33f0361b") + .customerId("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a") + .visitType("general") + .vetId("2") + .date(LocalDate.parse("2024-10-11")) + .amount(120.0) + .taxedAmount(10.0) + .billStatus(BillStatus.UNPAID) + .dueDate(LocalDate.parse("2024-10-13")) + .build(); + + + @Test + public void whenGetAllBillsByCustomerId_ThenReturnCustomerBills() { + when(billServiceClient.getBillsByOwnerId("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a")).thenReturn(Flux.just(billresponse, billresponse2)); + webTestClient.get() + .uri(baseBillURL + "/customer/{customerId}", "e6c7398e-8ac4-4e10-9ee0-03ef33f0361a") + .exchange() + .expectStatus().isOk() + .expectBodyList(BillResponseDTO.class) + .hasSize(2) + .contains(billresponse, billresponse2); + } + + +} \ No newline at end of file diff --git a/billing-service/src/main/java/com/petclinic/billing/datalayer/DataSetupService.java b/billing-service/src/main/java/com/petclinic/billing/datalayer/DataSetupService.java deleted file mode 100644 index 128b325a59..0000000000 --- a/billing-service/src/main/java/com/petclinic/billing/datalayer/DataSetupService.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.petclinic.billing.datalayer; - - -import com.petclinic.billing.businesslayer.BillService; -import org.springframework.boot.CommandLineRunner; -import org.springframework.stereotype.Service; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.time.LocalDate; - - -@Service -public class DataSetupService implements CommandLineRunner { - private final BillService billService; - public DataSetupService(BillService billService) { - this.billService = billService; - } - - - @Override - public void run(String... args) throws Exception { - - - BillRequestDTO b1 = new BillRequestDTO( "1", "general", "1", LocalDate.of(2023,9,19),59.99,BillStatus.PAID, LocalDate.of(2023, 10,3)); - BillRequestDTO b3 = new BillRequestDTO( "3", "operation", "1", LocalDate.of(2023,9,27), 199.99,BillStatus.PAID,LocalDate.of(2023, 10,11)); - BillRequestDTO b4 = new BillRequestDTO( "4", "injury", "1", LocalDate.of(2023,10,11), 199.99,BillStatus.UNPAID,LocalDate.of(2023, 10,25)); - BillRequestDTO b2 = new BillRequestDTO( "2", "operation", "2", LocalDate.of(2023,10,6), 199.99,BillStatus.OVERDUE,LocalDate.of(2023, 10,20)); - BillRequestDTO b5 = new BillRequestDTO( "5", "chronic", "3", LocalDate.of(2023,10,13), 199.99,BillStatus.UNPAID,LocalDate.of(2023, 10,27)); - BillRequestDTO b6 = new BillRequestDTO("6", "general", "2", LocalDate.of(2023, 10, 5), 59.99, BillStatus.PAID, LocalDate.of(2023, 10, 10)); - BillRequestDTO b7 = new BillRequestDTO("7", "operation", "3", LocalDate.of(2023, 10, 8), 199.99, BillStatus.PAID, LocalDate.of(2023, 10, 14)); - BillRequestDTO b8 = new BillRequestDTO("8", "injury", "2", LocalDate.of(2023, 10, 15), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 10, 30)); - BillRequestDTO b9 = new BillRequestDTO("9", "chronic", "1", LocalDate.of(2023, 10, 18), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 2)); - BillRequestDTO b10 = new BillRequestDTO("10", "general", "3", LocalDate.of(2023, 10, 21), 59.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 6)); - BillRequestDTO b11 = new BillRequestDTO("11", "operation", "1", LocalDate.of(2023, 10, 24), 199.99, BillStatus.PAID, LocalDate.of(2023, 11, 10)); - BillRequestDTO b12 = new BillRequestDTO("12", "injury", "3", LocalDate.of(2023, 10, 27), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 11, 14)); - BillRequestDTO b13 = new BillRequestDTO("13", "chronic", "2", LocalDate.of(2023, 10, 30), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 18)); - BillRequestDTO b14 = new BillRequestDTO("14", "general", "1", LocalDate.of(2023, 11, 2), 59.99, BillStatus.PAID, LocalDate.of(2023, 11, 22)); - BillRequestDTO b15 = new BillRequestDTO("15", "operation", "2", LocalDate.of(2023, 11, 5), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 26)); - BillRequestDTO b16 = new BillRequestDTO("16", "injury", "1", LocalDate.of(2023, 11, 8), 199.99, BillStatus.PAID, LocalDate.of(2023, 12, 2)); - BillRequestDTO b17 = new BillRequestDTO("17", "chronic", "3", LocalDate.of(2023, 11, 11), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 12, 6)); - BillRequestDTO b18 = new BillRequestDTO("18", "general", "2", LocalDate.of(2023, 11, 14), 59.99, BillStatus.PAID, LocalDate.of(2023, 12, 10)); - BillRequestDTO b19 = new BillRequestDTO("19", "operation", "3", LocalDate.of(2023, 11, 17), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 12, 14)); - BillRequestDTO b20 = new BillRequestDTO("20", "injury", "1", LocalDate.of(2023, 11, 20), 199.99, BillStatus.PAID, LocalDate.of(2023, 12, 18)); - BillRequestDTO b21 = new BillRequestDTO("21", "chronic", "2", LocalDate.of(2023, 11, 23), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 12, 22)); - BillRequestDTO b22 = new BillRequestDTO("22", "general", "3", LocalDate.of(2023, 11, 26), 59.99, BillStatus.PAID, LocalDate.of(2023, 12, 26)); - BillRequestDTO b23 = new BillRequestDTO("23", "operation", "2", LocalDate.of(2023, 11, 29), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 12, 30)); - BillRequestDTO b24 = new BillRequestDTO("24", "injury", "1", LocalDate.of(2023, 12, 2), 199.99, BillStatus.PAID, LocalDate.of(2024, 1, 2)); - BillRequestDTO b25 = new BillRequestDTO("25", "chronic", "3", LocalDate.of(2023, 12, 5), 199.99, BillStatus.OVERDUE, LocalDate.of(2024, 1, 6)); - BillRequestDTO b26 = new BillRequestDTO("26", "general", "2", LocalDate.of(2023, 12, 8), 59.99, BillStatus.UNPAID, LocalDate.of(2024, 1, 10)); - BillRequestDTO b27 = new BillRequestDTO("27", "operation", "3", LocalDate.of(2023, 12, 11), 199.99, BillStatus.PAID, LocalDate.of(2024, 1, 14)); - BillRequestDTO b28 = new BillRequestDTO("28", "injury", "1", LocalDate.of(2023, 12, 14), 199.99, BillStatus.PAID, LocalDate.of(2024, 1, 18)); - BillRequestDTO b29 = new BillRequestDTO("29", "chronic", "2", LocalDate.of(2023, 12, 17), 199.99, BillStatus.OVERDUE, LocalDate.of(2024, 1, 22)); - BillRequestDTO b30 = new BillRequestDTO("30", "general", "3", LocalDate.of(2023, 12, 20), 59.99, BillStatus.UNPAID, LocalDate.of(2024, 1, 26)); - - Flux.just(b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30) - .flatMap(b -> billService.CreateBill(Mono.just(b)) - .log(b.toString())) - .subscribe(); - - Flux.just(b1,b2,b3,b4,b5) - .flatMap(b -> billService.CreateBill(Mono.just(b)) - .log(b.toString())) - .subscribe(); - } -} diff --git a/billing-service/src/main/java/com/petclinic/billing/util/DataSetupService.java b/billing-service/src/main/java/com/petclinic/billing/util/DataSetupService.java new file mode 100644 index 0000000000..b8e093a605 --- /dev/null +++ b/billing-service/src/main/java/com/petclinic/billing/util/DataSetupService.java @@ -0,0 +1,68 @@ +package com.petclinic.billing.util; + + +import com.petclinic.billing.businesslayer.BillService; +import com.petclinic.billing.datalayer.BillRequestDTO; +import com.petclinic.billing.datalayer.BillStatus; +import org.springframework.boot.CommandLineRunner; +import org.springframework.stereotype.Service; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.time.LocalDate; + + +@Service +public class DataSetupService implements CommandLineRunner { + private final BillService billService; + public DataSetupService(BillService billService) { + this.billService = billService; + } + + + @Override + public void run(String... args) throws Exception { + + + BillRequestDTO b1 = new BillRequestDTO( "f470653d-05c5-4c45-b7a0-7d70f003d2ac", "general", "1", LocalDate.of(2023,9,19),59.99, BillStatus.PAID, LocalDate.of(2023, 10,3)); + BillRequestDTO b3 = new BillRequestDTO( "f470653d-05c5-4c45-b7a0-7d70f003d2ac", "operation", "1", LocalDate.of(2023,9,27), 199.99,BillStatus.PAID,LocalDate.of(2023, 10,11)); + BillRequestDTO b4 = new BillRequestDTO( "f470653d-05c5-4c45-b7a0-7d70f003d2ac", "injury", "1", LocalDate.of(2023,10,11), 199.99,BillStatus.UNPAID,LocalDate.of(2023, 10,25)); + BillRequestDTO b2 = new BillRequestDTO( "f470653d-05c5-4c45-b7a0-7d70f003d2ac", "operation", "2", LocalDate.of(2023,10,6), 199.99,BillStatus.OVERDUE,LocalDate.of(2023, 10,20)); + BillRequestDTO b5 = new BillRequestDTO( "e6c7398e-8ac4-4e10-9ee0-03ef33f0361a", "chronic", "3", LocalDate.of(2023,10,13), 199.99,BillStatus.UNPAID,LocalDate.of(2023, 10,27)); + BillRequestDTO b6 = new BillRequestDTO("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a", "general", "2", LocalDate.of(2023, 10, 5), 59.99, BillStatus.PAID, LocalDate.of(2023, 10, 10)); + BillRequestDTO b7 = new BillRequestDTO("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a", "operation", "3", LocalDate.of(2023, 10, 8), 199.99, BillStatus.PAID, LocalDate.of(2023, 10, 14)); + BillRequestDTO b8 = new BillRequestDTO("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a", "injury", "2", LocalDate.of(2023, 10, 15), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 10, 30)); + BillRequestDTO b9 = new BillRequestDTO("e6c7398e-8ac4-4e10-9ee0-03ef33f0361a", "chronic", "1", LocalDate.of(2023, 10, 18), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 2)); + BillRequestDTO b10 = new BillRequestDTO("3f59dca2-903e-495c-90c3-7f4d01f3a2aa", "general", "3", LocalDate.of(2023, 10, 21), 59.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 6)); + BillRequestDTO b11 = new BillRequestDTO("3f59dca2-903e-495c-90c3-7f4d01f3a2aa", "operation", "1", LocalDate.of(2023, 10, 24), 199.99, BillStatus.PAID, LocalDate.of(2023, 11, 10)); + BillRequestDTO b12 = new BillRequestDTO("a6e0e5b0-5f60-45f0-8ac7-becd8b330486", "injury", "3", LocalDate.of(2023, 10, 27), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 11, 14)); + BillRequestDTO b13 = new BillRequestDTO("a6e0e5b0-5f60-45f0-8ac7-becd8b330486", "chronic", "2", LocalDate.of(2023, 10, 30), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 18)); + BillRequestDTO b14 = new BillRequestDTO("a6e0e5b0-5f60-45f0-8ac7-becd8b330486", "general", "1", LocalDate.of(2023, 11, 2), 59.99, BillStatus.PAID, LocalDate.of(2023, 11, 22)); + BillRequestDTO b15 = new BillRequestDTO("c6a0fb9d-fc6f-4c21-95fc-4f5e7311d0e2", "operation", "2", LocalDate.of(2023, 11, 5), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 11, 26)); + BillRequestDTO b16 = new BillRequestDTO("c6a0fb9d-fc6f-4c21-95fc-4f5e7311d0e2", "injury", "1", LocalDate.of(2023, 11, 8), 199.99, BillStatus.PAID, LocalDate.of(2023, 12, 2)); + BillRequestDTO b17 = new BillRequestDTO("b3d09eab-4085-4b2d-a121-78a0a2f9e501", "chronic", "3", LocalDate.of(2023, 11, 11), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 12, 6)); + BillRequestDTO b18 = new BillRequestDTO("b3d09eab-4085-4b2d-a121-78a0a2f9e501", "general", "2", LocalDate.of(2023, 11, 14), 59.99, BillStatus.PAID, LocalDate.of(2023, 12, 10)); + BillRequestDTO b19 = new BillRequestDTO("b3d09eab-4085-4b2d-a121-78a0a2f9e501", "operation", "3", LocalDate.of(2023, 11, 17), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 12, 14)); + BillRequestDTO b20 = new BillRequestDTO("b3d09eab-4085-4b2d-a121-78a0a2f9e501", "injury", "1", LocalDate.of(2023, 11, 20), 199.99, BillStatus.PAID, LocalDate.of(2023, 12, 18)); + BillRequestDTO b21 = new BillRequestDTO("b3d09eab-4085-4b2d-a121-78a0a2f9e501", "chronic", "2", LocalDate.of(2023, 11, 23), 199.99, BillStatus.OVERDUE, LocalDate.of(2023, 12, 22)); + BillRequestDTO b22 = new BillRequestDTO("5fe81e29-1f1d-4f9d-b249-8d3e0cc0b7dd", "general", "3", LocalDate.of(2023, 11, 26), 59.99, BillStatus.PAID, LocalDate.of(2023, 12, 26)); + BillRequestDTO b23 = new BillRequestDTO("48f9945a-4ee0-4b0b-9b44-3da829a0f0f7", "operation", "2", LocalDate.of(2023, 11, 29), 199.99, BillStatus.UNPAID, LocalDate.of(2023, 12, 30)); + BillRequestDTO b24 = new BillRequestDTO("48f9945a-4ee0-4b0b-9b44-3da829a0f0f7", "injury", "1", LocalDate.of(2023, 12, 2), 199.99, BillStatus.PAID, LocalDate.of(2024, 1, 2)); + BillRequestDTO b25 = new BillRequestDTO("48f9945a-4ee0-4b0b-9b44-3da829a0f0f7", "chronic", "3", LocalDate.of(2023, 12, 5), 199.99, BillStatus.OVERDUE, LocalDate.of(2024, 1, 6)); + BillRequestDTO b26 = new BillRequestDTO("48f9945a-4ee0-4b0b-9b44-3da829a0f0f7", "general", "2", LocalDate.of(2023, 12, 8), 59.99, BillStatus.UNPAID, LocalDate.of(2024, 1, 10)); + BillRequestDTO b27 = new BillRequestDTO("48f9945a-4ee0-4b0b-9b44-3da829a0f0f7", "operation", "3", LocalDate.of(2023, 12, 11), 199.99, BillStatus.PAID, LocalDate.of(2024, 1, 14)); + BillRequestDTO b28 = new BillRequestDTO("9f6accd1-e943-4322-932e-199d93824317", "injury", "1", LocalDate.of(2023, 12, 14), 199.99, BillStatus.PAID, LocalDate.of(2024, 1, 18)); + BillRequestDTO b29 = new BillRequestDTO("9f6accd1-e943-4322-932e-199d93824317", "chronic", "2", LocalDate.of(2023, 12, 17), 199.99, BillStatus.OVERDUE, LocalDate.of(2024, 1, 22)); + BillRequestDTO b30 = new BillRequestDTO("7c0d42c2-0c2d-41ce-bd9c-6ca67478956f", "general", "3", LocalDate.of(2023, 12, 20), 59.99, BillStatus.UNPAID, LocalDate.of(2024, 1, 26)); + + Flux.just(b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30) + .flatMap(b -> billService.CreateBill(Mono.just(b)) + .log(b.toString())) + .subscribe(); + + Flux.just(b1,b2,b3,b4,b5) + .flatMap(b -> billService.CreateBill(Mono.just(b)) + .log(b.toString())) + .subscribe(); + } +} diff --git a/billing-service/src/main/resources/data-h2.sql b/billing-service/src/main/resources/data-h2.sql index b1e5b26ca2..128e8af6d8 100644 --- a/billing-service/src/main/resources/data-h2.sql +++ b/billing-service/src/main/resources/data-h2.sql @@ -1,6 +1,6 @@ -INSERT INTO billings VALUES (1, 1, 1, 'general', '2021-09-19',59.99); -INSERT INTO billings VALUES (2, 2, 2, 'operation', '2021-09-20',199.99); -INSERT INTO billings VALUES (3, 3, 3, 'operation', '2021-09-21',199.99); -INSERT INTO billings VALUES (4, 4, 4, 'operation', '2021-09-22',199.99); -INSERT INTO billings VALUES (5, 5, 5, 'operation', '2021-09-23',199.99); -INSERT INTO billings VALUES (6, 6, 6, 'operation', '2021-09-23',199.99); \ No newline at end of file +INSERT INTO billings VALUES (1, 1, 'f470653d-05c5-4c45-b7a0-7d70f003d2ac', 'general', '2021-09-19',59.99); +INSERT INTO billings VALUES (2, 2, 'e6c7398e-8ac4-4e10-9ee0-03ef33f0361a', 'operation', '2021-09-20',199.99); +INSERT INTO billings VALUES (3, 3, '3f59dca2-903e-495c-90c3-7f4d01f3a2aa', 'operation', '2021-09-21',199.99); +INSERT INTO billings VALUES (4, 4, 'a6e0e5b0-5f60-45f0-8ac7-becd8b330486', 'operation', '2021-09-22',199.99); +INSERT INTO billings VALUES (5, 5, 'c6a0fb9d-fc6f-4c21-95fc-4f5e7311d0e2', 'operation', '2021-09-23',199.99); +INSERT INTO billings VALUES (6, 6, 'b3d09eab-4085-4b2d-a121-78a0a2f9e501', 'operation', '2021-09-23',199.99); \ No newline at end of file diff --git a/billing-service/src/main/resources/data-mysql.sql b/billing-service/src/main/resources/data-mysql.sql index e62b055321..b2e434ceca 100644 --- a/billing-service/src/main/resources/data-mysql.sql +++ b/billing-service/src/main/resources/data-mysql.sql @@ -1,6 +1,6 @@ -INSERT IGNORE INTO billings VALUES (1, 1, 1, 'general', '2021-09-19',59.99); -INSERT IGNORE INTO billings VALUES (2, 2, 2, 'operation', '2021-09-20',199.99); -INSERT IGNORE INTO billings VALUES (3, 3, 3, 'operation', '2021-09-21',199.99); -INSERT IGNORE INTO billings VALUES (4, 4, 4, 'operation', '2021-09-22',199.99); -INSERT IGNORE INTO billings VALUES (5, 5, 5, 'operation', '2021-09-23',199.99); -INSERT IGNORE INTO billings VALUES (6, 6, 6, 'operation', '2021-09-23',199.99); \ No newline at end of file +INSERT IGNORE INTO billings VALUES (1, 1, 'f470653d-05c5-4c45-b7a0-7d70f003d2ac', 'general', '2021-09-19',59.99); +INSERT IGNORE INTO billings VALUES (2, 2, 'e6c7398e-8ac4-4e10-9ee0-03ef33f0361a', 'operation', '2021-09-20',199.99); +INSERT IGNORE INTO billings VALUES (3, 3, '3f59dca2-903e-495c-90c3-7f4d01f3a2aa', 'operation', '2021-09-21',199.99); +INSERT IGNORE INTO billings VALUES (4, 4, 'a6e0e5b0-5f60-45f0-8ac7-becd8b330486', 'operation', '2021-09-22',199.99); +INSERT IGNORE INTO billings VALUES (5, 5, 'c6a0fb9d-fc6f-4c21-95fc-4f5e7311d0e2', 'operation', '2021-09-23',199.99); +INSERT IGNORE INTO billings VALUES (6, 6, 'b3d09eab-4085-4b2d-a121-78a0a2f9e501', 'operation', '2021-09-23',199.99); \ No newline at end of file diff --git a/billing-service/src/main/resources/db/hsqldb/data.sql b/billing-service/src/main/resources/db/hsqldb/data.sql index a1d5b33d33..6ef3842c61 100644 --- a/billing-service/src/main/resources/db/hsqldb/data.sql +++ b/billing-service/src/main/resources/db/hsqldb/data.sql @@ -1,6 +1,6 @@ -INSERT INTO billings VALUES (1,1, '2021-09-19','general',59.99); -INSERT INTO billings VALUES (2,2, '2021-09-20','operation',199.99); -INSERT INTO billings VALUES (3,3, '2021-09-21','operation',199.99); -INSERT INTO billings VALUES (4,4, '2021-09-22','operation',199.99); -INSERT INTO billings VALUES (5,5, '2021-09-23','operation',199.99); -INSERT INTO billings VALUES (6,6, '2021-09-23','operation',199.99); \ No newline at end of file +INSERT INTO billings VALUES (1,'f470653d-05c5-4c45-b7a0-7d70f003d2ac', '2021-09-19','general',59.99); +INSERT INTO billings VALUES (2,'e6c7398e-8ac4-4e10-9ee0-03ef33f0361a', '2021-09-20','operation',199.99); +INSERT INTO billings VALUES (3,'3f59dca2-903e-495c-90c3-7f4d01f3a2aa', '2021-09-21','operation',199.99); +INSERT INTO billings VALUES (4,'a6e0e5b0-5f60-45f0-8ac7-becd8b330486', '2021-09-22','operation',199.99); +INSERT INTO billings VALUES (5,'c6a0fb9d-fc6f-4c21-95fc-4f5e7311d0e2', '2021-09-23','operation',199.99); +INSERT INTO billings VALUES (6,'b3d09eab-4085-4b2d-a121-78a0a2f9e501', '2021-09-23','operation',199.99); \ No newline at end of file diff --git a/billing-service/src/main/resources/db/mysql/data.sql b/billing-service/src/main/resources/db/mysql/data.sql index e62b055321..b2e434ceca 100644 --- a/billing-service/src/main/resources/db/mysql/data.sql +++ b/billing-service/src/main/resources/db/mysql/data.sql @@ -1,6 +1,6 @@ -INSERT IGNORE INTO billings VALUES (1, 1, 1, 'general', '2021-09-19',59.99); -INSERT IGNORE INTO billings VALUES (2, 2, 2, 'operation', '2021-09-20',199.99); -INSERT IGNORE INTO billings VALUES (3, 3, 3, 'operation', '2021-09-21',199.99); -INSERT IGNORE INTO billings VALUES (4, 4, 4, 'operation', '2021-09-22',199.99); -INSERT IGNORE INTO billings VALUES (5, 5, 5, 'operation', '2021-09-23',199.99); -INSERT IGNORE INTO billings VALUES (6, 6, 6, 'operation', '2021-09-23',199.99); \ No newline at end of file +INSERT IGNORE INTO billings VALUES (1, 1, 'f470653d-05c5-4c45-b7a0-7d70f003d2ac', 'general', '2021-09-19',59.99); +INSERT IGNORE INTO billings VALUES (2, 2, 'e6c7398e-8ac4-4e10-9ee0-03ef33f0361a', 'operation', '2021-09-20',199.99); +INSERT IGNORE INTO billings VALUES (3, 3, '3f59dca2-903e-495c-90c3-7f4d01f3a2aa', 'operation', '2021-09-21',199.99); +INSERT IGNORE INTO billings VALUES (4, 4, 'a6e0e5b0-5f60-45f0-8ac7-becd8b330486', 'operation', '2021-09-22',199.99); +INSERT IGNORE INTO billings VALUES (5, 5, 'c6a0fb9d-fc6f-4c21-95fc-4f5e7311d0e2', 'operation', '2021-09-23',199.99); +INSERT IGNORE INTO billings VALUES (6, 6, 'b3d09eab-4085-4b2d-a121-78a0a2f9e501', 'operation', '2021-09-23',199.99); \ No newline at end of file diff --git a/billing-service/src/main/resources/schema-h2.sql b/billing-service/src/main/resources/schema-h2.sql index 9103e295b0..961c266457 100644 --- a/billing-service/src/main/resources/schema-h2.sql +++ b/billing-service/src/main/resources/schema-h2.sql @@ -3,7 +3,7 @@ DROP TABLE billings IF EXISTS; CREATE TABLE billings ( id INT(4) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, bill_id Int, - customer_id INT, + customer_id VARCHAR(80), visit_type VARCHAR(80), visit_date DATE, amount DOUBLE diff --git a/billing-service/src/main/resources/schema-mysql.sql b/billing-service/src/main/resources/schema-mysql.sql index c84d6be133..58a3a008be 100644 --- a/billing-service/src/main/resources/schema-mysql.sql +++ b/billing-service/src/main/resources/schema-mysql.sql @@ -3,7 +3,7 @@ DROP TABLE IF EXISTS billings; CREATE TABLE IF NOT EXISTS billings ( id INT(7) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, bill_id Int, - customer_id INT, + customer_id VARCHAR(80), visit_type VARCHAR(80), visit_date DATE, amount DOUBLE diff --git a/petclinic-frontend/src/features/bills/BillsListTable.tsx b/petclinic-frontend/src/features/bills/BillsListTable.tsx new file mode 100644 index 0000000000..f7e6feeba1 --- /dev/null +++ b/petclinic-frontend/src/features/bills/BillsListTable.tsx @@ -0,0 +1,110 @@ +import { useEffect, useState } from 'react'; +import { Bill } from '@/features/bills/models/Bill.ts'; +import { useUser } from '@/context/UserContext'; + +export default function BillsListTable(): JSX.Element { + const { user } = useUser(); + const [bills, setBills] = useState([]); + const [error, setError] = useState(null); + + useEffect(() => { + if (!user.userId) return; + + const fetchBills = async (): Promise => { + try { + const response = await fetch( + `http://localhost:8080/api/v2/gateway/bills/customer/${user.userId}`, + { + headers: { + Accept: 'text/event-stream', + }, + credentials: 'include', + } + ); + + if (!response.ok) { + throw new Error(`Error: ${response.status} ${response.statusText}`); + } + + const reader = response.body?.getReader(); + const decoder = new TextDecoder('utf-8'); + + let done = false; + const billsArray: Bill[] = []; + + while (!done) { + const { value, done: streamDone } = (await reader?.read()) || {}; + done = streamDone || true; + + if (value) { + const chunk = decoder.decode(value, { stream: true }); + + const formattedChunks = chunk.trim().split(/\n\n/); + + formattedChunks.forEach(formattedChunk => { + const cleanChunk = formattedChunk.trim().replace(/^data:\s*/, ''); + + if (cleanChunk) { + try { + const newBill: Bill = JSON.parse(cleanChunk); + billsArray.push(newBill); + setBills([...billsArray]); + } catch (e) { + console.error('Error parsing chunk:', e); + } + } + }); + } + } + } catch (err) { + console.error('Error fetching bills:', err); + setError('Failed to fetch bills'); + } + }; + + fetchBills(); + }, [user.userId]); + + return ( +
+ {error ? ( +

{error}

+ ) : ( + + + + + + + + + + + + + + + + {bills.map(bill => ( + + + + + + + + + + + + ))} + +
Bill IDOwner NameVisit TypeVet NameDateAmountTaxed AmountStatusDue Date
{bill.billId} + {bill.ownerFirstName} {bill.ownerLastName} + {bill.visitType} + {bill.vetFirstName} {bill.vetLastName} + {bill.date}{bill.amount}{bill.taxedAmount}{bill.billStatus}{bill.dueDate}
+ )} +
+ ); +} diff --git a/petclinic-frontend/src/features/bills/models/Bill.ts b/petclinic-frontend/src/features/bills/models/Bill.ts new file mode 100644 index 0000000000..dbccfb8402 --- /dev/null +++ b/petclinic-frontend/src/features/bills/models/Bill.ts @@ -0,0 +1,15 @@ +export interface Bill { + billId: string; + customerId: string; + ownerFirstName: string; + ownerLastName: string; + visitType: string; + vetId: string; + vetFirstName: string; + vetLastName: string; + date: string; + amount: number; + taxedAmount: number; + billStatus: string; + dueDate: string; +} diff --git a/petclinic-frontend/src/layouts/AppNavBar.tsx b/petclinic-frontend/src/layouts/AppNavBar.tsx index 5b4b160c51..fe9bb1d78b 100644 --- a/petclinic-frontend/src/layouts/AppNavBar.tsx +++ b/petclinic-frontend/src/layouts/AppNavBar.tsx @@ -61,8 +61,15 @@ export function NavBar(): JSX.Element { + {IsAdmin() && ( +
  • + + Bills + +
  • + )}
  • - + Bills
  • diff --git a/petclinic-frontend/src/pages/Bills/CostumerBills.tsx b/petclinic-frontend/src/pages/Bills/CostumerBills.tsx new file mode 100644 index 0000000000..d8e9501279 --- /dev/null +++ b/petclinic-frontend/src/pages/Bills/CostumerBills.tsx @@ -0,0 +1,12 @@ +import { NavBar } from '@/layouts/AppNavBar.tsx'; +import BillsListTable from '@/features/bills/BillsListTable.tsx'; + +export default function CustomerBillingPage(): JSX.Element { + return ( +
    + +

    Your Bills

    + +
    + ); +} diff --git a/petclinic-frontend/src/router.tsx b/petclinic-frontend/src/router.tsx index c8b53b3595..d54ac0dd4e 100644 --- a/petclinic-frontend/src/router.tsx +++ b/petclinic-frontend/src/router.tsx @@ -7,6 +7,7 @@ import { ProtectedRoute } from '@/shared/components/ProtectedRouteProps.tsx'; import Home from '@/pages/Home/Home.tsx'; import ProfileEdit from '@/pages/Customer/ProfileEdit.tsx'; import AddingCustomer from '@/pages/Customer/AddingCustomer.tsx'; +import CustomerBillingPage from '@/pages/Bills/CostumerBills.tsx'; const router = createBrowserRouter([ { @@ -52,6 +53,14 @@ const router = createBrowserRouter([ ), }, + { + path: AppRoutePaths.CustomerBills, + element: ( + + + + ), + }, // { // path: AppRoutePaths.PageNotFound, // element: /* PageNotFoundComponent */ @@ -69,7 +78,7 @@ const router = createBrowserRouter([ // element: /* ServiceUnavailableComponent */ // }, // { - // path: AppRoutePaths.Unauthorized + // path: AppRoutePaths.Unauthorized, // element: /* UnauthorizedComponent */ // } ], @@ -77,4 +86,5 @@ const router = createBrowserRouter([ { path: AppRoutePaths.login, element: }, // {path: '*', element: /* PageNotFoundComponent */}, ]); + export default router; diff --git a/petclinic-frontend/src/shared/models/path.routes.ts b/petclinic-frontend/src/shared/models/path.routes.ts index 9aa1997aad..ef6e119c70 100644 --- a/petclinic-frontend/src/shared/models/path.routes.ts +++ b/petclinic-frontend/src/shared/models/path.routes.ts @@ -2,6 +2,7 @@ export enum AppRoutePaths { Default = '/', Inventories = '/inventories', Vet = '/vet', + CustomerBills = '/bills/customer', PageNotFound = '/page-not-found', Unauthorized = '/unauthorized', ServiceTimeout = '/service-timeout',